Merge branch 'drm-core-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[pandora-kernel.git] / drivers / usb / gadget / multi.c
1 /*
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 #include <linux/module.h>
28
29
30 #if defined USB_ETH_RNDIS
31 #  undef USB_ETH_RNDIS
32 #endif
33 #ifdef CONFIG_USB_G_MULTI_RNDIS
34 #  define USB_ETH_RNDIS y
35 #endif
36
37
38 #define DRIVER_DESC             "Multifunction Composite Gadget"
39
40 MODULE_DESCRIPTION(DRIVER_DESC);
41 MODULE_AUTHOR("Michal Nazarewicz");
42 MODULE_LICENSE("GPL");
43
44
45 /***************************** All the files... *****************************/
46
47 /*
48  * kbuild is not very cooperative with respect to linking separately
49  * compiled library objects into one module.  So for now we won't use
50  * separate compilation ... ensuring init/exit sections work to shrink
51  * the runtime footprint, and giving us at least some parts of what
52  * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
53  */
54
55 #include "composite.c"
56 #include "usbstring.c"
57 #include "config.c"
58 #include "epautoconf.c"
59
60 #include "f_mass_storage.c"
61
62 #include "u_serial.c"
63 #include "f_acm.c"
64
65 #include "f_ecm.c"
66 #include "f_subset.c"
67 #ifdef USB_ETH_RNDIS
68 #  include "f_rndis.c"
69 #  include "rndis.c"
70 #endif
71 #include "u_ether.c"
72
73
74
75 /***************************** Device Descriptor ****************************/
76
77 #define MULTI_VENDOR_NUM        0x0525  /* XXX NetChip */
78 #define MULTI_PRODUCT_NUM       0xa4ab  /* XXX */
79
80
81 enum {
82         __MULTI_NO_CONFIG,
83 #ifdef CONFIG_USB_G_MULTI_RNDIS
84         MULTI_RNDIS_CONFIG_NUM,
85 #endif
86 #ifdef CONFIG_USB_G_MULTI_CDC
87         MULTI_CDC_CONFIG_NUM,
88 #endif
89 };
90
91
92 static struct usb_device_descriptor device_desc = {
93         .bLength =              sizeof device_desc,
94         .bDescriptorType =      USB_DT_DEVICE,
95
96         .bcdUSB =               cpu_to_le16(0x0200),
97
98         .bDeviceClass =         USB_CLASS_MISC /* 0xEF */,
99         .bDeviceSubClass =      2,
100         .bDeviceProtocol =      1,
101
102         /* Vendor and product id can be overridden by module parameters.  */
103         .idVendor =             cpu_to_le16(MULTI_VENDOR_NUM),
104         .idProduct =            cpu_to_le16(MULTI_PRODUCT_NUM),
105 };
106
107
108 static const struct usb_descriptor_header *otg_desc[] = {
109         (struct usb_descriptor_header *) &(struct usb_otg_descriptor){
110                 .bLength =              sizeof(struct usb_otg_descriptor),
111                 .bDescriptorType =      USB_DT_OTG,
112
113                 /*
114                  * REVISIT SRP-only hardware is possible, although
115                  * it would not be called "OTG" ...
116                  */
117                 .bmAttributes =         USB_OTG_SRP | USB_OTG_HNP,
118         },
119         NULL,
120 };
121
122
123 enum {
124         MULTI_STRING_MANUFACTURER_IDX,
125         MULTI_STRING_PRODUCT_IDX,
126 #ifdef CONFIG_USB_G_MULTI_RNDIS
127         MULTI_STRING_RNDIS_CONFIG_IDX,
128 #endif
129 #ifdef CONFIG_USB_G_MULTI_CDC
130         MULTI_STRING_CDC_CONFIG_IDX,
131 #endif
132 };
133
134 static char manufacturer[50];
135
136 static struct usb_string strings_dev[] = {
137         [MULTI_STRING_MANUFACTURER_IDX].s = manufacturer,
138         [MULTI_STRING_PRODUCT_IDX].s      = DRIVER_DESC,
139 #ifdef CONFIG_USB_G_MULTI_RNDIS
140         [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS",
141 #endif
142 #ifdef CONFIG_USB_G_MULTI_CDC
143         [MULTI_STRING_CDC_CONFIG_IDX].s   = "Multifunction with CDC ECM",
144 #endif
145         {  } /* end of list */
146 };
147
148 static struct usb_gadget_strings *dev_strings[] = {
149         &(struct usb_gadget_strings){
150                 .language       = 0x0409,       /* en-us */
151                 .strings        = strings_dev,
152         },
153         NULL,
154 };
155
156
157
158
159 /****************************** Configurations ******************************/
160
161 static struct fsg_module_parameters fsg_mod_data = { .stall = 1 };
162 FSG_MODULE_PARAMETERS(/* no prefix */, fsg_mod_data);
163
164 static struct fsg_common fsg_common;
165
166 static u8 hostaddr[ETH_ALEN];
167
168
169 /********** RNDIS **********/
170
171 #ifdef USB_ETH_RNDIS
172
173 static __ref int rndis_do_config(struct usb_configuration *c)
174 {
175         int ret;
176
177         if (gadget_is_otg(c->cdev->gadget)) {
178                 c->descriptors = otg_desc;
179                 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
180         }
181
182         ret = rndis_bind_config(c, hostaddr);
183         if (ret < 0)
184                 return ret;
185
186         ret = acm_bind_config(c, 0);
187         if (ret < 0)
188                 return ret;
189
190         ret = fsg_bind_config(c->cdev, c, &fsg_common);
191         if (ret < 0)
192                 return ret;
193
194         return 0;
195 }
196
197 static int rndis_config_register(struct usb_composite_dev *cdev)
198 {
199         static struct usb_configuration config = {
200                 .bind                   = rndis_do_config,
201                 .bConfigurationValue    = MULTI_RNDIS_CONFIG_NUM,
202                 .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
203         };
204
205         config.label          = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].s;
206         config.iConfiguration = strings_dev[MULTI_STRING_RNDIS_CONFIG_IDX].id;
207
208         return usb_add_config(cdev, &config);
209 }
210
211 #else
212
213 static int rndis_config_register(struct usb_composite_dev *cdev)
214 {
215         return 0;
216 }
217
218 #endif
219
220
221 /********** CDC ECM **********/
222
223 #ifdef CONFIG_USB_G_MULTI_CDC
224
225 static __ref int cdc_do_config(struct usb_configuration *c)
226 {
227         int ret;
228
229         if (gadget_is_otg(c->cdev->gadget)) {
230                 c->descriptors = otg_desc;
231                 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
232         }
233
234         ret = ecm_bind_config(c, hostaddr);
235         if (ret < 0)
236                 return ret;
237
238         ret = acm_bind_config(c, 0);
239         if (ret < 0)
240                 return ret;
241
242         ret = fsg_bind_config(c->cdev, c, &fsg_common);
243         if (ret < 0)
244                 return ret;
245
246         return 0;
247 }
248
249 static int cdc_config_register(struct usb_composite_dev *cdev)
250 {
251         static struct usb_configuration config = {
252                 .bind                   = cdc_do_config,
253                 .bConfigurationValue    = MULTI_CDC_CONFIG_NUM,
254                 .bmAttributes           = USB_CONFIG_ATT_SELFPOWER,
255         };
256
257         config.label          = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].s;
258         config.iConfiguration = strings_dev[MULTI_STRING_CDC_CONFIG_IDX].id;
259
260         return usb_add_config(cdev, &config);
261 }
262
263 #else
264
265 static int cdc_config_register(struct usb_composite_dev *cdev)
266 {
267         return 0;
268 }
269
270 #endif
271
272
273
274 /****************************** Gadget Bind ******************************/
275
276
277 static int __ref multi_bind(struct usb_composite_dev *cdev)
278 {
279         struct usb_gadget *gadget = cdev->gadget;
280         int status, gcnum;
281
282         if (!can_support_ecm(cdev->gadget)) {
283                 dev_err(&gadget->dev, "controller '%s' not usable\n",
284                         gadget->name);
285                 return -EINVAL;
286         }
287
288         /* set up network link layer */
289         status = gether_setup(cdev->gadget, hostaddr);
290         if (status < 0)
291                 return status;
292
293         /* set up serial link layer */
294         status = gserial_setup(cdev->gadget, 1);
295         if (status < 0)
296                 goto fail0;
297
298         /* set up mass storage function */
299         {
300                 void *retp;
301                 retp = fsg_common_from_params(&fsg_common, cdev, &fsg_mod_data);
302                 if (IS_ERR(retp)) {
303                         status = PTR_ERR(retp);
304                         goto fail1;
305                 }
306         }
307
308         /* set bcdDevice */
309         gcnum = usb_gadget_controller_number(gadget);
310         if (gcnum >= 0) {
311                 device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
312         } else {
313                 WARNING(cdev, "controller '%s' not recognized\n", gadget->name);
314                 device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099);
315         }
316
317         /* allocate string descriptor numbers */
318         snprintf(manufacturer, sizeof manufacturer, "%s %s with %s",
319                  init_utsname()->sysname, init_utsname()->release,
320                  gadget->name);
321
322         status = usb_string_ids_tab(cdev, strings_dev);
323         if (unlikely(status < 0))
324                 goto fail2;
325
326         device_desc.iManufacturer =
327                 strings_dev[MULTI_STRING_MANUFACTURER_IDX].id;
328         device_desc.iProduct      =
329                 strings_dev[MULTI_STRING_PRODUCT_IDX].id;
330
331         /* register configurations */
332         status = rndis_config_register(cdev);
333         if (unlikely(status < 0))
334                 goto fail2;
335
336         status = cdc_config_register(cdev);
337         if (unlikely(status < 0))
338                 goto fail2;
339
340         /* we're done */
341         dev_info(&gadget->dev, DRIVER_DESC "\n");
342         fsg_common_put(&fsg_common);
343         return 0;
344
345
346         /* error recovery */
347 fail2:
348         fsg_common_put(&fsg_common);
349 fail1:
350         gserial_cleanup();
351 fail0:
352         gether_cleanup();
353         return status;
354 }
355
356 static int __exit multi_unbind(struct usb_composite_dev *cdev)
357 {
358         gserial_cleanup();
359         gether_cleanup();
360         return 0;
361 }
362
363
364 /****************************** Some noise ******************************/
365
366
367 static struct usb_composite_driver multi_driver = {
368         .name           = "g_multi",
369         .dev            = &device_desc,
370         .strings        = dev_strings,
371         .bind           = multi_bind,
372         .unbind         = __exit_p(multi_unbind),
373 };
374
375
376 static int __init multi_init(void)
377 {
378         return usb_composite_register(&multi_driver);
379 }
380 module_init(multi_init);
381
382 static void __exit multi_exit(void)
383 {
384         usb_composite_unregister(&multi_driver);
385 }
386 module_exit(multi_exit);