sysfs接口函数的建立_DEVICE_ATTR 【转】
出自:http://blog.csdn.net/manshq163com/article/details/7848714
2012-05-09 11:36:46| 分类:linux文件系统 | 标签:device_attr sysfs接口函数 |字号大中小 订阅
说道sysfs接口,就不得不提到函数宏 DEVICE_ATTR,原型是
#define DEVICE_ATTR(_name, _mode, _show, _store) \
struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)
函数宏DEVICE_ATTR内封装的是__ATTR(_name,_mode,_show,_stroe)方法
_show:表示的是读方法,
_stroe表示的是写方法。
当然_ATTR不是独生子女,他还有一系列的姊妹__ATTR_RO宏只有读方法,__ATTR_NULL等等
如对设备的使用 DEVICE_ATTR
对驱动使用 DRIVER_ATTR
对总线使用 BUS_ATTR
对类别 (class) 使用 CLASS_ATTR
这四个高级的宏来自于
DEVICE_ATTR 宏声明有四个参数,分别是名称、权限位、读函数、写函数。其中读函数和写函数是读写功能函数的函数名。
如果你完成了DEVICE_ATTR函数宏的填充,下面就需要创建接口了
例如:
static DEVICE_ATTR(polling, S_IRUGO | S_IWUSR, show_polling, set_polling);
static struct attribute *dev_attrs[] = {
&dev_attr_polling.attr,
NULL,
};
当你想要实现的接口名字是polling的时候,需要实现结构体struct attribute *dev_attrs[]
其中成员变量的名字必须是&dev_attr_polling.attr
然后再封装
static struct attribute_group dev_attr_grp = {
.attrs = dev_attrs,
};
通过以上简单的三个步骤,就可以在adb shell 终端查看到接口了。当我们将数据 echo 到接口中时,在上层实际上完成了一次 write 操作,对应到 kernel ,调用了驱动中的 “store”。同理,当我们cat 一个 接口时则会调用 “show” 。到这里,只是简单的建立了 android 层到 kernel 的桥梁,真正实现对硬件操作的,还是在 "show" 和 "store" 中完成的。
其实呢?!用个proc文件系统的就知道,这个就和proc中的write和read一样的,以我的理解:proc有点老了,以后肯定会大量使用attribute,proc好比是Windows XP,attribute就像是Windows Seven
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 10 //#include 11 12 /* Variables */ 13 static struct delayed_work vib_delayed_work; 14 15 /* Definitions */ 16 #define VIB_TEST 0 17 18 #define GPIO_VIBCTL EXYNOS4_GPD0(0) 19 20 #define CFG_VIB_CTRL do {\ 21 gpio_request(GPIO_VIBCTL, "MOTOR_PWM");\ 22 s3c_gpio_cfgpin(GPIO_VIBCTL,S3C_GPIO_OUTPUT);\ 23 s3c_gpio_setpull(GPIO_VIBCTL,S3C_GPIO_PULL_NONE);\ 24 } while(0) 25 26 #define VIB_START do {\ 27 gpio_set_value(GPIO_VIBCTL, 1);\ 28 } while(0) 29 30 #define VIB_STOP do {\ 31 gpio_set_value(GPIO_VIBCTL, 0);\ 32 } while(0) 33 34 #define RELEASE_VIB do {\ 35 gpio_free(GPIO_VIBCTL);\ 36 } while(0) 37 38 #ifndef CONFIG_TC4_DVT 39 #define USE_MOTOR_8997 40 #else 41 #undef USE_MOTOR_8997 42 #endif 43 44 #ifdef USE_MOTOR_8997 45 extern void motor8997_on(int on); 46 #endif 47 48 /* Functions */ 49 static void vib_delayed_work_func(struct work_struct *work) 50 { 51 #ifdef USE_MOTOR_8997 52 motor8997_on(0); 53 #else 54 VIB_STOP; 55 #endif 56 } 57 58 int strtoint(const char *str,int len) 59 { 60 int result = 0; 61 int i = 0; 62 char c; 63 while(i <= len-1) 64 { 65 c = str[i++]; 66 if(c<'0' || c>'9') 67 break; 68 result = 10*result + c - '0'; 69 } 70 return result; 71 } 72 73 static ssize_t vib_show(struct device *dev, 74 struct device_attribute *attr, char *buf) 75 { 76 return printk("write a number in to vibrate\n"); 77 } 78 79 static ssize_t vib_store(struct device *dev, 80 struct device_attribute *attr, 81 const char *buf, size_t count) 82 { 83 int retval; 84 int value; 85 value = strtoint(buf,count); 86 #if VIB_TEST 87 printk("count:%d, buf:%s",count,buf); 88 printk("inv:%d ms\n",value); 89 #endif 90 retval = count; 91 if(value) 92 { 93 #ifdef USE_MOTOR_8997 94 motor8997_on(1); 95 #else 96 VIB_START; 97 #endif 98 schedule_delayed_work(&vib_delayed_work, msecs_to_jiffies(value)); 99 } 100 else 101 { 102 #ifdef USE_MOTOR_8997 103 motor8997_on(0); 104 #else 105 VIB_STOP; 106 #endif 107 } 108 return retval; 109 } 110 111 /* 112 * sysfs: /sys/devices/platform/s5p-vib 113 * usage: echo ms > /sys/devices/platform/s5p-vib/vib 114 */ 115 static DEVICE_ATTR(vib, S_IRUGO | S_IWUSR, vib_show, vib_store); 116 117 static int __devinit s3c_vib_probe(struct platform_device *pdev) 118 { 119 int err; 120 err = device_create_file(&pdev->dev, &dev_attr_vib); 121 if (err) 122 goto error1; 123 124 /* delayed work */ 125 INIT_DELAYED_WORK(&vib_delayed_work, vib_delayed_work_func); 126 127 CFG_VIB_CTRL; 128 129 #if VIB_TEST 130 #ifdef USE_MOTOR_8997 131 motor8997_on(1); 132 #else 133 VIB_START; 134 #endif 135 schedule_delayed_work(&vib_delayed_work, msecs_to_jiffies(1000)); 136 #endif 137 printk("vibrator probe success\n"); 138 139 return 0; 140 141 error1: 142 return err; 143 } 144 145 static int __devexit s3c_vib_remove(struct platform_device *dev) 146 { 147 RELEASE_VIB; 148 return 0; 149 } 150 151 #ifdef CONFIG_PM 152 static int s3c_vib_suspend(struct platform_device *pdev, pm_message_t state) 153 { 154 #ifdef USE_MOTOR_8997 155 motor8997_on(0); 156 #else 157 VIB_STOP; 158 #endif 159 return 0; 160 } 161 162 static int s3c_vib_resume(struct platform_device *pdev) 163 { 164 return 0; 165 } 166 #else 167 #define s3c_vib_suspend NULL 168 #define s3c_vib_resume NULL 169 #endif 170 171 static struct platform_driver s5p_vib_driver = { 172 .probe = s3c_vib_probe, 173 .remove = __devexit_p(s3c_vib_remove), 174 .suspend = s3c_vib_suspend, 175 .resume = s3c_vib_resume, 176 .driver = { 177 .name = "s5p-vib", 178 .owner = THIS_MODULE, 179 }, 180 }; 181 182 static char __initdata banner[] = "S5P VIBRATOR\n"; 183 184 static int __init s3c_vib_init(void) 185 { 186 printk(banner); 187 return platform_driver_register(&s5p_vib_driver); 188 } 189 190 static void __exit s3c_vib_exit(void) 191 { 192 printk("%s()\n",__FUNCTION__); 193 platform_driver_unregister(&s5p_vib_driver); 194 } 195 196 module_init(s3c_vib_init); 197 module_exit(s3c_vib_exit);
按照这个接口 我们可以操作寄存器,可以调试流驱动