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