1 /* $OpenBSD: usbdi.c,v 1.14 2001/05/03 02:20:34 aaron Exp $ */ 2 /* $NetBSD: usbdi.c,v 1.81 2001/04/17 00:05:33 augustss Exp $ */ 3 /* $FreeBSD: src/sys/dev/usb/usbdi.c,v 1.28 1999/11/17 22:33:49 n_hibma Exp $ */ 4 5 /* 6 * Copyright (c) 1998 The NetBSD Foundation, Inc. 7 * All rights reserved. 8 * 9 * This code is derived from software contributed to The NetBSD Foundation 10 * by Lennart Augustsson (lennart@augustsson.net) at 11 * Carlstedt Research & Technology. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the NetBSD 24 * Foundation, Inc. and its contributors. 25 * 4. Neither the name of The NetBSD Foundation nor the names of its 26 * contributors may be used to endorse or promote products derived 27 * from this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 30 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 31 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 32 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 33 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 34 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 35 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 36 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 37 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 38 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 39 * POSSIBILITY OF SUCH DAMAGE. 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #if defined(__NetBSD__) || defined(__OpenBSD__) 45 #include <sys/kernel.h> 46 #include <sys/device.h> 47 #elif defined(__FreeBSD__) 48 #include <sys/module.h> 49 #include <sys/bus.h> 50 #include <sys/conf.h> 51 #include "usb_if.h" 52 #if defined(DIAGNOSTIC) && defined(__i386__) 53 #include <machine/cpu.h> 54 #endif 55 #endif 56 #include <sys/malloc.h> 57 #include <sys/proc.h> 58 59 #include <machine/bus.h> 60 61 #include <dev/usb/usb.h> 62 #include <dev/usb/usbdi.h> 63 #include <dev/usb/usbdi_util.h> 64 #include <dev/usb/usbdivar.h> 65 #include <dev/usb/usb_mem.h> 66 67 #if defined(__FreeBSD__) 68 #include "usb_if.h" 69 #endif 70 71 #ifdef USB_DEBUG 72 #define DPRINTF(x) if (usbdebug) logprintf x 73 #define DPRINTFN(n,x) if (usbdebug>(n)) logprintf x 74 extern int usbdebug; 75 #else 76 #define DPRINTF(x) 77 #define DPRINTFN(n,x) 78 #endif 79 80 Static usbd_status usbd_ar_pipe(usbd_pipe_handle pipe); 81 Static void usbd_do_request_async_cb 82 (usbd_xfer_handle, usbd_private_handle, usbd_status); 83 Static void usbd_start_next(usbd_pipe_handle pipe); 84 Static usbd_status usbd_open_pipe_ival 85 (usbd_interface_handle, u_int8_t, u_int8_t, usbd_pipe_handle *, int); 86 87 Static int usbd_nbuses = 0; 88 89 void 90 usbd_init(void) 91 { 92 usbd_nbuses++; 93 } 94 95 void 96 usbd_finish(void) 97 { 98 --usbd_nbuses; 99 } 100 101 static __inline int 102 usbd_xfer_isread(usbd_xfer_handle xfer) 103 { 104 if (xfer->rqflags & URQ_REQUEST) 105 return (xfer->request.bmRequestType & UT_READ); 106 else 107 return (xfer->pipe->endpoint->edesc->bEndpointAddress & 108 UE_DIR_IN); 109 } 110 111 #ifdef USB_DEBUG 112 void usbd_dump_queue(usbd_pipe_handle pipe); 113 void 114 usbd_dump_queue(usbd_pipe_handle pipe) 115 { 116 usbd_xfer_handle xfer; 117 118 printf("usbd_dump_queue: pipe=%p\n", pipe); 119 for (xfer = SIMPLEQ_FIRST(&pipe->queue); 120 xfer; 121 xfer = SIMPLEQ_NEXT(xfer, next)) { 122 printf(" xfer=%p\n", xfer); 123 } 124 } 125 #endif 126 127 usbd_status 128 usbd_open_pipe(usbd_interface_handle iface, u_int8_t address, 129 u_int8_t flags, usbd_pipe_handle *pipe) 130 { 131 return (usbd_open_pipe_ival(iface, address, flags, pipe, 132 USBD_DEFAULT_INTERVAL)); 133 } 134 135 usbd_status 136 usbd_open_pipe_ival(usbd_interface_handle iface, u_int8_t address, 137 u_int8_t flags, usbd_pipe_handle *pipe, int ival) 138 { 139 usbd_pipe_handle p; 140 struct usbd_endpoint *ep; 141 usbd_status err; 142 int i; 143 144 DPRINTFN(3,("usbd_open_pipe: iface=%p address=0x%x flags=0x%x\n", 145 iface, address, flags)); 146 147 for (i = 0; i < iface->idesc->bNumEndpoints; i++) { 148 ep = &iface->endpoints[i]; 149 if (ep->edesc == NULL) 150 return (USBD_IOERROR); 151 if (ep->edesc->bEndpointAddress == address) 152 goto found; 153 } 154 return (USBD_BAD_ADDRESS); 155 found: 156 if ((flags & USBD_EXCLUSIVE_USE) && ep->refcnt != 0) 157 return (USBD_IN_USE); 158 err = usbd_setup_pipe(iface->device, iface, ep, ival, &p); 159 if (err) 160 return (err); 161 LIST_INSERT_HEAD(&iface->pipes, p, next); 162 *pipe = p; 163 return (USBD_NORMAL_COMPLETION); 164 } 165 166 usbd_status 167 usbd_open_pipe_intr(usbd_interface_handle iface, u_int8_t address, 168 u_int8_t flags, usbd_pipe_handle *pipe, 169 usbd_private_handle priv, void *buffer, u_int32_t len, 170 usbd_callback cb, int ival) 171 { 172 usbd_status err; 173 usbd_xfer_handle xfer; 174 usbd_pipe_handle ipipe; 175 176 DPRINTFN(3,("usbd_open_pipe_intr: address=0x%x flags=0x%x len=%d\n", 177 address, flags, len)); 178 179 err = usbd_open_pipe_ival(iface, address, USBD_EXCLUSIVE_USE, 180 &ipipe, ival); 181 if (err) 182 return (err); 183 xfer = usbd_alloc_xfer(iface->device); 184 if (xfer == NULL) { 185 err = USBD_NOMEM; 186 goto bad1; 187 } 188 usbd_setup_xfer(xfer, ipipe, priv, buffer, len, flags, 189 USBD_NO_TIMEOUT, cb); 190 ipipe->intrxfer = xfer; 191 ipipe->repeat = 1; 192 err = usbd_transfer(xfer); 193 *pipe = ipipe; 194 if (err != USBD_IN_PROGRESS) 195 goto bad2; 196 return (USBD_NORMAL_COMPLETION); 197 198 bad2: 199 ipipe->intrxfer = NULL; 200 ipipe->repeat = 0; 201 usbd_free_xfer(xfer); 202 bad1: 203 usbd_close_pipe(ipipe); 204 return (err); 205 } 206 207 usbd_status 208 usbd_close_pipe(usbd_pipe_handle pipe) 209 { 210 #ifdef DIAGNOSTIC 211 if (pipe == NULL) { 212 printf("usbd_close_pipe: pipe==NULL\n"); 213 return (USBD_NORMAL_COMPLETION); 214 } 215 #endif 216 217 if (--pipe->refcnt != 0) 218 return (USBD_NORMAL_COMPLETION); 219 if (SIMPLEQ_FIRST(&pipe->queue) != 0) 220 return (USBD_PENDING_REQUESTS); 221 LIST_REMOVE(pipe, next); 222 pipe->endpoint->refcnt--; 223 pipe->methods->close(pipe); 224 #if defined(__NetBSD__) && defined(DIAGNOSTIC) 225 if (callout_pending(&pipe->abort_handle)) { 226 callout_stop(&pipe->abort_handle); 227 printf("usbd_close_pipe: abort_handle pending"); 228 } 229 #endif 230 if (pipe->intrxfer != NULL) 231 usbd_free_xfer(pipe->intrxfer); 232 free(pipe, M_USB); 233 return (USBD_NORMAL_COMPLETION); 234 } 235 236 usbd_status 237 usbd_transfer(usbd_xfer_handle xfer) 238 { 239 usbd_pipe_handle pipe = xfer->pipe; 240 usb_dma_t *dmap = &xfer->dmabuf; 241 usbd_status err; 242 u_int size; 243 int s; 244 245 DPRINTFN(5,("usbd_transfer: xfer=%p, flags=%d, pipe=%p, running=%d\n", 246 xfer, xfer->flags, pipe, pipe->running)); 247 #ifdef USB_DEBUG 248 if (usbdebug > 5) 249 usbd_dump_queue(pipe); 250 #endif 251 xfer->done = 0; 252 253 if (pipe->aborting) 254 return (USBD_CANCELLED); 255 256 size = xfer->length; 257 /* If there is no buffer, allocate one. */ 258 if (!(xfer->rqflags & URQ_DEV_DMABUF) && size != 0) { 259 struct usbd_bus *bus = pipe->device->bus; 260 261 #ifdef DIAGNOSTIC 262 if (xfer->rqflags & URQ_AUTO_DMABUF) 263 printf("usbd_transfer: has old buffer!\n"); 264 #endif 265 err = bus->methods->allocm(bus, dmap, size); 266 if (err) 267 return (err); 268 xfer->rqflags |= URQ_AUTO_DMABUF; 269 } 270 271 /* Copy data if going out. */ 272 if (!(xfer->flags & USBD_NO_COPY) && size != 0 && 273 !usbd_xfer_isread(xfer)) 274 memcpy(KERNADDR(dmap), xfer->buffer, size); 275 276 err = pipe->methods->transfer(xfer); 277 278 if (err != USBD_IN_PROGRESS && err) { 279 /* The transfer has not been queued, so free buffer. */ 280 if (xfer->rqflags & URQ_AUTO_DMABUF) { 281 struct usbd_bus *bus = pipe->device->bus; 282 283 bus->methods->freem(bus, &xfer->dmabuf); 284 xfer->rqflags &= ~URQ_AUTO_DMABUF; 285 } 286 } 287 288 if (!(xfer->flags & USBD_SYNCHRONOUS)) 289 return (err); 290 291 /* Sync transfer, wait for completion. */ 292 if (err != USBD_IN_PROGRESS) 293 return (err); 294 s = splusb(); 295 if (!xfer->done) { 296 if (pipe->device->bus->use_polling) 297 panic("usbd_transfer: not done\n"); 298 tsleep(xfer, PRIBIO, "usbsyn", 0); 299 } 300 splx(s); 301 return (xfer->status); 302 } 303 304 /* Like usbd_transfer(), but waits for completion. */ 305 usbd_status 306 usbd_sync_transfer(usbd_xfer_handle xfer) 307 { 308 xfer->flags |= USBD_SYNCHRONOUS; 309 return (usbd_transfer(xfer)); 310 } 311 312 void * 313 usbd_alloc_buffer(usbd_xfer_handle xfer, u_int32_t size) 314 { 315 struct usbd_bus *bus = xfer->device->bus; 316 usbd_status err; 317 318 err = bus->methods->allocm(bus, &xfer->dmabuf, size); 319 if (err) 320 return (0); 321 xfer->rqflags |= URQ_DEV_DMABUF; 322 return (KERNADDR(&xfer->dmabuf)); 323 } 324 325 void 326 usbd_free_buffer(usbd_xfer_handle xfer) 327 { 328 #ifdef DIAGNOSTIC 329 if (!(xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))) { 330 printf("usbd_free_buffer: no buffer\n"); 331 return; 332 } 333 #endif 334 xfer->rqflags &= ~(URQ_DEV_DMABUF | URQ_AUTO_DMABUF); 335 xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf); 336 } 337 338 void * 339 usbd_get_buffer(usbd_xfer_handle xfer) 340 { 341 if (!(xfer->rqflags & URQ_DEV_DMABUF)) 342 return (0); 343 return (KERNADDR(&xfer->dmabuf)); 344 } 345 346 usbd_xfer_handle 347 usbd_alloc_xfer(usbd_device_handle dev) 348 { 349 usbd_xfer_handle xfer; 350 351 xfer = dev->bus->methods->allocx(dev->bus); 352 if (xfer == NULL) 353 return (NULL); 354 xfer->device = dev; 355 usb_callout_init(xfer->timeout_handle); 356 DPRINTFN(5,("usbd_alloc_xfer() = %p\n", xfer)); 357 return (xfer); 358 } 359 360 usbd_status 361 usbd_free_xfer(usbd_xfer_handle xfer) 362 { 363 DPRINTFN(5,("usbd_free_xfer: %p\n", xfer)); 364 if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF)) 365 usbd_free_buffer(xfer); 366 #if defined(__NetBSD__) && defined(DIAGNOSTIC) 367 if (callout_pending(&xfer->timeout_handle)) { 368 callout_stop(&xfer->timeout_handle); 369 printf("usbd_free_xfer: timout_handle pending"); 370 } 371 #endif 372 xfer->device->bus->methods->freex(xfer->device->bus, xfer); 373 return (USBD_NORMAL_COMPLETION); 374 } 375 376 void 377 usbd_setup_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, 378 usbd_private_handle priv, void *buffer, u_int32_t length, 379 u_int16_t flags, u_int32_t timeout, 380 usbd_callback callback) 381 { 382 xfer->pipe = pipe; 383 xfer->priv = priv; 384 xfer->buffer = buffer; 385 xfer->length = length; 386 xfer->actlen = 0; 387 xfer->flags = flags; 388 xfer->timeout = timeout; 389 xfer->status = USBD_NOT_STARTED; 390 xfer->callback = callback; 391 xfer->rqflags &= ~URQ_REQUEST; 392 xfer->nframes = 0; 393 } 394 395 void 396 usbd_setup_default_xfer(usbd_xfer_handle xfer, usbd_device_handle dev, 397 usbd_private_handle priv, u_int32_t timeout, 398 usb_device_request_t *req, void *buffer, 399 u_int32_t length, u_int16_t flags, 400 usbd_callback callback) 401 { 402 xfer->pipe = dev->default_pipe; 403 xfer->priv = priv; 404 xfer->buffer = buffer; 405 xfer->length = length; 406 xfer->actlen = 0; 407 xfer->flags = flags; 408 xfer->timeout = timeout; 409 xfer->status = USBD_NOT_STARTED; 410 xfer->callback = callback; 411 xfer->request = *req; 412 xfer->rqflags |= URQ_REQUEST; 413 xfer->nframes = 0; 414 } 415 416 void 417 usbd_setup_isoc_xfer(usbd_xfer_handle xfer, usbd_pipe_handle pipe, 418 usbd_private_handle priv, u_int16_t *frlengths, 419 u_int32_t nframes, u_int16_t flags, usbd_callback callback) 420 { 421 xfer->pipe = pipe; 422 xfer->priv = priv; 423 xfer->buffer = 0; 424 xfer->length = 0; 425 xfer->actlen = 0; 426 xfer->flags = flags; 427 xfer->timeout = USBD_NO_TIMEOUT; 428 xfer->status = USBD_NOT_STARTED; 429 xfer->callback = callback; 430 xfer->rqflags &= ~URQ_REQUEST; 431 xfer->frlengths = frlengths; 432 xfer->nframes = nframes; 433 } 434 435 void 436 usbd_get_xfer_status(usbd_xfer_handle xfer, usbd_private_handle *priv, 437 void **buffer, u_int32_t *count, usbd_status *status) 438 { 439 if (priv != NULL) 440 *priv = xfer->priv; 441 if (buffer != NULL) 442 *buffer = xfer->buffer; 443 if (count != NULL) 444 *count = xfer->actlen; 445 if (status != NULL) 446 *status = xfer->status; 447 } 448 449 usb_config_descriptor_t * 450 usbd_get_config_descriptor(usbd_device_handle dev) 451 { 452 #ifdef DIAGNOSTIC 453 if (dev == NULL) { 454 printf("usbd_get_config_descriptor: dev == NULL\n"); 455 return (NULL); 456 } 457 #endif 458 return (dev->cdesc); 459 } 460 461 usb_interface_descriptor_t * 462 usbd_get_interface_descriptor(usbd_interface_handle iface) 463 { 464 #ifdef DIAGNOSTIC 465 if (iface == NULL) { 466 printf("usbd_get_interface_descriptor: dev == NULL\n"); 467 return (NULL); 468 } 469 #endif 470 return (iface->idesc); 471 } 472 473 usb_device_descriptor_t * 474 usbd_get_device_descriptor(usbd_device_handle dev) 475 { 476 return (&dev->ddesc); 477 } 478 479 usb_endpoint_descriptor_t * 480 usbd_interface2endpoint_descriptor(usbd_interface_handle iface, u_int8_t index) 481 { 482 if (index >= iface->idesc->bNumEndpoints) 483 return (0); 484 return (iface->endpoints[index].edesc); 485 } 486 487 usbd_status 488 usbd_abort_pipe(usbd_pipe_handle pipe) 489 { 490 usbd_status err; 491 int s; 492 493 #ifdef DIAGNOSTIC 494 if (pipe == NULL) { 495 printf("usbd_close_pipe: pipe==NULL\n"); 496 return (USBD_NORMAL_COMPLETION); 497 } 498 #endif 499 s = splusb(); 500 err = usbd_ar_pipe(pipe); 501 splx(s); 502 return (err); 503 } 504 505 usbd_status 506 usbd_clear_endpoint_stall(usbd_pipe_handle pipe) 507 { 508 usbd_device_handle dev = pipe->device; 509 usb_device_request_t req; 510 usbd_status err; 511 512 DPRINTFN(8, ("usbd_clear_endpoint_stall\n")); 513 514 /* 515 * Clearing en endpoint stall resets the enpoint toggle, so 516 * do the same to the HC toggle. 517 */ 518 pipe->methods->cleartoggle(pipe); 519 520 req.bmRequestType = UT_WRITE_ENDPOINT; 521 req.bRequest = UR_CLEAR_FEATURE; 522 USETW(req.wValue, UF_ENDPOINT_HALT); 523 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); 524 USETW(req.wLength, 0); 525 err = usbd_do_request(dev, &req, 0); 526 #if 0 527 XXX should we do this? 528 if (!err) { 529 pipe->state = USBD_PIPE_ACTIVE; 530 /* XXX activate pipe */ 531 } 532 #endif 533 return (err); 534 } 535 536 usbd_status 537 usbd_clear_endpoint_stall_async(usbd_pipe_handle pipe) 538 { 539 usbd_device_handle dev = pipe->device; 540 usb_device_request_t req; 541 usbd_status err; 542 543 pipe->methods->cleartoggle(pipe); 544 545 req.bmRequestType = UT_WRITE_ENDPOINT; 546 req.bRequest = UR_CLEAR_FEATURE; 547 USETW(req.wValue, UF_ENDPOINT_HALT); 548 USETW(req.wIndex, pipe->endpoint->edesc->bEndpointAddress); 549 USETW(req.wLength, 0); 550 err = usbd_do_request_async(dev, &req, 0); 551 return (err); 552 } 553 554 void usbd_clear_endpoint_toggle(usbd_pipe_handle pipe); /* XXXXX */ 555 void 556 usbd_clear_endpoint_toggle(usbd_pipe_handle pipe) 557 { 558 pipe->methods->cleartoggle(pipe); 559 } 560 561 usbd_status 562 usbd_endpoint_count(usbd_interface_handle iface, u_int8_t *count) 563 { 564 #ifdef DIAGNOSTIC 565 if (iface == NULL || iface->idesc == NULL) { 566 printf("usbd_endpoint_count: NULL pointer\n"); 567 return (USBD_INVAL); 568 } 569 #endif 570 *count = iface->idesc->bNumEndpoints; 571 return (USBD_NORMAL_COMPLETION); 572 } 573 574 usbd_status 575 usbd_interface_count(usbd_device_handle dev, u_int8_t *count) 576 { 577 if (dev->cdesc == NULL) 578 return (USBD_NOT_CONFIGURED); 579 *count = dev->cdesc->bNumInterface; 580 return (USBD_NORMAL_COMPLETION); 581 } 582 583 usbd_status 584 usbd_interface2device_handle(usbd_interface_handle iface, 585 usbd_device_handle *dev) 586 { 587 *dev = iface->device; 588 return (USBD_NORMAL_COMPLETION); 589 } 590 591 usbd_status 592 usbd_device2interface_handle(usbd_device_handle dev, 593 u_int8_t ifaceno, usbd_interface_handle *iface) 594 { 595 if (dev->cdesc == NULL) 596 return (USBD_NOT_CONFIGURED); 597 if (ifaceno >= dev->cdesc->bNumInterface) 598 return (USBD_INVAL); 599 *iface = &dev->ifaces[ifaceno]; 600 return (USBD_NORMAL_COMPLETION); 601 } 602 603 usbd_device_handle 604 usbd_pipe2device_handle(usbd_pipe_handle pipe) 605 { 606 return (pipe->device); 607 } 608 609 /* XXXX use altno */ 610 usbd_status 611 usbd_set_interface(usbd_interface_handle iface, int altidx) 612 { 613 usb_device_request_t req; 614 usbd_status err; 615 void *endpoints; 616 617 if (LIST_FIRST(&iface->pipes) != 0) 618 return (USBD_IN_USE); 619 620 endpoints = iface->endpoints; 621 err = usbd_fill_iface_data(iface->device, iface->index, altidx); 622 if (err) 623 return (err); 624 625 /* new setting works, we can free old endpoints */ 626 if (endpoints != NULL) 627 free(endpoints, M_USB); 628 629 #ifdef DIAGNOSTIC 630 if (iface->idesc == NULL) { 631 printf("usbd_set_interface: NULL pointer\n"); 632 return (USBD_INVAL); 633 } 634 #endif 635 636 req.bmRequestType = UT_WRITE_INTERFACE; 637 req.bRequest = UR_SET_INTERFACE; 638 USETW(req.wValue, iface->idesc->bAlternateSetting); 639 USETW(req.wIndex, iface->idesc->bInterfaceNumber); 640 USETW(req.wLength, 0); 641 return (usbd_do_request(iface->device, &req, 0)); 642 } 643 644 int 645 usbd_get_no_alts(usb_config_descriptor_t *cdesc, int ifaceno) 646 { 647 char *p = (char *)cdesc; 648 char *end = p + UGETW(cdesc->wTotalLength); 649 usb_interface_descriptor_t *d; 650 int n; 651 652 for (n = 0; p < end; p += d->bLength) { 653 d = (usb_interface_descriptor_t *)p; 654 if (p + d->bLength <= end && 655 d->bDescriptorType == UDESC_INTERFACE && 656 d->bInterfaceNumber == ifaceno) 657 n++; 658 } 659 return (n); 660 } 661 662 int 663 usbd_get_interface_altindex(usbd_interface_handle iface) 664 { 665 return (iface->altindex); 666 } 667 668 usbd_status 669 usbd_get_interface(usbd_interface_handle iface, u_int8_t *aiface) 670 { 671 usb_device_request_t req; 672 673 req.bmRequestType = UT_READ_INTERFACE; 674 req.bRequest = UR_GET_INTERFACE; 675 USETW(req.wValue, 0); 676 USETW(req.wIndex, iface->idesc->bInterfaceNumber); 677 USETW(req.wLength, 1); 678 return (usbd_do_request(iface->device, &req, aiface)); 679 } 680 681 /*** Internal routines ***/ 682 683 /* Dequeue all pipe operations, called at splusb(). */ 684 Static usbd_status 685 usbd_ar_pipe(usbd_pipe_handle pipe) 686 { 687 usbd_xfer_handle xfer; 688 689 SPLUSBCHECK; 690 691 DPRINTFN(2,("usbd_ar_pipe: pipe=%p\n", pipe)); 692 #ifdef USB_DEBUG 693 if (usbdebug > 5) 694 usbd_dump_queue(pipe); 695 #endif 696 pipe->repeat = 0; 697 pipe->aborting = 1; 698 while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) { 699 DPRINTFN(2,("usbd_ar_pipe: pipe=%p xfer=%p (methods=%p)\n", 700 pipe, xfer, pipe->methods)); 701 /* Make the HC abort it (and invoke the callback). */ 702 pipe->methods->abort(xfer); 703 /* XXX only for non-0 usbd_clear_endpoint_stall(pipe); */ 704 } 705 pipe->aborting = 0; 706 return (USBD_NORMAL_COMPLETION); 707 } 708 709 /* Called at splusb() */ 710 void 711 usb_transfer_complete(usbd_xfer_handle xfer) 712 { 713 usbd_pipe_handle pipe = xfer->pipe; 714 usb_dma_t *dmap = &xfer->dmabuf; 715 int repeat = pipe->repeat; 716 int polling; 717 718 SPLUSBCHECK; 719 720 DPRINTFN(5, ("usb_transfer_complete: pipe=%p xfer=%p status=%d " 721 "actlen=%d\n", pipe, xfer, xfer->status, xfer->actlen)); 722 723 #ifdef DIAGNOSTIC 724 if (pipe == NULL) { 725 printf("usbd_transfer_cb: pipe==0, xfer=%p\n", xfer); 726 return; 727 } 728 #endif 729 polling = pipe->device->bus->use_polling; 730 /* XXXX */ 731 if (polling) 732 pipe->running = 0; 733 734 if (!(xfer->flags & USBD_NO_COPY) && xfer->actlen != 0 && 735 usbd_xfer_isread(xfer)) { 736 #ifdef DIAGNOSTIC 737 if (xfer->actlen > xfer->length) { 738 printf("usb_transfer_complete: actlen > len %d > %d\n", 739 xfer->actlen, xfer->length); 740 xfer->actlen = xfer->length; 741 } 742 #endif 743 memcpy(xfer->buffer, KERNADDR(dmap), xfer->actlen); 744 } 745 746 /* if we allocated the buffer in usbd_transfer() we free it here. */ 747 if (xfer->rqflags & URQ_AUTO_DMABUF) { 748 if (!repeat) { 749 struct usbd_bus *bus = pipe->device->bus; 750 bus->methods->freem(bus, dmap); 751 xfer->rqflags &= ~URQ_AUTO_DMABUF; 752 } 753 } 754 755 if (!repeat) { 756 /* Remove request from queue. */ 757 #ifdef DIAGNOSTIC 758 if (xfer != SIMPLEQ_FIRST(&pipe->queue)) 759 printf("usb_transfer_complete: bad dequeue %p != %p\n", 760 xfer, SIMPLEQ_FIRST(&pipe->queue)); 761 #endif 762 SIMPLEQ_REMOVE_HEAD(&pipe->queue, xfer, next); 763 } 764 DPRINTFN(5,("usb_transfer_complete: repeat=%d new head=%p\n", 765 repeat, SIMPLEQ_FIRST(&pipe->queue))); 766 767 /* Count completed transfers. */ 768 ++pipe->device->bus->stats.requests 769 [pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE]; 770 771 xfer->done = 1; 772 if (!xfer->status && xfer->actlen < xfer->length && 773 !(xfer->flags & USBD_SHORT_XFER_OK)) { 774 DPRINTFN(-1,("usbd_transfer_cb: short transfer %d<%d\n", 775 xfer->actlen, xfer->length)); 776 xfer->status = USBD_SHORT_XFER; 777 } 778 779 if (xfer->callback) 780 xfer->callback(xfer, xfer->priv, xfer->status); 781 782 #ifdef DIAGNOSTIC 783 if (pipe->methods->done != NULL) 784 pipe->methods->done(xfer); 785 else 786 printf("usb_transfer_complete: pipe->methods->done == NULL\n"); 787 #else 788 pipe->methods->done(xfer); 789 #endif 790 791 if ((xfer->flags & USBD_SYNCHRONOUS) && !polling) 792 wakeup(xfer); 793 794 if (!repeat) { 795 /* XXX should we stop the queue on all errors? */ 796 if ((xfer->status == USBD_CANCELLED || 797 xfer->status == USBD_TIMEOUT) && 798 pipe->iface != NULL) /* not control pipe */ 799 pipe->running = 0; 800 else 801 usbd_start_next(pipe); 802 } 803 } 804 805 usbd_status 806 usb_insert_transfer(usbd_xfer_handle xfer) 807 { 808 usbd_pipe_handle pipe = xfer->pipe; 809 usbd_status err; 810 int s; 811 812 DPRINTFN(5,("usb_insert_transfer: pipe=%p running=%d timeout=%d\n", 813 pipe, pipe->running, xfer->timeout)); 814 s = splusb(); 815 SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next); 816 if (pipe->running) 817 err = USBD_IN_PROGRESS; 818 else { 819 pipe->running = 1; 820 err = USBD_NORMAL_COMPLETION; 821 } 822 splx(s); 823 return (err); 824 } 825 826 /* Called at splusb() */ 827 void 828 usbd_start_next(usbd_pipe_handle pipe) 829 { 830 usbd_xfer_handle xfer; 831 usbd_status err; 832 833 SPLUSBCHECK; 834 835 #ifdef DIAGNOSTIC 836 if (pipe == NULL) { 837 printf("usbd_start_next: pipe == NULL\n"); 838 return; 839 } 840 if (pipe->methods == NULL || pipe->methods->start == NULL) { 841 printf("usbd_start_next: pipe=%p no start method\n", pipe); 842 return; 843 } 844 #endif 845 846 /* Get next request in queue. */ 847 xfer = SIMPLEQ_FIRST(&pipe->queue); 848 DPRINTFN(5, ("usbd_start_next: pipe=%p, xfer=%p\n", pipe, xfer)); 849 if (xfer == NULL) { 850 pipe->running = 0; 851 } else { 852 err = pipe->methods->start(xfer); 853 if (err != USBD_IN_PROGRESS) { 854 printf("usbd_start_next: error=%d\n", err); 855 pipe->running = 0; 856 /* XXX do what? */ 857 } 858 } 859 } 860 861 usbd_status 862 usbd_do_request(usbd_device_handle dev, usb_device_request_t *req, void *data) 863 { 864 return (usbd_do_request_flags(dev, req, data, 0, 0)); 865 } 866 867 usbd_status 868 usbd_do_request_flags(usbd_device_handle dev, usb_device_request_t *req, 869 void *data, u_int16_t flags, int *actlen) 870 { 871 return (usbd_do_request_flags_pipe(dev, dev->default_pipe, req, 872 data, flags, actlen)); 873 } 874 875 usbd_status 876 usbd_do_request_flags_pipe(usbd_device_handle dev, usbd_pipe_handle pipe, 877 usb_device_request_t *req, void *data, u_int16_t flags, int *actlen) 878 { 879 usbd_xfer_handle xfer; 880 usbd_status err; 881 882 #ifdef DIAGNOSTIC 883 #if defined(__i386__) && defined(__FreeBSD__) 884 KASSERT(intr_nesting_level == 0, 885 ("usbd_do_request: in interrupt context")); 886 #endif 887 if (dev->bus->intr_context) { 888 printf("usbd_do_request: not in process context\n"); 889 return (USBD_INVAL); 890 } 891 #endif 892 893 xfer = usbd_alloc_xfer(dev); 894 if (xfer == NULL) 895 return (USBD_NOMEM); 896 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, 897 data, UGETW(req->wLength), flags, 0); 898 xfer->pipe = pipe; 899 err = usbd_sync_transfer(xfer); 900 #if defined(USB_DEBUG) || defined(DIAGNOSTIC) 901 if (xfer->actlen > xfer->length) 902 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" 903 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", 904 dev->address, xfer->request.bmRequestType, 905 xfer->request.bRequest, UGETW(xfer->request.wValue), 906 UGETW(xfer->request.wIndex), 907 UGETW(xfer->request.wLength), 908 xfer->length, xfer->actlen)); 909 #endif 910 if (actlen != NULL) 911 *actlen = xfer->actlen; 912 if (err == USBD_STALLED) { 913 /* 914 * The control endpoint has stalled. Control endpoints 915 * should not halt, but some may do so anyway so clear 916 * any halt condition. 917 */ 918 usb_device_request_t treq; 919 usb_status_t status; 920 u_int16_t s; 921 usbd_status nerr; 922 923 treq.bmRequestType = UT_READ_ENDPOINT; 924 treq.bRequest = UR_GET_STATUS; 925 USETW(treq.wValue, 0); 926 USETW(treq.wIndex, 0); 927 USETW(treq.wLength, sizeof(usb_status_t)); 928 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, 929 &treq, &status,sizeof(usb_status_t), 930 0, 0); 931 nerr = usbd_sync_transfer(xfer); 932 if (nerr) 933 goto bad; 934 s = UGETW(status.wStatus); 935 DPRINTF(("usbd_do_request: status = 0x%04x\n", s)); 936 if (!(s & UES_HALT)) 937 goto bad; 938 treq.bmRequestType = UT_WRITE_ENDPOINT; 939 treq.bRequest = UR_CLEAR_FEATURE; 940 USETW(treq.wValue, UF_ENDPOINT_HALT); 941 USETW(treq.wIndex, 0); 942 USETW(treq.wLength, 0); 943 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, 944 &treq, &status, 0, 0, 0); 945 nerr = usbd_sync_transfer(xfer); 946 if (nerr) 947 goto bad; 948 } 949 950 bad: 951 usbd_free_xfer(xfer); 952 return (err); 953 } 954 955 void 956 usbd_do_request_async_cb(usbd_xfer_handle xfer, usbd_private_handle priv, 957 usbd_status status) 958 { 959 #if defined(USB_DEBUG) || defined(DIAGNOSTIC) 960 if (xfer->actlen > xfer->length) 961 DPRINTF(("usbd_do_request: overrun addr=%d type=0x%02x req=0x" 962 "%02x val=%d index=%d rlen=%d length=%d actlen=%d\n", 963 xfer->pipe->device->address, 964 xfer->request.bmRequestType, 965 xfer->request.bRequest, UGETW(xfer->request.wValue), 966 UGETW(xfer->request.wIndex), 967 UGETW(xfer->request.wLength), 968 xfer->length, xfer->actlen)); 969 #endif 970 usbd_free_xfer(xfer); 971 } 972 973 /* 974 * Execute a request without waiting for completion. 975 * Can be used from interrupt context. 976 */ 977 usbd_status 978 usbd_do_request_async(usbd_device_handle dev, usb_device_request_t *req, 979 void *data) 980 { 981 usbd_xfer_handle xfer; 982 usbd_status err; 983 984 xfer = usbd_alloc_xfer(dev); 985 if (xfer == NULL) 986 return (USBD_NOMEM); 987 usbd_setup_default_xfer(xfer, dev, 0, USBD_DEFAULT_TIMEOUT, req, 988 data, UGETW(req->wLength), 0, usbd_do_request_async_cb); 989 err = usbd_transfer(xfer); 990 if (err != USBD_IN_PROGRESS) { 991 usbd_free_xfer(xfer); 992 return (err); 993 } 994 return (USBD_NORMAL_COMPLETION); 995 } 996 997 const struct usbd_quirks * 998 usbd_get_quirks(usbd_device_handle dev) 999 { 1000 #ifdef DIAGNOSTIC 1001 if (dev == NULL) { 1002 printf("usbd_get_quirks: dev == NULL\n"); 1003 return 0; 1004 } 1005 #endif 1006 return (dev->quirks); 1007 } 1008 1009 /* XXX do periodic free() of free list */ 1010 1011 /* 1012 * Called from keyboard driver when in polling mode. 1013 */ 1014 void 1015 usbd_dopoll(usbd_interface_handle iface) 1016 { 1017 iface->device->bus->methods->do_poll(iface->device->bus); 1018 } 1019 1020 void 1021 usbd_set_polling(usbd_device_handle dev, int on) 1022 { 1023 if (on) 1024 dev->bus->use_polling++; 1025 else 1026 dev->bus->use_polling--; 1027 } 1028 1029 1030 usb_endpoint_descriptor_t * 1031 usbd_get_endpoint_descriptor(usbd_interface_handle iface, u_int8_t address) 1032 { 1033 struct usbd_endpoint *ep; 1034 int i; 1035 1036 for (i = 0; i < iface->idesc->bNumEndpoints; i++) { 1037 ep = &iface->endpoints[i]; 1038 if (ep->edesc->bEndpointAddress == address) 1039 return (iface->endpoints[i].edesc); 1040 } 1041 return (0); 1042 } 1043 1044 /* 1045 * usbd_ratecheck() can limit the number of error messages that occurs. 1046 * When a device is unplugged it may take up to 0.25s for the hub driver 1047 * to notice it. If the driver continuosly tries to do I/O operations 1048 * this can generate a large number of messages. 1049 */ 1050 int 1051 usbd_ratecheck(struct timeval *last) 1052 { 1053 static struct timeval errinterval = { 0, 250000 }; /* 0.25 s*/ 1054 1055 return (ratecheck(last, &errinterval)); 1056 } 1057 1058 #if defined(__FreeBSD__) 1059 int 1060 usbd_driver_load(module_t mod, int what, void *arg) 1061 { 1062 /* XXX should implement something like a function that removes all generic devices */ 1063 1064 return (0); 1065 } 1066 1067 #endif 1068