现在的位置: 首页 > 综合 > 正文

Linux那些事儿 之 戏说USB(26)设备的生命线(五)

2013年09月20日 ⁄ 综合 ⁄ 共 6146字 ⁄ 字号 评论关闭
人的一生就象在拉屎,有时你已经很努力了可出来的只是一个屁。

看这内核代码也一个样,已经很努力了,俺的葱葱玉指都磨出茧子了,才勉勉强强把struct urb这个中心给说完,下面接着看那三个基本点。看之前,再猜个谜语,蜘蛛侠是什么颜色的?
第一个基本点,usb_alloc_urb函数,创建urb的专用函数,为一个urb申请内存并做初始化,在drviers/usb/core/urb.c里定义。
40 /**
41 * usb_alloc_urb - creates a new urb for a USB driver to use
42 * @iso_packets: number of iso packets for this urb
43 * @mem_flags: the type of memory to allocate, see kmalloc() for a list of
44 *      valid options for this.
45 *
46 * Creates an urb for the USB driver to use, initializes a few internal
47 * structures, incrementes the usage counter, and returns a pointer to it.
48 *
49 * If no memory is available, NULL is returned.
50 *
51 * If the driver want to use this urb for interrupt, control, or bulk
52 * endpoints, pass '' as the number of iso packets.
53 *
54 * The driver must call usb_free_urb() when it is finished with the urb.
55 */
56 struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
57 {
58         struct urb *urb;
60         urb = kmalloc(sizeof(struct urb) +
61                 iso_packets * sizeof(struct usb_iso_packet_descriptor),
62                 mem_flags);
63         if (!urb) {
64                 err("alloc_urb: kmalloc failed");
65                 return NULL;
66         }
67         usb_init_urb(urb);
68         return urb;
69 }
这函数长的很让人提神,是个亲民的角色。它只做了两件事情,拿kmalloc来为urb申请内存,然后调用usb_init_urb进行初始化。usb_init_urb函数在前面说struct urb中的引用计数的时候已经贴过了,它主要的作用就是初始化urb的引用计数,还用memset顺便把这里给urb申请的内存清零。
没什么说的了么?usb_alloc_urb说:别看我简单,我也是很有内涵的。先看第一个问题,它的第一个参数iso_packets,表示的是struct urb结构最后那个变长数组iso_frame_desc的元素数目,也就是应该与number_of_packets的值相同,所以对于控制/中断/批量传输,这个参数都应该为0。这也算是给咱们示范了下变长数组咋个用法,内核里到处都是C的示范工程。
第二个问题是参数mem_flags的类型gfp_t,早几个版本的内核,这里还是int,当然这里变成gfp_t是因为kmalloc参数里的那个标志参数的类型从int变成gfp_t了,你要用kmalloc来申请内存,就得遵守它的规则。不过这里要说的不是kmalloc,而是gfp_t,它在江湖上也没出现多久,名号还没打出来,很多人不了解,咱们来调查一下它的背景。它在include/linux/types.h里定义
193 typedef unsigned __bitwise__ gfp_t;
很显然,要了解gfp_t,关键是要了解__bitwise__,它也在types.h里定义
170 #ifdef __CHECKER__
171 #define __bitwise__ __attribute__((bitwise))
172 #else
174 #endif
__bitwise__的含义又取决于是否定义了__CHECKER__,如果没有定义__CHECKER__,那__bitwise__就啥也不是。哪里定义了__CHECKER__?穿别人的鞋,走自己的路,让他们去找吧,咱们不找,因为内核代码里就没有哪个地方定义了__CHECKER__,它是有关Sparse工具的,内核编译时的参数决定了是不是使用Sparse工具来做类型检查。那Sparse又是什么?它是一种静态分析工具(static analysis tool), 用于在linux内核源代码中发现各种类型的漏洞,一直都是比较神秘的角色,最初由Linus Torvalds写的,后来linus没有继续维护,直到去年的冬天,它才又有了新的维护者Josh Triplett。有关Sparse再多的东东,咱们还是各自去研究吧,这里不多说了。
可能还会有第三个问题,usb_alloc_urb也没做多少事啊,它做的那些咱们自己很容易就能做了,为什么还说驱动里一定要使用它来创建urb那?按照C++的说法,它就是urb的构造函数,构造函数是创建对象的唯一方式,你抬杠说C++里面儿使用位拷贝去复制一个简单对象给新对象就没使用构造函数,那是你不知道,C++的ARM里将这时的构造函数称为trivial copy constructor。再说,现在它做这些事儿,以后还是做这些么?它将创建urb的工作给包装了,咱们只管调用就是了,孙子兵法里有,以不变应万变。
对应的,当然还会有个析构函数,销毁urb的,也在urb.c里定义
71 /**
72 * usb_free_urb - frees the memory used by a urb when all users of it are finished
73 * @urb: pointer to the urb to free, may be NULL
74 *
75 * Must be called when a user of a urb is finished with it. When the last user
76 * of the urb calls this function, the memory of the urb is freed.
77 *
78 * Note: The transfer buffer associated with the urb is not freed, that must be
79 * done elsewhere.
80 */
81 void usb_free_urb(struct urb *urb)
82 {
83         if (urb)
84                 kref_put(&urb->kref, urb_destroy);
85 }
usb_free_urb更潇洒,只调用kref_put将urb的引用计数减一,减了之后如果变为0,也就是没人再用它了,就调用urb_destroy将它销毁掉。
接着看第二个基本点,usb_fill_control_urb函数,初始化刚才创建的控制urb,你要想使用urb进行usb传输,不是光为它申请点内存就够的,你得为它初始化,充实点实实在在的内容,这个和女星要出名快,也要填充点内容的道理是一样的。它是在include/linux/usb.h里定义的内联函数
1161 /**
1162 * usb_fill_control_urb - initializes a control urb
1163 * @urb: pointer to the urb to initialize.
1164 * @dev: pointer to the struct usb_device for this urb.
1165 * @pipe: the endpoint pipe
1166 * @setup_packet: pointer to the setup_packet buffer
1167 * @transfer_buffer: pointer to the transfer buffer
1168 * @buffer_length: length of the transfer buffer
1169 * @complete_fn: pointer to the usb_complete_t function
1170 * @context: what to set the urb context to.
1171 *
1172 * Initializes a control urb with the proper information needed to submit
1173 * it to a device.
1174 */
1175 static inline void usb_fill_control_urb (struct urb *urb,
1176                                          struct usb_device *dev,
1177                                          unsigned int pipe,
1178                                          unsigned char *setup_packet,
1179                                          void *transfer_buffer,
1180                                          int buffer_length,
1181                                          usb_complete_t complete_fn,
1182                                          void *context)
1184         spin_lock_init(&urb->lock);
1185         urb->dev = dev;
1186         urb->pipe = pipe;
1187         urb->setup_packet = setup_packet;
1188         urb->transfer_buffer = transfer_buffer;
1189         urb->transfer_buffer_length = buffer_length;
1190         urb->complete = complete_fn;
1191         urb->context = context;
这个函数长的就让人兴奋,纯粹是来增长咱们自信的,自信多一分,成功就多十分,你就能搞懂内核,你就能成为一个成功的男人。这个函数基本上都是赋值语句,把你在参数里指定的值充实给刚刚创建的urburb的元素有很多,这里只是填充了一部分,剩下那些不是控制传输管不着的,就是自有安排可以不用去管的。
你想想,一个struct urb结构要应付四种传输类型,每种传输类型总会有点自己特别的要求,总会有些元素专属于某种传输类型,而其它传输类型不用管的。如果按C++的做法,这称不上是一个好的设计思想,应该有个基类urb,里面放点儿四种传输类型公用的,比如pipetransfer_buffer等,再搞几个子类,control_urbbulk_urb等等,专门应付具体的传输类型,如果不用什么虚函数,实际的时间空间消耗也不会增加什么。但是实在没必要这么搞,这年头儿内核的结构已经够多了,你创建什么类型的urb,就填充相关的一些字段好了,况且写usb core的哥们儿已经给咱们提供了不同传输类型的初始化函数,就像上面的usb_fill_control_urb,对于批量传输有usb_fill_bulk_urb,对于中断传输有usb_fill_int_urb,一般来说这也就够了,下面就看看usb_fill_control_urb函数的这俩孪生兄弟。
1194 /**
1195 * usb_fill_bulk_urb - macro to help initialize a bulk urb
1196 * @urb: pointer to the urb to initialize.
1197 * @dev: pointer to the struct usb_device for this urb.
1198 * @pipe: the endpoint pipe
1199 * @transfer_buffer: pointer to the transfer buffer
1200 * @buffer_length: length of the transfer buffer
1201 * @complete_fn: pointer to the usb_complete_t function
1202 * @context: what to set the urb context to.
1203 *
1204 * Initializes a bulk urb with the proper information needed to submit it
1205 * to a device.
1206 */
1207 static inline void usb_fill_bulk_urb (struct urb *urb,
1208                                       struct usb_device *dev,
1209                                       unsigned int pipe,
1210                                       void *transfer_buffer,
1211                                       int buffer_length,
1212                                       usb_complete_t complete_fn,
1213                                       void *context)
1215         spin_lock_init(&urb->lock);
1216         urb->dev = dev;
1217         urb->pipe = pipe;
1218         urb->transfer_buffer = transfer_buffer;
1219         urb->transfer_buffer_length = buffer_length;

抱歉!评论已关闭.