blob: 6143d1b8714be43520632f829a43577d624d786d [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2011, The Linux Foundation. All rights reserved.
Jack Pham427f6922011-11-23 19:42:00 -08002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include <linux/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/device.h>
16#include <linux/delay.h>
17#include <linux/slab.h>
18#include <linux/termios.h>
19#include <linux/debugfs.h>
20#include <linux/bitops.h>
21#include <linux/termios.h>
22#include <mach/usb_bridge.h>
23#include <mach/usb_gadget_xport.h>
24
25/* from cdc-acm.h */
26#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */
27#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */
28#define ACM_CTRL_OVERRUN (1 << 6)
29#define ACM_CTRL_PARITY (1 << 5)
30#define ACM_CTRL_FRAMING (1 << 4)
31#define ACM_CTRL_RI (1 << 3)
32#define ACM_CTRL_BRK (1 << 2)
33#define ACM_CTRL_DSR (1 << 1)
34#define ACM_CTRL_DCD (1 << 0)
35
36
37static unsigned int no_ctrl_ports;
38
Jack Pham427f6922011-11-23 19:42:00 -080039#define READ_BUF_LEN 1024
40
41#define CH_OPENED 0
42#define CH_READY 1
43
44struct gctrl_port {
45 /* port */
46 unsigned port_num;
47
48 /* gadget */
49 spinlock_t port_lock;
50 void *port_usb;
51
52 /* work queue*/
53 struct workqueue_struct *wq;
54 struct work_struct connect_w;
55 struct work_struct disconnect_w;
56
57 enum gadget_type gtype;
58
59 /*ctrl pkt response cb*/
60 int (*send_cpkt_response)(void *g, void *buf, size_t len);
61
62 struct bridge brdg;
63
64 /* bridge status */
65 unsigned long bridge_sts;
66
67 /* control bits */
68 unsigned cbits_tomodem;
69 unsigned cbits_tohost;
70
71 /* counters */
72 unsigned long to_modem;
73 unsigned long to_host;
74 unsigned long drp_cpkt_cnt;
75};
76
77static struct {
78 struct gctrl_port *port;
79 struct platform_driver pdrv;
Hemant Kumarc2b17782013-02-03 15:56:29 -080080 char port_name[BRIDGE_NAME_MAX_LEN];
Jack Pham427f6922011-11-23 19:42:00 -080081} gctrl_ports[NUM_PORTS];
82
83static int ghsic_ctrl_receive(void *dev, void *buf, size_t actual)
84{
85 struct gctrl_port *port = dev;
86 int retval = 0;
87
88 pr_debug_ratelimited("%s: read complete bytes read: %d\n",
89 __func__, actual);
90
91 /* send it to USB here */
92 if (port && port->send_cpkt_response) {
93 retval = port->send_cpkt_response(port->port_usb, buf, actual);
94 port->to_host++;
95 }
96
97 return retval;
98}
99
100static int
101ghsic_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
102{
103 void *cbuf;
104 struct gctrl_port *port;
105
106 if (portno >= no_ctrl_ports) {
107 pr_err("%s: Invalid portno#%d\n", __func__, portno);
108 return -ENODEV;
109 }
110
111 port = gctrl_ports[portno].port;
112 if (!port) {
113 pr_err("%s: port is null\n", __func__);
114 return -ENODEV;
115 }
116
117 cbuf = kmalloc(len, GFP_ATOMIC);
118 if (!cbuf)
119 return -ENOMEM;
120
121 memcpy(cbuf, buf, len);
122
123 /* drop cpkt if ch is not open */
124 if (!test_bit(CH_OPENED, &port->bridge_sts)) {
125 port->drp_cpkt_cnt++;
126 kfree(cbuf);
127 return 0;
128 }
129
130 pr_debug("%s: ctrl_pkt:%d bytes\n", __func__, len);
131
132 ctrl_bridge_write(port->brdg.ch_id, cbuf, len);
133
134 port->to_modem++;
135
136 return 0;
137}
138
139static void
140ghsic_send_cbits_tomodem(void *gptr, u8 portno, int cbits)
141{
142 struct gctrl_port *port;
143
144 if (portno >= no_ctrl_ports || !gptr) {
145 pr_err("%s: Invalid portno#%d\n", __func__, portno);
146 return;
147 }
148
149 port = gctrl_ports[portno].port;
150 if (!port) {
151 pr_err("%s: port is null\n", __func__);
152 return;
153 }
154
155 if (cbits == port->cbits_tomodem)
156 return;
157
158 port->cbits_tomodem = cbits;
159
160 if (!test_bit(CH_OPENED, &port->bridge_sts))
161 return;
162
163 pr_debug("%s: ctrl_tomodem:%d\n", __func__, cbits);
164
165 ctrl_bridge_set_cbits(port->brdg.ch_id, cbits);
166}
167
168static void ghsic_ctrl_connect_w(struct work_struct *w)
169{
170 struct gserial *gser = NULL;
171 struct grmnet *gr = NULL;
172 struct gctrl_port *port =
173 container_of(w, struct gctrl_port, connect_w);
174 unsigned long flags;
175 int retval;
176 unsigned cbits;
177
178 if (!port || !test_bit(CH_READY, &port->bridge_sts))
179 return;
180
181 pr_debug("%s: port:%p\n", __func__, port);
182
183 retval = ctrl_bridge_open(&port->brdg);
184 if (retval) {
185 pr_err("%s: ctrl bridge open failed :%d\n", __func__, retval);
186 return;
187 }
188
189 spin_lock_irqsave(&port->port_lock, flags);
190 if (!port->port_usb) {
191 ctrl_bridge_close(port->brdg.ch_id);
192 spin_unlock_irqrestore(&port->port_lock, flags);
193 return;
194 }
195 set_bit(CH_OPENED, &port->bridge_sts);
196 spin_unlock_irqrestore(&port->port_lock, flags);
197
198 cbits = ctrl_bridge_get_cbits_tohost(port->brdg.ch_id);
199
200 if (port->gtype == USB_GADGET_SERIAL && (cbits & ACM_CTRL_DCD)) {
201 gser = port->port_usb;
202 if (gser && gser->connect)
203 gser->connect(gser);
204 return;
205 }
206
207 if (port->gtype == USB_GADGET_RMNET) {
208 gr = port->port_usb;
209 if (gr && gr->connect)
210 gr->connect(gr);
211 }
212}
213
214int ghsic_ctrl_connect(void *gptr, int port_num)
215{
216 struct gctrl_port *port;
217 struct gserial *gser;
218 struct grmnet *gr;
219 unsigned long flags;
220
221 pr_debug("%s: port#%d\n", __func__, port_num);
222
223 if (port_num > no_ctrl_ports || !gptr) {
224 pr_err("%s: invalid portno#%d\n", __func__, port_num);
225 return -ENODEV;
226 }
227
228 port = gctrl_ports[port_num].port;
229 if (!port) {
230 pr_err("%s: port is null\n", __func__);
231 return -ENODEV;
232 }
233
234 spin_lock_irqsave(&port->port_lock, flags);
235 if (port->gtype == USB_GADGET_SERIAL) {
236 gser = gptr;
237 gser->notify_modem = ghsic_send_cbits_tomodem;
238 }
239
240 if (port->gtype == USB_GADGET_RMNET) {
241 gr = gptr;
242 port->send_cpkt_response = gr->send_cpkt_response;
243 gr->send_encap_cmd = ghsic_send_cpkt_tomodem;
244 gr->notify_modem = ghsic_send_cbits_tomodem;
245 }
246
247 port->port_usb = gptr;
248 port->to_host = 0;
249 port->to_modem = 0;
250 port->drp_cpkt_cnt = 0;
251 spin_unlock_irqrestore(&port->port_lock, flags);
252
253 queue_work(port->wq, &port->connect_w);
254
255 return 0;
256}
257
258static void gctrl_disconnect_w(struct work_struct *w)
259{
260 struct gctrl_port *port =
261 container_of(w, struct gctrl_port, disconnect_w);
262
263 if (!test_bit(CH_OPENED, &port->bridge_sts))
264 return;
265
266 /* send the dtr zero */
267 ctrl_bridge_close(port->brdg.ch_id);
268 clear_bit(CH_OPENED, &port->bridge_sts);
269}
270
271void ghsic_ctrl_disconnect(void *gptr, int port_num)
272{
273 struct gctrl_port *port;
274 struct gserial *gser = NULL;
275 struct grmnet *gr = NULL;
276 unsigned long flags;
277
278 pr_debug("%s: port#%d\n", __func__, port_num);
279
280 port = gctrl_ports[port_num].port;
281
282 if (port_num > no_ctrl_ports) {
283 pr_err("%s: invalid portno#%d\n", __func__, port_num);
284 return;
285 }
286
287 if (!gptr || !port) {
288 pr_err("%s: grmnet port is null\n", __func__);
289 return;
290 }
291
292 if (port->gtype == USB_GADGET_SERIAL)
293 gser = gptr;
294 else
295 gr = gptr;
296
297 spin_lock_irqsave(&port->port_lock, flags);
298 if (gr) {
299 gr->send_encap_cmd = 0;
300 gr->notify_modem = 0;
301 }
302
303 if (gser)
304 gser->notify_modem = 0;
305 port->cbits_tomodem = 0;
306 port->port_usb = 0;
307 port->send_cpkt_response = 0;
308 spin_unlock_irqrestore(&port->port_lock, flags);
309
310 queue_work(port->wq, &port->disconnect_w);
311}
312
313static void ghsic_ctrl_status(void *ctxt, unsigned int ctrl_bits)
314{
315 struct gctrl_port *port = ctxt;
316 struct gserial *gser;
317
318 pr_debug("%s - input control lines: dcd%c dsr%c break%c "
319 "ring%c framing%c parity%c overrun%c\n", __func__,
320 ctrl_bits & ACM_CTRL_DCD ? '+' : '-',
321 ctrl_bits & ACM_CTRL_DSR ? '+' : '-',
322 ctrl_bits & ACM_CTRL_BRK ? '+' : '-',
323 ctrl_bits & ACM_CTRL_RI ? '+' : '-',
324 ctrl_bits & ACM_CTRL_FRAMING ? '+' : '-',
325 ctrl_bits & ACM_CTRL_PARITY ? '+' : '-',
326 ctrl_bits & ACM_CTRL_OVERRUN ? '+' : '-');
327
328 port->cbits_tohost = ctrl_bits;
329 gser = port->port_usb;
330 if (gser && gser->send_modem_ctrl_bits)
331 gser->send_modem_ctrl_bits(gser, ctrl_bits);
332}
333
Hemant Kumarc2b17782013-02-03 15:56:29 -0800334static int ghsic_ctrl_get_port_id(const char *pdev_name)
335{
336 struct gctrl_port *port;
337 int i;
338
339 for (i = 0; i < no_ctrl_ports; i++) {
340 port = gctrl_ports[i].port;
341 if (!strncmp(port->brdg.name, pdev_name, BRIDGE_NAME_MAX_LEN))
342 return i;
343 }
344
345 return -EINVAL;
346}
347
Jack Pham427f6922011-11-23 19:42:00 -0800348static int ghsic_ctrl_probe(struct platform_device *pdev)
349{
350 struct gctrl_port *port;
351 unsigned long flags;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800352 int id;
Jack Pham427f6922011-11-23 19:42:00 -0800353
354 pr_debug("%s: name:%s\n", __func__, pdev->name);
355
Hemant Kumarc2b17782013-02-03 15:56:29 -0800356 id = ghsic_ctrl_get_port_id(pdev->name);
357 if (id < 0 || id >= no_ctrl_ports) {
358 pr_err("%s: invalid port: %d\n", __func__, id);
Jack Pham427f6922011-11-23 19:42:00 -0800359 return -EINVAL;
360 }
361
Hemant Kumarc2b17782013-02-03 15:56:29 -0800362 port = gctrl_ports[id].port;
Jack Pham427f6922011-11-23 19:42:00 -0800363 set_bit(CH_READY, &port->bridge_sts);
364
365 /* if usb is online, start read */
366 spin_lock_irqsave(&port->port_lock, flags);
367 if (port->port_usb)
368 queue_work(port->wq, &port->connect_w);
369 spin_unlock_irqrestore(&port->port_lock, flags);
370
371 return 0;
372}
373
374static int ghsic_ctrl_remove(struct platform_device *pdev)
375{
376 struct gctrl_port *port;
377 struct gserial *gser = NULL;
378 struct grmnet *gr = NULL;
379 unsigned long flags;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800380 int id;
Jack Pham427f6922011-11-23 19:42:00 -0800381
382 pr_debug("%s: name:%s\n", __func__, pdev->name);
383
Hemant Kumarc2b17782013-02-03 15:56:29 -0800384 id = ghsic_ctrl_get_port_id(pdev->name);
385 if (id < 0 || id >= no_ctrl_ports) {
386 pr_err("%s: invalid port: %d\n", __func__, id);
Jack Pham427f6922011-11-23 19:42:00 -0800387 return -EINVAL;
388 }
389
Hemant Kumarc2b17782013-02-03 15:56:29 -0800390 port = gctrl_ports[id].port;
Jack Pham427f6922011-11-23 19:42:00 -0800391
392 spin_lock_irqsave(&port->port_lock, flags);
393 if (!port->port_usb) {
394 spin_unlock_irqrestore(&port->port_lock, flags);
395 goto not_ready;
396 }
397
398 if (port->gtype == USB_GADGET_SERIAL)
399 gser = port->port_usb;
400 else
401 gr = port->port_usb;
402
403 port->cbits_tohost = 0;
404 spin_unlock_irqrestore(&port->port_lock, flags);
405
406 if (gr && gr->disconnect)
407 gr->disconnect(gr);
408
409 if (gser && gser->disconnect)
410 gser->disconnect(gser);
411
412 ctrl_bridge_close(port->brdg.ch_id);
413
414 clear_bit(CH_OPENED, &port->bridge_sts);
415not_ready:
416 clear_bit(CH_READY, &port->bridge_sts);
417
418 return 0;
419}
420
421static void ghsic_ctrl_port_free(int portno)
422{
423 struct gctrl_port *port = gctrl_ports[portno].port;
424 struct platform_driver *pdrv = &gctrl_ports[portno].pdrv;
425
426 destroy_workqueue(port->wq);
427 kfree(port);
428
429 if (pdrv)
430 platform_driver_unregister(pdrv);
431}
432
433static int gctrl_port_alloc(int portno, enum gadget_type gtype)
434{
435 struct gctrl_port *port;
436 struct platform_driver *pdrv;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800437 char *name;
Jack Pham427f6922011-11-23 19:42:00 -0800438
439 port = kzalloc(sizeof(struct gctrl_port), GFP_KERNEL);
440 if (!port)
441 return -ENOMEM;
442
Hemant Kumarc2b17782013-02-03 15:56:29 -0800443 name = gctrl_ports[portno].port_name;
444
445 port->wq = create_singlethread_workqueue(name);
Jack Pham427f6922011-11-23 19:42:00 -0800446 if (!port->wq) {
Hemant Kumarc2b17782013-02-03 15:56:29 -0800447 pr_err("%s: Unable to create workqueue:%s\n", __func__, name);
Jack Pham427f6922011-11-23 19:42:00 -0800448 return -ENOMEM;
449 }
450
451 port->port_num = portno;
452 port->gtype = gtype;
453
454 spin_lock_init(&port->port_lock);
455
456 INIT_WORK(&port->connect_w, ghsic_ctrl_connect_w);
457 INIT_WORK(&port->disconnect_w, gctrl_disconnect_w);
458
Hemant Kumarc2b17782013-02-03 15:56:29 -0800459 port->brdg.name = name;
Jack Pham427f6922011-11-23 19:42:00 -0800460 port->brdg.ctx = port;
461 port->brdg.ops.send_pkt = ghsic_ctrl_receive;
462 if (port->gtype == USB_GADGET_SERIAL)
463 port->brdg.ops.send_cbits = ghsic_ctrl_status;
464 gctrl_ports[portno].port = port;
465
466 pdrv = &gctrl_ports[portno].pdrv;
467 pdrv->probe = ghsic_ctrl_probe;
468 pdrv->remove = ghsic_ctrl_remove;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800469 pdrv->driver.name = name;
Jack Pham427f6922011-11-23 19:42:00 -0800470 pdrv->driver.owner = THIS_MODULE;
471
472 platform_driver_register(pdrv);
473
474 pr_debug("%s: port:%p portno:%d\n", __func__, port, portno);
475
476 return 0;
477}
478
Hemant Kumarc2b17782013-02-03 15:56:29 -0800479/*portname will be used to find the bridge channel index*/
480void ghsic_ctrl_set_port_name(const char *name, const char *xport_type)
481{
482 static unsigned int port_num;
483
484 if (port_num >= NUM_PORTS) {
485 pr_err("%s: setting xport name for invalid port num %d\n",
486 __func__, port_num);
487 return;
488 }
489
490 /*if no xport name is passed set it to xport type e.g. hsic*/
491 if (!name)
492 strlcpy(gctrl_ports[port_num].port_name, xport_type,
493 BRIDGE_NAME_MAX_LEN);
494 else
495 strlcpy(gctrl_ports[port_num].port_name, name,
496 BRIDGE_NAME_MAX_LEN);
497
498 /*append _ctrl to get ctrl bridge name e.g. serial_hsic_ctrl*/
499 strlcat(gctrl_ports[port_num].port_name, "_ctrl", BRIDGE_NAME_MAX_LEN);
500
501 port_num++;
502}
503
Jack Pham427f6922011-11-23 19:42:00 -0800504int ghsic_ctrl_setup(unsigned int num_ports, enum gadget_type gtype)
505{
506 int first_port_id = no_ctrl_ports;
507 int total_num_ports = num_ports + no_ctrl_ports;
508 int i;
509 int ret = 0;
510
511 if (!num_ports || total_num_ports > NUM_PORTS) {
512 pr_err("%s: Invalid num of ports count:%d\n",
513 __func__, num_ports);
514 return -EINVAL;
515 }
516
517 pr_debug("%s: requested ports:%d\n", __func__, num_ports);
518
519 for (i = first_port_id; i < (first_port_id + num_ports); i++) {
520
521 /*probe can be called while port_alloc,so update no_ctrl_ports*/
522 no_ctrl_ports++;
523 ret = gctrl_port_alloc(i, gtype);
524 if (ret) {
525 no_ctrl_ports--;
526 pr_err("%s: Unable to alloc port:%d\n", __func__, i);
527 goto free_ports;
528 }
529 }
530
531 return first_port_id;
532
533free_ports:
534 for (i = first_port_id; i < no_ctrl_ports; i++)
535 ghsic_ctrl_port_free(i);
536 no_ctrl_ports = first_port_id;
537 return ret;
538}
539
540#if defined(CONFIG_DEBUG_FS)
541#define DEBUG_BUF_SIZE 1024
542static ssize_t gctrl_read_stats(struct file *file, char __user *ubuf,
543 size_t count, loff_t *ppos)
544{
545 struct gctrl_port *port;
546 struct platform_driver *pdrv;
547 char *buf;
548 unsigned long flags;
549 int ret;
550 int i;
551 int temp = 0;
552
553 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
554 if (!buf)
555 return -ENOMEM;
556
557 for (i = 0; i < no_ctrl_ports; i++) {
558 port = gctrl_ports[i].port;
559 if (!port)
560 continue;
561 pdrv = &gctrl_ports[i].pdrv;
562 spin_lock_irqsave(&port->port_lock, flags);
563
564 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
565 "\nName: %s\n"
566 "#PORT:%d port: %p\n"
567 "to_usbhost: %lu\n"
568 "to_modem: %lu\n"
569 "cpkt_drp_cnt: %lu\n"
570 "DTR: %s\n"
571 "ch_open: %d\n"
572 "ch_ready: %d\n",
573 pdrv->driver.name,
574 i, port,
575 port->to_host, port->to_modem,
576 port->drp_cpkt_cnt,
577 port->cbits_tomodem ? "HIGH" : "LOW",
578 test_bit(CH_OPENED, &port->bridge_sts),
579 test_bit(CH_READY, &port->bridge_sts));
580
581 spin_unlock_irqrestore(&port->port_lock, flags);
582 }
583
584 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
585
586 kfree(buf);
587
588 return ret;
589}
590
591static ssize_t gctrl_reset_stats(struct file *file,
592 const char __user *buf, size_t count, loff_t *ppos)
593{
594 struct gctrl_port *port;
595 int i;
596 unsigned long flags;
597
598 for (i = 0; i < no_ctrl_ports; i++) {
599 port = gctrl_ports[i].port;
600 if (!port)
601 continue;
602
603 spin_lock_irqsave(&port->port_lock, flags);
604 port->to_host = 0;
605 port->to_modem = 0;
606 port->drp_cpkt_cnt = 0;
607 spin_unlock_irqrestore(&port->port_lock, flags);
608 }
609 return count;
610}
611
612const struct file_operations gctrl_stats_ops = {
613 .read = gctrl_read_stats,
614 .write = gctrl_reset_stats,
615};
616
617struct dentry *gctrl_dent;
618struct dentry *gctrl_dfile;
619static void gctrl_debugfs_init(void)
620{
621 gctrl_dent = debugfs_create_dir("ghsic_ctrl_xport", 0);
622 if (IS_ERR(gctrl_dent))
623 return;
624
625 gctrl_dfile =
626 debugfs_create_file("status", 0444, gctrl_dent, 0,
627 &gctrl_stats_ops);
628 if (!gctrl_dfile || IS_ERR(gctrl_dfile))
629 debugfs_remove(gctrl_dent);
630}
631
632static void gctrl_debugfs_exit(void)
633{
634 debugfs_remove(gctrl_dfile);
635 debugfs_remove(gctrl_dent);
636}
637
638#else
639static void gctrl_debugfs_init(void) { }
640static void gctrl_debugfs_exit(void) { }
641#endif
642
643static int __init gctrl_init(void)
644{
645 gctrl_debugfs_init();
646
647 return 0;
648}
649module_init(gctrl_init);
650
651static void __exit gctrl_exit(void)
652{
653 gctrl_debugfs_exit();
654}
655module_exit(gctrl_exit);
656MODULE_DESCRIPTION("hsic control xport driver");
657MODULE_LICENSE("GPL v2");