Now that control requests targeted at an endpoint can be handled at the function level, move the UAC-specific control request handling code from the audio gadget driver to the audio function driver. Signed-off-by: Laurent Pinchart <laurent.pinchart@xxxxxxxxx> --- drivers/usb/gadget/audio.c | 115 ------------------------------------------ drivers/usb/gadget/f_audio.c | 76 +++++++++++++++++++++++++++- 2 files changed, 75 insertions(+), 116 deletions(-) diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index a3a0f4a..58f2203 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -89,120 +89,6 @@ static const struct usb_descriptor_header *otg_desc[] = { /*-------------------------------------------------------------------------*/ -/** - * Handle USB audio endpoint set/get command in setup class request - */ - -static int audio_set_endpoint_req(struct usb_configuration *c, - const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = c->cdev; - int value = -EOPNOTSUPP; - u16 ep = le16_to_cpu(ctrl->wIndex); - u16 len = le16_to_cpu(ctrl->wLength); - u16 w_value = le16_to_cpu(ctrl->wValue); - - DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", - ctrl->bRequest, w_value, len, ep); - - switch (ctrl->bRequest) { - case UAC_SET_CUR: - value = 0; - break; - - case UAC_SET_MIN: - break; - - case UAC_SET_MAX: - break; - - case UAC_SET_RES: - break; - - case UAC_SET_MEM: - break; - - default: - break; - } - - return value; -} - -static int audio_get_endpoint_req(struct usb_configuration *c, - const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = c->cdev; - int value = -EOPNOTSUPP; - u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); - u16 len = le16_to_cpu(ctrl->wLength); - u16 w_value = le16_to_cpu(ctrl->wValue); - - DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", - ctrl->bRequest, w_value, len, ep); - - switch (ctrl->bRequest) { - case UAC_GET_CUR: - case UAC_GET_MIN: - case UAC_GET_MAX: - case UAC_GET_RES: - value = 3; - break; - case UAC_GET_MEM: - break; - default: - break; - } - - return value; -} - -static int -audio_setup(struct usb_configuration *c, const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = c->cdev; - struct usb_request *req = 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 - * Audio class messages; interface activation uses set_alt(). - */ - switch (ctrl->bRequestType) { - case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: - value = audio_set_endpoint_req(c, ctrl); - break; - - case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: - value = audio_get_endpoint_req(c, ctrl); - break; - - default: - ERROR(cdev, "Invalid 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) { - DBG(cdev, "Audio 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(cdev->gadget->ep0, req, GFP_ATOMIC); - if (value < 0) - ERROR(cdev, "Audio response on err %d\n", value); - } - - /* device either stalls (value < 0) or reports success */ - return value; -} - -/*-------------------------------------------------------------------------*/ - static int __init audio_do_config(struct usb_configuration *c) { /* FIXME alloc iConfiguration string, set it in c->strings */ @@ -220,7 +106,6 @@ static int __init audio_do_config(struct usb_configuration *c) static struct usb_configuration audio_config_driver = { .label = DRIVER_DESC, .bind = audio_do_config, - .setup = audio_setup, .bConfigurationValue = 1, /* .iConfiguration = DYNAMIC */ .bmAttributes = USB_CONFIG_ATT_SELFPOWER, diff --git a/drivers/usb/gadget/f_audio.c b/drivers/usb/gadget/f_audio.c index 98e9bb9..a55d0e0 100644 --- a/drivers/usb/gadget/f_audio.c +++ b/drivers/usb/gadget/f_audio.c @@ -445,6 +445,70 @@ static int audio_get_intf_req(struct usb_function *f, return len; } +static int audio_set_endpoint_req(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev = f->config->cdev; + int value = -EOPNOTSUPP; + u16 ep = le16_to_cpu(ctrl->wIndex); + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + + DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", + ctrl->bRequest, w_value, len, ep); + + switch (ctrl->bRequest) { + case UAC_SET_CUR: + value = 0; + break; + + case UAC_SET_MIN: + break; + + case UAC_SET_MAX: + break; + + case UAC_SET_RES: + break; + + case UAC_SET_MEM: + break; + + default: + break; + } + + return value; +} + +static int audio_get_endpoint_req(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev = f->config->cdev; + int value = -EOPNOTSUPP; + u8 ep = ((le16_to_cpu(ctrl->wIndex) >> 8) & 0xFF); + u16 len = le16_to_cpu(ctrl->wLength); + u16 w_value = le16_to_cpu(ctrl->wValue); + + DBG(cdev, "bRequest 0x%x, w_value 0x%04x, len %d, endpoint %d\n", + ctrl->bRequest, w_value, len, ep); + + switch (ctrl->bRequest) { + case UAC_GET_CUR: + case UAC_GET_MIN: + case UAC_GET_MAX: + case UAC_GET_RES: + value = 3; + break; + case UAC_GET_MEM: + break; + default: + break; + } + + return value; +} + static int f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) { @@ -455,7 +519,7 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); - /* composite driver infrastructure handles everything except + /* composite driver infrastructure handles everything; * Audio class messages; interface activation uses set_alt(). */ switch (ctrl->bRequestType) { @@ -467,6 +531,14 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) value = audio_get_intf_req(f, ctrl); break; + case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: + value = audio_set_endpoint_req(f, ctrl); + break; + + case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: + value = audio_get_endpoint_req(f, ctrl); + break; + default: ERROR(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, @@ -602,6 +674,7 @@ f_audio_bind(struct usb_configuration *c, struct usb_function *f) goto fail; audio->out_ep = ep; ep->driver_data = cdev; /* claim */ + usb_function_claim_endpoint(f, ep); status = -ENOMEM; @@ -629,6 +702,7 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f) { struct f_audio *audio = func_to_audio(f); + usb_function_release_endpoint(f, audio->out_ep); usb_free_descriptors(f->descriptors); kfree(audio); } -- 1.6.3.3 -- Laurent Pinchart -- 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