blob: 64711feca8454fe4b8455082e099482a542cd3a3 [file] [log] [blame]
Michal Nazarewiczf176a5d2009-11-09 14:15:27 +01001/*
2 * multi.c -- Multifunction Composite driver
3 *
4 * Copyright (C) 2008 David Brownell
5 * Copyright (C) 2008 Nokia Corporation
6 * Copyright (C) 2009 Samsung Electronics
7 * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24
25#include <linux/kernel.h>
26#include <linux/utsname.h>
27
28
29#if defined CONFIG_USB_G_MULTI_RNDIS
30# define CONFIG_USB_ETH_RNDIS y
31#endif
32
33
34#define DRIVER_DESC "Multifunction Composite Gadget"
35#define DRIVER_VERSION "2009/07/21"
36
37/*-------------------------------------------------------------------------*/
38
39#define MULTI_VENDOR_NUM 0x0525 /* XXX NetChip */
40#define MULTI_PRODUCT_NUM 0xa4ab /* XXX */
41
42/*-------------------------------------------------------------------------*/
43
44/*
45 * kbuild is not very cooperative with respect to linking separately
46 * compiled library objects into one module. So for now we won't use
47 * separate compilation ... ensuring init/exit sections work to shrink
48 * the runtime footprint, and giving us at least some parts of what
49 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
50 */
51
52#include "composite.c"
53#include "usbstring.c"
54#include "config.c"
55#include "epautoconf.c"
56
57#include "u_serial.c"
58#include "f_acm.c"
59
60#include "f_ecm.c"
61#include "f_subset.c"
62#ifdef CONFIG_USB_ETH_RNDIS
63# include "f_rndis.c"
64# include "rndis.c"
65#endif
66#include "u_ether.c"
67
68#undef DBG /* u_ether.c has broken idea about macros */
69#undef VDBG /* so clean up after it */
70#undef ERROR
71#undef INFO
72#include "f_mass_storage.c"
73
74/*-------------------------------------------------------------------------*/
75
76static struct usb_device_descriptor device_desc = {
77 .bLength = sizeof device_desc,
78 .bDescriptorType = USB_DT_DEVICE,
79
80 .bcdUSB = cpu_to_le16(0x0200),
81
82 /* .bDeviceClass = USB_CLASS_COMM, */
83 /* .bDeviceSubClass = 0, */
84 /* .bDeviceProtocol = 0, */
85 .bDeviceClass = 0xEF,
86 .bDeviceSubClass = 2,
87 .bDeviceProtocol = 1,
88 /* .bMaxPacketSize0 = f(hardware) */
89
90 /* Vendor and product id can be overridden by module parameters. */
91 .idVendor = cpu_to_le16(MULTI_VENDOR_NUM),
92 .idProduct = cpu_to_le16(MULTI_PRODUCT_NUM),
93 /* .bcdDevice = f(hardware) */
94 /* .iManufacturer = DYNAMIC */
95 /* .iProduct = DYNAMIC */
96 /* NO SERIAL NUMBER */
97 .bNumConfigurations = 1,
98};
99
100static struct usb_otg_descriptor otg_descriptor = {
101 .bLength = sizeof otg_descriptor,
102 .bDescriptorType = USB_DT_OTG,
103
104 /* REVISIT SRP-only hardware is possible, although
105 * it would not be called "OTG" ...
106 */
107 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
108};
109
110static const struct usb_descriptor_header *otg_desc[] = {
111 (struct usb_descriptor_header *) &otg_descriptor,
112 NULL,
113};
114
115
116/* string IDs are assigned dynamically */
117
118#define STRING_MANUFACTURER_IDX 0
119#define STRING_PRODUCT_IDX 1
120
121static char manufacturer[50];
122
123static struct usb_string strings_dev[] = {
124 [STRING_MANUFACTURER_IDX].s = manufacturer,
125 [STRING_PRODUCT_IDX].s = DRIVER_DESC,
126 { } /* end of list */
127};
128
129static struct usb_gadget_strings stringtab_dev = {
130 .language = 0x0409, /* en-us */
131 .strings = strings_dev,
132};
133
134static struct usb_gadget_strings *dev_strings[] = {
135 &stringtab_dev,
136 NULL,
137};
138
139static u8 hostaddr[ETH_ALEN];
140
141
142
143/****************************** Configurations ******************************/
144
145static struct fsg_module_parameters mod_data = {
146 .stall = 1
147};
148FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
149
150static struct fsg_common *fsg_common;
151
152
153#ifdef CONFIG_USB_ETH_RNDIS
154
155static int __init rndis_do_config(struct usb_configuration *c)
156{
157 int ret;
158
159 if (gadget_is_otg(c->cdev->gadget)) {
160 c->descriptors = otg_desc;
161 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
162 }
163
164 ret = rndis_bind_config(c, hostaddr);
165 if (ret < 0)
166 return ret;
167
168 ret = acm_bind_config(c, 0);
169 if (ret < 0)
170 return ret;
171
172 ret = fsg_add(c->cdev, c, fsg_common);
173 if (ret < 0)
174 return ret;
175
176 return 0;
177}
178
179static struct usb_configuration rndis_config_driver = {
180 .label = "Multifunction Composite (RNDIS + MS + ACM)",
181 .bind = rndis_do_config,
182 .bConfigurationValue = 2,
183 /* .iConfiguration = DYNAMIC */
184 .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
185};
186
187#endif
188
189#ifdef CONFIG_USB_G_MULTI_CDC
190
191static int __init cdc_do_config(struct usb_configuration *c)
192{
193 int ret;
194
195 if (gadget_is_otg(c->cdev->gadget)) {
196 c->descriptors = otg_desc;
197 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
198 }
199
200 ret = ecm_bind_config(c, hostaddr);
201 if (ret < 0)
202 return ret;
203
204 ret = acm_bind_config(c, 0);
205 if (ret < 0)
206 return ret;
207
208 ret = fsg_add(c->cdev, c, fsg_common);
209 if (ret < 0)
210 return ret;
211 if (ret < 0)
212 return ret;
213
214 return 0;
215}
216
217static struct usb_configuration cdc_config_driver = {
218 .label = "Multifunction Composite (CDC + MS + ACM)",
219 .bind = cdc_do_config,
220 .bConfigurationValue = 1,
221 /* .iConfiguration = DYNAMIC */
222 .bmAttributes = USB_CONFIG_ATT_SELFPOWER,
223};
224
225#endif
226
227
228
229/****************************** Gadget Bind ******************************/
230
231
232static int __init multi_bind(struct usb_composite_dev *cdev)
233{
234 struct usb_gadget *gadget = cdev->gadget;
235 int status, gcnum;
236
237 if (!can_support_ecm(cdev->gadget)) {
238 dev_err(&gadget->dev, "controller '%s' not usable\n",
239 gadget->name);
240 return -EINVAL;
241 }
242
243 /* set up network link layer */
244 status = gether_setup(cdev->gadget, hostaddr);
245 if (status < 0)
246 return status;
247
248 /* set up serial link layer */
249 status = gserial_setup(cdev->gadget, 1);
250 if (status < 0)
251 goto fail0;
252
253 /* set up mass storage function */
254 fsg_common = fsg_common_from_params(0, cdev, &mod_data);
255 if (IS_ERR(fsg_common)) {
256 status = PTR_ERR(fsg_common);
257 goto fail1;
258 }
259
260
261 gcnum = usb_gadget_controller_number(gadget);
262 if (gcnum >= 0)
263 device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
264 else {
265 /* We assume that can_support_ecm() tells the truth;
266 * but if the controller isn't recognized at all then
267 * that assumption is a bit more likely to be wrong.
268 */
269 WARNING(cdev, "controller '%s' not recognized\n",
270 gadget->name);
271 device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
272 }
273
274
275 /* Allocate string descriptor numbers ... note that string
276 * contents can be overridden by the composite_dev glue.
277 */
278
279 /* device descriptor strings: manufacturer, product */
280 snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
281 init_utsname()->sysname, init_utsname()->release,
282 gadget->name);
283 status = usb_string_id(cdev);
284 if (status < 0)
285 goto fail2;
286 strings_dev[STRING_MANUFACTURER_IDX].id = status;
287 device_desc.iManufacturer = status;
288
289 status = usb_string_id(cdev);
290 if (status < 0)
291 goto fail2;
292 strings_dev[STRING_PRODUCT_IDX].id = status;
293 device_desc.iProduct = status;
294
295#ifdef CONFIG_USB_ETH_RNDIS
296 /* register our first configuration */
297 status = usb_add_config(cdev, &rndis_config_driver);
298 if (status < 0)
299 goto fail2;
300#endif
301
302#ifdef CONFIG_USB_G_MULTI_CDC
303 /* register our second configuration */
304 status = usb_add_config(cdev, &cdc_config_driver);
305 if (status < 0)
306 goto fail2;
307#endif
308
309 dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n");
310 fsg_common_put(fsg_common);
311 return 0;
312
313fail2:
314 fsg_common_put(fsg_common);
315fail1:
316 gserial_cleanup();
317fail0:
318 gether_cleanup();
319 return status;
320}
321
322static int __exit multi_unbind(struct usb_composite_dev *cdev)
323{
324 gserial_cleanup();
325 gether_cleanup();
326 return 0;
327}
328
329
330/****************************** Some noise ******************************/
331
332
333static struct usb_composite_driver multi_driver = {
334 .name = "g_multi",
335 .dev = &device_desc,
336 .strings = dev_strings,
337 .bind = multi_bind,
338 .unbind = __exit_p(multi_unbind),
339};
340
341MODULE_DESCRIPTION(DRIVER_DESC);
342MODULE_AUTHOR("Michal Nazarewicz");
343MODULE_LICENSE("GPL");
344
345static int __init g_multi_init(void)
346{
347 return usb_composite_register(&multi_driver);
348}
349module_init(g_multi_init);
350
351static void __exit g_multi_cleanup(void)
352{
353 usb_composite_unregister(&multi_driver);
354}
355module_exit(g_multi_cleanup);