mandag den 4. oktober 2010

Øvelse 5 - GPIO Linux Device Driver

Implementer ”init” og ”exit”
/*
* ID: mygpio.c
*/
#include
#include
#include
#include
#include

#define MYGPIO_MAJOR 62
#define MYGPIO_MINOR 0
#define MYGPIO_CHS 8
#define MAXLEN 512

static struct cdev MyGpioDev;
struct file_operations mygpio_Fops;

static int devno;

const unsigned int gpio_len = 8;
struct gpioPort{
unsigned int num;
enum direnu { in, out } dir;
const char label[10]; // Very important to specify a size. Just [] causes havoc to gpio indexing
} gpio[] = {
{130, in, "gpio0_0"},
{131, in, "gpio0_1"},
{132, in, "gpio0_2"},
{133, in, "gpio0_3"},
{134, out, "gpio0_4"},
{135, out, "gpio0_5"},
{136, out, "gpio0_6"},
{137, out, "gpio0_7"},
{139, out, "gpio0_9"}
};


static int mygpio_init(void)
{
int err, i;

printk(KERN_ALERT "Mygpio Module Inserted\n");


/*
* Allocate Major/Minor Numbers
*/
devno = MKDEV(MYGPIO_MAJOR, MYGPIO_MINOR);
if((err=register_chrdev_region(devno, gpio_len, "myGpio"))<0){
printk(KERN_ALERT "Can't Register Major no: %i\n", MYGPIO_MAJOR);
return err;
}

/*
* Create cdev
*/
cdev_init(&MyGpioDev, &mygpio_Fops);
MyGpioDev.owner = THIS_MODULE;
MyGpioDev.ops = &mygpio_Fops;
err = cdev_add(&MyGpioDev, devno, gpio_len);
if (err) {
printk (KERN_ALERT "Error %d adding MyGpio device\n", err);
return -1;
}

/*
* Request GPIO Ressources
*/

/*** YOUR CODE HERE ****/

//gpio_request(139, gpio);
gpio_request(130, "GPIO0_0");

/*
* Set GPIO Direction
*/

/*** YOUR CODE HERE ****/
//gpio_direction_output(139, 1);
gpio_direction_input(130);


return 0;
}

static void mygpio_exit(void)
{
int i;

printk(KERN_NOTICE "Removing Mygpio Module\n");

/*
* Set GPIOs to Inputs
* (leave things as when we entered)
*/

/*** YOUR CODE HERE ****/
gpio_direction_input(139);


/*
* Free GPIO Ressources
*/

/*** YOUR CODE HERE ****/
//gpio_free(139);
gpio_free(130);


/*
* Delete cdev
*/
unregister_chrdev_region(devno, gpio_len);
cdev_del(&MyGpioDev);
}


Implementer ”open” og ”release”
int mygpio_open(struct inode *inode, struct file *filep)
{
int major, minor;

major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);

printk("Opening MyGpio Device [major], [minor]: %i, %i\n", major, minor);


/*
* Check if major/minor is valid
*/

/*** YOUR CODE HERE ****/


/*
* Try to get the module sem
*/
if (!try_module_get(mygpio_Fops.owner)) // Get Module
return -ENODEV;

return 0;
}

int mygpio_release(struct inode *inode, struct file *filep)
{
int minor, major;

major = MAJOR(inode->i_rdev);
minor = MINOR(inode->i_rdev);

printk("Closing MyGpio Device [major], [minor]: %i, %i\n", major, minor);


/*
* Check if major/minor is valid
*/

/*** YOUR CODE HERE ****/


/*
* Put the module semaphore
* to release it
*/
module_put(mygpio_Fops.owner);

return 0;
}


Implementer ”write”
ssize_t mygpio_write(struct file *filep, const char __user *ubuf,
size_t count, loff_t *f_pos)
{
int minor, len, value;
char kbuf[MAXLEN];

/*
* retrieve minor from file ptr
*/
minor = MINOR(filep->f_dentry->d_inode->i_rdev);
printk(KERN_ALERT "Writing to MyGpio [Minor] %i \n", minor);

/*
* Check if minor is valid
*/

/*** YOUR CODE HERE ****/

/*
* Copy data from user space
* to kernel space
*/
len = count < MAXLEN ? count : MAXLEN; // set len < MAXLEN

/**** Use copy_from_user to get data ****/
/*** YOUR CODE HERE ****/
copy_from_user(kbuf, ubuf, count);

kbuf[len] = '\0'; // Pad null termination to string
printk("string from user: %s\n", kbuf);

/*
* Convert string to int
*/

/**** Use sscanf to convert string to int ****/
/*** YOUR CODE HERE ****/
sscanf(kbuf,"%i", &value);
printk("value %i\n", value);

value = value > 0 ? 1 : 0;

/*
* Set GPIO port
* (if an output port)
*/

/**** Use gpio_set_value on appropriate port ****/
/*** YOUR CODE HERE ****/
gpio_set_value(139, value);

*f_pos += count;
return count;
}

Implementer ”read”
ssize_t mygpio_read(struct file *filep, char __user *buf,
size_t count, loff_t *f_pos)
{
char readBuf[MAXLEN];
int len, result=-1, minor;

/*
* retrieve minor from file ptr
*/
minor = MINOR(filep->f_dentry->d_inode->i_rdev);
printk(KERN_ALERT "Reading from MyGpio [Minor] %i \n", minor);

/*
* Check if minor is valid
*/

/*** YOUR CODE HERE ****/

/*
* Read GPIO port
* (if an input port)
*/

/*** YOUR CODE HERE ****/
result = gpio_get_value(130);

/*
* Convert int to string
* using sprintf
*/
len=sprintf(readBuf,"%i", result);
len++; // To include null-termination

/*
* Copy string result
* to User Space
*/

/*** YOUR CODE HERE ****/
copy_to_user(buf, readBuf, len);

*f_pos += len;
return len;
}


struct file_operations mygpio_Fops =
{
.owner = THIS_MODULE,
.open = mygpio_open,
.release = mygpio_release,
.write = mygpio_write,
.read = mygpio_read,
};

module_init(mygpio_init);
module_exit(mygpio_exit);

MODULE_DESCRIPTION("My GPIO Module");
MODULE_AUTHOR("IHA ");
MODULE_LICENSE("GPL");


Indsæt modul, node, kørsel af læsningsprogram
insmod mygpio.ko
mknod /dev/wepee c 62
./rd /dev/wepee

Ingen kommentarer:

Send en kommentar