All of lore.kernel.org
 help / color / mirror / Atom feed
From: Robert Baldyga <r.baldyga@samsung.com>
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 <r.baldyga@samsung.com>
Subject: [PATCH v4 07/43] usb: gadget: composite: add functions for descriptors handling
Date: Wed, 03 Feb 2016 13:39:15 +0100	[thread overview]
Message-ID: <1454503191-11796-8-git-send-email-r.baldyga@samsung.com> (raw)
In-Reply-To: <1454503191-11796-1-git-send-email-r.baldyga@samsung.com>

Introduce functions and macros allowing to create and assign descriptors
to function easily. Macros build structure hierarchy using pointers to
USB descriptors, while functions assigning them to gadget make a deep
copy. It allows for easy conversion of USB functions to make them using
new descriptors format.

Signed-off-by: Robert Baldyga <r.baldyga@samsung.com>
---
 drivers/usb/gadget/composite.c | 343 +++++++++++++++++++++++++++++++++++++++++
 include/linux/usb/composite.h  |  52 +++++++
 2 files changed, 395 insertions(+)

diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index 65abc24..3f9cad8 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -327,6 +327,314 @@ int usb_function_activate(struct usb_function *function)
 EXPORT_SYMBOL_GPL(usb_function_activate);
 
 /**
+ * usb_function_set_descs - assing descriptors to USB function
+ * @f: USB function
+ * @descs: USB descriptors to be assigned to function
+ *
+ * This function is to be called from prep_desc() callback to provide
+ * descriptors needed during bind process. It does a deep copy of
+ * descriptors hierarchy.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_function_set_descs(struct usb_function *f,
+		struct usb_composite_descs *descs)
+{
+	struct usb_composite_descs *descs_c;
+	struct usb_composite_intf *intf, *intf_c;
+	struct usb_composite_altset *altset, *altset_c;
+	struct usb_composite_ep *ep, *ep_c;
+	int i, a, e;
+	size_t size;
+	void *mem;
+
+	if (!descs->intfs_num)
+		return -EINVAL;
+
+	size = sizeof(*descs);
+
+	size += descs->intfs_num *
+		(sizeof(*descs->intfs) + sizeof(**descs->intfs));
+	for (i = 0; i < descs->intfs_num; ++i) {
+		intf = descs->intfs[i];
+		if (!intf->altsets_num)
+			return -EINVAL;
+		size += intf->altsets_num *
+			(sizeof(*intf->altsets) + sizeof(**intf->altsets));
+		for (a = 0; a < intf->altsets_num; ++a) {
+			altset = intf->altsets[a];
+			size += sizeof(*altset->alt.desc);
+			size += altset->eps_num *
+				(sizeof(*altset->eps) + sizeof(**altset->eps));
+			for (e = 0; e < altset->eps_num; ++e) {
+				ep = altset->eps[e];
+				if (ep->fs.desc)
+					size += sizeof(*ep->fs.desc);
+				if (ep->hs.desc)
+					size += sizeof(*ep->hs.desc);
+				if (ep->ss.desc) {
+					if (!ep->ss_comp.desc)
+						return -EINVAL;
+					size += sizeof(*ep->ss.desc) +
+						sizeof(*ep->ss_comp.desc);
+				}
+			}
+		}
+	}
+
+	mem = kzalloc(size, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+
+	f->descs = descs_c = mem;
+	mem += sizeof(*descs_c);
+	INIT_LIST_HEAD(&descs_c->vendor_descs);
+	descs_c->intfs_num = descs->intfs_num;
+	descs_c->intfs = mem;
+	mem += descs_c->intfs_num * sizeof(*descs_c->intfs);
+
+	for (i = 0; i < f->descs->intfs_num; ++i) {
+		intf = descs->intfs[i];
+		descs_c->intfs[i] = intf_c = mem;
+		mem += sizeof(*intf_c);
+		intf_c->altsets_num = intf->altsets_num;
+		intf_c->altsets = mem;
+		mem += intf_c->altsets_num * sizeof(*intf_c->altsets);
+
+		for (a = 0; a < intf->altsets_num; ++a) {
+			altset = intf->altsets[a];
+			intf_c->altsets[a] = altset_c = mem;
+			mem += sizeof(*altset_c);
+			INIT_LIST_HEAD(&altset_c->vendor_descs);
+			altset_c->alt.desc = mem;
+			mem += sizeof(*altset->alt.desc);
+			memcpy(altset_c->alt.desc, altset->alt.desc,
+				sizeof(*altset->alt.desc));
+			altset_c->eps_num = altset->eps_num;
+			altset_c->eps = mem;
+			mem += altset_c->eps_num * sizeof(*altset_c->eps);
+
+			for (e = 0; e < altset->eps_num; ++e) {
+				ep = altset->eps[e];
+				altset_c->eps[e] = ep_c = mem;
+				mem += sizeof(*ep_c);
+				INIT_LIST_HEAD(&ep_c->vendor_descs);
+				if (ep->fs.desc) {
+					ep_c->fs.desc = mem;
+					mem += sizeof(*ep_c->fs.desc);
+					memcpy(ep_c->fs.desc, ep->fs.desc,
+						sizeof(*ep_c->fs.desc));
+					descs_c->fullspeed = true;
+				}
+				if (ep->hs.desc) {
+					ep_c->hs.desc = mem;
+					mem += sizeof(*ep_c->hs.desc);
+					memcpy(ep_c->hs.desc, ep->hs.desc,
+						sizeof(*ep_c->hs.desc));
+					descs_c->highspeed = true;
+				}
+				if (ep->ss.desc) {
+					ep_c->ss.desc = mem;
+					mem += sizeof(*ep_c->ss.desc);
+					memcpy(ep_c->ss.desc, ep->ss.desc,
+						sizeof(*ep_c->ss.desc));
+					descs_c->superspeed = true;
+				}
+				if (ep->ss_comp.desc) {
+					ep_c->ss_comp.desc = mem;
+					mem += sizeof(*ep_c->ss_comp.desc);
+					memcpy(ep_c->ss_comp.desc,
+						ep->ss_comp.desc,
+						sizeof(*ep_c->ss_comp.desc));
+				}
+			}
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_function_set_descs);
+
+/**
+ * usb_function_free_descs - frees descriptors assinged to function
+ * @f: USB function
+ */
+static inline void usb_function_free_descs(struct usb_function *f)
+{
+	kfree(f->descs);
+	f->descs = NULL;
+}
+
+/**
+ * usb_function_add_vendor_desc - add vendor specific descriptor to USB
+ *	function
+ * @f: USB function
+ * @desc: descriptor to be attached
+ *
+ * Descriptor is copied and attached at the end of linked list.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_function_add_vendor_desc(struct usb_function *f,
+		const struct usb_descriptor_header *desc)
+{
+	struct usb_composite_vendor_desc *vd;
+	void *mem;
+
+	if (!f->descs)
+		return -ENODEV;
+
+	mem = kmalloc(sizeof(*vd) + desc->bLength, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+
+	vd = mem;
+	vd->desc = mem + sizeof(*vd);
+
+	memcpy(vd->desc, desc, desc->bLength);
+
+	list_add_tail(&vd->list, &f->descs->vendor_descs);
+	f->descs->vendor_descs_num++;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_function_add_vendor_desc);
+
+/**
+ * usb_ep_add_vendor_desc - add vendor specific descriptor to altsetting
+ * @f: USB function
+ * @i: index of interface in function
+ * @a: index of altsetting in interface
+ * @desc: descriptor to be attached
+ *
+ * Descriptor is copied and attached at the end of linked list.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_altset_add_vendor_desc(struct usb_function *f, int i, int a,
+		const struct usb_descriptor_header *desc)
+{
+	struct usb_composite_vendor_desc *vd;
+	struct usb_composite_altset *alt;
+	void *mem;
+
+	if (!f->descs)
+		return -ENODEV;
+	if (f->descs->intfs_num <= i)
+		return -ENODEV;
+	if (f->descs->intfs[i]->altsets_num <= a)
+		return -ENODEV;
+
+	mem = kmalloc(sizeof(*vd) + desc->bLength, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+
+	vd = mem;
+	vd->desc = mem + sizeof(*vd);
+
+	memcpy(vd->desc, desc, desc->bLength);
+
+	alt = f->descs->intfs[i]->altsets[a];
+	list_add_tail(&vd->list, &alt->vendor_descs);
+	alt->vendor_descs_num++;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_altset_add_vendor_desc);
+
+/**
+ * usb_ep_add_vendor_desc - add vendor specific descriptor to endpoint
+ * @f: USB function
+ * @i: index of interface in function
+ * @a: index of altsetting in interface
+ * @e: index of endpoint in altsetting
+ * @desc: descriptor to be attached
+ *
+ * Descriptor is copied and attached at the end of linked list.
+ *
+ * Returns zero on success, else negative errno.
+ */
+int usb_ep_add_vendor_desc(struct usb_function *f, int i, int a, int e,
+		const struct usb_descriptor_header *desc)
+{
+	struct usb_composite_vendor_desc *vd;
+	struct usb_composite_ep *ep;
+	void *mem;
+
+	if (!f->descs)
+		return -ENODEV;
+	if (f->descs->intfs_num <= i)
+		return -ENODEV;
+	if (f->descs->intfs[i]->altsets_num <= a)
+		return -ENODEV;
+	if (f->descs->intfs[i]->altsets[a]->eps_num <= e)
+		return -ENODEV;
+
+	mem = kmalloc(sizeof(*vd) + desc->bLength, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+
+	vd = mem;
+	vd->desc = mem + sizeof(*vd);
+
+	memcpy(vd->desc, desc, desc->bLength);
+
+	ep = f->descs->intfs[i]->altsets[a]->eps[e];
+	list_add_tail(&vd->list, &ep->vendor_descs);
+	ep->vendor_descs_num++;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(usb_ep_add_vendor_desc);
+
+/**
+ * free_vendor_descs - removes and frees all vendor descriptors from
+ *	given list
+ * @vendor_descs: handle to the list of descriptors
+ */
+static inline void free_vendor_descs(struct list_head *vendor_descs)
+{
+	while (!list_empty(vendor_descs)) {
+		struct usb_composite_vendor_desc *d;
+
+		d = list_first_entry(vendor_descs,
+				struct usb_composite_vendor_desc, list);
+		list_del(&d->list);
+		kfree(d);
+	}
+}
+
+/**
+ * usb_function_free_vendor_descs - frees vendor specific descriptors
+ *	assinged to function
+ * @f: USB function
+ */
+static void usb_function_free_vendor_descs(struct usb_function *f)
+{
+	struct usb_composite_intf *intf;
+	struct usb_composite_altset *alt;
+	int i, a, e;
+
+	if (!f->descs)
+		return;
+
+	free_vendor_descs(&f->descs->vendor_descs);
+	f->descs->vendor_descs_num = 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];
+			free_vendor_descs(&alt->vendor_descs);
+			alt->vendor_descs_num = 0;
+			for (e = 0; e < alt->eps_num; ++e) {
+				free_vendor_descs(&alt->eps[e]->vendor_descs);
+				alt->eps[e]->vendor_descs_num = 0;
+			}
+		}
+	}
+}
+
+/**
  * usb_interface_id() - allocate an unused interface ID
  * @config: configuration associated with the interface
  * @function: function handling the interface
@@ -1893,6 +2201,38 @@ static ssize_t suspended_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(suspended);
 
+/**
+ * composite_free_descs - free entity descriptors for all functions in all
+ *	configurations, allocated with usb_function_set_descs()
+ * @cdev: composite device
+ */
+void composite_free_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)
+			usb_function_free_descs(f);
+}
+EXPORT_SYMBOL_GPL(composite_free_descs);
+
+/**
+ * composite_free_descs - free vendor and class specific descriptors for all
+ *	functions in all configurations.
+ * @cdev: composite device
+ */
+void composite_free_vendor_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)
+			usb_function_free_vendor_descs(f);
+}
+EXPORT_SYMBOL_GPL(composite_free_vendor_descs);
+
 static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
 {
 	struct usb_composite_dev	*cdev = get_gadget_data(gadget);
@@ -1904,6 +2244,9 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver)
 	 */
 	WARN_ON(cdev->config);
 
+	composite_free_vendor_descs(cdev);
+	composite_free_descs(cdev);
+
 	while (!list_empty(&cdev->configs)) {
 		struct usb_configuration	*c;
 		c = list_first_entry(&cdev->configs,
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 8bb5c35..91948c7 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -178,6 +178,43 @@ struct usb_composite_descs {
 	unsigned superspeed:1;
 };
 
+/*
+ * Macros to be used to create USB descriptors hierarchy.
+ */
+
+#define USB_COMPOSITE_ENDPOINT(_name, _fs_desc, _hs_desc, _ss_desc, _ss_comp) \
+	static struct usb_composite_ep _name = { \
+		.fs = { .desc = _fs_desc, }, \
+		.hs = { .desc = _hs_desc, }, \
+		.ss = { .desc = _ss_desc, }, \
+		.ss_comp = { .desc = _ss_comp, }, \
+		.vendor_descs = LIST_HEAD_INIT(_name.vendor_descs), \
+	}
+
+#define __EP_ARRAY(...) ((struct usb_composite_ep*[]){ __VA_ARGS__ })
+#define USB_COMPOSITE_ALTSETTING(_name, _desc, ...) \
+	static struct usb_composite_altset _name = { \
+		.alt = { .desc = _desc, }, \
+		.eps = __EP_ARRAY(__VA_ARGS__), \
+		.eps_num = ARRAY_SIZE(__EP_ARRAY(__VA_ARGS__)), \
+		.vendor_descs = LIST_HEAD_INIT(_name.vendor_descs), \
+	}
+
+#define __ALTSET_ARRAY(...) ((struct usb_composite_altset*[]){ __VA_ARGS__ })
+#define USB_COMPOSITE_INTERFACE(_name, ...) \
+	static struct usb_composite_intf _name = { \
+		.altsets = __ALTSET_ARRAY(__VA_ARGS__), \
+		.altsets_num = ARRAY_SIZE(__ALTSET_ARRAY(__VA_ARGS__)), \
+	}
+
+#define __INTF_ARRAY(...) ((struct usb_composite_intf*[]){ __VA_ARGS__ })
+#define USB_COMPOSITE_DESCRIPTORS(_name, ...) \
+	static struct usb_composite_descs _name = { \
+		.intfs = __INTF_ARRAY(__VA_ARGS__), \
+		.intfs_num = ARRAY_SIZE(__INTF_ARRAY(__VA_ARGS__)), \
+		.vendor_descs = LIST_HEAD_INIT(_name.vendor_descs), \
+	}
+
 /**
  * struct usb_os_desc_ext_prop - describes one "Extended Property"
  * @entry: used to keep a list of extended properties
@@ -363,6 +400,18 @@ int usb_add_function(struct usb_configuration *, struct usb_function *);
 int usb_function_deactivate(struct usb_function *);
 int usb_function_activate(struct usb_function *);
 
+int usb_function_set_descs(struct usb_function *f,
+		struct usb_composite_descs *descs);
+
+int usb_function_add_vendor_desc(struct usb_function *f,
+		const struct usb_descriptor_header *desc);
+
+int usb_altset_add_vendor_desc(struct usb_function *f, int i, int a,
+		const struct usb_descriptor_header *desc);
+
+int usb_ep_add_vendor_desc(struct usb_function *f, int i, int a, int e,
+		const struct usb_descriptor_header *desc);
+
 int usb_interface_id(struct usb_configuration *, struct usb_function *);
 
 int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
@@ -539,6 +588,9 @@ extern int composite_os_desc_req_prepare(struct usb_composite_dev *cdev,
 					 struct usb_ep *ep0);
 void composite_dev_cleanup(struct usb_composite_dev *cdev);
 
+void composite_free_descs(struct usb_composite_dev *cdev);
+void composite_free_vendor_descs(struct usb_composite_dev *cdev);
+
 static inline struct usb_composite_driver *to_cdriver(
 		struct usb_gadget_driver *gdrv)
 {
-- 
1.9.1

  parent reply	other threads:[~2016-02-03 12:54 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-03 12:39 [PATCH v4 00/43] usb: gadget: composite: introduce new function API Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 01/43] usb: gadget: f_sourcesink: make ISO altset user-selectable Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 02/43] usb: gadget: f_sourcesink: free requests in sourcesink_disable() Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 03/43] usb: gadget: f_loopback: free requests in loopback_disable() Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 04/43] usb: gadget: configfs: fix error path Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 05/43] usb: gadget: composite: fix recursive spinlock locking Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 06/43] usb: gadget: composite: introduce new descriptors format Robert Baldyga
2016-02-04  5:16   ` kbuild test robot
2016-02-03 12:39 ` Robert Baldyga [this message]
2016-02-03 12:39 ` [PATCH v4 08/43] usb: gadget: composite: introduce new USB function ops Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 09/43] usb: gadget: composite: handle function bind Robert Baldyga
2016-02-04  5:42   ` kbuild test robot
2016-02-03 12:39 ` [PATCH v4 10/43] usb: gadget: composite: handle vendor descs Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 11/43] usb: gadget: composite: generate old descs for compatibility Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 12/43] usb: gadget: composite: disable eps before calling disable() callback Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 13/43] usb: gadget: composite: enable eps before calling set_alt() callback Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 14/43] usb: gadget: composite: introduce clear_alt() operation Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 15/43] usb: gadget: composite: handle get_alt() automatically Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 16/43] usb: gadget: composite: add usb_function_get_ep() function Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 17/43] usb: gadget: composite: add usb_get_interface_id() function Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 18/43] usb: gadget: composite: usb_get_endpoint_address() function Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 19/43] usb: gadget: composite: enable adding USB functions using new API Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 20/43] usb: gadget: configfs: add new composite API support Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 21/43] usb: gadget: f_loopback: convert to new API Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 22/43] usb: gadget: f_sourcesink: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 23/43] usb: gadget: f_ecm: conversion " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 24/43] usb: gadget: f_rndis: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 25/43] usb: gadget: f_hid: handle requests lifetime properly Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 26/43] usb: gadget: f_hid: conversion to new API Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 27/43] usb: gadget: f_acm: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 28/43] usb: gadget: f_eem: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 29/43] usb: gadget: f_ncm: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 30/43] usb: gadget: f_printer: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 31/43] usb: gadget: f_serial: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 32/43] usb: gadget: f_obex: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 33/43] usb: gadget: f_phonet: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 34/43] usb: gadget: f_subset: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 35/43] usb: gadget: f_uac1: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 36/43] usb: gadget: f_uac2: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 37/43] usb: gadget: f_mass_storage: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 38/43] usb: gadget: u_serial: remove usb_ep_enable()/usb_ep_disable() Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 39/43] usb: gadget: u_ether: " Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 40/43] usb: gadget: uvc: fix typo in UVCG_OPTS_ATTR() macro Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 41/43] usb: gadget: uvc: simplify descriptors generation Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 42/43] Documentation: update uvc configfs interface description Robert Baldyga
2016-02-03 12:39 ` [PATCH v4 43/43] usb: gadget: f_uvc: conversion to new API Robert Baldyga

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1454503191-11796-8-git-send-email-r.baldyga@samsung.com \
    --to=r.baldyga@samsung.com \
    --cc=andrzej.p@samsung.com \
    --cc=b.zolnierkie@samsung.com \
    --cc=balbi@ti.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=m.szyprowski@samsung.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.