blob: 49591cdb6874b2ec71937b678adbf2dfe680dd50 [file] [log] [blame]
Jack Pham9b0a0e52012-02-28 18:05:14 -08001/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Hemant Kumar14401d52011-11-03 16:40:32 -07002 *
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/errno.h>
15#include <linux/init.h>
16#include <linux/slab.h>
17#include <linux/module.h>
18#include <linux/kref.h>
19#include <linux/debugfs.h>
20#include <linux/platform_device.h>
21#include <linux/uaccess.h>
22#include <linux/ratelimit.h>
23#include <linux/usb/ch9.h>
24#include <linux/usb/cdc.h>
25#include <linux/termios.h>
26#include <asm/unaligned.h>
27#include <mach/usb_bridge.h>
28
29static const char *ctrl_bridge_names[] = {
30 "dun_ctrl_hsic0",
31 "rmnet_ctrl_hsic0"
32};
33
34/* polling interval for Interrupt ep */
35#define HS_INTERVAL 7
36#define FS_LS_INTERVAL 3
37
38#define ACM_CTRL_DTR (1 << 0)
39#define DEFAULT_READ_URB_LENGTH 4096
40
Jack Pham9b0a0e52012-02-28 18:05:14 -080041#define SUSPENDED BIT(0)
Hemant Kumar14401d52011-11-03 16:40:32 -070042
Jack Pham9b0a0e52012-02-28 18:05:14 -080043struct ctrl_bridge {
Hemant Kumar14401d52011-11-03 16:40:32 -070044 struct usb_device *udev;
45 struct usb_interface *intf;
46
47 unsigned int int_pipe;
48 struct urb *inturb;
49 void *intbuf;
50
51 struct urb *readurb;
52 void *readbuf;
53
54 struct usb_anchor tx_submitted;
Jack Pham9b0a0e52012-02-28 18:05:14 -080055 struct usb_anchor tx_deferred;
Hemant Kumar14401d52011-11-03 16:40:32 -070056 struct usb_ctrlrequest *in_ctlreq;
57
58 struct bridge *brdg;
59 struct platform_device *pdev;
60
Jack Pham9b0a0e52012-02-28 18:05:14 -080061 unsigned long flags;
62
Hemant Kumar14401d52011-11-03 16:40:32 -070063 /* input control lines (DSR, CTS, CD, RI) */
64 unsigned int cbits_tohost;
65
66 /* output control lines (DTR, RTS) */
67 unsigned int cbits_tomdm;
68
69 /* counters */
70 unsigned int snd_encap_cmd;
71 unsigned int get_encap_res;
72 unsigned int resp_avail;
73 unsigned int set_ctrl_line_sts;
74 unsigned int notify_ser_state;
Hemant Kumar14401d52011-11-03 16:40:32 -070075};
76
77static struct ctrl_bridge *__dev[MAX_BRIDGE_DEVICES];
78
79/* counter used for indexing ctrl bridge devices */
80static int ch_id;
81
82unsigned int ctrl_bridge_get_cbits_tohost(unsigned int id)
83{
84 struct ctrl_bridge *dev;
85
86 if (id >= MAX_BRIDGE_DEVICES)
87 return -EINVAL;
88
89 dev = __dev[id];
90 if (!dev)
91 return -ENODEV;
92
93 return dev->cbits_tohost;
94}
95EXPORT_SYMBOL(ctrl_bridge_get_cbits_tohost);
96
97int ctrl_bridge_set_cbits(unsigned int id, unsigned int cbits)
98{
99 struct ctrl_bridge *dev;
100 struct bridge *brdg;
101 int retval;
102
103 if (id >= MAX_BRIDGE_DEVICES)
104 return -EINVAL;
105
106 dev = __dev[id];
107 if (!dev)
108 return -ENODEV;
109
110 pr_debug("%s: dev[id] =%u cbits : %u\n", __func__, id, cbits);
111
112 brdg = dev->brdg;
113 if (!brdg)
114 return -ENODEV;
115
116 dev->cbits_tomdm = cbits;
117
118 retval = ctrl_bridge_write(id, NULL, 0);
119
120 /* if DTR is high, update latest modem info to host */
121 if (brdg && (cbits & ACM_CTRL_DTR) && brdg->ops.send_cbits)
122 brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
123
124 return retval;
125}
126EXPORT_SYMBOL(ctrl_bridge_set_cbits);
127
128static void resp_avail_cb(struct urb *urb)
129{
130 struct ctrl_bridge *dev = urb->context;
131 struct usb_device *udev;
132 int status = 0;
133 int resubmit_urb = 1;
134 struct bridge *brdg = dev->brdg;
135
136 udev = interface_to_usbdev(dev->intf);
137 switch (urb->status) {
138 case 0:
139 /*success*/
140 dev->get_encap_res++;
141 if (brdg && brdg->ops.send_pkt)
142 brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer,
143 urb->actual_length);
144 break;
145
146 /*do not resubmit*/
147 case -ESHUTDOWN:
148 case -ENOENT:
149 case -ECONNRESET:
150 /* unplug */
151 case -EPROTO:
152 /*babble error*/
153 resubmit_urb = 0;
154 /*resubmit*/
155 case -EOVERFLOW:
156 default:
157 dev_dbg(&udev->dev, "%s: non zero urb status = %d\n",
158 __func__, urb->status);
159 }
160
161 if (resubmit_urb) {
162 /*re- submit int urb to check response available*/
Jack Pham9b0a0e52012-02-28 18:05:14 -0800163 usb_anchor_urb(dev->inturb, &dev->tx_submitted);
Hemant Kumar14401d52011-11-03 16:40:32 -0700164 status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800165 if (status) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700166 dev_err(&udev->dev,
167 "%s: Error re-submitting Int URB %d\n",
168 __func__, status);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800169 usb_unanchor_urb(dev->inturb);
170 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700171 }
172}
173
174static void notification_available_cb(struct urb *urb)
175{
176 int status;
177 struct usb_cdc_notification *ctrl;
178 struct usb_device *udev;
179 struct ctrl_bridge *dev = urb->context;
180 struct bridge *brdg = dev->brdg;
181 unsigned int ctrl_bits;
182 unsigned char *data;
183
184 udev = interface_to_usbdev(dev->intf);
185
186 switch (urb->status) {
187 case 0:
188 /*success*/
189 break;
190 case -ESHUTDOWN:
191 case -ENOENT:
192 case -ECONNRESET:
193 case -EPROTO:
194 /* unplug */
195 return;
196 case -EPIPE:
197 dev_err(&udev->dev, "%s: stall on int endpoint\n", __func__);
198 /* TBD : halt to be cleared in work */
199 case -EOVERFLOW:
200 default:
201 pr_debug_ratelimited("%s: non zero urb status = %d\n",
202 __func__, urb->status);
203 goto resubmit_int_urb;
204 }
205
206 ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
207 data = (unsigned char *)(ctrl + 1);
208
209 switch (ctrl->bNotificationType) {
210 case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
211 dev->resp_avail++;
212 usb_fill_control_urb(dev->readurb, udev,
213 usb_rcvctrlpipe(udev, 0),
214 (unsigned char *)dev->in_ctlreq,
215 dev->readbuf,
216 DEFAULT_READ_URB_LENGTH,
217 resp_avail_cb, dev);
218
Jack Pham9b0a0e52012-02-28 18:05:14 -0800219 usb_anchor_urb(dev->readurb, &dev->tx_submitted);
Hemant Kumar14401d52011-11-03 16:40:32 -0700220 status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
221 if (status) {
222 dev_err(&udev->dev,
223 "%s: Error submitting Read URB %d\n",
224 __func__, status);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800225 usb_unanchor_urb(dev->readurb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700226 goto resubmit_int_urb;
227 }
228 return;
229 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
230 dev_dbg(&udev->dev, "%s network\n", ctrl->wValue ?
231 "connected to" : "disconnected from");
232 break;
233 case USB_CDC_NOTIFY_SERIAL_STATE:
234 dev->notify_ser_state++;
235 ctrl_bits = get_unaligned_le16(data);
236 dev_dbg(&udev->dev, "serial state: %d\n", ctrl_bits);
237 dev->cbits_tohost = ctrl_bits;
238 if (brdg && brdg->ops.send_cbits)
239 brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
240 break;
241 default:
242 dev_err(&udev->dev, "%s: unknown notification %d received:"
243 "index %d len %d data0 %d data1 %d",
244 __func__, ctrl->bNotificationType, ctrl->wIndex,
245 ctrl->wLength, data[0], data[1]);
246 }
247
248resubmit_int_urb:
Jack Pham9b0a0e52012-02-28 18:05:14 -0800249 usb_anchor_urb(urb, &dev->tx_submitted);
Hemant Kumar14401d52011-11-03 16:40:32 -0700250 status = usb_submit_urb(urb, GFP_ATOMIC);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800251 if (status) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700252 dev_err(&udev->dev, "%s: Error re-submitting Int URB %d\n",
253 __func__, status);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800254 usb_unanchor_urb(urb);
255 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700256}
257
Jack Phamb9d67c62012-05-22 18:38:53 -0700258static int ctrl_bridge_start_read(struct ctrl_bridge *dev)
Hemant Kumar14401d52011-11-03 16:40:32 -0700259{
Jack Pham9b0a0e52012-02-28 18:05:14 -0800260 int retval = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700261
Jack Pham9b0a0e52012-02-28 18:05:14 -0800262 if (!dev->inturb) {
263 dev_err(&dev->udev->dev, "%s: inturb is NULL\n", __func__);
264 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700265 }
266
Jack Pham9b0a0e52012-02-28 18:05:14 -0800267 if (!dev->inturb->anchor) {
268 usb_anchor_urb(dev->inturb, &dev->tx_submitted);
269 retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
270 if (retval < 0) {
271 dev_err(&dev->udev->dev,
272 "%s error submitting int urb %d\n",
273 __func__, retval);
274 usb_unanchor_urb(dev->inturb);
275 }
276 }
Hemant Kumar14401d52011-11-03 16:40:32 -0700277
Hemant Kumar14401d52011-11-03 16:40:32 -0700278 return retval;
279}
280
Hemant Kumar14401d52011-11-03 16:40:32 -0700281int ctrl_bridge_open(struct bridge *brdg)
282{
283 struct ctrl_bridge *dev;
284
285 if (!brdg) {
286 err("bridge is null\n");
287 return -EINVAL;
288 }
289
290 if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
291 return -EINVAL;
292
293 dev = __dev[brdg->ch_id];
294 if (!dev) {
295 err("dev is null\n");
296 return -ENODEV;
297 }
298
299 dev->brdg = brdg;
300 dev->snd_encap_cmd = 0;
301 dev->get_encap_res = 0;
302 dev->resp_avail = 0;
303 dev->set_ctrl_line_sts = 0;
304 dev->notify_ser_state = 0;
305
Jack Phamb9d67c62012-05-22 18:38:53 -0700306 if (brdg->ops.send_cbits)
307 brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800308
Jack Phamb9d67c62012-05-22 18:38:53 -0700309 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700310}
311EXPORT_SYMBOL(ctrl_bridge_open);
312
313void ctrl_bridge_close(unsigned int id)
314{
315 struct ctrl_bridge *dev;
316
317 if (id >= MAX_BRIDGE_DEVICES)
318 return;
319
320 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800321 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700322 return;
323
324 dev_dbg(&dev->udev->dev, "%s:\n", __func__);
325
326 ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
327 usb_unlink_anchored_urbs(&dev->tx_submitted);
Hemant Kumar14401d52011-11-03 16:40:32 -0700328
329 dev->brdg = NULL;
330}
331EXPORT_SYMBOL(ctrl_bridge_close);
332
333static void ctrl_write_callback(struct urb *urb)
334{
Hemant Kumarf13358e2012-01-19 12:07:20 -0800335 struct ctrl_bridge *dev = urb->context;
Hemant Kumar14401d52011-11-03 16:40:32 -0700336
337 if (urb->status) {
338 pr_debug("Write status/size %d/%d\n",
339 urb->status, urb->actual_length);
340 }
341
342 kfree(urb->transfer_buffer);
343 kfree(urb->setup_packet);
344 usb_free_urb(urb);
Hemant Kumarf13358e2012-01-19 12:07:20 -0800345 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700346}
347
348int ctrl_bridge_write(unsigned int id, char *data, size_t size)
349{
350 int result;
351 struct urb *writeurb;
352 struct usb_ctrlrequest *out_ctlreq;
353 struct usb_device *udev;
354 struct ctrl_bridge *dev;
355
356 if (id >= MAX_BRIDGE_DEVICES) {
357 result = -EINVAL;
358 goto free_data;
359 }
360
361 dev = __dev[id];
362
363 if (!dev) {
364 result = -ENODEV;
365 goto free_data;
366 }
367
368 udev = interface_to_usbdev(dev->intf);
369
370 dev_dbg(&udev->dev, "%s:[id]:%u: write (%d bytes)\n",
371 __func__, id, size);
372
373 writeurb = usb_alloc_urb(0, GFP_ATOMIC);
374 if (!writeurb) {
375 dev_err(&udev->dev, "%s: error allocating read urb\n",
376 __func__);
377 result = -ENOMEM;
378 goto free_data;
379 }
380
381 out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
382 if (!out_ctlreq) {
383 dev_err(&udev->dev,
384 "%s: error allocating setup packet buffer\n",
385 __func__);
386 result = -ENOMEM;
387 goto free_urb;
388 }
389
390 /* CDC Send Encapsulated Request packet */
391 out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
392 USB_RECIP_INTERFACE);
393 if (!data && !size) {
394 out_ctlreq->bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
395 out_ctlreq->wValue = dev->cbits_tomdm;
396 dev->set_ctrl_line_sts++;
397 } else {
398 out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
399 out_ctlreq->wValue = 0;
400 dev->snd_encap_cmd++;
401 }
402 out_ctlreq->wIndex =
403 dev->intf->cur_altsetting->desc.bInterfaceNumber;
404 out_ctlreq->wLength = cpu_to_le16(size);
405
406 usb_fill_control_urb(writeurb, udev,
407 usb_sndctrlpipe(udev, 0),
408 (unsigned char *)out_ctlreq,
409 (void *)data, size,
Hemant Kumarf13358e2012-01-19 12:07:20 -0800410 ctrl_write_callback, dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700411
412 result = usb_autopm_get_interface_async(dev->intf);
413 if (result < 0) {
414 dev_err(&udev->dev, "%s: unable to resume interface: %d\n",
415 __func__, result);
416
417 /*
418 * Revisit: if (result == -EPERM)
419 * bridge_suspend(dev->intf, PMSG_SUSPEND);
420 */
421
422 goto free_ctrlreq;
423 }
424
Jack Pham9b0a0e52012-02-28 18:05:14 -0800425 if (test_bit(SUSPENDED, &dev->flags)) {
426 usb_anchor_urb(writeurb, &dev->tx_deferred);
427 goto deferred;
428 }
429
Hemant Kumar14401d52011-11-03 16:40:32 -0700430 usb_anchor_urb(writeurb, &dev->tx_submitted);
431 result = usb_submit_urb(writeurb, GFP_ATOMIC);
432 if (result < 0) {
433 dev_err(&udev->dev, "%s: submit URB error %d\n",
434 __func__, result);
435 usb_autopm_put_interface_async(dev->intf);
436 goto unanchor_urb;
437 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800438deferred:
Hemant Kumar14401d52011-11-03 16:40:32 -0700439 return size;
440
441unanchor_urb:
442 usb_unanchor_urb(writeurb);
443free_ctrlreq:
444 kfree(out_ctlreq);
445free_urb:
446 usb_free_urb(writeurb);
447free_data:
448 kfree(data);
449
450 return result;
451}
452EXPORT_SYMBOL(ctrl_bridge_write);
453
454int ctrl_bridge_suspend(unsigned int id)
455{
456 struct ctrl_bridge *dev;
457
458 if (id >= MAX_BRIDGE_DEVICES)
459 return -EINVAL;
460
461 dev = __dev[id];
462 if (!dev)
463 return -ENODEV;
464
Jack Pham9b0a0e52012-02-28 18:05:14 -0800465 set_bit(SUSPENDED, &dev->flags);
Hemant Kumar14401d52011-11-03 16:40:32 -0700466 usb_kill_anchored_urbs(&dev->tx_submitted);
467
Jack Pham9b0a0e52012-02-28 18:05:14 -0800468 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700469}
470
471int ctrl_bridge_resume(unsigned int id)
472{
473 struct ctrl_bridge *dev;
Jack Pham9b0a0e52012-02-28 18:05:14 -0800474 struct urb *urb;
Hemant Kumar14401d52011-11-03 16:40:32 -0700475
476 if (id >= MAX_BRIDGE_DEVICES)
477 return -EINVAL;
478
479 dev = __dev[id];
480 if (!dev)
481 return -ENODEV;
482
Jack Pham9b0a0e52012-02-28 18:05:14 -0800483 if (!test_and_clear_bit(SUSPENDED, &dev->flags))
484 return 0;
485
486 /* submit pending write requests */
487 while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
488 int ret;
489 usb_anchor_urb(urb, &dev->tx_submitted);
490 ret = usb_submit_urb(urb, GFP_ATOMIC);
491 if (ret < 0) {
492 usb_unanchor_urb(urb);
493 kfree(urb->setup_packet);
494 kfree(urb->transfer_buffer);
495 usb_free_urb(urb);
496 usb_autopm_put_interface_async(dev->intf);
497 }
498 }
499
Jack Phamb9d67c62012-05-22 18:38:53 -0700500 return ctrl_bridge_start_read(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700501}
502
503#if defined(CONFIG_DEBUG_FS)
504#define DEBUG_BUF_SIZE 1024
505static ssize_t ctrl_bridge_read_stats(struct file *file, char __user *ubuf,
506 size_t count, loff_t *ppos)
507{
508 struct ctrl_bridge *dev;
509 char *buf;
510 int ret;
511 int i;
512 int temp = 0;
513
514 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
515 if (!buf)
516 return -ENOMEM;
517
518 for (i = 0; i < ch_id; i++) {
519 dev = __dev[i];
520 if (!dev)
521 continue;
522
523 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
524 "\nName#%s dev %p\n"
525 "snd encap cmd cnt: %u\n"
526 "get encap res cnt: %u\n"
527 "res available cnt: %u\n"
528 "set ctrlline sts cnt: %u\n"
529 "notify ser state cnt: %u\n"
530 "cbits_tomdm: %d\n"
Jack Pham9b0a0e52012-02-28 18:05:14 -0800531 "cbits_tohost: %d\n"
532 "suspended: %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700533 dev->pdev->name, dev,
534 dev->snd_encap_cmd,
535 dev->get_encap_res,
536 dev->resp_avail,
537 dev->set_ctrl_line_sts,
538 dev->notify_ser_state,
539 dev->cbits_tomdm,
Jack Pham9b0a0e52012-02-28 18:05:14 -0800540 dev->cbits_tohost,
541 test_bit(SUSPENDED, &dev->flags));
Hemant Kumar14401d52011-11-03 16:40:32 -0700542 }
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 ctrl_bridge_reset_stats(struct file *file,
552 const char __user *buf, size_t count, loff_t *ppos)
553{
554 struct ctrl_bridge *dev;
555 int i;
556
557 for (i = 0; i < ch_id; i++) {
558 dev = __dev[i];
559 if (!dev)
560 continue;
561
562 dev->snd_encap_cmd = 0;
563 dev->get_encap_res = 0;
564 dev->resp_avail = 0;
565 dev->set_ctrl_line_sts = 0;
566 dev->notify_ser_state = 0;
567 }
568 return count;
569}
570
571const struct file_operations ctrl_stats_ops = {
572 .read = ctrl_bridge_read_stats,
573 .write = ctrl_bridge_reset_stats,
574};
575
576struct dentry *ctrl_dent;
577struct dentry *ctrl_dfile;
578static void ctrl_bridge_debugfs_init(void)
579{
580 ctrl_dent = debugfs_create_dir("ctrl_hsic_bridge", 0);
581 if (IS_ERR(ctrl_dent))
582 return;
583
584 ctrl_dfile =
585 debugfs_create_file("status", 0644, ctrl_dent, 0,
586 &ctrl_stats_ops);
587 if (!ctrl_dfile || IS_ERR(ctrl_dfile))
588 debugfs_remove(ctrl_dent);
589}
590
591static void ctrl_bridge_debugfs_exit(void)
592{
593 debugfs_remove(ctrl_dfile);
594 debugfs_remove(ctrl_dent);
595}
596
597#else
598static void ctrl_bridge_debugfs_init(void) { }
599static void ctrl_bridge_debugfs_exit(void) { }
600#endif
601
602int
603ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
604 int id)
605{
606 struct ctrl_bridge *dev;
607 struct usb_device *udev;
608 struct usb_endpoint_descriptor *ep;
609 u16 wMaxPacketSize;
610 int retval = 0;
611 int interval;
612
613 udev = interface_to_usbdev(ifc);
614
615 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
616 if (!dev) {
617 dev_err(&udev->dev, "%s: unable to allocate dev\n",
618 __func__);
619 return -ENOMEM;
620 }
621 dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
622 if (!dev->pdev) {
623 dev_err(&dev->udev->dev,
624 "%s: unable to allocate platform device\n", __func__);
625 retval = -ENOMEM;
626 goto nomem;
627 }
628
629 dev->udev = udev;
630 dev->int_pipe = usb_rcvintpipe(udev,
631 int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
632 dev->intf = ifc;
633
634 init_usb_anchor(&dev->tx_submitted);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800635 init_usb_anchor(&dev->tx_deferred);
Hemant Kumar14401d52011-11-03 16:40:32 -0700636
637 /*use max pkt size from ep desc*/
638 ep = &dev->intf->cur_altsetting->endpoint[0].desc;
639
640 dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
641 if (!dev->inturb) {
642 dev_err(&udev->dev, "%s: error allocating int urb\n", __func__);
643 retval = -ENOMEM;
644 goto pdev_del;
645 }
646
647 wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
648
649 dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
650 if (!dev->intbuf) {
651 dev_err(&udev->dev, "%s: error allocating int buffer\n",
652 __func__);
653 retval = -ENOMEM;
654 goto free_inturb;
655 }
656
657 interval =
658 (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL;
659
660 usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
661 dev->intbuf, wMaxPacketSize,
662 notification_available_cb, dev, interval);
663
664 dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
665 if (!dev->readurb) {
666 dev_err(&udev->dev, "%s: error allocating read urb\n",
667 __func__);
668 retval = -ENOMEM;
669 goto free_intbuf;
670 }
671
672 dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
673 if (!dev->readbuf) {
674 dev_err(&udev->dev, "%s: error allocating read buffer\n",
675 __func__);
676 retval = -ENOMEM;
677 goto free_rurb;
678 }
679
680 dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
681 if (!dev->in_ctlreq) {
682 dev_err(&udev->dev,
683 "%s:error allocating setup packet buffer\n",
684 __func__);
685 retval = -ENOMEM;
686 goto free_rbuf;
687 }
688
689 dev->in_ctlreq->bRequestType =
690 (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
691 dev->in_ctlreq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
692 dev->in_ctlreq->wValue = 0;
693 dev->in_ctlreq->wIndex =
694 dev->intf->cur_altsetting->desc.bInterfaceNumber;
695 dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
696
697 __dev[id] = dev;
698
699 platform_device_add(dev->pdev);
700
701 ch_id++;
702
Jack Phamb9d67c62012-05-22 18:38:53 -0700703 return ctrl_bridge_start_read(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700704
705free_rbuf:
706 kfree(dev->readbuf);
707free_rurb:
708 usb_free_urb(dev->readurb);
709free_intbuf:
710 kfree(dev->intbuf);
711free_inturb:
712 usb_free_urb(dev->inturb);
713pdev_del:
714 platform_device_del(dev->pdev);
715nomem:
716 kfree(dev);
717
718 return retval;
719}
720
721void ctrl_bridge_disconnect(unsigned int id)
722{
723 struct ctrl_bridge *dev = __dev[id];
724
725 dev_dbg(&dev->udev->dev, "%s:\n", __func__);
726
Jack Pham452c6922011-12-14 18:15:26 -0800727 platform_device_del(dev->pdev);
728
Hemant Kumar14401d52011-11-03 16:40:32 -0700729 kfree(dev->in_ctlreq);
730 kfree(dev->readbuf);
731 kfree(dev->intbuf);
732
733 usb_free_urb(dev->readurb);
734 usb_free_urb(dev->inturb);
735
Hemant Kumar14401d52011-11-03 16:40:32 -0700736 __dev[id] = NULL;
737 ch_id--;
738
739 kfree(dev);
740}
741
742static int __init ctrl_bridge_init(void)
743{
744 ctrl_bridge_debugfs_init();
745
746 return 0;
747}
748module_init(ctrl_bridge_init);
749
750static void __exit ctrl_bridge_exit(void)
751{
752 ctrl_bridge_debugfs_exit();
753}
754module_exit(ctrl_bridge_exit);
755
756MODULE_DESCRIPTION("Qualcomm modem control bridge driver");
757MODULE_LICENSE("GPL v2");