This commit adds a new vendor specific request to be handled by the g_zero module in it's sourcesink configuration. The purpose if this request is to update the length of the BULK transfer to a given value. The bRequest value of the new control request is 0x5e. It is used by the user-space Unit testing application for bulk in/out tests. The sourcesink_setup function was moved to be ->setup() of the function and not the configuration. Signed-off-by: Tatyana Brokhman <tlinder@xxxxxxxxxxxxxx> --- drivers/usb/gadget/f_sourcesink.c | 145 +++++++++++++++++++------------------ 1 files changed, 75 insertions(+), 70 deletions(-) diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index caf2f95..ff8840d 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -385,6 +385,80 @@ fail: return result; } +static int sourcesink_setup(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct f_sourcesink *ss = func_to_ss(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = f->config->cdev->req; + int retval = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + switch (ctrl->bRequest) { + /* + * These are the same vendor-specific requests supported by + * Intel's USB 2.0 compliance test devices. We exceed that + * device spec by allowing multiple-packet requests. + * + * NOTE: the Control-OUT data stays in req->buf ... better + * would be copying it into a scratch buffer, so that other + * requests may safely intervene. + */ + case 0x5b: /* control WRITE test -- fill the buffer */ + if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) + goto unknown; + if (w_value || w_index) + break; + /* just read that many bytes into the buffer */ + if (w_length > req->length) + break; + retval = w_length; + break; + case 0x5c: /* control READ test -- return the buffer */ + if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) + goto unknown; + if (w_value || w_index) + break; + /* expect those bytes are still in the buffer; send back */ + if (w_length > req->length) + break; + retval = w_length; + break; + + case 0x5e: + /* + * Change bulk ep buffer size. buflen is the length of + * the BULK transfer (req->length=buflen). Defined in g_zero.h + */ + disable_source_sink(ss); + buflen = w_value; + retval = enable_source_sink(cdev, ss); + break; + default: +unknown: + VDBG(cdev, "unknown control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (retval >= 0) { + VDBG(cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = retval; + retval = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (retval < 0) + ERROR(cdev, "source/sinkc response, err %d\n", retval); + } + + /* device either stalls (value < 0) or reports success */ + return retval; +} + static int sourcesink_set_alt(struct usb_function *f, unsigned intf, unsigned alt) { @@ -421,6 +495,7 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) ss->function.unbind = sourcesink_unbind; ss->function.set_alt = sourcesink_set_alt; ss->function.disable = sourcesink_disable; + ss->function.setup = sourcesink_setup; status = usb_add_function(c, &ss->function); if (status) @@ -428,79 +503,9 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) return status; } -static int sourcesink_setup(struct usb_configuration *c, - const struct usb_ctrlrequest *ctrl) -{ - struct usb_request *req = c->cdev->req; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - - /* composite driver infrastructure handles everything except - * the two control test requests. - */ - switch (ctrl->bRequest) { - - /* - * These are the same vendor-specific requests supported by - * Intel's USB 2.0 compliance test devices. We exceed that - * device spec by allowing multiple-packet requests. - * - * NOTE: the Control-OUT data stays in req->buf ... better - * would be copying it into a scratch buffer, so that other - * requests may safely intervene. - */ - case 0x5b: /* control WRITE test -- fill the buffer */ - if (ctrl->bRequestType != (USB_DIR_OUT|USB_TYPE_VENDOR)) - goto unknown; - if (w_value || w_index) - break; - /* just read that many bytes into the buffer */ - if (w_length > req->length) - break; - value = w_length; - break; - case 0x5c: /* control READ test -- return the buffer */ - if (ctrl->bRequestType != (USB_DIR_IN|USB_TYPE_VENDOR)) - goto unknown; - if (w_value || w_index) - break; - /* expect those bytes are still in the buffer; send back */ - if (w_length > req->length) - break; - value = w_length; - break; - - default: -unknown: - VDBG(c->cdev, - "unknown control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - } - - /* respond with data transfer or status phase? */ - if (value >= 0) { - VDBG(c->cdev, "source/sink req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - req->zero = 0; - req->length = value; - value = usb_ep_queue(c->cdev->gadget->ep0, req, GFP_ATOMIC); - if (value < 0) - ERROR(c->cdev, "source/sinkc response, err %d\n", - value); - } - - /* device either stalls (value < 0) or reports success */ - return value; -} - static struct usb_configuration sourcesink_driver = { .label = "source/sink", .strings = sourcesink_strings, - .setup = sourcesink_setup, .bConfigurationValue = 3, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, /* .iConfiguration = DYNAMIC */ -- 1.7.0.4 -- Sent by an employee of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html