blob: aca7714c7d58dc7d49796304b06cc73c14aa6c7c [file] [log] [blame]
Jack Pham291c77d2011-10-10 17:33:21 -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/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/platform_device.h>
20#include <linux/usb.h>
21#include <linux/usb/cdc.h>
22#include <linux/usb/ch9.h>
23#include <asm/unaligned.h>
24#include <mach/usb_dun_bridge.h>
25
26#define DRIVER_DESC "Qualcomm USB DUN bridge driver"
27#define DRIVER_VERSION "1.0"
28
29struct dun_bridge {
30 struct usb_device *udev;
31 struct usb_interface *intf;
32 struct usb_anchor submitted;
33 u8 int_in_epaddr;
34 unsigned in, out; /* bulk in/out pipes */
35
36 struct urb *inturb;
37 struct usb_ctrlrequest cmd;
38 u8 *ctrl_buf;
39
40 struct kref kref;
41 struct platform_device *pdev;
42
43 struct dun_bridge_ops *ops;
44};
45
46static struct dun_bridge *__dev;
47
48/* This assumes that __dev has already been initialized by probe(). */
49int dun_bridge_open(struct dun_bridge_ops *ops)
50{
51 struct dun_bridge *dev = __dev;
52 int ret = 0;
53
54 if (!dev) {
55 err("%s: dev is null", __func__);
56 return -ENODEV;
57 }
58
59 if (!ops || !ops->read_complete || !ops->write_complete)
60 return -EINVAL;
61
62 dev->ops = ops;
63 if (ops->ctrl_status) {
64 ret = usb_submit_urb(dev->inturb, GFP_KERNEL);
65 if (ret)
66 pr_err("%s: submitting int urb failed: %d\n",
67 __func__, ret);
68 }
69
70 return ret;
71}
72EXPORT_SYMBOL(dun_bridge_open);
73
74int dun_bridge_close(void)
75{
76 struct dun_bridge *dev = __dev;
77 if (!dev)
78 return -ENODEV;
79
80 dev_dbg(&dev->udev->dev, "%s:", __func__);
81 usb_unlink_anchored_urbs(&dev->submitted);
82 usb_unlink_urb(dev->inturb);
83 dev->ops = NULL;
84
85 return 0;
86}
87EXPORT_SYMBOL(dun_bridge_close);
88
89static void read_cb(struct urb *urb)
90{
91 struct dun_bridge *dev = urb->context;
92 struct dun_bridge_ops *ops;
93
94 if (!dev || !dev->intf) {
95 pr_err("%s: device is disconnected\n", __func__);
96 kfree(urb->transfer_buffer);
97 return;
98 }
99
100 dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
101 urb->status, urb->actual_length);
102
103 usb_autopm_put_interface(dev->intf);
104 ops = dev->ops;
105 if (ops)
106 ops->read_complete(ops->ctxt,
107 urb->transfer_buffer,
108 urb->transfer_buffer_length,
109 /* callback must check this value for error */
110 urb->status < 0 ?
111 urb->status : urb->actual_length);
112 else {
113 /* can't call back, free buffer on caller's behalf */
114 dev_err(&dev->udev->dev, "cannot complete read callback\n");
115 kfree(urb->transfer_buffer);
116 }
117}
118
119int dun_bridge_read(void *data, int len)
120{
121 struct dun_bridge *dev = __dev;
122 struct urb *urb;
123 int ret;
124
125 if (!dev || !dev->ops)
126 return -ENODEV;
127
128 if (!dev->intf) {
129 pr_err("%s: device is disconnected\n", __func__);
130 return -ENODEV;
131 }
132
133 if (!len) {
134 dev_err(&dev->udev->dev, "%s: invalid len:%d\n", __func__, len);
135 return -EINVAL;
136 }
137
138 urb = usb_alloc_urb(0, GFP_KERNEL);
139 if (!urb) {
140 dev_err(&dev->udev->dev, "%s: Unable to alloc urb\n", __func__);
141 return -ENOMEM;
142 }
143
144 usb_fill_bulk_urb(urb, dev->udev, dev->in,
145 data, len, read_cb, dev);
146 usb_anchor_urb(urb, &dev->submitted);
147
148 usb_autopm_get_interface(dev->intf);
149 ret = usb_submit_urb(urb, GFP_KERNEL);
150 if (ret) {
151 dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
152 __func__, ret);
153 usb_unanchor_urb(urb);
154 usb_autopm_put_interface(dev->intf);
155 }
156
157 usb_free_urb(urb);
158 return ret;
159}
160EXPORT_SYMBOL(dun_bridge_read);
161
162static void write_cb(struct urb *urb)
163{
164 struct dun_bridge *dev = urb->context;
165 struct dun_bridge_ops *ops;
166
167 if (!dev || !dev->intf) {
168 pr_err("%s: device is disconnected\n", __func__);
169 kfree(urb->transfer_buffer);
170 return;
171 }
172
173 dev_dbg(&dev->udev->dev, "%s: status:%d actual:%d\n", __func__,
174 urb->status, urb->actual_length);
175
176 usb_autopm_put_interface(dev->intf);
177 ops = dev->ops;
178 if (ops)
179 ops->write_complete(ops->ctxt,
180 urb->transfer_buffer,
181 urb->transfer_buffer_length,
182 /* callback must check this value for error */
183 urb->status < 0 ?
184 urb->status : urb->actual_length);
185 else {
186 /* can't call back, free buffer on caller's behalf */
187 dev_err(&dev->udev->dev, "cannot complete write callback\n");
188 kfree(urb->transfer_buffer);
189 }
190}
191
192int dun_bridge_write(void *data, int len)
193{
194 struct dun_bridge *dev = __dev;
195 struct urb *urb;
196 int ret;
197
198 if (!dev || !dev->ops)
199 return -ENODEV;
200
201 if (!dev->intf) {
202 pr_err("%s: device is disconnected\n", __func__);
203 return -ENODEV;
204 }
205
206 if (!len) {
207 dev_err(&dev->udev->dev, "%s: invalid len:%d\n", __func__, len);
208 return -EINVAL;
209 }
210
211 urb = usb_alloc_urb(0, GFP_KERNEL);
212 if (!urb) {
213 dev_err(&dev->udev->dev, "%s: Unable to alloc urb\n", __func__);
214 return -ENOMEM;
215 }
216
217 usb_fill_bulk_urb(urb, dev->udev, dev->out,
218 data, len, write_cb, dev);
219 usb_anchor_urb(urb, &dev->submitted);
220
221 usb_autopm_get_interface(dev->intf);
222 ret = usb_submit_urb(urb, GFP_KERNEL);
223 if (ret) {
224 dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
225 __func__, ret);
226 usb_unanchor_urb(urb);
227 usb_autopm_put_interface(dev->intf);
228 }
229
230 usb_free_urb(urb);
231 return ret;
232}
233EXPORT_SYMBOL(dun_bridge_write);
234
235static void ctrl_cb(struct urb *urb)
236{
237 struct dun_bridge *dev = urb->context;
238 usb_autopm_put_interface(dev->intf);
239}
240
241int dun_bridge_send_ctrl_bits(unsigned ctrl_bits)
242{
243 struct dun_bridge *dev = __dev;
244 struct urb *urb = NULL;
245 int ret;
246
247 if (!dev || !dev->intf) {
248 pr_err("%s: device is disconnected\n", __func__);
249 return -ENODEV;
250 }
251
252 dev_dbg(&dev->udev->dev, "%s: %#x", __func__, ctrl_bits);
253
254 dev->cmd.bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE;
255 dev->cmd.bRequest = USB_CDC_REQ_SET_CONTROL_LINE_STATE;
256 dev->cmd.wValue = cpu_to_le16(ctrl_bits);
257 dev->cmd.wIndex = cpu_to_le16(dev->int_in_epaddr);
258 dev->cmd.wLength = 0;
259
260 urb = usb_alloc_urb(0, GFP_ATOMIC);
261 if (!urb) {
262 dev_err(&dev->udev->dev, "%s: Unable to alloc urb\n", __func__);
263 return -ENOMEM;
264 }
265
266 usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0),
267 (unsigned char *)&dev->cmd, NULL, 0,
268 ctrl_cb, dev);
269
270 usb_autopm_get_interface(dev->intf);
271 ret = usb_submit_urb(urb, GFP_ATOMIC);
272 if (ret) {
273 dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
274 __func__, ret);
275 usb_autopm_put_interface(dev->intf);
276 }
277
278 usb_free_urb(urb);
279 return ret;
280}
281EXPORT_SYMBOL(dun_bridge_send_ctrl_bits);
282
283static void int_cb(struct urb *urb)
284{
285 struct dun_bridge *dev = urb->context;
286 struct usb_cdc_notification *dr = urb->transfer_buffer;
287 unsigned char *data;
288 unsigned int ctrl_bits;
289 int status = urb->status;
290
291 if (!dev || !dev->intf) {
292 pr_err("%s: device is disconnected\n", __func__);
293 return;
294 }
295
296 switch (status) {
297 case 0:
298 /* success */
299 break;
300 case -ECONNRESET:
301 case -ENOENT:
302 case -ESHUTDOWN:
303 /* this urb is terminated, clean up */
304 dev_err(&dev->udev->dev,
305 "%s - urb shutting down with status: %d\n",
306 __func__, status);
307 return;
308 default:
309 dev_err(&dev->udev->dev,
310 "%s - nonzero urb status received: %d\n",
311 __func__, status);
312 goto resubmit_urb;
313 }
314
315 data = (unsigned char *)(dr + 1);
316 switch (dr->bNotificationType) {
317 case USB_CDC_NOTIFY_NETWORK_CONNECTION:
318 dev_dbg(&dev->udev->dev, "%s network\n", dr->wValue ?
319 "connected to" : "disconnected from");
320 break;
321
322 case USB_CDC_NOTIFY_SERIAL_STATE:
323 ctrl_bits = get_unaligned_le16(data);
324 dev_dbg(&dev->udev->dev, "serial state: %d\n", ctrl_bits);
325 if (dev->ops && dev->ops->ctrl_status)
326 dev->ops->ctrl_status(dev->ops->ctxt, ctrl_bits);
327 break;
328
329 default:
330 dev_err(&dev->udev->dev, "unknown notification %d received: "
331 "index %d len %d data0 %d data1 %d\n",
332 dr->bNotificationType, dr->wIndex,
333 dr->wLength, data[0], data[1]);
334 break;
335 }
336resubmit_urb:
337 status = usb_submit_urb(dev->inturb, GFP_ATOMIC);
338 if (status)
339 dev_err(&dev->udev->dev, "%s: submit urb err:%d\n",
340 __func__, status);
341}
342
343static void dun_bridge_delete(struct kref *kref)
344{
345 struct dun_bridge *dev = container_of(kref, struct dun_bridge, kref);
346
347 __dev = NULL;
348 usb_put_dev(dev->udev);
349 usb_free_urb(dev->inturb);
350 kfree(dev->ctrl_buf);
351 kfree(dev);
352}
353
354static int
355dun_bridge_probe(struct usb_interface *intf, const struct usb_device_id *id)
356{
357 struct dun_bridge *dev;
358 struct usb_host_interface *iface_desc;
359 struct usb_endpoint_descriptor *epd;
360 __u8 iface_num;
361 int i;
362 int ctrlsize = 0;
363 int ret = -ENOMEM;
364
365 iface_desc = intf->cur_altsetting;
366 iface_num = iface_desc->desc.bInterfaceNumber;
367
368 /* is this interface supported? */
369 if (iface_num != id->driver_info)
370 return -ENODEV;
371
372 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
373 if (!dev) {
374 pr_err("%s: unable to allocate dev\n", __func__);
375 goto error;
376 }
377
378 dev->pdev = platform_device_alloc("dun_bridge", 0);
379 if (!dev->pdev) {
380 pr_err("%s: unable to allocate platform device\n", __func__);
381 kfree(dev);
382 return -ENOMEM;
383 }
384 __dev = dev;
385
386 kref_init(&dev->kref);
387 dev->udev = usb_get_dev(interface_to_usbdev(intf));
388 dev->intf = intf;
389
390 init_usb_anchor(&dev->submitted);
391 dev->inturb = usb_alloc_urb(0, GFP_KERNEL);
392 if (!dev->inturb) {
393 ret = -ENOMEM;
394 goto error;
395 }
396
397 for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
398 epd = &iface_desc->endpoint[i].desc;
399
400 if (usb_endpoint_is_int_in(epd)) {
401 dev->int_in_epaddr = epd->bEndpointAddress;
402 ctrlsize = le16_to_cpu(epd->wMaxPacketSize);
403
404 dev->ctrl_buf = kzalloc(ctrlsize, GFP_KERNEL);
405 if (!dev->ctrl_buf) {
406 ret = -ENOMEM;
407 goto error;
408 }
409
410 usb_fill_int_urb(dev->inturb, dev->udev,
411 usb_rcvintpipe(dev->udev,
412 dev->int_in_epaddr),
413 dev->ctrl_buf, ctrlsize,
414 int_cb, dev, epd->bInterval);
415
416 } else if (usb_endpoint_is_bulk_in(epd))
417 dev->in = usb_rcvbulkpipe(dev->udev,
418 epd->bEndpointAddress &
419 USB_ENDPOINT_NUMBER_MASK);
420
421 else if (usb_endpoint_is_bulk_out(epd))
422 dev->out = usb_sndbulkpipe(dev->udev,
423 epd->bEndpointAddress &
424 USB_ENDPOINT_NUMBER_MASK);
425 }
426
427 if (!dev->int_in_epaddr && !dev->in && !dev->out) {
428 dev_err(&dev->udev->dev, "%s: could not find all endpoints\n",
429 __func__);
430 ret = -ENODEV;
431 goto error;
432 }
433
434 usb_set_intfdata(intf, dev);
435 platform_device_add(dev->pdev);
436 return 0;
437error:
438 if (dev)
439 kref_put(&dev->kref, dun_bridge_delete);
440 return ret;
441}
442
443static void dun_bridge_disconnect(struct usb_interface *intf)
444{
445 struct dun_bridge *dev = usb_get_intfdata(intf);
446
447 platform_device_del(dev->pdev);
448 usb_set_intfdata(intf, NULL);
449 dev->intf = NULL;
450
451 kref_put(&dev->kref, dun_bridge_delete);
452
453 pr_debug("%s: DUN Bridge now disconnected\n", __func__);
454}
455
456static int dun_bridge_suspend(struct usb_interface *intf, pm_message_t message)
457{
458 struct dun_bridge *dev = usb_get_intfdata(intf);
459
460 dev_dbg(&dev->udev->dev, "%s:", __func__);
461 usb_unlink_anchored_urbs(&dev->submitted);
462 usb_unlink_urb(dev->inturb);
463
464 return 0;
465}
466
467static int dun_bridge_resume(struct usb_interface *intf)
468{
469 struct dun_bridge *dev = usb_get_intfdata(intf);
470 int ret = 0;
471
472 if (dev->ops && dev->ops->ctrl_status) {
473 ret = usb_submit_urb(dev->inturb, GFP_KERNEL);
474 if (ret)
475 dev_err(&dev->udev->dev, "%s: submit int urb err: %d\n",
476 __func__, ret);
477 }
478
479 return ret;
480}
481
482#define VALID_INTERFACE_NUM 2
483static const struct usb_device_id id_table[] = {
484 { USB_DEVICE(0x05c6, 0x9001), /* Generic QC Modem device */
485 .driver_info = VALID_INTERFACE_NUM },
486 { } /* Terminating entry */
487};
488MODULE_DEVICE_TABLE(usb, id_table);
489
490static struct usb_driver dun_bridge_driver = {
491 .name = "dun_usb_bridge",
492 .probe = dun_bridge_probe,
493 .disconnect = dun_bridge_disconnect,
494 .id_table = id_table,
495 .suspend = dun_bridge_suspend,
496 .resume = dun_bridge_resume,
497 .supports_autosuspend = true,
498};
499
500static int __init dun_bridge_init(void)
501{
502 int ret;
503
504 ret = usb_register(&dun_bridge_driver);
505 if (ret)
506 pr_err("%s: unable to register dun_bridge_driver\n", __func__);
507
508 return ret;
509}
510
511static void __exit dun_bridge_exit(void)
512{
513 usb_deregister(&dun_bridge_driver);
514}
515
516module_init(dun_bridge_init);
517module_exit(dun_bridge_exit);
518
519MODULE_DESCRIPTION(DRIVER_DESC);
520MODULE_LICENSE("GPL V2");