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