/*------------------------------------------------------------------------*
 *	usb_handle_request_callback
 *
 * This function is the USB callback for generic USB Device control
 * transfers.
 *------------------------------------------------------------------------*/
void
usb_handle_request_callback(struct usb_xfer *xfer, usb_error_t error)
{
	usb_error_t err;

	/* check the current transfer state */

	switch (USB_GET_STATE(xfer)) {
	case USB_ST_SETUP:
	case USB_ST_TRANSFERRED:

		/* handle the request */
		err = usb_handle_request(xfer);

		if (err) {

			if (err == USB_ERR_BAD_CONTEXT) {
				/* we need to re-setup the control transfer */
				usb_needs_explore(xfer->xroot->bus, 0);
				break;
			}
			goto tr_restart;
		}
		usbd_transfer_submit(xfer);
		break;

	default:
		/* check if a control transfer is active */
		if (xfer->flags_int.control_rem != 0xFFFF) {
			/* handle the request */
			err = usb_handle_request(xfer);
		}
		if (xfer->error != USB_ERR_CANCELLED) {
			/* should not happen - try stalling */
			goto tr_restart;
		}
		break;
	}
	return;

tr_restart:
	/*
	 * If a control transfer is active, stall it, and wait for the
	 * next control transfer.
	 */
	usbd_xfer_set_frame_len(xfer, 0, sizeof(struct usb_device_request));
	xfer->nframes = 1;
	xfer->flags.manual_status = 1;
	xfer->flags.force_short_xfer = 0;
	usbd_xfer_set_stall(xfer);	/* cancel previous transfer, if any */
	usbd_transfer_submit(xfer);
}
Exemplo n.º 2
0
void usb_rx_request_write_call(struct usb_manager_binding *binding,
        uint8_t *request, size_t req_length, uint8_t *data, size_t data_length)
{
    USB_DEBUG_TR_ENTER;

    USB_DEBUG_IDC("received usb_rx_request_call() of %i bytes\n", data_length);

    struct usb_device_request *req = (struct usb_device_request *) request;

    /* check if we have received the correct amount of data */
    if ((req_length != sizeof(struct usb_device_request))
            || (req->wLength != data_length)) {
        USB_DEBUG_IDC("ERROR in usb_rx_request_call(): received too less data"
                " to full fill the request:\n "
                "request length: expected %i bytes, was %i\n"
                "data length: expected %i, was %i\n",
                sizeof(struct usb_device_request), req_length, req->wLength,
                data_length);

        usb_request_send_error(USB_ERR_INVAL, binding,
                usb_tx_request_write_response);
    }

    /* execute request and prepare reply */

    struct usb_request_state *st = malloc(sizeof(struct usb_request_state));

    if (st == NULL) {
        USB_DEBUG_IDC("WARNING: usb_rx_request_write_call(): out of memory\b");

        usb_request_send_error(USB_ERR_NOMEM, binding,
                usb_tx_request_write_response);

        return;
    }

    /* fill in the struct */

    st->bind = binding;
    st->req = req;
    /* write requests have no data to return */
    st->data_length = data_length;
    st->data = data;
    st->callback = usb_tx_request_write_response;

    struct usb_device *device = (struct usb_device *) binding->st;

    usb_handle_request(device, 0, req, st, st->data, &st->data_length);

}
Exemplo n.º 3
0
void usb_rx_request_read_call(struct usb_manager_binding *binding,
        uint8_t *request, size_t req_length)
{
    USB_DEBUG_TR_ENTER;

    USB_DEBUG_IDC("received usb_rx_request_read_call()\n");

    // check if we have received the correct amount of data
    if (req_length != sizeof(struct usb_device_request)) {
        USB_DEBUG_IDC("received too less data to fullfill the request:\n "
                "request length: expected %i bytes, was %i\n",
                sizeof(struct usb_device_request), req_length);

        usb_request_send_error(USB_ERR_INVAL, binding,
                usb_tx_request_read_response);
    }

    /*
     * execute request and prepare reply
     */
    struct usb_request_state *st = malloc(sizeof(struct usb_request_state));

    struct usb_device *device = (struct usb_device *) binding->st;
    struct usb_device_request *req = (struct usb_device_request *) request;
    st->req = req;
    st->bind = binding;
    st->data_length = 0;
    if (req->wLength > 0) {
        st->data = malloc(req->wLength);
    } else {
        /* XXX: Just allocating some memory, note this may not be enough */
        st->data = malloc(1024);
        req->wLength = 1024;  // setting the maximum data length
    }

    st->callback = usb_tx_request_read_response;

    usb_handle_request(device, 0, req, st, st->data, &st->data_length);
}
Exemplo n.º 4
0
usb_error_t usb_exec_request(struct usb_device *device, uint16_t flags,
        struct usb_device_request *request, void *data, uint16_t *ret_length)
{
    return (usb_handle_request(device, flags, request, NULL, data, ret_length));
}