move usb to drivers for quilt patches
[kernel-power] / usbhost / drivers / usb / gadget / f_obex.c
1 /*
2  * f_obex.c -- USB CDC OBEX function driver
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Contact: Felipe Balbi <felipe.balbi@nokia.com>
6  *
7  * Based on f_acm.c by Al Borchers and David Brownell.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22  */
23
24 /* #define VERBOSE_DEBUG */
25
26 #include <linux/kernel.h>
27 #include <linux/utsname.h>
28 #include <linux/device.h>
29
30 #include "u_serial.h"
31 #include "gadget_chips.h"
32
33
34 /*
35  * This CDC OBEX function support just packages a TTY-ish byte stream.
36  * A user mode server will put it into "raw" mode and handle all the
37  * relevant protocol details ... this is just a kernel passthrough.
38  * When possible, we prevent gadget enumeration until that server is
39  * ready to handle the commands.
40  */
41
42 struct obex_ep_descs {
43         struct usb_endpoint_descriptor  *obex_in;
44         struct usb_endpoint_descriptor  *obex_out;
45 };
46
47 struct f_obex {
48         struct gserial                  port;
49         u8                              ctrl_id;
50         u8                              data_id;
51         u8                              port_num;
52         u8                              can_activate;
53         u8                              connected;
54
55         struct obex_ep_descs            fs;
56         struct obex_ep_descs            hs;
57 };
58
59 static inline struct f_obex *func_to_obex(struct usb_function *f)
60 {
61         return container_of(f, struct f_obex, port.func);
62 }
63
64 static inline struct f_obex *port_to_obex(struct gserial *p)
65 {
66         return container_of(p, struct f_obex, port);
67 }
68
69 /*-------------------------------------------------------------------------*/
70
71 #define OBEX_CTRL_IDX   0
72 #define OBEX_DATA_IDX   1
73 #define OBEX_CTRL0_IDX  2
74 #define OBEX_CTRL1_IDX  3
75
76 static struct usb_string obex_string_defs[] = {
77         [OBEX_CTRL_IDX].s       = "CDC Object Exchange (OBEX)",
78         [OBEX_DATA_IDX].s       = "CDC OBEX Data",
79         [OBEX_CTRL0_IDX].s      = "PC Suite Services",
80         [OBEX_CTRL1_IDX].s      = "SYNCML-SYNC",
81         {  },   /* end of list */
82 };
83
84 static struct usb_gadget_strings obex_string_table = {
85         .language               = 0x0409,       /* en-US */
86         .strings                = obex_string_defs,
87 };
88
89 static struct usb_gadget_strings *obex_strings[] = {
90         &obex_string_table,
91         NULL,
92 };
93
94 /*-------------------------------------------------------------------------*/
95
96 static struct usb_interface_descriptor obex_control_intf __initdata = {
97         .bLength                = sizeof(obex_control_intf),
98         .bDescriptorType        = USB_DT_INTERFACE,
99         .bInterfaceNumber       = 0,
100
101         .bAlternateSetting      = 0,
102         .bNumEndpoints          = 0,
103         .bInterfaceClass        = USB_CLASS_COMM,
104         .bInterfaceSubClass     = USB_CDC_SUBCLASS_OBEX,
105 };
106
107 static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
108         .bLength                = sizeof(obex_data_nop_intf),
109         .bDescriptorType        = USB_DT_INTERFACE,
110         .bInterfaceNumber       = 1,
111
112         .bAlternateSetting      = 0,
113         .bNumEndpoints          = 0,
114         .bInterfaceClass        = USB_CLASS_CDC_DATA,
115 };
116
117 static struct usb_interface_descriptor obex_data_intf __initdata = {
118         .bLength                = sizeof(obex_data_intf),
119         .bDescriptorType        = USB_DT_INTERFACE,
120         .bInterfaceNumber       = 2,
121
122         .bAlternateSetting      = 1,
123         .bNumEndpoints          = 2,
124         .bInterfaceClass        = USB_CLASS_CDC_DATA,
125 };
126
127 static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
128         .bLength                = sizeof(obex_cdc_header_desc),
129         .bDescriptorType        = USB_DT_CS_INTERFACE,
130         .bDescriptorSubType     = USB_CDC_HEADER_TYPE,
131         .bcdCDC                 = __constant_cpu_to_le16(0x0120),
132 };
133
134 static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
135         .bLength                = sizeof(obex_cdc_union_desc),
136         .bDescriptorType        = USB_DT_CS_INTERFACE,
137         .bDescriptorSubType     = USB_CDC_UNION_TYPE,
138         .bMasterInterface0      = 1,
139         .bSlaveInterface0       = 2,
140 };
141
142 static struct usb_cdc_obex_desc obex_desc __initdata = {
143         .bLength                = sizeof(obex_desc),
144         .bDescriptorType        = USB_DT_CS_INTERFACE,
145         .bDescriptorSubType     = USB_CDC_OBEX_TYPE,
146         .bcdVersion             = __constant_cpu_to_le16(0x0100),
147 };
148
149 /* High-Speed Support */
150
151 static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
152         .bLength                = USB_DT_ENDPOINT_SIZE,
153         .bDescriptorType        = USB_DT_ENDPOINT,
154
155         .bEndpointAddress       = USB_DIR_OUT,
156         .bmAttributes           = USB_ENDPOINT_XFER_BULK,
157         .wMaxPacketSize         = __constant_cpu_to_le16(512),
158 };
159
160 static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
161         .bLength                = USB_DT_ENDPOINT_SIZE,
162         .bDescriptorType        = USB_DT_ENDPOINT,
163
164         .bEndpointAddress       = USB_DIR_IN,
165         .bmAttributes           = USB_ENDPOINT_XFER_BULK,
166         .wMaxPacketSize         = __constant_cpu_to_le16(512),
167 };
168
169 static struct usb_descriptor_header *hs_function[] __initdata = {
170         (struct usb_descriptor_header *) &obex_control_intf,
171         (struct usb_descriptor_header *) &obex_cdc_header_desc,
172         (struct usb_descriptor_header *) &obex_desc,
173         (struct usb_descriptor_header *) &obex_cdc_union_desc,
174
175         (struct usb_descriptor_header *) &obex_data_nop_intf,
176         (struct usb_descriptor_header *) &obex_data_intf,
177         (struct usb_descriptor_header *) &obex_hs_ep_in_desc,
178         (struct usb_descriptor_header *) &obex_hs_ep_out_desc,
179         NULL,
180 };
181
182 /* Full-Speed Support */
183
184 static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
185         .bLength                = USB_DT_ENDPOINT_SIZE,
186         .bDescriptorType        = USB_DT_ENDPOINT,
187
188         .bEndpointAddress       = USB_DIR_IN,
189         .bmAttributes           = USB_ENDPOINT_XFER_BULK,
190 };
191
192 static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
193         .bLength                = USB_DT_ENDPOINT_SIZE,
194         .bDescriptorType        = USB_DT_ENDPOINT,
195
196         .bEndpointAddress       = USB_DIR_OUT,
197         .bmAttributes           = USB_ENDPOINT_XFER_BULK,
198 };
199
200 static struct usb_descriptor_header *fs_function[] __initdata = {
201         (struct usb_descriptor_header *) &obex_control_intf,
202         (struct usb_descriptor_header *) &obex_cdc_header_desc,
203         (struct usb_descriptor_header *) &obex_desc,
204         (struct usb_descriptor_header *) &obex_cdc_union_desc,
205
206         (struct usb_descriptor_header *) &obex_data_nop_intf,
207         (struct usb_descriptor_header *) &obex_data_intf,
208         (struct usb_descriptor_header *) &obex_fs_ep_in_desc,
209         (struct usb_descriptor_header *) &obex_fs_ep_out_desc,
210         NULL,
211 };
212
213 /*-------------------------------------------------------------------------*/
214
215 static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
216 {
217         struct f_obex           *obex = func_to_obex(f);
218         struct usb_composite_dev *cdev = f->config->cdev;
219
220         if (intf == obex->ctrl_id) {
221                 if (alt != 0)
222                         goto fail;
223                 /* NOP */
224                 DBG(cdev, "reset obex ttyGS%d control\n", obex->port_num);
225
226         } else if (intf == obex->data_id) {
227                 if (alt > 1)
228                         goto fail;
229
230                 if (obex->port.in->driver_data) {
231                         DBG(cdev, "reset obex ttyGS%d\n", obex->port_num);
232                         gserial_disconnect(&obex->port);
233                 }
234
235                 if (!obex->port.in_desc) {
236                         DBG(cdev, "init obex ttyGS%d\n", obex->port_num);
237                         obex->port.in_desc = ep_choose(cdev->gadget,
238                                         obex->hs.obex_in, obex->fs.obex_in);
239                         obex->port.out_desc = ep_choose(cdev->gadget,
240                                         obex->hs.obex_out, obex->fs.obex_out);
241                 }
242
243                 if (alt == 1) {
244                         DBG(cdev, "activate obex ttyGS%d\n", obex->port_num);
245                         obex->port.in_desc = ep_choose(cdev->gadget,
246                                         obex->hs.obex_in, obex->fs.obex_in);
247                         obex->port.out_desc = ep_choose(cdev->gadget,
248                                         obex->hs.obex_out, obex->fs.obex_out);
249                         gserial_connect(&obex->port, obex->port_num);
250                 }
251
252         } else
253                 goto fail;
254
255         return 0;
256
257 fail:
258         return -EINVAL;
259 }
260
261 static int obex_get_alt(struct usb_function *f, unsigned intf)
262 {
263         struct f_obex           *obex = func_to_obex(f);
264
265         if (intf == obex->ctrl_id)
266                 return 0;
267
268         return obex->port.in->driver_data ? 1 : 0;
269 }
270
271 static void obex_disable(struct usb_function *f)
272 {
273         struct f_obex   *obex = func_to_obex(f);
274         struct usb_composite_dev *cdev = f->config->cdev;
275
276         DBG(cdev, "obex ttyGS%d disable\n", obex->port_num);
277         gserial_disconnect(&obex->port);
278 }
279
280 /*-------------------------------------------------------------------------*/
281
282 static int __init
283 obex_bind(struct usb_configuration *c, struct usb_function *f)
284 {
285         struct usb_composite_dev *cdev = c->cdev;
286         struct f_obex           *obex = func_to_obex(f);
287         int                     status;
288         struct usb_ep           *ep;
289
290         /* allocate instance-specific interface IDs, and patch descriptors */
291
292         status = usb_interface_id(c, f);
293         if (status < 0)
294                 goto fail;
295         obex->ctrl_id = status;
296
297         obex_control_intf.bInterfaceNumber = status;
298         obex_cdc_union_desc.bMasterInterface0 = status;
299
300         status = usb_interface_id(c, f);
301         if (status < 0)
302                 goto fail;
303         obex->data_id = status;
304
305         obex_data_nop_intf.bInterfaceNumber = status;
306         obex_data_intf.bInterfaceNumber = status;
307         obex_cdc_union_desc.bSlaveInterface0 = status;
308
309         /* allocate instance-specific endpoints */
310
311         ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc);
312         if (!ep)
313                 goto fail;
314         obex->port.in = ep;
315         ep->driver_data = cdev; /* claim */
316
317         ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc);
318         if (!ep)
319                 goto fail;
320         obex->port.out = ep;
321         ep->driver_data = cdev; /* claim */
322
323         /* copy descriptors, and track endpoint copies */
324         f->descriptors = usb_copy_descriptors(fs_function);
325
326         obex->fs.obex_in = usb_find_endpoint(fs_function,
327                         f->descriptors, &obex_fs_ep_in_desc);
328         obex->fs.obex_out = usb_find_endpoint(fs_function,
329                         f->descriptors, &obex_fs_ep_out_desc);
330
331         /* support all relevant hardware speeds... we expect that when
332          * hardware is dual speed, all bulk-capable endpoints work at
333          * both speeds
334          */
335         if (gadget_is_dualspeed(c->cdev->gadget)) {
336
337                 obex_hs_ep_in_desc.bEndpointAddress =
338                                 obex_fs_ep_in_desc.bEndpointAddress;
339                 obex_hs_ep_out_desc.bEndpointAddress =
340                                 obex_fs_ep_out_desc.bEndpointAddress;
341
342                 /* copy descriptors, and track endpoint copies */
343                 f->hs_descriptors = usb_copy_descriptors(hs_function);
344
345                 obex->hs.obex_in = usb_find_endpoint(hs_function,
346                                 f->hs_descriptors, &obex_hs_ep_in_desc);
347                 obex->hs.obex_out = usb_find_endpoint(hs_function,
348                                 f->hs_descriptors, &obex_hs_ep_out_desc);
349         }
350
351         DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
352                         obex->port_num,
353                         gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
354                         obex->port.in->name, obex->port.out->name);
355
356         return 0;
357
358 fail:
359         /* we might as well release our claims on endpoints */
360         if (obex->port.out)
361                 obex->port.out->driver_data = NULL;
362         if (obex->port.in)
363                 obex->port.in->driver_data = NULL;
364
365         ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
366
367         return status;
368 }
369
370 static void
371 obex_unbind(struct usb_configuration *c, struct usb_function *f)
372 {
373         if (gadget_is_dualspeed(c->cdev->gadget))
374                 usb_free_descriptors(f->hs_descriptors);
375         usb_free_descriptors(f->descriptors);
376         kfree(func_to_obex(f));
377 }
378
379 /* Some controllers can't support CDC OBEX ... */
380 static inline bool can_support_obex(struct usb_configuration *c)
381 {
382         /* Since the first interface is a NOP, we can ignore the
383          * issue of multi-interface support on most controllers.
384          *
385          * Altsettings are mandatory, however...
386          */
387         if (!gadget_supports_altsettings(c->cdev->gadget))
388                 return false;
389
390         /* everything else is *probably* fine ... */
391         return true;
392 }
393
394 /**
395  * obex_bind_config - add a CDC OBEX function to a configuration
396  * @c: the configuration to support the CDC OBEX instance
397  * @port_num: /dev/ttyGS* port this interface will use
398  * Context: single threaded during gadget setup
399  *
400  * Returns zero on success, else negative errno.
401  *
402  * Caller must have called @gserial_setup() with enough ports to
403  * handle all the ones it binds.  Caller is also responsible
404  * for calling @gserial_cleanup() before module unload.
405  */
406 int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
407 {
408         struct f_obex   *obex;
409         int             status;
410
411         if (!can_support_obex(c))
412                 return -EINVAL;
413
414         /* maybe allocate device-global string IDs, and patch descriptors */
415         if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
416                 status = usb_string_id(c->cdev);
417                 if (status < 0)
418                         return status;
419                 obex_string_defs[OBEX_CTRL_IDX].id = status;
420
421                 status = usb_string_id(c->cdev);
422                 if (status < 0)
423                         return status;
424                 obex_string_defs[OBEX_DATA_IDX].id = status;
425
426                 status = usb_string_id(c->cdev);
427                 if (status < 0)
428                         return status;
429                 obex_string_defs[OBEX_CTRL0_IDX].id = status;
430
431                 status = usb_string_id(c->cdev);
432                 if (status < 0)
433                         return status;
434                 obex_string_defs[OBEX_CTRL1_IDX].id = status;
435         }
436
437         obex_data_nop_intf.iInterface = obex_string_defs[OBEX_DATA_IDX].id;
438         obex_data_intf.iInterface = obex_string_defs[OBEX_DATA_IDX].id;
439
440         switch (port_num) {
441         case 0:
442                 obex_control_intf.iInterface = obex_string_defs[OBEX_CTRL0_IDX].id;
443                 break;
444         case 1:
445                 obex_control_intf.iInterface = obex_string_defs[OBEX_CTRL1_IDX].id;
446                 break;
447         default:
448                 obex_control_intf.iInterface = obex_string_defs[OBEX_CTRL_IDX].id;
449                 break;
450         }
451
452         /* allocate and initialize one new instance */
453         obex = kzalloc(sizeof *obex, GFP_KERNEL);
454         if (!obex)
455                 return -ENOMEM;
456
457         obex->port_num = port_num;
458
459         obex->port.func.name = "obex";
460         obex->port.func.strings = obex_strings;
461         /* descriptors are per-instance copies */
462         obex->port.func.bind = obex_bind;
463         obex->port.func.unbind = obex_unbind;
464         obex->port.func.set_alt = obex_set_alt;
465         obex->port.func.get_alt = obex_get_alt;
466         obex->port.func.disable = obex_disable;
467
468         status = usb_add_function(c, &obex->port.func);
469         if (status)
470                 kfree(obex);
471
472         return status;
473 }
474
475 MODULE_AUTHOR("Felipe Balbi");
476 MODULE_LICENSE("GPL");