aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2008-08-06 21:49:57 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2008-08-13 20:32:57 -0400
commit1f1ba11b64947051fc32aa15fcccef6463b433f7 (patch)
tree546d99300dc56f4fe744385263eb3864e843f83e /drivers/usb
parent630c7aa80152881980e45c11584f22476f71959b (diff)
usb gadget: issue notifications from ACM function
Update the CDC-ACM gadget code to support the peripheral-to-host notifications when the tty is opened or closed, or issues a BREAK. The serial framework code calls new generic hooks; right now only CDC-ACM uses those hooks. This resolves several REVISIT comments in the code. (Based on a patch from Felipe Balbi.) Note that this doesn't expose USB_CDC_CAP_BRK to the host, since this code still rejects USB_CDC_REQ_SEND_BREAK control requests for host-to-peripheral BREAK signaling (received via /dev/ttyGS*). Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Cc: Felipe Balbi <felipe.balbi@nokia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/f_acm.c194
-rw-r--r--drivers/usb/gadget/u_serial.c56
-rw-r--r--drivers/usb/gadget/u_serial.h12
3 files changed, 235 insertions, 27 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index f3bf5612af2d..5ee1590b8e9c 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -47,16 +47,37 @@ struct f_acm {
47 u8 ctrl_id, data_id; 47 u8 ctrl_id, data_id;
48 u8 port_num; 48 u8 port_num;
49 49
50 u8 pending;
51
52 /* lock is mostly for pending and notify_req ... they get accessed
53 * by callbacks both from tty (open/close/break) under its spinlock,
54 * and notify_req.complete() which can't use that lock.
55 */
56 spinlock_t lock;
57
50 struct acm_ep_descs fs; 58 struct acm_ep_descs fs;
51 struct acm_ep_descs hs; 59 struct acm_ep_descs hs;
52 60
53 struct usb_ep *notify; 61 struct usb_ep *notify;
54 struct usb_endpoint_descriptor *notify_desc; 62 struct usb_endpoint_descriptor *notify_desc;
63 struct usb_request *notify_req;
55 64
56 struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ 65 struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
66
67 /* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
57 u16 port_handshake_bits; 68 u16 port_handshake_bits;
58#define RS232_RTS (1 << 1) /* unused with full duplex */ 69#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
59#define RS232_DTR (1 << 0) /* host is ready for data r/w */ 70#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
71
72 /* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
73 u16 serial_state;
74#define ACM_CTRL_OVERRUN (1 << 6)
75#define ACM_CTRL_PARITY (1 << 5)
76#define ACM_CTRL_FRAMING (1 << 4)
77#define ACM_CTRL_RI (1 << 3)
78#define ACM_CTRL_BRK (1 << 2)
79#define ACM_CTRL_DSR (1 << 1)
80#define ACM_CTRL_DCD (1 << 0)
60}; 81};
61 82
62static inline struct f_acm *func_to_acm(struct usb_function *f) 83static inline struct f_acm *func_to_acm(struct usb_function *f)
@@ -64,12 +85,17 @@ static inline struct f_acm *func_to_acm(struct usb_function *f)
64 return container_of(f, struct f_acm, port.func); 85 return container_of(f, struct f_acm, port.func);
65} 86}
66 87
88static inline struct f_acm *port_to_acm(struct gserial *p)
89{
90 return container_of(p, struct f_acm, port);
91}
92
67/*-------------------------------------------------------------------------*/ 93/*-------------------------------------------------------------------------*/
68 94
69/* notification endpoint uses smallish and infrequent fixed-size messages */ 95/* notification endpoint uses smallish and infrequent fixed-size messages */
70 96
71#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ 97#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
72#define GS_NOTIFY_MAXPACKET 8 98#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
73 99
74/* interface and class descriptors: */ 100/* interface and class descriptors: */
75 101
@@ -115,7 +141,7 @@ static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
115 .bLength = sizeof(acm_descriptor), 141 .bLength = sizeof(acm_descriptor),
116 .bDescriptorType = USB_DT_CS_INTERFACE, 142 .bDescriptorType = USB_DT_CS_INTERFACE,
117 .bDescriptorSubType = USB_CDC_ACM_TYPE, 143 .bDescriptorSubType = USB_CDC_ACM_TYPE,
118 .bmCapabilities = (1 << 1), 144 .bmCapabilities = USB_CDC_CAP_LINE,
119}; 145};
120 146
121static struct usb_cdc_union_desc acm_union_desc __initdata = { 147static struct usb_cdc_union_desc acm_union_desc __initdata = {
@@ -275,6 +301,11 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
275 301
276 /* composite driver infrastructure handles everything except 302 /* composite driver infrastructure handles everything except
277 * CDC class messages; interface activation uses set_alt(). 303 * CDC class messages; interface activation uses set_alt().
304 *
305 * Note CDC spec table 4 lists the ACM request profile. It requires
306 * encapsulated command support ... we don't handle any, and respond
307 * to them by stalling. Options include get/set/clear comm features
308 * (not that useful) and SEND_BREAK.
278 */ 309 */
279 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { 310 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
280 311
@@ -310,7 +341,7 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
310 value = 0; 341 value = 0;
311 342
312 /* FIXME we should not allow data to flow until the 343 /* FIXME we should not allow data to flow until the
313 * host sets the RS232_DTR bit; and when it clears 344 * host sets the ACM_CTRL_DTR bit; and when it clears
314 * that bit, we should return to that no-flow state. 345 * that bit, we should return to that no-flow state.
315 */ 346 */
316 acm->port_handshake_bits = w_value; 347 acm->port_handshake_bits = w_value;
@@ -348,9 +379,6 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
348 /* we know alt == 0, so this is an activation or a reset */ 379 /* we know alt == 0, so this is an activation or a reset */
349 380
350 if (intf == acm->ctrl_id) { 381 if (intf == acm->ctrl_id) {
351 /* REVISIT this may need more work when we start to
352 * send notifications ...
353 */
354 if (acm->notify->driver_data) { 382 if (acm->notify->driver_data) {
355 VDBG(cdev, "reset acm control interface %d\n", intf); 383 VDBG(cdev, "reset acm control interface %d\n", intf);
356 usb_ep_disable(acm->notify); 384 usb_ep_disable(acm->notify);
@@ -395,6 +423,128 @@ static void acm_disable(struct usb_function *f)
395 423
396/*-------------------------------------------------------------------------*/ 424/*-------------------------------------------------------------------------*/
397 425
426/**
427 * acm_cdc_notify - issue CDC notification to host
428 * @acm: wraps host to be notified
429 * @type: notification type
430 * @value: Refer to cdc specs, wValue field.
431 * @data: data to be sent
432 * @length: size of data
433 * Context: irqs blocked, acm->lock held, acm_notify_req non-null
434 *
435 * Returns zero on sucess or a negative errno.
436 *
437 * See section 6.3.5 of the CDC 1.1 specification for information
438 * about the only notification we issue: SerialState change.
439 */
440static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
441 void *data, unsigned length)
442{
443 struct usb_ep *ep = acm->notify;
444 struct usb_request *req;
445 struct usb_cdc_notification *notify;
446 const unsigned len = sizeof(*notify) + length;
447 void *buf;
448 int status;
449
450 req = acm->notify_req;
451 acm->notify_req = NULL;
452 acm->pending = false;
453
454 req->length = len;
455 notify = req->buf;
456 buf = notify + 1;
457
458 notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
459 | USB_RECIP_INTERFACE;
460 notify->bNotificationType = type;
461 notify->wValue = cpu_to_le16(value);
462 notify->wIndex = cpu_to_le16(acm->ctrl_id);
463 notify->wLength = cpu_to_le16(length);
464 memcpy(buf, data, length);
465
466 status = usb_ep_queue(ep, req, GFP_ATOMIC);
467 if (status < 0) {
468 ERROR(acm->port.func.config->cdev,
469 "acm ttyGS%d can't notify serial state, %d\n",
470 acm->port_num, status);
471 acm->notify_req = req;
472 }
473
474 return status;
475}
476
477static int acm_notify_serial_state(struct f_acm *acm)
478{
479 struct usb_composite_dev *cdev = acm->port.func.config->cdev;
480 int status;
481
482 spin_lock(&acm->lock);
483 if (acm->notify_req) {
484 DBG(cdev, "acm ttyGS%d serial state %04x\n",
485 acm->port_num, acm->serial_state);
486 status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
487 0, &acm->serial_state, sizeof(acm->serial_state));
488 } else {
489 acm->pending = true;
490 status = 0;
491 }
492 spin_unlock(&acm->lock);
493 return status;
494}
495
496static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
497{
498 struct f_acm *acm = req->context;
499 u8 doit = false;
500
501 /* on this call path we do NOT hold the port spinlock,
502 * which is why ACM needs its own spinlock
503 */
504 spin_lock(&acm->lock);
505 if (req->status != -ESHUTDOWN)
506 doit = acm->pending;
507 acm->notify_req = req;
508 spin_unlock(&acm->lock);
509
510 if (doit)
511 acm_notify_serial_state(acm);
512}
513
514/* connect == the TTY link is open */
515
516static void acm_connect(struct gserial *port)
517{
518 struct f_acm *acm = port_to_acm(port);
519
520 acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
521 acm_notify_serial_state(acm);
522}
523
524static void acm_disconnect(struct gserial *port)
525{
526 struct f_acm *acm = port_to_acm(port);
527
528 acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
529 acm_notify_serial_state(acm);
530}
531
532static int acm_send_break(struct gserial *port, int duration)
533{
534 struct f_acm *acm = port_to_acm(port);
535 u16 state;
536
537 state = acm->serial_state;
538 state &= ~ACM_CTRL_BRK;
539 if (duration)
540 state |= ACM_CTRL_BRK;
541
542 acm->serial_state = state;
543 return acm_notify_serial_state(acm);
544}
545
546/*-------------------------------------------------------------------------*/
547
398/* ACM function driver setup/binding */ 548/* ACM function driver setup/binding */
399static int __init 549static int __init
400acm_bind(struct usb_configuration *c, struct usb_function *f) 550acm_bind(struct usb_configuration *c, struct usb_function *f)
@@ -443,8 +593,20 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
443 acm->notify = ep; 593 acm->notify = ep;
444 ep->driver_data = cdev; /* claim */ 594 ep->driver_data = cdev; /* claim */
445 595
596 /* allocate notification */
597 acm->notify_req = gs_alloc_req(ep,
598 sizeof(struct usb_cdc_notification) + 2,
599 GFP_KERNEL);
600 if (!acm->notify_req)
601 goto fail;
602
603 acm->notify_req->complete = acm_cdc_notify_complete;
604 acm->notify_req->context = acm;
605
446 /* copy descriptors, and track endpoint copies */ 606 /* copy descriptors, and track endpoint copies */
447 f->descriptors = usb_copy_descriptors(acm_fs_function); 607 f->descriptors = usb_copy_descriptors(acm_fs_function);
608 if (!f->descriptors)
609 goto fail;
448 610
449 acm->fs.in = usb_find_endpoint(acm_fs_function, 611 acm->fs.in = usb_find_endpoint(acm_fs_function,
450 f->descriptors, &acm_fs_in_desc); 612 f->descriptors, &acm_fs_in_desc);
@@ -476,8 +638,6 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
476 f->hs_descriptors, &acm_hs_notify_desc); 638 f->hs_descriptors, &acm_hs_notify_desc);
477 } 639 }
478 640
479 /* FIXME provide a callback for triggering notifications */
480
481 DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", 641 DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
482 acm->port_num, 642 acm->port_num,
483 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 643 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -486,6 +646,9 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
486 return 0; 646 return 0;
487 647
488fail: 648fail:
649 if (acm->notify_req)
650 gs_free_req(acm->notify, acm->notify_req);
651
489 /* we might as well release our claims on endpoints */ 652 /* we might as well release our claims on endpoints */
490 if (acm->notify) 653 if (acm->notify)
491 acm->notify->driver_data = NULL; 654 acm->notify->driver_data = NULL;
@@ -502,10 +665,13 @@ fail:
502static void 665static void
503acm_unbind(struct usb_configuration *c, struct usb_function *f) 666acm_unbind(struct usb_configuration *c, struct usb_function *f)
504{ 667{
668 struct f_acm *acm = func_to_acm(f);
669
505 if (gadget_is_dualspeed(c->cdev->gadget)) 670 if (gadget_is_dualspeed(c->cdev->gadget))
506 usb_free_descriptors(f->hs_descriptors); 671 usb_free_descriptors(f->hs_descriptors);
507 usb_free_descriptors(f->descriptors); 672 usb_free_descriptors(f->descriptors);
508 kfree(func_to_acm(f)); 673 gs_free_req(acm->notify, acm->notify_req);
674 kfree(acm);
509} 675}
510 676
511/* Some controllers can't support CDC ACM ... */ 677/* Some controllers can't support CDC ACM ... */
@@ -569,8 +735,14 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
569 if (!acm) 735 if (!acm)
570 return -ENOMEM; 736 return -ENOMEM;
571 737
738 spin_lock_init(&acm->lock);
739
572 acm->port_num = port_num; 740 acm->port_num = port_num;
573 741
742 acm->port.connect = acm_connect;
743 acm->port.disconnect = acm_disconnect;
744 acm->port.send_break = acm_send_break;
745
574 acm->port.func.name = "acm"; 746 acm->port.func.name = "acm";
575 acm->port.func.strings = acm_strings; 747 acm->port.func.strings = acm_strings;
576 /* descriptors are per-instance copies */ 748 /* descriptors are per-instance copies */
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 6641efa55639..53d59287f2bc 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -60,7 +60,8 @@
60 * tty_struct links to the tty/filesystem framework 60 * tty_struct links to the tty/filesystem framework
61 * 61 *
62 * gserial <---> gs_port ... links will be null when the USB link is 62 * gserial <---> gs_port ... links will be null when the USB link is
63 * inactive; managed by gserial_{connect,disconnect}(). 63 * inactive; managed by gserial_{connect,disconnect}(). each gserial
64 * instance can wrap its own USB control protocol.
64 * gserial->ioport == usb_ep->driver_data ... gs_port 65 * gserial->ioport == usb_ep->driver_data ... gs_port
65 * gs_port->port_usb ... gserial 66 * gs_port->port_usb ... gserial
66 * 67 *
@@ -181,7 +182,7 @@ static void gs_buf_clear(struct gs_buf *gb)
181/* 182/*
182 * gs_buf_data_avail 183 * gs_buf_data_avail
183 * 184 *
184 * Return the number of bytes of data available in the circular 185 * Return the number of bytes of data written into the circular
185 * buffer. 186 * buffer.
186 */ 187 */
187static unsigned gs_buf_data_avail(struct gs_buf *gb) 188static unsigned gs_buf_data_avail(struct gs_buf *gb)
@@ -282,7 +283,7 @@ gs_buf_get(struct gs_buf *gb, char *buf, unsigned count)
282 * Allocate a usb_request and its buffer. Returns a pointer to the 283 * Allocate a usb_request and its buffer. Returns a pointer to the
283 * usb_request or NULL if there is an error. 284 * usb_request or NULL if there is an error.
284 */ 285 */
285static struct usb_request * 286struct usb_request *
286gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags) 287gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
287{ 288{
288 struct usb_request *req; 289 struct usb_request *req;
@@ -306,7 +307,7 @@ gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags)
306 * 307 *
307 * Free a usb_request and its buffer. 308 * Free a usb_request and its buffer.
308 */ 309 */
309static void gs_free_req(struct usb_ep *ep, struct usb_request *req) 310void gs_free_req(struct usb_ep *ep, struct usb_request *req)
310{ 311{
311 kfree(req->buf); 312 kfree(req->buf);
312 usb_ep_free_request(ep, req); 313 usb_ep_free_request(ep, req);
@@ -788,10 +789,13 @@ static int gs_open(struct tty_struct *tty, struct file *file)
788 789
789 /* if connected, start the I/O stream */ 790 /* if connected, start the I/O stream */
790 if (port->port_usb) { 791 if (port->port_usb) {
792 struct gserial *gser = port->port_usb;
793
791 pr_debug("gs_open: start ttyGS%d\n", port->port_num); 794 pr_debug("gs_open: start ttyGS%d\n", port->port_num);
792 gs_start_io(port); 795 gs_start_io(port);
793 796
794 /* REVISIT for ACM, issue "network connected" event */ 797 if (gser->connect)
798 gser->connect(gser);
795 } 799 }
796 800
797 pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); 801 pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file);
@@ -818,6 +822,7 @@ static int gs_writes_finished(struct gs_port *p)
818static void gs_close(struct tty_struct *tty, struct file *file) 822static void gs_close(struct tty_struct *tty, struct file *file)
819{ 823{
820 struct gs_port *port = tty->driver_data; 824 struct gs_port *port = tty->driver_data;
825 struct gserial *gser;
821 826
822 spin_lock_irq(&port->port_lock); 827 spin_lock_irq(&port->port_lock);
823 828
@@ -837,26 +842,27 @@ static void gs_close(struct tty_struct *tty, struct file *file)
837 port->openclose = true; 842 port->openclose = true;
838 port->open_count = 0; 843 port->open_count = 0;
839 844
840 if (port->port_usb) 845 gser = port->port_usb;
841 /* REVISIT for ACM, issue "network disconnected" event */; 846 if (gser && gser->disconnect)
847 gser->disconnect(gser);
842 848
843 /* wait for circular write buffer to drain, disconnect, or at 849 /* wait for circular write buffer to drain, disconnect, or at
844 * most GS_CLOSE_TIMEOUT seconds; then discard the rest 850 * most GS_CLOSE_TIMEOUT seconds; then discard the rest
845 */ 851 */
846 if (gs_buf_data_avail(&port->port_write_buf) > 0 852 if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) {
847 && port->port_usb) {
848 spin_unlock_irq(&port->port_lock); 853 spin_unlock_irq(&port->port_lock);
849 wait_event_interruptible_timeout(port->drain_wait, 854 wait_event_interruptible_timeout(port->drain_wait,
850 gs_writes_finished(port), 855 gs_writes_finished(port),
851 GS_CLOSE_TIMEOUT * HZ); 856 GS_CLOSE_TIMEOUT * HZ);
852 spin_lock_irq(&port->port_lock); 857 spin_lock_irq(&port->port_lock);
858 gser = port->port_usb;
853 } 859 }
854 860
855 /* Iff we're disconnected, there can be no I/O in flight so it's 861 /* Iff we're disconnected, there can be no I/O in flight so it's
856 * ok to free the circular buffer; else just scrub it. And don't 862 * ok to free the circular buffer; else just scrub it. And don't
857 * let the push tasklet fire again until we're re-opened. 863 * let the push tasklet fire again until we're re-opened.
858 */ 864 */
859 if (port->port_usb == NULL) 865 if (gser == NULL)
860 gs_buf_free(&port->port_write_buf); 866 gs_buf_free(&port->port_write_buf);
861 else 867 else
862 gs_buf_clear(&port->port_write_buf); 868 gs_buf_clear(&port->port_write_buf);
@@ -974,6 +980,24 @@ static void gs_unthrottle(struct tty_struct *tty)
974 spin_unlock_irqrestore(&port->port_lock, flags); 980 spin_unlock_irqrestore(&port->port_lock, flags);
975} 981}
976 982
983static int gs_break_ctl(struct tty_struct *tty, int duration)
984{
985 struct gs_port *port = tty->driver_data;
986 int status = 0;
987 struct gserial *gser;
988
989 pr_vdebug("gs_break_ctl: ttyGS%d, send break (%d) \n",
990 port->port_num, duration);
991
992 spin_lock_irq(&port->port_lock);
993 gser = port->port_usb;
994 if (gser && gser->send_break)
995 status = gser->send_break(gser, duration);
996 spin_unlock_irq(&port->port_lock);
997
998 return status;
999}
1000
977static const struct tty_operations gs_tty_ops = { 1001static const struct tty_operations gs_tty_ops = {
978 .open = gs_open, 1002 .open = gs_open,
979 .close = gs_close, 1003 .close = gs_close,
@@ -983,6 +1007,7 @@ static const struct tty_operations gs_tty_ops = {
983 .write_room = gs_write_room, 1007 .write_room = gs_write_room,
984 .chars_in_buffer = gs_chars_in_buffer, 1008 .chars_in_buffer = gs_chars_in_buffer,
985 .unthrottle = gs_unthrottle, 1009 .unthrottle = gs_unthrottle,
1010 .break_ctl = gs_break_ctl,
986}; 1011};
987 1012
988/*-------------------------------------------------------------------------*/ 1013/*-------------------------------------------------------------------------*/
@@ -1230,14 +1255,17 @@ int gserial_connect(struct gserial *gser, u8 port_num)
1230 1255
1231 /* REVISIT if waiting on "carrier detect", signal. */ 1256 /* REVISIT if waiting on "carrier detect", signal. */
1232 1257
1233 /* REVISIT for ACM, issue "network connection" status notification: 1258 /* if it's already open, start I/O ... and notify the serial
1234 * connected if open_count, else disconnected. 1259 * protocol about open/close status (connect/disconnect).
1235 */ 1260 */
1236
1237 /* if it's already open, start I/O */
1238 if (port->open_count) { 1261 if (port->open_count) {
1239 pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); 1262 pr_debug("gserial_connect: start ttyGS%d\n", port->port_num);
1240 gs_start_io(port); 1263 gs_start_io(port);
1264 if (gser->connect)
1265 gser->connect(gser);
1266 } else {
1267 if (gser->disconnect)
1268 gser->disconnect(gser);
1241 } 1269 }
1242 1270
1243 spin_unlock_irqrestore(&port->port_lock, flags); 1271 spin_unlock_irqrestore(&port->port_lock, flags);
diff --git a/drivers/usb/gadget/u_serial.h b/drivers/usb/gadget/u_serial.h
index 7b561138f90e..af3910d01aea 100644
--- a/drivers/usb/gadget/u_serial.h
+++ b/drivers/usb/gadget/u_serial.h
@@ -23,8 +23,7 @@
23 * style I/O using the USB peripheral endpoints listed here, including 23 * style I/O using the USB peripheral endpoints listed here, including
24 * hookups to sysfs and /dev for each logical "tty" device. 24 * hookups to sysfs and /dev for each logical "tty" device.
25 * 25 *
26 * REVISIT need TTY --> USB event flow too, so ACM can report open/close 26 * REVISIT at least ACM could support tiocmget() if needed.
27 * as carrier detect events. Model after ECM. There's more ACM state too.
28 * 27 *
29 * REVISIT someday, allow multiplexing several TTYs over these endpoints. 28 * REVISIT someday, allow multiplexing several TTYs over these endpoints.
30 */ 29 */
@@ -41,8 +40,17 @@ struct gserial {
41 40
42 /* REVISIT avoid this CDC-ACM support harder ... */ 41 /* REVISIT avoid this CDC-ACM support harder ... */
43 struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */ 42 struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */
43
44 /* notification callbacks */
45 void (*connect)(struct gserial *p);
46 void (*disconnect)(struct gserial *p);
47 int (*send_break)(struct gserial *p, int duration);
44}; 48};
45 49
50/* utilities to allocate/free request and buffer */
51struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags);
52void gs_free_req(struct usb_ep *, struct usb_request *req);
53
46/* port setup/teardown is handled by gadget driver */ 54/* port setup/teardown is handled by gadget driver */
47int gserial_setup(struct usb_gadget *g, unsigned n_ports); 55int gserial_setup(struct usb_gadget *g, unsigned n_ports);
48void gserial_cleanup(void); 56void gserial_cleanup(void);