Created
December 6, 2012 18:38
-
-
Save khaledsaied/4226913 to your computer and use it in GitHub Desktop.
sysLed Linux Device Model
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <linux/gpio.h> | |
| #include <linux/fs.h> | |
| #include <linux/cdev.h> | |
| #include <linux/device.h> | |
| #include <asm/uaccess.h> | |
| #include <linux/module.h> | |
| #define GPIO 164 //GPIO port-nr | |
| #define myMAJOR 64 | |
| #define myMINOR 0 | |
| #define ch 1 | |
| #define MAXLEN 512 | |
| static struct class *led_class; | |
| //static struct cdev My | |
| struct file_operations my_fops; | |
| static int devno; | |
| int err; | |
| MODULE_LICENSE("Dual BSD/GPL"); | |
| MODULE_AUTHOR("NKB"); | |
| MODULE_DESCRIPTION("Reads the user_key"); | |
| MODULE_LICENSE("Dual BSD/GPL"); | |
| ssize_t mygpio_write(struct file *filep, const char __user *ubuf, size_t count, loff_t *f_pos); | |
| int mygpio_open (struct inode *inode, struct file *file); | |
| int mygpio_release (struct inode *inode, struct file *file); | |
| struct file_operations my_fops = { | |
| .owner = THIS_MODULE, | |
| .write = mygpio_write, | |
| .open = mygpio_open, | |
| .release = mygpio_release, | |
| }; | |
| static struct cdev my_cdev; | |
| static int mygpio_init(void) | |
| { | |
| printk(KERN_ALERT "Hello, world\n"); | |
| err = gpio_request_one(GPIO, GPIOF_DIR_OUT, "Init User-key"); //Request GPIO, set GPIO direction (in) | |
| if (err != 0) | |
| goto requestError; | |
| devno = MKDEV(myMAJOR,myMINOR); //make device number | |
| cdev_init(&my_cdev, &my_fops); | |
| err = cdev_add(&my_cdev, devno, ch); | |
| if (err != 0) | |
| goto cdevAddError; | |
| err = register_chrdev_region(devno,ch,"User-key"); | |
| if (err != 0) | |
| goto registerChrdevError; | |
| // alloc_chrdev_region() kunne bruges for dynamisk allkoering | |
| /* Create a class, ie a folder in sysfs */ | |
| led_class = class_create(THIS_MODULE, "ledKlasse"); | |
| /* Create an object (device), ie a file under the class just created */ | |
| /* (New version of class_device_create) */ | |
| device_create(led_class, NULL, devno, NULL, "ledDevice"); | |
| return 0; | |
| requestError: | |
| { | |
| printk(KERN_ALERT "Request FAILED!\n"); | |
| gpio_free(GPIO); | |
| return 0; | |
| } | |
| cdevAddError: | |
| { | |
| printk(KERN_ALERT "cdev add FAILED!\n"); | |
| cdev_del(&my_cdev); | |
| return 0; | |
| } | |
| registerChrdevError: | |
| { | |
| printk(KERN_ALERT "registering FAILED!\n"); | |
| unregister_chrdev_region(devno,ch); | |
| return 0; | |
| } | |
| } | |
| static void mygpio_exit(void) | |
| { | |
| printk(KERN_ALERT "Goodbye, cruel world\n"); | |
| /* Destroy device from Device Model / Sysfs */ | |
| device_destroy(led_class, devno); | |
| /* Remove class from Device Model / Sysfs */ | |
| class_destroy(led_class); | |
| unregister_chrdev_region(devno,ch); // skal den ikke være i cleanup func? | |
| cdev_del(&my_cdev); | |
| gpio_free(GPIO); | |
| } | |
| int mygpio_open(struct inode *inode, struct file *file) | |
| { | |
| int major, minor; | |
| major = MAJOR(inode->i_rdev); | |
| minor = MINOR(inode->i_rdev); | |
| printk("Opening MyGpio Device [major], [minor]: %i, %i\n", major, minor); | |
| return 0; | |
| } | |
| int mygpio_release(struct inode *inode, struct file *file) | |
| { | |
| int minor, major; | |
| major = MAJOR(inode->i_rdev); | |
| minor = MINOR(inode->i_rdev); | |
| return 0; | |
| } | |
| ssize_t mygpio_write(struct file *filep, const char __user *ubuf, size_t count, loff_t *f_pos) | |
| { | |
| int minor, len, scanValue; | |
| char kbuf[MAXLEN]; | |
| minor = MINOR(filep->f_dentry->d_inode->i_rdev); | |
| if(count < MAXLEN) | |
| len = count; | |
| else | |
| len = MAXLEN; | |
| copy_from_user(kbuf, ubuf, len); | |
| kbuf[len]= '\0'; | |
| sscanf(kbuf, "%d",&scanValue); | |
| gpio_set_value(GPIO, scanValue); | |
| // Hvilke trin er det der skal udføres? | |
| // Hint konvertering fra string til int kan gøres via sscanf() - antagelsen er at det er strenge der sendes til og fra user space. Det debugging lettere. | |
| *f_pos += count; | |
| return count; | |
| } | |
| module_init(mygpio_init); | |
| module_exit(mygpio_exit); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <linux/gpio.h> | |
| #include <linux/fs.h> | |
| #include <linux/cdev.h> | |
| #include <linux/device.h> | |
| #include <asm/uaccess.h> | |
| #include <linux/module.h> | |
| #define GPIO 164 //GPIO port-nr | |
| //#define myMAJOR 64 | |
| #define MINOR_START 0 // minor nummer starter ved 0 | |
| #define ch 10 // Antal minor numre | |
| #define MAXLEN 512 | |
| static struct class *led_class; | |
| //static struct cdev My | |
| struct file_operations my_fops; | |
| static dev_t devno; | |
| int err; | |
| MODULE_LICENSE("Dual BSD/GPL"); | |
| MODULE_AUTHOR("NKB"); | |
| MODULE_DESCRIPTION("Reads the user_key"); | |
| MODULE_LICENSE("Dual BSD/GPL"); | |
| /* Sysfs "read" method prototype */ | |
| static ssize_t show_ledAttrs(struct device *dev, struct device_attribute *attr) | |
| { | |
| printk("SHOW !!! \n"); | |
| } | |
| /* Sysfs "write" method prototype */ | |
| static ssize_t store_ledAttrs(struct device *dev, struct device_attribute *attr ) | |
| { | |
| /* //OPGAVE h | |
| int *num = dev_get_drvdata(dev); | |
| ssize_t ret = -EINVAL; | |
| char *after; | |
| unsigned long value = simple_strtoul(buf, &after, 10); | |
| size_t count = after - buf; | |
| if (isspace(*after)) | |
| count++; | |
| printk("using Store to set gpio #%i to %i\n", *num, (int)value); | |
| gpio_set_value(*num, value); | |
| return count; | |
| */ | |
| } | |
| ssize_t mygpio_write(struct file *filep, const char __user *ubuf, size_t count, loff_t *f_pos); | |
| int mygpio_open (struct inode *inode, struct file *file); | |
| int mygpio_release (struct inode *inode, struct file *file); | |
| struct file_operations my_fops = { | |
| .owner = THIS_MODULE, | |
| .write = mygpio_write, | |
| .open = mygpio_open, | |
| .release = mygpio_release, | |
| }; | |
| static struct cdev my_cdev; | |
| static int mygpio_init(void) | |
| { | |
| int gpio_sysLed4_no = 164; | |
| printk(KERN_ALERT "Hello, world\n"); | |
| err = gpio_request_one(GPIO, GPIOF_DIR_OUT, "Init User-key"); //Request GPIO, set GPIO direction (in) | |
| if (err != 0) | |
| goto requestError; | |
| cdev_init(&my_cdev, &my_fops); | |
| err = cdev_add(&my_cdev, devno, ch); | |
| if (err != 0) | |
| goto cdevAddError; | |
| err = alloc_chrdev_region(&devno,MINOR_START,ch,"User-key"); | |
| if (err != 0) | |
| goto registerChrdevError; | |
| // alloc_chrdev_region() kunne bruges for dynamisk allkoering | |
| /* Create a class, ie a folder in sysfs */ | |
| led_class = class_create(THIS_MODULE, "ledKlasse"); | |
| /* Macro to create attributes */ | |
| static struct device_attribute led_class_attrs[] = {__ATTR(ledAttrs, S_IWUSR|S_IRUGO, show_ledAttrs, store_ledAttrs), __ATTR_NULL,}; | |
| /* ATTRIBUTER ??? */ | |
| led_class->dev_attrs = led_class_attrs; | |
| /* Create an object (device), ie a file under the class just created */ | |
| /* (New version of class_device_create) */ | |
| device_create(led_class, NULL, devno, NULL, "ledDevice", drvdata(&gpio_sysLed4_no)); | |
| return 0; | |
| requestError: | |
| { | |
| printk(KERN_ALERT "Request FAILED!\n"); | |
| gpio_free(GPIO); | |
| return 0; | |
| } | |
| cdevAddError: | |
| { | |
| printk(KERN_ALERT "cdev add FAILED!\n"); | |
| cdev_del(&my_cdev); | |
| return 0; | |
| } | |
| registerChrdevError: | |
| { | |
| printk(KERN_ALERT "registering FAILED!\n"); | |
| unregister_chrdev_region(devno,ch); | |
| return 0; | |
| } | |
| } | |
| static void mygpio_exit(void) | |
| { | |
| printk(KERN_ALERT "Goodbye, cruel world\n"); | |
| /* Destroy device from Device Model / Sysfs */ | |
| device_destroy(led_class, devno); | |
| /* Remove class from Device Model / Sysfs */ | |
| class_destroy(led_class); | |
| unregister_chrdev_region(devno,ch); // skal den ikke være i cleanup func? | |
| cdev_del(&my_cdev); | |
| gpio_free(GPIO); | |
| } | |
| int mygpio_open(struct inode *inode, struct file *file) | |
| { | |
| int major, minor; | |
| major = MAJOR(inode->i_rdev); | |
| minor = MINOR(inode->i_rdev); | |
| printk("Opening MyGpio Device [major], [minor]: %i, %i\n", major, minor); | |
| return 0; | |
| } | |
| int mygpio_release(struct inode *inode, struct file *file) | |
| { | |
| int minor, major; | |
| major = MAJOR(inode->i_rdev); | |
| minor = MINOR(inode->i_rdev); | |
| return 0; | |
| } | |
| ssize_t mygpio_write(struct file *filep, const char __user *ubuf, size_t count, loff_t *f_pos) | |
| { | |
| int minor, len, scanValue; | |
| char kbuf[MAXLEN]; | |
| minor = MINOR(filep->f_dentry->d_inode->i_rdev); | |
| if(count < MAXLEN) | |
| len = count; | |
| else | |
| len = MAXLEN; | |
| copy_from_user(kbuf, ubuf, len); | |
| kbuf[len]= '\0'; | |
| sscanf(kbuf, "%d",&scanValue); | |
| gpio_set_value(GPIO, scanValue); | |
| // Hvilke trin er det der skal udføres? | |
| // Hint konvertering fra string til int kan gøres via sscanf() - antagelsen er at det er strenge der sendes til og fra user space. Det debugging lettere. | |
| *f_pos += count; | |
| return count; | |
| } | |
| module_init(mygpio_init); | |
| module_exit(mygpio_exit); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment