blob: 410b5c4370969bf48790641c88e08300cb877602 [file] [log] [blame]
Vamsi Krishna5b944712012-06-29 18:36:23 -07001/*
2 * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14/* add additional information to our printk's */
15#define pr_fmt(fmt) "%s: " fmt "\n", __func__
16
17#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/module.h>
22#include <linux/kref.h>
23#include <linux/platform_device.h>
24#include <linux/ratelimit.h>
25#include <linux/uaccess.h>
26#include <linux/usb.h>
27#include <linux/debugfs.h>
28#include <linux/seq_file.h>
29#include <linux/miscdevice.h>
30#include <linux/list.h>
31#include <linux/wait.h>
32
33#define DRIVER_DESC "USB host ks bridge driver"
34#define DRIVER_VERSION "1.0"
35
36struct data_pkt {
37 int n_read;
38 char *buf;
39 size_t len;
40 struct list_head list;
41 void *ctxt;
42};
43
44#define FILE_OPENED BIT(0)
45#define USB_DEV_CONNECTED BIT(1)
46#define NO_RX_REQS 10
47#define NO_BRIDGE_INSTANCES 2
48#define BOOT_BRIDGE_INDEX 0
49#define EFS_BRIDGE_INDEX 1
50#define MAX_DATA_PKT_SIZE 16384
Hemant Kumarb3779d12012-09-16 20:28:56 -070051#define PENDING_URB_TIMEOUT 10
Vamsi Krishna5b944712012-06-29 18:36:23 -070052
53struct ks_bridge {
54 char *name;
55 spinlock_t lock;
56 struct workqueue_struct *wq;
57 struct work_struct to_mdm_work;
58 struct work_struct start_rx_work;
59 struct list_head to_mdm_list;
60 struct list_head to_ks_list;
61 wait_queue_head_t ks_wait_q;
Hemant Kumarb3779d12012-09-16 20:28:56 -070062 wait_queue_head_t pending_urb_wait;
Hemant Kumarda86bd22012-08-24 19:42:31 -070063 struct miscdevice *fs_dev;
Hemant Kumarb3779d12012-09-16 20:28:56 -070064 atomic_t tx_pending_cnt;
65 atomic_t rx_pending_cnt;
Vamsi Krishna5b944712012-06-29 18:36:23 -070066
67 /* usb specific */
68 struct usb_device *udev;
69 struct usb_interface *ifc;
70 __u8 in_epAddr;
71 __u8 out_epAddr;
72 unsigned int in_pipe;
73 unsigned int out_pipe;
74 struct usb_anchor submitted;
75
76 unsigned long flags;
77 unsigned int alloced_read_pkts;
78
79#define DBG_MSG_LEN 40
80#define DBG_MAX_MSG 500
81 unsigned int dbg_idx;
82 rwlock_t dbg_lock;
83 char (dbgbuf[DBG_MAX_MSG])[DBG_MSG_LEN]; /* buffer */
84};
85struct ks_bridge *__ksb[NO_BRIDGE_INSTANCES];
86
87/* by default debugging is enabled */
88static unsigned int enable_dbg = 1;
89module_param(enable_dbg, uint, S_IRUGO | S_IWUSR);
90
91static void
92dbg_log_event(struct ks_bridge *ksb, char *event, int d1, int d2)
93{
94 unsigned long flags;
95 unsigned long long t;
96 unsigned long nanosec;
97
98 if (!enable_dbg)
99 return;
100
101 write_lock_irqsave(&ksb->dbg_lock, flags);
102 t = cpu_clock(smp_processor_id());
103 nanosec = do_div(t, 1000000000)/1000;
104 scnprintf(ksb->dbgbuf[ksb->dbg_idx], DBG_MSG_LEN, "%5lu.%06lu:%s:%x:%x",
105 (unsigned long)t, nanosec, event, d1, d2);
106
107 ksb->dbg_idx++;
108 ksb->dbg_idx = ksb->dbg_idx % DBG_MAX_MSG;
109 write_unlock_irqrestore(&ksb->dbg_lock, flags);
110}
111
112static
113struct data_pkt *ksb_alloc_data_pkt(size_t count, gfp_t flags, void *ctxt)
114{
115 struct data_pkt *pkt;
116
117 pkt = kzalloc(sizeof(struct data_pkt), flags);
118 if (!pkt) {
119 pr_err("failed to allocate data packet\n");
120 return ERR_PTR(-ENOMEM);
121 }
122
123 pkt->buf = kmalloc(count, flags);
124 if (!pkt->buf) {
125 pr_err("failed to allocate data buffer\n");
126 kfree(pkt);
127 return ERR_PTR(-ENOMEM);
128 }
129
130 pkt->len = count;
131 INIT_LIST_HEAD(&pkt->list);
132 pkt->ctxt = ctxt;
133
134 return pkt;
135}
136
137static void ksb_free_data_pkt(struct data_pkt *pkt)
138{
139 kfree(pkt->buf);
140 kfree(pkt);
141}
142
143
144static ssize_t ksb_fs_read(struct file *fp, char __user *buf,
145 size_t count, loff_t *pos)
146{
147 int ret;
148 unsigned long flags;
149 struct ks_bridge *ksb = fp->private_data;
150 struct data_pkt *pkt;
151 size_t space, copied;
152
153read_start:
154 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
155 return -ENODEV;
156
157 spin_lock_irqsave(&ksb->lock, flags);
158 if (list_empty(&ksb->to_ks_list)) {
159 spin_unlock_irqrestore(&ksb->lock, flags);
160 ret = wait_event_interruptible(ksb->ks_wait_q,
161 !list_empty(&ksb->to_ks_list) ||
162 !test_bit(USB_DEV_CONNECTED, &ksb->flags));
163 if (ret < 0)
164 return ret;
165
166 goto read_start;
167 }
168
169 space = count;
170 copied = 0;
171 while (!list_empty(&ksb->to_ks_list) && space) {
172 size_t len;
173
174 pkt = list_first_entry(&ksb->to_ks_list, struct data_pkt, list);
Hemant Kumarb48f4732012-09-24 12:32:32 -0700175 len = min_t(size_t, space, pkt->len - pkt->n_read);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700176 spin_unlock_irqrestore(&ksb->lock, flags);
177
Hemant Kumarb48f4732012-09-24 12:32:32 -0700178 ret = copy_to_user(buf + copied, pkt->buf + pkt->n_read, len);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700179 if (ret) {
180 pr_err("copy_to_user failed err:%d\n", ret);
181 ksb_free_data_pkt(pkt);
182 ksb->alloced_read_pkts--;
183 return ret;
184 }
185
Hemant Kumarb48f4732012-09-24 12:32:32 -0700186 pkt->n_read += len;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700187 space -= len;
188 copied += len;
189
190 spin_lock_irqsave(&ksb->lock, flags);
191 if (pkt->n_read == pkt->len) {
192 list_del_init(&pkt->list);
193 ksb_free_data_pkt(pkt);
194 ksb->alloced_read_pkts--;
195 }
196 }
197 spin_unlock_irqrestore(&ksb->lock, flags);
198
199 dbg_log_event(ksb, "KS_READ", copied, 0);
200
201 pr_debug("count:%d space:%d copied:%d", count, space, copied);
202
203 return copied;
204}
205
206static void ksb_tx_cb(struct urb *urb)
207{
208 struct data_pkt *pkt = urb->context;
209 struct ks_bridge *ksb = pkt->ctxt;
210
211 dbg_log_event(ksb, "C TX_URB", urb->status, 0);
212 pr_debug("status:%d", urb->status);
213
Hemant Kumarb3779d12012-09-16 20:28:56 -0700214 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
Vamsi Krishna5b944712012-06-29 18:36:23 -0700215 usb_autopm_put_interface_async(ksb->ifc);
216
217 if (urb->status < 0)
218 pr_err_ratelimited("urb failed with err:%d", urb->status);
219
220 ksb_free_data_pkt(pkt);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700221
222 atomic_dec(&ksb->tx_pending_cnt);
223 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700224}
225
226static void ksb_tomdm_work(struct work_struct *w)
227{
228 struct ks_bridge *ksb = container_of(w, struct ks_bridge, to_mdm_work);
229 struct data_pkt *pkt;
230 unsigned long flags;
231 struct urb *urb;
232 int ret;
233
234 spin_lock_irqsave(&ksb->lock, flags);
235 while (!list_empty(&ksb->to_mdm_list)
236 && test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
237 pkt = list_first_entry(&ksb->to_mdm_list,
238 struct data_pkt, list);
239 list_del_init(&pkt->list);
240 spin_unlock_irqrestore(&ksb->lock, flags);
241
242 urb = usb_alloc_urb(0, GFP_KERNEL);
243 if (!urb) {
244 pr_err_ratelimited("unable to allocate urb");
245 ksb_free_data_pkt(pkt);
246 return;
247 }
248
249 ret = usb_autopm_get_interface(ksb->ifc);
250 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
251 pr_err_ratelimited("autopm_get failed:%d", ret);
252 usb_free_urb(urb);
253 ksb_free_data_pkt(pkt);
254 return;
255 }
256 usb_fill_bulk_urb(urb, ksb->udev, ksb->out_pipe,
257 pkt->buf, pkt->len, ksb_tx_cb, pkt);
258 usb_anchor_urb(urb, &ksb->submitted);
259
260 dbg_log_event(ksb, "S TX_URB", pkt->len, 0);
261
Hemant Kumarb3779d12012-09-16 20:28:56 -0700262 atomic_inc(&ksb->tx_pending_cnt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700263 ret = usb_submit_urb(urb, GFP_KERNEL);
264 if (ret) {
265 pr_err("out urb submission failed");
266 usb_unanchor_urb(urb);
267 usb_free_urb(urb);
268 ksb_free_data_pkt(pkt);
269 usb_autopm_put_interface(ksb->ifc);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700270 atomic_dec(&ksb->tx_pending_cnt);
271 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700272 return;
273 }
274
Hemant Kumar1432f6f2012-09-19 12:40:11 -0700275 usb_free_urb(urb);
276
Vamsi Krishna5b944712012-06-29 18:36:23 -0700277 spin_lock_irqsave(&ksb->lock, flags);
278 }
279 spin_unlock_irqrestore(&ksb->lock, flags);
280}
281
282static ssize_t ksb_fs_write(struct file *fp, const char __user *buf,
283 size_t count, loff_t *pos)
284{
285 int ret;
286 struct data_pkt *pkt;
287 unsigned long flags;
288 struct ks_bridge *ksb = fp->private_data;
289
Hemant Kumar2f20bda2012-09-17 14:05:54 -0700290 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
291 return -ENODEV;
292
Vamsi Krishna5b944712012-06-29 18:36:23 -0700293 pkt = ksb_alloc_data_pkt(count, GFP_KERNEL, ksb);
294 if (IS_ERR(pkt)) {
295 pr_err("unable to allocate data packet");
296 return PTR_ERR(pkt);
297 }
298
299 ret = copy_from_user(pkt->buf, buf, count);
300 if (ret) {
301 pr_err("copy_from_user failed: err:%d", ret);
302 ksb_free_data_pkt(pkt);
303 return ret;
304 }
305
306 spin_lock_irqsave(&ksb->lock, flags);
307 list_add_tail(&pkt->list, &ksb->to_mdm_list);
308 spin_unlock_irqrestore(&ksb->lock, flags);
309
310 queue_work(ksb->wq, &ksb->to_mdm_work);
311
312 return count;
313}
314
315static int efs_fs_open(struct inode *ip, struct file *fp)
316{
317 struct ks_bridge *ksb = __ksb[EFS_BRIDGE_INDEX];
318
319 pr_debug(":%s", ksb->name);
320 dbg_log_event(ksb, "EFS-FS-OPEN", 0, 0);
321
322 if (!ksb) {
323 pr_err("ksb is being removed");
324 return -ENODEV;
325 }
326
327 fp->private_data = ksb;
328 set_bit(FILE_OPENED, &ksb->flags);
329
330 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
331 queue_work(ksb->wq, &ksb->start_rx_work);
332
333 return 0;
334}
335
336static int ksb_fs_open(struct inode *ip, struct file *fp)
337{
338 struct ks_bridge *ksb = __ksb[BOOT_BRIDGE_INDEX];
339
340 pr_debug(":%s", ksb->name);
341 dbg_log_event(ksb, "KS-FS-OPEN", 0, 0);
342
343 if (!ksb) {
344 pr_err("ksb is being removed");
345 return -ENODEV;
346 }
347
348 fp->private_data = ksb;
349 set_bit(FILE_OPENED, &ksb->flags);
350
351 if (test_bit(USB_DEV_CONNECTED, &ksb->flags))
352 queue_work(ksb->wq, &ksb->start_rx_work);
353
354 return 0;
355}
356
357static int ksb_fs_release(struct inode *ip, struct file *fp)
358{
359 struct ks_bridge *ksb = fp->private_data;
360
361 pr_debug(":%s", ksb->name);
362 dbg_log_event(ksb, "FS-RELEASE", 0, 0);
363
364 clear_bit(FILE_OPENED, &ksb->flags);
365 fp->private_data = NULL;
366
367 return 0;
368}
369
370static const struct file_operations ksb_fops = {
371 .owner = THIS_MODULE,
372 .read = ksb_fs_read,
373 .write = ksb_fs_write,
374 .open = ksb_fs_open,
375 .release = ksb_fs_release,
376};
377
378static struct miscdevice ksb_fboot_dev = {
379 .minor = MISC_DYNAMIC_MINOR,
380 .name = "ks_bridge",
381 .fops = &ksb_fops,
382};
383
384static const struct file_operations efs_fops = {
385 .owner = THIS_MODULE,
386 .read = ksb_fs_read,
387 .write = ksb_fs_write,
388 .open = efs_fs_open,
389 .release = ksb_fs_release,
390};
391
392static struct miscdevice ksb_efs_dev = {
393 .minor = MISC_DYNAMIC_MINOR,
394 .name = "efs_bridge",
395 .fops = &efs_fops,
396};
397
398static const struct usb_device_id ksb_usb_ids[] = {
399 { USB_DEVICE(0x5c6, 0x9008),
400 .driver_info = (unsigned long)&ksb_fboot_dev, },
401 { USB_DEVICE(0x5c6, 0x9048),
402 .driver_info = (unsigned long)&ksb_efs_dev, },
403 { USB_DEVICE(0x5c6, 0x904C),
404 .driver_info = (unsigned long)&ksb_efs_dev, },
405
406 {} /* terminating entry */
407};
408MODULE_DEVICE_TABLE(usb, ksb_usb_ids);
409
410static void ksb_rx_cb(struct urb *urb);
411static void submit_one_urb(struct ks_bridge *ksb)
412{
413 struct data_pkt *pkt;
414 struct urb *urb;
415 int ret;
416
417 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_ATOMIC, ksb);
418 if (IS_ERR(pkt)) {
419 pr_err("unable to allocate data pkt");
420 return;
421 }
422
423 urb = usb_alloc_urb(0, GFP_ATOMIC);
424 if (!urb) {
425 pr_err("unable to allocate urb");
426 ksb_free_data_pkt(pkt);
427 return;
428 }
429 ksb->alloced_read_pkts++;
430
431 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
432 pkt->buf, pkt->len,
433 ksb_rx_cb, pkt);
434 usb_anchor_urb(urb, &ksb->submitted);
435
Hemant Kumarb3779d12012-09-16 20:28:56 -0700436 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags)) {
437 usb_unanchor_urb(urb);
438 usb_free_urb(urb);
439 ksb_free_data_pkt(pkt);
440 ksb->alloced_read_pkts--;
441 return;
442 }
Vamsi Krishna5b944712012-06-29 18:36:23 -0700443
Hemant Kumarb3779d12012-09-16 20:28:56 -0700444 atomic_inc(&ksb->rx_pending_cnt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700445 ret = usb_submit_urb(urb, GFP_ATOMIC);
446 if (ret) {
447 pr_err("in urb submission failed");
448 usb_unanchor_urb(urb);
449 usb_free_urb(urb);
450 ksb_free_data_pkt(pkt);
451 ksb->alloced_read_pkts--;
Hemant Kumarb3779d12012-09-16 20:28:56 -0700452 atomic_dec(&ksb->rx_pending_cnt);
453 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700454 return;
455 }
456
Hemant Kumarb3779d12012-09-16 20:28:56 -0700457 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
458
Vamsi Krishna5b944712012-06-29 18:36:23 -0700459 usb_free_urb(urb);
460}
461static void ksb_rx_cb(struct urb *urb)
462{
463 struct data_pkt *pkt = urb->context;
464 struct ks_bridge *ksb = pkt->ctxt;
465
466 dbg_log_event(ksb, "C RX_URB", urb->status, urb->actual_length);
467
468 pr_debug("status:%d actual:%d", urb->status, urb->actual_length);
469
Hemant Kumar853ebf62012-08-31 18:38:32 -0700470 /*non zero len of data received while unlinking urb*/
471 if (urb->status == -ENOENT && urb->actual_length > 0)
472 goto add_to_list;
473
Vamsi Krishna5b944712012-06-29 18:36:23 -0700474 if (urb->status < 0) {
Hemant Kumar853ebf62012-08-31 18:38:32 -0700475 if (urb->status != -ESHUTDOWN && urb->status != -ENOENT
476 && urb->status != -EPROTO)
Vamsi Krishna5b944712012-06-29 18:36:23 -0700477 pr_err_ratelimited("urb failed with err:%d",
478 urb->status);
479 ksb_free_data_pkt(pkt);
480 ksb->alloced_read_pkts--;
Hemant Kumarb3779d12012-09-16 20:28:56 -0700481 goto done;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700482 }
483
484 if (urb->actual_length == 0) {
485 ksb_free_data_pkt(pkt);
486 ksb->alloced_read_pkts--;
487 goto resubmit_urb;
488 }
489
Hemant Kumar853ebf62012-08-31 18:38:32 -0700490add_to_list:
Vamsi Krishna5b944712012-06-29 18:36:23 -0700491 spin_lock(&ksb->lock);
492 pkt->len = urb->actual_length;
493 list_add_tail(&pkt->list, &ksb->to_ks_list);
494 spin_unlock(&ksb->lock);
495
496 /* wake up read thread */
497 wake_up(&ksb->ks_wait_q);
498
499resubmit_urb:
500 submit_one_urb(ksb);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700501done:
502 atomic_dec(&ksb->rx_pending_cnt);
503 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700504}
505
506static void ksb_start_rx_work(struct work_struct *w)
507{
508 struct ks_bridge *ksb =
509 container_of(w, struct ks_bridge, start_rx_work);
510 struct data_pkt *pkt;
511 struct urb *urb;
512 int i = 0;
513 int ret;
514
515 for (i = 0; i < NO_RX_REQS; i++) {
Hemant Kumarb3779d12012-09-16 20:28:56 -0700516
517 if (!test_bit(USB_DEV_CONNECTED, &ksb->flags))
518 return;
519
Vamsi Krishna5b944712012-06-29 18:36:23 -0700520 pkt = ksb_alloc_data_pkt(MAX_DATA_PKT_SIZE, GFP_KERNEL, ksb);
521 if (IS_ERR(pkt)) {
522 pr_err("unable to allocate data pkt");
523 return;
524 }
525
526 urb = usb_alloc_urb(0, GFP_KERNEL);
527 if (!urb) {
528 pr_err("unable to allocate urb");
529 ksb_free_data_pkt(pkt);
530 return;
531 }
532
533 ret = usb_autopm_get_interface(ksb->ifc);
534 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
535 pr_err_ratelimited("autopm_get failed:%d", ret);
536 usb_free_urb(urb);
537 ksb_free_data_pkt(pkt);
538 return;
539 }
540 ksb->alloced_read_pkts++;
541
542 usb_fill_bulk_urb(urb, ksb->udev, ksb->in_pipe,
543 pkt->buf, pkt->len,
544 ksb_rx_cb, pkt);
545 usb_anchor_urb(urb, &ksb->submitted);
546
547 dbg_log_event(ksb, "S RX_URB", pkt->len, 0);
548
Hemant Kumarb3779d12012-09-16 20:28:56 -0700549 atomic_inc(&ksb->rx_pending_cnt);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700550 ret = usb_submit_urb(urb, GFP_KERNEL);
551 if (ret) {
552 pr_err("in urb submission failed");
553 usb_unanchor_urb(urb);
554 usb_free_urb(urb);
555 ksb_free_data_pkt(pkt);
556 ksb->alloced_read_pkts--;
557 usb_autopm_put_interface(ksb->ifc);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700558 atomic_dec(&ksb->rx_pending_cnt);
559 wake_up(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700560 return;
561 }
562
563 usb_autopm_put_interface_async(ksb->ifc);
564 usb_free_urb(urb);
565 }
566}
567
568static int
569ksb_usb_probe(struct usb_interface *ifc, const struct usb_device_id *id)
570{
571 __u8 ifc_num;
572 struct usb_host_interface *ifc_desc;
573 struct usb_endpoint_descriptor *ep_desc;
574 int i;
575 struct ks_bridge *ksb;
Hemant Kumar2f20bda2012-09-17 14:05:54 -0700576 unsigned long flags;
577 struct data_pkt *pkt;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700578
579 ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
580
581 switch (id->idProduct) {
582 case 0x9008:
583 if (ifc_num != 0)
584 return -ENODEV;
585 ksb = __ksb[BOOT_BRIDGE_INDEX];
586 break;
587 case 0x9048:
588 case 0x904C:
589 if (ifc_num != 2)
590 return -ENODEV;
591 ksb = __ksb[EFS_BRIDGE_INDEX];
592 break;
593 default:
594 return -ENODEV;
595 }
596
597 if (!ksb) {
598 pr_err("ksb is not initialized");
599 return -ENODEV;
600 }
601
602 ksb->udev = usb_get_dev(interface_to_usbdev(ifc));
603 ksb->ifc = ifc;
604 ifc_desc = ifc->cur_altsetting;
605
606 for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
607 ep_desc = &ifc_desc->endpoint[i].desc;
608
609 if (!ksb->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
610 ksb->in_epAddr = ep_desc->bEndpointAddress;
611
612 if (!ksb->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
613 ksb->out_epAddr = ep_desc->bEndpointAddress;
614 }
615
616 if (!(ksb->in_epAddr && ksb->out_epAddr)) {
617 pr_err("could not find bulk in and bulk out endpoints");
618 usb_put_dev(ksb->udev);
619 ksb->ifc = NULL;
620 return -ENODEV;
621 }
622
623 ksb->in_pipe = usb_rcvbulkpipe(ksb->udev, ksb->in_epAddr);
624 ksb->out_pipe = usb_sndbulkpipe(ksb->udev, ksb->out_epAddr);
625
626 usb_set_intfdata(ifc, ksb);
627 set_bit(USB_DEV_CONNECTED, &ksb->flags);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700628 atomic_set(&ksb->tx_pending_cnt, 0);
629 atomic_set(&ksb->rx_pending_cnt, 0);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700630
631 dbg_log_event(ksb, "PID-ATT", id->idProduct, 0);
632
Hemant Kumar2f20bda2012-09-17 14:05:54 -0700633 /*free up stale buffers if any from previous disconnect*/
634 spin_lock_irqsave(&ksb->lock, flags);
635 while (!list_empty(&ksb->to_ks_list)) {
636 pkt = list_first_entry(&ksb->to_ks_list,
637 struct data_pkt, list);
638 list_del_init(&pkt->list);
639 ksb_free_data_pkt(pkt);
640 ksb->alloced_read_pkts--;
641 }
642 while (!list_empty(&ksb->to_mdm_list)) {
643 pkt = list_first_entry(&ksb->to_mdm_list,
644 struct data_pkt, list);
645 list_del_init(&pkt->list);
646 ksb_free_data_pkt(pkt);
647 }
648 spin_unlock_irqrestore(&ksb->lock, flags);
649
Hemant Kumarda86bd22012-08-24 19:42:31 -0700650 ksb->fs_dev = (struct miscdevice *)id->driver_info;
651 misc_register(ksb->fs_dev);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700652
Hemant Kumard26076c2012-09-07 19:00:21 -0700653 ifc->needs_remote_wakeup = 1;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700654 usb_enable_autosuspend(ksb->udev);
655
656 pr_debug("usb dev connected");
657
658 return 0;
659}
660
661static int ksb_usb_suspend(struct usb_interface *ifc, pm_message_t message)
662{
663 struct ks_bridge *ksb = usb_get_intfdata(ifc);
664
665 dbg_log_event(ksb, "SUSPEND", 0, 0);
666
Hemant Kumar853ebf62012-08-31 18:38:32 -0700667 pr_debug("read cnt: %d", ksb->alloced_read_pkts);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700668
669 usb_kill_anchored_urbs(&ksb->submitted);
670
671 return 0;
672}
673
674static int ksb_usb_resume(struct usb_interface *ifc)
675{
676 struct ks_bridge *ksb = usb_get_intfdata(ifc);
677
678 dbg_log_event(ksb, "RESUME", 0, 0);
679
680 if (test_bit(FILE_OPENED, &ksb->flags))
681 queue_work(ksb->wq, &ksb->start_rx_work);
682
683 return 0;
684}
685
686static void ksb_usb_disconnect(struct usb_interface *ifc)
687{
688 struct ks_bridge *ksb = usb_get_intfdata(ifc);
689 unsigned long flags;
690 struct data_pkt *pkt;
691
692 dbg_log_event(ksb, "PID-DETACH", 0, 0);
693
694 clear_bit(USB_DEV_CONNECTED, &ksb->flags);
695 wake_up(&ksb->ks_wait_q);
696 cancel_work_sync(&ksb->to_mdm_work);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700697 cancel_work_sync(&ksb->start_rx_work);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700698
Hemant Kumar2f20bda2012-09-17 14:05:54 -0700699 misc_deregister(ksb->fs_dev);
700
Vamsi Krishna5b944712012-06-29 18:36:23 -0700701 usb_kill_anchored_urbs(&ksb->submitted);
702
Hemant Kumarb3779d12012-09-16 20:28:56 -0700703 wait_event_interruptible_timeout(
704 ksb->pending_urb_wait,
705 !atomic_read(&ksb->tx_pending_cnt) &&
706 !atomic_read(&ksb->rx_pending_cnt),
707 msecs_to_jiffies(PENDING_URB_TIMEOUT));
708
Vamsi Krishna5b944712012-06-29 18:36:23 -0700709 spin_lock_irqsave(&ksb->lock, flags);
710 while (!list_empty(&ksb->to_ks_list)) {
711 pkt = list_first_entry(&ksb->to_ks_list,
712 struct data_pkt, list);
713 list_del_init(&pkt->list);
714 ksb_free_data_pkt(pkt);
Hemant Kumar2f20bda2012-09-17 14:05:54 -0700715 ksb->alloced_read_pkts--;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700716 }
717 while (!list_empty(&ksb->to_mdm_list)) {
718 pkt = list_first_entry(&ksb->to_mdm_list,
719 struct data_pkt, list);
720 list_del_init(&pkt->list);
721 ksb_free_data_pkt(pkt);
722 }
723 spin_unlock_irqrestore(&ksb->lock, flags);
724
Hemant Kumard26076c2012-09-07 19:00:21 -0700725 ifc->needs_remote_wakeup = 0;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700726 usb_put_dev(ksb->udev);
727 ksb->ifc = NULL;
728 usb_set_intfdata(ifc, NULL);
729
730 return;
731}
732
733static struct usb_driver ksb_usb_driver = {
734 .name = "ks_bridge",
735 .probe = ksb_usb_probe,
736 .disconnect = ksb_usb_disconnect,
737 .suspend = ksb_usb_suspend,
738 .resume = ksb_usb_resume,
739 .id_table = ksb_usb_ids,
740 .supports_autosuspend = 1,
741};
742
743static ssize_t ksb_debug_show(struct seq_file *s, void *unused)
744{
745 unsigned long flags;
746 struct ks_bridge *ksb = s->private;
747 int i;
748
749 read_lock_irqsave(&ksb->dbg_lock, flags);
750 for (i = 0; i < DBG_MAX_MSG; i++) {
751 if (i == (ksb->dbg_idx - 1))
752 seq_printf(s, "-->%s\n", ksb->dbgbuf[i]);
753 else
754 seq_printf(s, "%s\n", ksb->dbgbuf[i]);
755 }
756 read_unlock_irqrestore(&ksb->dbg_lock, flags);
757
758 return 0;
759}
760
761static int ksb_debug_open(struct inode *ip, struct file *fp)
762{
763 return single_open(fp, ksb_debug_show, ip->i_private);
764
765 return 0;
766}
767
768static const struct file_operations dbg_fops = {
769 .open = ksb_debug_open,
770 .read = seq_read,
771 .llseek = seq_lseek,
772 .release = single_release,
773};
774static struct dentry *dbg_dir;
775static int __init ksb_init(void)
776{
777 struct ks_bridge *ksb;
778 int num_instances = 0;
779 int ret = 0;
780 int i;
781
782 dbg_dir = debugfs_create_dir("ks_bridge", NULL);
783 if (IS_ERR(dbg_dir))
784 pr_err("unable to create debug dir");
785
786 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
787 ksb = kzalloc(sizeof(struct ks_bridge), GFP_KERNEL);
788 if (!ksb) {
789 pr_err("unable to allocat mem for ks_bridge");
Hemant Kumarda86bd22012-08-24 19:42:31 -0700790 ret = -ENOMEM;
791 goto dev_free;
Vamsi Krishna5b944712012-06-29 18:36:23 -0700792 }
793 __ksb[i] = ksb;
794
795 ksb->name = kasprintf(GFP_KERNEL, "ks_bridge:%i", i + 1);
796 if (!ksb->name) {
797 pr_info("unable to allocate name");
798 kfree(ksb);
799 ret = -ENOMEM;
800 goto dev_free;
801 }
802
803 spin_lock_init(&ksb->lock);
804 INIT_LIST_HEAD(&ksb->to_mdm_list);
805 INIT_LIST_HEAD(&ksb->to_ks_list);
806 init_waitqueue_head(&ksb->ks_wait_q);
Hemant Kumarb3779d12012-09-16 20:28:56 -0700807 init_waitqueue_head(&ksb->pending_urb_wait);
Vamsi Krishna5b944712012-06-29 18:36:23 -0700808 ksb->wq = create_singlethread_workqueue(ksb->name);
809 if (!ksb->wq) {
810 pr_err("unable to allocate workqueue");
811 kfree(ksb->name);
812 kfree(ksb);
813 ret = -ENOMEM;
814 goto dev_free;
815 }
816
817 INIT_WORK(&ksb->to_mdm_work, ksb_tomdm_work);
818 INIT_WORK(&ksb->start_rx_work, ksb_start_rx_work);
819 init_usb_anchor(&ksb->submitted);
820
821 ksb->dbg_idx = 0;
822 ksb->dbg_lock = __RW_LOCK_UNLOCKED(lck);
823
824 if (!IS_ERR(dbg_dir))
825 debugfs_create_file(ksb->name, S_IRUGO, dbg_dir,
826 ksb, &dbg_fops);
827
828 num_instances++;
829 }
830
831 ret = usb_register(&ksb_usb_driver);
832 if (ret) {
833 pr_err("unable to register ks bridge driver");
834 goto dev_free;
835 }
836
837 pr_info("init done");
838
839 return 0;
840
841dev_free:
842 if (!IS_ERR(dbg_dir))
843 debugfs_remove_recursive(dbg_dir);
844
845 for (i = 0; i < num_instances; i++) {
846 ksb = __ksb[i];
847
848 destroy_workqueue(ksb->wq);
849 kfree(ksb->name);
850 kfree(ksb);
851 }
852
853 return ret;
854
855}
856
857static void __exit ksb_exit(void)
858{
859 struct ks_bridge *ksb;
860 int i;
861
862 if (!IS_ERR(dbg_dir))
863 debugfs_remove_recursive(dbg_dir);
864
865 usb_deregister(&ksb_usb_driver);
866
867 for (i = 0; i < NO_BRIDGE_INSTANCES; i++) {
868 ksb = __ksb[i];
869
870 destroy_workqueue(ksb->wq);
871 kfree(ksb->name);
872 kfree(ksb);
873 }
874}
875
876module_init(ksb_init);
877module_exit(ksb_exit);
878
879MODULE_DESCRIPTION(DRIVER_DESC);
880MODULE_VERSION(DRIVER_VERSION);
881MODULE_LICENSE("GPL v2");