Skip to content

Commit

Permalink
USB audio gadget: handle endpoint control requests at the function level
Browse files Browse the repository at this point in the history
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@ideasonboard.com>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Laurent Pinchart authored and Greg Kroah-Hartman committed Dec 11, 2009
1 parent 5242658 commit 0ad7252
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 117 deletions.
115 changes: 0 additions & 115 deletions drivers/usb/gadget/audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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,
Expand Down
76 changes: 74 additions & 2 deletions drivers/usb/gadget/f_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -455,8 +519,8 @@ 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
* Audio class messages; interface activation uses set_alt().
/* composite driver infrastructure handles everything; interface
* activation uses set_alt().
*/
switch (ctrl->bRequestType) {
case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE:
Expand All @@ -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,
Expand Down

0 comments on commit 0ad7252

Please sign in to comment.