Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/*
  2 * hid.c -- HID Composite driver
  3 *
  4 * Based on multi.c
  5 *
  6 * Copyright (C) 2010 Fabien Chouteau <fabien.chouteau@barco.com>
  7 *
  8 * This program is free software; you can redistribute it and/or modify
  9 * it under the terms of the GNU General Public License as published by
 10 * the Free Software Foundation; either version 2 of the License, or
 11 * (at your option) any later version.
 12 */
 13
 14
 15#include <linux/kernel.h>
 16#include <linux/platform_device.h>
 17#include <linux/list.h>
 18#include <linux/module.h>
 19#include <linux/usb/composite.h>
 20
 21#include "gadget_chips.h"
 22#define DRIVER_DESC		"HID Gadget"
 23#define DRIVER_VERSION		"2010/03/16"
 24
 25/*-------------------------------------------------------------------------*/
 26
 27#define HIDG_VENDOR_NUM		0x0525	/* XXX NetChip */
 28#define HIDG_PRODUCT_NUM	0xa4ac	/* Linux-USB HID gadget */
 29
 30/*-------------------------------------------------------------------------*/
 31
 32/*
 33 * kbuild is not very cooperative with respect to linking separately
 34 * compiled library objects into one module.  So for now we won't use
 35 * separate compilation ... ensuring init/exit sections work to shrink
 36 * the runtime footprint, and giving us at least some parts of what
 37 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
 38 */
 39#include "f_hid.c"
 40
 41
 42struct hidg_func_node {
 43	struct list_head node;
 44	struct hidg_func_descriptor *func;
 45};
 46
 47static LIST_HEAD(hidg_func_list);
 48
 49/*-------------------------------------------------------------------------*/
 50USB_GADGET_COMPOSITE_OPTIONS();
 51
 52static struct usb_device_descriptor device_desc = {
 53	.bLength =		sizeof device_desc,
 54	.bDescriptorType =	USB_DT_DEVICE,
 55
 56	.bcdUSB =		cpu_to_le16(0x0200),
 57
 58	/* .bDeviceClass =		USB_CLASS_COMM, */
 59	/* .bDeviceSubClass =	0, */
 60	/* .bDeviceProtocol =	0, */
 61	.bDeviceClass =		USB_CLASS_PER_INTERFACE,
 62	.bDeviceSubClass =	0,
 63	.bDeviceProtocol =	0,
 64	/* .bMaxPacketSize0 = f(hardware) */
 65
 66	/* Vendor and product id can be overridden by module parameters.  */
 67	.idVendor =		cpu_to_le16(HIDG_VENDOR_NUM),
 68	.idProduct =		cpu_to_le16(HIDG_PRODUCT_NUM),
 69	/* .bcdDevice = f(hardware) */
 70	/* .iManufacturer = DYNAMIC */
 71	/* .iProduct = DYNAMIC */
 72	/* NO SERIAL NUMBER */
 73	.bNumConfigurations =	1,
 74};
 75
 76static struct usb_otg_descriptor otg_descriptor = {
 77	.bLength =		sizeof otg_descriptor,
 78	.bDescriptorType =	USB_DT_OTG,
 79
 80	/* REVISIT SRP-only hardware is possible, although
 81	 * it would not be called "OTG" ...
 82	 */
 83	.bmAttributes =		USB_OTG_SRP | USB_OTG_HNP,
 84};
 85
 86static const struct usb_descriptor_header *otg_desc[] = {
 87	(struct usb_descriptor_header *) &otg_descriptor,
 88	NULL,
 89};
 90
 91
 92/* string IDs are assigned dynamically */
 93static struct usb_string strings_dev[] = {
 94	[USB_GADGET_MANUFACTURER_IDX].s = "",
 95	[USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
 96	[USB_GADGET_SERIAL_IDX].s = "",
 97	{  } /* end of list */
 98};
 99
100static struct usb_gadget_strings stringtab_dev = {
101	.language	= 0x0409,	/* en-us */
102	.strings	= strings_dev,
103};
104
105static struct usb_gadget_strings *dev_strings[] = {
106	&stringtab_dev,
107	NULL,
108};
109
110
111
112/****************************** Configurations ******************************/
113
114static int __init do_config(struct usb_configuration *c)
115{
116	struct hidg_func_node *e;
117	int func = 0, status = 0;
118
119	if (gadget_is_otg(c->cdev->gadget)) {
120		c->descriptors = otg_desc;
121		c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
122	}
123
124	list_for_each_entry(e, &hidg_func_list, node) {
125		status = hidg_bind_config(c, e->func, func++);
126		if (status)
127			break;
128	}
129
130	return status;
131}
132
133static struct usb_configuration config_driver = {
134	.label			= "HID Gadget",
135	.bConfigurationValue	= 1,
136	/* .iConfiguration = DYNAMIC */
137	.bmAttributes		= USB_CONFIG_ATT_SELFPOWER,
138};
139
140/****************************** Gadget Bind ******************************/
141
142static int __init hid_bind(struct usb_composite_dev *cdev)
143{
144	struct usb_gadget *gadget = cdev->gadget;
145	struct list_head *tmp;
146	int status, funcs = 0;
147
148	list_for_each(tmp, &hidg_func_list)
149		funcs++;
150
151	if (!funcs)
152		return -ENODEV;
153
154	/* set up HID */
155	status = ghid_setup(cdev->gadget, funcs);
156	if (status < 0)
157		return status;
158
159	/* Allocate string descriptor numbers ... note that string
160	 * contents can be overridden by the composite_dev glue.
161	 */
162
163	status = usb_string_ids_tab(cdev, strings_dev);
164	if (status < 0)
165		return status;
166	device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id;
167	device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id;
168
169	/* register our configuration */
170	status = usb_add_config(cdev, &config_driver, do_config);
171	if (status < 0)
172		return status;
173
174	usb_composite_overwrite_options(cdev, &coverwrite);
175	dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
176
177	return 0;
178}
179
180static int __exit hid_unbind(struct usb_composite_dev *cdev)
181{
182	ghid_cleanup();
183	return 0;
184}
185
186static int __init hidg_plat_driver_probe(struct platform_device *pdev)
187{
188	struct hidg_func_descriptor *func = dev_get_platdata(&pdev->dev);
189	struct hidg_func_node *entry;
190
191	if (!func) {
192		dev_err(&pdev->dev, "Platform data missing\n");
193		return -ENODEV;
194	}
195
196	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
197	if (!entry)
198		return -ENOMEM;
199
200	entry->func = func;
201	list_add_tail(&entry->node, &hidg_func_list);
202
203	return 0;
204}
205
206static int hidg_plat_driver_remove(struct platform_device *pdev)
207{
208	struct hidg_func_node *e, *n;
209
210	list_for_each_entry_safe(e, n, &hidg_func_list, node) {
211		list_del(&e->node);
212		kfree(e);
213	}
214
215	return 0;
216}
217
218
219/****************************** Some noise ******************************/
220
221
222static __refdata struct usb_composite_driver hidg_driver = {
223	.name		= "g_hid",
224	.dev		= &device_desc,
225	.strings	= dev_strings,
226	.max_speed	= USB_SPEED_HIGH,
227	.bind		= hid_bind,
228	.unbind		= __exit_p(hid_unbind),
229};
230
231static struct platform_driver hidg_plat_driver = {
232	.remove		= hidg_plat_driver_remove,
233	.driver		= {
234		.owner	= THIS_MODULE,
235		.name	= "hidg",
236	},
237};
238
239
240MODULE_DESCRIPTION(DRIVER_DESC);
241MODULE_AUTHOR("Fabien Chouteau, Peter Korsgaard");
242MODULE_LICENSE("GPL");
243
244static int __init hidg_init(void)
245{
246	int status;
247
248	status = platform_driver_probe(&hidg_plat_driver,
249				hidg_plat_driver_probe);
250	if (status < 0)
251		return status;
252
253	status = usb_composite_probe(&hidg_driver);
254	if (status < 0)
255		platform_driver_unregister(&hidg_plat_driver);
256
257	return status;
258}
259module_init(hidg_init);
260
261static void __exit hidg_cleanup(void)
262{
263	platform_driver_unregister(&hidg_plat_driver);
264	usb_composite_unregister(&hidg_driver);
265}
266module_exit(hidg_cleanup);