Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755493AbbLKL3p (ORCPT ); Fri, 11 Dec 2015 06:29:45 -0500 Received: from mailout1.samsung.com ([203.254.224.24]:49325 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755377AbbLKL1O (ORCPT ); Fri, 11 Dec 2015 06:27:14 -0500 X-AuditID: cbfee61b-f793c6d00000236c-0a-566ab31147bb From: Robert Baldyga To: balbi@ti.com Cc: gregkh@linuxfoundation.org, andrzej.p@samsung.com, m.szyprowski@samsung.com, b.zolnierkie@samsung.com, linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, Robert Baldyga Subject: [PATCH v3 35/36] usb: gadget: f_uac2: conversion to new API Date: Fri, 11 Dec 2015 12:25:14 +0100 Message-id: <1449833115-24065-36-git-send-email-r.baldyga@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1449833115-24065-1-git-send-email-r.baldyga@samsung.com> References: <1449833115-24065-1-git-send-email-r.baldyga@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprGLMWRmVeSWpSXmKPExsVy+t9jQV3BzVlhBktPqlrMetnOYrFxxnpW i4P36y2aF69ns7i8aw6bxaJlrcwWa4/cZbd4cHgnuwOHx/65a9g9+rasYvQ4fmM7k8fnTXIB LFFcNimpOZllqUX6dglcGcc/nGAqOFtT8XlbUgPj5YwuRk4OCQETiV+t/1khbDGJC/fWs3Ux cnEICcxilLizfSsrhPOTUeLN3slgVWwCOhJbvk9gBLFFBAQk1r+4xA5SxCxwjlHi4Z02sISw gItE459D7CA2i4CqxNZL65lBbF4BN4n7G69DrZOTOHkMYignUHzyyUtgNUICrhJvXq9jnMDI u4CRYRWjRGpBckFxUnquUV5quV5xYm5xaV66XnJ+7iZGcGg9k97BeHiX+yFGAQ5GJR7eBRxZ YUKsiWXFlbmHGCU4mJVEeH9tAArxpiRWVqUW5ccXleakFh9ilOZgURLn3XcpMkxIID2xJDU7 NbUgtQgmy8TBKdXAmP7W+nJjtlagl5jlS8uUkuY3z50DMt+nl+6czj37y6FgoeryUN+gPbX5 m0qVtSP7XO+uenBQPfrVxC3eUhf6U4VXeUvXv1/jqbnSeFWjqtfSJhGhyddaLyuabDI5ser+ 1vCtvCIWPM7Zsrv/7AstFn3FHjXTvWfS1LrwJQ9ZDe/JOXLl1y1XYinOSDTUYi4qTgQAubYB CCkCAAA= Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 15699 Lines: 500 Generate descriptors in new format and attach them to USB function in prep_descs(). Implement prep_vendor_descs() to supply class specific descriptors. Change set_alt() implementation and implement clear_alt() operation. Remove boilerplate code. Signed-off-by: Robert Baldyga --- drivers/usb/gadget/function/f_uac2.c | 345 +++++++++++++---------------------- 1 file changed, 122 insertions(+), 223 deletions(-) diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c index 044ca79..713b452 100644 --- a/drivers/usb/gadget/function/f_uac2.c +++ b/drivers/usb/gadget/function/f_uac2.c @@ -119,10 +119,6 @@ static struct snd_pcm_hardware uac2_pcm_hardware = { }; struct audio_dev { - 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; @@ -880,65 +876,20 @@ static struct uac2_iso_endpoint_descriptor as_iso_in_desc = { .wLockDelay = 0, }; -static struct usb_descriptor_header *fs_audio_desc[] = { - (struct usb_descriptor_header *)&iad_desc, - (struct usb_descriptor_header *)&std_ac_if_desc, - - (struct usb_descriptor_header *)&ac_hdr_desc, - (struct usb_descriptor_header *)&in_clk_src_desc, - (struct usb_descriptor_header *)&out_clk_src_desc, - (struct usb_descriptor_header *)&usb_out_it_desc, - (struct usb_descriptor_header *)&io_in_it_desc, - (struct usb_descriptor_header *)&usb_in_ot_desc, - (struct usb_descriptor_header *)&io_out_ot_desc, - - (struct usb_descriptor_header *)&std_as_out_if0_desc, - (struct usb_descriptor_header *)&std_as_out_if1_desc, - - (struct usb_descriptor_header *)&as_out_hdr_desc, - (struct usb_descriptor_header *)&as_out_fmt1_desc, - (struct usb_descriptor_header *)&fs_epout_desc, - (struct usb_descriptor_header *)&as_iso_out_desc, - - (struct usb_descriptor_header *)&std_as_in_if0_desc, - (struct usb_descriptor_header *)&std_as_in_if1_desc, - - (struct usb_descriptor_header *)&as_in_hdr_desc, - (struct usb_descriptor_header *)&as_in_fmt1_desc, - (struct usb_descriptor_header *)&fs_epin_desc, - (struct usb_descriptor_header *)&as_iso_in_desc, - NULL, -}; +USB_COMPOSITE_ENDPOINT(ep_out, &fs_epout_desc, &hs_epout_desc, NULL, NULL); +USB_COMPOSITE_ENDPOINT(ep_in, &fs_epin_desc, &hs_epin_desc, NULL, NULL); -static struct usb_descriptor_header *hs_audio_desc[] = { - (struct usb_descriptor_header *)&iad_desc, - (struct usb_descriptor_header *)&std_ac_if_desc, - - (struct usb_descriptor_header *)&ac_hdr_desc, - (struct usb_descriptor_header *)&in_clk_src_desc, - (struct usb_descriptor_header *)&out_clk_src_desc, - (struct usb_descriptor_header *)&usb_out_it_desc, - (struct usb_descriptor_header *)&io_in_it_desc, - (struct usb_descriptor_header *)&usb_in_ot_desc, - (struct usb_descriptor_header *)&io_out_ot_desc, - - (struct usb_descriptor_header *)&std_as_out_if0_desc, - (struct usb_descriptor_header *)&std_as_out_if1_desc, - - (struct usb_descriptor_header *)&as_out_hdr_desc, - (struct usb_descriptor_header *)&as_out_fmt1_desc, - (struct usb_descriptor_header *)&hs_epout_desc, - (struct usb_descriptor_header *)&as_iso_out_desc, - - (struct usb_descriptor_header *)&std_as_in_if0_desc, - (struct usb_descriptor_header *)&std_as_in_if1_desc, - - (struct usb_descriptor_header *)&as_in_hdr_desc, - (struct usb_descriptor_header *)&as_in_fmt1_desc, - (struct usb_descriptor_header *)&hs_epin_desc, - (struct usb_descriptor_header *)&as_iso_in_desc, - NULL, -}; +USB_COMPOSITE_ALTSETTING(intf0alt0, &std_ac_if_desc); +USB_COMPOSITE_ALTSETTING(intf1alt0, &std_as_out_if0_desc); +USB_COMPOSITE_ALTSETTING(intf1alt1, &std_as_out_if1_desc, &ep_out); +USB_COMPOSITE_ALTSETTING(intf2alt0, &std_as_in_if0_desc); +USB_COMPOSITE_ALTSETTING(intf2alt1, &std_as_in_if1_desc, &ep_in); + +USB_COMPOSITE_INTERFACE(intf0, &intf0alt0); +USB_COMPOSITE_INTERFACE(intf1, &intf1alt0, &intf1alt1); +USB_COMPOSITE_INTERFACE(intf2, &intf2alt0, &intf2alt1); + +USB_COMPOSITE_DESCRIPTORS(uac2_descs, &intf0, &intf1, &intf2); struct cntrl_cur_lay3 { __u32 dCUR; @@ -998,18 +949,13 @@ static void set_ep_max_packet_size(const struct f_uac2_opts *uac2_opts, le16_to_cpu(ep_desc->wMaxPacketSize))); } -static int -afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) +static int afunc_prep_descs(struct usb_function *fn) { struct audio_dev *agdev = func_to_agdev(fn); - struct snd_uac2_chip *uac2 = &agdev->uac2; - struct usb_composite_dev *cdev = cfg->cdev; - struct usb_gadget *gadget = cdev->gadget; - struct device *dev = &uac2->pdev.dev; + struct usb_composite_dev *cdev = fn->config->cdev; struct uac2_rtd_params *prm; struct f_uac2_opts *uac2_opts; struct usb_string *us; - int ret; uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); @@ -1029,6 +975,28 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) std_as_in_if0_desc.iInterface = us[STR_AS_IN_ALT0].id; std_as_in_if1_desc.iInterface = us[STR_AS_IN_ALT1].id; + /* Calculate wMaxPacketSize according to audio bandwidth */ + set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true); + set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false); + set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true); + set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false); + + prm = &agdev->uac2.c_prm; + prm->max_psize = hs_epout_desc.wMaxPacketSize; + + prm = &agdev->uac2.p_prm; + prm->max_psize = hs_epin_desc.wMaxPacketSize; + + return usb_function_set_descs(fn, &uac2_descs); +} + +static int afunc_prep_vendor_descs(struct usb_function *fn) +{ + struct audio_dev *agdev = func_to_agdev(fn); + struct f_uac2_opts *uac2_opts; + int ret; + + uac2_opts = container_of(fn->fi, struct f_uac2_opts, func_inst); /* Initialize the configurable parameters */ usb_out_it_desc.bNrChannels = num_channels(uac2_opts->c_chmask); @@ -1047,135 +1015,78 @@ afunc_bind(struct usb_configuration *cfg, struct usb_function *fn) snprintf(clksrc_in, sizeof(clksrc_in), "%uHz", uac2_opts->p_srate); snprintf(clksrc_out, sizeof(clksrc_out), "%uHz", uac2_opts->c_srate); - ret = usb_interface_id(cfg, fn); - if (ret < 0) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return ret; - } - std_ac_if_desc.bInterfaceNumber = ret; - agdev->ac_intf = ret; - agdev->ac_alt = 0; - - ret = usb_interface_id(cfg, fn); - if (ret < 0) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return ret; - } - std_as_out_if0_desc.bInterfaceNumber = ret; - std_as_out_if1_desc.bInterfaceNumber = ret; - agdev->as_out_intf = ret; - agdev->as_out_alt = 0; - - ret = usb_interface_id(cfg, fn); - if (ret < 0) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return ret; - } - std_as_in_if0_desc.bInterfaceNumber = ret; - std_as_in_if1_desc.bInterfaceNumber = 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) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - goto err; - } - - agdev->in_ep = usb_ep_autoconfig(gadget, &fs_epin_desc); - if (!agdev->in_ep) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - goto err; - } - - uac2->p_prm.uac2 = uac2; - uac2->c_prm.uac2 = uac2; - - /* Calculate wMaxPacketSize according to audio bandwidth */ - set_ep_max_packet_size(uac2_opts, &fs_epin_desc, 1000, true); - set_ep_max_packet_size(uac2_opts, &fs_epout_desc, 1000, false); - set_ep_max_packet_size(uac2_opts, &hs_epin_desc, 8000, true); - set_ep_max_packet_size(uac2_opts, &hs_epout_desc, 8000, false); - - hs_epout_desc.bEndpointAddress = fs_epout_desc.bEndpointAddress; - hs_epin_desc.bEndpointAddress = fs_epin_desc.bEndpointAddress; - - 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; - prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); - if (!prm->rbuf) { - prm->max_psize = 0; - goto err_free_descs; - } - - prm = &agdev->uac2.p_prm; - prm->max_psize = hs_epin_desc.wMaxPacketSize; - prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); - if (!prm->rbuf) { - prm->max_psize = 0; - goto err_free_descs; - } + usb_function_add_vendor_desc(fn, + (struct usb_descriptor_header *)&iad_desc); + + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&ac_hdr_desc); + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&in_clk_src_desc); + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&out_clk_src_desc); + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&usb_out_it_desc); + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&io_in_it_desc); + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&usb_in_ot_desc); + usb_altset_add_vendor_desc(fn, 0, 0, + (struct usb_descriptor_header *)&io_out_ot_desc); + + usb_altset_add_vendor_desc(fn, 1, 1, + (struct usb_descriptor_header *)&as_out_hdr_desc); + usb_altset_add_vendor_desc(fn, 1, 1, + (struct usb_descriptor_header *)&as_out_fmt1_desc); + usb_ep_add_vendor_desc(fn, 1, 1, 0, + (struct usb_descriptor_header *)&as_iso_out_desc); + + usb_altset_add_vendor_desc(fn, 2, 1, + (struct usb_descriptor_header *)&as_in_hdr_desc); + usb_altset_add_vendor_desc(fn, 2, 1, + (struct usb_descriptor_header *)&as_in_fmt1_desc); + usb_ep_add_vendor_desc(fn, 2, 1, 0, + (struct usb_descriptor_header *)&as_iso_in_desc); ret = alsa_uac2_init(agdev); if (ret) - goto err_free_descs; - return 0; + return ret; -err_free_descs: - usb_free_all_descriptors(fn); -err: - kfree(agdev->uac2.p_prm.rbuf); - kfree(agdev->uac2.c_prm.rbuf); - return -EINVAL; + return 0; } -static int -afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) +static int afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) { struct usb_composite_dev *cdev = fn->config->cdev; struct audio_dev *agdev = func_to_agdev(fn); struct snd_uac2_chip *uac2 = &agdev->uac2; struct usb_gadget *gadget = cdev->gadget; struct device *dev = &uac2->pdev.dev; + struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); + struct usb_endpoint_descriptor *ep_desc; struct usb_request *req; struct usb_ep *ep; struct uac2_rtd_params *prm; - int req_len, i; + unsigned int factor, rate; + int ret, req_len, i; - /* No i/f has more than 2 alt settings */ - if (alt > 1) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return -EINVAL; - } - - if (intf == agdev->ac_intf) { - /* Control I/f has only 1 AltSetting - 0 */ - if (alt) { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return -EINVAL; - } + if (alt == 0) return 0; - } - if (intf == agdev->as_out_intf) { - ep = agdev->out_ep; + switch (intf) { + case 1: + ep = agdev->out_ep = usb_function_get_ep(fn, intf, 0); prm = &uac2->c_prm; - config_ep_by_speed(gadget, fn, ep); - agdev->as_out_alt = alt; + prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); + if (!prm->rbuf) + return -ENOMEM; req_len = prm->max_psize; - } else if (intf == agdev->as_in_intf) { - struct f_uac2_opts *opts = agdev_to_uac2_opts(agdev); - unsigned int factor, rate; - struct usb_endpoint_descriptor *ep_desc; - - ep = agdev->in_ep; + break; + case 2: + ep = agdev->in_ep = usb_function_get_ep(fn, intf, 0); prm = &uac2->p_prm; - config_ep_by_speed(gadget, fn, ep); - agdev->as_in_alt = alt; + prm->rbuf = kzalloc(prm->max_psize * USB_XFERS, GFP_KERNEL); + if (!prm->rbuf) + return -ENOMEM; /* pre-calculate the playback endpoint's interval */ if (gadget->speed == USB_SPEED_FULL) { @@ -1201,24 +1112,21 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) req_len = uac2->p_pktsize; uac2->p_residue = 0; - } else { - dev_err(dev, "%s:%d Error!\n", __func__, __LINE__); - return -EINVAL; - } - - if (alt == 0) { - free_ep(prm, ep); + break; + default: return 0; } + prm->ep_enabled = true; - usb_ep_enable(ep); for (i = 0; i < USB_XFERS; i++) { if (!prm->ureq[i].req) { req = usb_ep_alloc_request(ep, GFP_ATOMIC); - if (req == NULL) - return -ENOMEM; + if (req == NULL) { + ret = -ENOMEM; + goto err; + } prm->ureq[i].req = req; prm->ureq[i].pp = prm; @@ -1235,39 +1143,31 @@ afunc_set_alt(struct usb_function *fn, unsigned intf, unsigned alt) } return 0; -} - -static int -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 == 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", - __func__, __LINE__, intf); - return -EINVAL; +err: + kfree(prm->rbuf); + return ret; } static void -afunc_disable(struct usb_function *fn) +afunc_clear_alt(struct usb_function *fn, unsigned intf, unsigned alt) { struct audio_dev *agdev = func_to_agdev(fn); struct snd_uac2_chip *uac2 = &agdev->uac2; - free_ep(&uac2->p_prm, agdev->in_ep); - agdev->as_in_alt = 0; + if (alt == 0) + return; - free_ep(&uac2->c_prm, agdev->out_ep); - agdev->as_out_alt = 0; + switch (intf) { + case 1: + free_ep(&uac2->c_prm, agdev->out_ep); + kfree(agdev->uac2.c_prm.rbuf); + break; + case 2: + free_ep(&uac2->p_prm, agdev->in_ep); + kfree(agdev->uac2.p_prm.rbuf); + break; + } } static int @@ -1386,7 +1286,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 != agdev->ac_intf) { + if (intf != usb_get_interface_id(fn, 0)) { dev_err(&uac2->pdev.dev, "%s:%d Error!\n", __func__, __LINE__); return -EOPNOTSUPP; @@ -1552,6 +1452,8 @@ static void afunc_free(struct usb_function *f) agdev = func_to_agdev(f); opts = container_of(f->fi, struct f_uac2_opts, func_inst); + + alsa_uac2_exit(agdev); kfree(agdev); mutex_lock(&opts->lock); --opts->refcnt; @@ -1561,21 +1463,14 @@ static void afunc_free(struct usb_function *f) static void afunc_unbind(struct usb_configuration *c, struct usb_function *f) { struct audio_dev *agdev = func_to_agdev(f); - struct uac2_rtd_params *prm; alsa_uac2_exit(agdev); - - prm = &agdev->uac2.p_prm; - kfree(prm->rbuf); - - prm = &agdev->uac2.c_prm; - kfree(prm->rbuf); - usb_free_all_descriptors(f); } static struct usb_function *afunc_alloc(struct usb_function_instance *fi) { struct audio_dev *agdev; + struct snd_uac2_chip *uac2; struct f_uac2_opts *opts; agdev = kzalloc(sizeof(*agdev), GFP_KERNEL); @@ -1588,14 +1483,18 @@ static struct usb_function *afunc_alloc(struct usb_function_instance *fi) mutex_unlock(&opts->lock); agdev->func.name = "uac2_func"; - agdev->func.bind = afunc_bind; + agdev->func.prep_descs = afunc_prep_descs; + agdev->func.prep_vendor_descs = afunc_prep_vendor_descs; agdev->func.unbind = afunc_unbind; agdev->func.set_alt = afunc_set_alt; - agdev->func.get_alt = afunc_get_alt; - agdev->func.disable = afunc_disable; + agdev->func.clear_alt = afunc_clear_alt; agdev->func.setup = afunc_setup; agdev->func.free_func = afunc_free; + uac2 = &agdev->uac2; + uac2->p_prm.uac2 = uac2; + uac2->c_prm.uac2 = uac2; + return &agdev->func; } -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/