打印

为驱动添加sysfs支持

[复制链接]
196|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
花了两天大概了解了sysfs,想着为下来了PCI总线与设备的驱动调试各方面做些准备.不过sysfs还真是有些复杂,或者说本来就只想"吃快餐".本想用现有的DEVICE_ATTR, DRIVER_ATTR, BUS_ATTR, CLASS_ATTR,可是这几种设备的依赖有点多,只能参照别人的自己做了个.虽说sysfs比之前的ioctl在用户层方面了不少,可是内核层要做的东西和要理解的东西会多些.本来还想再了解一下procfs, devfs,不过看来也只能看时间和精力了./* * my_dev_sysfs.c * author: fi9 * date: 2010-11-04 */#include <linux/config.h>#include <linux/module.h>#include <linux/kobject.h>#include <linux/sysfs.h>#include <linux/delay.h>#define MY_SYSFS_NAME "test"ssize_t my_attr_show(struct kobject *ko, struct attribute *attr, char *buf);ssize_t my_attr_store(struct kobject *kobj, struct attribute *attr,const char *buf, size_t count);void my_attr_release(struct kobject *ko);typedef struct my_attribute{  struct attribute attr;  ssize_t (*show)(char *buf);  ssize_t (*store)(const char *buf, size_t count);} my_attribute_t;#define MY_ATTR(_name, _mode, _show, _store) \my_attribute_t my_attr_##_name = { \  .attr = {.name  = __stringify(_name) , .mode   = _mode }, \  .show   = _show, \  .store  = _store, \};typedef struct my_info {  struct kobject kobj;} my_info_t;struct sysfs_ops my_sysfs_ops = {  .show  = my_attr_show,  .store = my_attr_store};////// begin 添加或修改此处ssize_t test_ata_show(char *buf);ssize_t test_ata_store(const char *buf, size_t n);MY_ATTR(ata, S_IRUGO|S_IWUGO, test_ata_show, test_ata_store);////// end 添加或修改此处struct attribute* my_sysfs_attrs[] = {        &my_attr_ata.attr, // 添加或修改此处        NULL};struct kobj_type my_ktype = {  .release       = my_attr_release,  .sysfs_ops     = &my_sysfs_ops,  .default_attrs = my_sysfs_attrs};my_info_t *my_info;////// begin 添加或修改此处ssize_t test_ata_show(char *buf){  int data;  if (ata_on)    data = 1;  else    data = 0;  return sprintf(buf, "%d\n", ((data) ? 1 : 0));}ssize_t test_ata_store(const char *buf, size_t n){  int val;  sscanf(buf, "%d", &val);        if (val) {          // ata on  } else {    // ata off  }                return n;}////// end 添加或修改此处// common func implssize_t my_attr_show(struct kobject *ko, struct attribute *attr, char *buf){  ssize_t len = 0;  my_attribute_t *a  = container_of(attr, my_attribute_t, attr);  if (a->show) {    len = a->show(buf);  }  return len;}ssize_t my_attr_store(struct kobject *kobj, struct attribute *attr,const char *buf, size_t count){  ssize_t len = 0;  my_attribute_t *a  = container_of(attr, my_attribute_t, attr);  if (a->store) {    len = a->store(buf, count);  }  return len;}void my_attr_release(struct kobject *ko){  my_info_t *a = container_of(ko, my_info_t, kobj);  kfree(a);  my_info = NULL;}void my_sysfs_add(struct kobject* kobj){  int i, n, ret;  n = ARRAY_SIZE(my_sysfs_attrs) - 1;  for (i=0; i<n; i++) {    if (my_sysfs_attrs){      ret = sysfs_create_file(kobj, my_sysfs_attrs);      if(ret < 0)        printk("sysfs is not created\n");    }  }}void my_sysfs_remove(struct kobject* kobj){  int i, n;  n = ARRAY_SIZE(my_sysfs_attrs) - 1;  for (i=0; i<n; i++) {    if (my_sysfs_attrs)      sysfs_remove_file(kobj, my_sysfs_attrs);  }}void my_sysfs_unregister(void){  // remove all files in sysfs arch  my_sysfs_remove(&my_info->kobj);  // deref the kobject  kobject_del(&my_info->kobj);  kobject_put(&my_info->kobj);  while (my_info) {    schedule_timeout(HZ/2);  }  return;}int32_t my_sysfs_register(void){  int32_t error;  my_info = kmalloc(sizeof(my_info_t), GFP_KERNEL);  if (!my_info) {    return -ENOMEM;  }  memset(my_info, 0, sizeof(my_info_t));  // init the kobject  kobject_init(&my_info->kobj);  my_info->kobj.ktype = &my_ktype;  // generate dir & attr_file  error = kobject_set_name(&my_info->kobj, MY_SYSFS_NAME);  if (!error) {    error = kobject_add(&my_info->kobj);    if (!error) {      my_sysfs_add(&my_info->kobj);    }  }  if (error) {    kfree(my_info);  }  return error;}

使用特权

评论回复

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

432

主题

439

帖子

0

粉丝