1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <linux/kernel.h>
44#include <linux/slab.h>
45#include <linux/utsname.h>
46#include <linux/device.h>
47
48#include "g_zero.h"
49#include "gadget_chips.h"
50
51
52
53
54
55
56
57
58
59
60
61#include "composite.c"
62#include "usbstring.c"
63#include "config.c"
64#include "epautoconf.c"
65
66#include "f_sourcesink.c"
67#include "f_loopback.c"
68
69
70
71#define DRIVER_VERSION "Cinco de Mayo 2008"
72
73static const char longname[] = "Gadget Zero";
74
75unsigned buflen = 4096;
76module_param(buflen, uint, 0);
77
78
79
80
81
82
83
84static int loopdefault = 0;
85module_param(loopdefault, bool, S_IRUGO|S_IWUSR);
86
87
88
89
90
91
92
93
94#ifndef CONFIG_USB_ZERO_HNPTEST
95#define DRIVER_VENDOR_NUM 0x0525
96#define DRIVER_PRODUCT_NUM 0xa4a0
97#define DEFAULT_AUTORESUME 0
98#else
99#define DRIVER_VENDOR_NUM 0x1a0a
100#define DRIVER_PRODUCT_NUM 0xbadd
101#define DEFAULT_AUTORESUME 5
102#endif
103
104
105
106
107
108unsigned autoresume = DEFAULT_AUTORESUME;
109module_param(autoresume, uint, S_IRUGO);
110MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup");
111
112
113
114static struct usb_device_descriptor device_desc = {
115 .bLength = sizeof device_desc,
116 .bDescriptorType = USB_DT_DEVICE,
117
118 .bcdUSB = cpu_to_le16(0x0200),
119 .bDeviceClass = USB_CLASS_VENDOR_SPEC,
120
121 .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM),
122 .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM),
123 .bNumConfigurations = 2,
124};
125
126#ifdef CONFIG_USB_OTG
127static struct usb_otg_descriptor otg_descriptor = {
128 .bLength = sizeof otg_descriptor,
129 .bDescriptorType = USB_DT_OTG,
130
131
132
133
134 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
135};
136
137const struct usb_descriptor_header *otg_desc[] = {
138 (struct usb_descriptor_header *) &otg_descriptor,
139 NULL,
140};
141#endif
142
143
144
145#define STRING_MANUFACTURER_IDX 0
146#define STRING_PRODUCT_IDX 1
147#define STRING_SERIAL_IDX 2
148
149static char manufacturer[50];
150
151
152static char serial[] = "0123456789.0123456789.0123456789";
153
154static struct usb_string strings_dev[] = {
155 [STRING_MANUFACTURER_IDX].s = manufacturer,
156 [STRING_PRODUCT_IDX].s = longname,
157 [STRING_SERIAL_IDX].s = serial,
158 { }
159};
160
161static struct usb_gadget_strings stringtab_dev = {
162 .language = 0x0409,
163 .strings = strings_dev,
164};
165
166static struct usb_gadget_strings *dev_strings[] = {
167 &stringtab_dev,
168 NULL,
169};
170
171
172
173struct usb_request *alloc_ep_req(struct usb_ep *ep)
174{
175 struct usb_request *req;
176
177 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
178 if (req) {
179 req->length = buflen;
180 req->buf = kmalloc(buflen, GFP_ATOMIC);
181 if (!req->buf) {
182 usb_ep_free_request(ep, req);
183 req = NULL;
184 }
185 }
186 return req;
187}
188
189void free_ep_req(struct usb_ep *ep, struct usb_request *req)
190{
191 kfree(req->buf);
192 usb_ep_free_request(ep, req);
193}
194
195static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
196{
197 int value;
198
199 if (ep->driver_data) {
200 value = usb_ep_disable(ep);
201 if (value < 0)
202 DBG(cdev, "disable %s --> %d\n",
203 ep->name, value);
204 ep->driver_data = NULL;
205 }
206}
207
208void disable_endpoints(struct usb_composite_dev *cdev,
209 struct usb_ep *in, struct usb_ep *out)
210{
211 disable_ep(cdev, in);
212 disable_ep(cdev, out);
213}
214
215
216
217static struct timer_list autoresume_timer;
218
219static void zero_autoresume(unsigned long _c)
220{
221 struct usb_composite_dev *cdev = (void *)_c;
222 struct usb_gadget *g = cdev->gadget;
223
224
225 if (!cdev->config)
226 return;
227
228
229
230
231
232 if (g->speed != USB_SPEED_UNKNOWN) {
233 int status = usb_gadget_wakeup(g);
234 INFO(cdev, "%s --> %d\n", __func__, status);
235 }
236}
237
238static void zero_suspend(struct usb_composite_dev *cdev)
239{
240 if (cdev->gadget->speed == USB_SPEED_UNKNOWN)
241 return;
242
243 if (autoresume) {
244 mod_timer(&autoresume_timer, jiffies + (HZ * autoresume));
245 DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume);
246 } else
247 DBG(cdev, "%s\n", __func__);
248}
249
250static void zero_resume(struct usb_composite_dev *cdev)
251{
252 DBG(cdev, "%s\n", __func__);
253 del_timer(&autoresume_timer);
254}
255
256
257
258static int __init zero_bind(struct usb_composite_dev *cdev)
259{
260 int gcnum;
261 struct usb_gadget *gadget = cdev->gadget;
262 int id;
263
264
265
266
267 id = usb_string_id(cdev);
268 if (id < 0)
269 return id;
270 strings_dev[STRING_MANUFACTURER_IDX].id = id;
271 device_desc.iManufacturer = id;
272
273 id = usb_string_id(cdev);
274 if (id < 0)
275 return id;
276 strings_dev[STRING_PRODUCT_IDX].id = id;
277 device_desc.iProduct = id;
278
279 id = usb_string_id(cdev);
280 if (id < 0)
281 return id;
282 strings_dev[STRING_SERIAL_IDX].id = id;
283 device_desc.iSerialNumber = id;
284
285 setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev);
286
287
288
289
290 if (loopdefault) {
291 loopback_add(cdev, autoresume != 0);
292 sourcesink_add(cdev, autoresume != 0);
293 } else {
294 sourcesink_add(cdev, autoresume != 0);
295 loopback_add(cdev, autoresume != 0);
296 }
297
298 gcnum = usb_gadget_controller_number(gadget);
299 if (gcnum >= 0)
300 device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum);
301 else {
302
303
304
305
306
307
308
309 pr_warning("%s: controller '%s' not recognized\n",
310 longname, gadget->name);
311 device_desc.bcdDevice = cpu_to_le16(0x9999);
312 }
313
314
315 INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname);
316
317 snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
318 init_utsname()->sysname, init_utsname()->release,
319 gadget->name);
320
321 return 0;
322}
323
324static int zero_unbind(struct usb_composite_dev *cdev)
325{
326 del_timer_sync(&autoresume_timer);
327 return 0;
328}
329
330static struct usb_composite_driver zero_driver = {
331 .name = "zero",
332 .dev = &device_desc,
333 .strings = dev_strings,
334 .max_speed = USB_SPEED_SUPER,
335 .unbind = zero_unbind,
336 .suspend = zero_suspend,
337 .resume = zero_resume,
338};
339
340MODULE_AUTHOR("David Brownell");
341MODULE_LICENSE("GPL");
342
343static int __init init(void)
344{
345 return usb_composite_probe(&zero_driver, zero_bind);
346}
347module_init(init);
348
349static void __exit cleanup(void)
350{
351 usb_composite_unregister(&zero_driver);
352}
353module_exit(cleanup);
354