blob: 7299dff0515af5b36b177a180996aba40f8f04d2 [file] [log] [blame]
David Brownell4d5a73d2008-06-19 18:18:40 -07001/*
2 * f_acm.c -- USB CDC serial (ACM) function driver
3 *
4 * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com)
5 * Copyright (C) 2008 by David Brownell
6 * Copyright (C) 2008 by Nokia Corporation
Michal Nazarewiczb97503f2009-10-28 16:57:30 +01007 * Copyright (C) 2009 by Samsung Electronics
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07008 * Copyright (c) 2011 Code Aurora Forum. All rights reserved.
Michal Nazarewiczb97503f2009-10-28 16:57:30 +01009 * Author: Michal Nazarewicz (m.nazarewicz@samsung.com)
David Brownell4d5a73d2008-06-19 18:18:40 -070010 *
11 * This software is distributed under the terms of the GNU General
12 * Public License ("GPL") as published by the Free Software Foundation,
13 * either version 2 of that License or (at your option) any later version.
14 */
15
16/* #define VERBOSE_DEBUG */
17
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090018#include <linux/slab.h>
David Brownell4d5a73d2008-06-19 18:18:40 -070019#include <linux/kernel.h>
20#include <linux/device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <linux/usb/android_composite.h>
David Brownell4d5a73d2008-06-19 18:18:40 -070022
23#include "u_serial.h"
24#include "gadget_chips.h"
25
26
27/*
28 * This CDC ACM function support just wraps control functions and
29 * notifications around the generic serial-over-usb code.
30 *
31 * Because CDC ACM is standardized by the USB-IF, many host operating
32 * systems have drivers for it. Accordingly, ACM is the preferred
33 * interop solution for serial-port type connections. The control
34 * models are often not necessary, and in any case don't do much in
35 * this bare-bones implementation.
36 *
37 * Note that even MS-Windows has some support for ACM. However, that
38 * support is somewhat broken because when you use ACM in a composite
39 * device, having multiple interfaces confuses the poor OS. It doesn't
40 * seem to understand CDC Union descriptors. The new "association"
41 * descriptors (roughly equivalent to CDC Unions) may sometimes help.
42 */
43
44struct acm_ep_descs {
45 struct usb_endpoint_descriptor *in;
46 struct usb_endpoint_descriptor *out;
47 struct usb_endpoint_descriptor *notify;
48};
49
50struct f_acm {
51 struct gserial port;
52 u8 ctrl_id, data_id;
53 u8 port_num;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070054 enum transport_type transport;
David Brownell4d5a73d2008-06-19 18:18:40 -070055
David Brownell1f1ba112008-08-06 18:49:57 -070056 u8 pending;
57
58 /* lock is mostly for pending and notify_req ... they get accessed
59 * by callbacks both from tty (open/close/break) under its spinlock,
60 * and notify_req.complete() which can't use that lock.
61 */
62 spinlock_t lock;
63
David Brownell4d5a73d2008-06-19 18:18:40 -070064 struct acm_ep_descs fs;
David Brownell4d5a73d2008-06-19 18:18:40 -070065 struct acm_ep_descs hs;
66
67 struct usb_ep *notify;
68 struct usb_endpoint_descriptor *notify_desc;
David Brownell1f1ba112008-08-06 18:49:57 -070069 struct usb_request *notify_req;
David Brownell4d5a73d2008-06-19 18:18:40 -070070
71 struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */
David Brownell1f1ba112008-08-06 18:49:57 -070072
73 /* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */
David Brownell4d5a73d2008-06-19 18:18:40 -070074 u16 port_handshake_bits;
David Brownell1f1ba112008-08-06 18:49:57 -070075#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
76#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
77
78 /* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */
79 u16 serial_state;
80#define ACM_CTRL_OVERRUN (1 << 6)
81#define ACM_CTRL_PARITY (1 << 5)
82#define ACM_CTRL_FRAMING (1 << 4)
83#define ACM_CTRL_RI (1 << 3)
84#define ACM_CTRL_BRK (1 << 2)
85#define ACM_CTRL_DSR (1 << 1)
86#define ACM_CTRL_DCD (1 << 0)
David Brownell4d5a73d2008-06-19 18:18:40 -070087};
88
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070089static unsigned int no_tty_ports;
90static unsigned int no_sdio_ports;
91static unsigned int no_smd_ports;
92static unsigned int nr_ports;
93
94static struct port_info {
95 enum transport_type transport;
96 unsigned port_num;
97 unsigned client_port_num;
98} gacm_ports[GSERIAL_NO_PORTS];
99
David Brownell4d5a73d2008-06-19 18:18:40 -0700100static inline struct f_acm *func_to_acm(struct usb_function *f)
101{
102 return container_of(f, struct f_acm, port.func);
103}
104
David Brownell1f1ba112008-08-06 18:49:57 -0700105static inline struct f_acm *port_to_acm(struct gserial *p)
106{
107 return container_of(p, struct f_acm, port);
108}
109
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700110static int gport_setup(struct usb_configuration *c)
111{
112 int ret = 0;
113
114 pr_debug("%s: no_tty_ports:%u no_sdio_ports: %u nr_ports:%u\n",
115 __func__, no_tty_ports, no_sdio_ports, nr_ports);
116
117 if (no_tty_ports)
118 ret = gserial_setup(c->cdev->gadget, no_tty_ports);
119 if (no_sdio_ports)
120 ret = gsdio_setup(c->cdev->gadget, no_sdio_ports);
121 if (no_smd_ports)
122 ret = gsmd_setup(c->cdev->gadget, no_smd_ports);
123
124 return ret;
125}
126
127static int gport_connect(struct f_acm *acm)
128{
129 unsigned port_num;
130
131 port_num = gacm_ports[acm->port_num].client_port_num;
132
133
134 pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_port_no:%d\n",
Hemant Kumar1b820d52011-11-03 15:08:28 -0700135 __func__, xport_to_str(acm->transport),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136 acm, &acm->port, acm->port_num, port_num);
137
138 switch (acm->transport) {
139 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
140 gserial_connect(&acm->port, port_num);
141 break;
142 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
143 gsdio_connect(&acm->port, port_num);
144 break;
145 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
146 gsmd_connect(&acm->port, port_num);
147 break;
148 default:
149 pr_err("%s: Un-supported transport: %s\n", __func__,
Hemant Kumar1b820d52011-11-03 15:08:28 -0700150 xport_to_str(acm->transport));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700151 return -ENODEV;
152 }
153
154 return 0;
155}
156
157static int gport_disconnect(struct f_acm *acm)
158{
159 unsigned port_num;
160
161 port_num = gacm_ports[acm->port_num].client_port_num;
162
163 pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_pno:%d\n",
Hemant Kumar1b820d52011-11-03 15:08:28 -0700164 __func__, xport_to_str(acm->transport),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700165 acm, &acm->port, acm->port_num, port_num);
166
167 switch (acm->transport) {
168 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
169 gserial_disconnect(&acm->port);
170 break;
171 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
172 gsdio_disconnect(&acm->port, port_num);
173 break;
174 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
175 gsmd_disconnect(&acm->port, port_num);
176 break;
177 default:
178 pr_err("%s: Un-supported transport:%s\n", __func__,
Hemant Kumar1b820d52011-11-03 15:08:28 -0700179 xport_to_str(acm->transport));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180 return -ENODEV;
181 }
182
183 return 0;
184}
David Brownell4d5a73d2008-06-19 18:18:40 -0700185/*-------------------------------------------------------------------------*/
186
187/* notification endpoint uses smallish and infrequent fixed-size messages */
188
189#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
David Brownell1f1ba112008-08-06 18:49:57 -0700190#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
David Brownell4d5a73d2008-06-19 18:18:40 -0700191
192/* interface and class descriptors: */
193
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100194static struct usb_interface_assoc_descriptor
195acm_iad_descriptor = {
196 .bLength = sizeof acm_iad_descriptor,
197 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
198
199 /* .bFirstInterface = DYNAMIC, */
200 .bInterfaceCount = 2, // control + data
201 .bFunctionClass = USB_CLASS_COMM,
202 .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
Praveena Nadahally5c8db072010-09-10 23:05:03 +0530203 .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100204 /* .iFunction = DYNAMIC */
205};
206
207
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200208static struct usb_interface_descriptor acm_control_interface_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700209 .bLength = USB_DT_INTERFACE_SIZE,
210 .bDescriptorType = USB_DT_INTERFACE,
211 /* .bInterfaceNumber = DYNAMIC */
212 .bNumEndpoints = 1,
213 .bInterfaceClass = USB_CLASS_COMM,
214 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
215 .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
216 /* .iInterface = DYNAMIC */
217};
218
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200219static struct usb_interface_descriptor acm_data_interface_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700220 .bLength = USB_DT_INTERFACE_SIZE,
221 .bDescriptorType = USB_DT_INTERFACE,
222 /* .bInterfaceNumber = DYNAMIC */
223 .bNumEndpoints = 2,
224 .bInterfaceClass = USB_CLASS_CDC_DATA,
225 .bInterfaceSubClass = 0,
226 .bInterfaceProtocol = 0,
227 /* .iInterface = DYNAMIC */
228};
229
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200230static struct usb_cdc_header_desc acm_header_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700231 .bLength = sizeof(acm_header_desc),
232 .bDescriptorType = USB_DT_CS_INTERFACE,
233 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
Harvey Harrison551509d2009-02-11 14:11:36 -0800234 .bcdCDC = cpu_to_le16(0x0110),
David Brownell4d5a73d2008-06-19 18:18:40 -0700235};
236
237static struct usb_cdc_call_mgmt_descriptor
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200238acm_call_mgmt_descriptor = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700239 .bLength = sizeof(acm_call_mgmt_descriptor),
240 .bDescriptorType = USB_DT_CS_INTERFACE,
241 .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
242 .bmCapabilities = 0,
243 /* .bDataInterface = DYNAMIC */
244};
245
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200246static struct usb_cdc_acm_descriptor acm_descriptor = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700247 .bLength = sizeof(acm_descriptor),
248 .bDescriptorType = USB_DT_CS_INTERFACE,
249 .bDescriptorSubType = USB_CDC_ACM_TYPE,
David Brownell1f1ba112008-08-06 18:49:57 -0700250 .bmCapabilities = USB_CDC_CAP_LINE,
David Brownell4d5a73d2008-06-19 18:18:40 -0700251};
252
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200253static struct usb_cdc_union_desc acm_union_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700254 .bLength = sizeof(acm_union_desc),
255 .bDescriptorType = USB_DT_CS_INTERFACE,
256 .bDescriptorSubType = USB_CDC_UNION_TYPE,
257 /* .bMasterInterface0 = DYNAMIC */
258 /* .bSlaveInterface0 = DYNAMIC */
259};
260
261/* full speed support: */
262
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200263static struct usb_endpoint_descriptor acm_fs_notify_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700264 .bLength = USB_DT_ENDPOINT_SIZE,
265 .bDescriptorType = USB_DT_ENDPOINT,
266 .bEndpointAddress = USB_DIR_IN,
267 .bmAttributes = USB_ENDPOINT_XFER_INT,
Harvey Harrison551509d2009-02-11 14:11:36 -0800268 .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
David Brownell4d5a73d2008-06-19 18:18:40 -0700269 .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
270};
271
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200272static struct usb_endpoint_descriptor acm_fs_in_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700273 .bLength = USB_DT_ENDPOINT_SIZE,
274 .bDescriptorType = USB_DT_ENDPOINT,
275 .bEndpointAddress = USB_DIR_IN,
276 .bmAttributes = USB_ENDPOINT_XFER_BULK,
277};
278
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200279static struct usb_endpoint_descriptor acm_fs_out_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700280 .bLength = USB_DT_ENDPOINT_SIZE,
281 .bDescriptorType = USB_DT_ENDPOINT,
282 .bEndpointAddress = USB_DIR_OUT,
283 .bmAttributes = USB_ENDPOINT_XFER_BULK,
284};
285
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200286static struct usb_descriptor_header *acm_fs_function[] = {
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100287 (struct usb_descriptor_header *) &acm_iad_descriptor,
David Brownell4d5a73d2008-06-19 18:18:40 -0700288 (struct usb_descriptor_header *) &acm_control_interface_desc,
289 (struct usb_descriptor_header *) &acm_header_desc,
290 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
291 (struct usb_descriptor_header *) &acm_descriptor,
292 (struct usb_descriptor_header *) &acm_union_desc,
293 (struct usb_descriptor_header *) &acm_fs_notify_desc,
294 (struct usb_descriptor_header *) &acm_data_interface_desc,
295 (struct usb_descriptor_header *) &acm_fs_in_desc,
296 (struct usb_descriptor_header *) &acm_fs_out_desc,
297 NULL,
298};
299
300/* high speed support: */
301
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200302static struct usb_endpoint_descriptor acm_hs_notify_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700303 .bLength = USB_DT_ENDPOINT_SIZE,
304 .bDescriptorType = USB_DT_ENDPOINT,
305 .bEndpointAddress = USB_DIR_IN,
306 .bmAttributes = USB_ENDPOINT_XFER_INT,
Harvey Harrison551509d2009-02-11 14:11:36 -0800307 .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
David Brownell4d5a73d2008-06-19 18:18:40 -0700308 .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
309};
310
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200311static struct usb_endpoint_descriptor acm_hs_in_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700312 .bLength = USB_DT_ENDPOINT_SIZE,
313 .bDescriptorType = USB_DT_ENDPOINT,
314 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Harvey Harrison551509d2009-02-11 14:11:36 -0800315 .wMaxPacketSize = cpu_to_le16(512),
David Brownell4d5a73d2008-06-19 18:18:40 -0700316};
317
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200318static struct usb_endpoint_descriptor acm_hs_out_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700319 .bLength = USB_DT_ENDPOINT_SIZE,
320 .bDescriptorType = USB_DT_ENDPOINT,
321 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Harvey Harrison551509d2009-02-11 14:11:36 -0800322 .wMaxPacketSize = cpu_to_le16(512),
David Brownell4d5a73d2008-06-19 18:18:40 -0700323};
324
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200325static struct usb_descriptor_header *acm_hs_function[] = {
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100326 (struct usb_descriptor_header *) &acm_iad_descriptor,
David Brownell4d5a73d2008-06-19 18:18:40 -0700327 (struct usb_descriptor_header *) &acm_control_interface_desc,
328 (struct usb_descriptor_header *) &acm_header_desc,
329 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
330 (struct usb_descriptor_header *) &acm_descriptor,
331 (struct usb_descriptor_header *) &acm_union_desc,
332 (struct usb_descriptor_header *) &acm_hs_notify_desc,
333 (struct usb_descriptor_header *) &acm_data_interface_desc,
334 (struct usb_descriptor_header *) &acm_hs_in_desc,
335 (struct usb_descriptor_header *) &acm_hs_out_desc,
336 NULL,
337};
338
339/* string descriptors: */
340
341#define ACM_CTRL_IDX 0
342#define ACM_DATA_IDX 1
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100343#define ACM_IAD_IDX 2
David Brownell4d5a73d2008-06-19 18:18:40 -0700344
345/* static strings, in UTF-8 */
346static struct usb_string acm_string_defs[] = {
347 [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
348 [ACM_DATA_IDX].s = "CDC ACM Data",
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100349 [ACM_IAD_IDX ].s = "CDC Serial",
David Brownell4d5a73d2008-06-19 18:18:40 -0700350 { /* ZEROES END LIST */ },
351};
352
353static struct usb_gadget_strings acm_string_table = {
354 .language = 0x0409, /* en-us */
355 .strings = acm_string_defs,
356};
357
358static struct usb_gadget_strings *acm_strings[] = {
359 &acm_string_table,
360 NULL,
361};
362
363/*-------------------------------------------------------------------------*/
364
365/* ACM control ... data handling is delegated to tty library code.
366 * The main task of this function is to activate and deactivate
367 * that code based on device state; track parameters like line
368 * speed, handshake state, and so on; and issue notifications.
369 */
370
371static void acm_complete_set_line_coding(struct usb_ep *ep,
372 struct usb_request *req)
373{
374 struct f_acm *acm = ep->driver_data;
375 struct usb_composite_dev *cdev = acm->port.func.config->cdev;
376
377 if (req->status != 0) {
378 DBG(cdev, "acm ttyGS%d completion, err %d\n",
379 acm->port_num, req->status);
380 return;
381 }
382
383 /* normal completion */
384 if (req->actual != sizeof(acm->port_line_coding)) {
385 DBG(cdev, "acm ttyGS%d short resp, len %d\n",
386 acm->port_num, req->actual);
387 usb_ep_set_halt(ep);
388 } else {
389 struct usb_cdc_line_coding *value = req->buf;
390
391 /* REVISIT: we currently just remember this data.
392 * If we change that, (a) validate it first, then
393 * (b) update whatever hardware needs updating,
394 * (c) worry about locking. This is information on
395 * the order of 9600-8-N-1 ... most of which means
396 * nothing unless we control a real RS232 line.
397 */
398 acm->port_line_coding = *value;
399 }
400}
401
402static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
403{
404 struct f_acm *acm = func_to_acm(f);
405 struct usb_composite_dev *cdev = f->config->cdev;
406 struct usb_request *req = cdev->req;
407 int value = -EOPNOTSUPP;
408 u16 w_index = le16_to_cpu(ctrl->wIndex);
409 u16 w_value = le16_to_cpu(ctrl->wValue);
410 u16 w_length = le16_to_cpu(ctrl->wLength);
411
412 /* composite driver infrastructure handles everything except
413 * CDC class messages; interface activation uses set_alt().
David Brownell1f1ba112008-08-06 18:49:57 -0700414 *
415 * Note CDC spec table 4 lists the ACM request profile. It requires
416 * encapsulated command support ... we don't handle any, and respond
417 * to them by stalling. Options include get/set/clear comm features
418 * (not that useful) and SEND_BREAK.
David Brownell4d5a73d2008-06-19 18:18:40 -0700419 */
420 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
421
422 /* SET_LINE_CODING ... just read and save what the host sends */
423 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
424 | USB_CDC_REQ_SET_LINE_CODING:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425 if (w_length != sizeof(struct usb_cdc_line_coding))
David Brownell4d5a73d2008-06-19 18:18:40 -0700426 goto invalid;
427
428 value = w_length;
429 cdev->gadget->ep0->driver_data = acm;
430 req->complete = acm_complete_set_line_coding;
431 break;
432
433 /* GET_LINE_CODING ... return what host sent, or initial value */
434 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
435 | USB_CDC_REQ_GET_LINE_CODING:
David Brownell4d5a73d2008-06-19 18:18:40 -0700436
437 value = min_t(unsigned, w_length,
438 sizeof(struct usb_cdc_line_coding));
439 memcpy(req->buf, &acm->port_line_coding, value);
440 break;
441
442 /* SET_CONTROL_LINE_STATE ... save what the host sent */
443 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
444 | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
David Brownell4d5a73d2008-06-19 18:18:40 -0700445 value = 0;
446
447 /* FIXME we should not allow data to flow until the
David Brownell1f1ba112008-08-06 18:49:57 -0700448 * host sets the ACM_CTRL_DTR bit; and when it clears
David Brownell4d5a73d2008-06-19 18:18:40 -0700449 * that bit, we should return to that no-flow state.
450 */
451 acm->port_handshake_bits = w_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700452 if (acm->port.notify_modem) {
453 unsigned port_num =
454 gacm_ports[acm->port_num].client_port_num;
455
456 acm->port.notify_modem(&acm->port, port_num, w_value);
457 }
David Brownell4d5a73d2008-06-19 18:18:40 -0700458 break;
459
460 default:
461invalid:
462 VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
463 ctrl->bRequestType, ctrl->bRequest,
464 w_value, w_index, w_length);
465 }
466
467 /* respond with data transfer or status phase? */
468 if (value >= 0) {
469 DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
470 acm->port_num, ctrl->bRequestType, ctrl->bRequest,
471 w_value, w_index, w_length);
472 req->zero = 0;
473 req->length = value;
474 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
475 if (value < 0)
476 ERROR(cdev, "acm response on ttyGS%d, err %d\n",
477 acm->port_num, value);
478 }
479
480 /* device either stalls (value < 0) or reports success */
481 return value;
482}
483
484static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
485{
486 struct f_acm *acm = func_to_acm(f);
487 struct usb_composite_dev *cdev = f->config->cdev;
488
489 /* we know alt == 0, so this is an activation or a reset */
490
491 if (intf == acm->ctrl_id) {
David Brownell4d5a73d2008-06-19 18:18:40 -0700492 if (acm->notify->driver_data) {
493 VDBG(cdev, "reset acm control interface %d\n", intf);
494 usb_ep_disable(acm->notify);
495 } else {
496 VDBG(cdev, "init acm ctrl interface %d\n", intf);
David Brownell4d5a73d2008-06-19 18:18:40 -0700497 }
Mike Lockwood789ef232010-01-12 10:33:59 -0800498 acm->notify_desc = ep_choose(cdev->gadget,
499 acm->hs.notify,
500 acm->fs.notify);
David Brownell4d5a73d2008-06-19 18:18:40 -0700501 usb_ep_enable(acm->notify, acm->notify_desc);
502 acm->notify->driver_data = acm;
503
504 } else if (intf == acm->data_id) {
505 if (acm->port.in->driver_data) {
506 DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700507 gport_disconnect(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700508 } else {
509 DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
David Brownell4d5a73d2008-06-19 18:18:40 -0700510 }
Mike Lockwood789ef232010-01-12 10:33:59 -0800511 acm->port.in_desc = ep_choose(cdev->gadget,
512 acm->hs.in, acm->fs.in);
513 acm->port.out_desc = ep_choose(cdev->gadget,
514 acm->hs.out, acm->fs.out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700515 gport_connect(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700516
517 } else
518 return -EINVAL;
519
520 return 0;
521}
522
523static void acm_disable(struct usb_function *f)
524{
525 struct f_acm *acm = func_to_acm(f);
526 struct usb_composite_dev *cdev = f->config->cdev;
527
528 DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529 gport_disconnect(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700530 usb_ep_disable(acm->notify);
531 acm->notify->driver_data = NULL;
532}
533
534/*-------------------------------------------------------------------------*/
535
David Brownell1f1ba112008-08-06 18:49:57 -0700536/**
537 * acm_cdc_notify - issue CDC notification to host
538 * @acm: wraps host to be notified
539 * @type: notification type
540 * @value: Refer to cdc specs, wValue field.
541 * @data: data to be sent
542 * @length: size of data
543 * Context: irqs blocked, acm->lock held, acm_notify_req non-null
544 *
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200545 * Returns zero on success or a negative errno.
David Brownell1f1ba112008-08-06 18:49:57 -0700546 *
547 * See section 6.3.5 of the CDC 1.1 specification for information
548 * about the only notification we issue: SerialState change.
549 */
550static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
551 void *data, unsigned length)
552{
553 struct usb_ep *ep = acm->notify;
554 struct usb_request *req;
555 struct usb_cdc_notification *notify;
556 const unsigned len = sizeof(*notify) + length;
557 void *buf;
558 int status;
559
560 req = acm->notify_req;
561 acm->notify_req = NULL;
562 acm->pending = false;
563
564 req->length = len;
565 notify = req->buf;
566 buf = notify + 1;
567
568 notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
569 | USB_RECIP_INTERFACE;
570 notify->bNotificationType = type;
571 notify->wValue = cpu_to_le16(value);
572 notify->wIndex = cpu_to_le16(acm->ctrl_id);
573 notify->wLength = cpu_to_le16(length);
574 memcpy(buf, data, length);
575
David Brownelle50ae572008-11-12 11:35:13 -0800576 /* ep_queue() can complete immediately if it fills the fifo... */
577 spin_unlock(&acm->lock);
David Brownell1f1ba112008-08-06 18:49:57 -0700578 status = usb_ep_queue(ep, req, GFP_ATOMIC);
David Brownelle50ae572008-11-12 11:35:13 -0800579 spin_lock(&acm->lock);
580
David Brownell1f1ba112008-08-06 18:49:57 -0700581 if (status < 0) {
582 ERROR(acm->port.func.config->cdev,
583 "acm ttyGS%d can't notify serial state, %d\n",
584 acm->port_num, status);
585 acm->notify_req = req;
586 }
587
588 return status;
589}
590
591static int acm_notify_serial_state(struct f_acm *acm)
592{
593 struct usb_composite_dev *cdev = acm->port.func.config->cdev;
594 int status;
595
596 spin_lock(&acm->lock);
597 if (acm->notify_req) {
598 DBG(cdev, "acm ttyGS%d serial state %04x\n",
599 acm->port_num, acm->serial_state);
600 status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
601 0, &acm->serial_state, sizeof(acm->serial_state));
602 } else {
603 acm->pending = true;
604 status = 0;
605 }
606 spin_unlock(&acm->lock);
607 return status;
608}
609
610static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
611{
612 struct f_acm *acm = req->context;
613 u8 doit = false;
614
615 /* on this call path we do NOT hold the port spinlock,
616 * which is why ACM needs its own spinlock
617 */
618 spin_lock(&acm->lock);
619 if (req->status != -ESHUTDOWN)
620 doit = acm->pending;
621 acm->notify_req = req;
622 spin_unlock(&acm->lock);
623
624 if (doit)
625 acm_notify_serial_state(acm);
626}
627
628/* connect == the TTY link is open */
629
630static void acm_connect(struct gserial *port)
631{
632 struct f_acm *acm = port_to_acm(port);
633
634 acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
635 acm_notify_serial_state(acm);
636}
637
638static void acm_disconnect(struct gserial *port)
639{
640 struct f_acm *acm = port_to_acm(port);
641
642 acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
643 acm_notify_serial_state(acm);
644}
645
646static int acm_send_break(struct gserial *port, int duration)
647{
648 struct f_acm *acm = port_to_acm(port);
649 u16 state;
650
651 state = acm->serial_state;
652 state &= ~ACM_CTRL_BRK;
653 if (duration)
654 state |= ACM_CTRL_BRK;
655
656 acm->serial_state = state;
657 return acm_notify_serial_state(acm);
658}
659
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700660static int acm_send_modem_ctrl_bits(struct gserial *port, int ctrl_bits)
661{
662 struct f_acm *acm = port_to_acm(port);
663
664 acm->serial_state = ctrl_bits;
665
666 return acm_notify_serial_state(acm);
667}
668
David Brownell1f1ba112008-08-06 18:49:57 -0700669/*-------------------------------------------------------------------------*/
670
David Brownell4d5a73d2008-06-19 18:18:40 -0700671/* ACM function driver setup/binding */
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200672static int
David Brownell4d5a73d2008-06-19 18:18:40 -0700673acm_bind(struct usb_configuration *c, struct usb_function *f)
674{
675 struct usb_composite_dev *cdev = c->cdev;
676 struct f_acm *acm = func_to_acm(f);
677 int status;
678 struct usb_ep *ep;
679
680 /* allocate instance-specific interface IDs, and patch descriptors */
681 status = usb_interface_id(c, f);
682 if (status < 0)
683 goto fail;
684 acm->ctrl_id = status;
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100685 acm_iad_descriptor.bFirstInterface = status;
David Brownell4d5a73d2008-06-19 18:18:40 -0700686
687 acm_control_interface_desc.bInterfaceNumber = status;
688 acm_union_desc .bMasterInterface0 = status;
689
690 status = usb_interface_id(c, f);
691 if (status < 0)
692 goto fail;
693 acm->data_id = status;
694
695 acm_data_interface_desc.bInterfaceNumber = status;
696 acm_union_desc.bSlaveInterface0 = status;
697 acm_call_mgmt_descriptor.bDataInterface = status;
698
699 status = -ENODEV;
700
701 /* allocate instance-specific endpoints */
702 ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
703 if (!ep)
704 goto fail;
705 acm->port.in = ep;
706 ep->driver_data = cdev; /* claim */
707
708 ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
709 if (!ep)
710 goto fail;
711 acm->port.out = ep;
712 ep->driver_data = cdev; /* claim */
713
714 ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
715 if (!ep)
716 goto fail;
717 acm->notify = ep;
718 ep->driver_data = cdev; /* claim */
719
David Brownell1f1ba112008-08-06 18:49:57 -0700720 /* allocate notification */
721 acm->notify_req = gs_alloc_req(ep,
722 sizeof(struct usb_cdc_notification) + 2,
723 GFP_KERNEL);
724 if (!acm->notify_req)
725 goto fail;
726
727 acm->notify_req->complete = acm_cdc_notify_complete;
728 acm->notify_req->context = acm;
729
David Brownell4d5a73d2008-06-19 18:18:40 -0700730 /* copy descriptors, and track endpoint copies */
731 f->descriptors = usb_copy_descriptors(acm_fs_function);
David Brownell1f1ba112008-08-06 18:49:57 -0700732 if (!f->descriptors)
733 goto fail;
David Brownell4d5a73d2008-06-19 18:18:40 -0700734
735 acm->fs.in = usb_find_endpoint(acm_fs_function,
736 f->descriptors, &acm_fs_in_desc);
737 acm->fs.out = usb_find_endpoint(acm_fs_function,
738 f->descriptors, &acm_fs_out_desc);
739 acm->fs.notify = usb_find_endpoint(acm_fs_function,
740 f->descriptors, &acm_fs_notify_desc);
741
742 /* support all relevant hardware speeds... we expect that when
743 * hardware is dual speed, all bulk-capable endpoints work at
744 * both speeds
745 */
746 if (gadget_is_dualspeed(c->cdev->gadget)) {
747 acm_hs_in_desc.bEndpointAddress =
748 acm_fs_in_desc.bEndpointAddress;
749 acm_hs_out_desc.bEndpointAddress =
750 acm_fs_out_desc.bEndpointAddress;
751 acm_hs_notify_desc.bEndpointAddress =
752 acm_fs_notify_desc.bEndpointAddress;
753
754 /* copy descriptors, and track endpoint copies */
755 f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
756
757 acm->hs.in = usb_find_endpoint(acm_hs_function,
758 f->hs_descriptors, &acm_hs_in_desc);
759 acm->hs.out = usb_find_endpoint(acm_hs_function,
760 f->hs_descriptors, &acm_hs_out_desc);
761 acm->hs.notify = usb_find_endpoint(acm_hs_function,
762 f->hs_descriptors, &acm_hs_notify_desc);
763 }
764
David Brownell4d5a73d2008-06-19 18:18:40 -0700765 DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
766 acm->port_num,
767 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
768 acm->port.in->name, acm->port.out->name,
769 acm->notify->name);
770 return 0;
771
772fail:
David Brownell1f1ba112008-08-06 18:49:57 -0700773 if (acm->notify_req)
774 gs_free_req(acm->notify, acm->notify_req);
775
David Brownell4d5a73d2008-06-19 18:18:40 -0700776 /* we might as well release our claims on endpoints */
777 if (acm->notify)
778 acm->notify->driver_data = NULL;
779 if (acm->port.out)
780 acm->port.out->driver_data = NULL;
781 if (acm->port.in)
782 acm->port.in->driver_data = NULL;
783
784 ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
785
786 return status;
787}
788
789static void
790acm_unbind(struct usb_configuration *c, struct usb_function *f)
791{
David Brownell1f1ba112008-08-06 18:49:57 -0700792 struct f_acm *acm = func_to_acm(f);
793
David Brownell4d5a73d2008-06-19 18:18:40 -0700794 if (gadget_is_dualspeed(c->cdev->gadget))
795 usb_free_descriptors(f->hs_descriptors);
796 usb_free_descriptors(f->descriptors);
David Brownell1f1ba112008-08-06 18:49:57 -0700797 gs_free_req(acm->notify, acm->notify_req);
John Michelau677ba872010-11-08 18:05:37 -0600798 kfree(acm->port.func.name);
David Brownell1f1ba112008-08-06 18:49:57 -0700799 kfree(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700800}
801
802/* Some controllers can't support CDC ACM ... */
803static inline bool can_support_cdc(struct usb_configuration *c)
804{
David Brownell4d5a73d2008-06-19 18:18:40 -0700805 /* everything else is *probably* fine ... */
806 return true;
807}
808
809/**
810 * acm_bind_config - add a CDC ACM function to a configuration
811 * @c: the configuration to support the CDC ACM instance
812 * @port_num: /dev/ttyGS* port this interface will use
813 * Context: single threaded during gadget setup
814 *
815 * Returns zero on success, else negative errno.
816 *
817 * Caller must have called @gserial_setup() with enough ports to
818 * handle all the ones it binds. Caller is also responsible
819 * for calling @gserial_cleanup() before module unload.
820 */
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200821int acm_bind_config(struct usb_configuration *c, u8 port_num)
David Brownell4d5a73d2008-06-19 18:18:40 -0700822{
823 struct f_acm *acm;
824 int status;
825
826 if (!can_support_cdc(c))
827 return -EINVAL;
828
829 /* REVISIT might want instance-specific strings to help
830 * distinguish instances ...
831 */
832
833 /* maybe allocate device-global string IDs, and patch descriptors */
834 if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
835 status = usb_string_id(c->cdev);
836 if (status < 0)
837 return status;
838 acm_string_defs[ACM_CTRL_IDX].id = status;
839
840 acm_control_interface_desc.iInterface = status;
841
842 status = usb_string_id(c->cdev);
843 if (status < 0)
844 return status;
845 acm_string_defs[ACM_DATA_IDX].id = status;
846
847 acm_data_interface_desc.iInterface = status;
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100848
849 status = usb_string_id(c->cdev);
850 if (status < 0)
851 return status;
852 acm_string_defs[ACM_IAD_IDX].id = status;
853
854 acm_iad_descriptor.iFunction = status;
David Brownell4d5a73d2008-06-19 18:18:40 -0700855 }
856
857 /* allocate and initialize one new instance */
858 acm = kzalloc(sizeof *acm, GFP_KERNEL);
859 if (!acm)
860 return -ENOMEM;
861
David Brownell1f1ba112008-08-06 18:49:57 -0700862 spin_lock_init(&acm->lock);
863
David Brownell4d5a73d2008-06-19 18:18:40 -0700864 acm->port_num = port_num;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700865 acm->transport = gacm_ports[port_num].transport;
David Brownell4d5a73d2008-06-19 18:18:40 -0700866
David Brownell1f1ba112008-08-06 18:49:57 -0700867 acm->port.connect = acm_connect;
868 acm->port.disconnect = acm_disconnect;
869 acm->port.send_break = acm_send_break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 acm->port.send_modem_ctrl_bits = acm_send_modem_ctrl_bits;
David Brownell1f1ba112008-08-06 18:49:57 -0700871
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700872 acm->port.func.name = kasprintf(GFP_KERNEL, "acm%u", port_num + 1);
John Michelau677ba872010-11-08 18:05:37 -0600873 if (!acm->port.func.name) {
874 kfree(acm);
875 return -ENOMEM;
876 }
David Brownell4d5a73d2008-06-19 18:18:40 -0700877 acm->port.func.strings = acm_strings;
878 /* descriptors are per-instance copies */
879 acm->port.func.bind = acm_bind;
880 acm->port.func.unbind = acm_unbind;
881 acm->port.func.set_alt = acm_set_alt;
882 acm->port.func.setup = acm_setup;
883 acm->port.func.disable = acm_disable;
884
885 status = usb_add_function(c, &acm->port.func);
886 if (status)
887 kfree(acm);
888 return status;
889}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700890
891#ifdef CONFIG_USB_ANDROID_ACM
892#include <linux/platform_device.h>
893
894static struct acm_platform_data *acm_pdata;
895
896static int acm_probe(struct platform_device *pdev)
897{
898 acm_pdata = pdev->dev.platform_data;
899 return 0;
900}
901
902static struct platform_driver acm_platform_driver = {
903 .driver = { .name = "acm", },
904 .probe = acm_probe,
905};
906
907int acm1_function_bind_config(struct usb_configuration *c)
908{
909 int ret = acm_bind_config(c, 0);
910 if (ret == 0)
911 gport_setup(c);
912 return ret;
913}
914
915int acm2_function_bind_config(struct usb_configuration *c)
916{
917 int ret = acm_bind_config(c, 1);
918
919 return ret;
920}
921
922static struct android_usb_function acm1_function = {
923 .name = "acm1",
924 .bind_config = acm1_function_bind_config,
925};
926
927static struct android_usb_function acm2_function = {
928 .name = "acm2",
929 .bind_config = acm2_function_bind_config,
930};
931
932static int facm_remove(struct platform_device *pdev)
933{
934 gserial_cleanup();
935
936 return 0;
937}
938
939static struct platform_driver usb_facm = {
940 .remove = facm_remove,
941 .driver = {
942 .name = "usb_facm",
943 .owner = THIS_MODULE,
944 },
945};
946
947static int __init facm_probe(struct platform_device *pdev)
948{
949 struct usb_gadget_facm_pdata *pdata = pdev->dev.platform_data;
950 int i;
951
952 dev_dbg(&pdev->dev, "%s: probe\n", __func__);
953
954 if (!pdata)
955 goto probe_android_register;
956
957 for (i = 0; i < GSERIAL_NO_PORTS; i++) {
958 gacm_ports[i].transport = pdata->transport[i];
959 gacm_ports[i].port_num = i;
960
961 switch (gacm_ports[i].transport) {
962 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
963 gacm_ports[i].client_port_num = no_tty_ports;
964 no_tty_ports++;
965 break;
966 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
967 gacm_ports[i].client_port_num = no_sdio_ports;
968 no_sdio_ports++;
969 break;
970 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
971 gacm_ports[i].client_port_num = no_smd_ports;
972 no_smd_ports++;
973 break;
974 default:
975 pr_err("%s: Un-supported transport transport: %u\n",
976 __func__, gacm_ports[i].transport);
977 return -ENODEV;
978 }
979
980 nr_ports++;
981 }
982
983 pr_info("%s:gport:tty_ports:%u sdio_ports:%u "
984 "smd_ports:%u nr_ports:%u\n",
985 __func__, no_tty_ports, no_sdio_ports,
986 no_smd_ports, nr_ports);
987
988probe_android_register:
989 android_register_function(&acm1_function);
990 android_register_function(&acm2_function);
991
992 return 0;
993}
994
995static int __init init(void)
996{
997 printk(KERN_INFO "f_acm init\n");
998
999 return platform_driver_probe(&usb_facm, facm_probe);
1000}
1001module_init(init);
1002
1003#endif /* CONFIG_USB_ANDROID_ACM */