Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * hid.c -- HID Composite driver
  4 *
  5 * Based on multi.c
  6 *
  7 * Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
  8 */
  9
 10
 11#include <linux/kernel.h>
 12#include <linux/platform_device.h>
 13#include <linux/list.h>
 14#include <linux/module.h>
 15#include <linux/usb/composite.h>
 16#include <linux/usb/g_hid.h>
 17
 18#define DRIVER_DESC		"HID Gadget"
 19#define DRIVER_VERSION		"2010/03/16"
 20
 21#include "u_hid.h"
 22
 23/*-------------------------------------------------------------------------*/
 24
 25#define HIDG_VENDOR_NUM		0x0525	/* XXX NetChip */
 26#define HIDG_PRODUCT_NUM	0xa4ac	/* Linux-USB HID gadget */
 27
 28/*-------------------------------------------------------------------------*/
 29
 30struct hidg_func_node {
 31	struct usb_function_instance *fi;
 32	struct usb_function *f;
 33	struct list_head node;
 34	struct hidg_func_descriptor *func;
 35};
 36
 37static LIST_HEAD(hidg_func_list);
 38
 39/*-------------------------------------------------------------------------*/
 40USB_GADGET_COMPOSITE_OPTIONS();
 41
 42static struct usb_device_descriptor device_desc = {
 43	.bLength =		sizeof device_desc,
 44	.bDescriptorType =	USB_DT_DEVICE,
 45
 46	/* .bcdUSB = DYNAMIC */
 47
 48	/* .bDeviceClass =		USB_CLASS_COMM, */
 49	/* .bDeviceSubClass =	0, */
 50	/* .bDeviceProtocol =	0, */
 51	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 52	.bDeviceSubClass =	0,
 53	.bDeviceProtocol =	0,
 54	/* .bMaxPacketSize0 = f(hardware) */
 55
 56	/* Vendor and product id can be overridden by module parameters.  */
 57	.idVendor =		cpu_to_le16(HIDG_VENDOR_NUM),
 58	.idProduct =		cpu_to_le16(HIDG_PRODUCT_NUM),
 59	/* .bcdDevice = f(hardware) */
 60	/* .iManufacturer = DYNAMIC */
 61	/* .iProduct = DYNAMIC */
 62	/* NO SERIAL NUMBER */
 63	.bNumConfigurations =	1,
 64};
 65
 66static const struct usb_descriptor_header *otg_desc[2];
 67
 68/* string IDs are assigned dynamically */
 69static struct usb_string strings_dev[] = {
 70	[USB_GADGET_MANUFACTURER_IDX].s = "",
 71	[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
 72	[USB_GADGET_SERIAL_IDX].s = "",
 73	{  } /* end of list */
 74};
 75
 76static struct usb_gadget_strings stringtab_dev = {
 77	.language	= 0x0409,	/* en-us */
 78	.strings	= strings_dev,
 79};
 80
 81static struct usb_gadget_strings *dev_strings[] = {
 82	&stringtab_dev,
 83	NULL,
 84};
 85
 86
 87
 88/****************************** Configurations ******************************/
 89
 90static int do_config(struct usb_configuration *c)
 91{
 92	struct hidg_func_node *e, *n;
 93	int status = 0;
 94
 95	if (gadget_is_otg(c->cdev->gadget)) {
 96		c->descriptors = otg_desc;
 97		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 98	}
 99
100	list_for_each_entry(e, &hidg_func_list, node) {
101		e->f = usb_get_function(e->fi);
102		if (IS_ERR(e->f)) {
103			status = PTR_ERR(e->f);
104			goto put;
105		}
106		status = usb_add_function(c, e->f);
107		if (status < 0) {
108			usb_put_function(e->f);
109			goto put;
110		}
111	}
112
113	return 0;
114put:
115	list_for_each_entry(n, &hidg_func_list, node) {
116		if (n == e)
117			break;
118		usb_remove_function(c, n->f);
119		usb_put_function(n->f);
120	}
121	return status;
122}
123
124static struct usb_configuration config_driver = {
125	.label			= "HID Gadget",
126	.bConfigurationValue	= 1,
127	/* .iConfiguration = DYNAMIC */
128	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
129};
130
131/****************************** Gadget Bind ******************************/
132
133static int hid_bind(struct usb_composite_dev *cdev)
134{
135	struct usb_gadget *gadget = cdev->gadget;
136	struct list_head *tmp;
137	struct hidg_func_node *n = NULL, *m, *iter_n;
138	struct f_hid_opts *hid_opts;
139	int status, funcs = 0;
140
141	list_for_each(tmp, &hidg_func_list)
142		funcs++;
143
144	if (!funcs)
145		return -ENODEV;
146
147	list_for_each_entry(iter_n, &hidg_func_list, node) {
148		iter_n->fi = usb_get_function_instance("hid");
149		if (IS_ERR(iter_n->fi)) {
150			status = PTR_ERR(iter_n->fi);
151			n = iter_n;
152			goto put;
153		}
154		hid_opts = container_of(iter_n->fi, struct f_hid_opts, func_inst);
155		hid_opts->subclass = iter_n->func->subclass;
156		hid_opts->protocol = iter_n->func->protocol;
157		hid_opts->report_length = iter_n->func->report_length;
158		hid_opts->report_desc_length = iter_n->func->report_desc_length;
159		hid_opts->report_desc = iter_n->func->report_desc;
160	}
161
162
163	/* Allocate string descriptor numbers ... note that string
164	 * contents can be overridden by the composite_dev glue.
165	 */
166
167	status = usb_string_ids_tab(cdev, strings_dev);
168	if (status < 0)
169		goto put;
170	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
171	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
172
173	if (gadget_is_otg(gadget) && !otg_desc[0]) {
174		struct usb_descriptor_header *usb_desc;
175
176		usb_desc = usb_otg_descriptor_alloc(gadget);
177		if (!usb_desc) {
178			status = -ENOMEM;
179			goto put;
180		}
181		usb_otg_descriptor_init(gadget, usb_desc);
182		otg_desc[0] = usb_desc;
183		otg_desc[1] = NULL;
184	}
185
186	/* register our configuration */
187	status = usb_add_config(cdev, &config_driver, do_config);
188	if (status < 0)
189		goto free_otg_desc;
190
191	usb_composite_overwrite_options(cdev, &coverwrite);
192	dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
193
194	return 0;
195
196free_otg_desc:
197	kfree(otg_desc[0]);
198	otg_desc[0] = NULL;
199put:
200	list_for_each_entry(m, &hidg_func_list, node) {
201		if (m == n)
202			break;
203		usb_put_function_instance(m->fi);
204	}
205	return status;
206}
207
208static int hid_unbind(struct usb_composite_dev *cdev)
209{
210	struct hidg_func_node *n;
211
212	list_for_each_entry(n, &hidg_func_list, node) {
213		usb_put_function(n->f);
214		usb_put_function_instance(n->fi);
215	}
216
217	kfree(otg_desc[0]);
218	otg_desc[0] = NULL;
219
220	return 0;
221}
222
223static int hidg_plat_driver_probe(struct platform_device *pdev)
224{
225	struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
226	struct hidg_func_node *entry;
227
228	if (!func) {
229		dev_err(&pdev->dev, "Platform data missing\n");
230		return -ENODEV;
231	}
232
233	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
234	if (!entry)
235		return -ENOMEM;
236
237	entry->func = func;
238	list_add_tail(&entry->node, &hidg_func_list);
239
240	return 0;
241}
242
243static int hidg_plat_driver_remove(struct platform_device *pdev)
244{
245	struct hidg_func_node *e, *n;
246
247	list_for_each_entry_safe(e, n, &hidg_func_list, node) {
248		list_del(&e->node);
249		kfree(e);
250	}
251
252	return 0;
253}
254
255
256/****************************** Some noise ******************************/
257
258
259static struct usb_composite_driver hidg_driver = {
260	.name		= "g_hid",
261	.dev		= &device_desc,
262	.strings	= dev_strings,
263	.max_speed	= USB_SPEED_HIGH,
264	.bind		= hid_bind,
265	.unbind		= hid_unbind,
266};
267
268static struct platform_driver hidg_plat_driver = {
269	.remove		= hidg_plat_driver_remove,
270	.driver		= {
271		.name	= "hidg",
272	},
273};
274
275
276MODULE_DESCRIPTION(DRIVER_DESC);
277MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
278MODULE_LICENSE("GPL");
279
280static int __init hidg_init(void)
281{
282	int status;
283
284	status = platform_driver_probe(&hidg_plat_driver,
285				hidg_plat_driver_probe);
286	if (status < 0)
287		return status;
288
289	status = usb_composite_probe(&hidg_driver);
290	if (status < 0)
291		platform_driver_unregister(&hidg_plat_driver);
292
293	return status;
294}
295module_init(hidg_init);
296
297static void __exit hidg_cleanup(void)
298{
299	usb_composite_unregister(&hidg_driver);
300	platform_driver_unregister(&hidg_plat_driver);
301}
302module_exit(hidg_cleanup);
v5.9
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * hid.c -- HID Composite driver
  4 *
  5 * Based on multi.c
  6 *
  7 * Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
  8 */
  9
 10
 11#include <linux/kernel.h>
 12#include <linux/platform_device.h>
 13#include <linux/list.h>
 14#include <linux/module.h>
 15#include <linux/usb/composite.h>
 16#include <linux/usb/g_hid.h>
 17
 18#define DRIVER_DESC		"HID Gadget"
 19#define DRIVER_VERSION		"2010/03/16"
 20
 21#include "u_hid.h"
 22
 23/*-------------------------------------------------------------------------*/
 24
 25#define HIDG_VENDOR_NUM		0x0525	/* XXX NetChip */
 26#define HIDG_PRODUCT_NUM	0xa4ac	/* Linux-USB HID gadget */
 27
 28/*-------------------------------------------------------------------------*/
 29
 30struct hidg_func_node {
 31	struct usb_function_instance *fi;
 32	struct usb_function *f;
 33	struct list_head node;
 34	struct hidg_func_descriptor *func;
 35};
 36
 37static LIST_HEAD(hidg_func_list);
 38
 39/*-------------------------------------------------------------------------*/
 40USB_GADGET_COMPOSITE_OPTIONS();
 41
 42static struct usb_device_descriptor device_desc = {
 43	.bLength =		sizeof device_desc,
 44	.bDescriptorType =	USB_DT_DEVICE,
 45
 46	/* .bcdUSB = DYNAMIC */
 47
 48	/* .bDeviceClass =		USB_CLASS_COMM, */
 49	/* .bDeviceSubClass =	0, */
 50	/* .bDeviceProtocol =	0, */
 51	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 52	.bDeviceSubClass =	0,
 53	.bDeviceProtocol =	0,
 54	/* .bMaxPacketSize0 = f(hardware) */
 55
 56	/* Vendor and product id can be overridden by module parameters.  */
 57	.idVendor =		cpu_to_le16(HIDG_VENDOR_NUM),
 58	.idProduct =		cpu_to_le16(HIDG_PRODUCT_NUM),
 59	/* .bcdDevice = f(hardware) */
 60	/* .iManufacturer = DYNAMIC */
 61	/* .iProduct = DYNAMIC */
 62	/* NO SERIAL NUMBER */
 63	.bNumConfigurations =	1,
 64};
 65
 66static const struct usb_descriptor_header *otg_desc[2];
 67
 68/* string IDs are assigned dynamically */
 69static struct usb_string strings_dev[] = {
 70	[USB_GADGET_MANUFACTURER_IDX].s = "",
 71	[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
 72	[USB_GADGET_SERIAL_IDX].s = "",
 73	{  } /* end of list */
 74};
 75
 76static struct usb_gadget_strings stringtab_dev = {
 77	.language	= 0x0409,	/* en-us */
 78	.strings	= strings_dev,
 79};
 80
 81static struct usb_gadget_strings *dev_strings[] = {
 82	&stringtab_dev,
 83	NULL,
 84};
 85
 86
 87
 88/****************************** Configurations ******************************/
 89
 90static int do_config(struct usb_configuration *c)
 91{
 92	struct hidg_func_node *e, *n;
 93	int status = 0;
 94
 95	if (gadget_is_otg(c->cdev->gadget)) {
 96		c->descriptors = otg_desc;
 97		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
 98	}
 99
100	list_for_each_entry(e, &hidg_func_list, node) {
101		e->f = usb_get_function(e->fi);
102		if (IS_ERR(e->f))
 
103			goto put;
 
104		status = usb_add_function(c, e->f);
105		if (status < 0) {
106			usb_put_function(e->f);
107			goto put;
108		}
109	}
110
111	return 0;
112put:
113	list_for_each_entry(n, &hidg_func_list, node) {
114		if (n == e)
115			break;
116		usb_remove_function(c, n->f);
117		usb_put_function(n->f);
118	}
119	return status;
120}
121
122static struct usb_configuration config_driver = {
123	.label			= "HID Gadget",
124	.bConfigurationValue	= 1,
125	/* .iConfiguration = DYNAMIC */
126	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
127};
128
129/****************************** Gadget Bind ******************************/
130
131static int hid_bind(struct usb_composite_dev *cdev)
132{
133	struct usb_gadget *gadget = cdev->gadget;
134	struct list_head *tmp;
135	struct hidg_func_node *n, *m;
136	struct f_hid_opts *hid_opts;
137	int status, funcs = 0;
138
139	list_for_each(tmp, &hidg_func_list)
140		funcs++;
141
142	if (!funcs)
143		return -ENODEV;
144
145	list_for_each_entry(n, &hidg_func_list, node) {
146		n->fi = usb_get_function_instance("hid");
147		if (IS_ERR(n->fi)) {
148			status = PTR_ERR(n->fi);
 
149			goto put;
150		}
151		hid_opts = container_of(n->fi, struct f_hid_opts, func_inst);
152		hid_opts->subclass = n->func->subclass;
153		hid_opts->protocol = n->func->protocol;
154		hid_opts->report_length = n->func->report_length;
155		hid_opts->report_desc_length = n->func->report_desc_length;
156		hid_opts->report_desc = n->func->report_desc;
157	}
158
159
160	/* Allocate string descriptor numbers ... note that string
161	 * contents can be overridden by the composite_dev glue.
162	 */
163
164	status = usb_string_ids_tab(cdev, strings_dev);
165	if (status < 0)
166		goto put;
167	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
168	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
169
170	if (gadget_is_otg(gadget) && !otg_desc[0]) {
171		struct usb_descriptor_header *usb_desc;
172
173		usb_desc = usb_otg_descriptor_alloc(gadget);
174		if (!usb_desc)
 
175			goto put;
 
176		usb_otg_descriptor_init(gadget, usb_desc);
177		otg_desc[0] = usb_desc;
178		otg_desc[1] = NULL;
179	}
180
181	/* register our configuration */
182	status = usb_add_config(cdev, &config_driver, do_config);
183	if (status < 0)
184		goto free_otg_desc;
185
186	usb_composite_overwrite_options(cdev, &coverwrite);
187	dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
188
189	return 0;
190
191free_otg_desc:
192	kfree(otg_desc[0]);
193	otg_desc[0] = NULL;
194put:
195	list_for_each_entry(m, &hidg_func_list, node) {
196		if (m == n)
197			break;
198		usb_put_function_instance(m->fi);
199	}
200	return status;
201}
202
203static int hid_unbind(struct usb_composite_dev *cdev)
204{
205	struct hidg_func_node *n;
206
207	list_for_each_entry(n, &hidg_func_list, node) {
208		usb_put_function(n->f);
209		usb_put_function_instance(n->fi);
210	}
211
212	kfree(otg_desc[0]);
213	otg_desc[0] = NULL;
214
215	return 0;
216}
217
218static int hidg_plat_driver_probe(struct platform_device *pdev)
219{
220	struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
221	struct hidg_func_node *entry;
222
223	if (!func) {
224		dev_err(&pdev->dev, "Platform data missing\n");
225		return -ENODEV;
226	}
227
228	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
229	if (!entry)
230		return -ENOMEM;
231
232	entry->func = func;
233	list_add_tail(&entry->node, &hidg_func_list);
234
235	return 0;
236}
237
238static int hidg_plat_driver_remove(struct platform_device *pdev)
239{
240	struct hidg_func_node *e, *n;
241
242	list_for_each_entry_safe(e, n, &hidg_func_list, node) {
243		list_del(&e->node);
244		kfree(e);
245	}
246
247	return 0;
248}
249
250
251/****************************** Some noise ******************************/
252
253
254static struct usb_composite_driver hidg_driver = {
255	.name		= "g_hid",
256	.dev		= &device_desc,
257	.strings	= dev_strings,
258	.max_speed	= USB_SPEED_HIGH,
259	.bind		= hid_bind,
260	.unbind		= hid_unbind,
261};
262
263static struct platform_driver hidg_plat_driver = {
264	.remove		= hidg_plat_driver_remove,
265	.driver		= {
266		.name	= "hidg",
267	},
268};
269
270
271MODULE_DESCRIPTION(DRIVER_DESC);
272MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
273MODULE_LICENSE("GPL");
274
275static int __init hidg_init(void)
276{
277	int status;
278
279	status = platform_driver_probe(&hidg_plat_driver,
280				hidg_plat_driver_probe);
281	if (status < 0)
282		return status;
283
284	status = usb_composite_probe(&hidg_driver);
285	if (status < 0)
286		platform_driver_unregister(&hidg_plat_driver);
287
288	return status;
289}
290module_init(hidg_init);
291
292static void __exit hidg_cleanup(void)
293{
294	usb_composite_unregister(&hidg_driver);
295	platform_driver_unregister(&hidg_plat_driver);
296}
297module_exit(hidg_cleanup);