blob: 3fd12b1fe53b6f7bb7941878297271f011921107 [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 char *transport_to_str(enum transport_type t)
111{
112 switch (t) {
113 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
114 return "TTY";
115 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
116 return "SDIO";
117 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
118 return "SMD";
119 }
120
121 return "NONE";
122}
123
124static int gport_setup(struct usb_configuration *c)
125{
126 int ret = 0;
127
128 pr_debug("%s: no_tty_ports:%u no_sdio_ports: %u nr_ports:%u\n",
129 __func__, no_tty_ports, no_sdio_ports, nr_ports);
130
131 if (no_tty_ports)
132 ret = gserial_setup(c->cdev->gadget, no_tty_ports);
133 if (no_sdio_ports)
134 ret = gsdio_setup(c->cdev->gadget, no_sdio_ports);
135 if (no_smd_ports)
136 ret = gsmd_setup(c->cdev->gadget, no_smd_ports);
137
138 return ret;
139}
140
141static int gport_connect(struct f_acm *acm)
142{
143 unsigned port_num;
144
145 port_num = gacm_ports[acm->port_num].client_port_num;
146
147
148 pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_port_no:%d\n",
149 __func__, transport_to_str(acm->transport),
150 acm, &acm->port, acm->port_num, port_num);
151
152 switch (acm->transport) {
153 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
154 gserial_connect(&acm->port, port_num);
155 break;
156 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
157 gsdio_connect(&acm->port, port_num);
158 break;
159 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
160 gsmd_connect(&acm->port, port_num);
161 break;
162 default:
163 pr_err("%s: Un-supported transport: %s\n", __func__,
164 transport_to_str(acm->transport));
165 return -ENODEV;
166 }
167
168 return 0;
169}
170
171static int gport_disconnect(struct f_acm *acm)
172{
173 unsigned port_num;
174
175 port_num = gacm_ports[acm->port_num].client_port_num;
176
177 pr_debug("%s: transport:%s f_acm:%p gserial:%p port_num:%d cl_pno:%d\n",
178 __func__, transport_to_str(acm->transport),
179 acm, &acm->port, acm->port_num, port_num);
180
181 switch (acm->transport) {
182 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
183 gserial_disconnect(&acm->port);
184 break;
185 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
186 gsdio_disconnect(&acm->port, port_num);
187 break;
188 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
189 gsmd_disconnect(&acm->port, port_num);
190 break;
191 default:
192 pr_err("%s: Un-supported transport:%s\n", __func__,
193 transport_to_str(acm->transport));
194 return -ENODEV;
195 }
196
197 return 0;
198}
David Brownell4d5a73d2008-06-19 18:18:40 -0700199/*-------------------------------------------------------------------------*/
200
201/* notification endpoint uses smallish and infrequent fixed-size messages */
202
203#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
David Brownell1f1ba112008-08-06 18:49:57 -0700204#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
David Brownell4d5a73d2008-06-19 18:18:40 -0700205
206/* interface and class descriptors: */
207
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100208static struct usb_interface_assoc_descriptor
209acm_iad_descriptor = {
210 .bLength = sizeof acm_iad_descriptor,
211 .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
212
213 /* .bFirstInterface = DYNAMIC, */
214 .bInterfaceCount = 2, // control + data
215 .bFunctionClass = USB_CLASS_COMM,
216 .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
Praveena Nadahally5c8db072010-09-10 23:05:03 +0530217 .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100218 /* .iFunction = DYNAMIC */
219};
220
221
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200222static struct usb_interface_descriptor acm_control_interface_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700223 .bLength = USB_DT_INTERFACE_SIZE,
224 .bDescriptorType = USB_DT_INTERFACE,
225 /* .bInterfaceNumber = DYNAMIC */
226 .bNumEndpoints = 1,
227 .bInterfaceClass = USB_CLASS_COMM,
228 .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
229 .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
230 /* .iInterface = DYNAMIC */
231};
232
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200233static struct usb_interface_descriptor acm_data_interface_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700234 .bLength = USB_DT_INTERFACE_SIZE,
235 .bDescriptorType = USB_DT_INTERFACE,
236 /* .bInterfaceNumber = DYNAMIC */
237 .bNumEndpoints = 2,
238 .bInterfaceClass = USB_CLASS_CDC_DATA,
239 .bInterfaceSubClass = 0,
240 .bInterfaceProtocol = 0,
241 /* .iInterface = DYNAMIC */
242};
243
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200244static struct usb_cdc_header_desc acm_header_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700245 .bLength = sizeof(acm_header_desc),
246 .bDescriptorType = USB_DT_CS_INTERFACE,
247 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
Harvey Harrison551509d2009-02-11 14:11:36 -0800248 .bcdCDC = cpu_to_le16(0x0110),
David Brownell4d5a73d2008-06-19 18:18:40 -0700249};
250
251static struct usb_cdc_call_mgmt_descriptor
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200252acm_call_mgmt_descriptor = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700253 .bLength = sizeof(acm_call_mgmt_descriptor),
254 .bDescriptorType = USB_DT_CS_INTERFACE,
255 .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
256 .bmCapabilities = 0,
257 /* .bDataInterface = DYNAMIC */
258};
259
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200260static struct usb_cdc_acm_descriptor acm_descriptor = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700261 .bLength = sizeof(acm_descriptor),
262 .bDescriptorType = USB_DT_CS_INTERFACE,
263 .bDescriptorSubType = USB_CDC_ACM_TYPE,
David Brownell1f1ba112008-08-06 18:49:57 -0700264 .bmCapabilities = USB_CDC_CAP_LINE,
David Brownell4d5a73d2008-06-19 18:18:40 -0700265};
266
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200267static struct usb_cdc_union_desc acm_union_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700268 .bLength = sizeof(acm_union_desc),
269 .bDescriptorType = USB_DT_CS_INTERFACE,
270 .bDescriptorSubType = USB_CDC_UNION_TYPE,
271 /* .bMasterInterface0 = DYNAMIC */
272 /* .bSlaveInterface0 = DYNAMIC */
273};
274
275/* full speed support: */
276
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200277static struct usb_endpoint_descriptor acm_fs_notify_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700278 .bLength = USB_DT_ENDPOINT_SIZE,
279 .bDescriptorType = USB_DT_ENDPOINT,
280 .bEndpointAddress = USB_DIR_IN,
281 .bmAttributes = USB_ENDPOINT_XFER_INT,
Harvey Harrison551509d2009-02-11 14:11:36 -0800282 .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
David Brownell4d5a73d2008-06-19 18:18:40 -0700283 .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
284};
285
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200286static struct usb_endpoint_descriptor acm_fs_in_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700287 .bLength = USB_DT_ENDPOINT_SIZE,
288 .bDescriptorType = USB_DT_ENDPOINT,
289 .bEndpointAddress = USB_DIR_IN,
290 .bmAttributes = USB_ENDPOINT_XFER_BULK,
291};
292
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200293static struct usb_endpoint_descriptor acm_fs_out_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700294 .bLength = USB_DT_ENDPOINT_SIZE,
295 .bDescriptorType = USB_DT_ENDPOINT,
296 .bEndpointAddress = USB_DIR_OUT,
297 .bmAttributes = USB_ENDPOINT_XFER_BULK,
298};
299
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200300static struct usb_descriptor_header *acm_fs_function[] = {
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100301 (struct usb_descriptor_header *) &acm_iad_descriptor,
David Brownell4d5a73d2008-06-19 18:18:40 -0700302 (struct usb_descriptor_header *) &acm_control_interface_desc,
303 (struct usb_descriptor_header *) &acm_header_desc,
304 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
305 (struct usb_descriptor_header *) &acm_descriptor,
306 (struct usb_descriptor_header *) &acm_union_desc,
307 (struct usb_descriptor_header *) &acm_fs_notify_desc,
308 (struct usb_descriptor_header *) &acm_data_interface_desc,
309 (struct usb_descriptor_header *) &acm_fs_in_desc,
310 (struct usb_descriptor_header *) &acm_fs_out_desc,
311 NULL,
312};
313
314/* high speed support: */
315
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200316static struct usb_endpoint_descriptor acm_hs_notify_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700317 .bLength = USB_DT_ENDPOINT_SIZE,
318 .bDescriptorType = USB_DT_ENDPOINT,
319 .bEndpointAddress = USB_DIR_IN,
320 .bmAttributes = USB_ENDPOINT_XFER_INT,
Harvey Harrison551509d2009-02-11 14:11:36 -0800321 .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET),
David Brownell4d5a73d2008-06-19 18:18:40 -0700322 .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
323};
324
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200325static struct usb_endpoint_descriptor acm_hs_in_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700326 .bLength = USB_DT_ENDPOINT_SIZE,
327 .bDescriptorType = USB_DT_ENDPOINT,
328 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Harvey Harrison551509d2009-02-11 14:11:36 -0800329 .wMaxPacketSize = cpu_to_le16(512),
David Brownell4d5a73d2008-06-19 18:18:40 -0700330};
331
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200332static struct usb_endpoint_descriptor acm_hs_out_desc = {
David Brownell4d5a73d2008-06-19 18:18:40 -0700333 .bLength = USB_DT_ENDPOINT_SIZE,
334 .bDescriptorType = USB_DT_ENDPOINT,
335 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Harvey Harrison551509d2009-02-11 14:11:36 -0800336 .wMaxPacketSize = cpu_to_le16(512),
David Brownell4d5a73d2008-06-19 18:18:40 -0700337};
338
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200339static struct usb_descriptor_header *acm_hs_function[] = {
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100340 (struct usb_descriptor_header *) &acm_iad_descriptor,
David Brownell4d5a73d2008-06-19 18:18:40 -0700341 (struct usb_descriptor_header *) &acm_control_interface_desc,
342 (struct usb_descriptor_header *) &acm_header_desc,
343 (struct usb_descriptor_header *) &acm_call_mgmt_descriptor,
344 (struct usb_descriptor_header *) &acm_descriptor,
345 (struct usb_descriptor_header *) &acm_union_desc,
346 (struct usb_descriptor_header *) &acm_hs_notify_desc,
347 (struct usb_descriptor_header *) &acm_data_interface_desc,
348 (struct usb_descriptor_header *) &acm_hs_in_desc,
349 (struct usb_descriptor_header *) &acm_hs_out_desc,
350 NULL,
351};
352
353/* string descriptors: */
354
355#define ACM_CTRL_IDX 0
356#define ACM_DATA_IDX 1
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100357#define ACM_IAD_IDX 2
David Brownell4d5a73d2008-06-19 18:18:40 -0700358
359/* static strings, in UTF-8 */
360static struct usb_string acm_string_defs[] = {
361 [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)",
362 [ACM_DATA_IDX].s = "CDC ACM Data",
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100363 [ACM_IAD_IDX ].s = "CDC Serial",
David Brownell4d5a73d2008-06-19 18:18:40 -0700364 { /* ZEROES END LIST */ },
365};
366
367static struct usb_gadget_strings acm_string_table = {
368 .language = 0x0409, /* en-us */
369 .strings = acm_string_defs,
370};
371
372static struct usb_gadget_strings *acm_strings[] = {
373 &acm_string_table,
374 NULL,
375};
376
377/*-------------------------------------------------------------------------*/
378
379/* ACM control ... data handling is delegated to tty library code.
380 * The main task of this function is to activate and deactivate
381 * that code based on device state; track parameters like line
382 * speed, handshake state, and so on; and issue notifications.
383 */
384
385static void acm_complete_set_line_coding(struct usb_ep *ep,
386 struct usb_request *req)
387{
388 struct f_acm *acm = ep->driver_data;
389 struct usb_composite_dev *cdev = acm->port.func.config->cdev;
390
391 if (req->status != 0) {
392 DBG(cdev, "acm ttyGS%d completion, err %d\n",
393 acm->port_num, req->status);
394 return;
395 }
396
397 /* normal completion */
398 if (req->actual != sizeof(acm->port_line_coding)) {
399 DBG(cdev, "acm ttyGS%d short resp, len %d\n",
400 acm->port_num, req->actual);
401 usb_ep_set_halt(ep);
402 } else {
403 struct usb_cdc_line_coding *value = req->buf;
404
405 /* REVISIT: we currently just remember this data.
406 * If we change that, (a) validate it first, then
407 * (b) update whatever hardware needs updating,
408 * (c) worry about locking. This is information on
409 * the order of 9600-8-N-1 ... most of which means
410 * nothing unless we control a real RS232 line.
411 */
412 acm->port_line_coding = *value;
413 }
414}
415
416static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
417{
418 struct f_acm *acm = func_to_acm(f);
419 struct usb_composite_dev *cdev = f->config->cdev;
420 struct usb_request *req = cdev->req;
421 int value = -EOPNOTSUPP;
422 u16 w_index = le16_to_cpu(ctrl->wIndex);
423 u16 w_value = le16_to_cpu(ctrl->wValue);
424 u16 w_length = le16_to_cpu(ctrl->wLength);
425
426 /* composite driver infrastructure handles everything except
427 * CDC class messages; interface activation uses set_alt().
David Brownell1f1ba112008-08-06 18:49:57 -0700428 *
429 * Note CDC spec table 4 lists the ACM request profile. It requires
430 * encapsulated command support ... we don't handle any, and respond
431 * to them by stalling. Options include get/set/clear comm features
432 * (not that useful) and SEND_BREAK.
David Brownell4d5a73d2008-06-19 18:18:40 -0700433 */
434 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
435
436 /* SET_LINE_CODING ... just read and save what the host sends */
437 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
438 | USB_CDC_REQ_SET_LINE_CODING:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700439 if (w_length != sizeof(struct usb_cdc_line_coding))
David Brownell4d5a73d2008-06-19 18:18:40 -0700440 goto invalid;
441
442 value = w_length;
443 cdev->gadget->ep0->driver_data = acm;
444 req->complete = acm_complete_set_line_coding;
445 break;
446
447 /* GET_LINE_CODING ... return what host sent, or initial value */
448 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
449 | USB_CDC_REQ_GET_LINE_CODING:
David Brownell4d5a73d2008-06-19 18:18:40 -0700450
451 value = min_t(unsigned, w_length,
452 sizeof(struct usb_cdc_line_coding));
453 memcpy(req->buf, &acm->port_line_coding, value);
454 break;
455
456 /* SET_CONTROL_LINE_STATE ... save what the host sent */
457 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
458 | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
David Brownell4d5a73d2008-06-19 18:18:40 -0700459 value = 0;
460
461 /* FIXME we should not allow data to flow until the
David Brownell1f1ba112008-08-06 18:49:57 -0700462 * host sets the ACM_CTRL_DTR bit; and when it clears
David Brownell4d5a73d2008-06-19 18:18:40 -0700463 * that bit, we should return to that no-flow state.
464 */
465 acm->port_handshake_bits = w_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700466 if (acm->port.notify_modem) {
467 unsigned port_num =
468 gacm_ports[acm->port_num].client_port_num;
469
470 acm->port.notify_modem(&acm->port, port_num, w_value);
471 }
David Brownell4d5a73d2008-06-19 18:18:40 -0700472 break;
473
474 default:
475invalid:
476 VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
477 ctrl->bRequestType, ctrl->bRequest,
478 w_value, w_index, w_length);
479 }
480
481 /* respond with data transfer or status phase? */
482 if (value >= 0) {
483 DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
484 acm->port_num, ctrl->bRequestType, ctrl->bRequest,
485 w_value, w_index, w_length);
486 req->zero = 0;
487 req->length = value;
488 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
489 if (value < 0)
490 ERROR(cdev, "acm response on ttyGS%d, err %d\n",
491 acm->port_num, value);
492 }
493
494 /* device either stalls (value < 0) or reports success */
495 return value;
496}
497
498static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
499{
500 struct f_acm *acm = func_to_acm(f);
501 struct usb_composite_dev *cdev = f->config->cdev;
502
503 /* we know alt == 0, so this is an activation or a reset */
504
505 if (intf == acm->ctrl_id) {
David Brownell4d5a73d2008-06-19 18:18:40 -0700506 if (acm->notify->driver_data) {
507 VDBG(cdev, "reset acm control interface %d\n", intf);
508 usb_ep_disable(acm->notify);
509 } else {
510 VDBG(cdev, "init acm ctrl interface %d\n", intf);
David Brownell4d5a73d2008-06-19 18:18:40 -0700511 }
Mike Lockwood789ef232010-01-12 10:33:59 -0800512 acm->notify_desc = ep_choose(cdev->gadget,
513 acm->hs.notify,
514 acm->fs.notify);
David Brownell4d5a73d2008-06-19 18:18:40 -0700515 usb_ep_enable(acm->notify, acm->notify_desc);
516 acm->notify->driver_data = acm;
517
518 } else if (intf == acm->data_id) {
519 if (acm->port.in->driver_data) {
520 DBG(cdev, "reset acm ttyGS%d\n", acm->port_num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700521 gport_disconnect(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700522 } else {
523 DBG(cdev, "activate acm ttyGS%d\n", acm->port_num);
David Brownell4d5a73d2008-06-19 18:18:40 -0700524 }
Mike Lockwood789ef232010-01-12 10:33:59 -0800525 acm->port.in_desc = ep_choose(cdev->gadget,
526 acm->hs.in, acm->fs.in);
527 acm->port.out_desc = ep_choose(cdev->gadget,
528 acm->hs.out, acm->fs.out);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700529 gport_connect(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700530
531 } else
532 return -EINVAL;
533
534 return 0;
535}
536
537static void acm_disable(struct usb_function *f)
538{
539 struct f_acm *acm = func_to_acm(f);
540 struct usb_composite_dev *cdev = f->config->cdev;
541
542 DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700543 gport_disconnect(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700544 usb_ep_disable(acm->notify);
545 acm->notify->driver_data = NULL;
546}
547
548/*-------------------------------------------------------------------------*/
549
David Brownell1f1ba112008-08-06 18:49:57 -0700550/**
551 * acm_cdc_notify - issue CDC notification to host
552 * @acm: wraps host to be notified
553 * @type: notification type
554 * @value: Refer to cdc specs, wValue field.
555 * @data: data to be sent
556 * @length: size of data
557 * Context: irqs blocked, acm->lock held, acm_notify_req non-null
558 *
André Goddard Rosaaf901ca2009-11-14 13:09:05 -0200559 * Returns zero on success or a negative errno.
David Brownell1f1ba112008-08-06 18:49:57 -0700560 *
561 * See section 6.3.5 of the CDC 1.1 specification for information
562 * about the only notification we issue: SerialState change.
563 */
564static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value,
565 void *data, unsigned length)
566{
567 struct usb_ep *ep = acm->notify;
568 struct usb_request *req;
569 struct usb_cdc_notification *notify;
570 const unsigned len = sizeof(*notify) + length;
571 void *buf;
572 int status;
573
574 req = acm->notify_req;
575 acm->notify_req = NULL;
576 acm->pending = false;
577
578 req->length = len;
579 notify = req->buf;
580 buf = notify + 1;
581
582 notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
583 | USB_RECIP_INTERFACE;
584 notify->bNotificationType = type;
585 notify->wValue = cpu_to_le16(value);
586 notify->wIndex = cpu_to_le16(acm->ctrl_id);
587 notify->wLength = cpu_to_le16(length);
588 memcpy(buf, data, length);
589
David Brownelle50ae572008-11-12 11:35:13 -0800590 /* ep_queue() can complete immediately if it fills the fifo... */
591 spin_unlock(&acm->lock);
David Brownell1f1ba112008-08-06 18:49:57 -0700592 status = usb_ep_queue(ep, req, GFP_ATOMIC);
David Brownelle50ae572008-11-12 11:35:13 -0800593 spin_lock(&acm->lock);
594
David Brownell1f1ba112008-08-06 18:49:57 -0700595 if (status < 0) {
596 ERROR(acm->port.func.config->cdev,
597 "acm ttyGS%d can't notify serial state, %d\n",
598 acm->port_num, status);
599 acm->notify_req = req;
600 }
601
602 return status;
603}
604
605static int acm_notify_serial_state(struct f_acm *acm)
606{
607 struct usb_composite_dev *cdev = acm->port.func.config->cdev;
608 int status;
609
610 spin_lock(&acm->lock);
611 if (acm->notify_req) {
612 DBG(cdev, "acm ttyGS%d serial state %04x\n",
613 acm->port_num, acm->serial_state);
614 status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
615 0, &acm->serial_state, sizeof(acm->serial_state));
616 } else {
617 acm->pending = true;
618 status = 0;
619 }
620 spin_unlock(&acm->lock);
621 return status;
622}
623
624static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req)
625{
626 struct f_acm *acm = req->context;
627 u8 doit = false;
628
629 /* on this call path we do NOT hold the port spinlock,
630 * which is why ACM needs its own spinlock
631 */
632 spin_lock(&acm->lock);
633 if (req->status != -ESHUTDOWN)
634 doit = acm->pending;
635 acm->notify_req = req;
636 spin_unlock(&acm->lock);
637
638 if (doit)
639 acm_notify_serial_state(acm);
640}
641
642/* connect == the TTY link is open */
643
644static void acm_connect(struct gserial *port)
645{
646 struct f_acm *acm = port_to_acm(port);
647
648 acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
649 acm_notify_serial_state(acm);
650}
651
652static void acm_disconnect(struct gserial *port)
653{
654 struct f_acm *acm = port_to_acm(port);
655
656 acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
657 acm_notify_serial_state(acm);
658}
659
660static int acm_send_break(struct gserial *port, int duration)
661{
662 struct f_acm *acm = port_to_acm(port);
663 u16 state;
664
665 state = acm->serial_state;
666 state &= ~ACM_CTRL_BRK;
667 if (duration)
668 state |= ACM_CTRL_BRK;
669
670 acm->serial_state = state;
671 return acm_notify_serial_state(acm);
672}
673
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700674static int acm_send_modem_ctrl_bits(struct gserial *port, int ctrl_bits)
675{
676 struct f_acm *acm = port_to_acm(port);
677
678 acm->serial_state = ctrl_bits;
679
680 return acm_notify_serial_state(acm);
681}
682
David Brownell1f1ba112008-08-06 18:49:57 -0700683/*-------------------------------------------------------------------------*/
684
David Brownell4d5a73d2008-06-19 18:18:40 -0700685/* ACM function driver setup/binding */
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200686static int
David Brownell4d5a73d2008-06-19 18:18:40 -0700687acm_bind(struct usb_configuration *c, struct usb_function *f)
688{
689 struct usb_composite_dev *cdev = c->cdev;
690 struct f_acm *acm = func_to_acm(f);
691 int status;
692 struct usb_ep *ep;
693
694 /* allocate instance-specific interface IDs, and patch descriptors */
695 status = usb_interface_id(c, f);
696 if (status < 0)
697 goto fail;
698 acm->ctrl_id = status;
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100699 acm_iad_descriptor.bFirstInterface = status;
David Brownell4d5a73d2008-06-19 18:18:40 -0700700
701 acm_control_interface_desc.bInterfaceNumber = status;
702 acm_union_desc .bMasterInterface0 = status;
703
704 status = usb_interface_id(c, f);
705 if (status < 0)
706 goto fail;
707 acm->data_id = status;
708
709 acm_data_interface_desc.bInterfaceNumber = status;
710 acm_union_desc.bSlaveInterface0 = status;
711 acm_call_mgmt_descriptor.bDataInterface = status;
712
713 status = -ENODEV;
714
715 /* allocate instance-specific endpoints */
716 ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc);
717 if (!ep)
718 goto fail;
719 acm->port.in = ep;
720 ep->driver_data = cdev; /* claim */
721
722 ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc);
723 if (!ep)
724 goto fail;
725 acm->port.out = ep;
726 ep->driver_data = cdev; /* claim */
727
728 ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc);
729 if (!ep)
730 goto fail;
731 acm->notify = ep;
732 ep->driver_data = cdev; /* claim */
733
David Brownell1f1ba112008-08-06 18:49:57 -0700734 /* allocate notification */
735 acm->notify_req = gs_alloc_req(ep,
736 sizeof(struct usb_cdc_notification) + 2,
737 GFP_KERNEL);
738 if (!acm->notify_req)
739 goto fail;
740
741 acm->notify_req->complete = acm_cdc_notify_complete;
742 acm->notify_req->context = acm;
743
David Brownell4d5a73d2008-06-19 18:18:40 -0700744 /* copy descriptors, and track endpoint copies */
745 f->descriptors = usb_copy_descriptors(acm_fs_function);
David Brownell1f1ba112008-08-06 18:49:57 -0700746 if (!f->descriptors)
747 goto fail;
David Brownell4d5a73d2008-06-19 18:18:40 -0700748
749 acm->fs.in = usb_find_endpoint(acm_fs_function,
750 f->descriptors, &acm_fs_in_desc);
751 acm->fs.out = usb_find_endpoint(acm_fs_function,
752 f->descriptors, &acm_fs_out_desc);
753 acm->fs.notify = usb_find_endpoint(acm_fs_function,
754 f->descriptors, &acm_fs_notify_desc);
755
756 /* support all relevant hardware speeds... we expect that when
757 * hardware is dual speed, all bulk-capable endpoints work at
758 * both speeds
759 */
760 if (gadget_is_dualspeed(c->cdev->gadget)) {
761 acm_hs_in_desc.bEndpointAddress =
762 acm_fs_in_desc.bEndpointAddress;
763 acm_hs_out_desc.bEndpointAddress =
764 acm_fs_out_desc.bEndpointAddress;
765 acm_hs_notify_desc.bEndpointAddress =
766 acm_fs_notify_desc.bEndpointAddress;
767
768 /* copy descriptors, and track endpoint copies */
769 f->hs_descriptors = usb_copy_descriptors(acm_hs_function);
770
771 acm->hs.in = usb_find_endpoint(acm_hs_function,
772 f->hs_descriptors, &acm_hs_in_desc);
773 acm->hs.out = usb_find_endpoint(acm_hs_function,
774 f->hs_descriptors, &acm_hs_out_desc);
775 acm->hs.notify = usb_find_endpoint(acm_hs_function,
776 f->hs_descriptors, &acm_hs_notify_desc);
777 }
778
David Brownell4d5a73d2008-06-19 18:18:40 -0700779 DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n",
780 acm->port_num,
781 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
782 acm->port.in->name, acm->port.out->name,
783 acm->notify->name);
784 return 0;
785
786fail:
David Brownell1f1ba112008-08-06 18:49:57 -0700787 if (acm->notify_req)
788 gs_free_req(acm->notify, acm->notify_req);
789
David Brownell4d5a73d2008-06-19 18:18:40 -0700790 /* we might as well release our claims on endpoints */
791 if (acm->notify)
792 acm->notify->driver_data = NULL;
793 if (acm->port.out)
794 acm->port.out->driver_data = NULL;
795 if (acm->port.in)
796 acm->port.in->driver_data = NULL;
797
798 ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status);
799
800 return status;
801}
802
803static void
804acm_unbind(struct usb_configuration *c, struct usb_function *f)
805{
David Brownell1f1ba112008-08-06 18:49:57 -0700806 struct f_acm *acm = func_to_acm(f);
807
David Brownell4d5a73d2008-06-19 18:18:40 -0700808 if (gadget_is_dualspeed(c->cdev->gadget))
809 usb_free_descriptors(f->hs_descriptors);
810 usb_free_descriptors(f->descriptors);
David Brownell1f1ba112008-08-06 18:49:57 -0700811 gs_free_req(acm->notify, acm->notify_req);
John Michelau677ba872010-11-08 18:05:37 -0600812 kfree(acm->port.func.name);
David Brownell1f1ba112008-08-06 18:49:57 -0700813 kfree(acm);
David Brownell4d5a73d2008-06-19 18:18:40 -0700814}
815
816/* Some controllers can't support CDC ACM ... */
817static inline bool can_support_cdc(struct usb_configuration *c)
818{
David Brownell4d5a73d2008-06-19 18:18:40 -0700819 /* everything else is *probably* fine ... */
820 return true;
821}
822
823/**
824 * acm_bind_config - add a CDC ACM function to a configuration
825 * @c: the configuration to support the CDC ACM instance
826 * @port_num: /dev/ttyGS* port this interface will use
827 * Context: single threaded during gadget setup
828 *
829 * Returns zero on success, else negative errno.
830 *
831 * Caller must have called @gserial_setup() with enough ports to
832 * handle all the ones it binds. Caller is also responsible
833 * for calling @gserial_cleanup() before module unload.
834 */
Michal Nazarewicz28824b12010-05-05 12:53:13 +0200835int acm_bind_config(struct usb_configuration *c, u8 port_num)
David Brownell4d5a73d2008-06-19 18:18:40 -0700836{
837 struct f_acm *acm;
838 int status;
839
840 if (!can_support_cdc(c))
841 return -EINVAL;
842
843 /* REVISIT might want instance-specific strings to help
844 * distinguish instances ...
845 */
846
847 /* maybe allocate device-global string IDs, and patch descriptors */
848 if (acm_string_defs[ACM_CTRL_IDX].id == 0) {
849 status = usb_string_id(c->cdev);
850 if (status < 0)
851 return status;
852 acm_string_defs[ACM_CTRL_IDX].id = status;
853
854 acm_control_interface_desc.iInterface = status;
855
856 status = usb_string_id(c->cdev);
857 if (status < 0)
858 return status;
859 acm_string_defs[ACM_DATA_IDX].id = status;
860
861 acm_data_interface_desc.iInterface = status;
Michal Nazarewiczb97503f2009-10-28 16:57:30 +0100862
863 status = usb_string_id(c->cdev);
864 if (status < 0)
865 return status;
866 acm_string_defs[ACM_IAD_IDX].id = status;
867
868 acm_iad_descriptor.iFunction = status;
David Brownell4d5a73d2008-06-19 18:18:40 -0700869 }
870
871 /* allocate and initialize one new instance */
872 acm = kzalloc(sizeof *acm, GFP_KERNEL);
873 if (!acm)
874 return -ENOMEM;
875
David Brownell1f1ba112008-08-06 18:49:57 -0700876 spin_lock_init(&acm->lock);
877
David Brownell4d5a73d2008-06-19 18:18:40 -0700878 acm->port_num = port_num;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700879 acm->transport = gacm_ports[port_num].transport;
David Brownell4d5a73d2008-06-19 18:18:40 -0700880
David Brownell1f1ba112008-08-06 18:49:57 -0700881 acm->port.connect = acm_connect;
882 acm->port.disconnect = acm_disconnect;
883 acm->port.send_break = acm_send_break;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884 acm->port.send_modem_ctrl_bits = acm_send_modem_ctrl_bits;
David Brownell1f1ba112008-08-06 18:49:57 -0700885
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886 acm->port.func.name = kasprintf(GFP_KERNEL, "acm%u", port_num + 1);
John Michelau677ba872010-11-08 18:05:37 -0600887 if (!acm->port.func.name) {
888 kfree(acm);
889 return -ENOMEM;
890 }
David Brownell4d5a73d2008-06-19 18:18:40 -0700891 acm->port.func.strings = acm_strings;
892 /* descriptors are per-instance copies */
893 acm->port.func.bind = acm_bind;
894 acm->port.func.unbind = acm_unbind;
895 acm->port.func.set_alt = acm_set_alt;
896 acm->port.func.setup = acm_setup;
897 acm->port.func.disable = acm_disable;
898
899 status = usb_add_function(c, &acm->port.func);
900 if (status)
901 kfree(acm);
902 return status;
903}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700904
905#ifdef CONFIG_USB_ANDROID_ACM
906#include <linux/platform_device.h>
907
908static struct acm_platform_data *acm_pdata;
909
910static int acm_probe(struct platform_device *pdev)
911{
912 acm_pdata = pdev->dev.platform_data;
913 return 0;
914}
915
916static struct platform_driver acm_platform_driver = {
917 .driver = { .name = "acm", },
918 .probe = acm_probe,
919};
920
921int acm1_function_bind_config(struct usb_configuration *c)
922{
923 int ret = acm_bind_config(c, 0);
924 if (ret == 0)
925 gport_setup(c);
926 return ret;
927}
928
929int acm2_function_bind_config(struct usb_configuration *c)
930{
931 int ret = acm_bind_config(c, 1);
932
933 return ret;
934}
935
936static struct android_usb_function acm1_function = {
937 .name = "acm1",
938 .bind_config = acm1_function_bind_config,
939};
940
941static struct android_usb_function acm2_function = {
942 .name = "acm2",
943 .bind_config = acm2_function_bind_config,
944};
945
946static int facm_remove(struct platform_device *pdev)
947{
948 gserial_cleanup();
949
950 return 0;
951}
952
953static struct platform_driver usb_facm = {
954 .remove = facm_remove,
955 .driver = {
956 .name = "usb_facm",
957 .owner = THIS_MODULE,
958 },
959};
960
961static int __init facm_probe(struct platform_device *pdev)
962{
963 struct usb_gadget_facm_pdata *pdata = pdev->dev.platform_data;
964 int i;
965
966 dev_dbg(&pdev->dev, "%s: probe\n", __func__);
967
968 if (!pdata)
969 goto probe_android_register;
970
971 for (i = 0; i < GSERIAL_NO_PORTS; i++) {
972 gacm_ports[i].transport = pdata->transport[i];
973 gacm_ports[i].port_num = i;
974
975 switch (gacm_ports[i].transport) {
976 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
977 gacm_ports[i].client_port_num = no_tty_ports;
978 no_tty_ports++;
979 break;
980 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
981 gacm_ports[i].client_port_num = no_sdio_ports;
982 no_sdio_ports++;
983 break;
984 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
985 gacm_ports[i].client_port_num = no_smd_ports;
986 no_smd_ports++;
987 break;
988 default:
989 pr_err("%s: Un-supported transport transport: %u\n",
990 __func__, gacm_ports[i].transport);
991 return -ENODEV;
992 }
993
994 nr_ports++;
995 }
996
997 pr_info("%s:gport:tty_ports:%u sdio_ports:%u "
998 "smd_ports:%u nr_ports:%u\n",
999 __func__, no_tty_ports, no_sdio_ports,
1000 no_smd_ports, nr_ports);
1001
1002probe_android_register:
1003 android_register_function(&acm1_function);
1004 android_register_function(&acm2_function);
1005
1006 return 0;
1007}
1008
1009static int __init init(void)
1010{
1011 printk(KERN_INFO "f_acm init\n");
1012
1013 return platform_driver_probe(&usb_facm, facm_probe);
1014}
1015module_init(init);
1016
1017#endif /* CONFIG_USB_ANDROID_ACM */