Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754671AbbKCM7q (ORCPT ); Tue, 3 Nov 2015 07:59:46 -0500 Received: from mailout1.samsung.com ([203.254.224.24]:55348 "EHLO mailout1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754085AbbKCMyz (ORCPT ); Tue, 3 Nov 2015 07:54:55 -0500 X-AuditID: cbfee61a-f79a06d000005c6f-bc-5638ae983b23 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 11/23] usb: gadget: composite: generate old descs for compatibility Date: Tue, 03 Nov 2015 13:53:50 +0100 Message-id: <1446555242-3733-12-git-send-email-r.baldyga@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1446555242-3733-1-git-send-email-r.baldyga@samsung.com> References: <1446555242-3733-1-git-send-email-r.baldyga@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprMLMWRmVeSWpSXmKPExsVy+t9jQd0Z6yzCDNYc17eY9bKdxWLjjPWs Fgfv11s0L17PZnF51xw2i0XLWpkt1h65y27x4PBOdgcOj/1z17B79G1Zxehx/MZ2Jo/Pm+QC WKK4bFJSczLLUov07RK4MlYviiv4Z1lxbMU6tgbGjfpdjJwcEgImEvt7H7BC2GISF+6tZ+ti 5OIQEpjFKHHo0n52COcno8TSmZPYQarYBHQktnyfwAhiiwgISKx/cQmsiFngHKPEwzttYAlh gVCJ3uctYA0sAqoSG+Y0A9kcHLwCrhLnzhhBbJOTOHlsMitImBMofOmdMogpJOAicXw7zwRG 3gWMDKsYJVILkguKk9JzDfNSy/WKE3OLS/PS9ZLzczcxgoPqmdQOxoO73A8xCnAwKvHwLlhi HibEmlhWXJl7iFGCg1lJhHf3XIswId6UxMqq1KL8+KLSnNTiQ4zSHCxK4rz6nkZhQgLpiSWp 2ampBalFMFkmDk6pBsZl2/TK1s4w+8/Ktm/9f6NV6z693u65cU+dfPqsx7NTnqvO8+o8e/jg B5YfNx8bVhitDeKWcT8YNPct941LixzcfqYGsj/l6DgpuFNW3UNb+/WH27N21m64dXfa9rcS S44Xb9pclfhuz/VXGm8F7ucVc7nd6bDen7xc6ZmM0aKab7fZdm/w0ti1UomlOCPRUIu5qDgR AIC0wWYmAgAA Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 7429 Lines: 243 For now we generate descriptor arrays for each speed as it is done by old API functions, to allow use mixed new and old API based functions in single configurations. This will be removed after complete switch to new API. Signed-off-by: Robert Baldyga --- drivers/usb/gadget/composite.c | 175 +++++++++++++++++++++++++++++++++++++++++ include/linux/usb/composite.h | 2 + 2 files changed, 177 insertions(+) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 9b4fcfe..b50ebdb 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2255,6 +2255,30 @@ void composite_free_vendor_descs(struct usb_composite_dev *cdev) } EXPORT_SYMBOL_GPL(composite_free_vendor_descs); +/** + * composite_free_old_descs - for all functions implementing new API free old + * descriptors arrays. + * @cdev: composite device + */ +void composite_free_old_descs(struct usb_composite_dev *cdev) +{ + struct usb_configuration *c; + struct usb_function *f; + + list_for_each_entry(c, &cdev->configs, list) + list_for_each_entry(f, &c->functions, list) { + if (!usb_function_is_new_api(f)) + continue; + kfree(f->fs_descriptors); + kfree(f->hs_descriptors); + kfree(f->ss_descriptors); + f->fs_descriptors = NULL; + f->hs_descriptors = NULL; + f->ss_descriptors = NULL; + } +} +EXPORT_SYMBOL_GPL(composite_free_old_descs); + static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) { struct usb_composite_dev *cdev = get_gadget_data(gadget); @@ -2266,6 +2290,7 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) */ WARN_ON(cdev->config); + composite_free_old_descs(cdev); composite_free_vendor_descs(cdev); composite_free_descs(cdev); @@ -2593,6 +2618,152 @@ int composite_prep_vendor_descs(struct usb_composite_dev *cdev) } EXPORT_SYMBOL_GPL(composite_prep_vendor_descs); +/* + * function_add_desc() - Add given descriptor to descriptor arrays for + * each supported speed, in proper version for each speed. + * + * @f - USB function + * @idx - pointer to index of descriptor in fs and hs array + * @idx_ss - pointer to index of descriptor in ss array + * @fs - descriptor for FS + * @hs - descriptor for HS + * @ss - descriptor for SS + * + * Indexes are automatically incremented. + * + * This function will be removed after converting all USB functions + * in kernel to new API. + */ +static inline void function_add_desc(struct usb_function *f, + int *idx, int *idx_ss, + struct usb_descriptor_header *fs, + struct usb_descriptor_header *hs, + struct usb_descriptor_header *ss) { + if (f->config->fullspeed) + f->fs_descriptors[*idx] = fs; + if (f->config->highspeed) + f->hs_descriptors[*idx] = hs; + if (f->config->superspeed) + f->ss_descriptors[*idx_ss] = ss; + ++(*idx); + ++(*idx_ss); +} + +/* + * function_generate_old_descs() - generate descriptors array for each speed + * + * Allocate arrays of needed size and assign to them USB descriptors. + * + * This is temporary solution allowing coexistence to both old and new function + * API. It will be removed after converting all functions in kernel to new API. + */ +static int function_generate_old_descs(struct usb_function *f) +{ + struct usb_composite_intf *intf; + struct usb_composite_altset *alt; + struct usb_composite_ep *ep; + struct usb_composite_vendor_desc *vd; + int cnt, eps, i, a, e, idx, idx_ss; + + cnt = f->descs->vendor_descs_num; + eps = 0; + + for (i = 0; i < f->descs->intfs_num; ++i) { + intf = f->descs->intfs[i]; + for (a = 0; a < intf->altsets_num; ++a) { + alt = intf->altsets[a]; + cnt += alt->vendor_descs_num + 1; + eps += alt->eps_num; + for (e = 0; e < alt->eps_num; ++e) + cnt += alt->eps[e]->vendor_descs_num + 1; + } + } + + if (f->config->fullspeed) { + f->fs_descriptors = kzalloc((cnt + 1) * + sizeof(*f->fs_descriptors), GFP_KERNEL); + if (!f->fs_descriptors) + return -ENOMEM; + } + if (f->config->highspeed) { + f->hs_descriptors = kzalloc((cnt + 1) * + sizeof(*f->hs_descriptors), GFP_KERNEL); + if (!f->hs_descriptors) + goto err; + } + if (f->config->superspeed) { + f->ss_descriptors = kzalloc((cnt + eps + 1) * + sizeof(*f->ss_descriptors), GFP_KERNEL); + if (!f->ss_descriptors) + goto err; + } + + idx = 0; + idx_ss = 0; + list_for_each_entry(vd, &f->descs->vendor_descs, list) + function_add_desc(f, &idx, &idx_ss, + vd->desc, vd->desc, vd->desc); + for (i = 0; i < f->descs->intfs_num; ++i) { + intf = f->descs->intfs[i]; + for (a = 0; a < intf->altsets_num; ++a) { + alt = intf->altsets[a]; + function_add_desc(f, &idx, &idx_ss, alt->alt.header, + alt->alt.header, alt->alt.header); + list_for_each_entry(vd, &alt->vendor_descs, list) + function_add_desc(f, &idx, &idx_ss, + vd->desc, vd->desc, vd->desc); + for (e = 0; e < alt->eps_num; ++e) { + ep = alt->eps[e]; + function_add_desc(f, &idx, &idx_ss, + ep->fs.header, ep->hs.header, + ep->ss.header); + if (f->config->superspeed) + f->ss_descriptors[idx_ss++] = + ep->ss_comp.header; + list_for_each_entry(vd, + &ep->vendor_descs, list) + function_add_desc(f, &idx, &idx_ss, + vd->desc, vd->desc, vd->desc); + } + } + } + + return 0; + +err: + kfree(f->ss_descriptors); + f->ss_descriptors = NULL; + kfree(f->hs_descriptors); + f->hs_descriptors = NULL; + kfree(f->fs_descriptors); + f->fs_descriptors = NULL; + + return -ENOMEM; +} + +/* + * composite_generate_old_descs() - generate descriptors arrays for each + * function in each configuraion + */ +int composite_generate_old_descs(struct usb_composite_dev *cdev) +{ + struct usb_configuration *c; + struct usb_function *f; + int ret; + + list_for_each_entry(c, &cdev->configs, list) + list_for_each_entry(f, &c->functions, list) { + if (!usb_function_is_new_api(f)) + continue; + ret = function_generate_old_descs(f); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(composite_generate_old_descs); + static int composite_bind(struct usb_gadget *gadget, struct usb_gadget_driver *gdriver) { @@ -2626,6 +2797,10 @@ static int composite_bind(struct usb_gadget *gadget, if (status < 0) goto fail; + status = composite_generate_old_descs(cdev); + if (status < 0) + goto fail; + if (cdev->use_os_string) { status = composite_os_desc_req_prepare(cdev, gadget->ep0); if (status) diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index dc0ac28c..7cef8c0 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -593,9 +593,11 @@ extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev, void composite_dev_cleanup(struct usb_composite_dev *cdev); int composite_prep_vendor_descs(struct usb_composite_dev *cdev); +int composite_generate_old_descs(struct usb_composite_dev *cdev); void composite_free_descs(struct usb_composite_dev *cdev); void composite_free_vendor_descs(struct usb_composite_dev *cdev); +void composite_free_old_descs(struct usb_composite_dev *cdev); static inline struct usb_composite_driver *to_cdriver( struct usb_gadget_driver *gdrv) -- 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/