blob: dcbd761fff9e1ad0630b26b6348ff88d073436b9 [file] [log] [blame]
Hemant Kumar37c35e42011-09-14 23:44:19 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
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/slab.h>
14#include <linux/kernel.h>
15#include <linux/device.h>
16#include <linux/uaccess.h>
17#include <linux/termios.h>
18#include <linux/ratelimit.h>
19#include <linux/debugfs.h>
20#include "rmnet_usb_ctrl.h"
21
22#define DEVICE_NAME "hsicctl"
23#define NUM_CTRL_CHANNELS 4
24#define DEFAULT_READ_URB_LENGTH 0x1000
25
26/*Output control lines.*/
27#define ACM_CTRL_DTR BIT(0)
28#define ACM_CTRL_RTS BIT(1)
29
30
31/*Input control lines.*/
32#define ACM_CTRL_DSR BIT(0)
33#define ACM_CTRL_CTS BIT(1)
34#define ACM_CTRL_RI BIT(2)
35#define ACM_CTRL_CD BIT(3)
36
37/* polling interval for Interrupt ep */
38#define HS_INTERVAL 7
39#define FS_LS_INTERVAL 3
40
41/*echo modem_wait > /sys/class/hsicctl/hsicctlx/modem_wait*/
42static ssize_t modem_wait_store(struct device *d, struct device_attribute *attr,
43 const char *buf, size_t n)
44{
45 unsigned int mdm_wait;
46 struct rmnet_ctrl_dev *dev = dev_get_drvdata(d);
47
48 if (!dev)
49 return -ENODEV;
50
51 sscanf(buf, "%u", &mdm_wait);
52
53 dev->mdm_wait_timeout = mdm_wait;
54
55 return n;
56}
57
58static ssize_t modem_wait_show(struct device *d, struct device_attribute *attr,
59 char *buf)
60{
61 struct rmnet_ctrl_dev *dev = dev_get_drvdata(d);
62
63 if (!dev)
64 return -ENODEV;
65
66 return snprintf(buf, PAGE_SIZE, "%u\n", dev->mdm_wait_timeout);
67}
68
69static DEVICE_ATTR(modem_wait, 0666, modem_wait_show, modem_wait_store);
70
71static int ctl_msg_dbg_mask;
72module_param_named(dump_ctrl_msg, ctl_msg_dbg_mask, int,
73 S_IRUGO | S_IWUSR | S_IWGRP);
74
75enum {
76 MSM_USB_CTL_DEBUG = 1U << 0,
77 MSM_USB_CTL_DUMP_BUFFER = 1U << 1,
78};
79
80#define DUMP_BUFFER(prestr, cnt, buf) \
81do { \
82 if (ctl_msg_dbg_mask & MSM_USB_CTL_DUMP_BUFFER) \
83 print_hex_dump(KERN_INFO, prestr, DUMP_PREFIX_NONE, \
84 16, 1, buf, cnt, false); \
85} while (0)
86
87#define DBG(x...) \
88 do { \
89 if (ctl_msg_dbg_mask & MSM_USB_CTL_DEBUG) \
90 pr_info(x); \
91 } while (0)
92
93struct rmnet_ctrl_dev *ctrl_dev[NUM_CTRL_CHANNELS];
94struct class *ctrldev_classp;
95static dev_t ctrldev_num;
96
97struct ctrl_pkt {
98 size_t data_size;
99 void *data;
100};
101
102struct ctrl_pkt_list_elem {
103 struct list_head list;
104 struct ctrl_pkt cpkt;
105};
106
107static void resp_avail_cb(struct urb *);
108
109static int is_dev_connected(struct rmnet_ctrl_dev *dev)
110{
111 if (dev) {
112 mutex_lock(&dev->dev_lock);
113 if (!dev->intf) {
114 mutex_unlock(&dev->dev_lock);
115 return 0;
116 }
117 mutex_unlock(&dev->dev_lock);
118 return 1;
119 }
120 return 0;
121}
122
123static void notification_available_cb(struct urb *urb)
124{
125 int status;
126 struct usb_cdc_notification *ctrl;
127 struct usb_device *udev;
128 struct rmnet_ctrl_dev *dev = urb->context;
129
130 udev = interface_to_usbdev(dev->intf);
131
132 switch (urb->status) {
133 case 0:
134 /*success*/
135 break;
136
137 /*do not resubmit*/
138 case -ESHUTDOWN:
139 case -ENOENT:
140 case -ECONNRESET:
141 case -EPROTO:
142 return;
143 case -EPIPE:
144 pr_err_ratelimited("%s: Stall on int endpoint\n", __func__);
145 /* TBD : halt to be cleared in work */
146 return;
147
148 /*resubmit*/
149 case -EOVERFLOW:
150 pr_err_ratelimited("%s: Babble error happened\n", __func__);
151 default:
152 pr_debug_ratelimited("%s: Non zero urb status = %d\n",
153 __func__, urb->status);
154 goto resubmit_int_urb;
155 }
156
157 ctrl = urb->transfer_buffer;
158
159 switch (ctrl->bNotificationType) {
160 case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
161 dev->resp_avail_cnt++;
162 usb_fill_control_urb(dev->rcvurb, udev,
163 usb_rcvctrlpipe(udev, 0),
164 (unsigned char *)dev->in_ctlreq,
165 dev->rcvbuf,
166 DEFAULT_READ_URB_LENGTH,
167 resp_avail_cb, dev);
168
169 status = usb_submit_urb(dev->rcvurb, GFP_ATOMIC);
170 if (status) {
171 dev_err(dev->devicep,
172 "%s: Error submitting Read URB %d\n", __func__, status);
173 goto resubmit_int_urb;
174 }
175
176 if (!dev->resp_available) {
177 dev->resp_available = true;
178 wake_up(&dev->open_wait_queue);
179 }
180
181 return;
182 default:
183 dev_err(dev->devicep,
184 "%s:Command not implemented\n", __func__);
185 }
186
187resubmit_int_urb:
188 status = usb_submit_urb(urb, GFP_ATOMIC);
189 if (status)
190 dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
191 __func__, status);
192
193 return;
194}
195
196static void resp_avail_cb(struct urb *urb)
197{
198 struct usb_device *udev;
199 struct ctrl_pkt_list_elem *list_elem = NULL;
200 struct rmnet_ctrl_dev *dev = urb->context;
201 void *cpkt;
202 int status = 0;
203 size_t cpkt_size = 0;
204
205 udev = interface_to_usbdev(dev->intf);
206
207 switch (urb->status) {
208 case 0:
209 /*success*/
210 dev->get_encap_resp_cnt++;
211 break;
212
213 /*do not resubmit*/
214 case -ESHUTDOWN:
215 case -ENOENT:
216 case -ECONNRESET:
217 case -EPROTO:
218 return;
219
220 /*resubmit*/
221 case -EOVERFLOW:
222 pr_err_ratelimited("%s: Babble error happened\n", __func__);
223 default:
224 pr_debug_ratelimited("%s: Non zero urb status = %d\n",
225 __func__, urb->status);
226 goto resubmit_int_urb;
227 }
228
229 dev_dbg(dev->devicep, "Read %d bytes for %s\n",
230 urb->actual_length, dev->name);
231
232 cpkt = urb->transfer_buffer;
233 cpkt_size = urb->actual_length;
234
235 list_elem = kmalloc(sizeof(struct ctrl_pkt_list_elem), GFP_ATOMIC);
236 if (!list_elem) {
237 dev_err(dev->devicep, "%s: list_elem alloc failed\n", __func__);
238 return;
239 }
240 list_elem->cpkt.data = kmalloc(cpkt_size, GFP_ATOMIC);
241 if (!list_elem->cpkt.data) {
242 dev_err(dev->devicep, "%s: list_elem->data alloc failed\n",
243 __func__);
244 kfree(list_elem);
245 return;
246 }
247 memcpy(list_elem->cpkt.data, cpkt, cpkt_size);
248 list_elem->cpkt.data_size = cpkt_size;
249 spin_lock(&dev->rx_lock);
250 list_add_tail(&list_elem->list, &dev->rx_list);
251 spin_unlock(&dev->rx_lock);
252
253 wake_up(&dev->read_wait_queue);
254
255resubmit_int_urb:
256 /*re-submit int urb to check response available*/
257 status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
258 if (status)
259 dev_err(dev->devicep, "%s: Error re-submitting Int URB %d\n",
260 __func__, status);
261}
262
263static int rmnet_usb_ctrl_start_rx(struct rmnet_ctrl_dev *dev)
264{
265 int retval = 0;
266
267 retval = usb_autopm_get_interface(dev->intf);
268 if (retval < 0) {
269 dev_err(dev->devicep, "%s Resumption fail\n", __func__);
270 goto done_nopm;
271 }
272
273 retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
274 if (retval < 0)
275 dev_err(dev->devicep, "%s Intr submit %d\n", __func__, retval);
276
277 usb_autopm_put_interface(dev->intf);
278
279done_nopm:
280 return retval;
281}
282
283int rmnet_usb_ctrl_stop_rx(struct rmnet_ctrl_dev *dev)
284{
285 if (!is_dev_connected(dev)) {
286 dev_dbg(dev->devicep, "%s: Ctrl device disconnected\n",
287 __func__);
288 return -ENODEV;
289 }
290
291 dev_dbg(dev->devicep, "%s\n", __func__);
292
293 usb_kill_urb(dev->rcvurb);
294 usb_kill_urb(dev->inturb);
295
296 return 0;
297}
298
299int rmnet_usb_ctrl_start(struct rmnet_ctrl_dev *dev)
300{
301 int status = 0;
302
303 mutex_lock(&dev->dev_lock);
304 if (dev->is_opened)
305 status = rmnet_usb_ctrl_start_rx(dev);
306 mutex_unlock(&dev->dev_lock);
307
308 return status;
309}
310
311static int rmnet_usb_ctrl_alloc_rx(struct rmnet_ctrl_dev *dev)
312{
313 int retval = -ENOMEM;
314
315 dev->rcvurb = usb_alloc_urb(0, GFP_KERNEL);
316 if (!dev->rcvurb) {
317 pr_err("%s: Error allocating read urb\n", __func__);
318 goto nomem;
319 }
320
321 dev->rcvbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
322 if (!dev->rcvbuf) {
323 pr_err("%s: Error allocating read buffer\n", __func__);
324 goto nomem;
325 }
326
327 dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
328 if (!dev->in_ctlreq) {
329 pr_err("%s: Error allocating setup packet buffer\n", __func__);
330 goto nomem;
331 }
332
333 return 0;
334
335nomem:
336 usb_free_urb(dev->rcvurb);
337 kfree(dev->rcvbuf);
338 kfree(dev->in_ctlreq);
339
340 return retval;
341
342}
343static int rmnet_usb_ctrl_write_cmd(struct rmnet_ctrl_dev *dev)
344{
345 int retval = 0;
346 struct usb_device *udev;
347
348 if (!is_dev_connected(dev))
349 return -ENODEV;
350
351 udev = interface_to_usbdev(dev->intf);
352 retval = usb_autopm_get_interface(dev->intf);
353 if (retval < 0) {
354 dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
355 __func__, retval);
356
357 /*
358 * Revisit if (retval == -EPERM)
359 * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND);
360 */
361
362 return retval;
363 }
364 dev->set_ctrl_line_state_cnt++;
365 retval = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
366 USB_CDC_REQ_SET_CONTROL_LINE_STATE,
367 (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE),
368 dev->cbits_tomdm,
369 dev->intf->cur_altsetting->desc.bInterfaceNumber,
370 NULL, 0, USB_CTRL_SET_TIMEOUT);
371 usb_autopm_put_interface(dev->intf);
372
373 return retval;
374}
375
376static void ctrl_write_callback(struct urb *urb)
377{
378 struct rmnet_ctrl_dev *dev = urb->context;
379
380 if (urb->status) {
381 dev->tx_ctrl_err_cnt++;
382 pr_debug_ratelimited("Write status/size %d/%d\n",
383 urb->status, urb->actual_length);
384 }
385
386 kfree(urb->setup_packet);
387 kfree(urb->transfer_buffer);
388 usb_free_urb(urb);
389 usb_autopm_put_interface_async(dev->intf);
390}
391
392static int rmnet_usb_ctrl_write(struct rmnet_ctrl_dev *dev, char *buf,
393 size_t size)
394{
395 int result;
396 struct urb *sndurb;
397 struct usb_ctrlrequest *out_ctlreq;
398 struct usb_device *udev;
399
400 if (!is_dev_connected(dev))
401 return -ENETRESET;
402
403 udev = interface_to_usbdev(dev->intf);
404
405 sndurb = usb_alloc_urb(0, GFP_KERNEL);
406 if (!sndurb) {
407 dev_err(dev->devicep, "Error allocating read urb\n");
408 return -ENOMEM;
409 }
410
411 out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_KERNEL);
412 if (!out_ctlreq) {
413 usb_free_urb(sndurb);
414 dev_err(dev->devicep, "Error allocating setup packet buffer\n");
415 return -ENOMEM;
416 }
417
418 /* CDC Send Encapsulated Request packet */
419 out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
420 USB_RECIP_INTERFACE);
421 out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
422 out_ctlreq->wValue = 0;
423 out_ctlreq->wIndex = dev->intf->cur_altsetting->desc.bInterfaceNumber;
424 out_ctlreq->wLength = cpu_to_le16(size);
425
426 usb_fill_control_urb(sndurb, udev,
427 usb_sndctrlpipe(udev, 0),
428 (unsigned char *)out_ctlreq, (void *)buf, size,
429 ctrl_write_callback, dev);
430
431 result = usb_autopm_get_interface_async(dev->intf);
432 if (result < 0) {
433 dev_err(dev->devicep, "%s: Unable to resume interface: %d\n",
434 __func__, result);
435
436 /*
437 * Revisit: if (result == -EPERM)
438 * rmnet_usb_suspend(dev->intf, PMSG_SUSPEND);
439 */
440
441 usb_free_urb(sndurb);
442 kfree(out_ctlreq);
443 return result;
444 }
445
446 usb_anchor_urb(sndurb, &dev->tx_submitted);
447 dev->snd_encap_cmd_cnt++;
448 result = usb_submit_urb(sndurb, GFP_KERNEL);
449 if (result < 0) {
450 dev_err(dev->devicep, "%s: Submit URB error %d\n",
451 __func__, result);
452 dev->snd_encap_cmd_cnt--;
453 usb_autopm_put_interface_async(dev->intf);
454 usb_unanchor_urb(sndurb);
455 usb_free_urb(sndurb);
456 kfree(out_ctlreq);
457 return result;
458 }
459
460 return size;
461}
462
463static int rmnet_ctl_open(struct inode *inode, struct file *file)
464{
465 int retval = 0;
466 struct rmnet_ctrl_dev *dev =
467 container_of(inode->i_cdev, struct rmnet_ctrl_dev, cdev);
468
469 if (!dev)
470 return -ENODEV;
471
472 if (dev->is_opened)
473 goto already_opened;
474
475ctrl_open:
476 if (!is_dev_connected(dev)) {
477 dev_dbg(dev->devicep, "%s: Device not connected\n",
478 __func__);
479 return -ENODEV;
480 }
481
482 /*block open to get first response available from mdm*/
483 if (dev->mdm_wait_timeout && !dev->resp_available) {
484 retval = wait_event_interruptible_timeout(
485 dev->open_wait_queue,
486 dev->resp_available ||
487 !is_dev_connected(dev),
488 msecs_to_jiffies(dev->mdm_wait_timeout *
489 1000));
490 if (retval == 0) {
491 dev_err(dev->devicep, "%s: Timeout opening %s\n",
492 __func__, dev->name);
493 return -ETIMEDOUT;
494 } else if (retval < 0) {
495 dev_err(dev->devicep, "%s: Error waiting for %s\n",
496 __func__, dev->name);
497 return retval;
498 }
499
500 goto ctrl_open;
501 }
502
503 if (!dev->resp_available) {
504 dev_dbg(dev->devicep, "%s: Connection timedout opening %s\n",
505 __func__, dev->name);
506 return -ETIMEDOUT;
507 }
508
509 mutex_lock(&dev->dev_lock);
510 dev->is_opened = 1;
511 mutex_unlock(&dev->dev_lock);
512
513 file->private_data = dev;
514
515already_opened:
516 DBG("%s: Open called for %s\n", __func__, dev->name);
517
518 return 0;
519}
520
521static int rmnet_ctl_release(struct inode *inode, struct file *file)
522{
523 struct ctrl_pkt_list_elem *list_elem = NULL;
524 struct rmnet_ctrl_dev *dev;
525 unsigned long flag;
526
527 dev = file->private_data;
528 if (!dev)
529 return -ENODEV;
530
531 DBG("%s Called on %s device\n", __func__, dev->name);
532
533 spin_lock_irqsave(&dev->rx_lock, flag);
534 while (!list_empty(&dev->rx_list)) {
535 list_elem = list_first_entry(
536 &dev->rx_list,
537 struct ctrl_pkt_list_elem,
538 list);
539 list_del(&list_elem->list);
540 kfree(list_elem->cpkt.data);
541 kfree(list_elem);
542 }
543 spin_unlock_irqrestore(&dev->rx_lock, flag);
544
545 mutex_lock(&dev->dev_lock);
546 dev->is_opened = 0;
547 mutex_unlock(&dev->dev_lock);
548
549 rmnet_usb_ctrl_stop_rx(dev);
550
551 if (is_dev_connected(dev))
552 usb_kill_anchored_urbs(&dev->tx_submitted);
553
554 file->private_data = NULL;
555
556 return 0;
557}
558
559static ssize_t rmnet_ctl_read(struct file *file, char __user *buf, size_t count,
560 loff_t *ppos)
561{
562 int retval = 0;
563 int bytes_to_read;
564 struct rmnet_ctrl_dev *dev;
565 struct ctrl_pkt_list_elem *list_elem = NULL;
566 unsigned long flags;
567
568 dev = file->private_data;
569 if (!dev)
570 return -ENODEV;
571
572 DBG("%s: Read from %s\n", __func__, dev->name);
573
574ctrl_read:
575 if (!is_dev_connected(dev)) {
Hemant Kumar4fa3ac52012-02-29 18:09:23 -0800576 dev_dbg(dev->devicep, "%s: Device not connected\n",
Hemant Kumar37c35e42011-09-14 23:44:19 -0700577 __func__);
578 return -ENETRESET;
579 }
580 spin_lock_irqsave(&dev->rx_lock, flags);
581 if (list_empty(&dev->rx_list)) {
582 spin_unlock_irqrestore(&dev->rx_lock, flags);
583
584 retval = wait_event_interruptible(dev->read_wait_queue,
585 !list_empty(&dev->rx_list) ||
586 !is_dev_connected(dev));
587 if (retval < 0)
588 return retval;
589
590 goto ctrl_read;
591 }
592
593 list_elem = list_first_entry(&dev->rx_list,
594 struct ctrl_pkt_list_elem, list);
595 bytes_to_read = (uint32_t)(list_elem->cpkt.data_size);
596 if (bytes_to_read > count) {
597 spin_unlock_irqrestore(&dev->rx_lock, flags);
598 dev_err(dev->devicep, "%s: Packet size %d > buf size %d\n",
599 __func__, bytes_to_read, count);
600 return -ENOMEM;
601 }
602 spin_unlock_irqrestore(&dev->rx_lock, flags);
603
604 if (copy_to_user(buf, list_elem->cpkt.data, bytes_to_read)) {
605 dev_err(dev->devicep,
606 "%s: copy_to_user failed for %s\n",
607 __func__, dev->name);
608 return -EFAULT;
609 }
610 spin_lock_irqsave(&dev->rx_lock, flags);
611 list_del(&list_elem->list);
612 spin_unlock_irqrestore(&dev->rx_lock, flags);
613
614 kfree(list_elem->cpkt.data);
615 kfree(list_elem);
616 DBG("%s: Returning %d bytes to %s\n", __func__, bytes_to_read,
617 dev->name);
618 DUMP_BUFFER("Read: ", bytes_to_read, buf);
619
620 return bytes_to_read;
621}
622
623static ssize_t rmnet_ctl_write(struct file *file, const char __user * buf,
624 size_t size, loff_t *pos)
625{
626 int status;
627 void *wbuf;
628 struct rmnet_ctrl_dev *dev = file->private_data;
629
630 if (!dev)
631 return -ENODEV;
632
633 if (size <= 0)
634 return -EINVAL;
635
636 if (!is_dev_connected(dev))
637 return -ENETRESET;
638
639 DBG("%s: Writing %i bytes on %s\n", __func__, size, dev->name);
640
641 wbuf = kmalloc(size , GFP_KERNEL);
642 if (!wbuf)
643 return -ENOMEM;
644
645 status = copy_from_user(wbuf , buf, size);
646 if (status) {
647 dev_err(dev->devicep,
648 "%s: Unable to copy data from userspace %d\n",
649 __func__, status);
650 kfree(wbuf);
651 return status;
652 }
653 DUMP_BUFFER("Write: ", size, buf);
654
655 status = rmnet_usb_ctrl_write(dev, wbuf, size);
656 if (status == size)
657 return size;
658
659 return status;
660}
661
662static int rmnet_ctrl_tiocmset(struct rmnet_ctrl_dev *dev, unsigned int set,
663 unsigned int clear)
664{
665 mutex_lock(&dev->dev_lock);
666 if (set & TIOCM_DTR)
667 dev->cbits_tomdm |= ACM_CTRL_DTR;
668
669 /*
670 * TBD if (set & TIOCM_RTS)
671 * dev->cbits_tomdm |= ACM_CTRL_RTS;
672 */
673
674 if (clear & TIOCM_DTR)
675 dev->cbits_tomdm &= ~ACM_CTRL_DTR;
676
677 /*
678 * (clear & TIOCM_RTS)
679 * dev->cbits_tomdm &= ~ACM_CTRL_RTS;
680 */
681
682 mutex_unlock(&dev->dev_lock);
683
684 return rmnet_usb_ctrl_write_cmd(dev);
685}
686
687static int rmnet_ctrl_tiocmget(struct rmnet_ctrl_dev *dev)
688{
689 int ret;
690
691 mutex_lock(&dev->dev_lock);
692 ret =
693 /*
694 * TBD(dev->cbits_tolocal & ACM_CTRL_DSR ? TIOCM_DSR : 0) |
695 * (dev->cbits_tolocal & ACM_CTRL_CTS ? TIOCM_CTS : 0) |
696 */
697 (dev->cbits_tolocal & ACM_CTRL_CD ? TIOCM_CD : 0) |
698 /*
699 * TBD (dev->cbits_tolocal & ACM_CTRL_RI ? TIOCM_RI : 0) |
700 *(dev->cbits_tomdm & ACM_CTRL_RTS ? TIOCM_RTS : 0) |
701 */
702 (dev->cbits_tomdm & ACM_CTRL_DTR ? TIOCM_DTR : 0);
703 mutex_unlock(&dev->dev_lock);
704
705 return ret;
706}
707
708static long rmnet_ctrl_ioctl(struct file *file, unsigned int cmd,
709 unsigned long arg)
710{
711 int ret;
712 struct rmnet_ctrl_dev *dev;
713
714 dev = file->private_data;
715 if (!dev)
716 return -ENODEV;
717
718 switch (cmd) {
719 case TIOCMGET:
720
721 ret = rmnet_ctrl_tiocmget(dev);
722 break;
723 case TIOCMSET:
724 ret = rmnet_ctrl_tiocmset(dev, arg, ~arg);
725 break;
726 default:
727 ret = -EINVAL;
728 }
729
730 return ret;
731}
732
733static const struct file_operations ctrldev_fops = {
734 .owner = THIS_MODULE,
735 .read = rmnet_ctl_read,
736 .write = rmnet_ctl_write,
737 .unlocked_ioctl = rmnet_ctrl_ioctl,
738 .open = rmnet_ctl_open,
739 .release = rmnet_ctl_release,
740};
741
742int rmnet_usb_ctrl_probe(struct usb_interface *intf,
743 struct usb_host_endpoint *int_in, struct rmnet_ctrl_dev *dev)
744{
745 u16 wMaxPacketSize;
746 struct usb_endpoint_descriptor *ep;
747 struct usb_device *udev;
748 int interval;
749 int ret = 0;
750
751 udev = interface_to_usbdev(intf);
752
753 if (!dev) {
754 pr_err("%s: Ctrl device not found\n", __func__);
755 return -ENODEV;
756 }
757 dev->int_pipe = usb_rcvintpipe(udev,
758 int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
759
760 mutex_lock(&dev->dev_lock);
761 dev->intf = intf;
762
763 /*TBD: for now just update CD status*/
764 dev->cbits_tolocal = ACM_CTRL_CD;
765
766 /*send DTR high to modem*/
767 dev->cbits_tomdm = ACM_CTRL_DTR;
768 mutex_unlock(&dev->dev_lock);
769
770 dev->resp_available = false;
771 dev->snd_encap_cmd_cnt = 0;
772 dev->get_encap_resp_cnt = 0;
773 dev->resp_avail_cnt = 0;
774 dev->tx_ctrl_err_cnt = 0;
775 dev->set_ctrl_line_state_cnt = 0;
776
777 dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
778 if (!dev->inturb) {
779 dev_err(dev->devicep, "Error allocating int urb\n");
780 return -ENOMEM;
781 }
782
783 /*use max pkt size from ep desc*/
784 ep = &dev->intf->cur_altsetting->endpoint[0].desc;
785 wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
786
787 dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
788 if (!dev->intbuf) {
789 usb_free_urb(dev->inturb);
790 dev_err(dev->devicep, "Error allocating int buffer\n");
791 return -ENOMEM;
792 }
793
794 dev->in_ctlreq->bRequestType =
795 (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
796 dev->in_ctlreq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
797 dev->in_ctlreq->wValue = 0;
798 dev->in_ctlreq->wIndex =
799 dev->intf->cur_altsetting->desc.bInterfaceNumber;
800 dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
801
802 interval =
803 max((int)int_in->desc.bInterval,
804 (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL);
805
806 usb_fill_int_urb(dev->inturb, udev,
807 dev->int_pipe,
808 dev->intbuf, wMaxPacketSize,
809 notification_available_cb, dev, interval);
810
811 ret = rmnet_usb_ctrl_write_cmd(dev);
812 if (ret < 0)
813 return ret;
814
815 return rmnet_usb_ctrl_start_rx(dev);
816}
817
818void rmnet_usb_ctrl_disconnect(struct rmnet_ctrl_dev *dev)
819{
820 rmnet_usb_ctrl_stop_rx(dev);
821
822 mutex_lock(&dev->dev_lock);
823
824 /*TBD: for now just update CD status*/
825 dev->cbits_tolocal = ~ACM_CTRL_CD;
826
827 dev->cbits_tomdm = ~ACM_CTRL_DTR;
828 dev->intf = NULL;
829 mutex_unlock(&dev->dev_lock);
830
Hemant Kumar4fa3ac52012-02-29 18:09:23 -0800831 wake_up(&dev->read_wait_queue);
832
Hemant Kumar37c35e42011-09-14 23:44:19 -0700833 usb_free_urb(dev->inturb);
834 dev->inturb = NULL;
835
836 kfree(dev->intbuf);
837 dev->intbuf = NULL;
838
839 usb_kill_anchored_urbs(&dev->tx_submitted);
840}
841
842#if defined(CONFIG_DEBUG_FS)
843#define DEBUG_BUF_SIZE 1024
844static ssize_t rmnet_usb_ctrl_read_stats(struct file *file, char __user *ubuf,
845 size_t count, loff_t *ppos)
846{
847 struct rmnet_ctrl_dev *dev;
848 char *buf;
849 int ret;
850 int i;
851 int temp = 0;
852
853 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
854 if (!buf)
855 return -ENOMEM;
856
857 for (i = 0; i < NUM_CTRL_CHANNELS; i++) {
858 dev = ctrl_dev[i];
859 if (!dev)
860 continue;
861
862 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
863 "\n#ctrl_dev: %p Name: %s#\n"
864 "snd encap cmd cnt %u\n"
865 "resp avail cnt: %u\n"
866 "get encap resp cnt: %u\n"
867 "set ctrl line state cnt: %u\n"
868 "tx_err_cnt: %u\n"
869 "cbits_tolocal: %d\n"
870 "cbits_tomdm: %d\n"
871 "mdm_wait_timeout: %u\n"
872 "dev opened: %s\n",
873 dev, dev->name,
874 dev->snd_encap_cmd_cnt,
875 dev->resp_avail_cnt,
876 dev->get_encap_resp_cnt,
877 dev->set_ctrl_line_state_cnt,
878 dev->tx_ctrl_err_cnt,
879 dev->cbits_tolocal,
880 dev->cbits_tomdm,
881 dev->mdm_wait_timeout,
882 dev->is_opened ? "OPEN" : "CLOSE");
883
884 }
885
886 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
887
888 kfree(buf);
889
890 return ret;
891}
892
893static ssize_t rmnet_usb_ctrl_reset_stats(struct file *file, const char __user *
894 buf, size_t count, loff_t *ppos)
895{
896 struct rmnet_ctrl_dev *dev;
897 int i;
898
899 for (i = 0; i < NUM_CTRL_CHANNELS; i++) {
900 dev = ctrl_dev[i];
901 if (!dev)
902 continue;
903
904 dev->snd_encap_cmd_cnt = 0;
905 dev->resp_avail_cnt = 0;
906 dev->get_encap_resp_cnt = 0;
907 dev->set_ctrl_line_state_cnt = 0;
908 dev->tx_ctrl_err_cnt = 0;
909 }
910 return count;
911}
912
913const struct file_operations rmnet_usb_ctrl_stats_ops = {
914 .read = rmnet_usb_ctrl_read_stats,
915 .write = rmnet_usb_ctrl_reset_stats,
916};
917
918struct dentry *usb_ctrl_dent;
919struct dentry *usb_ctrl_dfile;
920static void rmnet_usb_ctrl_debugfs_init(void)
921{
922 usb_ctrl_dent = debugfs_create_dir("rmnet_usb_ctrl", 0);
923 if (IS_ERR(usb_ctrl_dent))
924 return;
925
926 usb_ctrl_dfile = debugfs_create_file("status", 0644, usb_ctrl_dent, 0,
927 &rmnet_usb_ctrl_stats_ops);
928 if (!usb_ctrl_dfile || IS_ERR(usb_ctrl_dfile))
929 debugfs_remove(usb_ctrl_dent);
930}
931
932static void rmnet_usb_ctrl_debugfs_exit(void)
933{
934 debugfs_remove(usb_ctrl_dfile);
935 debugfs_remove(usb_ctrl_dent);
936}
937
938#else
939static void rmnet_usb_ctrl_debugfs_init(void) { }
940static void rmnet_usb_ctrl_debugfs_exit(void) { }
941#endif
942
943int rmnet_usb_ctrl_init(void)
944{
945 struct rmnet_ctrl_dev *dev;
946 int n;
947 int status;
948
949 for (n = 0; n < NUM_CTRL_CHANNELS; ++n) {
950
951 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
952 if (!dev) {
953 status = -ENOMEM;
954 goto error0;
955 }
956 /*for debug purpose*/
957 snprintf(dev->name, CTRL_DEV_MAX_LEN, "hsicctl%d", n);
958
959 mutex_init(&dev->dev_lock);
960 spin_lock_init(&dev->rx_lock);
961 init_waitqueue_head(&dev->read_wait_queue);
962 init_waitqueue_head(&dev->open_wait_queue);
963 INIT_LIST_HEAD(&dev->rx_list);
964 init_usb_anchor(&dev->tx_submitted);
965
966 status = rmnet_usb_ctrl_alloc_rx(dev);
967 if (status < 0) {
968 kfree(dev);
969 goto error0;
970 }
971
972 ctrl_dev[n] = dev;
973 }
974
975 status = alloc_chrdev_region(&ctrldev_num, 0, NUM_CTRL_CHANNELS,
976 DEVICE_NAME);
977 if (IS_ERR_VALUE(status)) {
978 pr_err("ERROR:%s: alloc_chrdev_region() ret %i.\n",
979 __func__, status);
980 goto error0;
981 }
982
983 ctrldev_classp = class_create(THIS_MODULE, DEVICE_NAME);
984 if (IS_ERR(ctrldev_classp)) {
985 pr_err("ERROR:%s: class_create() ENOMEM\n", __func__);
986 status = -ENOMEM;
987 goto error1;
988 }
989 for (n = 0; n < NUM_CTRL_CHANNELS; ++n) {
990 cdev_init(&ctrl_dev[n]->cdev, &ctrldev_fops);
991 ctrl_dev[n]->cdev.owner = THIS_MODULE;
992
993 status = cdev_add(&ctrl_dev[n]->cdev, (ctrldev_num + n), 1);
994
995 if (IS_ERR_VALUE(status)) {
996 pr_err("%s: cdev_add() ret %i\n", __func__, status);
997 kfree(ctrl_dev[n]);
998 goto error2;
999 }
1000
1001 ctrl_dev[n]->devicep =
1002 device_create(ctrldev_classp, NULL,
1003 (ctrldev_num + n), NULL,
1004 DEVICE_NAME "%d", n);
1005
1006 if (IS_ERR(ctrl_dev[n]->devicep)) {
1007 pr_err("%s: device_create() ENOMEM\n", __func__);
1008 status = -ENOMEM;
1009 cdev_del(&ctrl_dev[n]->cdev);
1010 kfree(ctrl_dev[n]);
1011 goto error2;
1012 }
1013 /*create /sys/class/hsicctl/hsicctlx/modem_wait*/
1014 status = device_create_file(ctrl_dev[n]->devicep,
1015 &dev_attr_modem_wait);
1016 if (status) {
1017 device_destroy(ctrldev_classp,
1018 MKDEV(MAJOR(ctrldev_num), n));
1019 cdev_del(&ctrl_dev[n]->cdev);
1020 kfree(ctrl_dev[n]);
1021 goto error2;
1022 }
1023 dev_set_drvdata(ctrl_dev[n]->devicep, ctrl_dev[n]);
1024 }
1025
1026 rmnet_usb_ctrl_debugfs_init();
1027 pr_info("rmnet usb ctrl Initialized.\n");
1028 return 0;
1029
1030error2:
1031 while (--n >= 0) {
1032 cdev_del(&ctrl_dev[n]->cdev);
1033 device_destroy(ctrldev_classp,
1034 MKDEV(MAJOR(ctrldev_num), n));
1035 }
1036
1037 class_destroy(ctrldev_classp);
1038 n = NUM_CTRL_CHANNELS;
1039error1:
1040 unregister_chrdev_region(MAJOR(ctrldev_num), NUM_CTRL_CHANNELS);
1041error0:
1042 while (--n >= 0)
1043 kfree(ctrl_dev[n]);
1044
1045 return status;
1046}
1047
1048void rmnet_usb_ctrl_exit(void)
1049{
1050 int i;
1051
1052 for (i = 0; i < NUM_CTRL_CHANNELS; ++i) {
1053 if (!ctrl_dev[i])
1054 return;
1055
1056 kfree(ctrl_dev[i]->in_ctlreq);
1057 kfree(ctrl_dev[i]->rcvbuf);
1058 kfree(ctrl_dev[i]->intbuf);
1059 usb_free_urb(ctrl_dev[i]->rcvurb);
1060 usb_free_urb(ctrl_dev[i]->inturb);
1061#if defined(DEBUG)
1062 device_remove_file(ctrl_dev[i]->devicep, &dev_attr_modem_wait);
1063#endif
1064 cdev_del(&ctrl_dev[i]->cdev);
1065 kfree(ctrl_dev[i]);
1066 ctrl_dev[i] = NULL;
1067 device_destroy(ctrldev_classp, MKDEV(MAJOR(ctrldev_num), i));
1068 }
1069
1070 class_destroy(ctrldev_classp);
1071 unregister_chrdev_region(MAJOR(ctrldev_num), NUM_CTRL_CHANNELS);
1072 rmnet_usb_ctrl_debugfs_exit();
1073}