aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/baseband_usb_chr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/serial/baseband_usb_chr.c')
-rw-r--r--drivers/usb/serial/baseband_usb_chr.c1124
1 files changed, 1124 insertions, 0 deletions
diff --git a/drivers/usb/serial/baseband_usb_chr.c b/drivers/usb/serial/baseband_usb_chr.c
new file mode 100644
index 00000000000..6d691a40312
--- /dev/null
+++ b/drivers/usb/serial/baseband_usb_chr.c
@@ -0,0 +1,1124 @@
1/*
2 * baseband_usb_chr.c
3 *
4 * USB character driver to communicate with baseband modems.
5 *
6 * Copyright (c) 2011, NVIDIA Corporation.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#include <linux/types.h>
24#include <linux/init.h>
25#include <linux/module.h>
26#include <linux/moduleparam.h>
27#include <linux/kernel.h>
28#include <linux/cdev.h>
29#include <linux/fs.h>
30#include <linux/slab.h>
31#include <linux/delay.h>
32#include <linux/list.h>
33#include <linux/errno.h>
34#include <linux/usb.h>
35#include <linux/workqueue.h>
36#include <asm/ioctls.h>
37#include <linux/uaccess.h>
38#include "baseband_usb_chr.h"
39
40MODULE_LICENSE("GPL");
41
42unsigned long baseband_usb_chr_vid = 0x058b;
43unsigned long baseband_usb_chr_pid = 0x0041;
44unsigned long baseband_usb_chr_intf = 0x01;
45
46module_param(baseband_usb_chr_vid, ulong, 0644);
47MODULE_PARM_DESC(baseband_usb_chr_vid, "baseband (usb chr) - USB VID");
48module_param(baseband_usb_chr_pid, ulong, 0644);
49MODULE_PARM_DESC(baseband_usb_chr_pid, "baseband (usb chr) - USB PID");
50module_param(baseband_usb_chr_intf, ulong, 0644);
51MODULE_PARM_DESC(baseband_usb_chr_intf, "baseband (usb chr) - USB interface");
52
53static struct baseband_usb *baseband_usb_chr;
54static bool usb_device_connection;
55
56static atomic_t g_rx_count = ATOMIC_INIT(0);
57
58/* baseband ipc functions */
59
60static void baseband_ipc_dump(const char *prefix, unsigned long int offset,
61 const void *buf, size_t bufsiz)
62{
63 size_t i;
64
65 for (i = 0; i < bufsiz; i += 16) {
66 pr_debug("%s"
67 "[%lx+%x] %p "
68 "%02x %02x %02x %02x "
69 "%02x %02x %02x %02x "
70 "%02x %02x %02x %02x "
71 "%02x %02x %02x %02x\n",
72 prefix,
73 offset,
74 i,
75 ((const unsigned char *) buf) + i,
76 (i + 0 < bufsiz) ? ((const unsigned char *) buf)[i+0]
77 : 0xff,
78 (i + 1 < bufsiz) ? ((const unsigned char *) buf)[i+1]
79 : 0xff,
80 (i + 2 < bufsiz) ? ((const unsigned char *) buf)[i+2]
81 : 0xff,
82 (i + 3 < bufsiz) ? ((const unsigned char *) buf)[i+3]
83 : 0xff,
84 (i + 4 < bufsiz) ? ((const unsigned char *) buf)[i+4]
85 : 0xff,
86 (i + 5 < bufsiz) ? ((const unsigned char *) buf)[i+5]
87 : 0xff,
88 (i + 6 < bufsiz) ? ((const unsigned char *) buf)[i+6]
89 : 0xff,
90 (i + 7 < bufsiz) ? ((const unsigned char *) buf)[i+7]
91 : 0xff,
92 (i + 8 < bufsiz) ? ((const unsigned char *) buf)[i+8]
93 : 0xff,
94 (i + 9 < bufsiz) ? ((const unsigned char *) buf)[i+9]
95 : 0xff,
96 (i + 10 < bufsiz) ? ((const unsigned char *) buf)[i+10]
97 : 0xff,
98 (i + 11 < bufsiz) ? ((const unsigned char *) buf)[i+11]
99 : 0xff,
100 (i + 12 < bufsiz) ? ((const unsigned char *) buf)[i+12]
101 : 0xff,
102 (i + 13 < bufsiz) ? ((const unsigned char *) buf)[i+13]
103 : 0xff,
104 (i + 14 < bufsiz) ? ((const unsigned char *) buf)[i+14]
105 : 0xff,
106 (i + 15 < bufsiz) ? ((const unsigned char *) buf)[i+15]
107 : 0xff);
108 }
109
110}
111
112static size_t peek_ipc_tx_bufsiz(struct baseband_ipc *ipc,
113 size_t bufsiz)
114{
115 struct baseband_ipc_buf *ipc_buf, *ipc_buf_next;
116 size_t tx_bufsiz;
117
118 pr_debug("peek_ipc_tx_bufsiz\n");
119
120 /* check input */
121 if (!ipc) {
122 pr_err("!ipc\n");
123 return 0;
124 }
125
126 /* acquire tx buffer semaphores */
127 if (down_interruptible(&ipc->buf_sem)) {
128 pr_err("peek_ipc_tx_bufsiz - "
129 "cannot acquire buffer semaphore\n");
130 return -ERESTARTSYS;
131 }
132
133 /* calculate maximum number of tx buffers which can be sent */
134 tx_bufsiz = 0;
135 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx.buf, list)
136 {
137 pr_debug("peek_ipc_tx_bufsiz - "
138 "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n",
139 ipc_buf, ipc_buf->offset, ipc_buf->count);
140 if (ipc_buf->count > bufsiz - tx_bufsiz)
141 break;
142 else
143 tx_bufsiz += ipc_buf->count;
144 }
145
146 /* release tx buffer semaphores */
147 up(&ipc->buf_sem);
148
149 return tx_bufsiz;
150}
151
152static size_t get_ipc_tx_buf(struct baseband_ipc *ipc,
153 void *buf, size_t bufsiz)
154{
155 struct baseband_ipc_buf *ipc_buf, *ipc_buf_next;
156 size_t tx_bufsiz;
157
158 pr_debug("get_ipc_tx_buf\n");
159
160 /* check input */
161 if (!ipc || !buf) {
162 pr_err("!ipc || !buf\n");
163 return 0;
164 }
165 if (!bufsiz)
166 return 0;
167
168 /* acquire tx buffer semaphores */
169 if (down_interruptible(&ipc->buf_sem)) {
170 pr_err("get_ipc_tx_buf - "
171 "cannot acquire buffer semaphore\n");
172 return -ERESTARTSYS;
173 }
174
175 /* get tx data from tx linked list */
176 tx_bufsiz = 0;
177 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx.buf, list)
178 {
179 pr_debug("get_ipc_tx_buf - "
180 "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n",
181 ipc_buf, ipc_buf->offset, ipc_buf->count);
182 pr_debug("get_ipc_tx_buf - "
183 "ipc_buf->data [0] %x [1] %x [2] %x [3] %x\n",
184 ipc_buf->data[0],
185 ipc_buf->data[1],
186 ipc_buf->data[2],
187 ipc_buf->data[3]);
188 if (ipc_buf->count > bufsiz - tx_bufsiz) {
189 /* copy part of tx buffer */
190 memcpy(buf + tx_bufsiz,
191 ipc_buf->data + ipc_buf->offset,
192 bufsiz - tx_bufsiz);
193 ipc_buf->offset += bufsiz - tx_bufsiz;
194 ipc_buf->count -= bufsiz - tx_bufsiz;
195 tx_bufsiz = bufsiz;
196 } else {
197 /* copy all data from tx buffer */
198 memcpy(buf + tx_bufsiz,
199 ipc_buf->data + ipc_buf->offset,
200 ipc_buf->count);
201 tx_bufsiz += ipc_buf->count;
202 ipc_buf->offset = 0;
203 ipc_buf->count = 0;
204 /* add tx buffer to tx free list */
205 list_move_tail(&ipc_buf->list, &ipc->tx_free.buf);
206 wake_up(&ipc->tx_free.wait);
207 }
208 /* check if done */
209 if (tx_bufsiz == bufsiz)
210 break;
211 }
212
213 /* release tx buffer semaphores */
214 up(&ipc->buf_sem);
215
216 return tx_bufsiz;
217}
218
219static size_t put_ipc_rx_buf(struct baseband_ipc *ipc,
220 const void *buf, size_t bufsiz)
221{
222 struct baseband_ipc_buf *ipc_buf, *ipc_buf_next;
223 size_t rx_bufsiz;
224
225 pr_debug("put_ipc_rx_buf\n");
226
227 /* check input */
228 if (!ipc || !buf) {
229 pr_err("!ipc || !buf\n");
230 return 0;
231 }
232 if (!bufsiz)
233 return 0;
234
235 /* acquire rx buffer semaphores */
236retry:
237 if (down_interruptible(&ipc->buf_sem)) {
238 pr_err("put_ipc_rx_buf - "
239 "cannot acquire buffer semaphore\n");
240 return -ERESTARTSYS;
241 }
242
243 /* put rx data in rx linked list */
244 rx_bufsiz = 0;
245 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx_free.buf, list)
246 {
247 pr_debug("put_ipc_rx_buf - "
248 "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n",
249 ipc_buf, ipc_buf->offset, ipc_buf->count);
250 if (sizeof(ipc_buf->data) > bufsiz - rx_bufsiz) {
251 /* partially fill rx free buffer */
252 memcpy(ipc_buf->data,
253 buf + rx_bufsiz,
254 bufsiz - rx_bufsiz);
255 ipc_buf->offset = 0;
256 ipc_buf->count = bufsiz - rx_bufsiz;
257 rx_bufsiz = bufsiz;
258 } else {
259 /* fill entire rx free buffer */
260 memcpy(ipc_buf->data,
261 buf + rx_bufsiz,
262 sizeof(ipc_buf->data));
263 ipc_buf->offset = 0;
264 ipc_buf->count = sizeof(ipc_buf->data);
265 rx_bufsiz += sizeof(ipc_buf->data);
266 }
267 /* add filled rx free buffer to rx linked list */
268 list_move_tail(&ipc_buf->list, &ipc->rx.buf);
269 wake_up(&ipc->rx.wait);
270 /* check if done */
271 if (rx_bufsiz == bufsiz)
272 break;
273 }
274
275 /* release rx buffer semaphores */
276 up(&ipc->buf_sem);
277
278 /* wait for rx free buffer available */
279 if (!rx_bufsiz) {
280 if (wait_event_interruptible(ipc->rx_free.wait,
281 !list_empty(&ipc->rx_free.buf))) {
282 pr_err("put_ipc_rx_buf - "
283 "interrupted wait\n");
284 return -ERESTARTSYS;
285 }
286 goto retry;
287 }
288
289 return rx_bufsiz;
290
291}
292
293static ssize_t baseband_ipc_file_read(struct baseband_ipc *ipc,
294 struct file *file, char *buf, size_t count, loff_t *pos)
295{
296 struct baseband_ipc_buf *ipc_buf, *ipc_buf_next;
297 size_t read_count;
298
299 pr_debug("baseband_ipc_file_read\n");
300
301 /* check input */
302 if (!ipc) {
303 pr_err("!ipc\n");
304 return -EIO;
305 }
306
307 /* acquire rx buffer semaphores */
308retry:
309 if (down_interruptible(&ipc->buf_sem)) {
310 pr_err("baseband_ipc_file_read - "
311 "cannot acquire buffer semaphore\n");
312 return -ERESTARTSYS;
313 }
314
315 /* get read data from rx linked list */
316 read_count = 0;
317 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx.buf, list)
318 {
319 pr_debug("baseband_ipc_file_read - "
320 "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n",
321 ipc_buf, ipc_buf->offset, ipc_buf->count);
322 pr_debug("baseband_ipc_file_read - "
323 "ipc_buf->data [0] %x [1] %x [2] %x [3] %x\n",
324 ipc_buf->data[0],
325 ipc_buf->data[1],
326 ipc_buf->data[2],
327 ipc_buf->data[3]);
328 if (ipc_buf->count > count - read_count) {
329 /* copy part of rx buffer */
330 if (copy_to_user(buf + read_count,
331 ipc_buf->data + ipc_buf->offset,
332 count - read_count)) {
333 pr_err("copy_to_user failed\n");
334 up(&ipc->buf_sem);
335 return -EFAULT;
336 }
337 ipc_buf->offset += count - read_count;
338 ipc_buf->count -= count - read_count;
339 read_count = count;
340 } else {
341 /* copy all data from rx buffer */
342 if (copy_to_user(buf + read_count,
343 ipc_buf->data + ipc_buf->offset,
344 ipc_buf->count)) {
345 pr_err("copy_to_user failed\n");
346 up(&ipc->buf_sem);
347 return -EFAULT;
348 }
349 read_count += ipc_buf->count;
350 ipc_buf->offset = 0;
351 ipc_buf->count = 0;
352 /* add rx buffer to rx free list */
353 list_move_tail(&ipc_buf->list, &ipc->rx_free.buf);
354 wake_up(&ipc->rx_free.wait);
355 }
356 /* check if done */
357 if (read_count == count)
358 break;
359 }
360
361 /* release rx buffer semaphores */
362 up(&ipc->buf_sem);
363
364 /* wait for rx buffer available */
365 if (!read_count) {
366 if (wait_event_interruptible(ipc->rx.wait,
367 !list_empty(&ipc->rx.buf))) {
368 pr_err("baseband_ipc_file_read - "
369 "interrupted wait\n");
370 return -ERESTARTSYS;
371 }
372 goto retry;
373 }
374
375 return read_count;
376}
377
378static ssize_t baseband_ipc_file_write(struct baseband_ipc *ipc,
379 struct file *file, const char *buf, size_t count, loff_t *pos)
380{
381 struct baseband_ipc_buf *ipc_buf, *ipc_buf_next;
382 size_t write_count;
383
384 pr_debug("baseband_ipc_file_write\n");
385
386 /* check input */
387 if (!ipc) {
388 pr_err("!ipc\n");
389 return -EIO;
390 }
391
392 /* acquire tx buffer semaphores */
393retry:
394 if (down_interruptible(&ipc->buf_sem)) {
395 pr_err("baseband_ipc_file_write - "
396 "cannot acquire buffer semaphore\n");
397 return -ERESTARTSYS;
398 }
399
400 /* put write data in tx linked list */
401 write_count = 0;
402 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list)
403 {
404 pr_debug("baseband_ipc_file_write - "
405 "ipc_buf %p ipc_buf->offset %x ipc_buf->count %x\n",
406 ipc_buf, ipc_buf->offset, ipc_buf->count);
407 if (sizeof(ipc_buf->data) > count - write_count) {
408 /* partially fill tx free buffer */
409 if (copy_from_user(ipc_buf->data,
410 buf + write_count,
411 count - write_count)) {
412 pr_err("copy_from_user failed\n");
413 up(&ipc->buf_sem);
414 return -EFAULT;
415 }
416 ipc_buf->offset = 0;
417 ipc_buf->count = count - write_count;
418 write_count = count;
419 } else {
420 /* fill entire tx free buffer */
421 if (copy_from_user(ipc_buf->data,
422 buf + write_count,
423 sizeof(ipc_buf->data))) {
424 pr_err("copy_from_user failed\n");
425 up(&ipc->buf_sem);
426 return -EFAULT;
427 }
428 ipc_buf->offset = 0;
429 ipc_buf->count = sizeof(ipc_buf->data);
430 write_count += sizeof(ipc_buf->data);
431 }
432 /* add filled tx free buffer to tx linked list */
433 pr_debug("baseband_ipc_file_write - "
434 "ipc_buf->data [0] %x [1] %x [2] %x [3] %x\n",
435 ipc_buf->data[0],
436 ipc_buf->data[1],
437 ipc_buf->data[2],
438 ipc_buf->data[3]);
439 list_move_tail(&ipc_buf->list, &ipc->tx.buf);
440 wake_up(&ipc->tx.wait);
441 /* check if done */
442 if (write_count == count)
443 break;
444 }
445
446 /* release tx buffer semaphores */
447 up(&ipc->buf_sem);
448
449 /* wait for tx buffer available */
450 if (!write_count) {
451 if (wait_event_interruptible(ipc->tx_free.wait,
452 !list_empty(&ipc->tx_free.buf))) {
453 pr_err("baseband_ipc_file_write - "
454 "interrupted wait\n");
455 return -ERESTARTSYS;
456 }
457 goto retry;
458 }
459
460 /* queue ipc transaction work */
461 queue_work(ipc->workqueue, &ipc->work);
462
463 return write_count;
464}
465
466static void baseband_ipc_close(struct baseband_ipc *ipc)
467{
468 struct baseband_ipc_buf *ipc_buf, *ipc_buf_next;
469
470 pr_debug("baseband_ipc_close {\n");
471
472 /* check input */
473 if (!ipc)
474 return;
475
476 /* destroy work queue */
477 if (ipc->workqueue) {
478 pr_debug("destroy workqueue {\n");
479 cancel_work_sync(&ipc->work);
480 destroy_workqueue(ipc->workqueue);
481 ipc->workqueue = (struct workqueue_struct *) 0;
482 pr_debug("destroy workqueue }\n");
483 }
484 memset(&ipc->work, 0, sizeof(ipc->work));
485
486 /* destroy wait queues */
487 memset(&ipc->tx_free.wait, 0, sizeof(ipc->tx_free.wait));
488 memset(&ipc->rx_free.wait, 0, sizeof(ipc->rx_free.wait));
489 memset(&ipc->tx.wait, 0, sizeof(ipc->tx.wait));
490 memset(&ipc->rx.wait, 0, sizeof(ipc->rx.wait));
491
492 /* destroy data buffers */
493 kfree(ipc->ipc_tx);
494 ipc->ipc_tx = (unsigned char *) 0;
495 kfree(ipc->ipc_rx);
496 ipc->ipc_rx = (unsigned char *) 0;
497 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx_free.buf, list)
498 {
499 kfree(ipc_buf);
500 }
501 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx_free.buf, list)
502 {
503 kfree(ipc_buf);
504 }
505 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->tx.buf, list)
506 {
507 kfree(ipc_buf);
508 }
509 list_for_each_entry_safe(ipc_buf, ipc_buf_next, &ipc->rx.buf, list)
510 {
511 kfree(ipc_buf);
512 }
513
514 /* destroy semaphores */
515 memset(&ipc->buf_sem, 0, sizeof(ipc->buf_sem));
516
517 /* free baseband ipc structure */
518 kfree(ipc);
519
520 pr_debug("baseband_ipc_close }\n");
521}
522
523static struct baseband_ipc *baseband_ipc_open(work_func_t work_func,
524 work_func_t rx_work_func,
525 work_func_t tx_work_func)
526{
527 struct baseband_ipc *ipc;
528 struct baseband_ipc_buf *ipc_buf;
529 int i;
530
531 pr_debug("baseband_ipc_open {\n");
532
533 /* allocate baseband ipc structure */
534 ipc = kzalloc(sizeof(struct baseband_ipc), GFP_KERNEL);
535 if (!ipc)
536 return (struct baseband_ipc *) 0;
537
538 /* create semaphores */
539 sema_init(&ipc->buf_sem, 1);
540
541 /* create data buffers */
542 INIT_LIST_HEAD(&ipc->rx.buf);
543 INIT_LIST_HEAD(&ipc->tx.buf);
544 INIT_LIST_HEAD(&ipc->rx_free.buf);
545 INIT_LIST_HEAD(&ipc->tx_free.buf);
546 for (i = 0; i < BASEBAND_IPC_NUM_RX_BUF; i++) {
547 ipc_buf = (struct baseband_ipc_buf *)
548 kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL);
549 if (!ipc_buf) {
550 pr_err("cannot allocate baseband ipc rx buffer #%d\n",
551 i);
552 goto error_exit;
553 }
554 pr_debug("baseband_ipc_open - "
555 "rx_free: ipc_buf %p\n",
556 ipc_buf);
557 list_add_tail(&ipc_buf->list, &ipc->rx_free.buf);
558 }
559 for (i = 0; i < BASEBAND_IPC_NUM_TX_BUF; i++) {
560 ipc_buf = (struct baseband_ipc_buf *)
561 kzalloc(sizeof(struct baseband_ipc_buf), GFP_KERNEL);
562 if (!ipc_buf) {
563 pr_err("cannot allocate baseband ipc tx buffer #%d\n",
564 i);
565 goto error_exit;
566 }
567 pr_debug("baseband_ipc_open - "
568 "tx_free: ipc_buf %p\n",
569 ipc_buf);
570 list_add_tail(&ipc_buf->list, &ipc->tx_free.buf);
571 }
572 ipc->ipc_rx = (unsigned char *) 0;
573 ipc->ipc_tx = (unsigned char *) 0;
574
575 /* create wait queues */
576 init_waitqueue_head(&ipc->rx.wait);
577 init_waitqueue_head(&ipc->tx.wait);
578 init_waitqueue_head(&ipc->rx_free.wait);
579 init_waitqueue_head(&ipc->tx_free.wait);
580
581 /* create work queue */
582 ipc->workqueue = create_singlethread_workqueue
583 ("baseband_usb_chr_ipc_workqueue");
584 if (!ipc->workqueue) {
585 pr_err("cannot create workqueue\n");
586 goto error_exit;
587 }
588 if (work_func)
589 INIT_WORK(&ipc->work, work_func);
590 if (rx_work_func)
591 INIT_WORK(&ipc->rx_work, rx_work_func);
592 if (tx_work_func)
593 INIT_WORK(&ipc->tx_work, tx_work_func);
594
595 pr_debug("baseband_ipc_open }\n");
596 return ipc;
597
598error_exit:
599 baseband_ipc_close(ipc);
600 return (struct baseband_ipc *) 0;
601}
602
603/* usb rx */
604
605static void baseband_usb_chr_rx_urb_comp(struct urb *urb)
606{
607 struct baseband_usb *usb = (struct baseband_usb *) urb->context;
608
609 pr_debug("baseband_usb_chr_rx_urb_comp { urb %p\n", urb);
610
611 /* queue rx urb completion work */
612 queue_work(usb->ipc->workqueue, &usb->ipc->rx_work);
613
614 pr_debug("baseband_usb_chr_rx_urb_comp }\n");
615}
616
617static int baseband_usb_chr_rx_urb_submit(struct baseband_usb *usb)
618{
619 struct urb *urb;
620 void *buf;
621 int err;
622
623 pr_debug("baseband_usb_chr_rx_urb_submit { usb %p\n", usb);
624
625 if (!usb_device_connection) {
626 pr_err("!!no usb device conenction!!!!!\n");
627 return -1;
628 }
629
630 /* check input */
631 if (usb->usb.rx_urb) {
632 pr_err("previous urb still active\n");
633 return -1;
634 }
635
636 /* allocate rx urb */
637 urb = usb_alloc_urb(0, GFP_ATOMIC);
638 if (!urb) {
639 pr_err("usb_alloc_urb() failed\n");
640 return -ENOMEM;
641 }
642 buf = kzalloc(USB_CHR_RX_BUFSIZ, GFP_ATOMIC);
643 if (!buf) {
644 pr_err("usb buffer kzalloc() failed\n");
645 usb_free_urb(urb);
646 return -ENOMEM;
647 }
648 usb_fill_bulk_urb(urb, usb->usb.device, usb->usb.pipe.bulk.in,
649 buf, USB_CHR_RX_BUFSIZ,
650 baseband_usb_chr_rx_urb_comp,
651 usb);
652 urb->transfer_flags = 0;
653
654 /* submit rx urb */
655 usb->usb.rx_urb = urb;
656 err = usb_submit_urb(urb, GFP_ATOMIC);
657 if (err < 0) {
658 pr_err("usb_submit_urb() failed - err %d\n", err);
659 usb->usb.rx_urb = (struct urb *) 0;
660 kfree(urb->transfer_buffer);
661 usb_free_urb(urb);
662 return err;
663 }
664
665 pr_debug("baseband_usb_chr_rx_urb_submit }\n");
666 return err;
667}
668
669static void baseband_usb_chr_rx_urb_comp_work(struct work_struct *work)
670{
671 struct baseband_usb *usb = baseband_usb_chr;
672 struct urb *urb = usb->usb.rx_urb;
673 size_t len;
674
675 pr_debug("baseband_usb_chr_rx_urb_comp_work { work %p\n", work);
676
677 /* put rx urb data in rx buffer */
678 if (urb->actual_length) {
679 pr_debug("baseband_usb_chr_rx_urb_comp_work - "
680 "urb->actual_length %d\n", urb->actual_length);
681 len = put_ipc_rx_buf(usb->ipc,
682 urb->transfer_buffer, urb->actual_length);
683 baseband_ipc_dump("baseband_usb_chr_rx_urb_comp_work"
684 " - rx buf ", 0,
685 urb->transfer_buffer, len > 16 ? 16 : len);
686 if (len != urb->actual_length) {
687 pr_err("baseband_usb_chr_rx_urb_comp_work - "
688 "put_ipx_rx_buf() only put %d/%d bytes\n",
689 len, urb->actual_length);
690 }
691 /* increment count of available rx bytes */
692 atomic_add(len, &g_rx_count);
693 }
694
695 /* free rx urb */
696 kfree(urb->transfer_buffer);
697 urb->transfer_buffer = (void *) 0;
698 usb_free_urb(urb);
699 usb->usb.rx_urb = (struct urb *) 0;
700
701 /* submit next rx urb */
702 baseband_usb_chr_rx_urb_submit(usb);
703
704 pr_debug("baseband_usb_chr_rx_urb_comp_work }\n");
705}
706
707/* usb functions */
708
709static void find_usb_pipe(struct baseband_usb *usb)
710{
711 struct usb_device *usbdev = usb->usb.device;
712 struct usb_interface *intf = usb->usb.interface;
713 unsigned char numendpoint = intf->cur_altsetting->desc.bNumEndpoints;
714 struct usb_host_endpoint *endpoint = intf->cur_altsetting->endpoint;
715 unsigned char n;
716
717 for (n = 0; n < numendpoint; n++) {
718 if (usb_endpoint_is_isoc_in(&endpoint[n].desc)) {
719 pr_debug("endpoint[%d] isochronous in\n", n);
720 usb->usb.pipe.isoch.in = usb_rcvisocpipe(usbdev,
721 endpoint[n].desc.bEndpointAddress);
722 } else if (usb_endpoint_is_isoc_out(&endpoint[n].desc)) {
723 pr_debug("endpoint[%d] isochronous out\n", n);
724 usb->usb.pipe.isoch.out = usb_sndisocpipe(usbdev,
725 endpoint[n].desc.bEndpointAddress);
726 } else if (usb_endpoint_is_bulk_in(&endpoint[n].desc)) {
727 pr_debug("endpoint[%d] bulk in\n", n);
728 usb->usb.pipe.bulk.in = usb_rcvbulkpipe(usbdev,
729 endpoint[n].desc.bEndpointAddress);
730 } else if (usb_endpoint_is_bulk_out(&endpoint[n].desc)) {
731 pr_debug("endpoint[%d] bulk out\n", n);
732 usb->usb.pipe.bulk.out = usb_sndbulkpipe(usbdev,
733 endpoint[n].desc.bEndpointAddress);
734 } else if (usb_endpoint_is_int_in(&endpoint[n].desc)) {
735 pr_debug("endpoint[%d] interrupt in\n", n);
736 usb->usb.pipe.interrupt.in = usb_rcvintpipe(usbdev,
737 endpoint[n].desc.bEndpointAddress);
738 } else if (usb_endpoint_is_int_out(&endpoint[n].desc)) {
739 pr_debug("endpoint[%d] interrupt out\n", n);
740 usb->usb.pipe.interrupt.out = usb_sndintpipe(usbdev,
741 endpoint[n].desc.bEndpointAddress);
742 } else {
743 pr_debug("endpoint[%d] skipped\n", n);
744 }
745 }
746}
747
748static int baseband_usb_driver_probe(struct usb_interface *intf,
749 const struct usb_device_id *id)
750{
751 int err;
752
753 pr_debug("%s(%d) { intf %p id %p\n", __func__, __LINE__, intf, id);
754
755 pr_debug("intf->cur_altsetting->desc.bInterfaceNumber %02x\n",
756 intf->cur_altsetting->desc.bInterfaceNumber);
757 pr_debug("intf->cur_altsetting->desc.bAlternateSetting %02x\n",
758 intf->cur_altsetting->desc.bAlternateSetting);
759 pr_debug("intf->cur_altsetting->desc.bNumEndpoints %02x\n",
760 intf->cur_altsetting->desc.bNumEndpoints);
761 pr_debug("intf->cur_altsetting->desc.bInterfaceClass %02x\n",
762 intf->cur_altsetting->desc.bInterfaceClass);
763 pr_debug("intf->cur_altsetting->desc.bInterfaceSubClass %02x\n",
764 intf->cur_altsetting->desc.bInterfaceSubClass);
765 pr_debug("intf->cur_altsetting->desc.bInterfaceProtocol %02x\n",
766 intf->cur_altsetting->desc.bInterfaceProtocol);
767 pr_debug("intf->cur_altsetting->desc.iInterface %02x\n",
768 intf->cur_altsetting->desc.iInterface);
769
770 /* usb interface mismatch */
771 if (baseband_usb_chr_intf !=
772 intf->cur_altsetting->desc.bInterfaceNumber) {
773 pr_debug("%s(%d) } -ENODEV\n", __func__, __LINE__);
774 return -ENODEV;
775 }
776
777 /* usb interface match */
778 baseband_usb_chr->usb.device = interface_to_usbdev(intf);
779 baseband_usb_chr->usb.interface = intf;
780 find_usb_pipe(baseband_usb_chr);
781 baseband_usb_chr->usb.rx_urb = (struct urb *) 0;
782 baseband_usb_chr->usb.tx_urb = (struct urb *) 0;
783 pr_debug("baseband_usb_chr->usb.driver->name %s\n",
784 baseband_usb_chr->usb.driver->name);
785 pr_debug("baseband_usb_chr->usb.device %p\n",
786 baseband_usb_chr->usb.device);
787 pr_debug("baseband_usb_chr->usb.interface %p\n",
788 baseband_usb_chr->usb.interface);
789 pr_debug("baseband_usb_chr->usb.pipe.isoch.in %x\n",
790 baseband_usb_chr->usb.pipe.isoch.in);
791 pr_debug("baseband_usb_chr->usb.pipe.isoch.out %x\n",
792 baseband_usb_chr->usb.pipe.isoch.out);
793 pr_debug("baseband_usb_chr->usb.pipe.bulk.in %x\n",
794 baseband_usb_chr->usb.pipe.bulk.in);
795 pr_debug("baseband_usb_chr->usb.pipe.bulk.out %x\n",
796 baseband_usb_chr->usb.pipe.bulk.out);
797 pr_debug("baseband_usb_chr->usb.pipe.interrupt.in %x\n",
798 baseband_usb_chr->usb.pipe.interrupt.in);
799 pr_debug("baseband_usb_chr->usb.pipe.interrupt.out %x\n",
800 baseband_usb_chr->usb.pipe.interrupt.out);
801 usb_device_connection = true;
802
803 /* start usb rx */
804 err = baseband_usb_chr_rx_urb_submit(baseband_usb_chr);
805 if (err < 0) {
806 pr_err("submit rx failed - err %d\n", err);
807 return -ENODEV;
808 }
809
810 pr_debug("%s(%d) }\n", __func__, __LINE__);
811 return 0;
812}
813
814static void baseband_usb_driver_disconnect(struct usb_interface *intf)
815{
816 struct usb_device *usb_dev = interface_to_usbdev(intf);
817 pr_debug("%s(%d) { intf %p\n", __func__, __LINE__, intf);
818 pr_debug("%s(%d) }\n", __func__, __LINE__);
819 if (baseband_usb_chr->usb.interface != intf) {
820 pr_info("%s(%d) -ENODEV\n", __func__, __LINE__);
821 return;
822 }
823 if (baseband_usb_chr->usb.device == usb_dev) {
824 pr_info("%s: Matching usb device: Flush workqueue\n", __func__);
825 flush_workqueue(baseband_usb_chr->ipc->workqueue);
826 usb_device_connection = false;
827 }
828
829}
830
831static char baseband_usb_driver_name[32];
832
833static struct usb_device_id baseband_usb_driver_id_table[2];
834
835static struct usb_driver baseband_usb_driver = {
836 .name = baseband_usb_driver_name,
837 .probe = baseband_usb_driver_probe,
838 .disconnect = baseband_usb_driver_disconnect,
839 .id_table = baseband_usb_driver_id_table,
840};
841
842static void baseband_usb_chr_work(struct work_struct *work)
843{
844 struct baseband_usb *usb = baseband_usb_chr;
845 struct {
846 unsigned char *buf;
847 unsigned int bufsiz_byte;
848 } rx, tx;
849 int ipc_tx_byte;
850 int err;
851
852 pr_debug("baseband_usb_chr_work {\n");
853
854 /* check input */
855 if (!usb || !usb->ipc) {
856 pr_err("baseband_usb_chr_work - "
857 "usb not open\n");
858 return;
859 }
860 if (!usb->usb.device) {
861 pr_err("baseband_usb_chr_work - "
862 "usb device not probed yet\n");
863 mdelay(10);
864 queue_work(usb->ipc->workqueue, &usb->ipc->work);
865 return;
866 }
867
868 /* allocate buffers on first transaction (will be freed on close) */
869 if (!usb->ipc->ipc_rx) {
870 usb->ipc->ipc_rx = kzalloc(USB_CHR_RX_BUFSIZ, GFP_KERNEL);
871 if (!usb->ipc->ipc_rx) {
872 pr_err("baseband_usb_chr_work - "
873 "cannot allocate usb->ipc->ipc_rx\n");
874 return;
875 }
876 }
877 if (!usb->ipc->ipc_tx) {
878 usb->ipc->ipc_tx = kzalloc(USB_CHR_TX_BUFSIZ, GFP_KERNEL);
879 if (!usb->ipc->ipc_tx) {
880 pr_err("baseband_usb_chr_work - "
881 "cannot allocate usb->ipc->ipc_tx\n");
882 return;
883 }
884 }
885
886 /* usb transaction loop */
887 rx.buf = usb->ipc->ipc_rx;
888 tx.buf = usb->ipc->ipc_tx;
889 while ((tx.bufsiz_byte = peek_ipc_tx_bufsiz(usb->ipc,
890 USB_CHR_TX_BUFSIZ)) != 0) {
891 get_ipc_tx_buf(usb->ipc, tx.buf, tx.bufsiz_byte);
892 err = usb_bulk_msg(usb->usb.device, usb->usb.pipe.bulk.out,
893 tx.buf, tx.bufsiz_byte, &ipc_tx_byte, USB_CHR_TIMEOUT);
894 if (err < 0) {
895 pr_err("baseband_usb_chr_work - "
896 "usb_bulk_msg err %d\n", err);
897 continue;
898 }
899 if (tx.bufsiz_byte != ipc_tx_byte) {
900 pr_err("tx.bufsiz_byte %d != ipc_tx_byte %d\n",
901 tx.bufsiz_byte, ipc_tx_byte);
902 continue;
903 }
904 }
905
906 pr_debug("baseband_usb_chr_work }\n");
907}
908
909/* usb character file operations */
910
911static int baseband_usb_chr_open(struct inode *inode, struct file *file)
912{
913 pr_debug("baseband_usb_chr_open\n");
914 return 0;
915}
916
917static int baseband_usb_chr_release(struct inode *inode, struct file *file)
918{
919 pr_debug("baseband_usb_chr_release\n");
920 return 0;
921}
922
923static ssize_t baseband_usb_chr_read(struct file *file, char *buf,
924 size_t count, loff_t *pos)
925{
926 ssize_t ret;
927
928 pr_debug("baseband_usb_chr_read\n");
929
930 ret = baseband_ipc_file_read(baseband_usb_chr->ipc,
931 file, buf, count, pos);
932 if (ret > 0) {
933 /* decrement count of available rx bytes */
934 int val = atomic_read(&g_rx_count);
935 pr_debug("baseband_usb_chr_read - read %d unread %d\n",
936 ret, val - ret);
937 atomic_sub(ret, &g_rx_count);
938 }
939 return ret;
940}
941
942static ssize_t baseband_usb_chr_write(struct file *file, const char *buf,
943 size_t count, loff_t *pos)
944{
945 pr_debug("baseband_usb_chr_write\n");
946 return baseband_ipc_file_write(baseband_usb_chr->ipc,
947 file, buf, count, pos);
948}
949
950static long baseband_usb_chr_ioctl(struct file *file, unsigned int cmd,
951 unsigned long arg)
952{
953 pr_debug("baseband_usb_chr_ioctl\n");
954 switch (cmd) {
955 case TCFLSH:
956 pr_debug("TCFLSH\n");
957 /* flush queued ipc transaction work */
958 flush_workqueue(baseband_usb_chr->ipc->workqueue);
959 return 0;
960 case FIONREAD:
961 pr_debug("FIONREAD\n");
962 /* return count of available rx bytes */
963 {
964 int __user *p = (int __user *) arg;
965 int val = atomic_read(&g_rx_count);
966 if (put_user(val, p))
967 break;
968 }
969 return 0;
970 default:
971 pr_err("unsupported ioctl cmd %x\n", cmd);
972 }
973 return -ENODEV;
974}
975
976static const struct file_operations baseband_usb_chr_fops = {
977 .open = baseband_usb_chr_open,
978 .release = baseband_usb_chr_release,
979 .read = baseband_usb_chr_read,
980 .write = baseband_usb_chr_write,
981 .unlocked_ioctl = baseband_usb_chr_ioctl,
982};
983
984/* usb device driver functions */
985
986static void baseband_usb_close(struct baseband_usb *usb)
987{
988 pr_debug("baseband_usb_close {\n");
989
990 /* check input */
991 if (!usb)
992 return;
993
994 /* close usb driver */
995 if (usb->usb.driver) {
996 pr_debug("close usb driver {\n");
997 usb_deregister(usb->usb.driver);
998 usb->usb.driver = (struct usb_driver *) 0;
999 pr_debug("close usb driver }\n");
1000 }
1001
1002 /* close baseband ipc */
1003 if (usb->ipc) {
1004 baseband_ipc_close(usb->ipc);
1005 usb->ipc = (struct baseband_ipc *) 0;
1006 }
1007
1008 /* free baseband usb structure */
1009 kfree(usb);
1010
1011 pr_debug("baseband_usb_close }\n");
1012}
1013
1014static struct baseband_usb *baseband_usb_open(unsigned int vid,
1015 unsigned int pid,
1016 unsigned int intf,
1017 work_func_t work_func,
1018 work_func_t rx_work_func,
1019 work_func_t tx_work_func)
1020{
1021 struct baseband_usb *usb;
1022 int err;
1023
1024 pr_debug("baseband_usb_open {\n");
1025
1026 /* allocate baseband usb structure */
1027 usb = kzalloc(sizeof(struct baseband_usb), GFP_KERNEL);
1028 if (!usb)
1029 return (struct baseband_usb *) 0;
1030 baseband_usb_chr = usb;
1031
1032 /* open baseband ipc */
1033 usb->ipc = baseband_ipc_open(work_func,
1034 rx_work_func,
1035 tx_work_func);
1036 if (!usb->ipc) {
1037 pr_err("open baseband ipc failed\n");
1038 goto error_exit;
1039 }
1040
1041 /* open usb driver */
1042 sprintf(baseband_usb_driver_name,
1043 "baseband_usb_%x_%x_%x",
1044 vid, pid, intf);
1045 baseband_usb_driver_id_table[0].match_flags
1046 = USB_DEVICE_ID_MATCH_DEVICE;
1047 baseband_usb_driver_id_table[0].idVendor = vid;
1048 baseband_usb_driver_id_table[0].idProduct = pid;
1049 usb->usb.driver = &baseband_usb_driver;
1050 err = usb_register(&baseband_usb_driver);
1051 if (err < 0) {
1052 pr_err("cannot open usb driver - err %d\n", err);
1053 goto error_exit;
1054 }
1055
1056 pr_debug("baseband_usb_open }\n");
1057 return usb;
1058
1059error_exit:
1060 baseband_usb_close(usb);
1061 baseband_usb_chr = (struct baseband_usb *) 0;
1062 return (struct baseband_usb *) 0;
1063}
1064
1065/* module init / exit functions */
1066
1067static int baseband_usb_chr_init(void)
1068{
1069 int err;
1070
1071 pr_debug("baseband_usb_chr_init {\n");
1072
1073 /* open baseband usb */
1074 baseband_usb_chr = baseband_usb_open
1075 (baseband_usb_chr_vid,
1076 baseband_usb_chr_pid,
1077 baseband_usb_chr_intf,
1078 baseband_usb_chr_work,
1079 baseband_usb_chr_rx_urb_comp_work,
1080 (work_func_t) 0);
1081 if (!baseband_usb_chr) {
1082 pr_err("cannot open baseband usb chr\n");
1083 err = -1;
1084 goto err1;
1085 }
1086
1087 /* register character device */
1088 err = register_chrdev(BASEBAND_USB_CHR_DEV_MAJOR,
1089 BASEBAND_USB_CHR_DEV_NAME,
1090 &baseband_usb_chr_fops);
1091 if (err < 0) {
1092 pr_err("cannot register character device - %d\n", err);
1093 goto err2;
1094 }
1095 pr_debug("registered baseband usb character device - major %d\n",
1096 BASEBAND_USB_CHR_DEV_MAJOR);
1097
1098 pr_debug("baseband_usb_chr_init }\n");
1099 return 0;
1100err2: baseband_usb_close(baseband_usb_chr);
1101 baseband_usb_chr = (struct baseband_usb *) 0;
1102err1: return err;
1103}
1104
1105static void baseband_usb_chr_exit(void)
1106{
1107 pr_debug("baseband_usb_chr_exit {\n");
1108
1109 /* unregister character device */
1110 unregister_chrdev(BASEBAND_USB_CHR_DEV_MAJOR,
1111 BASEBAND_USB_CHR_DEV_NAME);
1112
1113 /* close baseband usb */
1114 if (baseband_usb_chr) {
1115 baseband_usb_close(baseband_usb_chr);
1116 baseband_usb_chr = (struct baseband_usb *) 0;
1117 }
1118
1119 pr_debug("baseband_usb_chr_exit }\n");
1120}
1121
1122module_init(baseband_usb_chr_init)
1123module_exit(baseband_usb_chr_exit)
1124