linux kernel version:4.4.38
硬件平台:exynos4412-tiny4412
参考链接:https://www.cnblogs.com/ethandlwang/p/14759735.html
基于上一篇按键点灯程序,我给设备驱动添加了sysfs设备模型,demo级程序
添加了myled_status文件在用户空间获取灯的状态~
1 #include <linux/err.h> 2 #include <linux/gpio.h> 3 #include <linux/fs.h> 4 #include <linux/gpio/consumer.h> 5 #include <linux/kernel.h> 6 #include <linux/leds.h> 7 #include <linux/module.h> 8 #include <linux/of.h> 9 #include <linux/of_gpio.h> 10 #include <linux/of_irq.h> 11 #include <linux/platform_device.h> 12 #include <linux/property.h> 13 #include <linux/slab.h> 14 #include <linux/workqueue.h> 15 #include <linux/interrupt.h> 16 #include <linux/acpi.h> 17 18 static struct gpio_desc *gpiod; 19 20 static ssize_t myled_status_show(struct device *dev, 21 struct device_attribute *attr, char *buf) 22 { 23 int level = gpiod_get_value(gpiod); 24 printk(KERN_ALERT "%s %d level=%d\n", __FUNCTION__, __LINE__, level); 25 return 0; 26 27 } 28 29 static ssize_t myled_status_store(struct device *dev, 30 struct device_attribute *attr, 31 const char *buf, size_t len) 32 { 33 printk(KERN_ALERT "%s %d buf=%s len=%d\n", __FUNCTION__, __LINE__, buf, len); 34 int level = 1; 35 36 if(len >= 2){ 37 if(buf[0] == '0'){ 38 level = 0; 39 } 40 } 41 gpiod_set_value(gpiod, level); 42 return len; 43 } 44 45 static DEVICE_ATTR_RW(myled_status); 46 47 static struct attribute* myled_status_attrs[] = { 48 &dev_attr_myled_status.attr, 49 NULL 50 }; 51 52 static const struct attribute_group myled_group = { 53 .attrs = myled_status_attrs, 54 }; 55 56 static irqreturn_t my_irq(int irqno, void *dev_id) 57 { 58 int level = gpiod_get_value(gpiod); 59 printk(KERN_ALERT "%s %d irqno=%d level=%d\n", __FUNCTION__, __LINE__, irqno, level); 60 gpiod_set_value(gpiod, !level); 61 return IRQ_HANDLED; 62 } 63 64 static int hello_probe(struct platform_device *pdev) 65 { 66 int error = 0; 67 struct fwnode_handle *fwhandle; 68 const char *str; 69 u32 val[3]; 70 u32 interrupts_val[2]; 71 unsigned int irq; 72 int ret; 73 74 struct device_node* np = pdev->dev.of_node; 75 if(np == NULL) 76 { 77 printk(KERN_ALERT "%s %d of_node is NULL\n", __FUNCTION__, __LINE__); 78 return 0; 79 } 80 81 82 irq = platform_get_irq(pdev, 0); 83 printk(KERN_ALERT "%s %d irq = %d\n", __FUNCTION__, __LINE__, irq); 84 ret = devm_request_irq(&pdev->dev, irq, my_irq, 0, dev_name(&pdev->dev), NULL); 85 printk(KERN_ALERT "%s %d ret = %d\n", __FUNCTION__, __LINE__, ret); 86 87 gpiod = devm_gpiod_get_optional(&pdev->dev, "key1", GPIOD_OUT_LOW); 88 if(gpiod == NULL){ 89 printk(KERN_ALERT "%s %d devm_gpiod_get_optional fail!!!\n", __FUNCTION__, __LINE__); 90 } 91 92 ret = sysfs_create_group(&pdev->dev.kobj, &myled_group); 93 if(ret) 94 { 95 printk(KERN_ALERT "%s %d sysfs_create_group fail!!!\n", __FUNCTION__, __LINE__); 96 return 1; 97 } 98 99 printk(KERN_ALERT "%s %d success===\n", __FUNCTION__, __LINE__); 100 return error; 101 } 102 103 static int hello_remove(struct platform_device *pdev) 104 { 105 sysfs_remove_group(&pdev->dev.kobj,&myled_group); 106 107 printk(KERN_ALERT "%s %d success===\n", __FUNCTION__, __LINE__); 108 109 return 0; 110 111 } 112 113 static void hello_shutdown(struct platform_device *pdev) 114 { 115 printk(KERN_ALERT "%s %d success===\n", __FUNCTION__, __LINE__); 116 117 } 118 119 static struct of_device_id of_platform_hello_match[] = { 120 { .compatible = "interrupt-keys",}, 121 { }, 122 }; 123 MODULE_DEVICE_TABLE(of, of_platform_hello_match); 124 125 static struct platform_driver platform_hello_driver = { 126 .probe = hello_probe, 127 .remove = hello_remove, 128 .shutdown = hello_shutdown, 129 .driver = { 130 .name = "my_keys", 131 //.owner = THIS_MODULE, 132 .of_match_table = of_platform_hello_match, 133 }, 134 }; 135 136 module_platform_driver(platform_hello_driver); 137 138 MODULE_AUTHOR("EthanDL"); 139 MODULE_DESCRIPTION("platform hello"); 140 MODULE_LICENSE("GPL");
92行:向sysfs添加myled_status文件,所在目录/sys/devices/platform/my_keys/,因为my_keys是platform device,所以my_keys就会在/sys/devices/platform/下,sysfs_create_group的第一个参数kobj对应的正好是my_keys,所以myled_status是在my_keys下
20&29行:myled_status_show和myled_status_store,对应myled_status的读写,实现查看和控制led的亮灭~