usbdi.c revision 1.119.12.2 1 /* $NetBSD: usbdi.c,v 1.119.12.2 2007/05/31 23:15:18 itohy Exp $ */
2 /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.99 2006/11/27 18:39:02 marius Exp $ */
3
4 /*-
5 * Copyright (c) 1998 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Lennart Augustsson (lennart (at) augustsson.net) at
10 * Carlstedt Research & Technology.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the
19 * documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 * must display the following acknowledgement:
22 * This product includes software developed by the NetBSD
23 * Foundation, Inc. and its contributors.
24 * 4. Neither the name of The NetBSD Foundation nor the names of its
25 * contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
29 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
30 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
32 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include <sys/cdefs.h>
42 __KERNEL_RCSID(0, "$NetBSD: usbdi.c,v 1.119.12.2 2007/05/31 23:15:18 itohy Exp $");
43 /* __FBSDID("$FreeBSD: src/sys/dev/usb/usbdi.c,v 1.99 2006/11/27 18:39:02 marius Exp $"); */
44
45 #ifdef __NetBSD__
46 #include "opt_compat_netbsd.h"
47 #endif
48
49 #include <sys/param.h>
50 #include <sys/systm.h>
51 #if defined(__NetBSD__) || defined(__OpenBSD__)
52 #include <sys/kernel.h>
53 #include <sys/device.h>
54 #elif defined(__FreeBSD__)
55 #include <sys/module.h>
56 #include <sys/bus.h>
57 #include "usb_if.h"
58 #if defined(DIAGNOSTIC) && defined(__i386__)
59 #include <machine/cpu.h>
60 #endif
61 #endif
62 #include <sys/malloc.h>
63 #include <sys/mbuf.h>
64 #include <sys/proc.h>
65
66 #include <machine/bus.h>
67
68 #include <dev/usb/usb.h>
69 #include <dev/usb/usbdi.h>
70 #include <dev/usb/usbdi_util.h>
71 #include <dev/usb/usbdivar.h>
72 /* #include <dev/usb/usb_mem.h> */
73 #include <dev/usb/usb_quirks.h>
74
75 #if defined(__FreeBSD__)
76 #include "usb_if.h"
77 #define delay(d) DELAY(d)
78 #endif
79
80 /* UTF-8 encoding stuff */
81 #include <fs/unicode.h>
82
83 #ifdef USB_DEBUG
84 #define DPRINTF(x) if (usbdebug) logprintf x
85 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x
86 extern int usbdebug;
87 #else
88 #define DPRINTF(x)
89 #define DPRINTFN(n,x)
90 #endif
91
92 Static usbd_xfer_handle usbd_alloc_xfer_flag(usbd_device_handle,
93 usbd_pipe_handle pipe, enum usbd_waitflg);
94 Static void usbd_free_buffer_flag(usbd_xfer_handle, enum usbd_waitflg);
95 Static usbd_status usbd_free_xfer_flag(usbd_xfer_handle, enum usbd_waitflg);
96 Static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe);
97 Static void usbd_do_request_async_cb
98 (usbd_xfer_handle, usbd_private_handle, usbd_status);
99 Static void usbd_do_request_async_task(void *);
100 Static void usbd_start_next(usbd_pipe_handle pipe);
101 Static usbd_status usbd_open_pipe_ival
102 (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int);
103
104 int
105 usbd_xfer_isread(usbd_xfer_handle xfer)
106 {
107 if (xfer->rqflags & URQ_REQUEST)
108 return (xfer->request.bmRequestType & UT_READ);
109 else
110 return (xfer->pipe->endpoint->edesc->bEndpointAddress &
111 UE_DIR_IN);
112 }
113
114 #ifdef USB_DEBUG
115 void
116 usbd_dump_iface(struct usbd_interface *iface)
117 {
118 printf("usbd_dump_iface: iface=%p\n", iface);
119 if (iface == NULL)
120 return;
121 printf(" device=%p idesc=%p index=%d altindex=%d priv=%p\n",
122 iface->device, iface->idesc, iface->index, iface->altindex,
123 iface->priv);
124 }
125
126 void
127 usbd_dump_device(struct usbd_device *dev)
128 {
129 printf("usbd_dump_device: dev=%p\n", dev);
130 if (dev == NULL)
131 return;
132 printf(" bus=%p default_pipe=%p\n", dev->bus, dev->default_pipe);
133 printf(" address=%d config=%d depth=%d speed=%d self_powered=%d "
134 "power=%d langid=%d\n",
135 dev->address, dev->config, dev->depth, dev->speed,
136 dev->self_powered, dev->power, dev->langid);
137 }
138
139 void
140 usbd_dump_endpoint(struct usbd_endpoint *endp)
141 {
142 printf("usbd_dump_endpoint: endp=%p\n", endp);
143 if (endp == NULL)
144 return;
145 printf(" edesc=%p refcnt=%d\n", endp->edesc, endp->refcnt);
146 if (endp->edesc)
147 printf(" bEndpointAddress=0x%02x\n",
148 endp->edesc->bEndpointAddress);
149 }
150
151 void
152 usbd_dump_queue(usbd_pipe_handle pipe)
153 {
154 usbd_xfer_handle xfer;
155
156 printf("usbd_dump_queue: pipe=%p\n", pipe);
157 SIMPLEQ_FOREACH(xfer, &pipe->queue, next) {
158 printf(" xfer=%p\n", xfer);
159 }
160 }
161
162 void
163 usbd_dump_pipe(usbd_pipe_handle pipe)
164 {
165 printf("usbd_dump_pipe: pipe=%p\n", pipe);
166 if (pipe == NULL)
167 return;
168 usbd_dump_iface(pipe->iface);
169 usbd_dump_device(pipe->device);
170 usbd_dump_endpoint(pipe->endpoint);
171 printf(" (usbd_dump_pipe:)\n refcnt=%d running=%d aborting=%d\n",
172 pipe->refcnt, pipe->running, pipe->aborting);
173 printf(" intrxfer=%p, repeat=%d, interval=%d\n",
174 pipe->intrxfer, pipe->repeat, pipe->interval);
175 }
176 #endif
177
178 usbd_status
179 usbd_open_pipe(usbd_interface_handle iface, u_int8_t address,
180 u_int8_t flags, usbd_pipe_handle *pipe)
181 {
182 return (usbd_open_pipe_ival(iface, address, flags, pipe,
183 USBD_DEFAULT_INTERVAL));
184 }
185
186 usbd_status
187 usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address,
188 u_int8_t flags, usbd_pipe_handle *pipe, int ival)
189 {
190 usbd_pipe_handle p;
191 struct usbd_endpoint *ep;
192 usbd_status err;
193 int i;
194
195 DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n",
196 iface, address, flags));
197
198 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
199 ep = &iface->endpoints[i];
200 if (ep->edesc == NULL)
201 return (USBD_IOERROR);
202 if (ep->edesc->bEndpointAddress == address)
203 goto found;
204 }
205 return (USBD_BAD_ADDRESS);
206 found:
207 if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0)
208 return (USBD_IN_USE);
209 err = usbd_setup_pipe(iface->device, iface, ep, ival, &p);
210 if (err)
211 return (err);
212 LIST_INSERT_HEAD(&iface->pipes, p, next);
213 *pipe = p;
214 return (USBD_NORMAL_COMPLETION);
215 }
216
217 usbd_status
218 usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address,
219 u_int8_t flags, usbd_pipe_handle *pipe,
220 usbd_private_handle priv, void *buffer, u_int32_t len,
221 usbd_callback cb, int ival)
222 {
223 usbd_status err;
224 usbd_xfer_handle xfer;
225 usbd_pipe_handle ipipe;
226
227 DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n",
228 address, flags, len));
229
230 err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE,
231 &ipipe, ival);
232 if (err)
233 return (err);
234 xfer = usbd_alloc_xfer(iface->device, ipipe);
235 if (xfer == NULL) {
236 err = USBD_NOMEM;
237 goto bad1;
238 }
239 usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags,
240 USBD_NO_TIMEOUT, cb);
241 ipipe->intrxfer = xfer;
242 ipipe->repeat = 1;
243 err = usbd_transfer(xfer);
244 *pipe = ipipe;
245 if (err != USBD_IN_PROGRESS && err)
246 goto bad2;
247 return (USBD_NORMAL_COMPLETION);
248
249 bad2:
250 ipipe->intrxfer = NULL;
251 ipipe->repeat = 0;
252 usbd_free_xfer(xfer);
253 bad1:
254 usbd_close_pipe(ipipe);
255 return (err);
256 }
257
258 usbd_status
259 usbd_close_pipe(usbd_pipe_handle pipe)
260 {
261 #ifdef DIAGNOSTIC
262 if (pipe == NULL) {
263 printf("usbd_close_pipe: pipe==NULL\n");
264 return (USBD_NORMAL_COMPLETION);
265 }
266 #endif
267
268 if (--pipe->refcnt != 0)
269 return (USBD_NORMAL_COMPLETION);
270 if (! SIMPLEQ_EMPTY(&pipe->queue))
271 return (USBD_PENDING_REQUESTS);
272 LIST_REMOVE(pipe, next);
273 pipe->endpoint->refcnt--;
274 pipe->methods->close(pipe);
275 if (pipe->intrxfer != NULL)
276 usbd_free_xfer(pipe->intrxfer);
277 free(pipe, M_USB);
278 return (USBD_NORMAL_COMPLETION);
279 }
280
281 usbd_status
282 usbd_transfer(usbd_xfer_handle xfer)
283 {
284 usbd_pipe_handle pipe = xfer->pipe;
285 usbd_status err;
286 u_int size;
287 int s;
288
289 DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n",
290 xfer, xfer->flags, pipe, pipe->running));
291 #ifdef USB_DEBUG
292 if (usbdebug > 5)
293 usbd_dump_queue(pipe);
294 #endif
295 xfer->done = 0;
296
297 if (pipe->aborting)
298 return (USBD_CANCELLED);
299
300 size = xfer->length;
301 /* If there is no buffer, allocate one. */
302 if (!(xfer->rqflags & URQ_MASK_DRV_REQUESTED_BUF) && size != 0) {
303 struct usbd_bus *bus = pipe->device->bus;
304
305 #ifdef DIAGNOSTIC
306 if (xfer->rqflags & URQ_AUTO_BUF)
307 printf("usbd_transfer: has old buffer!\n");
308 if (xfer->device->bus->intr_context)
309 panic("usbd_transfer: allocm not in process context");
310 #endif
311 err = bus->methods->allocm(bus, xfer,
312 (xfer->flags & USBD_NO_COPY) ? xfer->buffer : NULL,
313 size);
314 if (err)
315 return (err);
316 xfer->rqflags |= URQ_AUTO_BUF;
317 }
318 #ifdef DIAGNOSTIC
319 if ((xfer->rqflags & URQ_MASK_DRV_REQUESTED_BUF) != 0 &&
320 size > xfer->bufsize) {
321 panic("usbd_transfer: buffer size overrun size=%u bufsize=%lu rqflags=%x",
322 size, (unsigned long)xfer->bufsize, xfer->rqflags);
323 }
324 #endif
325
326 #ifdef DIAGNOSTIC
327 if ((xfer->flags & USBD_NO_COPY) == 0 && size != 0) {
328 if (xfer->rqflags & URQ_DEV_MAP_BUFFER)
329 printf("usbd_transfer: USBD_NO_COPY recommended with mapped buffer");
330 if (xfer->rqflags & URQ_DEV_MAP_MBUF)
331 panic("usbd_transfer: USBD_NO_COPY required with mapped mbuf");
332 }
333 #endif
334 /* Copy data if going out. */
335 if (!(xfer->flags & USBD_NO_COPY) && size != 0 &&
336 !usbd_xfer_isread(xfer) && xfer->buffer != xfer->hcbuffer) {
337 DPRINTFN(5, ("usbd_transfer: copy %p (alloc) <- %p (buffer), %u bytes\n",
338 xfer->hcbuffer, xfer->buffer, (unsigned)size));
339 memcpy(xfer->hcbuffer, xfer->buffer, size);
340 }
341
342 err = pipe->methods->transfer(xfer);
343
344 if (err != USBD_IN_PROGRESS && err) {
345 /* The transfer has not been queued, so free buffer. */
346 if (xfer->rqflags & URQ_AUTO_BUF) {
347 struct usbd_bus *bus = pipe->device->bus;
348
349 #ifdef DIAGNOSTIC
350 if (bus->intr_context)
351 panic("usbd_transfer: freem not in process context");
352 #endif
353 bus->methods->freem(bus, xfer, U_WAITOK);
354 xfer->rqflags &= ~URQ_AUTO_BUF;
355 }
356 }
357
358 if (!(xfer->flags & USBD_SYNCHRONOUS))
359 return (xfer->done ? 0 : USBD_IN_PROGRESS);
360
361 /* Sync transfer, wait for completion. */
362 s = splusb();
363 while (!xfer->done) {
364 if (pipe->device->bus->use_polling)
365 panic("usbd_transfer: not done");
366 tsleep(xfer, PRIBIO, "usbsyn", 0);
367 }
368 splx(s);
369 return (xfer->status);
370 }
371
372 /* Like usbd_transfer(), but waits for completion. */
373 usbd_status
374 usbd_sync_transfer(usbd_xfer_handle xfer)
375 {
376 xfer->flags |= USBD_SYNCHRONOUS;
377 return (usbd_transfer(xfer));
378 }
379
380 void *
381 usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size)
382 {
383 struct usbd_bus *bus = xfer->device->bus;
384 usbd_status err;
385
386 USB_KASSERT2((xfer->rqflags & URQ_MASK_BUF) == 0,
387 ("usbd_alloc_buffer: xfer already has a buffer"));
388
389 #ifdef DIAGNOSTIC
390 if (xfer->device->bus->intr_context)
391 panic("usbd_alloc_buffer: allocm not in process context");
392 #endif
393 err = bus->methods->allocm(bus, xfer, NULL, size);
394 if (err)
395 return (NULL);
396 xfer->bufsize = size;
397 xfer->rqflags |= URQ_DEV_BUF;
398 return xfer->hcbuffer;
399 }
400
401 Static void
402 usbd_free_buffer_flag(usbd_xfer_handle xfer, enum usbd_waitflg waitflg)
403 {
404 struct usbd_bus *bus;
405
406 USB_KASSERT2((xfer->rqflags & URQ_MASK_BUF) == URQ_DEV_BUF,
407 ("usbd_free_buffer_flag: no/auto buffer"));
408
409 xfer->rqflags &= ~(URQ_DEV_BUF | URQ_AUTO_BUF);
410 xfer->bufsize = 0;
411 bus = xfer->device->bus;
412 #ifdef DIAGNOSTIC
413 if (waitflg == U_WAITOK && bus->intr_context)
414 panic("usbd_free_buffer: freem not in process context");
415 #endif
416 bus->methods->freem(bus, xfer, waitflg);
417
418 xfer->hcbuffer = NULL;
419 }
420
421 void
422 usbd_free_buffer(usbd_xfer_handle xfer)
423 {
424 usbd_free_buffer_flag(xfer, U_WAITOK);
425 }
426
427 void *
428 usbd_get_buffer(usbd_xfer_handle xfer)
429 {
430 if (!(xfer->rqflags & URQ_DEV_BUF))
431 return (NULL);
432 return (xfer->hcbuffer);
433 }
434
435 /*
436 * map buffer handlings
437 */
438
439 /* Allocate mapping resources to prepare buffer mapping. */
440 usbd_status
441 usbd_map_alloc(usbd_xfer_handle xfer)
442 {
443 struct usbd_bus *bus = xfer->device->bus;
444 usbd_status err;
445
446 #ifdef DIAGNOSTIC
447 if (bus->intr_context)
448 panic("usbd_map_alloc: map_alloc not in process context");
449 #endif
450 USB_KASSERT2((xfer->rqflags & URQ_DEV_MAP_PREPARED) == 0,
451 ("usbd_map_alloc: map already allocated"));
452
453 err = bus->methods->map_alloc(xfer);
454 if (err != USBD_NORMAL_COMPLETION)
455 return (err);
456
457 xfer->rqflags |= URQ_DEV_MAP_PREPARED;
458
459 return (USBD_NORMAL_COMPLETION);
460 }
461
462 /* Free mapping resources. */
463 void
464 usbd_map_free(usbd_xfer_handle xfer)
465 {
466 struct usbd_bus *bus = xfer->device->bus;
467
468 #ifdef DIAGNOSTIC
469 if (bus->intr_context)
470 panic("usbd_map_free: map_free not in process context");
471 #endif
472 USB_KASSERT2((xfer->rqflags & URQ_DEV_MAP_PREPARED),
473 ("usbd_map_free: map not allocated"));
474
475 bus->methods->map_free(xfer);
476
477 xfer->rqflags &= ~URQ_DEV_MAP_PREPARED;
478 }
479
480 /* Map plain buffer. */
481 void
482 usbd_map_buffer(usbd_xfer_handle xfer, void *buf, u_int32_t size)
483 {
484 struct usbd_bus *bus = xfer->device->bus;
485
486 #ifdef DIAGNOSTIC
487 if ((xfer->rqflags & URQ_MASK_BUF))
488 panic("usbd_map_buffer: already has buffer (rqflags=%x)",
489 xfer->rqflags);
490 if ((xfer->rqflags & URQ_DEV_MAP_PREPARED) == 0 && bus->intr_context)
491 panic("usbd_map_buffer: mapm (without map_alloc) not in process context");
492 #endif
493
494 bus->methods->mapm(xfer, buf, size);
495
496 xfer->bufsize = size;
497 xfer->rqflags |= URQ_DEV_MAP_BUFFER;
498 }
499
500 /* Map mbuf(9) chain. */
501 usbd_status
502 usbd_map_buffer_mbuf(usbd_xfer_handle xfer, struct mbuf *chain)
503 {
504 struct usbd_bus *bus = xfer->device->bus;
505 usbd_status err;
506
507 #ifdef DIAGNOSTIC
508 if ((xfer->rqflags & URQ_MASK_BUF))
509 panic("usbd_map_buffer_mbuf: already has buffer (rqflags=%x)",
510 xfer->rqflags);
511 if ((xfer->rqflags & URQ_DEV_MAP_PREPARED) == 0 && bus->intr_context)
512 panic("usbd_map_buffer_mbuf: mapm_mbuf (without map_alloc) not in process context");
513 #endif
514
515 err = bus->methods->mapm_mbuf(xfer, chain);
516 if (err != USBD_NORMAL_COMPLETION)
517 return (err);
518
519 xfer->bufsize = chain->m_pkthdr.len;
520 xfer->rqflags |= URQ_DEV_MAP_MBUF;
521
522 return (err);
523 }
524
525 /* Unmap plain buffer or mbuf(9) chain. */
526 void
527 usbd_unmap_buffer(usbd_xfer_handle xfer)
528 {
529 struct usbd_bus *bus = xfer->device->bus;
530
531 USB_KASSERT2((xfer->rqflags & (URQ_DEV_MAP_BUFFER | URQ_DEV_MAP_MBUF)),
532 ("usbd_unmap_buffer: no map"));
533 #ifdef DIAGNOSTIC
534 if ((xfer->rqflags & URQ_DEV_MAP_PREPARED) == 0 && bus->intr_context)
535 panic("usbd_unmap_buffer: unmapm (without map_alloc) not in process context");
536 #endif
537
538 bus->methods->unmapm(xfer);
539
540 xfer->rqflags &= ~(URQ_DEV_MAP_BUFFER | URQ_DEV_MAP_MBUF);
541 xfer->bufsize = 0;
542 }
543
544 Static usbd_xfer_handle
545 usbd_alloc_xfer_flag(usbd_device_handle dev, usbd_pipe_handle pipe,
546 enum usbd_waitflg waitflg)
547 {
548 usbd_xfer_handle xfer;
549
550 #ifdef DIAGNOSTIC
551 if (waitflg == U_WAITOK && dev->bus->intr_context)
552 panic("usbd_alloc_xfer: allocx not in process context");
553 if (pipe == NULL)
554 panic("usbd_alloc_xfer: pipe == NULL");
555 #endif
556 xfer = dev->bus->methods->allocx(dev->bus, pipe, waitflg);
557 if (xfer == NULL)
558 return (NULL);
559 xfer->pipe = pipe;
560 xfer->device = dev;
561 usb_callout_init(xfer->timeout_handle);
562 DPRINTFN(5,("usbd_alloc_xfer_flag() = %p\n", xfer));
563 return (xfer);
564 }
565
566 usbd_xfer_handle
567 usbd_alloc_xfer(usbd_device_handle dev, usbd_pipe_handle pipe)
568 {
569 return (usbd_alloc_xfer_flag(dev, pipe, U_WAITOK));
570 }
571
572 usbd_xfer_handle
573 usbd_alloc_default_xfer(usbd_device_handle dev)
574 {
575 return (usbd_alloc_xfer_flag(dev, dev->default_pipe, U_WAITOK));
576 }
577
578 Static usbd_status
579 usbd_free_xfer_flag(usbd_xfer_handle xfer, enum usbd_waitflg waitflg)
580 {
581 DPRINTFN(5,("usbd_free_xfer_flag: %p %d\n", xfer, waitflg));
582 if (xfer->rqflags & (URQ_DEV_BUF | URQ_AUTO_BUF))
583 usbd_free_buffer_flag(xfer, waitflg);
584 if (xfer->rqflags & (URQ_DEV_MAP_BUFFER | URQ_DEV_MAP_MBUF))
585 usbd_unmap_buffer(xfer);
586 if (waitflg == U_WAITOK && (xfer->rqflags & URQ_DEV_MAP_PREPARED))
587 usbd_map_free(xfer);
588 #if defined(__NetBSD__) && defined(DIAGNOSTIC)
589 if (callout_pending(&xfer->timeout_handle)) {
590 callout_stop(&xfer->timeout_handle);
591 printf("usbd_free_xfer_flag: timout_handle pending");
592 }
593 #endif
594 xfer->device->bus->methods->freex(xfer->device->bus, xfer);
595 return (USBD_NORMAL_COMPLETION);
596 }
597
598 usbd_status
599 usbd_free_xfer(usbd_xfer_handle xfer)
600 {
601
602 return (usbd_free_xfer_flag(xfer, U_WAITOK));
603 }
604
605 void
606 usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
607 usbd_private_handle priv, void *buffer, u_int32_t length,
608 u_int16_t flags, u_int32_t timeout,
609 usbd_callback callback)
610 {
611 USB_KASSERT(xfer->pipe == pipe); /* XXX pipe arg should go */
612 xfer->priv = priv;
613 xfer->buffer = buffer;
614 xfer->length = length;
615 xfer->actlen = 0;
616 xfer->flags = flags;
617 xfer->timeout = timeout;
618 xfer->status = USBD_NOT_STARTED;
619 xfer->callback = callback;
620 xfer->rqflags &= ~URQ_REQUEST;
621 xfer->nframes = 0;
622 }
623
624 void
625 usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev,
626 usbd_private_handle priv, u_int32_t timeout,
627 usb_device_request_t *req, void *buffer,
628 u_int32_t length, u_int16_t flags,
629 usbd_callback callback)
630 {
631 USB_KASSERT(xfer->pipe == dev->default_pipe); /* XXX */
632 xfer->priv = priv;
633 xfer->buffer = buffer;
634 xfer->length = length;
635 xfer->actlen = 0;
636 xfer->flags = flags;
637 xfer->timeout = timeout;
638 xfer->status = USBD_NOT_STARTED;
639 xfer->callback = callback;
640 xfer->request = *req;
641 xfer->rqflags |= URQ_REQUEST;
642 xfer->nframes = 0;
643 }
644
645 void
646 usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe,
647 usbd_private_handle priv, u_int16_t *frlengths,
648 u_int32_t nframes, u_int16_t flags, usbd_callback callback)
649 {
650 int i;
651
652 USB_KASSERT(xfer->pipe == pipe); /* XXX pipe arg should go */
653 xfer->priv = priv;
654 xfer->buffer = 0;
655 xfer->length = 0;
656 for (i = 0; i < nframes; i++)
657 xfer->length += frlengths[i];
658 xfer->actlen = 0;
659 xfer->flags = flags;
660 xfer->timeout = USBD_NO_TIMEOUT;
661 xfer->status = USBD_NOT_STARTED;
662 xfer->callback = callback;
663 xfer->rqflags &= ~URQ_REQUEST;
664 xfer->frlengths = frlengths;
665 xfer->nframes = nframes;
666 }
667
668 void
669 usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv,
670 void **buffer, u_int32_t *count, usbd_status *status)
671 {
672 if (priv != NULL)
673 *priv = xfer->priv;
674 if (buffer != NULL)
675 *buffer = xfer->buffer;
676 if (count != NULL)
677 *count = xfer->actlen;
678 if (status != NULL)
679 *status = xfer->status;
680 }
681
682 usb_config_descriptor_t *
683 usbd_get_config_descriptor(usbd_device_handle dev)
684 {
685 #ifdef DIAGNOSTIC
686 if (dev == NULL) {
687 printf("usbd_get_config_descriptor: dev == NULL\n");
688 return (NULL);
689 }
690 #endif
691 return (dev->cdesc);
692 }
693
694 int
695 usbd_get_speed(usbd_device_handle dev)
696 {
697 return (dev->speed);
698 }
699
700 usb_interface_descriptor_t *
701 usbd_get_interface_descriptor(usbd_interface_handle iface)
702 {
703 #ifdef DIAGNOSTIC
704 if (iface == NULL) {
705 printf("usbd_get_interface_descriptor: dev == NULL\n");
706 return (NULL);
707 }
708 #endif
709 return (iface->idesc);
710 }
711
712 usb_device_descriptor_t *
713 usbd_get_device_descriptor(usbd_device_handle dev)
714 {
715 return (&dev->ddesc);
716 }
717
718 usb_endpoint_descriptor_t *
719 usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index)
720 {
721 if (index >= iface->idesc->bNumEndpoints)
722 return (0);
723 return (iface->endpoints[index].edesc);
724 }
725
726 usbd_status
727 usbd_abort_pipe(usbd_pipe_handle pipe)
728 {
729 usbd_status err;
730 int s;
731
732 #ifdef DIAGNOSTIC
733 if (pipe == NULL) {
734 printf("usbd_close_pipe: pipe==NULL\n");
735 return (USBD_NORMAL_COMPLETION);
736 }
737 #endif
738 s = splusb();
739 err = usbd_ar_pipe(pipe);
740 splx(s);
741 return (err);
742 }
743
744 usbd_status
745 usbd_abort_default_pipe(usbd_device_handle dev)
746 {
747 return (usbd_abort_pipe(dev->default_pipe));
748 }
749
750 usbd_status
751 usbd_clear_endpoint_stall(usbd_pipe_handle pipe)
752 {
753 usbd_device_handle dev = pipe->device;
754 usb_device_request_t req;
755 usbd_status err;
756
757 DPRINTFN(8, ("usbd_clear_endpoint_stall\n"));
758
759 /*
760 * Clearing en endpoint stall resets the endpoint toggle, so
761 * do the same to the HC toggle.
762 */
763 pipe->methods->cleartoggle(pipe);
764
765 req.bmRequestType = UT_WRITE_ENDPOINT;
766 req.bRequest = UR_CLEAR_FEATURE;
767 USETW(req.wValue, UF_ENDPOINT_HALT);
768 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
769 USETW(req.wLength, 0);
770 err = usbd_do_request(dev, &req, 0);
771 #if 0
772 XXX should we do this?
773 if (!err) {
774 pipe->state = USBD_PIPE_ACTIVE;
775 /* XXX activate pipe */
776 }
777 #endif
778 return (err);
779 }
780
781 usbd_status
782 usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe)
783 {
784 usbd_device_handle dev = pipe->device;
785 usb_device_request_t req;
786 usbd_status err;
787
788 pipe->methods->cleartoggle(pipe);
789
790 req.bmRequestType = UT_WRITE_ENDPOINT;
791 req.bRequest = UR_CLEAR_FEATURE;
792 USETW(req.wValue, UF_ENDPOINT_HALT);
793 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress);
794 USETW(req.wLength, 0);
795 err = usbd_do_request_async(dev, &req, 0);
796 return (err);
797 }
798
799 void
800 usbd_clear_endpoint_toggle(usbd_pipe_handle pipe)
801 {
802 pipe->methods->cleartoggle(pipe);
803 }
804
805 usbd_status
806 usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count)
807 {
808 #ifdef DIAGNOSTIC
809 if (iface == NULL || iface->idesc == NULL) {
810 printf("usbd_endpoint_count: NULL pointer\n");
811 return (USBD_INVAL);
812 }
813 #endif
814 *count = iface->idesc->bNumEndpoints;
815 return (USBD_NORMAL_COMPLETION);
816 }
817
818 usbd_status
819 usbd_interface_count(usbd_device_handle dev, u_int8_t *count)
820 {
821 if (dev->cdesc == NULL)
822 return (USBD_NOT_CONFIGURED);
823 *count = dev->cdesc->bNumInterface;
824 return (USBD_NORMAL_COMPLETION);
825 }
826
827 void
828 usbd_interface2device_handle(usbd_interface_handle iface,
829 usbd_device_handle *dev)
830 {
831 *dev = iface->device;
832 }
833
834 usbd_status
835 usbd_device2interface_handle(usbd_device_handle dev,
836 u_int8_t ifaceno, usbd_interface_handle *iface)
837 {
838 if (dev->cdesc == NULL)
839 return (USBD_NOT_CONFIGURED);
840 if (ifaceno >= dev->cdesc->bNumInterface)
841 return (USBD_INVAL);
842 *iface = &dev->ifaces[ifaceno];
843 return (USBD_NORMAL_COMPLETION);
844 }
845
846 usbd_device_handle
847 usbd_pipe2device_handle(usbd_pipe_handle pipe)
848 {
849 return (pipe->device);
850 }
851
852 /* XXXX use altno */
853 usbd_status
854 usbd_set_interface(usbd_interface_handle iface, int altidx)
855 {
856 usb_device_request_t req;
857 usbd_status err;
858 void *endpoints;
859
860 if (LIST_FIRST(&iface->pipes) != 0)
861 return (USBD_IN_USE);
862
863 endpoints = iface->endpoints;
864 err = usbd_fill_iface_data(iface->device, iface->index, altidx);
865 if (err)
866 return (err);
867
868 /* new setting works, we can free old endpoints */
869 if (endpoints != NULL)
870 free(endpoints, M_USB);
871
872 #ifdef DIAGNOSTIC
873 if (iface->idesc == NULL) {
874 printf("usbd_set_interface: NULL pointer\n");
875 return (USBD_INVAL);
876 }
877 #endif
878
879 req.bmRequestType = UT_WRITE_INTERFACE;
880 req.bRequest = UR_SET_INTERFACE;
881 USETW(req.wValue, iface->idesc->bAlternateSetting);
882 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
883 USETW(req.wLength, 0);
884 return (usbd_do_request(iface->device, &req, 0));
885 }
886
887 int
888 usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno)
889 {
890 char *p = (char *)cdesc;
891 char *end = p + UGETW(cdesc->wTotalLength);
892 usb_interface_descriptor_t *d;
893 int n;
894
895 for (n = 0; p < end; p += d->bLength) {
896 d = (usb_interface_descriptor_t *)p;
897 if (p + d->bLength <= end &&
898 d->bDescriptorType == UDESC_INTERFACE &&
899 d->bInterfaceNumber == ifaceno)
900 n++;
901 }
902 return (n);
903 }
904
905 int
906 usbd_get_interface_altindex(usbd_interface_handle iface)
907 {
908 return (iface->altindex);
909 }
910
911 usbd_status
912 usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface)
913 {
914 usb_device_request_t req;
915
916 req.bmRequestType = UT_READ_INTERFACE;
917 req.bRequest = UR_GET_INTERFACE;
918 USETW(req.wValue, 0);
919 USETW(req.wIndex, iface->idesc->bInterfaceNumber);
920 USETW(req.wLength, 1);
921 return (usbd_do_request(iface->device, &req, aiface));
922 }
923
924 /*** Internal routines ***/
925
926 /* Dequeue all pipe operations, called at splusb(). */
927 Static usbd_status
928 usbd_ar_pipe(usbd_pipe_handle pipe)
929 {
930 usbd_xfer_handle xfer;
931
932 SPLUSBCHECK;
933
934 DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe));
935 #ifdef USB_DEBUG
936 if (usbdebug > 5)
937 usbd_dump_queue(pipe);
938 #endif
939 pipe->repeat = 0;
940 pipe->aborting = 1;
941 while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
942 DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n",
943 pipe, xfer, pipe->methods));
944 /* Make the HC abort it (and invoke the callback). */
945 pipe->methods->abort(xfer);
946 USB_KASSERT2(SIMPLEQ_FIRST(&pipe->queue) != xfer,
947 ("usbd_ar_pipe"));
948 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */
949 }
950 pipe->aborting = 0;
951 return (USBD_NORMAL_COMPLETION);
952 }
953
954 /* Called at splusb() */
955 void
956 usb_transfer_complete(usbd_xfer_handle xfer)
957 {
958 usbd_pipe_handle pipe = xfer->pipe;
959 int sync = xfer->flags & USBD_SYNCHRONOUS;
960 int erred = xfer->status == USBD_CANCELLED ||
961 xfer->status == USBD_TIMEOUT;
962 int repeat, polling;
963
964 SPLUSBCHECK;
965
966 DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d "
967 "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen));
968 #ifdef DIAGNOSTIC
969 if (xfer->busy_free != XFER_ONQU) {
970 printf("usb_transfer_complete: xfer=%p not busy 0x%08x\n",
971 xfer, xfer->busy_free);
972 }
973 #endif
974
975 #ifdef DIAGNOSTIC
976 if (pipe == NULL) {
977 printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer);
978 return;
979 }
980 #endif
981 repeat = pipe->repeat;
982 polling = pipe->device->bus->use_polling;
983 /* XXXX */
984 if (polling)
985 pipe->running = 0;
986
987 if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 &&
988 usbd_xfer_isread(xfer)) {
989 #ifdef DIAGNOSTIC
990 if (xfer->actlen > xfer->length) {
991 printf("usb_transfer_complete: actlen > len %d > %d\n",
992 xfer->actlen, xfer->length);
993 xfer->actlen = xfer->length;
994 }
995 #endif
996 /* Copy data if it is not already in the correct buffer. */
997 if (!(xfer->flags & USBD_NO_COPY) && xfer->hcbuffer != NULL) {
998 DPRINTFN(5, ("usb_transfer_complete: copy %p (buffer) <- %p (alloc), %u bytes\n",
999 xfer->buffer, xfer->hcbuffer, (unsigned)xfer->actlen));
1000 #ifdef DIAGNOSTIC
1001 if ((xfer->rqflags & (URQ_AUTO_BUF | URQ_DEV_BUF)) == 0)
1002 panic("usbd_transfer: USBD_NO_COPY required with mapped buffer");
1003 #endif
1004 memcpy(xfer->buffer, xfer->hcbuffer, xfer->actlen);
1005 }
1006 }
1007
1008 /*
1009 * if we allocated or mapped the buffer in usbd_transfer()
1010 * we unmap it here.
1011 */
1012 if (xfer->rqflags & URQ_AUTO_BUF) {
1013 if (!repeat) {
1014 struct usbd_bus *bus = pipe->device->bus;
1015 bus->methods->freem(bus, xfer, U_NOWAIT);
1016 xfer->rqflags &= ~URQ_AUTO_BUF;
1017 }
1018 }
1019
1020 if (!repeat) {
1021 /* Remove request from queue. */
1022 #ifdef DIAGNOSTIC
1023 xfer->busy_free = XFER_BUSY;
1024 #endif
1025 USB_KASSERT2(SIMPLEQ_FIRST(&pipe->queue) == xfer,
1026 ("usb_transfer_complete: bad dequeue"));
1027 SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
1028 }
1029 DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n",
1030 repeat, SIMPLEQ_FIRST(&pipe->queue)));
1031
1032 /* Count completed transfers. */
1033 ++pipe->device->bus->stats.uds_requests
1034 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE];
1035
1036 xfer->done = 1;
1037 if (!xfer->status && xfer->actlen < xfer->length &&
1038 !(xfer->flags & USBD_SHORT_XFER_OK)) {
1039 DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n",
1040 xfer->actlen, xfer->length));
1041 xfer->status = USBD_SHORT_XFER;
1042 }
1043
1044 /*
1045 * For repeat operations, call the callback first, as the xfer
1046 * will not go away and the "done" method may modify it. Otherwise
1047 * reverse the order in case the callback wants to free or reuse
1048 * the xfer.
1049 */
1050 if (repeat) {
1051 if (xfer->callback)
1052 xfer->callback(xfer, xfer->priv, xfer->status);
1053 pipe->methods->done(xfer);
1054 } else {
1055 pipe->methods->done(xfer);
1056 if (xfer->callback)
1057 xfer->callback(xfer, xfer->priv, xfer->status);
1058 }
1059
1060 if (sync && !polling)
1061 wakeup(xfer);
1062
1063 if (!repeat) {
1064 /* XXX should we stop the queue on all errors? */
1065 if (erred && pipe->iface != NULL) /* not control pipe */
1066 pipe->running = 0;
1067 else
1068 usbd_start_next(pipe);
1069 }
1070 }
1071
1072 usbd_status
1073 usb_insert_transfer(usbd_xfer_handle xfer)
1074 {
1075 usbd_pipe_handle pipe = xfer->pipe;
1076 usbd_status err;
1077 int s;
1078
1079 DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n",
1080 pipe, pipe->running, xfer->timeout));
1081 #ifdef DIAGNOSTIC
1082 if (xfer->busy_free != XFER_BUSY) {
1083 printf("usb_insert_transfer: xfer=%p not busy 0x%08x\n",
1084 xfer, xfer->busy_free);
1085 return (USBD_INVAL);
1086 }
1087 xfer->busy_free = XFER_ONQU;
1088 #endif
1089 s = splusb();
1090 USB_KASSERT2(SIMPLEQ_FIRST(&pipe->queue) != xfer,
1091 ("usb_insert_transfer"));
1092 SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
1093 if (pipe->running)
1094 err = USBD_IN_PROGRESS;
1095 else {
1096 pipe->running = 1;
1097 err = USBD_NORMAL_COMPLETION;
1098 }
1099 splx(s);
1100 return (err);
1101 }
1102
1103 /* Called at splusb() */
1104 void
1105 usbd_start_next(usbd_pipe_handle pipe)
1106 {
1107 usbd_xfer_handle xfer;
1108 usbd_status err;
1109
1110 SPLUSBCHECK;
1111
1112 #ifdef DIAGNOSTIC
1113 if (pipe == NULL) {
1114 printf("usbd_start_next: pipe == NULL\n");
1115 return;
1116 }
1117 if (pipe->methods == NULL || pipe->methods->start == NULL) {
1118 printf("usbd_start_next: pipe=%p no start method\n", pipe);
1119 return;
1120 }
1121 #endif
1122
1123 /* Get next request in queue. */
1124 xfer = SIMPLEQ_FIRST(&pipe->queue);
1125 DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer));
1126 if (xfer == NULL) {
1127 pipe->running = 0;
1128 } else {
1129 err = pipe->methods->start(xfer);
1130 if (err != USBD_IN_PROGRESS) {
1131 printf("usbd_start_next: error=%d\n", err);
1132 pipe->running = 0;
1133 /* XXX do what? */
1134 }
1135 }
1136 }
1137
1138 usbd_status
1139 usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data)
1140 {
1141 return (usbd_do_request_flags(dev, req, data, 0, 0,
1142 USBD_DEFAULT_TIMEOUT));
1143 }
1144
1145 usbd_status
1146 usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req,
1147 void *data, u_int16_t flags, int *actlen, u_int32_t timo)
1148 {
1149 return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req,
1150 data, flags, actlen, timo));
1151 }
1152
1153 usbd_status
1154 usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe,
1155 usb_device_request_t *req, void *data, u_int16_t flags, int *actlen,
1156 u_int32_t timeout)
1157 {
1158 usbd_xfer_handle xfer;
1159 usbd_status err;
1160
1161 #ifdef DIAGNOSTIC
1162 #if defined(__i386__) && defined(__FreeBSD__)
1163 KASSERT(curthread->td_intr_nesting_level == 0,
1164 ("usbd_do_request: in interrupt context"));
1165 #endif
1166 if (dev->bus->intr_context) {
1167 panic("usbd_do_request: not in process context");
1168 }
1169 #endif
1170
1171 xfer = usbd_alloc_xfer(dev, pipe);
1172 if (xfer == NULL)
1173 return (USBD_NOMEM);
1174 xfer->pipe = dev->default_pipe; /* XXX */
1175 /* XXX */
1176 usbd_setup_default_xfer(xfer, dev, 0, timeout, req,
1177 data, UGETW(req->wLength), flags, 0);
1178 /* XXX */
1179 xfer->pipe = pipe;
1180 err = usbd_sync_transfer(xfer);
1181 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1182 if (xfer->actlen > xfer->length) {
1183 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
1184 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
1185 dev->address, xfer->request.bmRequestType,
1186 xfer->request.bRequest, UGETW(xfer->request.wValue),
1187 UGETW(xfer->request.wIndex),
1188 UGETW(xfer->request.wLength),
1189 xfer->length, xfer->actlen));
1190 }
1191 #endif
1192 if (actlen != NULL)
1193 *actlen = xfer->actlen;
1194 if (err == USBD_STALLED) {
1195 /*
1196 * The control endpoint has stalled. Control endpoints
1197 * should not halt, but some may do so anyway so clear
1198 * any halt condition.
1199 */
1200 usb_device_request_t treq;
1201 usb_status_t status;
1202 u_int16_t s;
1203 usbd_status nerr;
1204
1205 treq.bmRequestType = UT_READ_ENDPOINT;
1206 treq.bRequest = UR_GET_STATUS;
1207 USETW(treq.wValue, 0);
1208 USETW(treq.wIndex, 0);
1209 USETW(treq.wLength, sizeof(usb_status_t));
1210 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
1211 &treq, &status,sizeof(usb_status_t),
1212 0, 0);
1213 nerr = usbd_sync_transfer(xfer);
1214 if (nerr)
1215 goto bad;
1216 s = UGETW(status.wStatus);
1217 DPRINTF(("usbd_do_request: status = 0x%04x\n", s));
1218 if (!(s & UES_HALT))
1219 goto bad;
1220 treq.bmRequestType = UT_WRITE_ENDPOINT;
1221 treq.bRequest = UR_CLEAR_FEATURE;
1222 USETW(treq.wValue, UF_ENDPOINT_HALT);
1223 USETW(treq.wIndex, 0);
1224 USETW(treq.wLength, 0);
1225 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT,
1226 &treq, &status, 0, 0, 0);
1227 nerr = usbd_sync_transfer(xfer);
1228 if (nerr)
1229 goto bad;
1230 }
1231
1232 bad:
1233 usbd_free_xfer(xfer);
1234 return (err);
1235 }
1236
1237 void
1238 usbd_do_request_async_cb(usbd_xfer_handle xfer,
1239 usbd_private_handle priv, usbd_status status)
1240 {
1241 #if defined(USB_DEBUG) || defined(DIAGNOSTIC)
1242 if (xfer->actlen > xfer->length) {
1243 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x"
1244 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n",
1245 xfer->pipe->device->address,
1246 xfer->request.bmRequestType,
1247 xfer->request.bRequest, UGETW(xfer->request.wValue),
1248 UGETW(xfer->request.wIndex),
1249 UGETW(xfer->request.wLength),
1250 xfer->length, xfer->actlen));
1251 }
1252 #endif
1253 usbd_free_xfer_flag(xfer, U_NOWAIT);
1254 }
1255
1256 /*
1257 * Execute a request without waiting for completion.
1258 * Can be used from interrupt context.
1259 */
1260 usbd_status
1261 usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req,
1262 void *data)
1263 {
1264 usbd_xfer_handle xfer;
1265
1266 xfer = usbd_alloc_xfer_flag(dev, dev->default_pipe, U_NOWAIT);
1267 if (xfer == NULL)
1268 return (USBD_NOMEM);
1269 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req,
1270 data, UGETW(req->wLength), 0, usbd_do_request_async_cb);
1271
1272 /*
1273 * Request will be processed later as a task (in thread context).
1274 */
1275 usb_init_task(&xfer->async_task, usbd_do_request_async_task, xfer);
1276 usb_add_task(dev, &xfer->async_task, USB_TASKQ_HC);
1277
1278 return (USBD_IN_PROGRESS);
1279 }
1280
1281 Static void
1282 usbd_do_request_async_task(void *arg)
1283 {
1284 usbd_xfer_handle xfer = arg;
1285 usbd_status err;
1286
1287 /* XXX impossible to notify caller the error */
1288 err = usbd_transfer(xfer);
1289 if (err != USBD_IN_PROGRESS && err) {
1290 usbd_free_xfer(xfer);
1291 }
1292 }
1293
1294 const struct usbd_quirks *
1295 usbd_get_quirks(usbd_device_handle dev)
1296 {
1297 #ifdef DIAGNOSTIC
1298 if (dev == NULL) {
1299 printf("usbd_get_quirks: dev == NULL\n");
1300 return 0;
1301 }
1302 #endif
1303 return (dev->quirks);
1304 }
1305
1306 /* XXX do periodic free() of free list */
1307
1308 /*
1309 * Called from keyboard driver when in polling mode.
1310 */
1311 void
1312 usbd_dopoll(usbd_interface_handle iface)
1313 {
1314 iface->device->bus->methods->do_poll(iface->device->bus);
1315 }
1316
1317 void
1318 usbd_set_polling(usbd_device_handle dev, int on)
1319 {
1320 if (on)
1321 dev->bus->use_polling++;
1322 else
1323 dev->bus->use_polling--;
1324 /* When polling we need to make sure there is nothing pending to do. */
1325 if (dev->bus->use_polling)
1326 dev->bus->methods->soft_intr(dev->bus);
1327 }
1328
1329
1330 usb_endpoint_descriptor_t *
1331 usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address)
1332 {
1333 struct usbd_endpoint *ep;
1334 int i;
1335
1336 for (i = 0; i < iface->idesc->bNumEndpoints; i++) {
1337 ep = &iface->endpoints[i];
1338 if (ep->edesc->bEndpointAddress == address)
1339 return (iface->endpoints[i].edesc);
1340 }
1341 return (0);
1342 }
1343
1344 /*
1345 * usbd_ratecheck() can limit the number of error messages that occurs.
1346 * When a device is unplugged it may take up to 0.25s for the hub driver
1347 * to notice it. If the driver continuosly tries to do I/O operations
1348 * this can generate a large number of messages.
1349 */
1350 int
1351 usbd_ratecheck(struct timeval *last)
1352 {
1353 #if defined(__NetBSD__)
1354 static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/
1355
1356 return (ratecheck(last, &errinterval));
1357 #elif defined(__FreeBSD__)
1358 if (last->tv_sec == time_second)
1359 return (0);
1360 last->tv_sec = time_second;
1361 return (1);
1362 #endif
1363 }
1364
1365 /*
1366 * Search for a vendor/product pair in an array. The item size is
1367 * given as an argument.
1368 */
1369 const struct usb_devno *
1370 usb_match_device(const struct usb_devno *tbl, u_int nentries, u_int sz,
1371 u_int16_t vendor, u_int16_t product)
1372 {
1373 while (nentries-- > 0) {
1374 u_int16_t tproduct = tbl->ud_product;
1375 if (tbl->ud_vendor == vendor &&
1376 (tproduct == product || tproduct == USB_PRODUCT_ANY))
1377 return (tbl);
1378 tbl = (const struct usb_devno *)((const char *)tbl + sz);
1379 }
1380 return (NULL);
1381 }
1382
1383
1384 void
1385 usb_desc_iter_init(usbd_device_handle dev, usbd_desc_iter_t *iter)
1386 {
1387 const usb_config_descriptor_t *cd = usbd_get_config_descriptor(dev);
1388
1389 iter->cur = (const uByte *)cd;
1390 iter->end = (const uByte *)cd + UGETW(cd->wTotalLength);
1391 }
1392
1393 const usb_descriptor_t *
1394 usb_desc_iter_next(usbd_desc_iter_t *iter)
1395 {
1396 const usb_descriptor_t *desc;
1397
1398 if (iter->cur + sizeof(usb_descriptor_t) >= iter->end) {
1399 if (iter->cur != iter->end)
1400 printf("usb_desc_iter_next: bad descriptor\n");
1401 return NULL;
1402 }
1403 desc = (const usb_descriptor_t *)iter->cur;
1404 if (desc->bLength == 0) {
1405 printf("usb_desc_iter_next: descriptor length = 0\n");
1406 return NULL;
1407 }
1408 iter->cur += desc->bLength;
1409 if (iter->cur > iter->end) {
1410 printf("usb_desc_iter_next: descriptor length too large\n");
1411 return NULL;
1412 }
1413 return desc;
1414 }
1415
1416 usbd_status
1417 usbd_get_string(usbd_device_handle dev, int si, char *buf)
1418 {
1419 return usbd_get_string0(dev, si, buf, 1);
1420 }
1421
1422 usbd_status
1423 usbd_get_string0(usbd_device_handle dev, int si, char *buf, int unicode)
1424 {
1425 int swap = dev->quirks->uq_flags & UQ_SWAP_UNICODE;
1426 usb_string_descriptor_t us;
1427 char *s;
1428 int i, n;
1429 u_int16_t c;
1430 usbd_status err;
1431 int size;
1432
1433 buf[0] = '\0';
1434 if (si == 0)
1435 return (USBD_INVAL);
1436 if (dev->quirks->uq_flags & UQ_NO_STRINGS)
1437 return (USBD_STALLED);
1438 if (dev->langid == USBD_NOLANG) {
1439 /* Set up default language */
1440 err = usbd_get_string_desc(dev, USB_LANGUAGE_TABLE, 0, &us,
1441 &size);
1442 if (err || size < 4) {
1443 DPRINTFN(-1,("usbd_get_string: getting lang failed, using 0\n"));
1444 dev->langid = 0; /* Well, just pick something then */
1445 } else {
1446 /* Pick the first language as the default. */
1447 dev->langid = UGETW(us.bString[0]);
1448 }
1449 }
1450 err = usbd_get_string_desc(dev, si, dev->langid, &us, &size);
1451 if (err)
1452 return (err);
1453 s = buf;
1454 n = size / 2 - 1;
1455 if (unicode) {
1456 for (i = 0; i < n; i++) {
1457 c = UGETW(us.bString[i]);
1458 if (swap)
1459 c = (c >> 8) | (c << 8);
1460 s += wput_utf8(s, 3, c);
1461 }
1462 *s++ = 0;
1463 }
1464 #if defined(__NetBSD__) && defined(COMPAT_30)
1465 else {
1466 for (i = 0; i < n; i++) {
1467 c = UGETW(us.bString[i]);
1468 if (swap)
1469 c = (c >> 8) | (c << 8);
1470 *s++ = (c < 0x80) ? c : '?';
1471 }
1472 *s++ = 0;
1473 }
1474 #endif
1475 return (USBD_NORMAL_COMPLETION);
1476 }
1477
1478 #if defined(__FreeBSD__)
1479 int
1480 usbd_driver_load(module_t mod, int what, void *arg)
1481 {
1482 /* XXX should implement something like a function that removes all generic devices */
1483
1484 return (0);
1485 }
1486
1487 #endif
1488