aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/f_acm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/gadget/f_acm.c')
-rw-r--r--drivers/usb/gadget/f_acm.c196
1 files changed, 183 insertions, 13 deletions
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index d8faccf27895..5ee1590b8e9c 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -47,18 +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 struct usb_descriptor_header **fs_function; 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
51 struct acm_ep_descs fs; 58 struct acm_ep_descs fs;
52 struct usb_descriptor_header **hs_function;
53 struct acm_ep_descs hs; 59 struct acm_ep_descs hs;
54 60
55 struct usb_ep *notify; 61 struct usb_ep *notify;
56 struct usb_endpoint_descriptor *notify_desc; 62 struct usb_endpoint_descriptor *notify_desc;
63 struct usb_request *notify_req;
57 64
58 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) */
59 u16 port_handshake_bits; 68 u16 port_handshake_bits;
60#define RS232_RTS (1 << 1) /* unused with full duplex */ 69#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
61#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)
62}; 81};
63 82
64static inline struct f_acm *func_to_acm(struct usb_function *f) 83static inline struct f_acm *func_to_acm(struct usb_function *f)
@@ -66,12 +85,17 @@ static inline struct f_acm *func_to_acm(struct usb_function *f)
66 return container_of(f, struct f_acm, port.func); 85 return container_of(f, struct f_acm, port.func);
67} 86}
68 87
88static inline struct f_acm *port_to_acm(struct gserial *p)
89{
90 return container_of(p, struct f_acm, port);
91}
92
69/*-------------------------------------------------------------------------*/ 93/*-------------------------------------------------------------------------*/
70 94
71/* notification endpoint uses smallish and infrequent fixed-size messages */ 95/* notification endpoint uses smallish and infrequent fixed-size messages */
72 96
73#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ 97#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
74#define GS_NOTIFY_MAXPACKET 8 98#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
75 99
76/* interface and class descriptors: */ 100/* interface and class descriptors: */
77 101
@@ -117,7 +141,7 @@ static struct usb_cdc_acm_descriptor acm_descriptor __initdata = {
117 .bLength = sizeof(acm_descriptor), 141 .bLength = sizeof(acm_descriptor),
118 .bDescriptorType = USB_DT_CS_INTERFACE, 142 .bDescriptorType = USB_DT_CS_INTERFACE,
119 .bDescriptorSubType = USB_CDC_ACM_TYPE, 143 .bDescriptorSubType = USB_CDC_ACM_TYPE,
120 .bmCapabilities = (1 << 1), 144 .bmCapabilities = USB_CDC_CAP_LINE,
121}; 145};
122 146
123static struct usb_cdc_union_desc acm_union_desc __initdata = { 147static struct usb_cdc_union_desc acm_union_desc __initdata = {
@@ -277,6 +301,11 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
277 301
278 /* composite driver infrastructure handles everything except 302 /* composite driver infrastructure handles everything except
279 * 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.
280 */ 309 */
281 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { 310 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
282 311
@@ -312,7 +341,7 @@ static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
312 value = 0; 341 value = 0;
313 342
314 /* FIXME we should not allow data to flow until the 343 /* FIXME we should not allow data to flow until the
315 * host sets the RS232_DTR bit; and when it clears 344 * host sets the ACM_CTRL_DTR bit; and when it clears
316 * that bit, we should return to that no-flow state. 345 * that bit, we should return to that no-flow state.
317 */ 346 */
318 acm->port_handshake_bits = w_value; 347 acm->port_handshake_bits = w_value;
@@ -350,9 +379,6 @@ static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
350 /* 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 */
351 380
352 if (intf == acm->ctrl_id) { 381 if (intf == acm->ctrl_id) {
353 /* REVISIT this may need more work when we start to
354 * send notifications ...
355 */
356 if (acm->notify->driver_data) { 382 if (acm->notify->driver_data) {
357 VDBG(cdev, "reset acm control interface %d\n", intf); 383 VDBG(cdev, "reset acm control interface %d\n", intf);
358 usb_ep_disable(acm->notify); 384 usb_ep_disable(acm->notify);
@@ -397,6 +423,128 @@ static void acm_disable(struct usb_function *f)
397 423
398/*-------------------------------------------------------------------------*/ 424/*-------------------------------------------------------------------------*/
399 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
400/* ACM function driver setup/binding */ 548/* ACM function driver setup/binding */
401static int __init 549static int __init
402acm_bind(struct usb_configuration *c, struct usb_function *f) 550acm_bind(struct usb_configuration *c, struct usb_function *f)
@@ -445,8 +593,20 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
445 acm->notify = ep; 593 acm->notify = ep;
446 ep->driver_data = cdev; /* claim */ 594 ep->driver_data = cdev; /* claim */
447 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
448 /* copy descriptors, and track endpoint copies */ 606 /* copy descriptors, and track endpoint copies */
449 f->descriptors = usb_copy_descriptors(acm_fs_function); 607 f->descriptors = usb_copy_descriptors(acm_fs_function);
608 if (!f->descriptors)
609 goto fail;
450 610
451 acm->fs.in = usb_find_endpoint(acm_fs_function, 611 acm->fs.in = usb_find_endpoint(acm_fs_function,
452 f->descriptors, &acm_fs_in_desc); 612 f->descriptors, &acm_fs_in_desc);
@@ -478,8 +638,6 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
478 f->hs_descriptors, &acm_hs_notify_desc); 638 f->hs_descriptors, &acm_hs_notify_desc);
479 } 639 }
480 640
481 /* FIXME provide a callback for triggering notifications */
482
483 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",
484 acm->port_num, 642 acm->port_num,
485 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 643 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
@@ -488,6 +646,9 @@ acm_bind(struct usb_configuration *c, struct usb_function *f)
488 return 0; 646 return 0;
489 647
490fail: 648fail:
649 if (acm->notify_req)
650 gs_free_req(acm->notify, acm->notify_req);
651
491 /* we might as well release our claims on endpoints */ 652 /* we might as well release our claims on endpoints */
492 if (acm->notify) 653 if (acm->notify)
493 acm->notify->driver_data = NULL; 654 acm->notify->driver_data = NULL;
@@ -504,10 +665,13 @@ fail:
504static void 665static void
505acm_unbind(struct usb_configuration *c, struct usb_function *f) 666acm_unbind(struct usb_configuration *c, struct usb_function *f)
506{ 667{
668 struct f_acm *acm = func_to_acm(f);
669
507 if (gadget_is_dualspeed(c->cdev->gadget)) 670 if (gadget_is_dualspeed(c->cdev->gadget))
508 usb_free_descriptors(f->hs_descriptors); 671 usb_free_descriptors(f->hs_descriptors);
509 usb_free_descriptors(f->descriptors); 672 usb_free_descriptors(f->descriptors);
510 kfree(func_to_acm(f)); 673 gs_free_req(acm->notify, acm->notify_req);
674 kfree(acm);
511} 675}
512 676
513/* Some controllers can't support CDC ACM ... */ 677/* Some controllers can't support CDC ACM ... */
@@ -571,8 +735,14 @@ int __init acm_bind_config(struct usb_configuration *c, u8 port_num)
571 if (!acm) 735 if (!acm)
572 return -ENOMEM; 736 return -ENOMEM;
573 737
738 spin_lock_init(&acm->lock);
739
574 acm->port_num = port_num; 740 acm->port_num = port_num;
575 741
742 acm->port.connect = acm_connect;
743 acm->port.disconnect = acm_disconnect;
744 acm->port.send_break = acm_send_break;
745
576 acm->port.func.name = "acm"; 746 acm->port.func.name = "acm";
577 acm->port.func.strings = acm_strings; 747 acm->port.func.strings = acm_strings;
578 /* descriptors are per-instance copies */ 748 /* descriptors are per-instance copies */