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