blob: 69e28e4ce1e59ed9fe380d75bd8a3c6b39d7fc9b [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
Hemant Kumar14401d52011-11-03 16:40:32 -070029/* polling interval for Interrupt ep */
30#define HS_INTERVAL 7
31#define FS_LS_INTERVAL 3
32
33#define ACM_CTRL_DTR (1 << 0)
34#define DEFAULT_READ_URB_LENGTH 4096
35
Jack Pham9b0a0e52012-02-28 18:05:14 -080036#define SUSPENDED BIT(0)
Hemant Kumar14401d52011-11-03 16:40:32 -070037
Jack Pham9b0a0e52012-02-28 18:05:14 -080038struct ctrl_bridge {
Hemant Kumar14401d52011-11-03 16:40:32 -070039 struct usb_device *udev;
40 struct usb_interface *intf;
41
Hemant Kumarc2b17782013-02-03 15:56:29 -080042 char *name;
43
Hemant Kumar14401d52011-11-03 16:40:32 -070044 unsigned int int_pipe;
45 struct urb *inturb;
46 void *intbuf;
47
48 struct urb *readurb;
49 void *readbuf;
50
51 struct usb_anchor tx_submitted;
Jack Pham9b0a0e52012-02-28 18:05:14 -080052 struct usb_anchor tx_deferred;
Hemant Kumar14401d52011-11-03 16:40:32 -070053 struct usb_ctrlrequest *in_ctlreq;
54
55 struct bridge *brdg;
56 struct platform_device *pdev;
57
Jack Pham9b0a0e52012-02-28 18:05:14 -080058 unsigned long flags;
59
Hemant Kumar14401d52011-11-03 16:40:32 -070060 /* input control lines (DSR, CTS, CD, RI) */
61 unsigned int cbits_tohost;
62
63 /* output control lines (DTR, RTS) */
64 unsigned int cbits_tomdm;
65
66 /* counters */
67 unsigned int snd_encap_cmd;
68 unsigned int get_encap_res;
69 unsigned int resp_avail;
70 unsigned int set_ctrl_line_sts;
71 unsigned int notify_ser_state;
Hemant Kumar14401d52011-11-03 16:40:32 -070072};
73
74static struct ctrl_bridge *__dev[MAX_BRIDGE_DEVICES];
75
Hemant Kumarc2b17782013-02-03 15:56:29 -080076static int get_ctrl_bridge_chid(char *xport_name)
77{
78 struct ctrl_bridge *dev;
79 int i;
80
81 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
82 dev = __dev[i];
83 if (!strncmp(dev->name, xport_name, BRIDGE_NAME_MAX_LEN))
84 return i;
85 }
86
87 return -ENODEV;
88}
89
Hemant Kumar14401d52011-11-03 16:40:32 -070090unsigned int ctrl_bridge_get_cbits_tohost(unsigned int id)
91{
92 struct ctrl_bridge *dev;
93
94 if (id >= MAX_BRIDGE_DEVICES)
95 return -EINVAL;
96
97 dev = __dev[id];
98 if (!dev)
99 return -ENODEV;
100
101 return dev->cbits_tohost;
102}
103EXPORT_SYMBOL(ctrl_bridge_get_cbits_tohost);
104
105int ctrl_bridge_set_cbits(unsigned int id, unsigned int cbits)
106{
107 struct ctrl_bridge *dev;
108 struct bridge *brdg;
109 int retval;
110
111 if (id >= MAX_BRIDGE_DEVICES)
112 return -EINVAL;
113
114 dev = __dev[id];
115 if (!dev)
116 return -ENODEV;
117
118 pr_debug("%s: dev[id] =%u cbits : %u\n", __func__, id, cbits);
119
120 brdg = dev->brdg;
121 if (!brdg)
122 return -ENODEV;
123
124 dev->cbits_tomdm = cbits;
125
126 retval = ctrl_bridge_write(id, NULL, 0);
127
128 /* if DTR is high, update latest modem info to host */
129 if (brdg && (cbits & ACM_CTRL_DTR) && brdg->ops.send_cbits)
130 brdg->ops.send_cbits(brdg->ctx, dev->cbits_tohost);
131
132 return retval;
133}
134EXPORT_SYMBOL(ctrl_bridge_set_cbits);
135
136static void resp_avail_cb(struct urb *urb)
137{
138 struct ctrl_bridge *dev = urb->context;
Hemant Kumar14401d52011-11-03 16:40:32 -0700139 int status = 0;
140 int resubmit_urb = 1;
141 struct bridge *brdg = dev->brdg;
142
Hemant Kumar262682a2013-02-01 09:46:45 -0800143 /*usb device disconnect*/
144 if (urb->dev->state == USB_STATE_NOTATTACHED)
145 return;
146
Hemant Kumar14401d52011-11-03 16:40:32 -0700147 switch (urb->status) {
148 case 0:
149 /*success*/
150 dev->get_encap_res++;
151 if (brdg && brdg->ops.send_pkt)
152 brdg->ops.send_pkt(brdg->ctx, urb->transfer_buffer,
153 urb->actual_length);
154 break;
155
156 /*do not resubmit*/
157 case -ESHUTDOWN:
158 case -ENOENT:
159 case -ECONNRESET:
160 /* unplug */
161 case -EPROTO:
162 /*babble error*/
163 resubmit_urb = 0;
164 /*resubmit*/
165 case -EOVERFLOW:
166 default:
Jack Phame8741502012-06-13 17:34:07 -0700167 dev_dbg(&dev->intf->dev, "%s: non zero urb status = %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700168 __func__, urb->status);
169 }
170
171 if (resubmit_urb) {
172 /*re- submit int urb to check response available*/
173 status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
Hemant Kumar262682a2013-02-01 09:46:45 -0800174 if (status)
Jack Phame8741502012-06-13 17:34:07 -0700175 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700176 "%s: Error re-submitting Int URB %d\n",
177 __func__, status);
178 }
179}
180
181static void notification_available_cb(struct urb *urb)
182{
183 int status;
184 struct usb_cdc_notification *ctrl;
Hemant Kumar14401d52011-11-03 16:40:32 -0700185 struct ctrl_bridge *dev = urb->context;
186 struct bridge *brdg = dev->brdg;
187 unsigned int ctrl_bits;
188 unsigned char *data;
189
Hemant Kumar262682a2013-02-01 09:46:45 -0800190 /*usb device disconnect*/
191 if (urb->dev->state == USB_STATE_NOTATTACHED)
192 return;
193
Hemant Kumar14401d52011-11-03 16:40:32 -0700194 switch (urb->status) {
195 case 0:
196 /*success*/
197 break;
198 case -ESHUTDOWN:
199 case -ENOENT:
200 case -ECONNRESET:
201 case -EPROTO:
202 /* unplug */
203 return;
204 case -EPIPE:
Jack Phame8741502012-06-13 17:34:07 -0700205 dev_err(&dev->intf->dev,
206 "%s: stall on int endpoint\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700207 /* TBD : halt to be cleared in work */
208 case -EOVERFLOW:
209 default:
210 pr_debug_ratelimited("%s: non zero urb status = %d\n",
211 __func__, urb->status);
212 goto resubmit_int_urb;
213 }
214
215 ctrl = (struct usb_cdc_notification *)urb->transfer_buffer;
216 data = (unsigned char *)(ctrl + 1);
217
218 switch (ctrl->bNotificationType) {
219 case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
220 dev->resp_avail++;
Jack Phame8741502012-06-13 17:34:07 -0700221 usb_fill_control_urb(dev->readurb, dev->udev,
222 usb_rcvctrlpipe(dev->udev, 0),
Hemant Kumar14401d52011-11-03 16:40:32 -0700223 (unsigned char *)dev->in_ctlreq,
224 dev->readbuf,
225 DEFAULT_READ_URB_LENGTH,
226 resp_avail_cb, dev);
227
228 status = usb_submit_urb(dev->readurb, GFP_ATOMIC);
229 if (status) {
Jack Phame8741502012-06-13 17:34:07 -0700230 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700231 "%s: Error submitting Read URB %d\n",
232 __func__, status);
233 goto resubmit_int_urb;
234 }
235 return;
236 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
Jack Phame8741502012-06-13 17:34:07 -0700237 dev_dbg(&dev->intf->dev, "%s network\n", ctrl->wValue ?
Hemant Kumar14401d52011-11-03 16:40:32 -0700238 "connected to" : "disconnected from");
239 break;
240 case USB_CDC_NOTIFY_SERIAL_STATE:
241 dev->notify_ser_state++;
242 ctrl_bits = get_unaligned_le16(data);
Jack Phame8741502012-06-13 17:34:07 -0700243 dev_dbg(&dev->intf->dev, "serial state: %d\n", ctrl_bits);
Hemant Kumar14401d52011-11-03 16:40:32 -0700244 dev->cbits_tohost = ctrl_bits;
245 if (brdg && brdg->ops.send_cbits)
246 brdg->ops.send_cbits(brdg->ctx, ctrl_bits);
247 break;
248 default:
Jack Phame8741502012-06-13 17:34:07 -0700249 dev_err(&dev->intf->dev, "%s: unknown notification %d received:"
Hemant Kumar14401d52011-11-03 16:40:32 -0700250 "index %d len %d data0 %d data1 %d",
251 __func__, ctrl->bNotificationType, ctrl->wIndex,
252 ctrl->wLength, data[0], data[1]);
253 }
254
255resubmit_int_urb:
256 status = usb_submit_urb(urb, GFP_ATOMIC);
Hemant Kumar262682a2013-02-01 09:46:45 -0800257 if (status)
Jack Phame8741502012-06-13 17:34:07 -0700258 dev_err(&dev->intf->dev, "%s: Error re-submitting Int URB %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700259 __func__, status);
260}
261
Jack Phamb9d67c62012-05-22 18:38:53 -0700262static int ctrl_bridge_start_read(struct ctrl_bridge *dev)
Hemant Kumar14401d52011-11-03 16:40:32 -0700263{
Jack Pham9b0a0e52012-02-28 18:05:14 -0800264 int retval = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700265
Jack Pham9b0a0e52012-02-28 18:05:14 -0800266 if (!dev->inturb) {
Jack Phame8741502012-06-13 17:34:07 -0700267 dev_err(&dev->intf->dev, "%s: inturb is NULL\n", __func__);
Jack Pham9b0a0e52012-02-28 18:05:14 -0800268 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700269 }
270
Hemant Kumar262682a2013-02-01 09:46:45 -0800271 retval = usb_submit_urb(dev->inturb, GFP_KERNEL);
272 if (retval < 0)
273 dev_err(&dev->intf->dev,
274 "%s error submitting int urb %d\n",
275 __func__, retval);
Hemant Kumar14401d52011-11-03 16:40:32 -0700276
Hemant Kumar14401d52011-11-03 16:40:32 -0700277 return retval;
278}
279
Hemant Kumar14401d52011-11-03 16:40:32 -0700280int ctrl_bridge_open(struct bridge *brdg)
281{
282 struct ctrl_bridge *dev;
Hemant Kumarc2b17782013-02-03 15:56:29 -0800283 int ch_id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700284
285 if (!brdg) {
286 err("bridge is null\n");
287 return -EINVAL;
288 }
289
Hemant Kumarc2b17782013-02-03 15:56:29 -0800290 ch_id = get_ctrl_bridge_chid(brdg->name);
291 if (ch_id < 0 || ch_id >= MAX_BRIDGE_DEVICES) {
292 err("%s: %s dev not found\n", __func__, brdg->name);
293 return ch_id;
Hemant Kumar14401d52011-11-03 16:40:32 -0700294 }
295
Hemant Kumarc2b17782013-02-03 15:56:29 -0800296 brdg->ch_id = ch_id;
297
298 dev = __dev[ch_id];
Hemant Kumar14401d52011-11-03 16:40:32 -0700299 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
Jack Phame8741502012-06-13 17:34:07 -0700324 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700325
326 ctrl_bridge_set_cbits(dev->brdg->ch_id, 0);
Hemant Kumar14401d52011-11-03 16:40:32 -0700327
328 dev->brdg = NULL;
329}
330EXPORT_SYMBOL(ctrl_bridge_close);
331
332static void ctrl_write_callback(struct urb *urb)
333{
Hemant Kumarf13358e2012-01-19 12:07:20 -0800334 struct ctrl_bridge *dev = urb->context;
Hemant Kumar14401d52011-11-03 16:40:32 -0700335
336 if (urb->status) {
337 pr_debug("Write status/size %d/%d\n",
338 urb->status, urb->actual_length);
339 }
340
341 kfree(urb->transfer_buffer);
342 kfree(urb->setup_packet);
343 usb_free_urb(urb);
Hemant Kumar262682a2013-02-01 09:46:45 -0800344
345 /* if we are here after device disconnect
346 * usb_unbind_interface() takes care of
347 * residual pm_autopm_get_interface_* calls
348 */
349 if (urb->dev->state != USB_STATE_NOTATTACHED)
350 usb_autopm_put_interface_async(dev->intf);
Hemant Kumar14401d52011-11-03 16:40:32 -0700351}
352
353int ctrl_bridge_write(unsigned int id, char *data, size_t size)
354{
355 int result;
356 struct urb *writeurb;
357 struct usb_ctrlrequest *out_ctlreq;
Hemant Kumar14401d52011-11-03 16:40:32 -0700358 struct ctrl_bridge *dev;
359
360 if (id >= MAX_BRIDGE_DEVICES) {
361 result = -EINVAL;
362 goto free_data;
363 }
364
365 dev = __dev[id];
366
367 if (!dev) {
368 result = -ENODEV;
369 goto free_data;
370 }
371
Jack Phame8741502012-06-13 17:34:07 -0700372 dev_dbg(&dev->intf->dev, "%s:[id]:%u: write (%d bytes)\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700373 __func__, id, size);
374
375 writeurb = usb_alloc_urb(0, GFP_ATOMIC);
376 if (!writeurb) {
Jack Phame8741502012-06-13 17:34:07 -0700377 dev_err(&dev->intf->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700378 __func__);
379 result = -ENOMEM;
380 goto free_data;
381 }
382
383 out_ctlreq = kmalloc(sizeof(*out_ctlreq), GFP_ATOMIC);
384 if (!out_ctlreq) {
Jack Phame8741502012-06-13 17:34:07 -0700385 dev_err(&dev->intf->dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700386 "%s: error allocating setup packet buffer\n",
387 __func__);
388 result = -ENOMEM;
389 goto free_urb;
390 }
391
392 /* CDC Send Encapsulated Request packet */
393 out_ctlreq->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
394 USB_RECIP_INTERFACE);
395 if (!data && !size) {
396 out_ctlreq->bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
397 out_ctlreq->wValue = dev->cbits_tomdm;
398 dev->set_ctrl_line_sts++;
399 } else {
400 out_ctlreq->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
401 out_ctlreq->wValue = 0;
402 dev->snd_encap_cmd++;
403 }
404 out_ctlreq->wIndex =
405 dev->intf->cur_altsetting->desc.bInterfaceNumber;
406 out_ctlreq->wLength = cpu_to_le16(size);
407
Jack Phame8741502012-06-13 17:34:07 -0700408 usb_fill_control_urb(writeurb, dev->udev,
409 usb_sndctrlpipe(dev->udev, 0),
Hemant Kumar14401d52011-11-03 16:40:32 -0700410 (unsigned char *)out_ctlreq,
411 (void *)data, size,
Hemant Kumarf13358e2012-01-19 12:07:20 -0800412 ctrl_write_callback, dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700413
414 result = usb_autopm_get_interface_async(dev->intf);
415 if (result < 0) {
Jack Pham4380e002012-08-30 19:06:24 -0700416 dev_dbg(&dev->intf->dev, "%s: unable to resume interface: %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700417 __func__, result);
418
419 /*
420 * Revisit: if (result == -EPERM)
421 * bridge_suspend(dev->intf, PMSG_SUSPEND);
422 */
423
424 goto free_ctrlreq;
425 }
426
Jack Pham9b0a0e52012-02-28 18:05:14 -0800427 if (test_bit(SUSPENDED, &dev->flags)) {
428 usb_anchor_urb(writeurb, &dev->tx_deferred);
429 goto deferred;
430 }
431
Hemant Kumar14401d52011-11-03 16:40:32 -0700432 usb_anchor_urb(writeurb, &dev->tx_submitted);
433 result = usb_submit_urb(writeurb, GFP_ATOMIC);
434 if (result < 0) {
Jack Phame8741502012-06-13 17:34:07 -0700435 dev_err(&dev->intf->dev, "%s: submit URB error %d\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700436 __func__, result);
437 usb_autopm_put_interface_async(dev->intf);
438 goto unanchor_urb;
439 }
Jack Pham9b0a0e52012-02-28 18:05:14 -0800440deferred:
Hemant Kumar14401d52011-11-03 16:40:32 -0700441 return size;
442
443unanchor_urb:
444 usb_unanchor_urb(writeurb);
445free_ctrlreq:
446 kfree(out_ctlreq);
447free_urb:
448 usb_free_urb(writeurb);
449free_data:
450 kfree(data);
451
452 return result;
453}
454EXPORT_SYMBOL(ctrl_bridge_write);
455
456int ctrl_bridge_suspend(unsigned int id)
457{
458 struct ctrl_bridge *dev;
459
460 if (id >= MAX_BRIDGE_DEVICES)
461 return -EINVAL;
462
463 dev = __dev[id];
464 if (!dev)
465 return -ENODEV;
466
Jack Pham9b0a0e52012-02-28 18:05:14 -0800467 set_bit(SUSPENDED, &dev->flags);
Hemant Kumar262682a2013-02-01 09:46:45 -0800468 usb_kill_urb(dev->inturb);
469 usb_kill_urb(dev->readurb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700470 usb_kill_anchored_urbs(&dev->tx_submitted);
471
Jack Pham9b0a0e52012-02-28 18:05:14 -0800472 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700473}
474
475int ctrl_bridge_resume(unsigned int id)
476{
477 struct ctrl_bridge *dev;
Jack Pham9b0a0e52012-02-28 18:05:14 -0800478 struct urb *urb;
Hemant Kumar14401d52011-11-03 16:40:32 -0700479
480 if (id >= MAX_BRIDGE_DEVICES)
481 return -EINVAL;
482
483 dev = __dev[id];
484 if (!dev)
485 return -ENODEV;
486
Jack Pham9b0a0e52012-02-28 18:05:14 -0800487 if (!test_and_clear_bit(SUSPENDED, &dev->flags))
488 return 0;
489
490 /* submit pending write requests */
491 while ((urb = usb_get_from_anchor(&dev->tx_deferred))) {
492 int ret;
493 usb_anchor_urb(urb, &dev->tx_submitted);
494 ret = usb_submit_urb(urb, GFP_ATOMIC);
495 if (ret < 0) {
496 usb_unanchor_urb(urb);
497 kfree(urb->setup_packet);
498 kfree(urb->transfer_buffer);
499 usb_free_urb(urb);
500 usb_autopm_put_interface_async(dev->intf);
501 }
502 }
503
Jack Phamb9d67c62012-05-22 18:38:53 -0700504 return ctrl_bridge_start_read(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700505}
506
507#if defined(CONFIG_DEBUG_FS)
508#define DEBUG_BUF_SIZE 1024
509static ssize_t ctrl_bridge_read_stats(struct file *file, char __user *ubuf,
510 size_t count, loff_t *ppos)
511{
512 struct ctrl_bridge *dev;
513 char *buf;
514 int ret;
515 int i;
516 int temp = 0;
517
518 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
519 if (!buf)
520 return -ENOMEM;
521
Hemant Kumar67107002013-02-11 13:24:08 -0800522 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700523 dev = __dev[i];
524 if (!dev)
525 continue;
526
527 temp += scnprintf(buf + temp, DEBUG_BUF_SIZE - temp,
528 "\nName#%s dev %p\n"
529 "snd encap cmd cnt: %u\n"
530 "get encap res cnt: %u\n"
531 "res available cnt: %u\n"
532 "set ctrlline sts cnt: %u\n"
533 "notify ser state cnt: %u\n"
534 "cbits_tomdm: %d\n"
Jack Pham9b0a0e52012-02-28 18:05:14 -0800535 "cbits_tohost: %d\n"
536 "suspended: %d\n",
Hemant Kumar67107002013-02-11 13:24:08 -0800537 dev->name, dev,
Hemant Kumar14401d52011-11-03 16:40:32 -0700538 dev->snd_encap_cmd,
539 dev->get_encap_res,
540 dev->resp_avail,
541 dev->set_ctrl_line_sts,
542 dev->notify_ser_state,
543 dev->cbits_tomdm,
Jack Pham9b0a0e52012-02-28 18:05:14 -0800544 dev->cbits_tohost,
545 test_bit(SUSPENDED, &dev->flags));
Hemant Kumar14401d52011-11-03 16:40:32 -0700546 }
547
548 ret = simple_read_from_buffer(ubuf, count, ppos, buf, temp);
549
550 kfree(buf);
551
552 return ret;
553}
554
555static ssize_t ctrl_bridge_reset_stats(struct file *file,
556 const char __user *buf, size_t count, loff_t *ppos)
557{
558 struct ctrl_bridge *dev;
559 int i;
560
Hemant Kumar67107002013-02-11 13:24:08 -0800561 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
Hemant Kumar14401d52011-11-03 16:40:32 -0700562 dev = __dev[i];
563 if (!dev)
564 continue;
565
566 dev->snd_encap_cmd = 0;
567 dev->get_encap_res = 0;
568 dev->resp_avail = 0;
569 dev->set_ctrl_line_sts = 0;
570 dev->notify_ser_state = 0;
571 }
572 return count;
573}
574
575const struct file_operations ctrl_stats_ops = {
576 .read = ctrl_bridge_read_stats,
577 .write = ctrl_bridge_reset_stats,
578};
579
580struct dentry *ctrl_dent;
581struct dentry *ctrl_dfile;
582static void ctrl_bridge_debugfs_init(void)
583{
584 ctrl_dent = debugfs_create_dir("ctrl_hsic_bridge", 0);
585 if (IS_ERR(ctrl_dent))
586 return;
587
588 ctrl_dfile =
589 debugfs_create_file("status", 0644, ctrl_dent, 0,
590 &ctrl_stats_ops);
591 if (!ctrl_dfile || IS_ERR(ctrl_dfile))
592 debugfs_remove(ctrl_dent);
593}
594
595static void ctrl_bridge_debugfs_exit(void)
596{
597 debugfs_remove(ctrl_dfile);
598 debugfs_remove(ctrl_dent);
599}
600
601#else
602static void ctrl_bridge_debugfs_init(void) { }
603static void ctrl_bridge_debugfs_exit(void) { }
604#endif
605
606int
607ctrl_bridge_probe(struct usb_interface *ifc, struct usb_host_endpoint *int_in,
Hemant Kumarc2b17782013-02-03 15:56:29 -0800608 char *name, int id)
Hemant Kumar14401d52011-11-03 16:40:32 -0700609{
610 struct ctrl_bridge *dev;
611 struct usb_device *udev;
612 struct usb_endpoint_descriptor *ep;
613 u16 wMaxPacketSize;
614 int retval = 0;
615 int interval;
616
617 udev = interface_to_usbdev(ifc);
618
Hemant Kumar262682a2013-02-01 09:46:45 -0800619 dev = __dev[id];
Hemant Kumar14401d52011-11-03 16:40:32 -0700620 if (!dev) {
Hemant Kumar262682a2013-02-01 09:46:45 -0800621 pr_err("%s:device not found\n", __func__);
622 return -ENODEV;
Hemant Kumar14401d52011-11-03 16:40:32 -0700623 }
Hemant Kumar262682a2013-02-01 09:46:45 -0800624
Hemant Kumarc2b17782013-02-03 15:56:29 -0800625 dev->name = name;
626
627 dev->pdev = platform_device_alloc(name, -1);
Hemant Kumar14401d52011-11-03 16:40:32 -0700628 if (!dev->pdev) {
Jack Phame8741502012-06-13 17:34:07 -0700629 dev_err(&ifc->dev, "%s: unable to allocate platform device\n",
630 __func__);
Hemant Kumar262682a2013-02-01 09:46:45 -0800631 return -ENOMEM;
Hemant Kumar14401d52011-11-03 16:40:32 -0700632 }
633
Hemant Kumar262682a2013-02-01 09:46:45 -0800634 dev->flags = 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700635 dev->udev = udev;
636 dev->int_pipe = usb_rcvintpipe(udev,
637 int_in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
638 dev->intf = ifc;
639
Hemant Kumar14401d52011-11-03 16:40:32 -0700640 /*use max pkt size from ep desc*/
641 ep = &dev->intf->cur_altsetting->endpoint[0].desc;
642
643 dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
644 if (!dev->inturb) {
Jack Phame8741502012-06-13 17:34:07 -0700645 dev_err(&ifc->dev, "%s: error allocating int urb\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700646 retval = -ENOMEM;
647 goto pdev_del;
648 }
649
650 wMaxPacketSize = le16_to_cpu(ep->wMaxPacketSize);
651
652 dev->intbuf = kmalloc(wMaxPacketSize, GFP_KERNEL);
653 if (!dev->intbuf) {
Jack Phame8741502012-06-13 17:34:07 -0700654 dev_err(&ifc->dev, "%s: error allocating int buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700655 __func__);
656 retval = -ENOMEM;
657 goto free_inturb;
658 }
659
660 interval =
661 (udev->speed == USB_SPEED_HIGH) ? HS_INTERVAL : FS_LS_INTERVAL;
662
663 usb_fill_int_urb(dev->inturb, udev, dev->int_pipe,
664 dev->intbuf, wMaxPacketSize,
665 notification_available_cb, dev, interval);
666
667 dev->readurb = usb_alloc_urb(0, GFP_KERNEL);
668 if (!dev->readurb) {
Jack Phame8741502012-06-13 17:34:07 -0700669 dev_err(&ifc->dev, "%s: error allocating read urb\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700670 __func__);
671 retval = -ENOMEM;
672 goto free_intbuf;
673 }
674
675 dev->readbuf = kmalloc(DEFAULT_READ_URB_LENGTH, GFP_KERNEL);
676 if (!dev->readbuf) {
Jack Phame8741502012-06-13 17:34:07 -0700677 dev_err(&ifc->dev, "%s: error allocating read buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700678 __func__);
679 retval = -ENOMEM;
680 goto free_rurb;
681 }
682
683 dev->in_ctlreq = kmalloc(sizeof(*dev->in_ctlreq), GFP_KERNEL);
684 if (!dev->in_ctlreq) {
Jack Phame8741502012-06-13 17:34:07 -0700685 dev_err(&ifc->dev, "%s:error allocating setup packet buffer\n",
Hemant Kumar14401d52011-11-03 16:40:32 -0700686 __func__);
687 retval = -ENOMEM;
688 goto free_rbuf;
689 }
690
691 dev->in_ctlreq->bRequestType =
692 (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
693 dev->in_ctlreq->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
694 dev->in_ctlreq->wValue = 0;
695 dev->in_ctlreq->wIndex =
696 dev->intf->cur_altsetting->desc.bInterfaceNumber;
697 dev->in_ctlreq->wLength = cpu_to_le16(DEFAULT_READ_URB_LENGTH);
698
Hemant Kumar14401d52011-11-03 16:40:32 -0700699 platform_device_add(dev->pdev);
700
Jack Phamb9d67c62012-05-22 18:38:53 -0700701 return ctrl_bridge_start_read(dev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700702
703free_rbuf:
704 kfree(dev->readbuf);
705free_rurb:
706 usb_free_urb(dev->readurb);
707free_intbuf:
708 kfree(dev->intbuf);
709free_inturb:
710 usb_free_urb(dev->inturb);
711pdev_del:
Jack Pham1b1ba472012-06-13 16:40:15 -0700712 platform_device_unregister(dev->pdev);
Hemant Kumar14401d52011-11-03 16:40:32 -0700713
714 return retval;
715}
716
717void ctrl_bridge_disconnect(unsigned int id)
718{
719 struct ctrl_bridge *dev = __dev[id];
720
Jack Phame8741502012-06-13 17:34:07 -0700721 dev_dbg(&dev->intf->dev, "%s:\n", __func__);
Hemant Kumar14401d52011-11-03 16:40:32 -0700722
Hemant Kumar67107002013-02-11 13:24:08 -0800723 /*set device name to none to get correct channel id
724 * at the time of bridge open
725 */
726 dev->name = "none";
727
Jack Pham1b1ba472012-06-13 16:40:15 -0700728 platform_device_unregister(dev->pdev);
Jack Pham452c6922011-12-14 18:15:26 -0800729
Hemant Kumar262682a2013-02-01 09:46:45 -0800730 usb_kill_anchored_urbs(&dev->tx_submitted);
731
732 usb_kill_urb(dev->inturb);
733 usb_kill_urb(dev->readurb);
Hemant Kumar77f79572012-11-08 12:19:26 -0800734
Hemant Kumar14401d52011-11-03 16:40:32 -0700735 kfree(dev->in_ctlreq);
736 kfree(dev->readbuf);
737 kfree(dev->intbuf);
738
739 usb_free_urb(dev->readurb);
740 usb_free_urb(dev->inturb);
Hemant Kumar14401d52011-11-03 16:40:32 -0700741}
742
Hemant Kumar262682a2013-02-01 09:46:45 -0800743int ctrl_bridge_init(void)
Hemant Kumar14401d52011-11-03 16:40:32 -0700744{
Hemant Kumar262682a2013-02-01 09:46:45 -0800745 struct ctrl_bridge *dev;
746 int i;
747 int retval = 0;
748
749 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
750
751 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
752 if (!dev) {
753 pr_err("%s: unable to allocate dev\n", __func__);
754 retval = -ENOMEM;
755 goto error;
756 }
757
Hemant Kumarc2b17782013-02-03 15:56:29 -0800758 /*transport name will be set during probe*/
Hemant Kumar67107002013-02-11 13:24:08 -0800759 dev->name = "none";
Hemant Kumarc2b17782013-02-03 15:56:29 -0800760
Hemant Kumar262682a2013-02-01 09:46:45 -0800761 init_usb_anchor(&dev->tx_submitted);
762 init_usb_anchor(&dev->tx_deferred);
763
764 __dev[i] = dev;
765 }
766
Hemant Kumar14401d52011-11-03 16:40:32 -0700767 ctrl_bridge_debugfs_init();
768
769 return 0;
Hemant Kumar14401d52011-11-03 16:40:32 -0700770
Hemant Kumar262682a2013-02-01 09:46:45 -0800771error:
772 while (--i >= 0) {
773 kfree(__dev[i]);
774 __dev[i] = NULL;
775 }
776
777 return retval;
778}
779
780void ctrl_bridge_exit(void)
Hemant Kumar14401d52011-11-03 16:40:32 -0700781{
Hemant Kumar262682a2013-02-01 09:46:45 -0800782 int i;
Hemant Kumar14401d52011-11-03 16:40:32 -0700783
Hemant Kumar262682a2013-02-01 09:46:45 -0800784 ctrl_bridge_debugfs_exit();
785
786 for (i = 0; i < MAX_BRIDGE_DEVICES; i++) {
787 kfree(__dev[i]);
788 __dev[i] = NULL;
789 }
790}