diff options
-rw-r--r-- | drivers/usb/gadget/f_obex.c | 61 |
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 | ||
47 | struct obex_ep_descs { | 42 | struct 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 | ||
63 | static 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 | ||
273 | static 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 | |||
288 | static 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 | |||
272 | static int __init | 305 | static int __init |
273 | obex_bind(struct usb_configuration *c, struct usb_function *f) | 306 | obex_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 */ |