usb_handle_request.c revision 190633
1/* $FreeBSD: head/sys/dev/usb/usb_handle_request.c 190633 2009-04-01 20:23:47Z piso $ */ 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 usb2_device *, uint8_t); 55static usb2_error_t usb2_handle_remote_wakeup(struct usb2_xfer *, uint8_t); 56static usb2_error_t usb2_handle_request(struct usb2_xfer *); 57static usb2_error_t usb2_handle_set_config(struct usb2_xfer *, uint8_t); 58static usb2_error_t usb2_handle_set_stall(struct usb2_xfer *, uint8_t, 59 uint8_t); 60static usb2_error_t usb2_handle_iface_request(struct usb2_xfer *, void **, 61 uint16_t *, struct usb2_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 usb2_xfer *xfer) 72{ 73 usb2_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 usb2_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 usb2_error_t 126usb2_handle_set_config(struct usb2_xfer *xfer, uint8_t conf_no) 127{ 128 struct usb2_device *udev = xfer->xroot->udev; 129 usb2_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 usb2_error_t 174usb2_handle_iface_request(struct usb2_xfer *xfer, 175 void **ppdata, uint16_t *plen, 176 struct usb2_device_request req, uint16_t off, uint8_t state) 177{ 178 struct usb2_interface *iface; 179 struct usb2_interface *iface_parent; /* parent interface */ 180 struct usb2_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 usb2_error_t 337usb2_handle_set_stall(struct usb2_xfer *xfer, uint8_t ep, uint8_t do_stall) 338{ 339 struct usb2_device *udev = xfer->xroot->udev; 340 usb2_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 usb2_device *udev, uint8_t ea_val) 358{ 359 struct usb2_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 usb2_error_t 382usb2_handle_remote_wakeup(struct usb2_xfer *xfer, uint8_t is_on) 383{ 384 struct usb2_device *udev; 385 struct usb2_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 402 usb2_bus_power_update(udev->bus); 403 404 return (0); /* success */ 405} 406 407/*------------------------------------------------------------------------* 408 * usb2_handle_request 409 * 410 * Internal state sequence: 411 * 412 * ST_DATA -> ST_POST_STATUS 413 * 414 * Returns: 415 * 0: Ready to start hardware 416 * Else: Stall current transfer, if any 417 *------------------------------------------------------------------------*/ 418static usb2_error_t 419usb2_handle_request(struct usb2_xfer *xfer) 420{ 421 struct usb2_device_request req; 422 struct usb2_device *udev; 423 const void *src_zcopy; /* zero-copy source pointer */ 424 const void *src_mcopy; /* non zero-copy source pointer */ 425 uint16_t off; /* data offset */ 426 uint16_t rem; /* data remainder */ 427 uint16_t max_len; /* max fragment length */ 428 uint16_t wValue; 429 uint16_t wIndex; 430 uint8_t state; 431 usb2_error_t err; 432 union { 433 uWord wStatus; 434 uint8_t buf[2]; 435 } temp; 436 437 /* 438 * Filter the USB transfer state into 439 * something which we understand: 440 */ 441 442 switch (USB_GET_STATE(xfer)) { 443 case USB_ST_SETUP: 444 state = ST_DATA; 445 446 if (!xfer->flags_int.control_act) { 447 /* nothing to do */ 448 goto tr_stalled; 449 } 450 break; 451 452 default: /* USB_ST_TRANSFERRED */ 453 if (!xfer->flags_int.control_act) { 454 state = ST_POST_STATUS; 455 } else { 456 state = ST_DATA; 457 } 458 break; 459 } 460 461 /* reset frame stuff */ 462 463 xfer->frlengths[0] = 0; 464 465 usb2_set_frame_offset(xfer, 0, 0); 466 usb2_set_frame_offset(xfer, sizeof(req), 1); 467 468 /* get the current request, if any */ 469 470 usb2_copy_out(xfer->frbuffers, 0, &req, sizeof(req)); 471 472 if (xfer->flags_int.control_rem == 0xFFFF) { 473 /* first time - not initialised */ 474 rem = UGETW(req.wLength); 475 off = 0; 476 } else { 477 /* not first time - initialised */ 478 rem = xfer->flags_int.control_rem; 479 off = UGETW(req.wLength) - rem; 480 } 481 482 /* set some defaults */ 483 484 max_len = 0; 485 src_zcopy = NULL; 486 src_mcopy = NULL; 487 udev = xfer->xroot->udev; 488 489 /* get some request fields decoded */ 490 491 wValue = UGETW(req.wValue); 492 wIndex = UGETW(req.wIndex); 493 494 DPRINTF("req 0x%02x 0x%02x 0x%04x 0x%04x " 495 "off=0x%x rem=0x%x, state=%d\n", req.bmRequestType, 496 req.bRequest, wValue, wIndex, off, rem, state); 497 498 /* demultiplex the control request */ 499 500 switch (req.bmRequestType) { 501 case UT_READ_DEVICE: 502 if (state != ST_DATA) { 503 break; 504 } 505 switch (req.bRequest) { 506 case UR_GET_DESCRIPTOR: 507 goto tr_handle_get_descriptor; 508 case UR_GET_CONFIG: 509 goto tr_handle_get_config; 510 case UR_GET_STATUS: 511 goto tr_handle_get_status; 512 default: 513 goto tr_stalled; 514 } 515 break; 516 517 case UT_WRITE_DEVICE: 518 switch (req.bRequest) { 519 case UR_SET_ADDRESS: 520 goto tr_handle_set_address; 521 case UR_SET_CONFIG: 522 goto tr_handle_set_config; 523 case UR_CLEAR_FEATURE: 524 switch (wValue) { 525 case UF_DEVICE_REMOTE_WAKEUP: 526 goto tr_handle_clear_wakeup; 527 default: 528 goto tr_stalled; 529 } 530 break; 531 case UR_SET_FEATURE: 532 switch (wValue) { 533 case UF_DEVICE_REMOTE_WAKEUP: 534 goto tr_handle_set_wakeup; 535 default: 536 goto tr_stalled; 537 } 538 break; 539 default: 540 goto tr_stalled; 541 } 542 break; 543 544 case UT_WRITE_ENDPOINT: 545 switch (req.bRequest) { 546 case UR_CLEAR_FEATURE: 547 switch (wValue) { 548 case UF_ENDPOINT_HALT: 549 goto tr_handle_clear_halt; 550 default: 551 goto tr_stalled; 552 } 553 break; 554 case UR_SET_FEATURE: 555 switch (wValue) { 556 case UF_ENDPOINT_HALT: 557 goto tr_handle_set_halt; 558 default: 559 goto tr_stalled; 560 } 561 break; 562 default: 563 goto tr_stalled; 564 } 565 break; 566 567 case UT_READ_ENDPOINT: 568 switch (req.bRequest) { 569 case UR_GET_STATUS: 570 goto tr_handle_get_ep_status; 571 default: 572 goto tr_stalled; 573 } 574 break; 575 default: 576 /* we use "USB_ADD_BYTES" to de-const the src_zcopy */ 577 err = usb2_handle_iface_request(xfer, 578 USB_ADD_BYTES(&src_zcopy, 0), 579 &max_len, req, off, state); 580 if (err == 0) { 581 goto tr_valid; 582 } 583 /* 584 * Reset zero-copy pointer and max length 585 * variable in case they were unintentionally 586 * set: 587 */ 588 src_zcopy = NULL; 589 max_len = 0; 590 591 /* 592 * Check if we have a vendor specific 593 * descriptor: 594 */ 595 goto tr_handle_get_descriptor; 596 } 597 goto tr_valid; 598 599tr_handle_get_descriptor: 600 (usb2_temp_get_desc_p) (udev, &req, &src_zcopy, &max_len); 601 if (src_zcopy == NULL) { 602 goto tr_stalled; 603 } 604 goto tr_valid; 605 606tr_handle_get_config: 607 temp.buf[0] = udev->curr_config_no; 608 src_mcopy = temp.buf; 609 max_len = 1; 610 goto tr_valid; 611 612tr_handle_get_status: 613 614 wValue = 0; 615 616 USB_BUS_LOCK(udev->bus); 617 if (udev->flags.remote_wakeup) { 618 wValue |= UDS_REMOTE_WAKEUP; 619 } 620 if (udev->flags.self_powered) { 621 wValue |= UDS_SELF_POWERED; 622 } 623 USB_BUS_UNLOCK(udev->bus); 624 625 USETW(temp.wStatus, wValue); 626 src_mcopy = temp.wStatus; 627 max_len = sizeof(temp.wStatus); 628 goto tr_valid; 629 630tr_handle_set_address: 631 if (state == ST_DATA) { 632 if (wValue >= 0x80) { 633 /* invalid value */ 634 goto tr_stalled; 635 } else if (udev->curr_config_no != 0) { 636 /* we are configured ! */ 637 goto tr_stalled; 638 } 639 } else if (state == ST_POST_STATUS) { 640 udev->address = (wValue & 0x7F); 641 goto tr_bad_context; 642 } 643 goto tr_valid; 644 645tr_handle_set_config: 646 if (state == ST_DATA) { 647 if (usb2_handle_set_config(xfer, req.wValue[0])) { 648 goto tr_stalled; 649 } 650 } 651 goto tr_valid; 652 653tr_handle_clear_halt: 654 if (state == ST_DATA) { 655 if (usb2_handle_set_stall(xfer, req.wIndex[0], 0)) { 656 goto tr_stalled; 657 } 658 } 659 goto tr_valid; 660 661tr_handle_clear_wakeup: 662 if (state == ST_DATA) { 663 if (usb2_handle_remote_wakeup(xfer, 0)) { 664 goto tr_stalled; 665 } 666 } 667 goto tr_valid; 668 669tr_handle_set_halt: 670 if (state == ST_DATA) { 671 if (usb2_handle_set_stall(xfer, req.wIndex[0], 1)) { 672 goto tr_stalled; 673 } 674 } 675 goto tr_valid; 676 677tr_handle_set_wakeup: 678 if (state == ST_DATA) { 679 if (usb2_handle_remote_wakeup(xfer, 1)) { 680 goto tr_stalled; 681 } 682 } 683 goto tr_valid; 684 685tr_handle_get_ep_status: 686 if (state == ST_DATA) { 687 temp.wStatus[0] = 688 usb2_handle_get_stall(udev, req.wIndex[0]); 689 temp.wStatus[1] = 0; 690 src_mcopy = temp.wStatus; 691 max_len = sizeof(temp.wStatus); 692 } 693 goto tr_valid; 694 695tr_valid: 696 if (state == ST_POST_STATUS) { 697 goto tr_stalled; 698 } 699 /* subtract offset from length */ 700 701 max_len -= off; 702 703 /* Compute the real maximum data length */ 704 705 if (max_len > xfer->max_data_length) { 706 max_len = xfer->max_data_length; 707 } 708 if (max_len > rem) { 709 max_len = rem; 710 } 711 /* 712 * If the remainder is greater than the maximum data length, 713 * we need to truncate the value for the sake of the 714 * comparison below: 715 */ 716 if (rem > xfer->max_data_length) { 717 rem = xfer->max_data_length; 718 } 719 if (rem != max_len) { 720 /* 721 * If we don't transfer the data we can transfer, then 722 * the transfer is short ! 723 */ 724 xfer->flags.force_short_xfer = 1; 725 xfer->nframes = 2; 726 } else { 727 /* 728 * Default case 729 */ 730 xfer->flags.force_short_xfer = 0; 731 xfer->nframes = max_len ? 2 : 1; 732 } 733 if (max_len > 0) { 734 if (src_mcopy) { 735 src_mcopy = USB_ADD_BYTES(src_mcopy, off); 736 usb2_copy_in(xfer->frbuffers + 1, 0, 737 src_mcopy, max_len); 738 } else { 739 usb2_set_frame_data(xfer, 740 USB_ADD_BYTES(src_zcopy, off), 1); 741 } 742 xfer->frlengths[1] = max_len; 743 } else { 744 /* the end is reached, send status */ 745 xfer->flags.manual_status = 0; 746 xfer->frlengths[1] = 0; 747 } 748 DPRINTF("success\n"); 749 return (0); /* success */ 750 751tr_stalled: 752 DPRINTF("%s\n", (state == ST_POST_STATUS) ? 753 "complete" : "stalled"); 754 return (USB_ERR_STALLED); 755 756tr_bad_context: 757 DPRINTF("bad context\n"); 758 return (USB_ERR_BAD_CONTEXT); 759} 760