aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-08-18 20:45:25 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-10-17 17:40:53 -0400
commit2121427836c9eeaed3002e1add89f1e8c7a00261 (patch)
treeeedc03c671d431bcdbc8dc6a866c564bd6a0b53c
parent3086775a4916b0fe128d924d83f4e7d7c39e4d0e (diff)
usb gadget: defer obex enumeration
Some USB peripheral controller drivers support software control over the data pullup. Use those controls to prevent the OBEX function from enumerating until the userspace server has opened the /dev/ttyGS* node it will use to implement protocol chitchat with the USB host. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/usb/gadget/f_obex.c61
1 files changed, 54 insertions, 7 deletions
diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c
index 86241b2ca8f4..80c2e7e9622f 100644
--- a/drivers/usb/gadget/f_obex.c
+++ b/drivers/usb/gadget/f_obex.c
@@ -35,13 +35,8 @@
35 * This CDC OBEX function support just packages a TTY-ish byte stream. 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 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. 37 * relevant protocol details ... this is just a kernel passthrough.
38 * 38 * When possible, we prevent gadget enumeration until that server is
39 * REVISIT this driver shouldn't actually activate before that user mode 39 * ready to handle the commands.
40 * server is ready to respond! When the "serial gadget" utility code
41 * adds open/close notifications, this driver should use them with new
42 * (TBS) composite gadget hooks that wrap usb_gadget_disconnect() and
43 * usb_gadget_connect() calls with refcounts ... disconnect() when we
44 * bind, then connect() when the user server code is ready to respond.
45 */ 40 */
46 41
47struct obex_ep_descs { 42struct obex_ep_descs {
@@ -54,6 +49,7 @@ struct f_obex {
54 u8 ctrl_id; 49 u8 ctrl_id;
55 u8 data_id; 50 u8 data_id;
56 u8 port_num; 51 u8 port_num;
52 u8 can_activate;
57 53
58 struct obex_ep_descs fs; 54 struct obex_ep_descs fs;
59 struct obex_ep_descs hs; 55 struct obex_ep_descs hs;
@@ -64,6 +60,11 @@ static inline struct f_obex *func_to_obex(struct usb_function *f)
64 return container_of(f, struct f_obex, port.func); 60 return container_of(f, struct f_obex, port.func);
65} 61}
66 62
63static inline struct f_obex *port_to_obex(struct gserial *p)
64{
65 return container_of(p, struct f_obex, port);
66}
67
67/*-------------------------------------------------------------------------*/ 68/*-------------------------------------------------------------------------*/
68 69
69#define OBEX_CTRL_IDX 0 70#define OBEX_CTRL_IDX 0
@@ -269,6 +270,38 @@ static void obex_disable(struct usb_function *f)
269 270
270/*-------------------------------------------------------------------------*/ 271/*-------------------------------------------------------------------------*/
271 272
273static void obex_connect(struct gserial *g)
274{
275 struct f_obex *obex = port_to_obex(g);
276 struct usb_composite_dev *cdev = g->func.config->cdev;
277 int status;
278
279 if (!obex->can_activate)
280 return;
281
282 status = usb_function_activate(&g->func);
283 if (status)
284 DBG(cdev, "obex ttyGS%d function activate --> %d\n",
285 obex->port_num, status);
286}
287
288static void obex_disconnect(struct gserial *g)
289{
290 struct f_obex *obex = port_to_obex(g);
291 struct usb_composite_dev *cdev = g->func.config->cdev;
292 int status;
293
294 if (!obex->can_activate)
295 return;
296
297 status = usb_function_deactivate(&g->func);
298 if (status)
299 DBG(cdev, "obex ttyGS%d function deactivate --> %d\n",
300 obex->port_num, status);
301}
302
303/*-------------------------------------------------------------------------*/
304
272static int __init 305static int __init
273obex_bind(struct usb_configuration *c, struct usb_function *f) 306obex_bind(struct usb_configuration *c, struct usb_function *f)
274{ 307{
@@ -338,6 +371,17 @@ obex_bind(struct usb_configuration *c, struct usb_function *f)
338 f->descriptors, &obex_hs_ep_out_desc); 371 f->descriptors, &obex_hs_ep_out_desc);
339 } 372 }
340 373
374 /* Avoid letting this gadget enumerate until the userspace
375 * OBEX server is active.
376 */
377 status = usb_function_deactivate(f);
378 if (status < 0)
379 WARNING(cdev, "obex ttyGS%d: can't prevent enumeration, %d\n",
380 obex->port_num, status);
381 else
382 obex->can_activate = true;
383
384
341 DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", 385 DBG(cdev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n",
342 obex->port_num, 386 obex->port_num,
343 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 387 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -426,6 +470,9 @@ int __init obex_bind_config(struct usb_configuration *c, u8 port_num)
426 470
427 obex->port_num = port_num; 471 obex->port_num = port_num;
428 472
473 obex->port.connect = obex_connect;
474 obex->port.disconnect = obex_disconnect;
475
429 obex->port.func.name = "obex"; 476 obex->port.func.name = "obex";
430 obex->port.func.strings = obex_strings; 477 obex->port.func.strings = obex_strings;
431 /* descriptors are per-instance copies */ 478 /* descriptors are per-instance copies */