1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
| /** * @file sysfs_drv.c * @author Late Lee <latelee@163.com> * @date Tue Nov 12 22:21:19 2013 * * @brief sysfs测试示例 * * @note */
#include <linux/module.h> #include <linux/kernel.h> /**< printk() */ #include <linux/init.h> #include <linux/platform_device.h>
#include <linux/cdev.h> /**< cdev_* */ #include <linux/fs.h> #include <asm/uaccess.h> /**< copy_*_user */
#include <linux/types.h> /**< size_t */ #include <linux/errno.h> /**< error codes */ #include <linux/string.h> #include <linux/ctype.h>
static void foo_dev_release(struct device* dev) { return; }
// platform设备 static struct platform_device foo_device = { .name = "foo", .id = -1, .dev = { //.platform_data = &foo_pdata, .release = &foo_dev_release, }, };
#define DEBUG
#ifdef DEBUG /* KERN_INFO */ #define debug(fmt, ...) printk(KERN_NOTICE fmt, ##__VA_ARGS__) #else #define debug(fmt, ...) #endif
static struct class* foo_class;
static int user_data = 250;
// cat foobar 调用此函数 static ssize_t foobar_show(struct device *dev, struct device_attribute *attr, char *buf) { printk("set data to user space: %d\n", user_data); return sprintf(buf, "%u\n", user_data); }
// echo 111 > foobar 调用此函数 static ssize_t foobar_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { unsigned long state = simple_strtoul(buf, NULL, 10); user_data = state; printk("got data from user space: %d %d\n", (unsigned int)state, user_data); // 一定要返回size,否则会一直执行 return size; }
// 生成文件为foobar static DEVICE_ATTR(foobar, 0666, foobar_show, foobar_store);
static int foo_remove(struct platform_device *dev) { device_remove_file(&foo_device.dev, &dev_attr_foobar);
class_destroy(foo_class);
//printk(KERN_NOTICE "remove...\n");
return 0; }
static int foo_probe(struct platform_device *dev) { int ret = 0;
foo_class = class_create(THIS_MODULE, "foo"); if (IS_ERR(foo_class)) { dev_err(&foo_device.dev, "failed to create class.\n"); return PTR_ERR(foo_class); }
ret = device_create_file(&foo_device.dev, &dev_attr_foobar); if (ret) goto err_out;
err_out: return ret; }
// driver static struct platform_driver foo_driver = { .probe = foo_probe, .remove = foo_remove, .driver = { .name = "foo", .owner = THIS_MODULE, }, };
static int __init foo_drv_init(void) { int ret = 0;
// 先注册设备(适用于静态定义设备结构体) ret = platform_device_register(&foo_device); if (ret) { dev_err(&foo_device.dev, "platform_device_register failed!\n"); return ret; } // 再注册驱动 ret = platform_driver_register(&foo_driver); if (ret) { dev_err(&foo_device.dev, "platform_driver_register failed!\n"); return ret; } dev_info(&foo_device.dev, "init OK!\n"); return ret; }
static void __exit foo_drv_exit(void) { // 先卸载驱动 platform_driver_unregister(&foo_driver); // 再卸载设备 platform_device_unregister(&foo_device);
printk("exit OK!\n"); }
module_init(foo_drv_init); module_exit(foo_drv_exit);
MODULE_AUTHOR("Late Lee"); MODULE_DESCRIPTION("Simple platform driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:foo");
|