usb gadget: don't save bind callback in struct usb_gadget_driver
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / usb / gadget / g_ffs.c
CommitLineData
c6c56008
MN
1#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];
f8dae531
MN
35# ifdef CONFIG_USB_FUNCTIONFS_ETH
36static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]);
c6c56008 37# endif
f8dae531 38#else
c6c56008
MN
39# define gether_cleanup() do { } while (0)
40# define gether_setup(gadget, hostaddr) ((int)0)
f8dae531 41# define gfs_hostaddr NULL
c6c56008
MN
42#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
fc19de61
MN
55#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
56#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
c6c56008
MN
57
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
fc19de61
MN
65 .idVendor = cpu_to_le16(GFS_VENDOR_ID),
66 .idProduct = cpu_to_le16(GFS_PRODUCT_ID),
c6c56008
MN
67};
68
fc19de61
MN
69module_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");
c6c56008
MN
75
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
fc19de61
MN
84 /*
85 * REVISIT SRP-only hardware is possible, although
86 * it would not be called "OTG" ...
87 */
c6c56008
MN
88 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
89 },
90
91 NULL
92};
93
94/* string IDs are assigned dynamically */
95
c6c56008 96static struct usb_string gfs_strings[] = {
c6c56008 97#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
f8dae531 98 { .s = "FunctionFS + RNDIS" },
c6c56008
MN
99#endif
100#ifdef CONFIG_USB_FUNCTIONFS_ETH
f8dae531 101 { .s = "FunctionFS + ECM" },
c6c56008
MN
102#endif
103#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
f8dae531 104 { .s = "FunctionFS" },
c6c56008
MN
105#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
f8dae531
MN
118
119struct gfs_configuration {
120 struct usb_configuration c;
121 int (*eth)(struct usb_configuration *c, u8 *ethaddr);
122} gfs_configurations[] = {
c6c56008 123#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
f8dae531
MN
124 {
125 .eth = rndis_bind_config,
126 },
c6c56008
MN
127#endif
128
c6c56008 129#ifdef CONFIG_USB_FUNCTIONFS_ETH
f8dae531
MN
130 {
131 .eth = eth_bind_config,
132 },
c6c56008
MN
133#endif
134
c6c56008 135#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
f8dae531
MN
136 {
137 },
c6c56008 138#endif
f8dae531 139};
c6c56008
MN
140
141
142static int gfs_bind(struct usb_composite_dev *cdev);
143static int gfs_unbind(struct usb_composite_dev *cdev);
f8dae531 144static int gfs_do_config(struct usb_configuration *c);
c6c56008
MN
145
146static struct usb_composite_driver gfs_driver = {
fc19de61 147 .name = DRIVER_NAME,
c6c56008
MN
148 .dev = &gfs_dev_desc,
149 .strings = gfs_dev_strings,
150 .bind = gfs_bind,
151 .unbind = gfs_unbind,
fc19de61 152 .iProduct = DRIVER_DESC,
c6c56008
MN
153};
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{
f8dae531 214 int ret, i;
c6c56008
MN
215
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
f8dae531 225 ret = usb_string_ids_tab(cdev, gfs_strings);
c6c56008
MN
226 if (unlikely(ret < 0))
227 goto error;
c6c56008 228
c6c56008
MN
229 ret = functionfs_bind(gfs_ffs_data, cdev);
230 if (unlikely(ret < 0))
231 goto error;
232
f8dae531
MN
233 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
234 struct gfs_configuration *c = gfs_configurations + i;
c6c56008 235
fc19de61
MN
236 c->c.label = gfs_strings[i].s;
237 c->c.iConfiguration = gfs_strings[i].id;
f8dae531
MN
238 c->c.bind = gfs_do_config;
239 c->c.bConfigurationValue = 1 + i;
240 c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
c6c56008 241
f8dae531
MN
242 ret = usb_add_config(cdev, &c->c);
243 if (unlikely(ret < 0))
244 goto error_unbind;
245 }
c6c56008
MN
246
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
fc19de61
MN
262 /*
263 * We may have been called in an error recovery from
c6c56008
MN
264 * 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
fc19de61
MN
268 * do...?
269 */
c6c56008
MN
270 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
f8dae531 280static int gfs_do_config(struct usb_configuration *c)
c6c56008 281{
f8dae531
MN
282 struct gfs_configuration *gc =
283 container_of(c, struct gfs_configuration, c);
c6c56008
MN
284 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
f8dae531
MN
294 if (gc->eth) {
295 ret = gc->eth(c, gfs_hostaddr);
c6c56008
MN
296 if (unlikely(ret < 0))
297 return ret;
298 }
299
7898aee1 300 ret = functionfs_bind_config(c->cdev, c, gfs_ffs_data);
c6c56008
MN
301 if (unlikely(ret < 0))
302 return ret;
303
fc19de61
MN
304 /*
305 * After previous do_configs there may be some invalid
f588c0db
MN
306 * 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
fc19de61
MN
312 * c->interface array. We need to make sure this is true.
313 */
f588c0db
MN
314 if (c->next_interface_id < ARRAY_SIZE(c->interface))
315 c->interface[c->next_interface_id] = NULL;
316
c6c56008
MN
317 return 0;
318}
319
c6c56008
MN
320
321#ifdef CONFIG_USB_FUNCTIONFS_ETH
fc19de61 322
f8dae531 323static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN])
c6c56008 324{
f8dae531
MN
325 return can_support_ecm(c->cdev->gadget)
326 ? ecm_bind_config(c, ethaddr)
327 : geth_bind_config(c, ethaddr);
c6c56008 328}
fc19de61 329
c6c56008 330#endif