sysfs____之ATTR实例

来源:互联网 发布:富甲天下3武将数据 编辑:程序博客网 时间:2024/05/10 20:41

接下来的例子,我会在驱动中提取,来源是高通MSM8610下Android4.3对应的kernel


1、触屏虚拟按键(通用ATTR)

这个示例创建目录和attr是通用的,不管device,device_driver,还是class,只要是/sys目录下的任何目录路径下都可。

使用的结构是

struct kobj_attribute {struct attribute attr;ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *attr,char *buf);ssize_t (*store)(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count);};

具体解释代码中见

/** *基于新思电容触摸屏驱动v2.3上的synaptics_dsx_core.c,其中的虚拟按键就是使用sysfs的attr, *Android HAL只认/sys/board_propertys/virtualkeys.$(PLATFORM_DRIVER_NAME)节点, *PLATFORM_DRIVER_NAME为虚拟按键基于的触屏dev_name,我的是触屏dev_name是synaptics_dsx,所以 *我的虚拟按键节点路径就是/sys/board_properties/virtualkeys.synaptics_dsx读取这个attr节点 *就能获取到虚拟按键在触屏像素点的坐标范围和按键code,我读这个节点数据为0x01:102:60:850:100:60//102为HOME案件。虚拟按键版本号;code;x坐标;y坐标,x坐标直径方位,y坐标的直径范围0x01:158:420:850:100:60//158为BACK按键 */ #define VIRTUAL_KEY_MAP_FILE_NAME "virtualkeys." PLATFORM_DRIVER_NAME/*要创建的目录,用于存放一个attr*/struct kobject *board_prop_dir;static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,struct kobj_attribute *attr, char *buf)/*定义一个attr,这是用最基本的kobject创建attr方法,是一个通用方法,不管是device,还是class, *而XXX_ATTR这样的宏是针对于device或class等那4种框架基础上的,不是此处用的 *最多可以使用 __ATTR(_name,_mode,_show,_store)宏 **/static struct kobj_attribute virtual_key_map_attr = {//__ATTR(VIRTUAL_KEY_MAP_FILE_NAME, S_IRUGO, synaptics_rmi4_virtual_key_map_show, NULL);.attr = {.name = VIRTUAL_KEY_MAP_FILE_NAME,.mode = S_IRUGO,},.show = synaptics_rmi4_virtual_key_map_show,//当然你也可以实现store函数};/*attr的show方法 *注意属性分配的缓存大小都是PAGE_SIZE(一般为4K)的页大小  */static ssize_t synaptics_rmi4_virtual_key_map_show(struct kobject *kobj,struct kobj_attribute *attr, char *buf){int ii;int cnt;int count = 0;for (ii = 0; ii < vir_button_map->nbuttons; ii++) {cnt = snprintf(buf, PAGE_SIZE - count, "0x01:%d:%d:%d:%d:%d\n",vir_button_map->map[ii * 5 + 0],vir_button_map->map[ii * 5 + 1],vir_button_map->map[ii * 5 + 2],vir_button_map->map[ii * 5 + 3],vir_button_map->map[ii * 5 + 4]);buf += cnt;count += cnt;}return count;}static int __devinit synaptics_rmi4_probe(struct platform_device *pdev){int retval;//...忽略无关的/*参数2为NULL会在/sys/下创建board_properties目录<span style="background-color: rgb(255, 255, 255); font-family: Arial, Helvetica, sans-serif;">,否则你就传入指定目录的koject*/</span>board_prop_dir = kobject_create_and_add("board_properties", NULL);if (!board_prop_dir) {dev_err(&pdev->dev,"%s: Failed to create board_properties directory\n",__func__);goto err_virtual_buttons;} else {retval = sysfs_create_file(board_prop_dir,&virtual_key_map_attr.attr);if (retval < 0) {dev_err(&pdev->dev,"%s: Failed to create virtual key map file\n",__func__);goto err_virtual_buttons;}}//...忽略无关的return retval;}static int __devexit synaptics_rmi4_remove(struct platform_device *pdev){//...忽略无关的if (board_prop_dir) {sysfs_remove_file(board_prop_dir,&virtual_key_map_attr.attr);kobject_put(board_prop_dir);}//...忽略无关的}


如果你要创建一组属性当然可以循环创建,其实有现成内核函数可用了

属性放在一起很直观

static struct kobj_attribute gsmi_clear_config_attr = {.attr = {.name = "clear_config", .mode = 0200},.store = gsmi_clear_config_store,};static struct kobj_attribute gsmi_clear_eventlog_attr = {.attr = {.name = "clear_eventlog", .mode = 0200},.store = gsmi_clear_eventlog_store,};/*成员必须以NULL结束,这个NULL是给sysfs_create_files创建attr节点结束标志*/static const struct attribute *gsmi_attrs[] = {&gsmi_clear_config_attr.attr,&gsmi_clear_eventlog_attr.attr,NULL,};static __init int gsmi_init(void){//...ret = sysfs_create_files(gsmi_kobj, gsmi_attrs);if (ret) {printk(KERN_INFO "gsmi: Failed to add attrs");goto out_remove_bin_file;}//...}                                                                                                            <span style="white-space:pre"></span>  static void __exit gsmi_exit(void){<span style="white-space:pre"></span>//...<span style="white-space:pre"></span>sysfs_remove_files(gsmi_kobj, gsmi_attrs);<span style="white-space:pre"></span>//...}



2、 光强/距离传感器cm36283(DEVICE_ATTR)


/* interface for exporting device attributes */struct device_attribute {struct attributeattr;ssize_t (*show)(struct device *dev, struct device_attribute *attr,char *buf);ssize_t (*store)(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);};#define DEVICE_ATTR(_name, _mode, _show, _store) \struct device_attribute dev_attr_##_name = __ATTR(_name, _mode, _show, _store)



/* *该示例提取与cm36283光强/距离感应器中的光强配置attr**/static ssize_t ls_conf_show(struct device *dev,  struct device_attribute *attr, char *buf){struct cm36283_info *lpi = lp_info;/*有溢出安全问题,最好都用snprintf包括strcat,strcpy最好都用带n的函数*/return sprintf(buf, "ALS_CONF = %x\n", lpi->ls_cmd);}static ssize_t ls_conf_store(struct device *dev,struct device_attribute *attr,const char *buf, size_t count){struct cm36283_info *lpi = lp_info;int value = 0;sscanf(buf, "0x%x", &value);lpi->ls_cmd = value;dev_dbg(&lpi->i2c_client->dev, "ALS_CONF:0x%x\n", lpi->ls_cmd);_cm36283_I2C_Write_Word(lpi->slave_addr, ALS_CONF, lpi->ls_cmd);return count;}/*变量名字实质还有个dev_attr_前缀,详见其宏定义*/static DEVICE_ATTR(ls_conf, 0664, ls_conf_show, ls_conf_store);static int cm36283_probe(struct i2c_client *client,const struct i2c_device_id *id){//。。。ret = device_create_file(lpi->ls_dev, &dev_attr_ls_conf);if (ret)goto err_create_ls_device_file;//。。。}static int cm36283_remove(struct i2c_client *){//。。。device_remove_file(lpi->ls_dev, &dev_attr_ls_conf);//。。。}




0 0
原创粉丝点击