blob: 99ae8ec23c9cd49c8dd008de489ea5b668d28e32 [file] [log] [blame]
Michal Nazarewicz5ab54cf2010-11-12 14:29:28 +01001/*
2 * g_ffs.c -- user mode file system API for USB composite function controllers
3 *
4 * Copyright (C) 2010 Samsung Electronics
Michal Nazarewicz54b83602012-01-13 15:05:16 +01005 * Author: Michal Nazarewicz <mina86@mina86.com>
Michal Nazarewicz5ab54cf2010-11-12 14:29:28 +01006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
Michal Nazarewicz5ab54cf2010-11-12 14:29:28 +010011 */
12
Michal Nazarewiczaa02f172010-11-17 17:09:47 +010013#define pr_fmt(fmt) "g_ffs: " fmt
14
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020015#include <linux/module.h>
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020016/*
17 * kbuild is not very cooperative with respect to linking separately
18 * compiled library objects into one module. So for now we won't use
19 * separate compilation ... ensuring init/exit sections work to shrink
20 * the runtime footprint, and giving us at least some parts of what
21 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
22 */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020023#if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +010024#include <linux/netdevice.h>
25
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020026# if defined USB_ETH_RNDIS
27# undef USB_ETH_RNDIS
28# endif
29# ifdef CONFIG_USB_FUNCTIONFS_RNDIS
30# define USB_ETH_RNDIS y
31# endif
32
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +010033# include "u_ecm.h"
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +010034# include "u_gether.h"
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020035# ifdef USB_ETH_RNDIS
Andrzej Pietrasiewiczf466c632013-05-28 09:15:57 +020036# define USB_FRNDIS_INCLUDED
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020037# include "f_rndis.c"
Andrzej Pietrasiewiczcbbd14a2013-05-24 10:23:02 +020038# include "rndis.h"
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020039# endif
Andrzej Pietrasiewiczf1a18232013-05-23 09:22:03 +020040# include "u_ether.h"
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020041
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +010042USB_ETHERNET_MODULE_PARAMETERS();
43
Andrzej Pietrasiewiczf1a18232013-05-23 09:22:03 +020044static u8 gfs_host_mac[ETH_ALEN];
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +010045static struct eth_dev *the_dev;
Michal Nazarewiczf8dae532010-06-25 16:29:27 +020046# ifdef CONFIG_USB_FUNCTIONFS_ETH
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +010047static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
48 struct eth_dev *dev);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +010049static struct usb_function_instance *fi_ecm;
50static struct usb_function *f_ecm;
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +010051static struct usb_function_instance *fi_geth;
52static struct usb_function *f_geth;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020053# endif
Michal Nazarewiczf8dae532010-06-25 16:29:27 +020054#else
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +010055# define the_dev NULL
56# define gether_cleanup(dev) do { } while (0)
Andrzej Pietrasiewiczf1a18232013-05-23 09:22:03 +020057# define gfs_host_mac NULL
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +010058struct eth_dev;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020059#endif
60
61#include "f_fs.c"
62
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020063#define DRIVER_NAME "g_ffs"
64#define DRIVER_DESC "USB Function Filesystem"
65#define DRIVER_VERSION "24 Aug 2004"
66
67MODULE_DESCRIPTION(DRIVER_DESC);
68MODULE_AUTHOR("Michal Nazarewicz");
69MODULE_LICENSE("GPL");
70
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020071#define GFS_VENDOR_ID 0x1d6b /* Linux Foundation */
72#define GFS_PRODUCT_ID 0x0105 /* FunctionFS Gadget */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020073
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +020074#define GFS_MAX_DEVS 10
75
76struct gfs_ffs_obj {
77 const char *name;
78 bool mounted;
79 bool desc_ready;
80 struct ffs_data *ffs_data;
81};
82
Sebastian Andrzej Siewior7d16e8d2012-09-10 15:01:53 +020083USB_GADGET_COMPOSITE_OPTIONS();
84
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020085static struct usb_device_descriptor gfs_dev_desc = {
86 .bLength = sizeof gfs_dev_desc,
87 .bDescriptorType = USB_DT_DEVICE,
88
89 .bcdUSB = cpu_to_le16(0x0200),
90 .bDeviceClass = USB_CLASS_PER_INTERFACE,
91
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020092 .idVendor = cpu_to_le16(GFS_VENDOR_ID),
93 .idProduct = cpu_to_le16(GFS_PRODUCT_ID),
Michal Nazarewiczc6c56002010-05-05 12:53:15 +020094};
95
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +020096static char *func_names[GFS_MAX_DEVS];
97static unsigned int func_num;
98
Michal Nazarewiczfc19de62010-08-12 17:43:48 +020099module_param_named(bDeviceClass, gfs_dev_desc.bDeviceClass, byte, 0644);
100MODULE_PARM_DESC(bDeviceClass, "USB Device class");
101module_param_named(bDeviceSubClass, gfs_dev_desc.bDeviceSubClass, byte, 0644);
102MODULE_PARM_DESC(bDeviceSubClass, "USB Device subclass");
103module_param_named(bDeviceProtocol, gfs_dev_desc.bDeviceProtocol, byte, 0644);
104MODULE_PARM_DESC(bDeviceProtocol, "USB Device protocol");
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200105module_param_array_named(functions, func_names, charp, &func_num, 0);
106MODULE_PARM_DESC(functions, "USB Functions list");
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200107
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200108static const struct usb_descriptor_header *gfs_otg_desc[] = {
109 (const struct usb_descriptor_header *)
110 &(const struct usb_otg_descriptor) {
111 .bLength = sizeof(struct usb_otg_descriptor),
112 .bDescriptorType = USB_DT_OTG,
113
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200114 /*
115 * REVISIT SRP-only hardware is possible, although
116 * it would not be called "OTG" ...
117 */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200118 .bmAttributes = USB_OTG_SRP | USB_OTG_HNP,
119 },
120
121 NULL
122};
123
Michal Nazarewicz5ab54cf2010-11-12 14:29:28 +0100124/* String IDs are assigned dynamically */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200125static struct usb_string gfs_strings[] = {
Sebastian Andrzej Siewior276e2e42012-09-06 20:11:21 +0200126 [USB_GADGET_MANUFACTURER_IDX].s = "",
Sebastian Andrzej Siewiord33f74f2012-09-10 15:01:57 +0200127 [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC,
Sebastian Andrzej Siewior276e2e42012-09-06 20:11:21 +0200128 [USB_GADGET_SERIAL_IDX].s = "",
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200129#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200130 { .s = "FunctionFS + RNDIS" },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200131#endif
132#ifdef CONFIG_USB_FUNCTIONFS_ETH
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200133 { .s = "FunctionFS + ECM" },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200134#endif
135#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200136 { .s = "FunctionFS" },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200137#endif
138 { } /* end of list */
139};
140
141static struct usb_gadget_strings *gfs_dev_strings[] = {
142 &(struct usb_gadget_strings) {
143 .language = 0x0409, /* en-us */
144 .strings = gfs_strings,
145 },
146 NULL,
147};
148
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200149struct gfs_configuration {
150 struct usb_configuration c;
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +0100151 int (*eth)(struct usb_configuration *c, u8 *ethaddr,
152 struct eth_dev *dev);
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200153} gfs_configurations[] = {
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200154#ifdef CONFIG_USB_FUNCTIONFS_RNDIS
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200155 {
156 .eth = rndis_bind_config,
157 },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200158#endif
159
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200160#ifdef CONFIG_USB_FUNCTIONFS_ETH
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200161 {
162 .eth = eth_bind_config,
163 },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200164#endif
165
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200166#ifdef CONFIG_USB_FUNCTIONFS_GENERIC
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200167 {
168 },
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200169#endif
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200170};
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200171
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200172static int gfs_bind(struct usb_composite_dev *cdev);
173static int gfs_unbind(struct usb_composite_dev *cdev);
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200174static int gfs_do_config(struct usb_configuration *c);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200175
Sebastian Andrzej Siewiorc2ec75c2012-09-06 20:11:03 +0200176static __refdata struct usb_composite_driver gfs_driver = {
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200177 .name = DRIVER_NAME,
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200178 .dev = &gfs_dev_desc,
179 .strings = gfs_dev_strings,
Tatyana Brokhman35a0e0b2011-06-29 16:41:49 +0300180 .max_speed = USB_SPEED_HIGH,
Sebastian Andrzej Siewior03e42bd2012-09-06 20:11:04 +0200181 .bind = gfs_bind,
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200182 .unbind = gfs_unbind,
183};
184
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200185static DEFINE_MUTEX(gfs_lock);
186static unsigned int missing_funcs;
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200187static bool gfs_registered;
188static bool gfs_single_func;
189static struct gfs_ffs_obj *ffs_tab;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200190
Andrzej Pietrasiewicz8545e602012-03-12 12:55:42 +0100191static int __init gfs_init(void)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200192{
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200193 int i;
194
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200195 ENTER();
196
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200197 if (!func_num) {
198 gfs_single_func = true;
199 func_num = 1;
200 }
201
202 ffs_tab = kcalloc(func_num, sizeof *ffs_tab, GFP_KERNEL);
203 if (!ffs_tab)
204 return -ENOMEM;
205
206 if (!gfs_single_func)
207 for (i = 0; i < func_num; i++)
208 ffs_tab[i].name = func_names[i];
209
210 missing_funcs = func_num;
211
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200212 return functionfs_init();
213}
214module_init(gfs_init);
215
Andrzej Pietrasiewicz8545e602012-03-12 12:55:42 +0100216static void __exit gfs_exit(void)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200217{
218 ENTER();
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200219 mutex_lock(&gfs_lock);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200220
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200221 if (gfs_registered)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200222 usb_composite_unregister(&gfs_driver);
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200223 gfs_registered = false;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200224
225 functionfs_cleanup();
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200226
227 mutex_unlock(&gfs_lock);
228 kfree(ffs_tab);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200229}
230module_exit(gfs_exit);
231
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200232static struct gfs_ffs_obj *gfs_find_dev(const char *dev_name)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200233{
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200234 int i;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200235
236 ENTER();
237
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200238 if (gfs_single_func)
239 return &ffs_tab[0];
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200240
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200241 for (i = 0; i < func_num; i++)
242 if (strcmp(ffs_tab[i].name, dev_name) == 0)
243 return &ffs_tab[i];
244
245 return NULL;
246}
247
248static int functionfs_ready_callback(struct ffs_data *ffs)
249{
250 struct gfs_ffs_obj *ffs_obj;
251 int ret;
252
253 ENTER();
254 mutex_lock(&gfs_lock);
255
256 ffs_obj = ffs->private_data;
257 if (!ffs_obj) {
258 ret = -EINVAL;
259 goto done;
260 }
261
262 if (WARN_ON(ffs_obj->desc_ready)) {
263 ret = -EBUSY;
264 goto done;
265 }
266 ffs_obj->desc_ready = true;
267 ffs_obj->ffs_data = ffs;
268
269 if (--missing_funcs) {
270 ret = 0;
271 goto done;
272 }
273
274 if (gfs_registered) {
275 ret = -EBUSY;
276 goto done;
277 }
278 gfs_registered = true;
279
Sebastian Andrzej Siewior03e42bd2012-09-06 20:11:04 +0200280 ret = usb_composite_probe(&gfs_driver);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200281 if (unlikely(ret < 0))
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200282 gfs_registered = false;
283
284done:
285 mutex_unlock(&gfs_lock);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200286 return ret;
287}
288
289static void functionfs_closed_callback(struct ffs_data *ffs)
290{
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200291 struct gfs_ffs_obj *ffs_obj;
292
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200293 ENTER();
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200294 mutex_lock(&gfs_lock);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200295
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200296 ffs_obj = ffs->private_data;
297 if (!ffs_obj)
298 goto done;
299
300 ffs_obj->desc_ready = false;
301 missing_funcs++;
302
303 if (gfs_registered)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200304 usb_composite_unregister(&gfs_driver);
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200305 gfs_registered = false;
306
307done:
308 mutex_unlock(&gfs_lock);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200309}
310
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200311static void *functionfs_acquire_dev_callback(const char *dev_name)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200312{
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200313 struct gfs_ffs_obj *ffs_dev;
314
315 ENTER();
316 mutex_lock(&gfs_lock);
317
318 ffs_dev = gfs_find_dev(dev_name);
319 if (!ffs_dev) {
320 ffs_dev = ERR_PTR(-ENODEV);
321 goto done;
322 }
323
324 if (ffs_dev->mounted) {
325 ffs_dev = ERR_PTR(-EBUSY);
326 goto done;
327 }
328 ffs_dev->mounted = true;
329
330done:
331 mutex_unlock(&gfs_lock);
332 return ffs_dev;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200333}
334
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200335static void functionfs_release_dev_callback(struct ffs_data *ffs_data)
336{
337 struct gfs_ffs_obj *ffs_dev;
338
339 ENTER();
340 mutex_lock(&gfs_lock);
341
342 ffs_dev = ffs_data->private_data;
343 if (ffs_dev)
344 ffs_dev->mounted = false;
345
346 mutex_unlock(&gfs_lock);
347}
348
349/*
350 * It is assumed that gfs_bind is called from a context where gfs_lock is held
351 */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200352static int gfs_bind(struct usb_composite_dev *cdev)
353{
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100354#if defined CONFIG_USB_FUNCTIONFS_ETH
355 struct net_device *net;
356#endif
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200357 int ret, i;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200358
359 ENTER();
360
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200361 if (missing_funcs)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200362 return -ENODEV;
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100363#if defined CONFIG_USB_FUNCTIONFS_ETH
364 if (can_support_ecm(cdev->gadget)) {
365 struct f_ecm_opts *ecm_opts;
366
367 fi_ecm = usb_get_function_instance("ecm");
368 if (IS_ERR(fi_ecm))
369 return PTR_ERR(fi_ecm);
370 ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100371 net = ecm_opts->net;
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100372 } else {
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100373 struct f_gether_opts *geth_opts;
374
375 fi_geth = usb_get_function_instance("geth");
376 if (IS_ERR(fi_geth))
377 return PTR_ERR(fi_geth);
378 geth_opts = container_of(fi_geth, struct f_gether_opts,
379 func_inst);
380 net = geth_opts->net;
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100381 }
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100382 gether_set_qmult(net, qmult);
383
384 if (!gether_set_host_addr(net, host_addr))
385 pr_info("using host ethernet address: %s", host_addr);
386 if (!gether_set_dev_addr(net, dev_addr))
387 pr_info("using self ethernet address: %s", dev_addr);
388
389 the_dev = netdev_priv(net);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100390
391#elif defined CONFIG_USB_FUNCTIONFS_RNDIS
392
Andrzej Pietrasiewiczf1a18232013-05-23 09:22:03 +0200393 the_dev = gether_setup(cdev->gadget, dev_addr, host_addr, gfs_host_mac,
394 qmult);
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +0100395#endif
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100396 if (IS_ERR(the_dev))
397 return PTR_ERR(the_dev);
398
399#if defined CONFIG_USB_FUNCTIONFS_RNDIS && defined CONFIG_USB_FUNCTIONFS_ETH
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100400 gether_set_gadget(net, cdev->gadget);
401 ret = gether_register_netdev(net);
402 if (ret)
403 goto error;
404
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100405 if (can_support_ecm(cdev->gadget)) {
406 struct f_ecm_opts *ecm_opts;
407
408 ecm_opts = container_of(fi_ecm, struct f_ecm_opts, func_inst);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100409 ecm_opts->bound = true;
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100410 } else {
411 struct f_gether_opts *geth_opts;
412
413 geth_opts = container_of(fi_geth, struct f_gether_opts,
414 func_inst);
415 geth_opts->bound = true;
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +0100416 }
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100417 gether_get_host_addr_u8(net, gfs_host_mac);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100418#endif
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200419
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200420 ret = usb_string_ids_tab(cdev, gfs_strings);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200421 if (unlikely(ret < 0))
422 goto error;
Sebastian Andrzej Siewiord33f74f2012-09-10 15:01:57 +0200423 gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200424
Andrzej Pietrasiewicz34169052013-03-11 16:32:14 +0100425 for (i = func_num; i--; ) {
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200426 ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
427 if (unlikely(ret < 0)) {
428 while (++i < func_num)
429 functionfs_unbind(ffs_tab[i].ffs_data);
430 goto error;
431 }
432 }
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200433
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200434 for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) {
435 struct gfs_configuration *c = gfs_configurations + i;
Sebastian Andrzej Siewior276e2e42012-09-06 20:11:21 +0200436 int sid = USB_GADGET_FIRST_AVAIL_IDX + i;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200437
Sebastian Andrzej Siewior276e2e42012-09-06 20:11:21 +0200438 c->c.label = gfs_strings[sid].s;
439 c->c.iConfiguration = gfs_strings[sid].id;
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200440 c->c.bConfigurationValue = 1 + i;
441 c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200442
Uwe Kleine-Königc9bfff92010-08-12 17:43:55 +0200443 ret = usb_add_config(cdev, &c->c, gfs_do_config);
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200444 if (unlikely(ret < 0))
445 goto error_unbind;
446 }
Sebastian Andrzej Siewior7d16e8d2012-09-10 15:01:53 +0200447 usb_composite_overwrite_options(cdev, &coverwrite);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200448 return 0;
449
450error_unbind:
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200451 for (i = 0; i < func_num; i++)
452 functionfs_unbind(ffs_tab[i].ffs_data);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200453error:
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100454#if defined CONFIG_USB_FUNCTIONFS_ETH
455 if (can_support_ecm(cdev->gadget))
456 usb_put_function_instance(fi_ecm);
457 else
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100458 usb_put_function_instance(fi_geth);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100459 the_dev = NULL;
460#elif defined CONFIG_USB_FUNCTIONFS_RNDIS
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +0100461 gether_cleanup(the_dev);
Andrzej Pietrasiewicz1ec8f002013-12-03 15:15:22 +0100462 the_dev = NULL;
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100463#endif
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200464 return ret;
465}
466
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200467/*
468 * It is assumed that gfs_unbind is called from a context where gfs_lock is held
469 */
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200470static int gfs_unbind(struct usb_composite_dev *cdev)
471{
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200472 int i;
473
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200474 ENTER();
475
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100476
477#if defined CONFIG_USB_FUNCTIONFS_ETH
478 if (can_support_ecm(cdev->gadget)) {
479 usb_put_function(f_ecm);
480 usb_put_function_instance(fi_ecm);
481 } else {
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100482 usb_put_function(f_geth);
483 usb_put_function_instance(fi_geth);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100484 }
485 the_dev = NULL;
486#elif defined CONFIG_USB_FUNCTIONFS_RNDIS
Andrzej Pietrasiewicz1ec8f002013-12-03 15:15:22 +0100487 gether_cleanup(the_dev);
488 the_dev = NULL;
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100489#endif
Andrzej Pietrasiewicz1ec8f002013-12-03 15:15:22 +0100490
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200491 /*
492 * We may have been called in an error recovery from
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200493 * composite_bind() after gfs_unbind() failure so we need to
Andrzej Pietrasiewicz1ec8f002013-12-03 15:15:22 +0100494 * check if instance's ffs_data is not NULL since gfs_bind() handles
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200495 * all error recovery itself. I'd rather we werent called
496 * from composite on orror recovery, but what you're gonna
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200497 * do...?
498 */
Andrzej Pietrasiewicz34169052013-03-11 16:32:14 +0100499 for (i = func_num; i--; )
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200500 if (ffs_tab[i].ffs_data)
501 functionfs_unbind(ffs_tab[i].ffs_data);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200502
503 return 0;
504}
505
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200506/*
507 * It is assumed that gfs_do_config is called from a context where
508 * gfs_lock is held
509 */
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200510static int gfs_do_config(struct usb_configuration *c)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200511{
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200512 struct gfs_configuration *gc =
513 container_of(c, struct gfs_configuration, c);
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200514 int i;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200515 int ret;
516
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200517 if (missing_funcs)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200518 return -ENODEV;
519
520 if (gadget_is_otg(c->cdev->gadget)) {
521 c->descriptors = gfs_otg_desc;
522 c->bmAttributes |= USB_CONFIG_ATT_WAKEUP;
523 }
524
Michal Nazarewiczf8dae532010-06-25 16:29:27 +0200525 if (gc->eth) {
Andrzej Pietrasiewiczf1a18232013-05-23 09:22:03 +0200526 ret = gc->eth(c, gfs_host_mac, the_dev);
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200527 if (unlikely(ret < 0))
528 return ret;
529 }
530
Andrzej Pietrasiewicz581791f2012-05-14 15:51:52 +0200531 for (i = 0; i < func_num; i++) {
532 ret = functionfs_bind_config(c->cdev, c, ffs_tab[i].ffs_data);
533 if (unlikely(ret < 0))
534 return ret;
535 }
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200536
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200537 /*
538 * After previous do_configs there may be some invalid
Michal Nazarewiczf588c0d2010-06-14 10:43:34 +0200539 * pointers in c->interface array. This happens every time
540 * a user space function with fewer interfaces than a user
541 * space function that was run before the new one is run. The
542 * compasit's set_config() assumes that if there is no more
543 * then MAX_CONFIG_INTERFACES interfaces in a configuration
544 * then there is a NULL pointer after the last interface in
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200545 * c->interface array. We need to make sure this is true.
546 */
Michal Nazarewiczf588c0d2010-06-14 10:43:34 +0200547 if (c->next_interface_id < ARRAY_SIZE(c->interface))
548 c->interface[c->next_interface_id] = NULL;
549
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200550 return 0;
551}
552
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200553#ifdef CONFIG_USB_FUNCTIONFS_ETH
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200554
Sebastian Andrzej Siewiord6a01432012-12-23 21:10:12 +0100555static int eth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN],
556 struct eth_dev *dev)
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200557{
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100558 int status = 0;
559
560 if (can_support_ecm(c->cdev->gadget)) {
561 f_ecm = usb_get_function(fi_ecm);
562 if (IS_ERR(f_ecm))
563 return PTR_ERR(f_ecm);
564
565 status = usb_add_function(c, f_ecm);
566 if (status < 0)
567 usb_put_function(f_ecm);
568
569 } else {
Andrzej Pietrasiewicz85aec592013-12-03 15:15:25 +0100570 f_geth = usb_get_function(fi_geth);
571 if (IS_ERR(f_geth))
572 return PTR_ERR(f_geth);
573
574 status = usb_add_function(c, f_geth);
575 if (status < 0)
576 usb_put_function(f_geth);
Andrzej Pietrasiewiczf212ad42013-12-03 15:15:23 +0100577 }
578 return status;
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200579}
Michal Nazarewiczfc19de62010-08-12 17:43:48 +0200580
Michal Nazarewiczc6c56002010-05-05 12:53:15 +0200581#endif