]> code.ossystems Code Review - openembedded-core.git/blob
14b4bfbc02a384b3a9729b1dd0fd068cfd6aa8b0
[openembedded-core.git] /
1 From d96b241bd2ad42b6c49d5f6435c69b23818f001e Mon Sep 17 00:00:00 2001
2 From: Felipe Balbi <felipe.balbi@nokia.com>
3 Date: Tue, 5 Jan 2010 16:10:13 +0200
4 Subject: [PATCH 9/10] USB: gadget: introduce g_nokia gadget driver
5
6 Patch-mainline: 2.6.34
7 Git-commit: f358f5b40af67caf28b627889d007294614170b2
8
9 g_nokia is the gadget driver implementing
10 WMCDC Wireless Handset Control Model for the N900
11 device.
12
13 Signed-off-by: Felipe Balbi <felipe.balbi@nokia.com>
14 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
15 ---
16  drivers/usb/gadget/Kconfig  |   10 +
17  drivers/usb/gadget/Makefile |    2 
18  drivers/usb/gadget/nokia.c  |  259 ++++++++++++++++++++++++++++++++++++++++++++
19  3 files changed, 271 insertions(+)
20  create mode 100644 drivers/usb/gadget/nokia.c
21
22 --- a/drivers/usb/gadget/Kconfig
23 +++ b/drivers/usb/gadget/Kconfig
24 @@ -828,6 +828,16 @@
25           Say "y" to link the driver statically, or "m" to build a
26           dynamically linked module.
27  
28 +config USB_G_NOKIA
29 +       tristate "Nokia composite gadget"
30 +       depends on PHONET
31 +       help
32 +         The Nokia composite gadget provides support for acm, obex
33 +         and phonet in only one composite gadget driver.
34 +
35 +         It's only really useful for N900 hardware. If you're building
36 +         a kernel for N900, say Y or M here. If unsure, say N.
37 +
38  config USB_G_MULTI
39         tristate "Multifunction Composite Gadget (EXPERIMENTAL)"
40         depends on BLOCK && NET
41 --- a/drivers/usb/gadget/Makefile
42 +++ b/drivers/usb/gadget/Makefile
43 @@ -44,6 +44,7 @@
44  g_cdc-objs                     := cdc2.o
45  g_multi-objs                   := multi.o
46  g_still_image-objs             := still_image.o
47 +g_nokia-objs                   := nokia.o
48  
49  obj-$(CONFIG_USB_ZERO)         += g_zero.o
50  obj-$(CONFIG_USB_AUDIO)                += g_audio.o
51 @@ -57,6 +58,7 @@
52  obj-$(CONFIG_USB_CDC_COMPOSITE) += g_cdc.o
53  obj-$(CONFIG_USB_G_MULTI)      += g_multi.o
54  obj-$(CONFIG_USB_STILL_IMAGE)  += g_still_image.o
55 +obj-$(CONFIG_USB_G_NOKIA)      += g_nokia.o
56  
57  ifeq ($(CONFIG_USB_GADGET_DEBUG),y)
58          EXTRA_CFLAGS += -DDMA_PPB_MODE
59 --- /dev/null
60 +++ b/drivers/usb/gadget/nokia.c
61 @@ -0,0 +1,259 @@
62 +/*
63 + * nokia.c -- Nokia Composite Gadget Driver
64 + *
65 + * Copyright (C) 2008-2010 Nokia Corporation
66 + * Contact: Felipe Balbi <felipe.balbi@nokia.com>
67 + *
68 + * This gadget driver borrows from serial.c which is:
69 + *
70 + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
71 + * Copyright (C) 2008 by David Brownell
72 + * Copyright (C) 2008 by Nokia Corporation
73 + *
74 + * This software is distributed under the terms of the GNU General
75 + * Public License ("GPL") as published by the Free Software Foundation,
76 + * version 2 of that License.
77 + */
78 +
79 +#include <linux/kernel.h>
80 +#include <linux/utsname.h>
81 +#include <linux/device.h>
82 +
83 +#include "u_serial.h"
84 +#include "u_ether.h"
85 +#include "u_phonet.h"
86 +#include "gadget_chips.h"
87 +
88 +/* Defines */
89 +
90 +#define NOKIA_VERSION_NUM              0x0211
91 +#define NOKIA_LONG_NAME                        "N900 (PC-Suite Mode)"
92 +
93 +/*-------------------------------------------------------------------------*/
94 +
95 +/*
96 + * Kbuild is not very cooperative with respect to linking separately
97 + * compiled library objects into one module.  So for now we won't use
98 + * separate compilation ... ensuring init/exit sections work to shrink
99 + * the runtime footprint, and giving us at least some parts of what
100 + * a "gcc --combine ... part1.c part2.c part3.c ... " build would.
101 + */
102 +#include "composite.c"
103 +#include "usbstring.c"
104 +#include "config.c"
105 +#include "epautoconf.c"
106 +
107 +#include "u_serial.c"
108 +#include "f_acm.c"
109 +#include "f_ecm.c"
110 +#include "f_obex.c"
111 +#include "f_serial.c"
112 +#include "f_phonet.c"
113 +#include "u_ether.c"
114 +
115 +/*-------------------------------------------------------------------------*/
116 +
117 +#define NOKIA_VENDOR_ID                        0x0421  /* Nokia */
118 +#define NOKIA_PRODUCT_ID               0x01c8  /* Nokia Gadget */
119 +
120 +/* string IDs are assigned dynamically */
121 +
122 +#define STRING_MANUFACTURER_IDX                0
123 +#define STRING_PRODUCT_IDX             1
124 +#define STRING_DESCRIPTION_IDX         2
125 +
126 +static char manufacturer_nokia[] = "Nokia";
127 +static const char product_nokia[] = NOKIA_LONG_NAME;
128 +static const char description_nokia[] = "PC-Suite Configuration";
129 +
130 +static struct usb_string strings_dev[] = {
131 +       [STRING_MANUFACTURER_IDX].s = manufacturer_nokia,
132 +       [STRING_PRODUCT_IDX].s = NOKIA_LONG_NAME,
133 +       [STRING_DESCRIPTION_IDX].s = description_nokia,
134 +       {  } /* end of list */
135 +};
136 +
137 +static struct usb_gadget_strings stringtab_dev = {
138 +       .language       = 0x0409,       /* en-us */
139 +       .strings        = strings_dev,
140 +};
141 +
142 +static struct usb_gadget_strings *dev_strings[] = {
143 +       &stringtab_dev,
144 +       NULL,
145 +};
146 +
147 +static struct usb_device_descriptor device_desc = {
148 +       .bLength                = USB_DT_DEVICE_SIZE,
149 +       .bDescriptorType        = USB_DT_DEVICE,
150 +       .bcdUSB                 = __constant_cpu_to_le16(0x0200),
151 +       .bDeviceClass           = USB_CLASS_COMM,
152 +       .idVendor               = __constant_cpu_to_le16(NOKIA_VENDOR_ID),
153 +       .idProduct              = __constant_cpu_to_le16(NOKIA_PRODUCT_ID),
154 +       /* .iManufacturer = DYNAMIC */
155 +       /* .iProduct = DYNAMIC */
156 +       .bNumConfigurations =   1,
157 +};
158 +
159 +/*-------------------------------------------------------------------------*/
160 +
161 +/* Module */
162 +MODULE_DESCRIPTION("Nokia composite gadget driver for N900");
163 +MODULE_AUTHOR("Felipe Balbi");
164 +MODULE_LICENSE("GPL");
165 +
166 +/*-------------------------------------------------------------------------*/
167 +
168 +static u8 hostaddr[ETH_ALEN];
169 +
170 +static int __init nokia_bind_config(struct usb_configuration *c)
171 +{
172 +       int status = 0;
173 +
174 +       status = phonet_bind_config(c);
175 +       if (status)
176 +               printk(KERN_DEBUG "could not bind phonet config\n");
177 +
178 +       status = obex_bind_config(c, 0);
179 +       if (status)
180 +               printk(KERN_DEBUG "could not bind obex config %d\n", 0);
181 +
182 +       status = obex_bind_config(c, 1);
183 +       if (status)
184 +               printk(KERN_DEBUG "could not bind obex config %d\n", 0);
185 +
186 +       status = acm_bind_config(c, 2);
187 +       if (status)
188 +               printk(KERN_DEBUG "could not bind acm config\n");
189 +
190 +       status = ecm_bind_config(c, hostaddr);
191 +       if (status)
192 +               printk(KERN_DEBUG "could not bind ecm config\n");
193 +
194 +       return status;
195 +}
196 +
197 +static struct usb_configuration nokia_config_500ma_driver = {
198 +       .label          = "Bus Powered",
199 +       .bind           = nokia_bind_config,
200 +       .bConfigurationValue = 1,
201 +       /* .iConfiguration = DYNAMIC */
202 +       .bmAttributes   = USB_CONFIG_ATT_ONE,
203 +       .bMaxPower      = 250, /* 500mA */
204 +};
205 +
206 +static struct usb_configuration nokia_config_100ma_driver = {
207 +       .label          = "Self Powered",
208 +       .bind           = nokia_bind_config,
209 +       .bConfigurationValue = 2,
210 +       /* .iConfiguration = DYNAMIC */
211 +       .bmAttributes   = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
212 +       .bMaxPower      = 50, /* 100 mA */
213 +};
214 +
215 +static int __init nokia_bind(struct usb_composite_dev *cdev)
216 +{
217 +       int                     gcnum;
218 +       struct usb_gadget       *gadget = cdev->gadget;
219 +       int                     status;
220 +
221 +       status = gphonet_setup(cdev->gadget);
222 +       if (status < 0)
223 +               goto err_phonet;
224 +
225 +       status = gserial_setup(cdev->gadget, 3);
226 +       if (status < 0)
227 +               goto err_serial;
228 +
229 +       status = gether_setup(cdev->gadget, hostaddr);
230 +       if (status < 0)
231 +               goto err_ether;
232 +
233 +       status = usb_string_id(cdev);
234 +       if (status < 0)
235 +               goto err_usb;
236 +       strings_dev[STRING_MANUFACTURER_IDX].id = status;
237 +
238 +       device_desc.iManufacturer = status;
239 +
240 +       status = usb_string_id(cdev);
241 +       if (status < 0)
242 +               goto err_usb;
243 +       strings_dev[STRING_PRODUCT_IDX].id = status;
244 +
245 +       device_desc.iProduct = status;
246 +
247 +       /* config description */
248 +       status = usb_string_id(cdev);
249 +       if (status < 0)
250 +               goto err_usb;
251 +       strings_dev[STRING_DESCRIPTION_IDX].id = status;
252 +
253 +       nokia_config_500ma_driver.iConfiguration = status;
254 +       nokia_config_100ma_driver.iConfiguration = status;
255 +
256 +       /* set up other descriptors */
257 +       gcnum = usb_gadget_controller_number(gadget);
258 +       if (gcnum >= 0)
259 +               device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM);
260 +       else {
261 +               /* this should only work with hw that supports altsettings
262 +                * and several endpoints, anything else, panic.
263 +                */
264 +               pr_err("nokia_bind: controller '%s' not recognized\n",
265 +                       gadget->name);
266 +               goto err_usb;
267 +       }
268 +
269 +       /* finaly register the configuration */
270 +       status = usb_add_config(cdev, &nokia_config_500ma_driver);
271 +       if (status < 0)
272 +               goto err_usb;
273 +
274 +       status = usb_add_config(cdev, &nokia_config_100ma_driver);
275 +       if (status < 0)
276 +               goto err_usb;
277 +
278 +       dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME);
279 +
280 +       return 0;
281 +
282 +err_usb:
283 +       gether_cleanup();
284 +err_ether:
285 +       gserial_cleanup();
286 +err_serial:
287 +       gphonet_cleanup();
288 +err_phonet:
289 +       return status;
290 +}
291 +
292 +static int __exit nokia_unbind(struct usb_composite_dev *cdev)
293 +{
294 +       gphonet_cleanup();
295 +       gserial_cleanup();
296 +       gether_cleanup();
297 +
298 +       return 0;
299 +}
300 +
301 +static struct usb_composite_driver nokia_driver = {
302 +       .name           = "g_nokia",
303 +       .dev            = &device_desc,
304 +       .strings        = dev_strings,
305 +       .bind           = nokia_bind,
306 +       .unbind         = __exit_p(nokia_unbind),
307 +};
308 +
309 +static int __init nokia_init(void)
310 +{
311 +       return usb_composite_register(&nokia_driver);
312 +}
313 +module_init(nokia_init);
314 +
315 +static void __exit nokia_cleanup(void)
316 +{
317 +       usb_composite_unregister(&nokia_driver);
318 +}
319 +module_exit(nokia_cleanup);
320 +