blob: 0f93ad49ce4c29434c2e596ff36c6dedb3bb1d40 [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
39static const char *ctrl_bridge_names[] = {
40 "dun_ctrl_hsic0",
41 "rmnet_ctrl_hsic0"
42};
43
44#define CTRL_BRIDGE_NAME_MAX_LEN 20
45#define READ_BUF_LEN 1024
46
47#define CH_OPENED 0
48#define CH_READY 1
49
50struct gctrl_port {
51 /* port */
52 unsigned port_num;
53
54 /* gadget */
55 spinlock_t port_lock;
56 void *port_usb;
57
58 /* work queue*/
59 struct workqueue_struct *wq;
60 struct work_struct connect_w;
61 struct work_struct disconnect_w;
62
63 enum gadget_type gtype;
64
65 /*ctrl pkt response cb*/
66 int (*send_cpkt_response)(void *g, void *buf, size_t len);
67
68 struct bridge brdg;
69
70 /* bridge status */
71 unsigned long bridge_sts;
72
73 /* control bits */
74 unsigned cbits_tomodem;
75 unsigned cbits_tohost;
76
77 /* counters */
78 unsigned long to_modem;
79 unsigned long to_host;
80 unsigned long drp_cpkt_cnt;
81};
82
83static struct {
84 struct gctrl_port *port;
85 struct platform_driver pdrv;
86} gctrl_ports[NUM_PORTS];
87
88static int ghsic_ctrl_receive(void *dev, void *buf, size_t actual)
89{
90 struct gctrl_port *port = dev;
91 int retval = 0;
92
93 pr_debug_ratelimited("%s: read complete bytes read: %d\n",
94 __func__, actual);
95
96 /* send it to USB here */
97 if (port && port->send_cpkt_response) {
98 retval = port->send_cpkt_response(port->port_usb, buf, actual);
99 port->to_host++;
100 }
101
102 return retval;
103}
104
105static int
106ghsic_send_cpkt_tomodem(u8 portno, void *buf, size_t len)
107{
108 void *cbuf;
109 struct gctrl_port *port;
110
111 if (portno >= no_ctrl_ports) {
112 pr_err("%s: Invalid portno#%d\n", __func__, portno);
113 return -ENODEV;
114 }
115
116 port = gctrl_ports[portno].port;
117 if (!port) {
118 pr_err("%s: port is null\n", __func__);
119 return -ENODEV;
120 }
121
122 cbuf = kmalloc(len, GFP_ATOMIC);
123 if (!cbuf)
124 return -ENOMEM;
125
126 memcpy(cbuf, buf, len);
127
128 /* drop cpkt if ch is not open */
129 if (!test_bit(CH_OPENED, &port->bridge_sts)) {
130 port->drp_cpkt_cnt++;
131 kfree(cbuf);
132 return 0;
133 }
134
135 pr_debug("%s: ctrl_pkt:%d bytes\n", __func__, len);
136
137 ctrl_bridge_write(port->brdg.ch_id, cbuf, len);
138
139 port->to_modem++;
140
141 return 0;
142}
143
144static void
145ghsic_send_cbits_tomodem(void *gptr, u8 portno, int cbits)
146{
147 struct gctrl_port *port;
148
149 if (portno >= no_ctrl_ports || !gptr) {
150 pr_err("%s: Invalid portno#%d\n", __func__, portno);
151 return;
152 }
153
154 port = gctrl_ports[portno].port;
155 if (!port) {
156 pr_err("%s: port is null\n", __func__);
157 return;
158 }
159
160 if (cbits == port->cbits_tomodem)
161 return;
162
163 port->cbits_tomodem = cbits;
164
165 if (!test_bit(CH_OPENED, &port->bridge_sts))
166 return;
167
168 pr_debug("%s: ctrl_tomodem:%d\n", __func__, cbits);
169
170 ctrl_bridge_set_cbits(port->brdg.ch_id, cbits);
171}
172
173static void ghsic_ctrl_connect_w(struct work_struct *w)
174{
175 struct gserial *gser = NULL;
176 struct grmnet *gr = NULL;
177 struct gctrl_port *port =
178 container_of(w, struct gctrl_port, connect_w);
179 unsigned long flags;
180 int retval;
181 unsigned cbits;
182
183 if (!port || !test_bit(CH_READY, &port->bridge_sts))
184 return;
185
186 pr_debug("%s: port:%p\n", __func__, port);
187
188 retval = ctrl_bridge_open(&port->brdg);
189 if (retval) {
190 pr_err("%s: ctrl bridge open failed :%d\n", __func__, retval);
191 return;
192 }
193
194 spin_lock_irqsave(&port->port_lock, flags);
195 if (!port->port_usb) {
196 ctrl_bridge_close(port->brdg.ch_id);
197 spin_unlock_irqrestore(&port->port_lock, flags);
198 return;
199 }
200 set_bit(CH_OPENED, &port->bridge_sts);
201 spin_unlock_irqrestore(&port->port_lock, flags);
202
203 cbits = ctrl_bridge_get_cbits_tohost(port->brdg.ch_id);
204
205 if (port->gtype == USB_GADGET_SERIAL && (cbits & ACM_CTRL_DCD)) {
206 gser = port->port_usb;
207 if (gser && gser->connect)
208 gser->connect(gser);
209 return;
210 }
211
212 if (port->gtype == USB_GADGET_RMNET) {
213 gr = port->port_usb;
214 if (gr && gr->connect)
215 gr->connect(gr);
216 }
217}
218
219int ghsic_ctrl_connect(void *gptr, int port_num)
220{
221 struct gctrl_port *port;
222 struct gserial *gser;
223 struct grmnet *gr;
224 unsigned long flags;
225
226 pr_debug("%s: port#%d\n", __func__, port_num);
227
228 if (port_num > no_ctrl_ports || !gptr) {
229 pr_err("%s: invalid portno#%d\n", __func__, port_num);
230 return -ENODEV;
231 }
232
233 port = gctrl_ports[port_num].port;
234 if (!port) {
235 pr_err("%s: port is null\n", __func__);
236 return -ENODEV;
237 }
238
239 spin_lock_irqsave(&port->port_lock, flags);
240 if (port->gtype == USB_GADGET_SERIAL) {
241 gser = gptr;
242 gser->notify_modem = ghsic_send_cbits_tomodem;
243 }
244
245 if (port->gtype == USB_GADGET_RMNET) {
246 gr = gptr;
247 port->send_cpkt_response = gr->send_cpkt_response;
248 gr->send_encap_cmd = ghsic_send_cpkt_tomodem;
249 gr->notify_modem = ghsic_send_cbits_tomodem;
250 }
251
252 port->port_usb = gptr;
253 port->to_host = 0;
254 port->to_modem = 0;
255 port->drp_cpkt_cnt = 0;
256 spin_unlock_irqrestore(&port->port_lock, flags);
257
258 queue_work(port->wq, &port->connect_w);
259
260 return 0;
261}
262
263static void gctrl_disconnect_w(struct work_struct *w)
264{
265 struct gctrl_port *port =
266 container_of(w, struct gctrl_port, disconnect_w);
267
268 if (!test_bit(CH_OPENED, &port->bridge_sts))
269 return;
270
271 /* send the dtr zero */
272 ctrl_bridge_close(port->brdg.ch_id);
273 clear_bit(CH_OPENED, &port->bridge_sts);
274}
275
276void ghsic_ctrl_disconnect(void *gptr, int port_num)
277{
278 struct gctrl_port *port;
279 struct gserial *gser = NULL;
280 struct grmnet *gr = NULL;
281 unsigned long flags;
282
283 pr_debug("%s: port#%d\n", __func__, port_num);
284
285 port = gctrl_ports[port_num].port;
286
287 if (port_num > no_ctrl_ports) {
288 pr_err("%s: invalid portno#%d\n", __func__, port_num);
289 return;
290 }
291
292 if (!gptr || !port) {
293 pr_err("%s: grmnet port is null\n", __func__);
294 return;
295 }
296
297 if (port->gtype == USB_GADGET_SERIAL)
298 gser = gptr;
299 else
300 gr = gptr;
301
302 spin_lock_irqsave(&port->port_lock, flags);
303 if (gr) {
304 gr->send_encap_cmd = 0;
305 gr->notify_modem = 0;
306 }
307
308 if (gser)
309 gser->notify_modem = 0;
310 port->cbits_tomodem = 0;
311 port->port_usb = 0;
312 port->send_cpkt_response = 0;
313 spin_unlock_irqrestore(&port->port_lock, flags);
314
315 queue_work(port->wq, &port->disconnect_w);
316}
317
318static void ghsic_ctrl_status(void *ctxt, unsigned int ctrl_bits)
319{
320 struct gctrl_port *port = ctxt;
321 struct gserial *gser;
322
323 pr_debug("%s - input control lines: dcd%c dsr%c break%c "
324 "ring%c framing%c parity%c overrun%c\n", __func__,
325 ctrl_bits & ACM_CTRL_DCD ? '+' : '-',
326 ctrl_bits & ACM_CTRL_DSR ? '+' : '-',
327 ctrl_bits & ACM_CTRL_BRK ? '+' : '-',
328 ctrl_bits & ACM_CTRL_RI ? '+' : '-',
329 ctrl_bits & ACM_CTRL_FRAMING ? '+' : '-',
330 ctrl_bits & ACM_CTRL_PARITY ? '+' : '-',
331 ctrl_bits & ACM_CTRL_OVERRUN ? '+' : '-');
332
333 port->cbits_tohost = ctrl_bits;
334 gser = port->port_usb;
335 if (gser && gser->send_modem_ctrl_bits)
336 gser->send_modem_ctrl_bits(gser, ctrl_bits);
337}
338
339static int ghsic_ctrl_probe(struct platform_device *pdev)
340{
341 struct gctrl_port *port;
342 unsigned long flags;
343
344 pr_debug("%s: name:%s\n", __func__, pdev->name);
345
346 if (pdev->id >= no_ctrl_ports) {
347 pr_err("%s: invalid port: %d\n", __func__, pdev->id);
348 return -EINVAL;
349 }
350
351 port = gctrl_ports[pdev->id].port;
352 set_bit(CH_READY, &port->bridge_sts);
353
354 /* if usb is online, start read */
355 spin_lock_irqsave(&port->port_lock, flags);
356 if (port->port_usb)
357 queue_work(port->wq, &port->connect_w);
358 spin_unlock_irqrestore(&port->port_lock, flags);
359
360 return 0;
361}
362
363static int ghsic_ctrl_remove(struct platform_device *pdev)
364{
365 struct gctrl_port *port;
366 struct gserial *gser = NULL;
367 struct grmnet *gr = NULL;
368 unsigned long flags;
369
370 pr_debug("%s: name:%s\n", __func__, pdev->name);
371
372 if (pdev->id >= no_ctrl_ports) {
373 pr_err("%s: invalid port: %d\n", __func__, pdev->id);
374 return -EINVAL;
375 }
376
377 port = gctrl_ports[pdev->id].port;
378
379 spin_lock_irqsave(&port->port_lock, flags);
380 if (!port->port_usb) {
381 spin_unlock_irqrestore(&port->port_lock, flags);
382 goto not_ready;
383 }
384
385 if (port->gtype == USB_GADGET_SERIAL)
386 gser = port->port_usb;
387 else
388 gr = port->port_usb;
389
390 port->cbits_tohost = 0;
391 spin_unlock_irqrestore(&port->port_lock, flags);
392
393 if (gr && gr->disconnect)
394 gr->disconnect(gr);
395
396 if (gser && gser->disconnect)
397 gser->disconnect(gser);
398
399 ctrl_bridge_close(port->brdg.ch_id);
400
401 clear_bit(CH_OPENED, &port->bridge_sts);
402not_ready:
403 clear_bit(CH_READY, &port->bridge_sts);
404
405 return 0;
406}
407
408static void ghsic_ctrl_port_free(int portno)
409{
410 struct gctrl_port *port = gctrl_ports[portno].port;
411 struct platform_driver *pdrv = &gctrl_ports[portno].pdrv;
412
413 destroy_workqueue(port->wq);
414 kfree(port);
415
416 if (pdrv)
417 platform_driver_unregister(pdrv);
418}
419
420static int gctrl_port_alloc(int portno, enum gadget_type gtype)
421{
422 struct gctrl_port *port;
423 struct platform_driver *pdrv;
424
425 port = kzalloc(sizeof(struct gctrl_port), GFP_KERNEL);
426 if (!port)
427 return -ENOMEM;
428
429 port->wq = create_singlethread_workqueue(ctrl_bridge_names[portno]);
430 if (!port->wq) {
431 pr_err("%s: Unable to create workqueue:%s\n",
432 __func__, ctrl_bridge_names[portno]);
433 return -ENOMEM;
434 }
435
436 port->port_num = portno;
437 port->gtype = gtype;
438
439 spin_lock_init(&port->port_lock);
440
441 INIT_WORK(&port->connect_w, ghsic_ctrl_connect_w);
442 INIT_WORK(&port->disconnect_w, gctrl_disconnect_w);
443
444 port->brdg.ch_id = portno;
445 port->brdg.ctx = port;
446 port->brdg.ops.send_pkt = ghsic_ctrl_receive;
447 if (port->gtype == USB_GADGET_SERIAL)
448 port->brdg.ops.send_cbits = ghsic_ctrl_status;
449 gctrl_ports[portno].port = port;
450
451 pdrv = &gctrl_ports[portno].pdrv;
452 pdrv->probe = ghsic_ctrl_probe;
453 pdrv->remove = ghsic_ctrl_remove;
454 pdrv->driver.name = ctrl_bridge_names[portno];
455 pdrv->driver.owner = THIS_MODULE;
456
457 platform_driver_register(pdrv);
458
459 pr_debug("%s: port:%p portno:%d\n", __func__, port, portno);
460
461 return 0;
462}
463
464int ghsic_ctrl_setup(unsigned int num_ports, enum gadget_type gtype)
465{
466 int first_port_id = no_ctrl_ports;
467 int total_num_ports = num_ports + no_ctrl_ports;
468 int i;
469 int ret = 0;
470
471 if (!num_ports || total_num_ports > NUM_PORTS) {
472 pr_err("%s: Invalid num of ports count:%d\n",
473 __func__, num_ports);
474 return -EINVAL;
475 }
476
477 pr_debug("%s: requested ports:%d\n", __func__, num_ports);
478
479 for (i = first_port_id; i < (first_port_id + num_ports); i++) {
480
481 /*probe can be called while port_alloc,so update no_ctrl_ports*/
482 no_ctrl_ports++;
483 ret = gctrl_port_alloc(i, gtype);
484 if (ret) {
485 no_ctrl_ports--;
486 pr_err("%s: Unable to alloc port:%d\n", __func__, i);
487 goto free_ports;
488 }
489 }
490
491 return first_port_id;
492
493free_ports:
494 for (i = first_port_id; i < no_ctrl_ports; i++)
495 ghsic_ctrl_port_free(i);
496 no_ctrl_ports = first_port_id;
497 return ret;
498}
499
500#if defined(CONFIG_DEBUG_FS)
501#define DEBUG_BUF_SIZE 1024
502static ssize_t gctrl_read_stats(struct file *file, char __user *ubuf,
503 size_t count, loff_t *ppos)
504{
505 struct gctrl_port *port;
506 struct platform_driver *pdrv;
507 char *buf;
508 unsigned long flags;
509 int ret;
510 int i;
511 int temp = 0;
512
513 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
514 if (!buf)
515 return -ENOMEM;
516
517 for (i = 0; i < no_ctrl_ports; i++) {
518 port = gctrl_ports[i].port;
519 if (!port)
520 continue;
521 pdrv = &gctrl_ports[i].pdrv;
522 spin_lock_irqsave(&port->port_lock, flags);
523
524 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
525 "\nName: %s\n"
526 "#PORT:%d port: %p\n"
527 "to_usbhost: %lu\n"
528 "to_modem: %lu\n"
529 "cpkt_drp_cnt: %lu\n"
530 "DTR: %s\n"
531 "ch_open: %d\n"
532 "ch_ready: %d\n",
533 pdrv->driver.name,
534 i, port,
535 port->to_host, port->to_modem,
536 port->drp_cpkt_cnt,
537 port->cbits_tomodem ? "HIGH" : "LOW",
538 test_bit(CH_OPENED, &port->bridge_sts),
539 test_bit(CH_READY, &port->bridge_sts));
540
541 spin_unlock_irqrestore(&port->port_lock, flags);
542 }
543
544 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
545
546 kfree(buf);
547
548 return ret;
549}
550
551static ssize_t gctrl_reset_stats(struct file *file,
552 const char __user *buf, size_t count, loff_t *ppos)
553{
554 struct gctrl_port *port;
555 int i;
556 unsigned long flags;
557
558 for (i = 0; i < no_ctrl_ports; i++) {
559 port = gctrl_ports[i].port;
560 if (!port)
561 continue;
562
563 spin_lock_irqsave(&port->port_lock, flags);
564 port->to_host = 0;
565 port->to_modem = 0;
566 port->drp_cpkt_cnt = 0;
567 spin_unlock_irqrestore(&port->port_lock, flags);
568 }
569 return count;
570}
571
572const struct file_operations gctrl_stats_ops = {
573 .read = gctrl_read_stats,
574 .write = gctrl_reset_stats,
575};
576
577struct dentry *gctrl_dent;
578struct dentry *gctrl_dfile;
579static void gctrl_debugfs_init(void)
580{
581 gctrl_dent = debugfs_create_dir("ghsic_ctrl_xport", 0);
582 if (IS_ERR(gctrl_dent))
583 return;
584
585 gctrl_dfile =
586 debugfs_create_file("status", 0444, gctrl_dent, 0,
587 &gctrl_stats_ops);
588 if (!gctrl_dfile || IS_ERR(gctrl_dfile))
589 debugfs_remove(gctrl_dent);
590}
591
592static void gctrl_debugfs_exit(void)
593{
594 debugfs_remove(gctrl_dfile);
595 debugfs_remove(gctrl_dent);
596}
597
598#else
599static void gctrl_debugfs_init(void) { }
600static void gctrl_debugfs_exit(void) { }
601#endif
602
603static int __init gctrl_init(void)
604{
605 gctrl_debugfs_init();
606
607 return 0;
608}
609module_init(gctrl_init);
610
611static void __exit gctrl_exit(void)
612{
613 gctrl_debugfs_exit();
614}
615module_exit(gctrl_exit);
616MODULE_DESCRIPTION("hsic control xport driver");
617MODULE_LICENSE("GPL v2");