blob: 39686c4e05c0f48a908cc186ce9a7125f433f8be [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/*
2 * Qualcomm Maemo Composite driver
3 *
4 * Copyright (C) 2008 David Brownell
5 * Copyright (C) 2008 Nokia Corporation
6 * Copyright (C) 2009 Samsung Electronics
7 * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
8 *
9 * This program from the Code Aurora Forum is free software; you can
10 * redistribute it and/or modify it under the GNU General Public License
11 * version 2 and only version 2 as published by the Free Software Foundation.
12 * The original work available from [git.kernel.org ] is subject to the
13 * notice below.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30#include <linux/kernel.h>
31#include <linux/utsname.h>
32#include <linux/kdev_t.h>
33#include <linux/delay.h>
34
35
36#define DRIVER_DESC "Qcom Maemo Composite Gadget"
37#define VENDOR_ID 0x05c6
38#define PRODUCT_ID 0x902E
39
40/*
41 * kbuild is not very cooperative with respect to linking separately
42 * compiled library objects into one module. So for now we won't use
43 * separate compilation ... ensuring init/exit sections work to shrink
44 * the runtime footprint, and giving us at least some parts of what
45 * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
46 */
47
48#include "composite.c"
49#include "usbstring.c"
50#include "config.c"
51#include "epautoconf.c"
52
53#define USB_ETH
54
55#define USB_ETH_RNDIS
56#ifdef USB_ETH_RNDIS
57# include "f_rndis.c"
58# include "rndis.c"
59#endif
60
61
62#include "u_serial.c"
63#include "f_serial.c"
64
65#include "u_ether.c"
66
67#undef DBG /* u_ether.c has broken idea about macros */
68#undef VDBG /* so clean up after it */
69#undef ERROR
70#undef INFO
71
72#include "f_mass_storage.c"
73#include "f_diag.c"
74#include "f_rmnet.c"
75
76/*-------------------------------------------------------------------------*/
77/* string IDs are assigned dynamically */
78
79#define STRING_MANUFACTURER_IDX 0
80#define STRING_PRODUCT_IDX 1
81#define STRING_SERIAL_IDX 2
82
83/* String Table */
84static struct usb_string strings_dev[] = {
85 /* These dummy values should be overridden by platform data */
86 [STRING_MANUFACTURER_IDX].s = "Qualcomm Incorporated",
87 [STRING_PRODUCT_IDX].s = "Usb composition",
88 [STRING_SERIAL_IDX].s = "0123456789ABCDEF",
89 { } /* end of list */
90};
91
92static struct usb_gadget_strings stringtab_dev = {
93 .language = 0x0409, /* en-us */
94 .strings = strings_dev,
95};
96
97static struct usb_gadget_strings *dev_strings[] = {
98 &stringtab_dev,
99 NULL,
100};
101
102static struct usb_device_descriptor device_desc = {
103 .bLength = sizeof(device_desc),
104 .bDescriptorType = USB_DT_DEVICE,
105 .bcdUSB = __constant_cpu_to_le16(0x0200),
106 .bDeviceClass = USB_CLASS_PER_INTERFACE,
107 .bDeviceSubClass = 0,
108 .bDeviceProtocol = 0,
109 .idVendor = __constant_cpu_to_le16(VENDOR_ID),
110 .idProduct = __constant_cpu_to_le16(PRODUCT_ID),
111 .bcdDevice = __constant_cpu_to_le16(0xffff),
112 .bNumConfigurations = 1,
113};
114
115static u8 hostaddr[ETH_ALEN];
116static struct usb_diag_ch *diag_ch;
117static struct usb_diag_platform_data usb_diag_pdata = {
118 .ch_name = DIAG_LEGACY,
119};
120
121/****************************** Configurations ******************************/
122static struct fsg_module_parameters mod_data = {
123 .stall = 0
124};
125FSG_MODULE_PARAMETERS(/* no prefix */, mod_data);
126
127static struct fsg_common *fsg_common;
128static int maemo_setup_config(struct usb_configuration *c,
129 const struct usb_ctrlrequest *ctrl);
130
131static int maemo_do_config(struct usb_configuration *c)
132{
133 int ret;
134
135 ret = rndis_bind_config(c, hostaddr);
136 if (ret < 0)
137 return ret;
138
139 ret = diag_function_add(c);
140 if (ret < 0)
141 return ret;
142
143 ret = gser_bind_config(c, 0);
144 if (ret < 0)
145 return ret;
146
147 ret = gser_bind_config(c, 1);
148 if (ret < 0)
149 return ret;
150
151 ret = rmnet_function_add(c);
152 if (ret < 0)
153 return ret;
154
155 ret = fsg_add(c->cdev, c, fsg_common);
156 if (ret < 0)
157 return ret;
158
159 return 0;
160}
161
162static struct usb_configuration maemo_config_driver = {
163 .label = "Qcom Maemo Gadget",
164 .bind = maemo_do_config,
165 .setup = maemo_setup_config,
166 .bConfigurationValue = 1,
167 .bMaxPower = 0xFA,
168};
169static int maemo_setup_config(struct usb_configuration *c,
170 const struct usb_ctrlrequest *ctrl)
171{
172 int i;
173 int ret = -EOPNOTSUPP;
174
175 for (i = 0; i < maemo_config_driver.next_interface_id; i++) {
176 if (maemo_config_driver.interface[i]->setup) {
177 ret = maemo_config_driver.interface[i]->setup(
178 maemo_config_driver.interface[i], ctrl);
179 if (ret >= 0)
180 return ret;
181 }
182 }
183
184 return ret;
185}
186
187static int maemo_bind(struct usb_composite_dev *cdev)
188{
189 struct usb_gadget *gadget = cdev->gadget;
190 int status, gcnum;
191
192 /* set up diag channel */
193 diag_ch = diag_setup(&usb_diag_pdata);
194 if (IS_ERR(diag_ch))
195 return PTR_ERR(diag_ch);
196
197 /* set up network link layer */
198 status = gether_setup(cdev->gadget, hostaddr);
199 if (status < 0)
200 goto diag_clean;
201
202 /* set up serial link layer */
203 status = gserial_setup(cdev->gadget, 2);
204 if (status < 0)
205 goto fail0;
206
207 /* set up mass storage function */
208 fsg_common = fsg_common_from_params(0, cdev, &mod_data);
209 if (IS_ERR(fsg_common)) {
210 status = PTR_ERR(fsg_common);
211 goto fail1;
212 }
213
214 gcnum = usb_gadget_controller_number(gadget);
215 if (gcnum >= 0)
216 device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum);
217 else {
218 /* gadget zero is so simple (for now, no altsettings) that
219 * it SHOULD NOT have problems with bulk-capable hardware.
220 * so just warn about unrcognized controllers -- don't panic.
221 *
222 * things like configuration and altsetting numbering
223 * can need hardware-specific attention though.
224 */
225 WARNING(cdev, "controller '%s' not recognized\n",
226 gadget->name);
227 device_desc.bcdDevice = __constant_cpu_to_le16(0x9999);
228 }
229
230 /* Allocate string descriptor numbers ... note that string
231 * contents can be overridden by the composite_dev glue.
232 */
233
234 status = usb_string_id(cdev);
235 if (status < 0)
236 goto fail2;
237 strings_dev[STRING_MANUFACTURER_IDX].id = status;
238 device_desc.iManufacturer = status;
239
240 status = usb_string_id(cdev);
241 if (status < 0)
242 goto fail2;
243 strings_dev[STRING_PRODUCT_IDX].id = status;
244 device_desc.iProduct = status;
245
246 if (!usb_gadget_set_selfpowered(gadget))
247 maemo_config_driver.bmAttributes |= USB_CONFIG_ATT_SELFPOWER;
248
249 if (gadget->ops->wakeup)
250 maemo_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
251
252 /* register our first configuration */
253 status = usb_add_config(cdev, &maemo_config_driver);
254 if (status < 0)
255 goto fail2;
256
257 usb_gadget_set_selfpowered(gadget);
258 dev_info(&gadget->dev, DRIVER_DESC "\n");
259 fsg_common_put(fsg_common);
260 return 0;
261
262fail2:
263 fsg_common_put(fsg_common);
264fail1:
265 gserial_cleanup();
266fail0:
267 gether_cleanup();
268diag_clean:
269 diag_cleanup(diag_ch);
270
271 return status;
272}
273
274static int __exit maemo_unbind(struct usb_composite_dev *cdev)
275{
276 gserial_cleanup();
277 gether_cleanup();
278 diag_cleanup(diag_ch);
279 return 0;
280}
281
282static struct usb_composite_driver qcom_maemo_driver = {
283 .name = "Qcom Maemo Gadget",
284 .dev = &device_desc,
285 .strings = dev_strings,
286 .bind = maemo_bind,
287 .unbind = __exit_p(maemo_unbind),
288};
289
290static int __init qcom_maemo_usb_init(void)
291{
292 return usb_composite_register(&qcom_maemo_driver);
293}
294module_init(qcom_maemo_usb_init);
295
296static void __exit qcom_maemo_usb_cleanup(void)
297{
298 usb_composite_unregister(&qcom_maemo_driver);
299}
300module_exit(qcom_maemo_usb_cleanup);
301
302MODULE_DESCRIPTION(DRIVER_DESC);
303MODULE_LICENSE("GPL v2");
304MODULE_VERSION("1.0");