【转】Linux那些事儿 之 戏说USB(27)设备的生命线(六)

等俺变拽了,手表买两块,左一块右一块,汽车买两辆,开一辆拖一辆

等俺变拽了,宝马买两辆,一辆开道一辆护架,俺在中间骑自行车

等俺变拽了,上市公司开两家,一家挤垮另一家

等俺变拽了,航空母舰造两艘,一艘打沉另一艘;原子弹造两颗,一颗引爆另一颗

等俺变拽了,通信公司开两家,一家叫不在服务区,一家叫暂时无法接通,我让你不在服务区你就不在服务区,我让你暂时无法接通你就暂时无法接通

俺变拽了,变态函数写两个,一个让系统崩溃,一个让你崩溃

俺现在离拽还差两个筋斗云,所以只有usb_submit_urb函数让我给崩溃的份儿,现在就看看这个几百行的函数。

107 /**
108  * usb_submit_urb - issue an asynchronous transfer request for an endpoint
109  * @urb: pointer to the urb describing the request
110  * @mem_flags: the type of memory to allocate, see kmalloc() for a list
111  *      of valid options for this.
112  *
113  * This submits a transfer request, and transfers control of the URB
114  * describing that request to the USB subsystem.  Request completion will
115  * be indicated later, asynchronously, by calling the completion handler.
116  * The three types of completion are success, error, and unlink
117  * (a software-induced fault, also called "request cancellation"). 
118  *
119  * URBs may be submitted in interrupt context.
120  *
121  * The caller must have correctly initialized the URB before submitting
122  * it.  Functions such as usb_fill_bulk_urb() and usb_fill_control_urb() are
123  * available to ensure that most fields are correctly initialized, for
124  * the particular kind of transfer, although they will not initialize
125  * any transfer flags.
126  *
127  * Successful submissions return 0; otherwise this routine returns a
128  * negative error number.  If the submission is successful, the complete()
129  * callback from the URB will be called exactly once, when the USB core and
130  * Host Controller Driver (HCD) are finished with the URB.  When the completion
131  * function is called, control of the URB is returned to the device
132  * driver which issued the request.  The completion handler may then
133  * immediately free or reuse that URB.
134  *
135  * With few exceptions, USB device drivers should never access URB fields
136  * provided by usbcore or the HCD until its complete() is called.
137  * The exceptions relate to periodic transfer scheduling.  For both
138  * interrupt and isochronous urbs, as part of successful URB submission
139  * urb->interval is modified to reflect the actual transfer period used
140  * (normally some power of two units).  And for isochronous urbs,
141  * urb->start_frame is modified to reflect when the URB's transfers were
142  * scheduled to start.  Not all isochronous transfer scheduling policies
143  * will work, but most host controller drivers should easily handle ISO
144  * queues going from now until 10-200 msec into the future.
145  *
146  * For control endpoints, the synchronous usb_control_msg() call is
147  * often used (in non-interrupt context) instead of this call.
148  * That is often used through convenience wrappers, for the requests
149  * that are standardized in the USB 2.0 specification.  For bulk
150  * endpoints, a synchronous usb_bulk_msg() call is available.
151  *
152  * Request Queuing:
153  *
154  * URBs may be submitted to endpoints before previous ones complete, to
155  * minimize the impact of interrupt latencies and system overhead on data
156  * throughput.  With that queuing policy, an endpoint's queue would never
157  * be empty.  This is required for continuous isochronous data streams,
158  * and may also be required for some kinds of interrupt transfers. Such
159   * queuing also maximizes bandwidth utilization by letting USB controllers
160   * start work on later requests before driver software has finished the
161   * completion processing for earlier (successful) requests.
162   *
163   * As of Linux 2.6, all USB endpoint transfer queues support depths greater
164   * than one.  This was previously a HCD-specific behavior, except for ISO
165   * transfers.  Non-isochronous endpoint queues are inactive during cleanup
166   * after faults (transfer errors or cancellation).
167   *
168   * Reserved Bandwidth Transfers:
169   *
170  * Periodic transfers (interrupt or isochronous) are performed repeatedly,
171  * using the interval specified in the urb.  Submitting the first urb to
172  * the endpoint reserves the bandwidth necessary to make those transfers.
173  * If the USB subsystem can't allocate sufficient bandwidth to perform
174  * the periodic request, submitting such a periodic request should fail.
175   *
176   * Device drivers must explicitly request that repetition, by ensuring that
177   * some URB is always on the endpoint's queue (except possibly for short
178   * periods during completion callacks).  When there is no longer an urb
179  * queued, the endpoint's bandwidth reservation is canceled.  This means
180  * drivers can use their completion handlers to ensure they keep bandwidth
181  * they need, by reinitializing and resubmitting the just-completed urb
182  * until the driver longer needs that periodic bandwidth.
183  *
184  * Memory Flags:
185  *
186  * The general rules for how to decide which mem_flags to use
187  * are the same as for kmalloc.  There are four
188  * different possible values; GFP_KERNEL, GFP_NOFS, GFP_NOIO and
189  * GFP_ATOMIC.
190  *
191  * GFP_NOFS is not ever used, as it has not been implemented yet.
192  *
193  * GFP_ATOMIC is used when
194  *   (a) you are inside a completion handler, an interrupt, bottom half,
195  *       tasklet or timer, or
196  *   (b) you are holding a spinlock or rwlock (does not apply to
197  *       semaphores), or
198  *   (c) current->state != TASK_RUNNING, this is the case only after
199  *       you've changed it.
200  *
201   * GFP_NOIO is used in the block io path and error handling of storage
202   * devices.
203  *
204  * All other situations use GFP_KERNEL.
205  *
206  * Some more specific rules for mem_flags can be inferred, such as
207  *  (1) start_xmit, timeout, and receive methods of network drivers must
208  *      use GFP_ATOMIC (they are called with a spinlock held);
209  *  (2) queuecommand methods of scsi drivers must use GFP_ATOMIC (also
210  *      called with a spinlock held);
211  *  (3) If you use a kernel thread with a network driver you must use
212  *      GFP_NOIO, unless (b) or (c) apply;
213  *  (4) after you have done a down() you can use GFP_KERNEL, unless (b) or (c)
214  *      apply or your are in a storage driver's block io path;
215  *  (5) USB probe and disconnect can use GFP_KERNEL unless (b) or (c) apply; and
216  *  (6) changing firmware on a running storage or net device uses
217  *      GFP_NOIO, unless b) or c) apply
218  *
219  */
220 int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
221 {
222         int                     pipe, temp, max;
223         struct usb_device       *dev;
224         int                     is_out;
225
226         if (!urb || urb->hcpriv || !urb->complete)
227                 return -EINVAL;
228         if (!(dev = urb->dev) ||
229             (dev->state < USB_STATE_DEFAULT) ||
230             (!dev->bus) || (dev->devnum <= 0))
231                 return -ENODEV;
232         if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
233                         || dev->state == USB_STATE_SUSPENDED)
234                 return -EHOSTUNREACH;
235
236         urb->status = -EINPROGRESS;
237         urb->actual_length = 0;
238
239         /* Lots of sanity checks, so HCDs can rely on clean data
240          * and don't need to duplicate tests
241          */
242         pipe = urb->pipe;
243         temp = usb_pipetype(pipe);
244         is_out = usb_pipeout(pipe);
245
246         if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)
247                 return -ENODEV;
248
249         /* FIXME there should be a sharable lock protecting us against
250          * config/altsetting changes and disconnects, kicking in here.
251          * (here == before maxpacket, and eventually endpoint type,
252          * checks get made.)
253          */
254
255         max = usb_maxpacket(dev, pipe, is_out);
256         if (max <= 0) {
257                 dev_dbg(&dev->dev,
258                         "bogus endpoint ep%d%s in %s (bad maxpacket %d)/n",
259                         usb_pipeendpoint(pipe), is_out ? "out" : "in",
260                         __FUNCTION__, max);
261                 return -EMSGSIZE;
262         }
263
264         /* periodic transfers limit size per frame/uframe,
265          * but drivers only control those sizes for ISO.
266          * while we're checking, initialize return status.
267          */
268         if (temp == PIPE_ISOCHRONOUS) {
269                 int     n, len;
270
271                 /* "high bandwidth" mode, 1-3 packets/uframe? */
272                 if (dev->speed == USB_SPEED_HIGH) {
273                         int     mult = 1 + ((max >> 11) & 0x03);
274                         max &= 0x07ff;
275                         max *= mult;
276                 }
277
278                 if (urb->number_of_packets <= 0)                   
279                         return -EINVAL;
280                 for (n = 0; n < urb->number_of_packets; n++) {
281                         len = urb->iso_frame_desc[n].length;
282                         if (len < 0 || len > max)
283                                 return -EMSGSIZE;
284                         urb->iso_frame_desc[n].status = -EXDEV;
285                         urb->iso_frame_desc[n].actual_length = 0;
286                 }
287         }
288
289         /* the I/O buffer must be mapped/unmapped, except when length=0 */
290         if (urb->transfer_buffer_length < 0)
291                 return -EMSGSIZE;
292
293 #ifdef DEBUG
294         /* stuff that drivers shouldn't do, but which shouldn't
295          * cause problems in HCDs if they get it wrong.
296          */
297         {
298         unsigned int    orig_flags = urb->transfer_flags;
299         unsigned int    allowed;
300
301         /* enforce simple/standard policy */
302         allowed = (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP |
303                         URB_NO_INTERRUPT);
304         switch (temp) {
305         case PIPE_BULK:
306                 if (is_out)
307                          allowed |= URB_ZERO_PACKET;
308                 /* FALLTHROUGH */
309          case PIPE_CONTROL:
310                  allowed |= URB_NO_FSBR; /* only affects UHCI */
311                  /* FALLTHROUGH */
312         default:                        /* all non-iso endpoints */
313                 if (!is_out)
314                         allowed |= URB_SHORT_NOT_OK;
315                 break;
316         case PIPE_ISOCHRONOUS:
317                 allowed |= URB_ISO_ASAP;
318                 break;
319         }
320         urb->transfer_flags &= allowed;
321
322         /* fail if submitter gave bogus flags */
323         if (urb->transfer_flags != orig_flags) {
324                 err("BOGUS urb flags, %x --> %x",
325                         orig_flags, urb->transfer_flags);
326                 return -EINVAL;
327         }
328         }
329 #endif
330         /*
331          * Force periodic transfer intervals to be legal values that are
332          * a power of two (so HCDs don't need to).
333          *
334          * FIXME want bus->{intr,iso}_sched_horizon values here.  Each HC
335          * supports different values... this uses EHCI/UHCI defaults (and
336          * EHCI can use smaller non-default values).
337          */
338         switch (temp) {
339         case PIPE_ISOCHRONOUS:
340         case PIPE_INTERRUPT:
341                 /* too small? */
342                 if (urb->interval <= 0)
343                         return -EINVAL;
344                 /* too big? */
345                 switch (dev->speed) {
346                 case USB_SPEED_HIGH:    /* units are microframes */
347                         // NOTE usb handles 2^15
348                         if (urb->interval > (1024 * 8))
349                                 urb->interval = 1024 * 8;
350                         temp = 1024 * 8;
351                         break;
352                 case USB_SPEED_FULL:    /* units are frames/msec */
353                 case USB_SPEED_LOW:
354                         if (temp == PIPE_INTERRUPT) {
355                                 if (urb->interval > 255)
356                                         return -EINVAL;
357                                 // NOTE ohci only handles up to 32
358                                 temp = 128;
359                         } else {
360                                 if (urb->interval > 1024)
361                                         urb->interval = 1024;
362                                 // NOTE usb and ohci handle up to 2^15
363                                 temp = 1024;
364                         }
365                         break;
366                 default:
367                         return -EINVAL;
368                 }
369                 /* power of two? */
370                 while (temp > urb->interval)
371                         temp >>= 1;
372                 urb->interval = temp;
373         }
374
375         return usb_hcd_submit_urb(urb, mem_flags);
376 }

看到这个函数之后我深刻的体会到,世界上只有一个地方有真乐:乐土。不过这个函数长归长,目标却很简单,就是对urb做些前期处理后扔给HCD

226行,一些有关存在性的判断,某主义的哲学告诉我们:存在是检验真理的唯一标准。所以这个函数的开头儿就要履行一下常规的检验,urb为空,都没有初始化是不可以提交给core的,core很生气,后果很严重,hcpriv本来说好了留给HCD用的,你得保证送过去的时候它还是贞洁的,自己不能偷偷先用了,HCD很生气,后果也会很严重,complete,每个urb结束了都必须的调用一次complete代表的函数,这是真理,你必须得让它存在。

228行,上边儿是对urb本身的检验,这里是对urb的目的地usb设备的检验。设备所属于的那条总线不存在,或者设备本身不存在,你urb还嚷嚷着要过去要过去,也太苏维埃了吧?或者设备甚至还没进入USB_STATE_DEFAULT状态,管道的另一端还都是堵着的怎么过去,早先强调多少回了,要想让设备回应你,它起码得达到Default状态。设备编号devnum肯定是不能为负的了,那为0为什么也不行那?到现在,地球人都知道了,Token包的地址域里有7位是表示设备地址的,也就是说总共可以有128个地址来分配给设备,但是其中0号地址是被保留作为缺省地址用的,任何一个设备处于Default状态还没有进入Address状态的时候都需要通过这个缺省地址来响应主机的请求,所以0号地址不能分配给任何一个设备,hub为设备选择一个地址的时候,只有选择到一个大于0的地址,设备的生命线才会继续,才会走到这里,因此说这里的devnum是不可能也不应该为0的,如果为0的话,那就是中间哪里谁暗地里动了手脚,就没必要往下走了。

因为咱们看到这里是因为要设置设备的地址,让设备进入Address状态,所以针对SET_ADDRESS请求再看看这个devnum。主机向设备发送SET_ADDRESS请求时,如果设备处于Default状态,就是它现在处的状态,指定一个非0值时,设备将进入Adress状态,指定0值时,设备仍然会处于Default状态,所以说即使从这个角度看,这里的devnum也是不能为0的,不然就是吃饱饭没事干故意找抽。如果设备已经处于Adress状态,指定一个非0值时,设备仍然会处于Address状态,只是将使用新分配的地址,一个设备只能占用一个地址,是包分配的,真正的居者有其屋,如果指定了一个0值,则设备将离开Address状态退回到Default状态。

232行,powerpower_stateevent,还有PM_EVENT_ON都是电源管理核心里的东西,这里的目的是判断设备所在的那条总线的主机控制器有没有挂起,然后再判断设备本身是不是处于Suspended状态,如果挂起了都不欢迎你,还死皮赖脸去个什么劲儿,回去得了。

236行,常规检查都做完了,coreHCD已经认同了这个urb,就将它的状态设置为-EINPROGRESS,表示从现在开始urb的控制权就在coreHCD手里边儿了,驱动那里是看不到这个状态的。

237行,这时还没开始传输,实际传输的数据长度当然为0了,这里初始化这么一下,也是为了防止以后哪里出错返回了,驱动里好检查。

242行,这几行获得管道的类型还有方向。

246行,在设备进入Configured状态之前,主机只能使用控制传输,通过缺省管道,也就是管道0来和设备进行交流。

255行,获得端点的wMaxPacketSize,看看include/linux/usb.h里定义的这个函数

1458 static inline __u16
1459 usb_maxpacket(struct usb_device *udev, int pipe, int is_out)
1460 {
1461          struct usb_host_endpoint        *ep;
1462          unsigned                        epnum = usb_pipeendpoint(pipe);
1464          if (is_out) {
1465                  WARN_ON(usb_pipein(pipe));
1466                  ep = udev->ep_out[epnum];
1467          } else {
1468                  WARN_ON(usb_pipeout(pipe));
1469                  ep = udev->ep_in[epnum];
1470          }
1471          if (!ep)
1472                  return 0;
1474          /* NOTE:  only 0x07ff bits are for packet size... */
1475          return le16_to_cpu(ep->desc.wMaxPacketSize);
1476 }

这个函数不管从理论上还是实际上都是很简单的。咱们可以先问下自己,根据现有的信息如何获得一个端点的wMaxPacketSize?当然是必须得获得该端点的描述符,我们知道每个struct usb_device结构体里都有两个数组ep_outep_in保存了各个端点对应的struct usb_host_endpoint结构体,只要知道该端点对应了这两个数组里的哪个元素就可以获得它的描述符了,这就需要知道该端点的端点号和方向,而端点的方向就管道的方向,端点号也在pipe里保存有。

你是不是会担心ep_outep_in数组都还空着,或者说没有保存对应的端点信息?倒不用担心它还是空的,即使是现在设备还刚从Powered走到Default,百废待兴,连自己的Address都没有,但是在使用usb_alloc_dev构造这个设备的struct usb_device的时候就把它里面端点0struct usb_host_endpoint结构体ep0指定给ep_out[0]ep_in[0]了,而且后来还对ep0wMaxPacketSize指定了值。不过如果真的没有从它们里面找到想要的那个端点的信息,那肯定就是哪里出错了,指定了错误的端点号,或其它什么原因,也就不用再继续走了,还是打到回府吧。

268行,如果是等时传输要做一些特别的处理。272276这几行涉及到高速、高带宽端点(high speedhigh bandwidth endpoint)。前面提到interval的时候,说过每一帧或微帧最多只能有一次等时传输,完成一次等时transaction,那时这么说主要是因为还没遇到高速高带宽的等时端点。高速高带宽等时端点每个微帧可以进行23次等时transaction,它和一般等时端点的主要区别也就在这儿,没必要专门为它搞个描述符类型,端点描述符wMaxPacketSize字段的bit 11~12就是用来指定可以额外有几次等时transaction的,00表示没有额外的transaction01表示额外有1次,10表示额外有两次,11被保留。wMaxPacketSize字段的前10位就是实际的端点每次能够处理的最大字节数。所以这几行意思就是如果是高速等时端点,获得它允许的额外的等时transaction次数,和每次能够处理的最大字节数,再将它们相乘就得出了该等时端点每个微帧的所能传输的最大字节数。

278行,number_of_packets不大于0就表示这个等时urb没有指定任何一次等时传输,这就怪哉了,咋混过来的,可以直接返回了。

280~286行对等时urb里指定的各次等时传输分别做处理。如果它们预期传输的数据长度比上面算出来的max还要大,对不起,要求太过分了,返回吧。然后将它们实际传输的数据长度先置为0,状态都先初始化为-EXDEV,表示这次等时传输仅仅部分完成了,因为走到这里时传输都还没开始那。

290行,transfer_buffer_length长度不能小于0吧,等于0倒是可以的,毕竟不是什么时候都是有数据要传的。

293行,见到#ifdef DEBUG我们都应该很高兴,这意味着直到下面对应的#endif,之间的代码都可以华丽丽的飘过了,给人调试时用的,说明对整体无关痛痒。

338行,temp是上面计算出来的管道类型,那下面的各个case肯定是针对四种传输类型的了。不过经过实地考察,我们可以发现,这里只case了等时传输和中断传输两种周期性的传输类型,因为是关于interval的处理,所以就没控制传输和批量传输什么事儿了。

342行,这里保证等时和中断urbinterval必须是大于0的,不然主机那边儿看不懂你这是表示什么意思,究竟要不要去访问你,搞个负数和0含含糊糊的,日里万鸡的主机没功夫去猜你心思。

345行,这里的switch根据目的设备的速度去case,速度有三种,case也有三个。我们前面已经说过,不同的速度,urb->interval可以取不同的范围,不过你可能会发现那时说的最大值要比这里的限制要大一些,这是因为协议归协议,实现归实现,比如,对于UHCI来说,中断传输的interval不能比128更大,而协议规定的最大值为255。那么现在的问题是,temp又是做什么用的?要注意urb->interval的单位是帧或者微帧,temp只是为了调整它的值为2的次幂,这点从370行就可以看出来。

375行,将urb扔给HCD,然后就进入HCD的片儿区了。

 

本来usb_submit_urb函数到此应该结束了,但是它对于写驱动的来说太重要了,驱动里做的所有铺垫就是为了使用usb_submit_urb提交一个合适的urb给设备,然后满怀期待的等待着设备回馈你需要的信息,再然后才有你接下来的处理,不然你的usb驱动只是一纸空谈毫无用处,就像长工一年的辛劳就是为了交够给地主家的租子,咱们一生的辛苦只是为了从房地产商那里讨得一套房子。所以有必要多说一些。

首先还是要再次强调一下,在调用usb_submit_urb提交你的urb之前,一定必须不得不要对它正确的初始化,对于控制/中断/批量传输,core都提供了usb_fill_control_urb的几个孪生兄弟供你初始化使用,对于等时传输要自己手工一步一步小心翼翼的对urb的相关元素逐个赋值。下层基础决定上层建筑,你的urb决定了你的整个usb驱动能否顺利运转。

第二,对于驱动来说,usb_submit_urb是异步的,也就是说不用等传输完全完成就返回了,只要usb_submit_urb的返回值表示为0,就表示已经提交成功了,你的urb已经被coreHCD认可了,接下来coreHCD怎么处理就是它们的事了,驱动该干吗干吗去。比如你东拼西凑拿够了开发商要的款子,他给你个证明,俗称合同,然后你就就不用管也管不着他们怎么去盖,用什么材料去盖,你能做的只是等着收房子。

只要你提交成功了,不管是中间出了差错还是顺利完成,你指定的结束处理函数总是会调用,只有到这个时候,你才能够重新拿到urb的控制权,检查它是不是出错了,需要不需要释放或者是重新提交。你只要付了款子,房子盖好了不管怎样总是会有你的,你可以去测量,去检查,去验收,运气好了就OK,运气不好就自己受着吧,或者去大马路边儿上挂横幅“黑心开发商还我血汗钱”。过程是不同的,道理是一样的。

那么,第三就是,什么时候需要在结束处理函数里重新提交这个urb?其实,我更想问的是对于中断/等时传输,是怎么实现让主机按一定周期去访问端点的?端点的描述符里已经指定了这个间隔时间是没错儿,urb里也有interval描述了这个间隔周期,更没错儿,可是咱们的urb一次只完成一次传输,即使等时传输也只完成有限次的传输,然后就在结束处理函数里返回了,urb的控制权就完全属于驱动了,接下来的周期访问是怎么做到的?难道脱离urb主机自己就去智能化的自动的与端点通信了?OK,即使是这样了,那通信的数据又在哪里,你又怎么去得到这些数据?

事实上,你第一次提交一个中断或等时的urb的时候,HCD会根据interval判断一下自己是否能够满足你的需要,如果不能够安排足够的带宽来完成这种周期性的传输,它是不可能会批准你的请求的,如果它估量一下觉得自己可以满足,就会为你保留足够的带宽。但是这并不是就表明万事大吉了,HCD是为你保留带宽了,可是驱动得保证在对应端点要处理的那个urb队列里总是有urb,不能是空的,否则这个保留的带宽就会被cancel掉。那么问题就变成,对于中断/等时传输,如何保证对应端点的urb队列里总是会有urb?这就回到最开始的问题了,驱动需要在结束处理函数里重新初始化和提交刚刚完成的urb,友情提醒一下,这个时候你是不能够修改interval的值的,否则等待你的只能是错误。中断传输的例子可以去看看触摸屏驱动,等时传输的可以去看看摄像头驱动,看看它们在结束处理函数里都做了些什么,你就悟道了。

第四个要说的是,对于控制/批量/中断传输,实际上很多时候你可以不用创建urb,不用对它初始化,不用调用usb_submit_urb来提交,core将这个过程分别封装在了usb_control_msgusb_bulk_msgusb_interrupt_msg这三个函数里,不同的是它们的实现是同步的,会去等待传输的完全结束。咱们就是从usb_control_msg走过来的,所以这里只看看另外两个,它们都定义在drivers/usb/core/message.c

145 /**
146  * usb_interrupt_msg - Builds an interrupt urb, sends it off and waits for completion
147  * @usb_dev: pointer to the usb device to send the message to
148  * @pipe: endpoint "pipe" to send the message to
149  * @data: pointer to the data to send
150  * @len: length in bytes of the data to send
151  * @actual_length: pointer to a location to put the actual length transferred in bytes
152  * @timeout: time in msecs to wait for the message to complete before
153  *      timing out (if 0 the wait is forever)
154  * Context: !in_interrupt ()
155  *
156  * This function sends a simple interrupt message to a specified endpoint and
157  * waits for the message to complete, or timeout.
158  *
159  * If successful, it returns 0, otherwise a negative error number.  The number
160  * of actual bytes transferred will be stored in the actual_length paramater.
161  *
162  * Don't use this function from within an interrupt context, like a bottom half
163  * handler.  If you need an asynchronous message, or need to send a message
164  * from within interrupt context, use usb_submit_urb() If a thread in your
165  * driver uses this call, make sure your disconnect() method can wait for it to
166  * complete.  Since you don't have a handle on the URB used, you can't cancel
167  * the request.
168  */
169 int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe,
170                       void *data, int len, int *actual_length, int timeout)
171 {
172         return usb_bulk_msg(usb_dev, pipe, data, len, actual_length, timeout);
173 }
usb_interrupt_msg够酷,也够省事儿,全部都借助usb_bulk_msg去完成了。
176 /**
177  *      usb_bulk_msg - Builds a bulk urb, sends it off and waits for completion
178  *      @usb_dev: pointer to the usb device to send the message to
179  *      @pipe: endpoint "pipe" to send the message to
180  *      @data: pointer to the data to send
181  *      @len: length in bytes of the data to send
182  *      @actual_length: pointer to a location to put the actual length transferred in bytes
183  *      @timeout: time in msecs to wait for the message to complete before
184  *              timing out (if 0 the wait is forever)
185  *      Context: !in_interrupt ()
186  *
187  *      This function sends a simple bulk message to a specified endpoint
188  *      and waits for the message to complete, or timeout.
189  *     
190  *      If successful, it returns 0, otherwise a negative error number.
191  *      The number of actual bytes transferred will be stored in the
192  *      actual_length paramater.
193  *
194  *      Don't use this function from within an interrupt context, like a
195  *      bottom half handler.  If you need an asynchronous message, or need to
196  *      send a message from within interrupt context, use usb_submit_urb()
197  *      If a thread in your driver uses this call, make sure your disconnect()
198  *      method can wait for it to complete.  Since you don't have a handle on
199  *      the URB used, you can't cancel the request.
200  *
201  *      Because there is no usb_interrupt_msg() and no USBDEVFS_INTERRUPT
202  *      ioctl, users are forced to abuse this routine by using it to submit
203  *      URBs for interrupt endpoints.  We will take the liberty of creating
204  *      an interrupt URB (with the default interval) if the target is an
205  *      interrupt endpoint.
206  */
207 int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe,
208                         void *data, int len, int *actual_length, int timeout)
209 {
210         struct urb *urb;
211         struct usb_host_endpoint *ep;
212
213         ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)
214                         [usb_pipeendpoint(pipe)];
215         if (!ep || len < 0)
216                 return -EINVAL;
217
218         urb = usb_alloc_urb(0, GFP_KERNEL);
219         if (!urb)
220                 return -ENOMEM;
221
222         if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
223                         USB_ENDPOINT_XFER_INT) {
224                 pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);
225                 usb_fill_int_urb(urb, usb_dev, pipe, data, len,
226                                 usb_api_blocking_completion, NULL,
227                                 ep->desc.bInterval);
228         } else
229                 usb_fill_bulk_urb(urb, usb_dev, pipe, data, len,
230                                 usb_api_blocking_completion, NULL);
231
232         return usb_start_wait_urb(urb, timeout, actual_length);
233 }

都坚持走到这里了,看懂这个函数还是很easy的,首先根据指定的pipe获得端点的方向和端点号,然后从设备struct usb_device结构体的ep_inep_out数组里得道端点对应的struct usb_host_endpoint结构体,接着调用usb_alloc_urb创建urb。因为这个函数可能是从usb_interrupt_msg那里调用过来的,所以接下来要根据端点描述符的bmAttributes字段获取传输的类型,判断究竟是中断传输还是批量传输,是中断传输的话还要修改pipe的类型,防止万一谁谁直接调用usb_bulk_msg来完成中断传输,虽说很少人会穷极无聊到这种地步,预防一下总归是没错的。不管是中断传输还是批量传输,都要调用usb_fill_xxx_urb来初始化,最后,和usb_control_msg一样,调用usb_start_wait_urb函数。

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
作者用通俗幽默的语言简述了linux的相关知识点,很容易掌握的,建议大家好好学哦 我是U盘 说的是2.6.10的内核 我是Sysfs 说的是2.6.10的内核 戏说USB 说的是2.6.22的内核 我是Hub/UHCI/EHCI 说的是2.6.22.1的内核 其中我是U盘属于基础性的.这一阶段会遇到一些问题.比如urb提交之后究竟怎么处理的?用户空间究竟是如何访问U盘的?DMA究竟怎么回事. 这之后可以开始看Hub.这一阶段你会明白一个usb设备,比如U盘,连接到hub上之后都发生了什么. 然后是usb core(也就是戏说USB),这一阶段是个承上启下的角色,承的是U盘/HUB,启的是UHCI/EHCI,主要描述一个usb设备连接到hub上之后,在HUB和UHCI/EHCI之间也就是usb core里发生的故事. 再然后可以开始看UHCI/EHCI.这一阶段会找到上一阶段的部分问题的答案.但同时在PCI方面可能会遇到另外一些问题.比如PCI设备究竟如何被枚举的? 再然后是PCI总线驱动.这一阶段会找到上一阶段问题的答案. 再然后是scsi disk的驱动.这一阶段会找到第一阶段的部分问题的答案.即U盘是如何以一种磁盘的方式被访问的. 再然后是scsi core以及block层驱动.到了这一阶段基本上就能回答我是U盘中所有的困惑了.(其中Block层由于过于复杂和规模庞大,主要是举例和个别函数分析,主要是辅助另外几个模块进行分析.) 以上每一阶段代码跳跃性会逐渐增强,即开始会讲的细,之后会讲的粗.但整体上,各个阶段是相互关联的.  ==================================================================================== 此外, 我是Sysfs是贯穿所有故事的,sysfs提供了诸多的接口,各个子系统都会用到.可以把它当作参考书. 这个系列可以伴随着相应的系列一起看,对理解其它各部分都有帮助.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值