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