blob: 52fd3fa0d130855e24ed2724c6a675fb2394b9a2 [file] [log] [blame]
Michal Nazarewiczc6c56002010-05-05 12:53:15 +02001#include <linux/module.h>
2#include <linux/utsname.h>
3
4
5/*
6 * kbuild is not very cooperative with respect to linking separately
7 * compiled library objects into one module. So for now we won't use
8 * separate compilation ... ensuring init/exit sections work to shrink
9 * the runtime footprint, and giving us at least some parts of what
10 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
11 */
12
13#include "composite.c"
14#include "usbstring.c"
15#include "config.c"
16#include "epautoconf.c"
17
18#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
19# if defined USB_ETH_RNDIS
20# undef USB_ETH_RNDIS
21# endif
22# ifdef CONFIG_USB_FUNCTIONFS_RNDIS
23# define USB_ETH_RNDIS y
24# endif
25
26# include "f_ecm.c"
27# include "f_subset.c"
28# ifdef USB_ETH_RNDIS
29# include "f_rndis.c"
30# include "rndis.c"
31# endif
32# include "u_ether.c"
33
34static u8 gfs_hostaddr[ETH_ALEN];
Michal Nazarewiczf8dae532010-06-25 16:29:27 +020035# ifdef CONFIG_USB_FUNCTIONFS_ETH
36static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020037# endif
Michal Nazarewiczf8dae532010-06-25 16:29:27 +020038#else
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020039# define gether_cleanup() do { } while (0)
40# define gether_setup(gadget, hostaddr) ((int)0)
Michal Nazarewiczf8dae532010-06-25 16:29:27 +020041# define gfs_hostaddr NULL
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020042#endif
43
44#include "f_fs.c"
45
46
47#define DRIVER_NAME "g_ffs"
48#define DRIVER_DESC "USB Function Filesystem"
49#define DRIVER_VERSION "24 Aug 2004"
50
51MODULE_DESCRIPTION(DRIVER_DESC);
52MODULE_AUTHOR("Michal Nazarewicz");
53MODULE_LICENSE("GPL");
54
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020055#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
56#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020057
58static struct usb_device_descriptor gfs_dev_desc = {
59 .bLength = sizeof gfs_dev_desc,
60 .bDescriptorType = USB_DT_DEVICE,
61
62 .bcdUSB = cpu_to_le16(0x0200),
63 .bDeviceClass = USB_CLASS_PER_INTERFACE,
64
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020065 .idVendor = cpu_to_le16(GFS_VENDOR_ID),
66 .idProduct = cpu_to_le16(GFS_PRODUCT_ID),
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020067};
68
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020069module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644);
70MODULE_PARM_DESC(bDeviceClass, "USB Device class");
71module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
72MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
73module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
74MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020075
76
77
78static const struct usb_descriptor_header *gfs_otg_desc[] = {
79 (const struct usb_descriptor_header *)
80 &(const struct usb_otg_descriptor) {
81 .bLength = sizeof(struct usb_otg_descriptor),
82 .bDescriptorType = USB_DT_OTG,
83
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020084 /*
85 * REVISIT SRP-only hardware is possible, although
86 * it would not be called "OTG" ...
87 */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020088 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
89 },
90
91 NULL
92};
93
94/* string IDs are assigned dynamically */
95
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020096static struct usb_string gfs_strings[] = {
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020097#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
Michal Nazarewiczf8dae532010-06-25 16:29:27 +020098 { .s = "FunctionFS + RNDIS" },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020099#endif
100#ifdef CONFIG_USB_FUNCTIONFS_ETH
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200101 { .s = "FunctionFS + ECM" },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200102#endif
103#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200104 { .s = "FunctionFS" },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200105#endif
106 { } /* end of list */
107};
108
109static struct usb_gadget_strings *gfs_dev_strings[] = {
110 &(struct usb_gadget_strings) {
111 .language = 0x0409, /* en-us */
112 .strings = gfs_strings,
113 },
114 NULL,
115};
116
117
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200118
119struct gfs_configuration {
120 struct usb_configuration c;
121 int (*eth)(struct usb_configuration *c, u8 *ethaddr);
122} gfs_configurations[] = {
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200123#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200124 {
125 .eth = rndis_bind_config,
126 },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200127#endif
128
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200129#ifdef CONFIG_USB_FUNCTIONFS_ETH
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200130 {
131 .eth = eth_bind_config,
132 },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200133#endif
134
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200135#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200136 {
137 },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200138#endif
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200139};
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200140
141
142static int gfs_bind(struct usb_composite_dev *cdev);
143static int gfs_unbind(struct usb_composite_dev *cdev);
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200144static int gfs_do_config(struct usb_configuration *c);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200145
146static struct usb_composite_driver gfs_driver = {
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200147 .name = DRIVER_NAME,
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200148 .dev = &gfs_dev_desc,
149 .strings = gfs_dev_strings,
150 .bind = gfs_bind,
151 .unbind = gfs_unbind,
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200152 .iProduct = DRIVER_DESC,
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200153};
154
155
156static struct ffs_data *gfs_ffs_data;
157static unsigned long gfs_registered;
158
159
160static int gfs_init(void)
161{
162 ENTER();
163
164 return functionfs_init();
165}
166module_init(gfs_init);
167
168static void gfs_exit(void)
169{
170 ENTER();
171
172 if (test_and_clear_bit(0, &gfs_registered))
173 usb_composite_unregister(&gfs_driver);
174
175 functionfs_cleanup();
176}
177module_exit(gfs_exit);
178
179
180static int functionfs_ready_callback(struct ffs_data *ffs)
181{
182 int ret;
183
184 ENTER();
185
186 if (WARN_ON(test_and_set_bit(0, &gfs_registered)))
187 return -EBUSY;
188
189 gfs_ffs_data = ffs;
190 ret = usb_composite_register(&gfs_driver);
191 if (unlikely(ret < 0))
192 clear_bit(0, &gfs_registered);
193 return ret;
194}
195
196static void functionfs_closed_callback(struct ffs_data *ffs)
197{
198 ENTER();
199
200 if (test_and_clear_bit(0, &gfs_registered))
201 usb_composite_unregister(&gfs_driver);
202}
203
204
205static int functionfs_check_dev_callback(const char *dev_name)
206{
207 return 0;
208}
209
210
211
212static int gfs_bind(struct usb_composite_dev *cdev)
213{
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200214 int ret, i;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200215
216 ENTER();
217
218 if (WARN_ON(!gfs_ffs_data))
219 return -ENODEV;
220
221 ret = gether_setup(cdev->gadget, gfs_hostaddr);
222 if (unlikely(ret < 0))
223 goto error_quick;
224
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200225 ret = usb_string_ids_tab(cdev, gfs_strings);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200226 if (unlikely(ret < 0))
227 goto error;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200228
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200229 ret = functionfs_bind(gfs_ffs_data, cdev);
230 if (unlikely(ret < 0))
231 goto error;
232
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200233 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
234 struct gfs_configuration *c = gfs_configurations + i;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200235
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200236 c->c.label = gfs_strings[i].s;
237 c->c.iConfiguration = gfs_strings[i].id;
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200238 c->c.bind = gfs_do_config;
239 c->c.bConfigurationValue = 1 + i;
240 c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200241
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200242 ret = usb_add_config(cdev, &c->c);
243 if (unlikely(ret < 0))
244 goto error_unbind;
245 }
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200246
247 return 0;
248
249error_unbind:
250 functionfs_unbind(gfs_ffs_data);
251error:
252 gether_cleanup();
253error_quick:
254 gfs_ffs_data = NULL;
255 return ret;
256}
257
258static int gfs_unbind(struct usb_composite_dev *cdev)
259{
260 ENTER();
261
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200262 /*
263 * We may have been called in an error recovery from
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200264 * composite_bind() after gfs_unbind() failure so we need to
265 * check if gfs_ffs_data is not NULL since gfs_bind() handles
266 * all error recovery itself. I'd rather we werent called
267 * from composite on orror recovery, but what you're gonna
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200268 * do...?
269 */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200270 if (gfs_ffs_data) {
271 gether_cleanup();
272 functionfs_unbind(gfs_ffs_data);
273 gfs_ffs_data = NULL;
274 }
275
276 return 0;
277}
278
279
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200280static int gfs_do_config(struct usb_configuration *c)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200281{
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200282 struct gfs_configuration *gc =
283 container_of(c, struct gfs_configuration, c);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200284 int ret;
285
286 if (WARN_ON(!gfs_ffs_data))
287 return -ENODEV;
288
289 if (gadget_is_otg(c->cdev->gadget)) {
290 c->descriptors = gfs_otg_desc;
291 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
292 }
293
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200294 if (gc->eth) {
295 ret = gc->eth(c, gfs_hostaddr);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200296 if (unlikely(ret < 0))
297 return ret;
298 }
299
Michal Nazarewicz7898aee2010-06-16 12:07:58 +0200300 ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200301 if (unlikely(ret < 0))
302 return ret;
303
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200304 /*
305 * After previous do_configs there may be some invalid
Michal Nazarewiczf588c0d2010-06-14 10:43:34 +0200306 * pointers in c->interface array. This happens every time
307 * a user space function with fewer interfaces than a user
308 * space function that was run before the new one is run. The
309 * compasit's set_config() assumes that if there is no more
310 * then MAX_CONFIG_INTERFACES interfaces in a configuration
311 * then there is a NULL pointer after the last interface in
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200312 * c->interface array. We need to make sure this is true.
313 */
Michal Nazarewiczf588c0d2010-06-14 10:43:34 +0200314 if (c->next_interface_id < ARRAY_SIZE(c->interface))
315 c->interface[c->next_interface_id] = NULL;
316
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200317 return 0;
318}
319
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200320
321#ifdef CONFIG_USB_FUNCTIONFS_ETH
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200322
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200323static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200324{
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200325 return can_support_ecm(c->cdev->gadget)
326 ? ecm_bind_config(c, ethaddr)
327 : geth_bind_config(c, ethaddr);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200328}
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200329
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200330#endif