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

转载地址:http://blog.csdn.net/fudan_abc/article/details/1825017

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

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

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

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

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

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

俺现在离拽还差两个筋斗云,所以只有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行,power,power_state,event,还有PM_EVENT_ON都是电源管理核心里的东西,这里的目的是判断设备所在的那条总线的主机控制器有没有挂起,然后再判断设备本身是不是处于Suspended状态,如果挂起了都不欢迎你,还死皮赖脸去个什么劲儿,回去得了。

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

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_out和ep_in保存了各个端点对应的struct usb_host_endpoint结构体,只要知道该端点对应了这两个数组里的哪个元素就可以获得它的描述符了,这就需要知道该端点的端点号和方向,而端点的方向就管道的方向,端点号也在pipe里保存有。

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

268行,如果是等时传输要做一些特别的处理。272到276这几行涉及到高速、高带宽端点(high speed,high bandwidth endpoint)。前面提到interval的时候,说过每一帧或微帧最多只能有一次等时传输,完成一次等时transaction,那时这么说主要是因为还没遇到高速高带宽的等时端点。高速高带宽等时端点每个微帧可以进行2到3次等时transaction,它和一般等时端点的主要区别也就在这儿,没必要专门为它搞个描述符类型,端点描述符wMaxPacketSize字段的bit 11~12就是用来指定可以额外有几次等时transaction的,00表示没有额外的transaction,01表示额外有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行,这里保证等时和中断urb的interval必须是大于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已经被core和HCD认可了,接下来core和HCD怎么处理就是它们的事了,驱动该干吗干吗去。比如你东拼西凑拿够了开发商要的款子,他给你个证明,俗称合同,然后你就就不用管也管不着他们怎么去盖,用什么材料去盖,你能做的只是等着收房子。

只要你提交成功了,不管是中间出了差错还是顺利完成,你指定的结束处理函数总是会调用,只有到这个时候,你才能够重新拿到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_msg、usb_bulk_msg和usb_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_in或ep_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
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值