diff options
Diffstat (limited to 'drivers/usb/gadget/f_uac2.c')
-rw-r--r-- | drivers/usb/gadget/f_uac2.c | 222 |
1 files changed, 75 insertions, 147 deletions
diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index d3c6cffccb72..d7da258fa3f6 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c @@ -50,13 +50,6 @@ static int c_ssize = 2; module_param(c_ssize, uint, S_IRUGO); MODULE_PARM_DESC(c_ssize, "Capture Sample Size(bytes)"); -#define DMA_ADDR_INVALID (~(dma_addr_t)0) - -#define ALT_SET(x, a) do {(x) &= ~0xff; (x) |= (a); } while (0) -#define ALT_GET(x) ((x) & 0xff) -#define INTF_SET(x, i) do {(x) &= 0xff; (x) |= ((i) << 8); } while (0) -#define INTF_GET(x) ((x >> 8) & 0xff) - /* Keep everyone on toes */ #define USB_XFERS 2 @@ -144,8 +137,9 @@ static struct snd_pcm_hardware uac2_pcm_hardware = { }; struct audio_dev { - /* Currently active {Interface[15:8] | AltSettings[7:0]} */ - __u16 ac_alt, as_out_alt, as_in_alt; + u8 ac_intf, ac_alt; + u8 as_out_intf, as_out_alt; + u8 as_in_intf, as_in_alt; struct usb_ep *in_ep, *out_ep; struct usb_function func; @@ -408,7 +402,7 @@ static struct snd_pcm_ops uac2_pcm_ops = { .prepare = uac2_pcm_null, }; -static int __devinit snd_uac2_probe(struct platform_device *pdev) +static int snd_uac2_probe(struct platform_device *pdev) { struct snd_uac2_chip *uac2 = pdev_to_uac2(pdev); struct snd_card *card; @@ -526,32 +520,22 @@ enum { STR_AS_IN_ALT1, }; -static const char ifassoc[] = "Source/Sink"; -static const char ifctrl[] = "Topology Control"; static char clksrc_in[8]; static char clksrc_out[8]; -static const char usb_it[] = "USBH Out"; -static const char io_it[] = "USBD Out"; -static const char usb_ot[] = "USBH In"; -static const char io_ot[] = "USBD In"; -static const char out_alt0[] = "Playback Inactive"; -static const char out_alt1[] = "Playback Active"; -static const char in_alt0[] = "Capture Inactive"; -static const char in_alt1[] = "Capture Active"; static struct usb_string strings_fn[] = { - [STR_ASSOC].s = ifassoc, - [STR_IF_CTRL].s = ifctrl, + [STR_ASSOC].s = "Source/Sink", + [STR_IF_CTRL].s = "Topology Control", [STR_CLKSRC_IN].s = clksrc_in, [STR_CLKSRC_OUT].s = clksrc_out, - [STR_USB_IT].s = usb_it, - [STR_IO_IT].s = io_it, - [STR_USB_OT].s = usb_ot, - [STR_IO_OT].s = io_ot, - [STR_AS_OUT_ALT0].s = out_alt0, - [STR_AS_OUT_ALT1].s = out_alt1, - [STR_AS_IN_ALT0].s = in_alt0, - [STR_AS_IN_ALT1].s = in_alt1, + [STR_USB_IT].s = "USBH Out", + [STR_IO_IT].s = "USBD Out", + [STR_USB_OT].s = "USBH In", + [STR_IO_OT].s = "USBD In", + [STR_AS_OUT_ALT0].s = "Playback Inactive", + [STR_AS_OUT_ALT1].s = "Playback Active", + [STR_AS_IN_ALT0].s = "Capture Inactive", + [STR_AS_IN_ALT1].s = "Capture Active", { }, }; @@ -952,8 +936,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) return ret; } std_ac_if_desc.bInterfaceNumber = ret; - ALT_SET(agdev->ac_alt, 0); - INTF_SET(agdev->ac_alt, ret); + agdev->ac_intf = ret; + agdev->ac_alt = 0; ret = usb_interface_id(cfg, fn); if (ret < 0) { @@ -963,8 +947,8 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) } std_as_out_if0_desc.bInterfaceNumber = ret; std_as_out_if1_desc.bInterfaceNumber = ret; - ALT_SET(agdev->as_out_alt, 0); - INTF_SET(agdev->as_out_alt, ret); + agdev->as_out_intf = ret; + agdev->as_out_alt = 0; ret = usb_interface_id(cfg, fn); if (ret < 0) { @@ -974,19 +958,23 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) } std_as_in_if0_desc.bInterfaceNumber = ret; std_as_in_if1_desc.bInterfaceNumber = ret; - ALT_SET(agdev->as_in_alt, 0); - INTF_SET(agdev->as_in_alt, ret); + agdev->as_in_intf = ret; + agdev->as_in_alt = 0; agdev->out_ep = usb_ep_autoconfig(gadget, &fs_epout_desc); - if (!agdev->out_ep) + if (!agdev->out_ep) { dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); + goto err; + } agdev->out_ep->driver_data = agdev; agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); - if (!agdev->in_ep) + if (!agdev->in_ep) { dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); + goto err; + } agdev->in_ep->driver_data = agdev; hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; @@ -994,9 +982,9 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; hs_epin_desc.wMaxPacketSize = fs_epin_desc.wMaxPacketSize; - fn->descriptors = usb_copy_descriptors(fs_audio_desc); - if (gadget_is_dualspeed(gadget)) - fn->hs_descriptors = usb_copy_descriptors(hs_audio_desc); + ret = usb_assign_descriptors(fn, fs_audio_desc, hs_audio_desc, NULL); + if (ret) + goto err; prm = &agdev->uac2.c_prm; prm->max_psize = hs_epout_desc.wMaxPacketSize; @@ -1005,6 +993,7 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) prm->max_psize = 0; dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); + goto err; } prm = &agdev->uac2.p_prm; @@ -1014,17 +1003,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) prm->max_psize = 0; dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); + goto err; } - return alsa_uac2_init(agdev); + ret = alsa_uac2_init(agdev); + if (ret) + goto err; + return 0; +err: + kfree(agdev->uac2.p_prm.rbuf); + kfree(agdev->uac2.c_prm.rbuf); + usb_free_all_descriptors(fn); + if (agdev->in_ep) + agdev->in_ep->driver_data = NULL; + if (agdev->out_ep) + agdev->out_ep->driver_data = NULL; + return -EINVAL; } static void afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) { struct audio_dev *agdev = func_to_agdev(fn); - struct usb_composite_dev *cdev = cfg->cdev; - struct usb_gadget *gadget = cdev->gadget; struct uac2_rtd_params *prm; alsa_uac2_exit(agdev); @@ -1034,10 +1034,7 @@ afunc_unbind(struct usb_configuration *cfg, struct usb_function *fn) prm = &agdev->uac2.c_prm; kfree(prm->rbuf); - - if (gadget_is_dualspeed(gadget)) - usb_free_descriptors(fn->hs_descriptors); - usb_free_descriptors(fn->descriptors); + usb_free_all_descriptors(fn); if (agdev->in_ep) agdev->in_ep->driver_data = NULL; @@ -1064,7 +1061,7 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) return -EINVAL; } - if (intf == INTF_GET(agdev->ac_alt)) { + if (intf == agdev->ac_intf) { /* Control I/f has only 1 AltSetting - 0 */ if (alt) { dev_err(&uac2->pdev.dev, @@ -1074,16 +1071,16 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) return 0; } - if (intf == INTF_GET(agdev->as_out_alt)) { + if (intf == agdev->as_out_intf) { ep = agdev->out_ep; prm = &uac2->c_prm; config_ep_by_speed(gadget, fn, ep); - ALT_SET(agdev->as_out_alt, alt); - } else if (intf == INTF_GET(agdev->as_in_alt)) { + agdev->as_out_alt = alt; + } else if (intf == agdev->as_in_intf) { ep = agdev->in_ep; prm = &uac2->p_prm; config_ep_by_speed(gadget, fn, ep); - ALT_SET(agdev->as_in_alt, alt); + agdev->as_in_alt = alt; } else { dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); @@ -1117,7 +1114,6 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) prm->ureq[i].pp = prm; req->zero = 0; - req->dma = DMA_ADDR_INVALID; req->context = &prm->ureq[i]; req->length = prm->max_psize; req->complete = agdev_iso_complete; @@ -1136,12 +1132,12 @@ afunc_get_alt(struct usb_function *fn, unsigned intf) struct audio_dev *agdev = func_to_agdev(fn); struct snd_uac2_chip *uac2 = &agdev->uac2; - if (intf == INTF_GET(agdev->ac_alt)) - return ALT_GET(agdev->ac_alt); - else if (intf == INTF_GET(agdev->as_out_alt)) - return ALT_GET(agdev->as_out_alt); - else if (intf == INTF_GET(agdev->as_in_alt)) - return ALT_GET(agdev->as_in_alt); + if (intf == agdev->ac_intf) + return agdev->ac_alt; + else if (intf == agdev->as_out_intf) + return agdev->as_out_alt; + else if (intf == agdev->as_in_intf) + return agdev->as_in_alt; else dev_err(&uac2->pdev.dev, "%s:%d Invalid Interface %d!\n", @@ -1157,10 +1153,10 @@ afunc_disable(struct usb_function *fn) struct snd_uac2_chip *uac2 = &agdev->uac2; free_ep(&uac2->p_prm, agdev->in_ep); - ALT_SET(agdev->as_in_alt, 0); + agdev->as_in_alt = 0; free_ep(&uac2->c_prm, agdev->out_ep); - ALT_SET(agdev->as_out_alt, 0); + agdev->as_out_alt = 0; } static int @@ -1267,7 +1263,7 @@ setup_rq_inf(struct usb_function *fn, const struct usb_ctrlrequest *cr) u16 w_index = le16_to_cpu(cr->wIndex); u8 intf = w_index & 0xff; - if (intf != INTF_GET(agdev->ac_alt)) { + if (intf != agdev->ac_intf) { dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); return -EOPNOTSUPP; @@ -1316,7 +1312,7 @@ afunc_setup(struct usb_function *fn, const struct usb_ctrlrequest *cr) static int audio_bind_config(struct usb_configuration *cfg) { - int id, res; + int res; agdev_g = kzalloc(sizeof *agdev_g, GFP_KERNEL); if (agdev_g == NULL) { @@ -1324,89 +1320,21 @@ static int audio_bind_config(struct usb_configuration *cfg) return -ENOMEM; } - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_ASSOC].id = id; - iad_desc.iFunction = id, - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_IF_CTRL].id = id; - std_ac_if_desc.iInterface = id, - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_CLKSRC_IN].id = id; - in_clk_src_desc.iClockSource = id, - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_CLKSRC_OUT].id = id; - out_clk_src_desc.iClockSource = id, - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_USB_IT].id = id; - usb_out_it_desc.iTerminal = id, - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_IO_IT].id = id; - io_in_it_desc.iTerminal = id; - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_USB_OT].id = id; - usb_in_ot_desc.iTerminal = id; - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_IO_OT].id = id; - io_out_ot_desc.iTerminal = id; - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_AS_OUT_ALT0].id = id; - std_as_out_if0_desc.iInterface = id; - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_AS_OUT_ALT1].id = id; - std_as_out_if1_desc.iInterface = id; - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_AS_IN_ALT0].id = id; - std_as_in_if0_desc.iInterface = id; - - id = usb_string_id(cfg->cdev); - if (id < 0) - return id; - - strings_fn[STR_AS_IN_ALT1].id = id; - std_as_in_if1_desc.iInterface = id; + res = usb_string_ids_tab(cfg->cdev, strings_fn); + if (res) + return res; + iad_desc.iFunction = strings_fn[STR_ASSOC].id; + std_ac_if_desc.iInterface = strings_fn[STR_IF_CTRL].id; + in_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_IN].id; + out_clk_src_desc.iClockSource = strings_fn[STR_CLKSRC_OUT].id; + usb_out_it_desc.iTerminal = strings_fn[STR_USB_IT].id; + io_in_it_desc.iTerminal = strings_fn[STR_IO_IT].id; + usb_in_ot_desc.iTerminal = strings_fn[STR_USB_OT].id; + io_out_ot_desc.iTerminal = strings_fn[STR_IO_OT].id; + std_as_out_if0_desc.iInterface = strings_fn[STR_AS_OUT_ALT0].id; + std_as_out_if1_desc.iInterface = strings_fn[STR_AS_OUT_ALT1].id; + std_as_in_if0_desc.iInterface = strings_fn[STR_AS_IN_ALT0].id; + std_as_in_if1_desc.iInterface = strings_fn[STR_AS_IN_ALT1].id; agdev_g->func.name = "uac2_func"; agdev_g->func.strings = fn_strings; |