在sys目录下创建属性文件 sysfs_create_group()

正常情况下, 我们可以通过module_param()在module相应目录下创建一个文件, 以用作user space与kernel space的交互.

如果需要在/sys/bus/usb/devices/usbx目录下创建相应文件, 则需要用到sysfs_create_group()函数。 

 

// 初始化一个全局变量epStatusErr_default , 即最终在sys目录下产生的属性文件
unsigned epStatusErr_default = 0;

EXPORT_SYMBOL_GPL(epStatusErr_default);

Module_param(epStatusErr_default, int,S_IRUGO|S_IWUSR);

MODULE_PAR_DESC(epStatusErr_default,

“Default USB endpoint status: 0 is ep enough, 1 is not enough”);

 

// usb_host_epStatusErr_default_show/ usb_host_epStatusErr_default_store对应文件的读/写//操作. 在命令行通过echo向epStatusErr_default写数据将会调用到store, cat命令读数据时//则会调用到show.

static ssize_tusb_host_epStatusErr_default_show(struct device *dev,

struct device_attribute *attr,

char *buf)

{

 Return 0;

}

  

static ssize_tusb_host_epStatusErr_default_store(struct device *dev,

struct device_attribute *attr,

const char*buf, size_t size)

{

          Return0;

}

 

// --------------------

static DEVIC_ATTR(epStatusErr_default,0644,

usb_host_epStatusErr_default_show,

usb_host_epStatusErr_default_store);

 

static struc attribute *usb_endpoint_status[] = {

         &dev_attr_epStatusErr_default.attr,

         NULL,

};

 

Static struct attribute_groupusb_endpoint_status_group={

         .name= NULL,

         .attrs= usb_endpoint_status,

};

  

//在初始化时,调用sysfs_create_group()来创建sysfs 

Retval = sysfs_create_group(&rhdev->dev.kobj,&usb_endpoint_status_group);

If(retval < 0)

{

         printk(KERNEL_ERR“Cannot register USB endpoint status: %d\n”,retval);

         gotoerror_create_attr_group;

}

 

//在退出时,调用sysfs_remove_group()来删除sysfs

Sysfs_remove_group(&rhdev->dev.kobj,&usb_endpoint_status_group);


---------------- cut line  -------- chrovery ----------

原以为故事到这里可以结束了, 结果不知道LG的哪个engineer抽风,要求将parameter的路径从 /sys/bus/usb/devices/usb1 换到/sys/bus/usb/devices/1-0:1.0 . 好端端的usb1 / usb2 /usb3路径多好,分别代表controller host 1/2/3 , 简洁不缺详实, 明确不乏生动. 却偏偏要求改到1-0:1.0/ 2-0:1.0 / 3-0:1.0.

只能来看看代表interface的1-0:1.0下面有哪些变量了

shell@android:/sys/bus/usb/devices/1-0:1.0# ls

bAlternateSetting

bInterfaceClass

bInterfaceNumber

bInterfaceProtocol

bInterfaceSubClass

bNumEndpoints

driver

ep_81

modalias

port1

power

subsystem

supports_autosuspend

uevent

对应在如下结构体: usb_interface_descriptor

 

350 /*USB_DT_INTERFACE: Interface descriptor */
351 struct usb_interface_descriptor{
352         __u8  bLength;
353         __u8  bDescriptorType;
354
355         __u8  bInterfaceNumber;
356         __u8  bAlternateSetting;
357         __u8  bNumEndpoints;
358         __u8  bInterfaceClass;
359         __u8  bInterfaceSubClass;
360         __u8  bInterfaceProtocol;
361         __u8  iInterface;
362 } __attribute__((packed));
363
364 #define USB_DT_INTERFACE_SIZE           9

 

第一步先在该结构体中增加一个成员变量:

__u8  epStatusErr;

然后在sysfs.c里面添加如下操作

<span style="color: rgb(120, 120, 120);">831 usb_intf_attr(bInterfaceNumber, "%02x\n")
832 usb_intf_attr(bAlternateSetting, "%2d\n")
833 usb_intf_attr(bNumEndpoints, "%02x\n")
834 usb_intf_attr(bInterfaceClass, "%02x\n")
835 usb_intf_attr(bInterfaceSubClass, "%02x\n")
836 usb_intf_attr(bInterfaceProtocol, "%02x\n")
</span><span style="color:#ff0000;">837 usb_intf_attr(epStatusErr,  "%02x\n")</span><span style="color:#787878;">
</span>

<span style="color:#787878;">903 static struct attribute *intf_attrs[] = {
904         &dev_attr_bInterfaceNumber.attr,
905         &dev_attr_bAlternateSetting.attr,
906         &dev_attr_bNumEndpoints.attr,
907         &dev_attr_bInterfaceClass.attr,
908         &dev_attr_bInterfaceSubClass.attr,
909         &dev_attr_bInterfaceProtocol.attr,
910         &dev_attr_modalias.attr,
911         &dev_attr_supports_autosuspend.attr,
9xx	    </span><span style="color:#ff0000;">&dev_attr_epStatusErr.attr,</span><span style="color:#787878;">
912         NULL,
913 };
</span>

这样在1-0:1.0 / 2-0:1.0 / 3-0:1.0目录下就生成了epStatusErr这个文件了. 当然不仅限于这三个目录下,因为我们所修改的是interfacedescriptor structure, 所以在

/sys/bus/usb/devices目录下有关interface的都会包含该变量.

1-0:1.0      1-1.1.2:1.0  1-1.1.2:1.4  1-1.1:1.0    2-0:1.0      usb3

1-1         1-1.1.2:1.1  1-1.1.2:1.5  1-1.2       3-0:1.0

1-1.1       1-1.1.2:1.2  1-1.1.3      1-1.2:1.0    usb1

1-1.1.2      1-1.1.2:1.3 1-1.1.3:1.0  1-1:1.0     usb2

 

简要提一下Linux/drivers/usb/core/sysfs.c这个文件, 从目录结构来看, 基本可以断定该文件是用于创建和usb相关的system file.

结构比较简单, usb_intf_attr宏定义了show函数, 通过cat查看该parameter时即调用的该function.

818 /* Interface fields */
819 #define usb_intf_attr(field, format_string)                             \
820 static ssize_t                                                          \
821 show_##field(struct device *dev, struct device_attribute *attr, \
822                 char *buf)                                              \
823 {                                                                       \
824         struct usb_interface *intf = to_usb_interface(dev);             \
825                                                                         \
826         return sprintf(buf, format_string,                              \
827                         intf->cur_altsetting->desc.field);              \
828 }                                                                       \
829 static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
830 
831 usb_intf_attr(bInterfaceNumber, "%02x\n")
832 usb_intf_attr(bAlternateSetting, "%2d\n")
833 usb_intf_attr(bNumEndpoints, "%02x\n")
834 usb_intf_attr(bInterfaceClass, "%02x\n")
835 usb_intf_attr(bInterfaceSubClass, "%02x\n")
836 usb_intf_attr(bInterfaceProtocol, "%02x\n")
<span style="color:#ff0000;">837 usb_intf_attr(epStatusErr,  "%02x\n")</span>

 下一步就是如何给epStatusErr赋值了, 这里所定义的epStatusErr用来表示当前port EP 是否足够, 如果不够则写1, 否则写0. 因此写1的动作放在MGC_CheckFreeEndpoint() 

Struct usb_device *parent;
for(parent = dev->parent; parent->parent; parent = parent->parent);
parent->config->interface[0]->cur_altsetting->desc.epStatusErr = 0x1;

首先通过for循环得到root hub的device structure, 然后通过一系列操作将0x1 写到epStatusErr这一个变量.



阅读更多
个人分类: Linux
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭