`
javatome
  • 浏览: 820132 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

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;

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;

233 || dev->state == USB_STATE_SUSPENDED)

234 return -EHOSTUNREACH;

237 urb->actual_length = 0;

239 /* Lots of sanity checks, so HCDs can rely on clean data

240 * and don't need to duplicate tests

241 */

244 is_out = usb_pipeout(pipe);

246 if (!usb_pipecontrol(pipe) && dev->state < USB_STATE_CONFIGURED)

247 return -ENODEV;

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 */

256 if (max <= 0) {

258 "bogus endpoint ep%d%s in %s (bad maxpacket %d)/n",

259 usb_pipeendpoint(pipe), is_out ? "out" : "in",

261 return -EMSGSIZE;

262 }

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 */

269 int n, len;

271 /* "high bandwidth" mode, 1-3 packets/uframe? */

273 int mult = 1 + ((max >> 11) & 0x03);

274 max &= 0x07ff;

275 max *= mult;

276 }

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 }

289 /* the I/O buffer must be mapped/unmapped, except when length=0 */

290 if (urb->transfer_buffer_length < 0)

291 return -EMSGSIZE;

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;

301 /* enforce simple/standard policy */

304 switch (temp) {

306 if (is_out)

307 allowed |= URB_ZERO_PACKET;

308 /* FALLTHROUGH */

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;

317 allowed |= URB_ISO_ASAP;

318 break;

319 }

320 urb->transfer_flags &= allowed;

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) {

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 */

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;

373 }

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;

1464 if (is_out) {

1466 ep = udev->ep_out[epnum];

1467 } else {

1469 ep = udev->ep_in[epnum];

1470 }

1471 if (!ep)

1472 return 0;

1474 /* NOTE: only 0x07ff bits are for packet size... */

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;

213 ep = (usb_pipein(pipe) ? usb_dev->ep_in : usb_dev->ep_out)

215 if (!ep || len < 0)

216 return -EINVAL;

219 if (!urb)

220 return -ENOMEM;

222 if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==

224 pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30);

227 ep->desc.bInterval);

228 } else

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函数。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics