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