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