sys/bus/u4b/usb_request.c
void
usb_do_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct usb_device_request req;
	struct usb_device *udev;
	struct usb_endpoint *ep;
	struct usb_endpoint *ep_end;
	struct usb_endpoint *ep_first;
	uint8_t to;

	udev = xfer->xroot->udev;

	USB_BUS_LOCK(udev->bus);

	/* round robin endpoint clear stall */

	ep = udev->ep_curr;
	ep_end = udev->endpoints + udev->endpoints_max;
	ep_first = udev->endpoints;
	to = udev->endpoints_max;

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:
tr_transferred:
		/* reset error counter */
		udev->clear_stall_errors = 0;

		if (ep == NULL)
			goto tr_setup;		/* device was unconfigured */
		if (ep->edesc &&
		    ep->is_stalled) {
			ep->toggle_next = 0;
			ep->is_stalled = 0;
			/* some hardware needs a callback to clear the data toggle */
			usbd_clear_stall_locked(udev, ep);
			/* start up the current or next transfer, if any */
			usb_command_wrapper(&ep->endpoint_q,
			    ep->endpoint_q.curr);
		}
		ep++;

	case USB_ST_SETUP:
tr_setup:
		if (to == 0)
			break;			/* no endpoints - nothing to do */
		if ((ep < ep_first) || (ep >= ep_end))
			ep = ep_first;	/* endpoint wrapped around */
		if (ep->edesc &&
		    ep->is_stalled) {

			/* setup a clear-stall packet */

			req.bmRequestType = UT_WRITE_ENDPOINT;
			req.bRequest = UR_CLEAR_FEATURE;
			USETW(req.wValue, UF_ENDPOINT_HALT);
			req.wIndex[0] = ep->edesc->bEndpointAddress;
			req.wIndex[1] = 0;
			USETW(req.wLength, 0);

			/* copy in the transfer */

			usbd_copy_in(xfer->frbuffers, 0, &req, sizeof(req));

			/* set length */
			usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
			xfer->nframes = 1;
			USB_BUS_UNLOCK(udev->bus);

			usbd_transfer_submit(xfer);

			USB_BUS_LOCK(udev->bus);
			break;
		}
		ep++;
		to--;
		goto tr_setup;

	default:
		if (error == USB_ERR_CANCELLED)
			break;

		DPRINTF("Clear stall failed.\n");

		/*
		 * Some VMs like VirtualBox always return failure on
		 * clear-stall which we sometimes should just ignore.
		 */
		if (usb_no_cs_fail)
			goto tr_transferred;
		if (udev->clear_stall_errors == USB_CS_RESET_LIMIT)
			goto tr_setup;

		if (error == USB_ERR_TIMEOUT) {
			udev->clear_stall_errors = USB_CS_RESET_LIMIT;
			DPRINTF("Trying to re-enumerate.\n");
			usbd_start_re_enumerate(udev);
		} else {
			udev->clear_stall_errors++;
			if (udev->clear_stall_errors == USB_CS_RESET_LIMIT) {
				DPRINTF("Trying to re-enumerate.\n");
				usbd_start_re_enumerate(udev);
			}
		}
		goto tr_setup;
	}

	/* store current endpoint */
	udev->ep_curr = ep;
	USB_BUS_UNLOCK(udev->bus);
}
/*------------------------------------------------------------------------*
 *	usb_do_clear_stall_callback
 *
 * This function is the USB callback for generic clear stall requests.
 *------------------------------------------------------------------------*/
usb_do_clear_stall_callback
This function is the USB callback for generic clear stall requests.
usb_do_clear_stall_callback This function is the USB callback for generic clear stall requests .
void
usb_do_clear_stall_callback(struct usb_xfer *xfer, usb_error_t error)
{
	struct usb_device_request req;
	struct usb_device *udev;
	struct usb_endpoint *ep;
	struct usb_endpoint *ep_end;
	struct usb_endpoint *ep_first;
	uint8_t to;
	udev = xfer->xroot->udev;
	USB_BUS_LOCK(udev->bus);
	ep = udev->ep_curr;
	ep_end = udev->endpoints + udev->endpoints_max;
	ep_first = udev->endpoints;
	to = udev->endpoints_max;
	switch (USB_GET_STATE(xfer)) {
	case USB_ST_TRANSFERRED:
tr_transferred:
		udev->clear_stall_errors = 0;
		if (ep == NULL)
			goto tr_setup;		
		if (ep->edesc &&
		    ep->is_stalled) {
			ep->toggle_next = 0;
			ep->is_stalled = 0;
			usbd_clear_stall_locked(udev, ep);
			usb_command_wrapper(&ep->endpoint_q,
			    ep->endpoint_q.curr);
		}
		ep++;
	case USB_ST_SETUP:
tr_setup:
		if (to == 0)
			break;			
		if ((ep < ep_first) || (ep >= ep_end))
			ep = ep_first;	
		if (ep->edesc &&
		    ep->is_stalled) {
			req.bmRequestType = UT_WRITE_ENDPOINT;
			req.bRequest = UR_CLEAR_FEATURE;
			USETW(req.wValue, UF_ENDPOINT_HALT);
			req.wIndex[0] = ep->edesc->bEndpointAddress;
			req.wIndex[1] = 0;
			USETW(req.wLength, 0);
			usbd_copy_in(xfer->frbuffers, 0, &req, sizeof(req));
			usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
			xfer->nframes = 1;
			USB_BUS_UNLOCK(udev->bus);
			usbd_transfer_submit(xfer);
			USB_BUS_LOCK(udev->bus);
			break;
		}
		ep++;
		to--;
		goto tr_setup;
	default:
		if (error == USB_ERR_CANCELLED)
			break;
		DPRINTF("Clear stall failed.\n");
		if (usb_no_cs_fail)
			goto tr_transferred;
		if (udev->clear_stall_errors == USB_CS_RESET_LIMIT)
			goto tr_setup;
		if (error == USB_ERR_TIMEOUT) {
			udev->clear_stall_errors = USB_CS_RESET_LIMIT;
			DPRINTF("Trying to re-enumerate.\n");
			usbd_start_re_enumerate(udev);
		} else {
			udev->clear_stall_errors++;
			if (udev->clear_stall_errors == USB_CS_RESET_LIMIT) {
				DPRINTF("Trying to re-enumerate.\n");
				usbd_start_re_enumerate(udev);
			}
		}
		goto tr_setup;
	}
	udev->ep_curr = ep;
	USB_BUS_UNLOCK(udev->bus);
}
void usb_do_clear_stall_callback ( struct usb_xfer * xfer , usb_error_t error ) { struct usb_device_request req ; struct usb_device * udev ; struct usb_endpoint * ep ; struct usb_endpoint * ep_end ; struct usb_endpoint * ep_first ; uint8_t to ; udev = xfer -> xroot -> udev ; USB_BUS_LOCK ( udev -> bus ) ; ep = udev -> ep_curr ; ep_end = udev -> endpoints + udev -> endpoints_max ; ep_first = udev -> endpoints ; to = udev -> endpoints_max ; switch ( USB_GET_STATE ( xfer ) ) { case USB_ST_TRANSFERRED : tr_transferred : udev -> clear_stall_errors = 0 ; if ( ep == NULL ) goto tr_setup ; if ( ep -> edesc && ep -> is_stalled ) { ep -> toggle_next = 0 ; ep -> is_stalled = 0 ; usbd_clear_stall_locked ( udev , ep ) ; usb_command_wrapper ( & ep -> endpoint_q , ep -> endpoint_q . curr ) ; } ep ++ ; case USB_ST_SETUP : tr_setup : if ( to == 0 ) break ; if ( ( ep < ep_first ) || ( ep >= ep_end ) ) ep = ep_first ; if ( ep -> edesc && ep -> is_stalled ) { req . bmRequestType = UT_WRITE_ENDPOINT ; req . bRequest = UR_CLEAR_FEATURE ; USETW ( req . wValue , UF_ENDPOINT_HALT ) ; req . wIndex [ 0 ] = ep -> edesc -> bEndpointAddress ; req . wIndex [ 1 ] = 0 ; USETW ( req . wLength , 0 ) ; usbd_copy_in ( xfer -> frbuffers , 0 , & req , sizeof ( req ) ) ; usbd_xfer_set_frame_len ( xfer , 0 , sizeof ( req ) ) ; xfer -> nframes = 1 ; USB_BUS_UNLOCK ( udev -> bus ) ; usbd_transfer_submit ( xfer ) ; USB_BUS_LOCK ( udev -> bus ) ; break ; } ep ++ ; to -- ; goto tr_setup ; default : if ( error == USB_ERR_CANCELLED ) break ; DPRINTF ( " \n " ) ; if ( usb_no_cs_fail ) goto tr_transferred ; if ( udev -> clear_stall_errors == USB_CS_RESET_LIMIT ) goto tr_setup ; if ( error == USB_ERR_TIMEOUT ) { udev -> clear_stall_errors = USB_CS_RESET_LIMIT ; DPRINTF ( " \n " ) ; usbd_start_re_enumerate ( udev ) ; } else { udev -> clear_stall_errors ++ ; if ( udev -> clear_stall_errors == USB_CS_RESET_LIMIT ) { DPRINTF ( " \n " ) ; usbd_start_re_enumerate ( udev ) ; } } goto tr_setup ; } udev -> ep_curr = ep ; USB_BUS_UNLOCK ( udev -> bus ) ; }
usb_do_clear_stall_callback
 This function is the USB callback for generic clear stall requests.
usb_do_clear_stall_callback This function is the USB callback for generic clear stall requests .
/* round robin endpoint clear stall */ /* reset error counter */ /* device was unconfigured */ /* some hardware needs a callback to clear the data toggle */ /* start up the current or next transfer, if any */ /* no endpoints - nothing to do */ /* endpoint wrapped around */ /* setup a clear-stall packet */ /* copy in the transfer */ /* set length */ /*
		 * Some VMs like VirtualBox always return failure on
		 * clear-stall which we sometimes should just ignore.
		 */ /* store current endpoint */