blob: 2b56ee03304f5bea0b1c9e6a72e8310c559310df [file] [log] [blame]
Hemant Kumar262682a2013-02-01 09:46:45 -08001/* Copyright (c) 2011-2013, The Linux Foundation. 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;
Hemant Kumar14401d52011-11-03 16:40:32 -0700131 int status = 0;
132 int resubmit_urb = 1;
133 struct bridge *brdg = dev->brdg;
134
Hemant Kumar262682a2013-02-01 09:46:45 -0800135 /*usb device disconnect*/
136 if (urb->dev->state == USB_STATE_NOTATTACHED)
137 return;
138
Hemant Kumar14401d52011-11-03 16:40:32 -0700139 switch (urb->status) {
140 case 0:
141 /*success*/
142 dev->get_encap_res++;
143 if (brdg && brdg->ops.send_pkt)
144 brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer,
145 urb->actual_length);
146 break;
147
148 /*do not resubmit*/
149 case -ESHUTDOWN:
150 case -ENOENT:
151 case -ECONNRESET:
152 /* unplug */
153 case -EPROTO:
154 /*babble error*/
155 resubmit_urb = 0;
156 /*resubmit*/
157 case -EOVERFLOW:
158 default:
Jack Phame8741502012-06-13 17:34:07 -0700159 dev_dbg(&dev->intf->dev, "%s: non zero urb status = %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700160 __func__, urb->status);
161 }
162
163 if (resubmit_urb) {
164 /*re- submit int urb to check response available*/
165 status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
Hemant Kumar262682a2013-02-01 09:46:45 -0800166 if (status)
Jack Phame8741502012-06-13 17:34:07 -0700167 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700168 "%s: Error re-submitting Int URB %d\n",
169 __func__, status);
170 }
171}
172
173static void notification_available_cb(struct urb *urb)
174{
175 int status;
176 struct usb_cdc_notification *ctrl;
Hemant Kumar14401d52011-11-03 16:40:32 -0700177 struct ctrl_bridge *dev = urb->context;
178 struct bridge *brdg = dev->brdg;
179 unsigned int ctrl_bits;
180 unsigned char *data;
181
Hemant Kumar262682a2013-02-01 09:46:45 -0800182 /*usb device disconnect*/
183 if (urb->dev->state == USB_STATE_NOTATTACHED)
184 return;
185
Hemant Kumar14401d52011-11-03 16:40:32 -0700186 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:
Jack Phame8741502012-06-13 17:34:07 -0700197 dev_err(&dev->intf->dev,
198 "%s: stall on int endpoint\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700199 /* TBD : halt to be cleared in work */
200 case -EOVERFLOW:
201 default:
202 pr_debug_ratelimited("%s: non zero urb status = %d\n",
203 __func__, urb->status);
204 goto resubmit_int_urb;
205 }
206
207 ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
208 data = (unsigned char *)(ctrl + 1);
209
210 switch (ctrl->bNotificationType) {
211 case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
212 dev->resp_avail++;
Jack Phame8741502012-06-13 17:34:07 -0700213 usb_fill_control_urb(dev->readurb, dev->udev,
214 usb_rcvctrlpipe(dev->udev, 0),
Hemant Kumar14401d52011-11-03 16:40:32 -0700215 (unsigned char *)dev->in_ctlreq,
216 dev->readbuf,
217 DEFAULT_READ_URB_LENGTH,
218 resp_avail_cb, dev);
219
220 status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
221 if (status) {
Jack Phame8741502012-06-13 17:34:07 -0700222 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700223 "%s: Error submitting Read URB %d\n",
224 __func__, status);
225 goto resubmit_int_urb;
226 }
227 return;
228 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
Jack Phame8741502012-06-13 17:34:07 -0700229 dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
Hemant Kumar14401d52011-11-03 16:40:32 -0700230 "connected to" : "disconnected from");
231 break;
232 case USB_CDC_NOTIFY_SERIAL_STATE:
233 dev->notify_ser_state++;
234 ctrl_bits = get_unaligned_le16(data);
Jack Phame8741502012-06-13 17:34:07 -0700235 dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
Hemant Kumar14401d52011-11-03 16:40:32 -0700236 dev->cbits_tohost = ctrl_bits;
237 if (brdg && brdg->ops.send_cbits)
238 brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
239 break;
240 default:
Jack Phame8741502012-06-13 17:34:07 -0700241 dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
Hemant Kumar14401d52011-11-03 16:40:32 -0700242 "index %d len %d data0 %d data1 %d",
243 __func__, ctrl->bNotificationType, ctrl->wIndex,
244 ctrl->wLength, data[0], data[1]);
245 }
246
247resubmit_int_urb:
248 status = usb_submit_urb(urb, GFP_ATOMIC);
Hemant Kumar262682a2013-02-01 09:46:45 -0800249 if (status)
Jack Phame8741502012-06-13 17:34:07 -0700250 dev_err(&dev->intf->dev, "%s: Error re-submitting Int URB %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700251 __func__, status);
252}
253
Jack Phamb9d67c62012-05-22 18:38:53 -0700254static int ctrl_bridge_start_read(struct ctrl_bridge *dev)
Hemant Kumar14401d52011-11-03 16:40:32 -0700255{
Jack Pham9b0a0e52012-02-28 18:05:14 -0800256 int retval = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700257
Jack Pham9b0a0e52012-02-28 18:05:14 -0800258 if (!dev->inturb) {
Jack Phame8741502012-06-13 17:34:07 -0700259 dev_err(&dev->intf->dev, "%s: inturb is NULL\n", __func__);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800260 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700261 }
262
Hemant Kumar262682a2013-02-01 09:46:45 -0800263 retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
264 if (retval < 0)
265 dev_err(&dev->intf->dev,
266 "%s error submitting int urb %d\n",
267 __func__, retval);
Hemant Kumar14401d52011-11-03 16:40:32 -0700268
Hemant Kumar14401d52011-11-03 16:40:32 -0700269 return retval;
270}
271
Hemant Kumar14401d52011-11-03 16:40:32 -0700272int ctrl_bridge_open(struct bridge *brdg)
273{
274 struct ctrl_bridge *dev;
275
276 if (!brdg) {
277 err("bridge is null\n");
278 return -EINVAL;
279 }
280
281 if (brdg->ch_id >= MAX_BRIDGE_DEVICES)
282 return -EINVAL;
283
284 dev = __dev[brdg->ch_id];
285 if (!dev) {
286 err("dev is null\n");
287 return -ENODEV;
288 }
289
290 dev->brdg = brdg;
291 dev->snd_encap_cmd = 0;
292 dev->get_encap_res = 0;
293 dev->resp_avail = 0;
294 dev->set_ctrl_line_sts = 0;
295 dev->notify_ser_state = 0;
296
Jack Phamb9d67c62012-05-22 18:38:53 -0700297 if (brdg->ops.send_cbits)
298 brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800299
Jack Phamb9d67c62012-05-22 18:38:53 -0700300 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700301}
302EXPORT_SYMBOL(ctrl_bridge_open);
303
304void ctrl_bridge_close(unsigned int id)
305{
306 struct ctrl_bridge *dev;
307
308 if (id >= MAX_BRIDGE_DEVICES)
309 return;
310
311 dev = __dev[id];
Jack Phama7c92672011-11-29 16:38:21 -0800312 if (!dev || !dev->brdg)
Hemant Kumar14401d52011-11-03 16:40:32 -0700313 return;
314
Jack Phame8741502012-06-13 17:34:07 -0700315 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700316
317 ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
Hemant Kumar14401d52011-11-03 16:40:32 -0700318
319 dev->brdg = NULL;
320}
321EXPORT_SYMBOL(ctrl_bridge_close);
322
323static void ctrl_write_callback(struct urb *urb)
324{
Hemant Kumarf13358e2012-01-19 12:07:20 -0800325 struct ctrl_bridge *dev = urb->context;
Hemant Kumar14401d52011-11-03 16:40:32 -0700326
327 if (urb->status) {
328 pr_debug("Write status/size %d/%d\n",
329 urb->status, urb->actual_length);
330 }
331
332 kfree(urb->transfer_buffer);
333 kfree(urb->setup_packet);
334 usb_free_urb(urb);
Hemant Kumar262682a2013-02-01 09:46:45 -0800335
336 /* if we are here after device disconnect
337 * usb_unbind_interface() takes care of
338 * residual pm_autopm_get_interface_* calls
339 */
340 if (urb->dev->state != USB_STATE_NOTATTACHED)
341 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700342}
343
344int ctrl_bridge_write(unsigned int id, char *data, size_t size)
345{
346 int result;
347 struct urb *writeurb;
348 struct usb_ctrlrequest *out_ctlreq;
Hemant Kumar14401d52011-11-03 16:40:32 -0700349 struct ctrl_bridge *dev;
350
351 if (id >= MAX_BRIDGE_DEVICES) {
352 result = -EINVAL;
353 goto free_data;
354 }
355
356 dev = __dev[id];
357
358 if (!dev) {
359 result = -ENODEV;
360 goto free_data;
361 }
362
Jack Phame8741502012-06-13 17:34:07 -0700363 dev_dbg(&dev->intf->dev, "%s:[id]:%u: write (%d bytes)\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700364 __func__, id, size);
365
366 writeurb = usb_alloc_urb(0, GFP_ATOMIC);
367 if (!writeurb) {
Jack Phame8741502012-06-13 17:34:07 -0700368 dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700369 __func__);
370 result = -ENOMEM;
371 goto free_data;
372 }
373
374 out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
375 if (!out_ctlreq) {
Jack Phame8741502012-06-13 17:34:07 -0700376 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700377 "%s: error allocating setup packet buffer\n",
378 __func__);
379 result = -ENOMEM;
380 goto free_urb;
381 }
382
383 /* CDC Send Encapsulated Request packet */
384 out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
385 USB_RECIP_INTERFACE);
386 if (!data && !size) {
387 out_ctlreq->bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
388 out_ctlreq->wValue = dev->cbits_tomdm;
389 dev->set_ctrl_line_sts++;
390 } else {
391 out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
392 out_ctlreq->wValue = 0;
393 dev->snd_encap_cmd++;
394 }
395 out_ctlreq->wIndex =
396 dev->intf->cur_altsetting->desc.bInterfaceNumber;
397 out_ctlreq->wLength = cpu_to_le16(size);
398
Jack Phame8741502012-06-13 17:34:07 -0700399 usb_fill_control_urb(writeurb, dev->udev,
400 usb_sndctrlpipe(dev->udev, 0),
Hemant Kumar14401d52011-11-03 16:40:32 -0700401 (unsigned char *)out_ctlreq,
402 (void *)data, size,
Hemant Kumarf13358e2012-01-19 12:07:20 -0800403 ctrl_write_callback, dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700404
405 result = usb_autopm_get_interface_async(dev->intf);
406 if (result < 0) {
Jack Pham4380e002012-08-30 19:06:24 -0700407 dev_dbg(&dev->intf->dev, "%s: unable to resume interface: %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700408 __func__, result);
409
410 /*
411 * Revisit: if (result == -EPERM)
412 * bridge_suspend(dev->intf, PMSG_SUSPEND);
413 */
414
415 goto free_ctrlreq;
416 }
417
Jack Pham9b0a0e52012-02-28 18:05:14 -0800418 if (test_bit(SUSPENDED, &dev->flags)) {
419 usb_anchor_urb(writeurb, &dev->tx_deferred);
420 goto deferred;
421 }
422
Hemant Kumar14401d52011-11-03 16:40:32 -0700423 usb_anchor_urb(writeurb, &dev->tx_submitted);
424 result = usb_submit_urb(writeurb, GFP_ATOMIC);
425 if (result < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700426 dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700427 __func__, result);
428 usb_autopm_put_interface_async(dev->intf);
429 goto unanchor_urb;
430 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800431deferred:
Hemant Kumar14401d52011-11-03 16:40:32 -0700432 return size;
433
434unanchor_urb:
435 usb_unanchor_urb(writeurb);
436free_ctrlreq:
437 kfree(out_ctlreq);
438free_urb:
439 usb_free_urb(writeurb);
440free_data:
441 kfree(data);
442
443 return result;
444}
445EXPORT_SYMBOL(ctrl_bridge_write);
446
447int ctrl_bridge_suspend(unsigned int id)
448{
449 struct ctrl_bridge *dev;
450
451 if (id >= MAX_BRIDGE_DEVICES)
452 return -EINVAL;
453
454 dev = __dev[id];
455 if (!dev)
456 return -ENODEV;
457
Jack Pham9b0a0e52012-02-28 18:05:14 -0800458 set_bit(SUSPENDED, &dev->flags);
Hemant Kumar262682a2013-02-01 09:46:45 -0800459 usb_kill_urb(dev->inturb);
460 usb_kill_urb(dev->readurb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700461 usb_kill_anchored_urbs(&dev->tx_submitted);
462
Jack Pham9b0a0e52012-02-28 18:05:14 -0800463 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700464}
465
466int ctrl_bridge_resume(unsigned int id)
467{
468 struct ctrl_bridge *dev;
Jack Pham9b0a0e52012-02-28 18:05:14 -0800469 struct urb *urb;
Hemant Kumar14401d52011-11-03 16:40:32 -0700470
471 if (id >= MAX_BRIDGE_DEVICES)
472 return -EINVAL;
473
474 dev = __dev[id];
475 if (!dev)
476 return -ENODEV;
477
Jack Pham9b0a0e52012-02-28 18:05:14 -0800478 if (!test_and_clear_bit(SUSPENDED, &dev->flags))
479 return 0;
480
481 /* submit pending write requests */
482 while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
483 int ret;
484 usb_anchor_urb(urb, &dev->tx_submitted);
485 ret = usb_submit_urb(urb, GFP_ATOMIC);
486 if (ret < 0) {
487 usb_unanchor_urb(urb);
488 kfree(urb->setup_packet);
489 kfree(urb->transfer_buffer);
490 usb_free_urb(urb);
491 usb_autopm_put_interface_async(dev->intf);
492 }
493 }
494
Jack Phamb9d67c62012-05-22 18:38:53 -0700495 return ctrl_bridge_start_read(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700496}
497
498#if defined(CONFIG_DEBUG_FS)
499#define DEBUG_BUF_SIZE 1024
500static ssize_t ctrl_bridge_read_stats(struct file *file, char __user *ubuf,
501 size_t count, loff_t *ppos)
502{
503 struct ctrl_bridge *dev;
504 char *buf;
505 int ret;
506 int i;
507 int temp = 0;
508
509 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
510 if (!buf)
511 return -ENOMEM;
512
513 for (i = 0; i < ch_id; i++) {
514 dev = __dev[i];
515 if (!dev)
516 continue;
517
518 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
519 "\nName#%s dev %p\n"
520 "snd encap cmd cnt: %u\n"
521 "get encap res cnt: %u\n"
522 "res available cnt: %u\n"
523 "set ctrlline sts cnt: %u\n"
524 "notify ser state cnt: %u\n"
525 "cbits_tomdm: %d\n"
Jack Pham9b0a0e52012-02-28 18:05:14 -0800526 "cbits_tohost: %d\n"
527 "suspended: %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700528 dev->pdev->name, dev,
529 dev->snd_encap_cmd,
530 dev->get_encap_res,
531 dev->resp_avail,
532 dev->set_ctrl_line_sts,
533 dev->notify_ser_state,
534 dev->cbits_tomdm,
Jack Pham9b0a0e52012-02-28 18:05:14 -0800535 dev->cbits_tohost,
536 test_bit(SUSPENDED, &dev->flags));
Hemant Kumar14401d52011-11-03 16:40:32 -0700537 }
538
539 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
540
541 kfree(buf);
542
543 return ret;
544}
545
546static ssize_t ctrl_bridge_reset_stats(struct file *file,
547 const char __user *buf, size_t count, loff_t *ppos)
548{
549 struct ctrl_bridge *dev;
550 int i;
551
552 for (i = 0; i < ch_id; i++) {
553 dev = __dev[i];
554 if (!dev)
555 continue;
556
557 dev->snd_encap_cmd = 0;
558 dev->get_encap_res = 0;
559 dev->resp_avail = 0;
560 dev->set_ctrl_line_sts = 0;
561 dev->notify_ser_state = 0;
562 }
563 return count;
564}
565
566const struct file_operations ctrl_stats_ops = {
567 .read = ctrl_bridge_read_stats,
568 .write = ctrl_bridge_reset_stats,
569};
570
571struct dentry *ctrl_dent;
572struct dentry *ctrl_dfile;
573static void ctrl_bridge_debugfs_init(void)
574{
575 ctrl_dent = debugfs_create_dir("ctrl_hsic_bridge", 0);
576 if (IS_ERR(ctrl_dent))
577 return;
578
579 ctrl_dfile =
580 debugfs_create_file("status", 0644, ctrl_dent, 0,
581 &ctrl_stats_ops);
582 if (!ctrl_dfile || IS_ERR(ctrl_dfile))
583 debugfs_remove(ctrl_dent);
584}
585
586static void ctrl_bridge_debugfs_exit(void)
587{
588 debugfs_remove(ctrl_dfile);
589 debugfs_remove(ctrl_dent);
590}
591
592#else
593static void ctrl_bridge_debugfs_init(void) { }
594static void ctrl_bridge_debugfs_exit(void) { }
595#endif
596
597int
598ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
599 int id)
600{
601 struct ctrl_bridge *dev;
602 struct usb_device *udev;
603 struct usb_endpoint_descriptor *ep;
604 u16 wMaxPacketSize;
605 int retval = 0;
606 int interval;
607
608 udev = interface_to_usbdev(ifc);
609
Hemant Kumar262682a2013-02-01 09:46:45 -0800610 dev = __dev[id];
Hemant Kumar14401d52011-11-03 16:40:32 -0700611 if (!dev) {
Hemant Kumar262682a2013-02-01 09:46:45 -0800612 pr_err("%s:device not found\n", __func__);
613 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700614 }
Hemant Kumar262682a2013-02-01 09:46:45 -0800615
Hemant Kumar14401d52011-11-03 16:40:32 -0700616 dev->pdev = platform_device_alloc(ctrl_bridge_names[id], id);
617 if (!dev->pdev) {
Jack Phame8741502012-06-13 17:34:07 -0700618 dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
619 __func__);
Hemant Kumar262682a2013-02-01 09:46:45 -0800620 return -ENOMEM;
Hemant Kumar14401d52011-11-03 16:40:32 -0700621 }
622
Hemant Kumar262682a2013-02-01 09:46:45 -0800623 dev->flags = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700624 dev->udev = udev;
625 dev->int_pipe = usb_rcvintpipe(udev,
626 int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
627 dev->intf = ifc;
628
Hemant Kumar14401d52011-11-03 16:40:32 -0700629 /*use max pkt size from ep desc*/
630 ep = &dev->intf->cur_altsetting->endpoint[0].desc;
631
632 dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
633 if (!dev->inturb) {
Jack Phame8741502012-06-13 17:34:07 -0700634 dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700635 retval = -ENOMEM;
636 goto pdev_del;
637 }
638
639 wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
640
641 dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
642 if (!dev->intbuf) {
Jack Phame8741502012-06-13 17:34:07 -0700643 dev_err(&ifc->dev, "%s: error allocating int buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700644 __func__);
645 retval = -ENOMEM;
646 goto free_inturb;
647 }
648
649 interval =
650 (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL;
651
652 usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
653 dev->intbuf, wMaxPacketSize,
654 notification_available_cb, dev, interval);
655
656 dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
657 if (!dev->readurb) {
Jack Phame8741502012-06-13 17:34:07 -0700658 dev_err(&ifc->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700659 __func__);
660 retval = -ENOMEM;
661 goto free_intbuf;
662 }
663
664 dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
665 if (!dev->readbuf) {
Jack Phame8741502012-06-13 17:34:07 -0700666 dev_err(&ifc->dev, "%s: error allocating read buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700667 __func__);
668 retval = -ENOMEM;
669 goto free_rurb;
670 }
671
672 dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
673 if (!dev->in_ctlreq) {
Jack Phame8741502012-06-13 17:34:07 -0700674 dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700675 __func__);
676 retval = -ENOMEM;
677 goto free_rbuf;
678 }
679
680 dev->in_ctlreq->bRequestType =
681 (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
682 dev->in_ctlreq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
683 dev->in_ctlreq->wValue = 0;
684 dev->in_ctlreq->wIndex =
685 dev->intf->cur_altsetting->desc.bInterfaceNumber;
686 dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
687
Hemant Kumar14401d52011-11-03 16:40:32 -0700688 platform_device_add(dev->pdev);
689
690 ch_id++;
691
Jack Phamb9d67c62012-05-22 18:38:53 -0700692 return ctrl_bridge_start_read(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700693
694free_rbuf:
695 kfree(dev->readbuf);
696free_rurb:
697 usb_free_urb(dev->readurb);
698free_intbuf:
699 kfree(dev->intbuf);
700free_inturb:
701 usb_free_urb(dev->inturb);
702pdev_del:
Jack Pham1b1ba472012-06-13 16:40:15 -0700703 platform_device_unregister(dev->pdev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700704
705 return retval;
706}
707
708void ctrl_bridge_disconnect(unsigned int id)
709{
710 struct ctrl_bridge *dev = __dev[id];
711
Jack Phame8741502012-06-13 17:34:07 -0700712 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700713
Jack Pham1b1ba472012-06-13 16:40:15 -0700714 platform_device_unregister(dev->pdev);
Jack Pham452c6922011-12-14 18:15:26 -0800715
Hemant Kumar262682a2013-02-01 09:46:45 -0800716 usb_kill_anchored_urbs(&dev->tx_submitted);
717
718 usb_kill_urb(dev->inturb);
719 usb_kill_urb(dev->readurb);
Hemant Kumar77f79572012-11-08 12:19:26 -0800720
Hemant Kumar14401d52011-11-03 16:40:32 -0700721 kfree(dev->in_ctlreq);
722 kfree(dev->readbuf);
723 kfree(dev->intbuf);
724
725 usb_free_urb(dev->readurb);
726 usb_free_urb(dev->inturb);
727
Hemant Kumar14401d52011-11-03 16:40:32 -0700728 ch_id--;
Hemant Kumar14401d52011-11-03 16:40:32 -0700729}
730
Hemant Kumar262682a2013-02-01 09:46:45 -0800731int ctrl_bridge_init(void)
Hemant Kumar14401d52011-11-03 16:40:32 -0700732{
Hemant Kumar262682a2013-02-01 09:46:45 -0800733 struct ctrl_bridge *dev;
734 int i;
735 int retval = 0;
736
737 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
738
739 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
740 if (!dev) {
741 pr_err("%s: unable to allocate dev\n", __func__);
742 retval = -ENOMEM;
743 goto error;
744 }
745
746 init_usb_anchor(&dev->tx_submitted);
747 init_usb_anchor(&dev->tx_deferred);
748
749 __dev[i] = dev;
750 }
751
Hemant Kumar14401d52011-11-03 16:40:32 -0700752 ctrl_bridge_debugfs_init();
753
754 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700755
Hemant Kumar262682a2013-02-01 09:46:45 -0800756error:
757 while (--i >= 0) {
758 kfree(__dev[i]);
759 __dev[i] = NULL;
760 }
761
762 return retval;
763}
764
765void ctrl_bridge_exit(void)
Hemant Kumar14401d52011-11-03 16:40:32 -0700766{
Hemant Kumar262682a2013-02-01 09:46:45 -0800767 int i;
Hemant Kumar14401d52011-11-03 16:40:32 -0700768
Hemant Kumar262682a2013-02-01 09:46:45 -0800769 ctrl_bridge_debugfs_exit();
770
771 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
772 kfree(__dev[i]);
773 __dev[i] = NULL;
774 }
775}