usb_handle_request.c revision 193045
1/* $FreeBSD: head/sys/dev/usb/usb_handle_request.c 193045 2009-05-29 18:46:57Z thompsa $ */ 2/*- 3 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <dev/usb/usb_mfunc.h> 28#include <dev/usb/usb_error.h> 29#include <dev/usb/usb.h> 30 31#define USB_DEBUG_VAR usb2_debug 32 33#include <dev/usb/usb_core.h> 34#include <dev/usb/usb_process.h> 35#include <dev/usb/usb_busdma.h> 36#include <dev/usb/usb_transfer.h> 37#include <dev/usb/usb_device.h> 38#include <dev/usb/usb_debug.h> 39#include <dev/usb/usb_dynamic.h> 40#include <dev/usb/usb_hub.h> 41 42#include <dev/usb/usb_controller.h> 43#include <dev/usb/usb_bus.h> 44 45/* enum */ 46 47enum { 48 ST_DATA, 49 ST_POST_STATUS, 50}; 51 52/* function prototypes */ 53 54static uint8_t usb2_handle_get_stall(struct usb_device *, uint8_t); 55static usb_error_t usb2_handle_remote_wakeup(struct usb_xfer *, uint8_t); 56static usb_error_t usb2_handle_request(struct usb_xfer *); 57static usb_error_t usb2_handle_set_config(struct usb_xfer *, uint8_t); 58static usb_error_t usb2_handle_set_stall(struct usb_xfer *, uint8_t, 59 uint8_t); 60static usb_error_t usb2_handle_iface_request(struct usb_xfer *, void **, 61 uint16_t *, struct usb_device_request, uint16_t, 62 uint8_t); 63 64/*------------------------------------------------------------------------* 65 * usb2_handle_request_callback 66 * 67 * This function is the USB callback for generic USB Device control 68 * transfers. 69 *------------------------------------------------------------------------*/ 70void 71usb2_handle_request_callback(struct usb_xfer *xfer) 72{ 73 usb_error_t err; 74 75 /* check the current transfer state */ 76 77 switch (USB_GET_STATE(xfer)) { 78 case USB_ST_SETUP: 79 case USB_ST_TRANSFERRED: 80 81 /* handle the request */ 82 err = usb2_handle_request(xfer); 83 84 if (err) { 85 86 if (err == USB_ERR_BAD_CONTEXT) { 87 /* we need to re-setup the control transfer */ 88 usb2_needs_explore(xfer->xroot->bus, 0); 89 break; 90 } 91 /* 92 * If no control transfer is active, 93 * receive the next SETUP message: 94 */ 95 goto tr_restart; 96 } 97 usb2_start_hardware(xfer); 98 break; 99 100 default: 101 if (xfer->error != USB_ERR_CANCELLED) { 102 /* should not happen - try stalling */ 103 goto tr_restart; 104 } 105 break; 106 } 107 return; 108 109tr_restart: 110 xfer->frlengths[0] = sizeof(struct usb_device_request); 111 xfer->nframes = 1; 112 xfer->flags.manual_status = 1; 113 xfer->flags.force_short_xfer = 0; 114 xfer->flags.stall_pipe = 1; /* cancel previous transfer, if any */ 115 usb2_start_hardware(xfer); 116} 117 118/*------------------------------------------------------------------------* 119 * usb2_handle_set_config 120 * 121 * Returns: 122 * 0: Success 123 * Else: Failure 124 *------------------------------------------------------------------------*/ 125static usb_error_t 126usb2_handle_set_config(struct usb_xfer *xfer, uint8_t conf_no) 127{ 128 struct usb_device *udev = xfer->xroot->udev; 129 usb_error_t err = 0; 130 131 /* 132 * We need to protect against other threads doing probe and 133 * attach: 134 */ 135 USB_XFER_UNLOCK(xfer); 136 mtx_lock(&Giant); /* XXX */ 137 sx_xlock(udev->default_sx + 1); 138 139 if (conf_no == USB_UNCONFIG_NO) { 140 conf_no = USB_UNCONFIG_INDEX; 141 } else { 142 /* 143 * The relationship between config number and config index 144 * is very simple in our case: 145 */ 146 conf_no--; 147 } 148 149 if (usb2_set_config_index(udev, conf_no)) { 150 DPRINTF("set config %d failed\n", conf_no); 151 err = USB_ERR_STALLED; 152 goto done; 153 } 154 if (usb2_probe_and_attach(udev, USB_IFACE_INDEX_ANY)) { 155 DPRINTF("probe and attach failed\n"); 156 err = USB_ERR_STALLED; 157 goto done; 158 } 159done: 160 mtx_unlock(&Giant); /* XXX */ 161 sx_unlock(udev->default_sx + 1); 162 USB_XFER_LOCK(xfer); 163 return (err); 164} 165 166/*------------------------------------------------------------------------* 167 * usb2_handle_iface_request 168 * 169 * Returns: 170 * 0: Success 171 * Else: Failure 172 *------------------------------------------------------------------------*/ 173static usb_error_t 174usb2_handle_iface_request(struct usb_xfer *xfer, 175 void **ppdata, uint16_t *plen, 176 struct usb_device_request req, uint16_t off, uint8_t state) 177{ 178 struct usb_interface *iface; 179 struct usb_interface *iface_parent; /* parent interface */ 180 struct usb_device *udev = xfer->xroot->udev; 181 int error; 182 uint8_t iface_index; 183 184 if ((req.bmRequestType & 0x1F) == UT_INTERFACE) { 185 iface_index = req.wIndex[0]; /* unicast */ 186 } else { 187 iface_index = 0; /* broadcast */ 188 } 189 190 /* 191 * We need to protect against other threads doing probe and 192 * attach: 193 */ 194 USB_XFER_UNLOCK(xfer); 195 mtx_lock(&Giant); /* XXX */ 196 sx_xlock(udev->default_sx + 1); 197 198 error = ENXIO; 199 200tr_repeat: 201 iface = usb2_get_iface(udev, iface_index); 202 if ((iface == NULL) || 203 (iface->idesc == NULL)) { 204 /* end of interfaces non-existing interface */ 205 goto tr_stalled; 206 } 207 /* forward request to interface, if any */ 208 209 if ((error != 0) && 210 (error != ENOTTY) && 211 (iface->subdev != NULL) && 212 device_is_attached(iface->subdev)) { 213#if 0 214 DEVMETHOD(usb_handle_request, NULL); /* dummy */ 215#endif 216 error = USB_HANDLE_REQUEST(iface->subdev, 217 &req, ppdata, plen, 218 off, (state == ST_POST_STATUS)); 219 } 220 iface_parent = usb2_get_iface(udev, iface->parent_iface_index); 221 222 if ((iface_parent == NULL) || 223 (iface_parent->idesc == NULL)) { 224 /* non-existing interface */ 225 iface_parent = NULL; 226 } 227 /* forward request to parent interface, if any */ 228 229 if ((error != 0) && 230 (error != ENOTTY) && 231 (iface_parent != NULL) && 232 (iface_parent->subdev != NULL) && 233 ((req.bmRequestType & 0x1F) == UT_INTERFACE) && 234 (iface_parent->subdev != iface->subdev) && 235 device_is_attached(iface_parent->subdev)) { 236 error = USB_HANDLE_REQUEST(iface_parent->subdev, 237 &req, ppdata, plen, off, 238 (state == ST_POST_STATUS)); 239 } 240 if (error == 0) { 241 /* negativly adjust pointer and length */ 242 *ppdata = ((uint8_t *)(*ppdata)) - off; 243 *plen += off; 244 goto tr_valid; 245 } else if (error == ENOTTY) { 246 goto tr_stalled; 247 } 248 if ((req.bmRequestType & 0x1F) != UT_INTERFACE) { 249 iface_index++; /* iterate */ 250 goto tr_repeat; 251 } 252 if (state == ST_POST_STATUS) { 253 /* we are complete */ 254 goto tr_valid; 255 } 256 switch (req.bmRequestType) { 257 case UT_WRITE_INTERFACE: 258 switch (req.bRequest) { 259 case UR_SET_INTERFACE: 260 /* 261 * Handle special case. If we have parent interface 262 * we just reset the endpoints, because this is a 263 * multi interface device and re-attaching only a 264 * part of the device is not possible. Also if the 265 * alternate setting is the same like before we just 266 * reset the interface endoints. 267 */ 268 if ((iface_parent != NULL) || 269 (iface->alt_index == req.wValue[0])) { 270 error = usb2_reset_iface_endpoints(udev, 271 iface_index); 272 if (error) { 273 DPRINTF("alt setting failed %s\n", 274 usb2_errstr(error)); 275 goto tr_stalled; 276 } 277 break; 278 } 279 /* 280 * Doing the alternate setting will detach the 281 * interface aswell: 282 */ 283 error = usb2_set_alt_interface_index(udev, 284 iface_index, req.wValue[0]); 285 if (error) { 286 DPRINTF("alt setting failed %s\n", 287 usb2_errstr(error)); 288 goto tr_stalled; 289 } 290 error = usb2_probe_and_attach(udev, 291 iface_index); 292 if (error) { 293 DPRINTF("alt setting probe failed\n"); 294 goto tr_stalled; 295 } 296 break; 297 default: 298 goto tr_stalled; 299 } 300 break; 301 302 case UT_READ_INTERFACE: 303 switch (req.bRequest) { 304 case UR_GET_INTERFACE: 305 *ppdata = &iface->alt_index; 306 *plen = 1; 307 break; 308 309 default: 310 goto tr_stalled; 311 } 312 break; 313 default: 314 goto tr_stalled; 315 } 316tr_valid: 317 mtx_unlock(&Giant); 318 sx_unlock(udev->default_sx + 1); 319 USB_XFER_LOCK(xfer); 320 return (0); 321 322tr_stalled: 323 mtx_unlock(&Giant); 324 sx_unlock(udev->default_sx + 1); 325 USB_XFER_LOCK(xfer); 326 return (USB_ERR_STALLED); 327} 328 329/*------------------------------------------------------------------------* 330 * usb2_handle_stall 331 * 332 * Returns: 333 * 0: Success 334 * Else: Failure 335 *------------------------------------------------------------------------*/ 336static usb_error_t 337usb2_handle_set_stall(struct usb_xfer *xfer, uint8_t ep, uint8_t do_stall) 338{ 339 struct usb_device *udev = xfer->xroot->udev; 340 usb_error_t err; 341 342 USB_XFER_UNLOCK(xfer); 343 err = usb2_set_endpoint_stall(udev, 344 usb2_get_pipe_by_addr(udev, ep), do_stall); 345 USB_XFER_LOCK(xfer); 346 return (err); 347} 348 349/*------------------------------------------------------------------------* 350 * usb2_handle_get_stall 351 * 352 * Returns: 353 * 0: Success 354 * Else: Failure 355 *------------------------------------------------------------------------*/ 356static uint8_t 357usb2_handle_get_stall(struct usb_device *udev, uint8_t ea_val) 358{ 359 struct usb_pipe *pipe; 360 uint8_t halted; 361 362 pipe = usb2_get_pipe_by_addr(udev, ea_val); 363 if (pipe == NULL) { 364 /* nothing to do */ 365 return (0); 366 } 367 USB_BUS_LOCK(udev->bus); 368 halted = pipe->is_stalled; 369 USB_BUS_UNLOCK(udev->bus); 370 371 return (halted); 372} 373 374/*------------------------------------------------------------------------* 375 * usb2_handle_remote_wakeup 376 * 377 * Returns: 378 * 0: Success 379 * Else: Failure 380 *------------------------------------------------------------------------*/ 381static usb_error_t 382usb2_handle_remote_wakeup(struct usb_xfer *xfer, uint8_t is_on) 383{ 384 struct usb_device *udev; 385 struct usb_bus *bus; 386 387 udev = xfer->xroot->udev; 388 bus = udev->bus; 389 390 USB_BUS_LOCK(bus); 391 392 if (is_on) { 393 udev->flags.remote_wakeup = 1; 394 } else { 395 udev->flags.remote_wakeup = 0; 396 } 397 398 USB_BUS_UNLOCK(bus); 399 400 /* In case we are out of sync, update the power state. */ 401 usb2_bus_power_update(udev->bus); 402 return (0); /* success */ 403} 404 405/*------------------------------------------------------------------------* 406 * usb2_handle_request 407 * 408 * Internal state sequence: 409 * 410 * ST_DATA -> ST_POST_STATUS 411 * 412 * Returns: 413 * 0: Ready to start hardware 414 * Else: Stall current transfer, if any 415 *------------------------------------------------------------------------*/ 416static usb_error_t 417usb2_handle_request(struct usb_xfer *xfer) 418{ 419 struct usb_device_request req; 420 struct usb_device *udev; 421 const void *src_zcopy; /* zero-copy source pointer */ 422 const void *src_mcopy; /* non zero-copy source pointer */ 423 uint16_t off; /* data offset */ 424 uint16_t rem; /* data remainder */ 425 uint16_t max_len; /* max fragment length */ 426 uint16_t wValue; 427 uint16_t wIndex; 428 uint8_t state; 429 usb_error_t err; 430 union { 431 uWord wStatus; 432 uint8_t buf[2]; 433 } temp; 434 435 /* 436 * Filter the USB transfer state into 437 * something which we understand: 438 */ 439 440 switch (USB_GET_STATE(xfer)) { 441 case USB_ST_SETUP: 442 state = ST_DATA; 443 444 if (!xfer->flags_int.control_act) { 445 /* nothing to do */ 446 goto tr_stalled; 447 } 448 break; 449 450 default: /* USB_ST_TRANSFERRED */ 451 if (!xfer->flags_int.control_act) { 452 state = ST_POST_STATUS; 453 } else { 454 state = ST_DATA; 455 } 456 break; 457 } 458 459 /* reset frame stuff */ 460 461 xfer->frlengths[0] = 0; 462 463 usb2_set_frame_offset(xfer, 0, 0); 464 usb2_set_frame_offset(xfer, sizeof(req), 1); 465 466 /* get the current request, if any */ 467 468 usb2_copy_out(xfer->frbuffers, 0, &req, sizeof(req)); 469 470 if (xfer->flags_int.control_rem == 0xFFFF) { 471 /* first time - not initialised */ 472 rem = UGETW(req.wLength); 473 off = 0; 474 } else { 475 /* not first time - initialised */ 476 rem = xfer->flags_int.control_rem; 477 off = UGETW(req.wLength) - rem; 478 } 479 480 /* set some defaults */ 481 482 max_len = 0; 483 src_zcopy = NULL; 484 src_mcopy = NULL; 485 udev = xfer->xroot->udev; 486 487 /* get some request fields decoded */ 488 489 wValue = UGETW(req.wValue); 490 wIndex = UGETW(req.wIndex); 491 492 DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x " 493 "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType, 494 req.bRequest, wValue, wIndex, off, rem, state); 495 496 /* demultiplex the control request */ 497 498 switch (req.bmRequestType) { 499 case UT_READ_DEVICE: 500 if (state != ST_DATA) { 501 break; 502 } 503 switch (req.bRequest) { 504 case UR_GET_DESCRIPTOR: 505 goto tr_handle_get_descriptor; 506 case UR_GET_CONFIG: 507 goto tr_handle_get_config; 508 case UR_GET_STATUS: 509 goto tr_handle_get_status; 510 default: 511 goto tr_stalled; 512 } 513 break; 514 515 case UT_WRITE_DEVICE: 516 switch (req.bRequest) { 517 case UR_SET_ADDRESS: 518 goto tr_handle_set_address; 519 case UR_SET_CONFIG: 520 goto tr_handle_set_config; 521 case UR_CLEAR_FEATURE: 522 switch (wValue) { 523 case UF_DEVICE_REMOTE_WAKEUP: 524 goto tr_handle_clear_wakeup; 525 default: 526 goto tr_stalled; 527 } 528 break; 529 case UR_SET_FEATURE: 530 switch (wValue) { 531 case UF_DEVICE_REMOTE_WAKEUP: 532 goto tr_handle_set_wakeup; 533 default: 534 goto tr_stalled; 535 } 536 break; 537 default: 538 goto tr_stalled; 539 } 540 break; 541 542 case UT_WRITE_ENDPOINT: 543 switch (req.bRequest) { 544 case UR_CLEAR_FEATURE: 545 switch (wValue) { 546 case UF_ENDPOINT_HALT: 547 goto tr_handle_clear_halt; 548 default: 549 goto tr_stalled; 550 } 551 break; 552 case UR_SET_FEATURE: 553 switch (wValue) { 554 case UF_ENDPOINT_HALT: 555 goto tr_handle_set_halt; 556 default: 557 goto tr_stalled; 558 } 559 break; 560 default: 561 goto tr_stalled; 562 } 563 break; 564 565 case UT_READ_ENDPOINT: 566 switch (req.bRequest) { 567 case UR_GET_STATUS: 568 goto tr_handle_get_ep_status; 569 default: 570 goto tr_stalled; 571 } 572 break; 573 default: 574 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */ 575 err = usb2_handle_iface_request(xfer, 576 USB_ADD_BYTES(&src_zcopy, 0), 577 &max_len, req, off, state); 578 if (err == 0) { 579 goto tr_valid; 580 } 581 /* 582 * Reset zero-copy pointer and max length 583 * variable in case they were unintentionally 584 * set: 585 */ 586 src_zcopy = NULL; 587 max_len = 0; 588 589 /* 590 * Check if we have a vendor specific 591 * descriptor: 592 */ 593 goto tr_handle_get_descriptor; 594 } 595 goto tr_valid; 596 597tr_handle_get_descriptor: 598 err = (usb2_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len); 599 if (err) 600 goto tr_stalled; 601 if (src_zcopy == NULL) 602 goto tr_stalled; 603 goto tr_valid; 604 605tr_handle_get_config: 606 temp.buf[0] = udev->curr_config_no; 607 src_mcopy = temp.buf; 608 max_len = 1; 609 goto tr_valid; 610 611tr_handle_get_status: 612 613 wValue = 0; 614 615 USB_BUS_LOCK(udev->bus); 616 if (udev->flags.remote_wakeup) { 617 wValue |= UDS_REMOTE_WAKEUP; 618 } 619 if (udev->flags.self_powered) { 620 wValue |= UDS_SELF_POWERED; 621 } 622 USB_BUS_UNLOCK(udev->bus); 623 624 USETW(temp.wStatus, wValue); 625 src_mcopy = temp.wStatus; 626 max_len = sizeof(temp.wStatus); 627 goto tr_valid; 628 629tr_handle_set_address: 630 if (state == ST_DATA) { 631 if (wValue >= 0x80) { 632 /* invalid value */ 633 goto tr_stalled; 634 } else if (udev->curr_config_no != 0) { 635 /* we are configured ! */ 636 goto tr_stalled; 637 } 638 } else if (state == ST_POST_STATUS) { 639 udev->address = (wValue & 0x7F); 640 goto tr_bad_context; 641 } 642 goto tr_valid; 643 644tr_handle_set_config: 645 if (state == ST_DATA) { 646 if (usb2_handle_set_config(xfer, req.wValue[0])) { 647 goto tr_stalled; 648 } 649 } 650 goto tr_valid; 651 652tr_handle_clear_halt: 653 if (state == ST_DATA) { 654 if (usb2_handle_set_stall(xfer, req.wIndex[0], 0)) { 655 goto tr_stalled; 656 } 657 } 658 goto tr_valid; 659 660tr_handle_clear_wakeup: 661 if (state == ST_DATA) { 662 if (usb2_handle_remote_wakeup(xfer, 0)) { 663 goto tr_stalled; 664 } 665 } 666 goto tr_valid; 667 668tr_handle_set_halt: 669 if (state == ST_DATA) { 670 if (usb2_handle_set_stall(xfer, req.wIndex[0], 1)) { 671 goto tr_stalled; 672 } 673 } 674 goto tr_valid; 675 676tr_handle_set_wakeup: 677 if (state == ST_DATA) { 678 if (usb2_handle_remote_wakeup(xfer, 1)) { 679 goto tr_stalled; 680 } 681 } 682 goto tr_valid; 683 684tr_handle_get_ep_status: 685 if (state == ST_DATA) { 686 temp.wStatus[0] = 687 usb2_handle_get_stall(udev, req.wIndex[0]); 688 temp.wStatus[1] = 0; 689 src_mcopy = temp.wStatus; 690 max_len = sizeof(temp.wStatus); 691 } 692 goto tr_valid; 693 694tr_valid: 695 if (state == ST_POST_STATUS) { 696 goto tr_stalled; 697 } 698 /* subtract offset from length */ 699 700 max_len -= off; 701 702 /* Compute the real maximum data length */ 703 704 if (max_len > xfer->max_data_length) { 705 max_len = xfer->max_data_length; 706 } 707 if (max_len > rem) { 708 max_len = rem; 709 } 710 /* 711 * If the remainder is greater than the maximum data length, 712 * we need to truncate the value for the sake of the 713 * comparison below: 714 */ 715 if (rem > xfer->max_data_length) { 716 rem = xfer->max_data_length; 717 } 718 if (rem != max_len) { 719 /* 720 * If we don't transfer the data we can transfer, then 721 * the transfer is short ! 722 */ 723 xfer->flags.force_short_xfer = 1; 724 xfer->nframes = 2; 725 } else { 726 /* 727 * Default case 728 */ 729 xfer->flags.force_short_xfer = 0; 730 xfer->nframes = max_len ? 2 : 1; 731 } 732 if (max_len > 0) { 733 if (src_mcopy) { 734 src_mcopy = USB_ADD_BYTES(src_mcopy, off); 735 usb2_copy_in(xfer->frbuffers + 1, 0, 736 src_mcopy, max_len); 737 } else { 738 usb2_set_frame_data(xfer, 739 USB_ADD_BYTES(src_zcopy, off), 1); 740 } 741 xfer->frlengths[1] = max_len; 742 } else { 743 /* the end is reached, send status */ 744 xfer->flags.manual_status = 0; 745 xfer->frlengths[1] = 0; 746 } 747 DPRINTF("success\n"); 748 return (0); /* success */ 749 750tr_stalled: 751 DPRINTF("%s\n", (state == ST_POST_STATUS) ? 752 "complete" : "stalled"); 753 return (USB_ERR_STALLED); 754 755tr_bad_context: 756 DPRINTF("bad context\n"); 757 return (USB_ERR_BAD_CONTEXT); 758} 759