blob: 0c315443125d93c0c9a8e20bd9cfe0127143009b [file] [log] [blame]
David Brownell61d8bae2008-06-19 18:18:50 -07001/*
2 * f_serial.c - generic USB serial 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
7 *
8 * This software is distributed under the terms of the GNU General
9 * Public License ("GPL") as published by the Free Software Foundation,
10 * either version 2 of that License or (at your option) any later version.
11 */
12
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090013#include <linux/slab.h>
David Brownell61d8bae2008-06-19 18:18:50 -070014#include <linux/kernel.h>
15#include <linux/device.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070016#include <linux/usb/android_composite.h>
17#include <mach/usb_gadget_fserial.h>
David Brownell61d8bae2008-06-19 18:18:50 -070018
19#include "u_serial.h"
20#include "gadget_chips.h"
21
22
23/*
24 * This function packages a simple "generic serial" port with no real
25 * control mechanisms, just raw data transfer over two bulk endpoints.
26 *
27 * Because it's not standardized, this isn't as interoperable as the
28 * CDC ACM driver. However, for many purposes it's just as functional
29 * if you can arrange appropriate host side drivers.
30 */
31
32struct gser_descs {
33 struct usb_endpoint_descriptor *in;
34 struct usb_endpoint_descriptor *out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070035#ifdef CONFIG_MODEM_SUPPORT
36 struct usb_endpoint_descriptor *notify;
37#endif
David Brownell61d8bae2008-06-19 18:18:50 -070038};
39
40struct f_gser {
41 struct gserial port;
42 u8 data_id;
43 u8 port_num;
44
David Brownell61d8bae2008-06-19 18:18:50 -070045 struct gser_descs fs;
David Brownell61d8bae2008-06-19 18:18:50 -070046 struct gser_descs hs;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047 u8 online;
48 enum transport_type transport;
49
50#ifdef CONFIG_MODEM_SUPPORT
51 u8 pending;
52 spinlock_t lock;
53 struct usb_ep *notify;
54 struct usb_endpoint_descriptor *notify_desc;
55 struct usb_request *notify_req;
56
57 struct usb_cdc_line_coding port_line_coding;
58
59 /* SetControlLineState request */
60 u16 port_handshake_bits;
61#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
62#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
63
64 /* SerialState notification */
65 u16 serial_state;
66#define ACM_CTRL_OVERRUN (1 << 6)
67#define ACM_CTRL_PARITY (1 << 5)
68#define ACM_CTRL_FRAMING (1 << 4)
69#define ACM_CTRL_RI (1 << 3)
70#define ACM_CTRL_BRK (1 << 2)
71#define ACM_CTRL_DSR (1 << 1)
72#define ACM_CTRL_DCD (1 << 0)
73#endif
David Brownell61d8bae2008-06-19 18:18:50 -070074};
75
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076#ifdef CONFIG_USB_F_SERIAL
77static unsigned int no_tty_ports;
78static unsigned int no_sdio_ports;
79static unsigned int no_smd_ports;
80static unsigned int nr_ports;
81#endif
82
83static struct port_info {
84 enum transport_type transport;
85 unsigned port_num;
86 unsigned client_port_num;
87} gserial_ports[GSERIAL_NO_PORTS];
88
89static inline bool is_transport_sdio(enum transport_type t)
90{
91 if (t == USB_GADGET_FSERIAL_TRANSPORT_SDIO)
92 return 1;
93 return 0;
94}
95
David Brownell61d8bae2008-06-19 18:18:50 -070096static inline struct f_gser *func_to_gser(struct usb_function *f)
97{
98 return container_of(f, struct f_gser, port.func);
99}
100
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700101#ifdef CONFIG_MODEM_SUPPORT
102static inline struct f_gser *port_to_gser(struct gserial *p)
103{
104 return container_of(p, struct f_gser, port);
105}
106#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
107#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
108#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700109/*-------------------------------------------------------------------------*/
110
111/* interface descriptor: */
112
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700113static struct usb_interface_descriptor gser_interface_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700114 .bLength = USB_DT_INTERFACE_SIZE,
115 .bDescriptorType = USB_DT_INTERFACE,
116 /* .bInterfaceNumber = DYNAMIC */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700117#ifdef CONFIG_MODEM_SUPPORT
118 .bNumEndpoints = 3,
119#else
David Brownell61d8bae2008-06-19 18:18:50 -0700120 .bNumEndpoints = 2,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700121#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700122 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
123 .bInterfaceSubClass = 0,
124 .bInterfaceProtocol = 0,
125 /* .iInterface = DYNAMIC */
126};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700127#ifdef CONFIG_MODEM_SUPPORT
128static struct usb_cdc_header_desc gser_header_desc = {
129 .bLength = sizeof(gser_header_desc),
130 .bDescriptorType = USB_DT_CS_INTERFACE,
131 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
132 .bcdCDC = __constant_cpu_to_le16(0x0110),
133};
David Brownell61d8bae2008-06-19 18:18:50 -0700134
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700135static struct usb_cdc_call_mgmt_descriptor
136gser_call_mgmt_descriptor = {
137 .bLength = sizeof(gser_call_mgmt_descriptor),
138 .bDescriptorType = USB_DT_CS_INTERFACE,
139 .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
140 .bmCapabilities = 0,
141 /* .bDataInterface = DYNAMIC */
142};
143
144static struct usb_cdc_acm_descriptor gser_descriptor = {
145 .bLength = sizeof(gser_descriptor),
146 .bDescriptorType = USB_DT_CS_INTERFACE,
147 .bDescriptorSubType = USB_CDC_ACM_TYPE,
148 .bmCapabilities = USB_CDC_CAP_LINE,
149};
150
151static struct usb_cdc_union_desc gser_union_desc = {
152 .bLength = sizeof(gser_union_desc),
153 .bDescriptorType = USB_DT_CS_INTERFACE,
154 .bDescriptorSubType = USB_CDC_UNION_TYPE,
155 /* .bMasterInterface0 = DYNAMIC */
156 /* .bSlaveInterface0 = DYNAMIC */
157};
158#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700159/* full speed support: */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160#ifdef CONFIG_MODEM_SUPPORT
161static struct usb_endpoint_descriptor gser_fs_notify_desc = {
162 .bLength = USB_DT_ENDPOINT_SIZE,
163 .bDescriptorType = USB_DT_ENDPOINT,
164 .bEndpointAddress = USB_DIR_IN,
165 .bmAttributes = USB_ENDPOINT_XFER_INT,
166 .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
167 .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
168};
169#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700170
171static struct usb_endpoint_descriptor gser_fs_in_desc __initdata = {
172 .bLength = USB_DT_ENDPOINT_SIZE,
173 .bDescriptorType = USB_DT_ENDPOINT,
174 .bEndpointAddress = USB_DIR_IN,
175 .bmAttributes = USB_ENDPOINT_XFER_BULK,
176};
177
178static struct usb_endpoint_descriptor gser_fs_out_desc __initdata = {
179 .bLength = USB_DT_ENDPOINT_SIZE,
180 .bDescriptorType = USB_DT_ENDPOINT,
181 .bEndpointAddress = USB_DIR_OUT,
182 .bmAttributes = USB_ENDPOINT_XFER_BULK,
183};
184
185static struct usb_descriptor_header *gser_fs_function[] __initdata = {
186 (struct usb_descriptor_header *) &gser_interface_desc,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187#ifdef CONFIG_MODEM_SUPPORT
188 (struct usb_descriptor_header *) &gser_header_desc,
189 (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
190 (struct usb_descriptor_header *) &gser_descriptor,
191 (struct usb_descriptor_header *) &gser_union_desc,
192 (struct usb_descriptor_header *) &gser_fs_notify_desc,
193#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700194 (struct usb_descriptor_header *) &gser_fs_in_desc,
195 (struct usb_descriptor_header *) &gser_fs_out_desc,
196 NULL,
197};
198
199/* high speed support: */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200#ifdef CONFIG_MODEM_SUPPORT
201static struct usb_endpoint_descriptor gser_hs_notify_desc = {
202 .bLength = USB_DT_ENDPOINT_SIZE,
203 .bDescriptorType = USB_DT_ENDPOINT,
204 .bEndpointAddress = USB_DIR_IN,
205 .bmAttributes = USB_ENDPOINT_XFER_INT,
206 .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
207 .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
208};
209#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700210
211static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = {
212 .bLength = USB_DT_ENDPOINT_SIZE,
213 .bDescriptorType = USB_DT_ENDPOINT,
214 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215 .wMaxPacketSize = __constant_cpu_to_le16(512),
David Brownell61d8bae2008-06-19 18:18:50 -0700216};
217
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700218static struct usb_endpoint_descriptor gser_hs_out_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700219 .bLength = USB_DT_ENDPOINT_SIZE,
220 .bDescriptorType = USB_DT_ENDPOINT,
221 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222 .wMaxPacketSize = __constant_cpu_to_le16(512),
David Brownell61d8bae2008-06-19 18:18:50 -0700223};
224
225static struct usb_descriptor_header *gser_hs_function[] __initdata = {
226 (struct usb_descriptor_header *) &gser_interface_desc,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227#ifdef CONFIG_MODEM_SUPPORT
228 (struct usb_descriptor_header *) &gser_header_desc,
229 (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
230 (struct usb_descriptor_header *) &gser_descriptor,
231 (struct usb_descriptor_header *) &gser_union_desc,
232 (struct usb_descriptor_header *) &gser_hs_notify_desc,
233#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700234 (struct usb_descriptor_header *) &gser_hs_in_desc,
235 (struct usb_descriptor_header *) &gser_hs_out_desc,
236 NULL,
237};
238
239/* string descriptors: */
240
241static struct usb_string gser_string_defs[] = {
242 [0].s = "Generic Serial",
243 { } /* end of list */
244};
245
246static struct usb_gadget_strings gser_string_table = {
247 .language = 0x0409, /* en-us */
248 .strings = gser_string_defs,
249};
250
251static struct usb_gadget_strings *gser_strings[] = {
252 &gser_string_table,
253 NULL,
254};
255
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256static char *transport_to_str(enum transport_type t)
257{
258 switch (t) {
259 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
260 return "TTY";
261 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
262 return "SDIO";
263 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
264 return "SMD";
265 }
266
267 return "NONE";
268}
269
270#ifdef CONFIG_USB_F_SERIAL
271static int gport_setup(struct usb_configuration *c)
272{
273 int ret = 0;
274
275 pr_debug("%s: no_tty_ports:%u no_sdio_ports: %u nr_ports:%u\n",
276 __func__, no_tty_ports, no_sdio_ports, nr_ports);
277
278 if (no_tty_ports)
279 ret = gserial_setup(c->cdev->gadget, no_tty_ports);
280 if (no_sdio_ports)
281 ret = gsdio_setup(c->cdev->gadget, no_sdio_ports);
282 if (no_smd_ports)
283 ret = gsmd_setup(c->cdev->gadget, no_smd_ports);
284
285 return ret;
286}
287#endif
288static int gport_connect(struct f_gser *gser)
289{
290 unsigned port_num;
291
292 pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
293 __func__, transport_to_str(gser->transport),
294 gser, &gser->port, gser->port_num);
295
296 port_num = gserial_ports[gser->port_num].client_port_num;
297
298 switch (gser->transport) {
299 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
300 gserial_connect(&gser->port, port_num);
301 break;
302 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
303 gsdio_connect(&gser->port, port_num);
304 break;
305 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
306 gsmd_connect(&gser->port, port_num);
307 break;
308 default:
309 pr_err("%s: Un-supported transport: %s\n", __func__,
310 transport_to_str(gser->transport));
311 return -ENODEV;
312 }
313
314 return 0;
315}
316
317static int gport_disconnect(struct f_gser *gser)
318{
319 unsigned port_num;
320
321 pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
322 __func__, transport_to_str(gser->transport),
323 gser, &gser->port, gser->port_num);
324
325 port_num = gserial_ports[gser->port_num].client_port_num;
326
327 switch (gser->transport) {
328 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
329 gserial_disconnect(&gser->port);
330 break;
331 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
332 gsdio_disconnect(&gser->port, port_num);
333 break;
334 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
335 gsmd_disconnect(&gser->port, port_num);
336 break;
337 default:
338 pr_err("%s: Un-supported transport:%s\n", __func__,
339 transport_to_str(gser->transport));
340 return -ENODEV;
341 }
342
343 return 0;
344}
345
346#ifdef CONFIG_MODEM_SUPPORT
347static void gser_complete_set_line_coding(struct usb_ep *ep,
348 struct usb_request *req)
349{
350 struct f_gser *gser = ep->driver_data;
351 struct usb_composite_dev *cdev = gser->port.func.config->cdev;
352
353 if (req->status != 0) {
354 DBG(cdev, "gser ttyGS%d completion, err %d\n",
355 gser->port_num, req->status);
356 return;
357 }
358
359 /* normal completion */
360 if (req->actual != sizeof(gser->port_line_coding)) {
361 DBG(cdev, "gser ttyGS%d short resp, len %d\n",
362 gser->port_num, req->actual);
363 usb_ep_set_halt(ep);
364 } else {
365 struct usb_cdc_line_coding *value = req->buf;
366 gser->port_line_coding = *value;
367 }
368}
David Brownell61d8bae2008-06-19 18:18:50 -0700369/*-------------------------------------------------------------------------*/
370
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700371static int
372gser_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
373{
374 struct f_gser *gser = func_to_gser(f);
375 struct usb_composite_dev *cdev = f->config->cdev;
376 struct usb_request *req = cdev->req;
377 int value = -EOPNOTSUPP;
378 u16 w_index = le16_to_cpu(ctrl->wIndex);
379 u16 w_value = le16_to_cpu(ctrl->wValue);
380 u16 w_length = le16_to_cpu(ctrl->wLength);
381
382 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
383
384 /* SET_LINE_CODING ... just read and save what the host sends */
385 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
386 | USB_CDC_REQ_SET_LINE_CODING:
387 if (w_length != sizeof(struct usb_cdc_line_coding))
388 goto invalid;
389
390 value = w_length;
391 cdev->gadget->ep0->driver_data = gser;
392 req->complete = gser_complete_set_line_coding;
393 break;
394
395 /* GET_LINE_CODING ... return what host sent, or initial value */
396 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
397 | USB_CDC_REQ_GET_LINE_CODING:
398 value = min_t(unsigned, w_length,
399 sizeof(struct usb_cdc_line_coding));
400 memcpy(req->buf, &gser->port_line_coding, value);
401 break;
402
403 /* SET_CONTROL_LINE_STATE ... save what the host sent */
404 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
405 | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
406
407 value = 0;
408 gser->port_handshake_bits = w_value;
409 if (gser->port.notify_modem) {
410 unsigned port_num =
411 gserial_ports[gser->port_num].client_port_num;
412
413 gser->port.notify_modem(&gser->port,
414 port_num, w_value);
415 }
416 break;
417
418 default:
419invalid:
420 DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
421 ctrl->bRequestType, ctrl->bRequest,
422 w_value, w_index, w_length);
423 }
424
425 /* respond with data transfer or status phase? */
426 if (value >= 0) {
427 DBG(cdev, "gser ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
428 gser->port_num, ctrl->bRequestType, ctrl->bRequest,
429 w_value, w_index, w_length);
430 req->zero = 0;
431 req->length = value;
432 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
433 if (value < 0)
434 ERROR(cdev, "gser response on ttyGS%d, err %d\n",
435 gser->port_num, value);
436 }
437
438 /* device either stalls (value < 0) or reports success */
439 return value;
440}
441#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700442static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
443{
444 struct f_gser *gser = func_to_gser(f);
445 struct usb_composite_dev *cdev = f->config->cdev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700446 int rc = 0;
David Brownell61d8bae2008-06-19 18:18:50 -0700447
448 /* we know alt == 0, so this is an activation or a reset */
449
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700450#ifdef CONFIG_MODEM_SUPPORT
451 if (gser->notify->driver_data) {
452 DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num);
453 usb_ep_disable(gser->notify);
David Brownell61d8bae2008-06-19 18:18:50 -0700454 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700455 gser->notify_desc = ep_choose(cdev->gadget,
456 gser->hs.notify,
457 gser->fs.notify);
458 rc = usb_ep_enable(gser->notify, gser->notify_desc);
459 if (rc) {
460 ERROR(cdev, "can't enable %s, result %d\n",
461 gser->notify->name, rc);
462 return rc;
463 }
464 gser->notify->driver_data = gser;
465#endif
466
467 if (gser->port.in->driver_data) {
468 DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num);
469 gport_disconnect(gser);
470 } else {
471 DBG(cdev, "activate generic data ttyGS%d\n", gser->port_num);
472 }
473 gser->port.in_desc = ep_choose(cdev->gadget,
474 gser->hs.in, gser->fs.in);
475 gser->port.out_desc = ep_choose(cdev->gadget,
476 gser->hs.out, gser->fs.out);
477
478 gport_connect(gser);
479
480 gser->online = 1;
481 return rc;
David Brownell61d8bae2008-06-19 18:18:50 -0700482}
483
484static void gser_disable(struct usb_function *f)
485{
486 struct f_gser *gser = func_to_gser(f);
487 struct usb_composite_dev *cdev = f->config->cdev;
488
489 DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700490
491 gport_disconnect(gser);
492
493#ifdef CONFIG_MODEM_SUPPORT
494 usb_ep_fifo_flush(gser->notify);
495 usb_ep_disable(gser->notify);
496#endif
497 gser->online = 0;
498}
499#ifdef CONFIG_MODEM_SUPPORT
500static int gser_notify(struct f_gser *gser, u8 type, u16 value,
501 void *data, unsigned length)
502{
503 struct usb_ep *ep = gser->notify;
504 struct usb_request *req;
505 struct usb_cdc_notification *notify;
506 const unsigned len = sizeof(*notify) + length;
507 void *buf;
508 int status;
509 struct usb_composite_dev *cdev = gser->port.func.config->cdev;
510
511 req = gser->notify_req;
512 gser->notify_req = NULL;
513 gser->pending = false;
514
515 req->length = len;
516 notify = req->buf;
517 buf = notify + 1;
518
519 notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
520 | USB_RECIP_INTERFACE;
521 notify->bNotificationType = type;
522 notify->wValue = cpu_to_le16(value);
523 notify->wIndex = cpu_to_le16(gser->data_id);
524 notify->wLength = cpu_to_le16(length);
525 memcpy(buf, data, length);
526
527 status = usb_ep_queue(ep, req, GFP_ATOMIC);
528 if (status < 0) {
529 ERROR(cdev, "gser ttyGS%d can't notify serial state, %d\n",
530 gser->port_num, status);
531 gser->notify_req = req;
532 }
533
534 return status;
David Brownell61d8bae2008-06-19 18:18:50 -0700535}
536
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537static int gser_notify_serial_state(struct f_gser *gser)
538{
539 int status;
540 unsigned long flags;
541 struct usb_composite_dev *cdev = gser->port.func.config->cdev;
542
543 spin_lock_irqsave(&gser->lock, flags);
544 if (gser->notify_req) {
545 DBG(cdev, "gser ttyGS%d serial state %04x\n",
546 gser->port_num, gser->serial_state);
547 status = gser_notify(gser, USB_CDC_NOTIFY_SERIAL_STATE,
548 0, &gser->serial_state,
549 sizeof(gser->serial_state));
550 } else {
551 gser->pending = true;
552 status = 0;
553 }
554 spin_unlock_irqrestore(&gser->lock, flags);
555 return status;
556}
557
558static void gser_notify_complete(struct usb_ep *ep, struct usb_request *req)
559{
560 struct f_gser *gser = req->context;
561 u8 doit = false;
562 unsigned long flags;
563
564 /* on this call path we do NOT hold the port spinlock,
565 * which is why ACM needs its own spinlock
566 */
567 spin_lock_irqsave(&gser->lock, flags);
568 if (req->status != -ESHUTDOWN)
569 doit = gser->pending;
570 gser->notify_req = req;
571 spin_unlock_irqrestore(&gser->lock, flags);
572
573 if (doit && gser->online)
574 gser_notify_serial_state(gser);
575}
576static void gser_connect(struct gserial *port)
577{
578 struct f_gser *gser = port_to_gser(port);
579
580 gser->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
581 gser_notify_serial_state(gser);
582}
583
584unsigned int gser_get_dtr(struct gserial *port)
585{
586 struct f_gser *gser = port_to_gser(port);
587
588 if (gser->port_handshake_bits & ACM_CTRL_DTR)
589 return 1;
590 else
591 return 0;
592}
593
594unsigned int gser_get_rts(struct gserial *port)
595{
596 struct f_gser *gser = port_to_gser(port);
597
598 if (gser->port_handshake_bits & ACM_CTRL_RTS)
599 return 1;
600 else
601 return 0;
602}
603
604unsigned int gser_send_carrier_detect(struct gserial *port, unsigned int yes)
605{
606 struct f_gser *gser = port_to_gser(port);
607 u16 state;
608
609 state = gser->serial_state;
610 state &= ~ACM_CTRL_DCD;
611 if (yes)
612 state |= ACM_CTRL_DCD;
613
614 gser->serial_state = state;
615 return gser_notify_serial_state(gser);
616
617}
618
619unsigned int gser_send_ring_indicator(struct gserial *port, unsigned int yes)
620{
621 struct f_gser *gser = port_to_gser(port);
622 u16 state;
623
624 state = gser->serial_state;
625 state &= ~ACM_CTRL_RI;
626 if (yes)
627 state |= ACM_CTRL_RI;
628
629 gser->serial_state = state;
630 return gser_notify_serial_state(gser);
631
632}
633static void gser_disconnect(struct gserial *port)
634{
635 struct f_gser *gser = port_to_gser(port);
636
637 gser->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
638 gser_notify_serial_state(gser);
639}
640
641static int gser_send_break(struct gserial *port, int duration)
642{
643 struct f_gser *gser = port_to_gser(port);
644 u16 state;
645
646 state = gser->serial_state;
647 state &= ~ACM_CTRL_BRK;
648 if (duration)
649 state |= ACM_CTRL_BRK;
650
651 gser->serial_state = state;
652 return gser_notify_serial_state(gser);
653}
654
655static int gser_send_modem_ctrl_bits(struct gserial *port, int ctrl_bits)
656{
657 struct f_gser *gser = port_to_gser(port);
658
659 gser->serial_state = ctrl_bits;
660
661 return gser_notify_serial_state(gser);
662}
663#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700664/*-------------------------------------------------------------------------*/
665
666/* serial function driver setup/binding */
667
668static int __init
669gser_bind(struct usb_configuration *c, struct usb_function *f)
670{
671 struct usb_composite_dev *cdev = c->cdev;
672 struct f_gser *gser = func_to_gser(f);
673 int status;
674 struct usb_ep *ep;
675
676 /* allocate instance-specific interface IDs */
677 status = usb_interface_id(c, f);
678 if (status < 0)
679 goto fail;
680 gser->data_id = status;
681 gser_interface_desc.bInterfaceNumber = status;
682
683 status = -ENODEV;
684
685 /* allocate instance-specific endpoints */
686 ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc);
687 if (!ep)
688 goto fail;
689 gser->port.in = ep;
690 ep->driver_data = cdev; /* claim */
691
692 ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
693 if (!ep)
694 goto fail;
695 gser->port.out = ep;
696 ep->driver_data = cdev; /* claim */
697
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700698#ifdef CONFIG_MODEM_SUPPORT
699 ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc);
700 if (!ep)
701 goto fail;
702 gser->notify = ep;
703 ep->driver_data = cdev; /* claim */
704 /* allocate notification */
705 gser->notify_req = gs_alloc_req(ep,
706 sizeof(struct usb_cdc_notification) + 2,
707 GFP_KERNEL);
708 if (!gser->notify_req)
709 goto fail;
710
711 gser->notify_req->complete = gser_notify_complete;
712 gser->notify_req->context = gser;
713#endif
714
David Brownell61d8bae2008-06-19 18:18:50 -0700715 /* copy descriptors, and track endpoint copies */
716 f->descriptors = usb_copy_descriptors(gser_fs_function);
717
718 gser->fs.in = usb_find_endpoint(gser_fs_function,
719 f->descriptors, &gser_fs_in_desc);
720 gser->fs.out = usb_find_endpoint(gser_fs_function,
721 f->descriptors, &gser_fs_out_desc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700722#ifdef CONFIG_MODEM_SUPPORT
723 gser->fs.notify = usb_find_endpoint(gser_fs_function,
724 f->descriptors, &gser_fs_notify_desc);
725#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700726
727
728 /* support all relevant hardware speeds... we expect that when
729 * hardware is dual speed, all bulk-capable endpoints work at
730 * both speeds
731 */
732 if (gadget_is_dualspeed(c->cdev->gadget)) {
733 gser_hs_in_desc.bEndpointAddress =
734 gser_fs_in_desc.bEndpointAddress;
735 gser_hs_out_desc.bEndpointAddress =
736 gser_fs_out_desc.bEndpointAddress;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700737#ifdef CONFIG_MODEM_SUPPORT
738 gser_hs_notify_desc.bEndpointAddress =
739 gser_fs_notify_desc.bEndpointAddress;
740#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700741
742 /* copy descriptors, and track endpoint copies */
743 f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
744
745 gser->hs.in = usb_find_endpoint(gser_hs_function,
746 f->hs_descriptors, &gser_hs_in_desc);
747 gser->hs.out = usb_find_endpoint(gser_hs_function,
748 f->hs_descriptors, &gser_hs_out_desc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749#ifdef CONFIG_MODEM_SUPPORT
750 gser->hs.notify = usb_find_endpoint(gser_hs_function,
751 f->hs_descriptors, &gser_hs_notify_desc);
752#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700753 }
754
755 DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
756 gser->port_num,
757 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
758 gser->port.in->name, gser->port.out->name);
759 return 0;
760
761fail:
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762#ifdef CONFIG_MODEM_SUPPORT
763 if (gser->notify_req)
764 gs_free_req(gser->notify, gser->notify_req);
765
766 /* we might as well release our claims on endpoints */
767 if (gser->notify)
768 gser->notify->driver_data = NULL;
769#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700770 /* we might as well release our claims on endpoints */
771 if (gser->port.out)
772 gser->port.out->driver_data = NULL;
773 if (gser->port.in)
774 gser->port.in->driver_data = NULL;
775
776 ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
777
778 return status;
779}
780
781static void
782gser_unbind(struct usb_configuration *c, struct usb_function *f)
783{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784#ifdef CONFIG_MODEM_SUPPORT
785 struct f_gser *gser = func_to_gser(f);
786#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700787 if (gadget_is_dualspeed(c->cdev->gadget))
788 usb_free_descriptors(f->hs_descriptors);
789 usb_free_descriptors(f->descriptors);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700790#ifdef CONFIG_MODEM_SUPPORT
791 gs_free_req(gser->notify, gser->notify_req);
792#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700793 kfree(func_to_gser(f));
794}
795
796/**
797 * gser_bind_config - add a generic serial function to a configuration
798 * @c: the configuration to support the serial instance
799 * @port_num: /dev/ttyGS* port this interface will use
800 * Context: single threaded during gadget setup
801 *
802 * Returns zero on success, else negative errno.
803 *
804 * Caller must have called @gserial_setup() with enough ports to
805 * handle all the ones it binds. Caller is also responsible
806 * for calling @gserial_cleanup() before module unload.
807 */
808int __init gser_bind_config(struct usb_configuration *c, u8 port_num)
809{
810 struct f_gser *gser;
811 int status;
812
813 /* REVISIT might want instance-specific strings to help
814 * distinguish instances ...
815 */
816
817 /* maybe allocate device-global string ID */
818 if (gser_string_defs[0].id == 0) {
819 status = usb_string_id(c->cdev);
820 if (status < 0)
821 return status;
822 gser_string_defs[0].id = status;
823 }
824
825 /* allocate and initialize one new instance */
826 gser = kzalloc(sizeof *gser, GFP_KERNEL);
827 if (!gser)
828 return -ENOMEM;
829
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700830#ifdef CONFIG_MODEM_SUPPORT
831 spin_lock_init(&gser->lock);
832#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700833 gser->port_num = port_num;
834
835 gser->port.func.name = "gser";
836 gser->port.func.strings = gser_strings;
837 gser->port.func.bind = gser_bind;
838 gser->port.func.unbind = gser_unbind;
839 gser->port.func.set_alt = gser_set_alt;
840 gser->port.func.disable = gser_disable;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841 gser->transport = gserial_ports[port_num].transport;
842#ifdef CONFIG_MODEM_SUPPORT
843 /* We support only two ports for now */
844 if (port_num == 0)
845 gser->port.func.name = "modem";
846 else
847 gser->port.func.name = "nmea";
848 gser->port.func.setup = gser_setup;
849 gser->port.connect = gser_connect;
850 gser->port.get_dtr = gser_get_dtr;
851 gser->port.get_rts = gser_get_rts;
852 gser->port.send_carrier_detect = gser_send_carrier_detect;
853 gser->port.send_ring_indicator = gser_send_ring_indicator;
854 gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;
855 gser->port.disconnect = gser_disconnect;
856 gser->port.send_break = gser_send_break;
857#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700858
859 status = usb_add_function(c, &gser->port.func);
860 if (status)
861 kfree(gser);
862 return status;
863}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700864
865#ifdef CONFIG_USB_F_SERIAL
866
867int fserial_nmea_bind_config(struct usb_configuration *c)
868{
869 return gser_bind_config(c, 1);
870}
871
872static struct android_usb_function nmea_function = {
873 .name = "nmea",
874 .bind_config = fserial_nmea_bind_config,
875};
876
877int fserial_modem_bind_config(struct usb_configuration *c)
878{
879 int ret;
880
881 /* See if composite driver can allocate
882 * serial ports. But for now allocate
883 * two ports for modem and nmea.
884 */
885 ret = gport_setup(c);
886
887 if (ret)
888 return ret;
889 return gser_bind_config(c, 0);
890}
891
892static struct android_usb_function modem_function = {
893 .name = "modem",
894 .bind_config = fserial_modem_bind_config,
895};
896
897static int fserial_remove(struct platform_device *dev)
898{
899 gserial_cleanup();
900
901 return 0;
902}
903
904static struct platform_driver usb_fserial = {
905 .remove = fserial_remove,
906 .driver = {
907 .name = "usb_fserial",
908 .owner = THIS_MODULE,
909 },
910};
911
912static int __init fserial_probe(struct platform_device *pdev)
913{
914 struct usb_gadget_fserial_platform_data *pdata =
915 pdev->dev.platform_data;
916 int i;
917
918 dev_dbg(&pdev->dev, "%s: probe\n", __func__);
919
920 if (!pdata)
921 goto probe_android_register;
922
923 for (i = 0; i < GSERIAL_NO_PORTS; i++) {
924 gserial_ports[i].transport = pdata->transport[i];
925 gserial_ports[i].port_num = i;
926
927 switch (gserial_ports[i].transport) {
928 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
929 gserial_ports[i].client_port_num = no_tty_ports;
930 no_tty_ports++;
931 break;
932 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
933 gserial_ports[i].client_port_num = no_sdio_ports;
934 no_sdio_ports++;
935 break;
936 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
937 gserial_ports[i].client_port_num = no_smd_ports;
938 no_smd_ports++;
939 break;
940 default:
941 pr_err("%s: Un-supported transport transport: %u\n",
942 __func__, gserial_ports[i].transport);
943 return -ENODEV;
944 }
945
946 nr_ports++;
947 }
948
949 pr_info("%s:gport:tty_ports:%u sdio_ports:%u "
950 "smd_ports:%u nr_ports:%u\n",
951 __func__, no_tty_ports, no_sdio_ports,
952 no_smd_ports, nr_ports);
953
954probe_android_register:
955 android_register_function(&modem_function);
956 android_register_function(&nmea_function);
957
958 return 0;
959}
960
961static int __init fserial_init(void)
962{
963 return platform_driver_probe(&usb_fserial, fserial_probe);
964}
965module_init(fserial_init);
966
967#endif /* CONFIG_USB_ANDROID_ACM */