Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
f_obex.c
Go to the documentation of this file.
1 /*
2  * f_obex.c -- USB CDC OBEX function driver
3  *
4  * Copyright (C) 2008 Nokia Corporation
5  * Contact: Felipe Balbi <[email protected]>
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 
15 /* #define VERBOSE_DEBUG */
16 
17 #include <linux/slab.h>
18 #include <linux/kernel.h>
19 #include <linux/device.h>
20 #include <linux/module.h>
21 
22 #include "u_serial.h"
23 #include "gadget_chips.h"
24 
25 
26 /*
27  * This CDC OBEX function support just packages a TTY-ish byte stream.
28  * A user mode server will put it into "raw" mode and handle all the
29  * relevant protocol details ... this is just a kernel passthrough.
30  * When possible, we prevent gadget enumeration until that server is
31  * ready to handle the commands.
32  */
33 
34 struct f_obex {
35  struct gserial port;
40 };
41 
42 static inline struct f_obex *func_to_obex(struct usb_function *f)
43 {
44  return container_of(f, struct f_obex, port.func);
45 }
46 
47 static inline struct f_obex *port_to_obex(struct gserial *p)
48 {
49  return container_of(p, struct f_obex, port);
50 }
51 
52 /*-------------------------------------------------------------------------*/
53 
54 #define OBEX_CTRL_IDX 0
55 #define OBEX_DATA_IDX 1
56 
57 static struct usb_string obex_string_defs[] = {
58  [OBEX_CTRL_IDX].s = "CDC Object Exchange (OBEX)",
59  [OBEX_DATA_IDX].s = "CDC OBEX Data",
60  { }, /* end of list */
61 };
62 
63 static struct usb_gadget_strings obex_string_table = {
64  .language = 0x0409, /* en-US */
65  .strings = obex_string_defs,
66 };
67 
68 static struct usb_gadget_strings *obex_strings[] = {
69  &obex_string_table,
70  NULL,
71 };
72 
73 /*-------------------------------------------------------------------------*/
74 
75 static struct usb_interface_descriptor obex_control_intf __initdata = {
76  .bLength = sizeof(obex_control_intf),
78  .bInterfaceNumber = 0,
79 
80  .bAlternateSetting = 0,
81  .bNumEndpoints = 0,
84 };
85 
86 static struct usb_interface_descriptor obex_data_nop_intf __initdata = {
87  .bLength = sizeof(obex_data_nop_intf),
89  .bInterfaceNumber = 1,
90 
91  .bAlternateSetting = 0,
92  .bNumEndpoints = 0,
94 };
95 
96 static struct usb_interface_descriptor obex_data_intf __initdata = {
97  .bLength = sizeof(obex_data_intf),
99  .bInterfaceNumber = 2,
100 
101  .bAlternateSetting = 1,
102  .bNumEndpoints = 2,
104 };
105 
106 static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = {
107  .bLength = sizeof(obex_cdc_header_desc),
110  .bcdCDC = cpu_to_le16(0x0120),
111 };
112 
113 static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = {
114  .bLength = sizeof(obex_cdc_union_desc),
117  .bMasterInterface0 = 1,
118  .bSlaveInterface0 = 2,
119 };
120 
121 static struct usb_cdc_obex_desc obex_desc __initdata = {
122  .bLength = sizeof(obex_desc),
125  .bcdVersion = cpu_to_le16(0x0100),
126 };
127 
128 /* High-Speed Support */
129 
130 static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = {
132  .bDescriptorType = USB_DT_ENDPOINT,
133 
134  .bEndpointAddress = USB_DIR_OUT,
135  .bmAttributes = USB_ENDPOINT_XFER_BULK,
136  .wMaxPacketSize = cpu_to_le16(512),
137 };
138 
139 static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = {
141  .bDescriptorType = USB_DT_ENDPOINT,
142 
143  .bEndpointAddress = USB_DIR_IN,
144  .bmAttributes = USB_ENDPOINT_XFER_BULK,
145  .wMaxPacketSize = cpu_to_le16(512),
146 };
147 
148 static struct usb_descriptor_header *hs_function[] __initdata = {
149  (struct usb_descriptor_header *) &obex_control_intf,
150  (struct usb_descriptor_header *) &obex_cdc_header_desc,
151  (struct usb_descriptor_header *) &obex_desc,
152  (struct usb_descriptor_header *) &obex_cdc_union_desc,
153 
154  (struct usb_descriptor_header *) &obex_data_nop_intf,
155  (struct usb_descriptor_header *) &obex_data_intf,
156  (struct usb_descriptor_header *) &obex_hs_ep_in_desc,
157  (struct usb_descriptor_header *) &obex_hs_ep_out_desc,
158  NULL,
159 };
160 
161 /* Full-Speed Support */
162 
163 static struct usb_endpoint_descriptor obex_fs_ep_in_desc __initdata = {
165  .bDescriptorType = USB_DT_ENDPOINT,
166 
167  .bEndpointAddress = USB_DIR_IN,
168  .bmAttributes = USB_ENDPOINT_XFER_BULK,
169 };
170 
171 static struct usb_endpoint_descriptor obex_fs_ep_out_desc __initdata = {
173  .bDescriptorType = USB_DT_ENDPOINT,
174 
175  .bEndpointAddress = USB_DIR_OUT,
176  .bmAttributes = USB_ENDPOINT_XFER_BULK,
177 };
178 
179 static struct usb_descriptor_header *fs_function[] __initdata = {
180  (struct usb_descriptor_header *) &obex_control_intf,
181  (struct usb_descriptor_header *) &obex_cdc_header_desc,
182  (struct usb_descriptor_header *) &obex_desc,
183  (struct usb_descriptor_header *) &obex_cdc_union_desc,
184 
185  (struct usb_descriptor_header *) &obex_data_nop_intf,
186  (struct usb_descriptor_header *) &obex_data_intf,
187  (struct usb_descriptor_header *) &obex_fs_ep_in_desc,
188  (struct usb_descriptor_header *) &obex_fs_ep_out_desc,
189  NULL,
190 };
191 
192 /*-------------------------------------------------------------------------*/
193 
194 static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
195 {
196  struct f_obex *obex = func_to_obex(f);
197  struct usb_composite_dev *cdev = f->config->cdev;
198 
199  if (intf == obex->ctrl_id) {
200  if (alt != 0)
201  goto fail;
202  /* NOP */
203  DBG(cdev, "reset obex ttyGS%d control\n", obex->port_num);
204 
205  } else if (intf == obex->data_id) {
206  if (alt > 1)
207  goto fail;
208 
209  if (obex->port.in->driver_data) {
210  DBG(cdev, "reset obex ttyGS%d\n", obex->port_num);
211  gserial_disconnect(&obex->port);
212  }
213 
214  if (!obex->port.in->desc || !obex->port.out->desc) {
215  DBG(cdev, "init obex ttyGS%d\n", obex->port_num);
216  if (config_ep_by_speed(cdev->gadget, f,
217  obex->port.in) ||
218  config_ep_by_speed(cdev->gadget, f,
219  obex->port.out)) {
220  obex->port.out->desc = NULL;
221  obex->port.in->desc = NULL;
222  goto fail;
223  }
224  }
225 
226  if (alt == 1) {
227  DBG(cdev, "activate obex ttyGS%d\n", obex->port_num);
228  gserial_connect(&obex->port, obex->port_num);
229  }
230 
231  } else
232  goto fail;
233 
234  return 0;
235 
236 fail:
237  return -EINVAL;
238 }
239 
240 static int obex_get_alt(struct usb_function *f, unsigned intf)
241 {
242  struct f_obex *obex = func_to_obex(f);
243 
244  if (intf == obex->ctrl_id)
245  return 0;
246 
247  return obex->port.in->driver_data ? 1 : 0;
248 }
249 
250 static void obex_disable(struct usb_function *f)
251 {
252  struct f_obex *obex = func_to_obex(f);
253  struct usb_composite_dev *cdev = f->config->cdev;
254 
255  DBG(cdev, "obex ttyGS%d disable\n", obex->port_num);
256  gserial_disconnect(&obex->port);
257 }
258 
259 /*-------------------------------------------------------------------------*/
260 
261 static void obex_connect(struct gserial *g)
262 {
263  struct f_obex *obex = port_to_obex(g);
264  struct usb_composite_dev *cdev = g->func.config->cdev;
265  int status;
266 
267  if (!obex->can_activate)
268  return;
269 
270  status = usb_function_activate(&g->func);
271  if (status)
272  DBG(cdev, "obex ttyGS%d function activate --> %d\n",
273  obex->port_num, status);
274 }
275 
276 static void obex_disconnect(struct gserial *g)
277 {
278  struct f_obex *obex = port_to_obex(g);
279  struct usb_composite_dev *cdev = g->func.config->cdev;
280  int status;
281 
282  if (!obex->can_activate)
283  return;
284 
285  status = usb_function_deactivate(&g->func);
286  if (status)
287  DBG(cdev, "obex ttyGS%d function deactivate --> %d\n",
288  obex->port_num, status);
289 }
290 
291 /*-------------------------------------------------------------------------*/
292 
293 static int __init
294 obex_bind(struct usb_configuration *c, struct usb_function *f)
295 {
296  struct usb_composite_dev *cdev = c->cdev;
297  struct f_obex *obex = func_to_obex(f);
298  int status;
299  struct usb_ep *ep;
300 
301  /* allocate instance-specific interface IDs, and patch descriptors */
302 
303  status = usb_interface_id(c, f);
304  if (status < 0)
305  goto fail;
306  obex->ctrl_id = status;
307 
308  obex_control_intf.bInterfaceNumber = status;
309  obex_cdc_union_desc.bMasterInterface0 = status;
310 
311  status = usb_interface_id(c, f);
312  if (status < 0)
313  goto fail;
314  obex->data_id = status;
315 
316  obex_data_nop_intf.bInterfaceNumber = status;
317  obex_data_intf.bInterfaceNumber = status;
318  obex_cdc_union_desc.bSlaveInterface0 = status;
319 
320  /* allocate instance-specific endpoints */
321 
322  ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc);
323  if (!ep)
324  goto fail;
325  obex->port.in = ep;
326  ep->driver_data = cdev; /* claim */
327 
328  ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc);
329  if (!ep)
330  goto fail;
331  obex->port.out = ep;
332  ep->driver_data = cdev; /* claim */
333 
334  /* copy descriptors, and track endpoint copies */
335  f->descriptors = usb_copy_descriptors(fs_function);
336 
337  /* support all relevant hardware speeds... we expect that when
338  * hardware is dual speed, all bulk-capable endpoints work at
339  * both speeds
340  */
341  if (gadget_is_dualspeed(c->cdev->gadget)) {
342 
343  obex_hs_ep_in_desc.bEndpointAddress =
344  obex_fs_ep_in_desc.bEndpointAddress;
345  obex_hs_ep_out_desc.bEndpointAddress =
346  obex_fs_ep_out_desc.bEndpointAddress;
347 
348  /* copy descriptors, and track endpoint copies */
349  f->hs_descriptors = usb_copy_descriptors(hs_function);
350  }
351 
352  /* Avoid letting this gadget enumerate until the userspace
353  * OBEX server is active.
354  */
355  status = usb_function_deactivate(f);
356  if (status < 0)
357  WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
358  obex->port_num, status);
359  else
360  obex->can_activate = true;
361 
362 
363  DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
364  obex->port_num,
365  gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
366  obex->port.in->name, obex->port.out->name);
367 
368  return 0;
369 
370 fail:
371  /* we might as well release our claims on endpoints */
372  if (obex->port.out)
373  obex->port.out->driver_data = NULL;
374  if (obex->port.in)
375  obex->port.in->driver_data = NULL;
376 
377  ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
378 
379  return status;
380 }
381 
382 static void
383 obex_unbind(struct usb_configuration *c, struct usb_function *f)
384 {
385  if (gadget_is_dualspeed(c->cdev->gadget))
386  usb_free_descriptors(f->hs_descriptors);
387  usb_free_descriptors(f->descriptors);
388  kfree(func_to_obex(f));
389 }
390 
391 /* Some controllers can't support CDC OBEX ... */
392 static inline bool can_support_obex(struct usb_configuration *c)
393 {
394  /* Since the first interface is a NOP, we can ignore the
395  * issue of multi-interface support on most controllers.
396  *
397  * Altsettings are mandatory, however...
398  */
399  if (!gadget_supports_altsettings(c->cdev->gadget))
400  return false;
401 
402  /* everything else is *probably* fine ... */
403  return true;
404 }
405 
419 {
420  struct f_obex *obex;
421  int status;
422 
423  if (!can_support_obex(c))
424  return -EINVAL;
425 
426  /* maybe allocate device-global string IDs, and patch descriptors */
427  if (obex_string_defs[OBEX_CTRL_IDX].id == 0) {
428  status = usb_string_id(c->cdev);
429  if (status < 0)
430  return status;
431  obex_string_defs[OBEX_CTRL_IDX].id = status;
432 
433  obex_control_intf.iInterface = status;
434 
435  status = usb_string_id(c->cdev);
436  if (status < 0)
437  return status;
438  obex_string_defs[OBEX_DATA_IDX].id = status;
439 
440  obex_data_nop_intf.iInterface =
441  obex_data_intf.iInterface = status;
442  }
443 
444  /* allocate and initialize one new instance */
445  obex = kzalloc(sizeof *obex, GFP_KERNEL);
446  if (!obex)
447  return -ENOMEM;
448 
449  obex->port_num = port_num;
450 
451  obex->port.connect = obex_connect;
452  obex->port.disconnect = obex_disconnect;
453 
454  obex->port.func.name = "obex";
455  obex->port.func.strings = obex_strings;
456  /* descriptors are per-instance copies */
457  obex->port.func.bind = obex_bind;
458  obex->port.func.unbind = obex_unbind;
459  obex->port.func.set_alt = obex_set_alt;
460  obex->port.func.get_alt = obex_get_alt;
461  obex->port.func.disable = obex_disable;
462 
463  status = usb_add_function(c, &obex->port.func);
464  if (status)
465  kfree(obex);
466 
467  return status;
468 }
469 
470 MODULE_AUTHOR("Felipe Balbi");
471 MODULE_LICENSE("GPL");