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