blob: 6cf148a748489b7972b92af424221477c3327ee0 [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 <mach/usb_gadget_fserial.h>
David Brownell61d8bae2008-06-19 18:18:50 -070017
18#include "u_serial.h"
19#include "gadget_chips.h"
20
21
22/*
23 * This function packages a simple "generic serial" port with no real
24 * control mechanisms, just raw data transfer over two bulk endpoints.
25 *
26 * Because it's not standardized, this isn't as interoperable as the
27 * CDC ACM driver. However, for many purposes it's just as functional
28 * if you can arrange appropriate host side drivers.
29 */
30
31struct gser_descs {
32 struct usb_endpoint_descriptor *in;
33 struct usb_endpoint_descriptor *out;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070034#ifdef CONFIG_MODEM_SUPPORT
35 struct usb_endpoint_descriptor *notify;
36#endif
David Brownell61d8bae2008-06-19 18:18:50 -070037};
38
39struct f_gser {
40 struct gserial port;
41 u8 data_id;
42 u8 port_num;
43
David Brownell61d8bae2008-06-19 18:18:50 -070044 struct gser_descs fs;
David Brownell61d8bae2008-06-19 18:18:50 -070045 struct gser_descs hs;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070046 u8 online;
47 enum transport_type transport;
48
49#ifdef CONFIG_MODEM_SUPPORT
50 u8 pending;
51 spinlock_t lock;
52 struct usb_ep *notify;
53 struct usb_endpoint_descriptor *notify_desc;
54 struct usb_request *notify_req;
55
56 struct usb_cdc_line_coding port_line_coding;
57
58 /* SetControlLineState request */
59 u16 port_handshake_bits;
60#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
61#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
62
63 /* SerialState notification */
64 u16 serial_state;
65#define ACM_CTRL_OVERRUN (1 << 6)
66#define ACM_CTRL_PARITY (1 << 5)
67#define ACM_CTRL_FRAMING (1 << 4)
68#define ACM_CTRL_RI (1 << 3)
69#define ACM_CTRL_BRK (1 << 2)
70#define ACM_CTRL_DSR (1 << 1)
71#define ACM_CTRL_DCD (1 << 0)
72#endif
David Brownell61d8bae2008-06-19 18:18:50 -070073};
74
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075static unsigned int no_tty_ports;
76static unsigned int no_sdio_ports;
77static unsigned int no_smd_ports;
78static unsigned int nr_ports;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070079
80static struct port_info {
81 enum transport_type transport;
82 unsigned port_num;
83 unsigned client_port_num;
84} gserial_ports[GSERIAL_NO_PORTS];
85
86static inline bool is_transport_sdio(enum transport_type t)
87{
88 if (t == USB_GADGET_FSERIAL_TRANSPORT_SDIO)
89 return 1;
90 return 0;
91}
92
David Brownell61d8bae2008-06-19 18:18:50 -070093static inline struct f_gser *func_to_gser(struct usb_function *f)
94{
95 return container_of(f, struct f_gser, port.func);
96}
97
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070098#ifdef CONFIG_MODEM_SUPPORT
99static inline struct f_gser *port_to_gser(struct gserial *p)
100{
101 return container_of(p, struct f_gser, port);
102}
103#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */
104#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */
105#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700106/*-------------------------------------------------------------------------*/
107
108/* interface descriptor: */
109
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700110static struct usb_interface_descriptor gser_interface_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700111 .bLength = USB_DT_INTERFACE_SIZE,
112 .bDescriptorType = USB_DT_INTERFACE,
113 /* .bInterfaceNumber = DYNAMIC */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700114#ifdef CONFIG_MODEM_SUPPORT
115 .bNumEndpoints = 3,
116#else
David Brownell61d8bae2008-06-19 18:18:50 -0700117 .bNumEndpoints = 2,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700118#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700119 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
120 .bInterfaceSubClass = 0,
121 .bInterfaceProtocol = 0,
122 /* .iInterface = DYNAMIC */
123};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124#ifdef CONFIG_MODEM_SUPPORT
125static struct usb_cdc_header_desc gser_header_desc = {
126 .bLength = sizeof(gser_header_desc),
127 .bDescriptorType = USB_DT_CS_INTERFACE,
128 .bDescriptorSubType = USB_CDC_HEADER_TYPE,
129 .bcdCDC = __constant_cpu_to_le16(0x0110),
130};
David Brownell61d8bae2008-06-19 18:18:50 -0700131
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700132static struct usb_cdc_call_mgmt_descriptor
133gser_call_mgmt_descriptor = {
134 .bLength = sizeof(gser_call_mgmt_descriptor),
135 .bDescriptorType = USB_DT_CS_INTERFACE,
136 .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE,
137 .bmCapabilities = 0,
138 /* .bDataInterface = DYNAMIC */
139};
140
141static struct usb_cdc_acm_descriptor gser_descriptor = {
142 .bLength = sizeof(gser_descriptor),
143 .bDescriptorType = USB_DT_CS_INTERFACE,
144 .bDescriptorSubType = USB_CDC_ACM_TYPE,
145 .bmCapabilities = USB_CDC_CAP_LINE,
146};
147
148static struct usb_cdc_union_desc gser_union_desc = {
149 .bLength = sizeof(gser_union_desc),
150 .bDescriptorType = USB_DT_CS_INTERFACE,
151 .bDescriptorSubType = USB_CDC_UNION_TYPE,
152 /* .bMasterInterface0 = DYNAMIC */
153 /* .bSlaveInterface0 = DYNAMIC */
154};
155#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700156/* full speed support: */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700157#ifdef CONFIG_MODEM_SUPPORT
158static struct usb_endpoint_descriptor gser_fs_notify_desc = {
159 .bLength = USB_DT_ENDPOINT_SIZE,
160 .bDescriptorType = USB_DT_ENDPOINT,
161 .bEndpointAddress = USB_DIR_IN,
162 .bmAttributes = USB_ENDPOINT_XFER_INT,
163 .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
164 .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL,
165};
166#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700167
Manu Gautama4d993f2011-08-30 18:25:55 +0530168static struct usb_endpoint_descriptor gser_fs_in_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700169 .bLength = USB_DT_ENDPOINT_SIZE,
170 .bDescriptorType = USB_DT_ENDPOINT,
171 .bEndpointAddress = USB_DIR_IN,
172 .bmAttributes = USB_ENDPOINT_XFER_BULK,
173};
174
Manu Gautama4d993f2011-08-30 18:25:55 +0530175static struct usb_endpoint_descriptor gser_fs_out_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700176 .bLength = USB_DT_ENDPOINT_SIZE,
177 .bDescriptorType = USB_DT_ENDPOINT,
178 .bEndpointAddress = USB_DIR_OUT,
179 .bmAttributes = USB_ENDPOINT_XFER_BULK,
180};
181
Manu Gautama4d993f2011-08-30 18:25:55 +0530182static struct usb_descriptor_header *gser_fs_function[] = {
David Brownell61d8bae2008-06-19 18:18:50 -0700183 (struct usb_descriptor_header *) &gser_interface_desc,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700184#ifdef CONFIG_MODEM_SUPPORT
185 (struct usb_descriptor_header *) &gser_header_desc,
186 (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
187 (struct usb_descriptor_header *) &gser_descriptor,
188 (struct usb_descriptor_header *) &gser_union_desc,
189 (struct usb_descriptor_header *) &gser_fs_notify_desc,
190#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700191 (struct usb_descriptor_header *) &gser_fs_in_desc,
192 (struct usb_descriptor_header *) &gser_fs_out_desc,
193 NULL,
194};
195
196/* high speed support: */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197#ifdef CONFIG_MODEM_SUPPORT
198static struct usb_endpoint_descriptor gser_hs_notify_desc = {
199 .bLength = USB_DT_ENDPOINT_SIZE,
200 .bDescriptorType = USB_DT_ENDPOINT,
201 .bEndpointAddress = USB_DIR_IN,
202 .bmAttributes = USB_ENDPOINT_XFER_INT,
203 .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET),
204 .bInterval = GS_LOG2_NOTIFY_INTERVAL+4,
205};
206#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700207
Manu Gautama4d993f2011-08-30 18:25:55 +0530208static struct usb_endpoint_descriptor gser_hs_in_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700209 .bLength = USB_DT_ENDPOINT_SIZE,
210 .bDescriptorType = USB_DT_ENDPOINT,
211 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700212 .wMaxPacketSize = __constant_cpu_to_le16(512),
David Brownell61d8bae2008-06-19 18:18:50 -0700213};
214
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700215static struct usb_endpoint_descriptor gser_hs_out_desc = {
David Brownell61d8bae2008-06-19 18:18:50 -0700216 .bLength = USB_DT_ENDPOINT_SIZE,
217 .bDescriptorType = USB_DT_ENDPOINT,
218 .bmAttributes = USB_ENDPOINT_XFER_BULK,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700219 .wMaxPacketSize = __constant_cpu_to_le16(512),
David Brownell61d8bae2008-06-19 18:18:50 -0700220};
221
Manu Gautama4d993f2011-08-30 18:25:55 +0530222static struct usb_descriptor_header *gser_hs_function[] = {
David Brownell61d8bae2008-06-19 18:18:50 -0700223 (struct usb_descriptor_header *) &gser_interface_desc,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700224#ifdef CONFIG_MODEM_SUPPORT
225 (struct usb_descriptor_header *) &gser_header_desc,
226 (struct usb_descriptor_header *) &gser_call_mgmt_descriptor,
227 (struct usb_descriptor_header *) &gser_descriptor,
228 (struct usb_descriptor_header *) &gser_union_desc,
229 (struct usb_descriptor_header *) &gser_hs_notify_desc,
230#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700231 (struct usb_descriptor_header *) &gser_hs_in_desc,
232 (struct usb_descriptor_header *) &gser_hs_out_desc,
233 NULL,
234};
235
236/* string descriptors: */
237
238static struct usb_string gser_string_defs[] = {
239 [0].s = "Generic Serial",
240 { } /* end of list */
241};
242
243static struct usb_gadget_strings gser_string_table = {
244 .language = 0x0409, /* en-us */
245 .strings = gser_string_defs,
246};
247
248static struct usb_gadget_strings *gser_strings[] = {
249 &gser_string_table,
250 NULL,
251};
252
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700253static char *transport_to_str(enum transport_type t)
254{
255 switch (t) {
256 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
257 return "TTY";
258 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
259 return "SDIO";
260 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
261 return "SMD";
262 }
263
264 return "NONE";
265}
266
Manu Gautama4d993f2011-08-30 18:25:55 +0530267static enum transport_type serial_str_to_transport(const char *name)
268{
269 if (!strcasecmp("SDIO", name))
270 return USB_GADGET_FSERIAL_TRANSPORT_SDIO;
271 if (!strcasecmp("SMD", name))
272 return USB_GADGET_FSERIAL_TRANSPORT_SMD;
273
274 return USB_GADGET_FSERIAL_TRANSPORT_TTY;
275}
276
277
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700278static int gport_setup(struct usb_configuration *c)
279{
280 int ret = 0;
281
282 pr_debug("%s: no_tty_ports:%u no_sdio_ports: %u nr_ports:%u\n",
283 __func__, no_tty_ports, no_sdio_ports, nr_ports);
284
285 if (no_tty_ports)
286 ret = gserial_setup(c->cdev->gadget, no_tty_ports);
287 if (no_sdio_ports)
288 ret = gsdio_setup(c->cdev->gadget, no_sdio_ports);
289 if (no_smd_ports)
290 ret = gsmd_setup(c->cdev->gadget, no_smd_ports);
291
292 return ret;
293}
Manu Gautama4d993f2011-08-30 18:25:55 +0530294
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295static int gport_connect(struct f_gser *gser)
296{
297 unsigned port_num;
298
299 pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
300 __func__, transport_to_str(gser->transport),
301 gser, &gser->port, gser->port_num);
302
303 port_num = gserial_ports[gser->port_num].client_port_num;
304
305 switch (gser->transport) {
306 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
307 gserial_connect(&gser->port, port_num);
308 break;
309 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
310 gsdio_connect(&gser->port, port_num);
311 break;
312 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
313 gsmd_connect(&gser->port, port_num);
314 break;
315 default:
316 pr_err("%s: Un-supported transport: %s\n", __func__,
317 transport_to_str(gser->transport));
318 return -ENODEV;
319 }
320
321 return 0;
322}
323
324static int gport_disconnect(struct f_gser *gser)
325{
326 unsigned port_num;
327
328 pr_debug("%s: transport:%s f_gser:%p gserial:%p port_num:%d\n",
329 __func__, transport_to_str(gser->transport),
330 gser, &gser->port, gser->port_num);
331
332 port_num = gserial_ports[gser->port_num].client_port_num;
333
334 switch (gser->transport) {
335 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
336 gserial_disconnect(&gser->port);
337 break;
338 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
339 gsdio_disconnect(&gser->port, port_num);
340 break;
341 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
342 gsmd_disconnect(&gser->port, port_num);
343 break;
344 default:
345 pr_err("%s: Un-supported transport:%s\n", __func__,
346 transport_to_str(gser->transport));
347 return -ENODEV;
348 }
349
350 return 0;
351}
352
353#ifdef CONFIG_MODEM_SUPPORT
354static void gser_complete_set_line_coding(struct usb_ep *ep,
355 struct usb_request *req)
356{
357 struct f_gser *gser = ep->driver_data;
358 struct usb_composite_dev *cdev = gser->port.func.config->cdev;
359
360 if (req->status != 0) {
361 DBG(cdev, "gser ttyGS%d completion, err %d\n",
362 gser->port_num, req->status);
363 return;
364 }
365
366 /* normal completion */
367 if (req->actual != sizeof(gser->port_line_coding)) {
368 DBG(cdev, "gser ttyGS%d short resp, len %d\n",
369 gser->port_num, req->actual);
370 usb_ep_set_halt(ep);
371 } else {
372 struct usb_cdc_line_coding *value = req->buf;
373 gser->port_line_coding = *value;
374 }
375}
David Brownell61d8bae2008-06-19 18:18:50 -0700376/*-------------------------------------------------------------------------*/
377
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378static int
379gser_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
380{
381 struct f_gser *gser = func_to_gser(f);
382 struct usb_composite_dev *cdev = f->config->cdev;
383 struct usb_request *req = cdev->req;
384 int value = -EOPNOTSUPP;
385 u16 w_index = le16_to_cpu(ctrl->wIndex);
386 u16 w_value = le16_to_cpu(ctrl->wValue);
387 u16 w_length = le16_to_cpu(ctrl->wLength);
388
389 switch ((ctrl->bRequestType << 8) | ctrl->bRequest) {
390
391 /* SET_LINE_CODING ... just read and save what the host sends */
392 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
393 | USB_CDC_REQ_SET_LINE_CODING:
394 if (w_length != sizeof(struct usb_cdc_line_coding))
395 goto invalid;
396
397 value = w_length;
398 cdev->gadget->ep0->driver_data = gser;
399 req->complete = gser_complete_set_line_coding;
400 break;
401
402 /* GET_LINE_CODING ... return what host sent, or initial value */
403 case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
404 | USB_CDC_REQ_GET_LINE_CODING:
405 value = min_t(unsigned, w_length,
406 sizeof(struct usb_cdc_line_coding));
407 memcpy(req->buf, &gser->port_line_coding, value);
408 break;
409
410 /* SET_CONTROL_LINE_STATE ... save what the host sent */
411 case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
412 | USB_CDC_REQ_SET_CONTROL_LINE_STATE:
413
414 value = 0;
415 gser->port_handshake_bits = w_value;
416 if (gser->port.notify_modem) {
417 unsigned port_num =
418 gserial_ports[gser->port_num].client_port_num;
419
420 gser->port.notify_modem(&gser->port,
421 port_num, w_value);
422 }
423 break;
424
425 default:
426invalid:
427 DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n",
428 ctrl->bRequestType, ctrl->bRequest,
429 w_value, w_index, w_length);
430 }
431
432 /* respond with data transfer or status phase? */
433 if (value >= 0) {
434 DBG(cdev, "gser ttyGS%d req%02x.%02x v%04x i%04x l%d\n",
435 gser->port_num, ctrl->bRequestType, ctrl->bRequest,
436 w_value, w_index, w_length);
437 req->zero = 0;
438 req->length = value;
439 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
440 if (value < 0)
441 ERROR(cdev, "gser response on ttyGS%d, err %d\n",
442 gser->port_num, value);
443 }
444
445 /* device either stalls (value < 0) or reports success */
446 return value;
447}
448#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700449static int gser_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
450{
451 struct f_gser *gser = func_to_gser(f);
452 struct usb_composite_dev *cdev = f->config->cdev;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 int rc = 0;
David Brownell61d8bae2008-06-19 18:18:50 -0700454
455 /* we know alt == 0, so this is an activation or a reset */
456
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700457#ifdef CONFIG_MODEM_SUPPORT
458 if (gser->notify->driver_data) {
459 DBG(cdev, "reset generic ctl ttyGS%d\n", gser->port_num);
460 usb_ep_disable(gser->notify);
David Brownell61d8bae2008-06-19 18:18:50 -0700461 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700462 gser->notify_desc = ep_choose(cdev->gadget,
463 gser->hs.notify,
464 gser->fs.notify);
465 rc = usb_ep_enable(gser->notify, gser->notify_desc);
466 if (rc) {
467 ERROR(cdev, "can't enable %s, result %d\n",
468 gser->notify->name, rc);
469 return rc;
470 }
471 gser->notify->driver_data = gser;
472#endif
473
474 if (gser->port.in->driver_data) {
475 DBG(cdev, "reset generic data ttyGS%d\n", gser->port_num);
476 gport_disconnect(gser);
477 } else {
478 DBG(cdev, "activate generic data ttyGS%d\n", gser->port_num);
479 }
480 gser->port.in_desc = ep_choose(cdev->gadget,
481 gser->hs.in, gser->fs.in);
482 gser->port.out_desc = ep_choose(cdev->gadget,
483 gser->hs.out, gser->fs.out);
484
485 gport_connect(gser);
486
487 gser->online = 1;
488 return rc;
David Brownell61d8bae2008-06-19 18:18:50 -0700489}
490
491static void gser_disable(struct usb_function *f)
492{
493 struct f_gser *gser = func_to_gser(f);
494 struct usb_composite_dev *cdev = f->config->cdev;
495
496 DBG(cdev, "generic ttyGS%d deactivated\n", gser->port_num);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497
498 gport_disconnect(gser);
499
500#ifdef CONFIG_MODEM_SUPPORT
501 usb_ep_fifo_flush(gser->notify);
502 usb_ep_disable(gser->notify);
503#endif
504 gser->online = 0;
505}
506#ifdef CONFIG_MODEM_SUPPORT
507static int gser_notify(struct f_gser *gser, u8 type, u16 value,
508 void *data, unsigned length)
509{
510 struct usb_ep *ep = gser->notify;
511 struct usb_request *req;
512 struct usb_cdc_notification *notify;
513 const unsigned len = sizeof(*notify) + length;
514 void *buf;
515 int status;
516 struct usb_composite_dev *cdev = gser->port.func.config->cdev;
517
518 req = gser->notify_req;
519 gser->notify_req = NULL;
520 gser->pending = false;
521
522 req->length = len;
523 notify = req->buf;
524 buf = notify + 1;
525
526 notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS
527 | USB_RECIP_INTERFACE;
528 notify->bNotificationType = type;
529 notify->wValue = cpu_to_le16(value);
530 notify->wIndex = cpu_to_le16(gser->data_id);
531 notify->wLength = cpu_to_le16(length);
532 memcpy(buf, data, length);
533
534 status = usb_ep_queue(ep, req, GFP_ATOMIC);
535 if (status < 0) {
536 ERROR(cdev, "gser ttyGS%d can't notify serial state, %d\n",
537 gser->port_num, status);
538 gser->notify_req = req;
539 }
540
541 return status;
David Brownell61d8bae2008-06-19 18:18:50 -0700542}
543
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700544static int gser_notify_serial_state(struct f_gser *gser)
545{
546 int status;
547 unsigned long flags;
548 struct usb_composite_dev *cdev = gser->port.func.config->cdev;
549
550 spin_lock_irqsave(&gser->lock, flags);
551 if (gser->notify_req) {
552 DBG(cdev, "gser ttyGS%d serial state %04x\n",
553 gser->port_num, gser->serial_state);
554 status = gser_notify(gser, USB_CDC_NOTIFY_SERIAL_STATE,
555 0, &gser->serial_state,
556 sizeof(gser->serial_state));
557 } else {
558 gser->pending = true;
559 status = 0;
560 }
561 spin_unlock_irqrestore(&gser->lock, flags);
562 return status;
563}
564
565static void gser_notify_complete(struct usb_ep *ep, struct usb_request *req)
566{
567 struct f_gser *gser = req->context;
568 u8 doit = false;
569 unsigned long flags;
570
571 /* on this call path we do NOT hold the port spinlock,
572 * which is why ACM needs its own spinlock
573 */
574 spin_lock_irqsave(&gser->lock, flags);
575 if (req->status != -ESHUTDOWN)
576 doit = gser->pending;
577 gser->notify_req = req;
578 spin_unlock_irqrestore(&gser->lock, flags);
579
580 if (doit && gser->online)
581 gser_notify_serial_state(gser);
582}
583static void gser_connect(struct gserial *port)
584{
585 struct f_gser *gser = port_to_gser(port);
586
587 gser->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD;
588 gser_notify_serial_state(gser);
589}
590
591unsigned int gser_get_dtr(struct gserial *port)
592{
593 struct f_gser *gser = port_to_gser(port);
594
595 if (gser->port_handshake_bits & ACM_CTRL_DTR)
596 return 1;
597 else
598 return 0;
599}
600
601unsigned int gser_get_rts(struct gserial *port)
602{
603 struct f_gser *gser = port_to_gser(port);
604
605 if (gser->port_handshake_bits & ACM_CTRL_RTS)
606 return 1;
607 else
608 return 0;
609}
610
611unsigned int gser_send_carrier_detect(struct gserial *port, unsigned int yes)
612{
613 struct f_gser *gser = port_to_gser(port);
614 u16 state;
615
616 state = gser->serial_state;
617 state &= ~ACM_CTRL_DCD;
618 if (yes)
619 state |= ACM_CTRL_DCD;
620
621 gser->serial_state = state;
622 return gser_notify_serial_state(gser);
623
624}
625
626unsigned int gser_send_ring_indicator(struct gserial *port, unsigned int yes)
627{
628 struct f_gser *gser = port_to_gser(port);
629 u16 state;
630
631 state = gser->serial_state;
632 state &= ~ACM_CTRL_RI;
633 if (yes)
634 state |= ACM_CTRL_RI;
635
636 gser->serial_state = state;
637 return gser_notify_serial_state(gser);
638
639}
640static void gser_disconnect(struct gserial *port)
641{
642 struct f_gser *gser = port_to_gser(port);
643
644 gser->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD);
645 gser_notify_serial_state(gser);
646}
647
648static int gser_send_break(struct gserial *port, int duration)
649{
650 struct f_gser *gser = port_to_gser(port);
651 u16 state;
652
653 state = gser->serial_state;
654 state &= ~ACM_CTRL_BRK;
655 if (duration)
656 state |= ACM_CTRL_BRK;
657
658 gser->serial_state = state;
659 return gser_notify_serial_state(gser);
660}
661
662static int gser_send_modem_ctrl_bits(struct gserial *port, int ctrl_bits)
663{
664 struct f_gser *gser = port_to_gser(port);
665
666 gser->serial_state = ctrl_bits;
667
668 return gser_notify_serial_state(gser);
669}
670#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700671/*-------------------------------------------------------------------------*/
672
673/* serial function driver setup/binding */
674
Manu Gautama4d993f2011-08-30 18:25:55 +0530675static int
David Brownell61d8bae2008-06-19 18:18:50 -0700676gser_bind(struct usb_configuration *c, struct usb_function *f)
677{
678 struct usb_composite_dev *cdev = c->cdev;
679 struct f_gser *gser = func_to_gser(f);
680 int status;
681 struct usb_ep *ep;
682
683 /* allocate instance-specific interface IDs */
684 status = usb_interface_id(c, f);
685 if (status < 0)
686 goto fail;
687 gser->data_id = status;
688 gser_interface_desc.bInterfaceNumber = status;
689
690 status = -ENODEV;
691
692 /* allocate instance-specific endpoints */
693 ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_in_desc);
694 if (!ep)
695 goto fail;
696 gser->port.in = ep;
697 ep->driver_data = cdev; /* claim */
698
699 ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_out_desc);
700 if (!ep)
701 goto fail;
702 gser->port.out = ep;
703 ep->driver_data = cdev; /* claim */
704
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700705#ifdef CONFIG_MODEM_SUPPORT
706 ep = usb_ep_autoconfig(cdev->gadget, &gser_fs_notify_desc);
707 if (!ep)
708 goto fail;
709 gser->notify = ep;
710 ep->driver_data = cdev; /* claim */
711 /* allocate notification */
712 gser->notify_req = gs_alloc_req(ep,
713 sizeof(struct usb_cdc_notification) + 2,
714 GFP_KERNEL);
715 if (!gser->notify_req)
716 goto fail;
717
718 gser->notify_req->complete = gser_notify_complete;
719 gser->notify_req->context = gser;
720#endif
721
David Brownell61d8bae2008-06-19 18:18:50 -0700722 /* copy descriptors, and track endpoint copies */
723 f->descriptors = usb_copy_descriptors(gser_fs_function);
724
Pavankumar Kondetif0f95d82011-09-23 11:38:57 +0530725 if (!f->descriptors)
726 goto fail;
727
David Brownell61d8bae2008-06-19 18:18:50 -0700728 gser->fs.in = usb_find_endpoint(gser_fs_function,
729 f->descriptors, &gser_fs_in_desc);
730 gser->fs.out = usb_find_endpoint(gser_fs_function,
731 f->descriptors, &gser_fs_out_desc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700732#ifdef CONFIG_MODEM_SUPPORT
733 gser->fs.notify = usb_find_endpoint(gser_fs_function,
734 f->descriptors, &gser_fs_notify_desc);
735#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700736
737
738 /* support all relevant hardware speeds... we expect that when
739 * hardware is dual speed, all bulk-capable endpoints work at
740 * both speeds
741 */
742 if (gadget_is_dualspeed(c->cdev->gadget)) {
743 gser_hs_in_desc.bEndpointAddress =
744 gser_fs_in_desc.bEndpointAddress;
745 gser_hs_out_desc.bEndpointAddress =
746 gser_fs_out_desc.bEndpointAddress;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700747#ifdef CONFIG_MODEM_SUPPORT
748 gser_hs_notify_desc.bEndpointAddress =
749 gser_fs_notify_desc.bEndpointAddress;
750#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700751
752 /* copy descriptors, and track endpoint copies */
753 f->hs_descriptors = usb_copy_descriptors(gser_hs_function);
754
Pavankumar Kondetif0f95d82011-09-23 11:38:57 +0530755 if (!f->hs_descriptors)
756 goto fail;
757
David Brownell61d8bae2008-06-19 18:18:50 -0700758 gser->hs.in = usb_find_endpoint(gser_hs_function,
759 f->hs_descriptors, &gser_hs_in_desc);
760 gser->hs.out = usb_find_endpoint(gser_hs_function,
761 f->hs_descriptors, &gser_hs_out_desc);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700762#ifdef CONFIG_MODEM_SUPPORT
763 gser->hs.notify = usb_find_endpoint(gser_hs_function,
764 f->hs_descriptors, &gser_hs_notify_desc);
765#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700766 }
767
768 DBG(cdev, "generic ttyGS%d: %s speed IN/%s OUT/%s\n",
769 gser->port_num,
770 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
771 gser->port.in->name, gser->port.out->name);
772 return 0;
773
774fail:
Pavankumar Kondetif0f95d82011-09-23 11:38:57 +0530775 if (f->descriptors)
776 usb_free_descriptors(f->descriptors);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777#ifdef CONFIG_MODEM_SUPPORT
778 if (gser->notify_req)
779 gs_free_req(gser->notify, gser->notify_req);
780
781 /* we might as well release our claims on endpoints */
782 if (gser->notify)
783 gser->notify->driver_data = NULL;
784#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700785 /* we might as well release our claims on endpoints */
786 if (gser->port.out)
787 gser->port.out->driver_data = NULL;
788 if (gser->port.in)
789 gser->port.in->driver_data = NULL;
790
791 ERROR(cdev, "%s: can't bind, err %d\n", f->name, status);
792
793 return status;
794}
795
796static void
797gser_unbind(struct usb_configuration *c, struct usb_function *f)
798{
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700799#ifdef CONFIG_MODEM_SUPPORT
800 struct f_gser *gser = func_to_gser(f);
801#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700802 if (gadget_is_dualspeed(c->cdev->gadget))
803 usb_free_descriptors(f->hs_descriptors);
804 usb_free_descriptors(f->descriptors);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805#ifdef CONFIG_MODEM_SUPPORT
806 gs_free_req(gser->notify, gser->notify_req);
807#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700808 kfree(func_to_gser(f));
809}
810
811/**
812 * gser_bind_config - add a generic serial function to a configuration
813 * @c: the configuration to support the serial instance
814 * @port_num: /dev/ttyGS* port this interface will use
815 * Context: single threaded during gadget setup
816 *
817 * Returns zero on success, else negative errno.
818 *
819 * Caller must have called @gserial_setup() with enough ports to
820 * handle all the ones it binds. Caller is also responsible
821 * for calling @gserial_cleanup() before module unload.
822 */
Manu Gautama4d993f2011-08-30 18:25:55 +0530823int gser_bind_config(struct usb_configuration *c, u8 port_num)
David Brownell61d8bae2008-06-19 18:18:50 -0700824{
825 struct f_gser *gser;
826 int status;
827
828 /* REVISIT might want instance-specific strings to help
829 * distinguish instances ...
830 */
831
832 /* maybe allocate device-global string ID */
833 if (gser_string_defs[0].id == 0) {
834 status = usb_string_id(c->cdev);
835 if (status < 0)
836 return status;
837 gser_string_defs[0].id = status;
838 }
839
840 /* allocate and initialize one new instance */
841 gser = kzalloc(sizeof *gser, GFP_KERNEL);
842 if (!gser)
843 return -ENOMEM;
844
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700845#ifdef CONFIG_MODEM_SUPPORT
846 spin_lock_init(&gser->lock);
847#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700848 gser->port_num = port_num;
849
850 gser->port.func.name = "gser";
851 gser->port.func.strings = gser_strings;
852 gser->port.func.bind = gser_bind;
853 gser->port.func.unbind = gser_unbind;
854 gser->port.func.set_alt = gser_set_alt;
855 gser->port.func.disable = gser_disable;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700856 gser->transport = gserial_ports[port_num].transport;
857#ifdef CONFIG_MODEM_SUPPORT
858 /* We support only two ports for now */
859 if (port_num == 0)
860 gser->port.func.name = "modem";
861 else
862 gser->port.func.name = "nmea";
863 gser->port.func.setup = gser_setup;
864 gser->port.connect = gser_connect;
865 gser->port.get_dtr = gser_get_dtr;
866 gser->port.get_rts = gser_get_rts;
867 gser->port.send_carrier_detect = gser_send_carrier_detect;
868 gser->port.send_ring_indicator = gser_send_ring_indicator;
869 gser->port.send_modem_ctrl_bits = gser_send_modem_ctrl_bits;
870 gser->port.disconnect = gser_disconnect;
871 gser->port.send_break = gser_send_break;
872#endif
David Brownell61d8bae2008-06-19 18:18:50 -0700873
874 status = usb_add_function(c, &gser->port.func);
875 if (status)
876 kfree(gser);
877 return status;
878}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700879
Manu Gautama4d993f2011-08-30 18:25:55 +0530880/**
881 * gserial_init_port - bind a gserial_port to its transport
882 */
883static int gserial_init_port(int port_num, const char *name)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700884{
Manu Gautama4d993f2011-08-30 18:25:55 +0530885 enum transport_type transport;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700886
Manu Gautama4d993f2011-08-30 18:25:55 +0530887 if (port_num >= GSERIAL_NO_PORTS)
888 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700889
Manu Gautama4d993f2011-08-30 18:25:55 +0530890 transport = serial_str_to_transport(name);
891 pr_debug("%s, port:%d, transport:%s\n", __func__,
892 port_num, transport_to_str(transport));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700893
Manu Gautama4d993f2011-08-30 18:25:55 +0530894 gserial_ports[port_num].transport = transport;
895 gserial_ports[port_num].port_num = port_num;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896
Manu Gautama4d993f2011-08-30 18:25:55 +0530897 switch (transport) {
898 case USB_GADGET_FSERIAL_TRANSPORT_TTY:
899 gserial_ports[port_num].client_port_num = no_tty_ports;
900 no_tty_ports++;
901 break;
902 case USB_GADGET_FSERIAL_TRANSPORT_SDIO:
903 gserial_ports[port_num].client_port_num = no_sdio_ports;
904 no_sdio_ports++;
905 break;
906 case USB_GADGET_FSERIAL_TRANSPORT_SMD:
907 gserial_ports[port_num].client_port_num = no_smd_ports;
908 no_smd_ports++;
909 break;
910 default:
911 pr_err("%s: Un-supported transport transport: %u\n",
912 __func__, gserial_ports[port_num].transport);
913 return -ENODEV;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700914 }
915
Manu Gautama4d993f2011-08-30 18:25:55 +0530916 nr_ports++;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700917
918 return 0;
919}