Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755195AbbLKL0J (ORCPT ); Fri, 11 Dec 2015 06:26:09 -0500 Received: from mailout3.samsung.com ([203.254.224.33]:45197 "EHLO mailout3.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754719AbbLKL0E (ORCPT ); Fri, 11 Dec 2015 06:26:04 -0500 X-AuditID: cbfee61a-f79266d000003652-df-566ab2ca32b0 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 11/36] usb: gadget: composite: generate old descs for compatibility Date: Fri, 11 Dec 2015 12:24:50 +0100 Message-id: <1449833115-24065-12-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+t9jQd1Tm7LCDD7vNLWY9bKdxWLjjPWs Fgfv11s0L17PZnF51xw2i0XLWpkt1h65y27x4PBOdgcOj/1z17B79G1Zxehx/MZ2Jo/Pm+QC WKK4bFJSczLLUov07RK4MroXfWEv+GdZ8X/aV6YGxo36XYwcHBICJhIPbpd0MXICmWISF+6t Z+ti5OIQEpjFKLH46yJGCOcno8TDP5fYQKrYBHQktnyfwAhiiwgISKx/cYkdpIhZ4BxQ0Z02 sISwQITEqe4fYA0sAqoS2/b9YgKxeQXcJP49fMgCsU5O4uSxyawgNidQfPLJS8wgtpCAq8Sb 1+sYJzDyLmBkWMUokVqQXFCclJ5rmJdarlecmFtcmpeul5yfu4kRHFrPpHYwHtzlfohRgINR iYd3AUdWmBBrYllxZe4hRgkOZiUR3l8bgEK8KYmVValF+fFFpTmpxYcYpTlYlMR5ay9FhgkJ pCeWpGanphakFsFkmTg4pRoYFx47/XTfVK9P69bWnLTyZvjSUMQou2iaw3wO2/6OwACuluM3 LA78Xpuw9gHriz69RuEKkftlYt+PX+6VNJhU33e5qMZF8dzs25yNW7cEvbgqd/xmXMZNf5vu ltuvuNLUvne95gnYda9Dk+2nJA9zzQQxjoCaGdZ6wUzfV/TXzeTfITdfv0NCiaU4I9FQi7mo OBEA2+e9BikCAAA= 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 1b8e204..fdd0cbe 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2258,6 +2258,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); @@ -2269,6 +2293,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); @@ -2596,6 +2621,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) { @@ -2629,6 +2800,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/