blob: ae7e1b626c26a2755f0ff0290dac85c879c77f6b [file] [log] [blame]
Jack Phame32cf322011-09-26 10:20:17 -07001/*
Hemant Kumar7a067f12012-01-05 15:35:15 -08002 * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Jack Phame32cf322011-09-26 10:20:17 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
Jack Pham76e61dd2012-06-14 18:48:53 -070014/* add additional information to our printk's */
15#define pr_fmt(fmt) "%s: " fmt "\n", __func__
16
Jack Phame32cf322011-09-26 10:20:17 -070017#include <linux/kernel.h>
18#include <linux/errno.h>
19#include <linux/init.h>
20#include <linux/slab.h>
21#include <linux/module.h>
22#include <linux/kref.h>
Jack Phamb1795542012-09-04 17:13:37 -070023#include <linux/mutex.h>
Jack Phame32cf322011-09-26 10:20:17 -070024#include <linux/platform_device.h>
Jack Phamcca03322012-06-14 19:00:31 -070025#include <linux/ratelimit.h>
Jack Phame32cf322011-09-26 10:20:17 -070026#include <linux/uaccess.h>
27#include <linux/usb.h>
Jack Pham9a08de42012-02-06 15:43:23 -080028#include <linux/debugfs.h>
Jack Phame32cf322011-09-26 10:20:17 -070029#include <mach/diag_bridge.h>
30
31#define DRIVER_DESC "USB host diag bridge driver"
Jack Phamf6ed5582011-11-02 16:08:31 -070032#define DRIVER_VERSION "1.0"
Jack Phame32cf322011-09-26 10:20:17 -070033
Hemant Kumara3d4a6e2012-10-16 17:57:08 -070034#define AUTOSUSP_DELAY_WITH_USB 1000
35
Jack Phame32cf322011-09-26 10:20:17 -070036struct diag_bridge {
37 struct usb_device *udev;
38 struct usb_interface *ifc;
39 struct usb_anchor submitted;
40 __u8 in_epAddr;
41 __u8 out_epAddr;
Jack Pham3ae820f2011-12-14 16:21:04 -080042 int err;
Jack Phame32cf322011-09-26 10:20:17 -070043 struct kref kref;
Jack Phamb1795542012-09-04 17:13:37 -070044 struct mutex ifc_mutex;
Jack Phame32cf322011-09-26 10:20:17 -070045 struct diag_bridge_ops *ops;
46 struct platform_device *pdev;
Hemant Kumara3d4a6e2012-10-16 17:57:08 -070047 unsigned default_autosusp_delay;
Jack Pham9a08de42012-02-06 15:43:23 -080048
49 /* debugging counters */
50 unsigned long bytes_to_host;
51 unsigned long bytes_to_mdm;
52 unsigned pending_reads;
53 unsigned pending_writes;
Jack Phame32cf322011-09-26 10:20:17 -070054};
55struct diag_bridge *__dev;
56
Jack Phamf6ed5582011-11-02 16:08:31 -070057int diag_bridge_open(struct diag_bridge_ops *ops)
Jack Phame32cf322011-09-26 10:20:17 -070058{
59 struct diag_bridge *dev = __dev;
60
61 if (!dev) {
Jack Pham76e61dd2012-06-14 18:48:53 -070062 pr_err("dev is null");
Jack Phame32cf322011-09-26 10:20:17 -070063 return -ENODEV;
64 }
65
Jack Phamfbd22552012-09-07 17:29:08 -070066 if (dev->ops) {
67 pr_err("bridge already opened");
68 return -EALREADY;
69 }
70
Jack Phame32cf322011-09-26 10:20:17 -070071 dev->ops = ops;
Jack Pham3ae820f2011-12-14 16:21:04 -080072 dev->err = 0;
Jack Phame32cf322011-09-26 10:20:17 -070073
Hemant Kumara3d4a6e2012-10-16 17:57:08 -070074#ifdef CONFIG_PM_RUNTIME
75 dev->default_autosusp_delay = dev->udev->dev.power.autosuspend_delay;
76#endif
77 pm_runtime_set_autosuspend_delay(&dev->udev->dev,
78 AUTOSUSP_DELAY_WITH_USB);
79
Jack Pham76e61dd2012-06-14 18:48:53 -070080 kref_get(&dev->kref);
81
Jack Phame32cf322011-09-26 10:20:17 -070082 return 0;
83}
Jack Phamf6ed5582011-11-02 16:08:31 -070084EXPORT_SYMBOL(diag_bridge_open);
Jack Phame32cf322011-09-26 10:20:17 -070085
Jack Pham76e61dd2012-06-14 18:48:53 -070086static void diag_bridge_delete(struct kref *kref)
87{
88 struct diag_bridge *dev = container_of(kref, struct diag_bridge, kref);
89
90 usb_put_dev(dev->udev);
91 __dev = 0;
92 kfree(dev);
93}
94
Jack Phamf6ed5582011-11-02 16:08:31 -070095void diag_bridge_close(void)
Jack Phame32cf322011-09-26 10:20:17 -070096{
97 struct diag_bridge *dev = __dev;
98
Jack Phamfbd22552012-09-07 17:29:08 -070099 if (!dev) {
100 pr_err("dev is null");
101 return;
102 }
103
104 if (!dev->ops) {
105 pr_err("can't close bridge that was not open");
106 return;
107 }
108
Jack Phame8741502012-06-13 17:34:07 -0700109 dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
Jack Phame32cf322011-09-26 10:20:17 -0700110
111 usb_kill_anchored_urbs(&dev->submitted);
Jack Phame32cf322011-09-26 10:20:17 -0700112 dev->ops = 0;
Hemant Kumara3d4a6e2012-10-16 17:57:08 -0700113
114 pm_runtime_set_autosuspend_delay(&dev->udev->dev,
115 dev->default_autosusp_delay);
116
Jack Pham76e61dd2012-06-14 18:48:53 -0700117 kref_put(&dev->kref, diag_bridge_delete);
Jack Phame32cf322011-09-26 10:20:17 -0700118}
Jack Phamf6ed5582011-11-02 16:08:31 -0700119EXPORT_SYMBOL(diag_bridge_close);
Jack Phame32cf322011-09-26 10:20:17 -0700120
Jack Phamf6ed5582011-11-02 16:08:31 -0700121static void diag_bridge_read_cb(struct urb *urb)
Jack Phame32cf322011-09-26 10:20:17 -0700122{
123 struct diag_bridge *dev = urb->context;
124 struct diag_bridge_ops *cbs = dev->ops;
125
Jack Phame8741502012-06-13 17:34:07 -0700126 dev_dbg(&dev->ifc->dev, "%s: status:%d actual:%d\n", __func__,
Jack Phame32cf322011-09-26 10:20:17 -0700127 urb->status, urb->actual_length);
Jack Phame32cf322011-09-26 10:20:17 -0700128
Jack Pham3ec42b62012-08-31 15:36:27 -0700129 /* save error so that subsequent read/write returns ENODEV */
130 if (urb->status == -EPROTO)
Jack Pham3ae820f2011-12-14 16:21:04 -0800131 dev->err = urb->status;
Jack Pham3ae820f2011-12-14 16:21:04 -0800132
Vamsi Krishna90125642012-05-12 16:06:13 -0700133 if (cbs && cbs->read_complete_cb)
134 cbs->read_complete_cb(cbs->ctxt,
Jack Phame32cf322011-09-26 10:20:17 -0700135 urb->transfer_buffer,
136 urb->transfer_buffer_length,
Jack Phamf6ed5582011-11-02 16:08:31 -0700137 urb->status < 0 ? urb->status : urb->actual_length);
Jack Pham9a08de42012-02-06 15:43:23 -0800138
139 dev->bytes_to_host += urb->actual_length;
140 dev->pending_reads--;
Jack Pham76e61dd2012-06-14 18:48:53 -0700141 kref_put(&dev->kref, diag_bridge_delete);
Jack Phame32cf322011-09-26 10:20:17 -0700142}
143
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800144int diag_bridge_read(char *data, int size)
Jack Phame32cf322011-09-26 10:20:17 -0700145{
146 struct urb *urb = NULL;
147 unsigned int pipe;
148 struct diag_bridge *dev = __dev;
149 int ret;
150
Jack Pham76e61dd2012-06-14 18:48:53 -0700151 pr_debug("reading %d bytes", size);
152
Jack Phamb1795542012-09-04 17:13:37 -0700153 if (!dev) {
Jack Pham76e61dd2012-06-14 18:48:53 -0700154 pr_err("device is disconnected");
155 return -ENODEV;
156 }
157
Jack Phamb1795542012-09-04 17:13:37 -0700158 mutex_lock(&dev->ifc_mutex);
159 if (!dev->ifc) {
160 ret = -ENODEV;
161 goto error;
162 }
163
Jack Pham76e61dd2012-06-14 18:48:53 -0700164 if (!dev->ops) {
165 pr_err("bridge is not open");
Jack Phamb1795542012-09-04 17:13:37 -0700166 ret = -ENODEV;
167 goto error;
Jack Pham76e61dd2012-06-14 18:48:53 -0700168 }
Jack Phame32cf322011-09-26 10:20:17 -0700169
170 if (!size) {
Jack Phame8741502012-06-13 17:34:07 -0700171 dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
Jack Phamb1795542012-09-04 17:13:37 -0700172 ret = -EINVAL;
173 goto error;
Jack Phame32cf322011-09-26 10:20:17 -0700174 }
175
Jack Pham3ae820f2011-12-14 16:21:04 -0800176 /* if there was a previous unrecoverable error, just quit */
Jack Phamb1795542012-09-04 17:13:37 -0700177 if (dev->err) {
178 ret = -ENODEV;
179 goto error;
180 }
Jack Pham3ae820f2011-12-14 16:21:04 -0800181
Jack Pham76e61dd2012-06-14 18:48:53 -0700182 kref_get(&dev->kref);
183
Jack Phamb60775a2012-02-14 17:57:41 -0800184 urb = usb_alloc_urb(0, GFP_KERNEL);
Jack Phame32cf322011-09-26 10:20:17 -0700185 if (!urb) {
Jack Phame8741502012-06-13 17:34:07 -0700186 dev_err(&dev->ifc->dev, "unable to allocate urb\n");
Jack Pham76e61dd2012-06-14 18:48:53 -0700187 ret = -ENOMEM;
Jack Phamb1795542012-09-04 17:13:37 -0700188 goto put_error;
Jack Phame32cf322011-09-26 10:20:17 -0700189 }
190
Jack Phamb60775a2012-02-14 17:57:41 -0800191 ret = usb_autopm_get_interface(dev->ifc);
Jack Phamcca03322012-06-14 19:00:31 -0700192 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
193 pr_err_ratelimited("read: autopm_get failed:%d", ret);
Jack Pham76e61dd2012-06-14 18:48:53 -0700194 goto free_error;
Jack Phamb60775a2012-02-14 17:57:41 -0800195 }
196
Jack Phame32cf322011-09-26 10:20:17 -0700197 pipe = usb_rcvbulkpipe(dev->udev, dev->in_epAddr);
198 usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
Jack Phamf6ed5582011-11-02 16:08:31 -0700199 diag_bridge_read_cb, dev);
Jack Phame32cf322011-09-26 10:20:17 -0700200 usb_anchor_urb(urb, &dev->submitted);
Jack Pham9a08de42012-02-06 15:43:23 -0800201 dev->pending_reads++;
Jack Phame32cf322011-09-26 10:20:17 -0700202
Jack Phamb60775a2012-02-14 17:57:41 -0800203 ret = usb_submit_urb(urb, GFP_KERNEL);
Jack Phame32cf322011-09-26 10:20:17 -0700204 if (ret) {
Jack Phamcca03322012-06-14 19:00:31 -0700205 pr_err_ratelimited("submitting urb failed err:%d", ret);
Jack Pham9a08de42012-02-06 15:43:23 -0800206 dev->pending_reads--;
Jack Phame32cf322011-09-26 10:20:17 -0700207 usb_unanchor_urb(urb);
Jack Phame32cf322011-09-26 10:20:17 -0700208 }
Jack Phamb60775a2012-02-14 17:57:41 -0800209 usb_autopm_put_interface(dev->ifc);
Jack Phame32cf322011-09-26 10:20:17 -0700210
Jack Pham76e61dd2012-06-14 18:48:53 -0700211free_error:
212 usb_free_urb(urb);
Jack Phamb1795542012-09-04 17:13:37 -0700213put_error:
Jack Pham76e61dd2012-06-14 18:48:53 -0700214 if (ret) /* otherwise this is done in the completion handler */
215 kref_put(&dev->kref, diag_bridge_delete);
Jack Phamb1795542012-09-04 17:13:37 -0700216error:
217 mutex_unlock(&dev->ifc_mutex);
Jack Pham76e61dd2012-06-14 18:48:53 -0700218 return ret;
Jack Phame32cf322011-09-26 10:20:17 -0700219}
Jack Phamf6ed5582011-11-02 16:08:31 -0700220EXPORT_SYMBOL(diag_bridge_read);
Jack Phame32cf322011-09-26 10:20:17 -0700221
Jack Phamf6ed5582011-11-02 16:08:31 -0700222static void diag_bridge_write_cb(struct urb *urb)
Jack Phame32cf322011-09-26 10:20:17 -0700223{
224 struct diag_bridge *dev = urb->context;
225 struct diag_bridge_ops *cbs = dev->ops;
226
Jack Phame8741502012-06-13 17:34:07 -0700227 dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
Jack Phame32cf322011-09-26 10:20:17 -0700228
Jack Phamb60775a2012-02-14 17:57:41 -0800229 usb_autopm_put_interface_async(dev->ifc);
230
Jack Pham3ec42b62012-08-31 15:36:27 -0700231 /* save error so that subsequent read/write returns ENODEV */
232 if (urb->status == -EPROTO)
Jack Pham3ae820f2011-12-14 16:21:04 -0800233 dev->err = urb->status;
Jack Pham3ae820f2011-12-14 16:21:04 -0800234
Vamsi Krishna90125642012-05-12 16:06:13 -0700235 if (cbs && cbs->write_complete_cb)
236 cbs->write_complete_cb(cbs->ctxt,
Jack Phame32cf322011-09-26 10:20:17 -0700237 urb->transfer_buffer,
238 urb->transfer_buffer_length,
Jack Phamf6ed5582011-11-02 16:08:31 -0700239 urb->status < 0 ? urb->status : urb->actual_length);
Jack Pham9a08de42012-02-06 15:43:23 -0800240
241 dev->bytes_to_mdm += urb->actual_length;
242 dev->pending_writes--;
Jack Pham76e61dd2012-06-14 18:48:53 -0700243 kref_put(&dev->kref, diag_bridge_delete);
Jack Phame32cf322011-09-26 10:20:17 -0700244}
245
Dixon Peterson32e70bb2011-12-16 13:26:45 -0800246int diag_bridge_write(char *data, int size)
Jack Phame32cf322011-09-26 10:20:17 -0700247{
248 struct urb *urb = NULL;
249 unsigned int pipe;
250 struct diag_bridge *dev = __dev;
251 int ret;
252
Jack Pham76e61dd2012-06-14 18:48:53 -0700253 pr_debug("writing %d bytes", size);
254
Jack Phamb1795542012-09-04 17:13:37 -0700255 if (!dev) {
Jack Pham76e61dd2012-06-14 18:48:53 -0700256 pr_err("device is disconnected");
257 return -ENODEV;
258 }
259
Jack Phamb1795542012-09-04 17:13:37 -0700260 mutex_lock(&dev->ifc_mutex);
261 if (!dev->ifc) {
262 ret = -ENODEV;
263 goto error;
264 }
265
Jack Pham76e61dd2012-06-14 18:48:53 -0700266 if (!dev->ops) {
267 pr_err("bridge is not open");
Jack Phamb1795542012-09-04 17:13:37 -0700268 ret = -ENODEV;
269 goto error;
Jack Pham76e61dd2012-06-14 18:48:53 -0700270 }
Jack Phame32cf322011-09-26 10:20:17 -0700271
272 if (!size) {
Jack Phame8741502012-06-13 17:34:07 -0700273 dev_err(&dev->ifc->dev, "invalid size:%d\n", size);
Jack Phamb1795542012-09-04 17:13:37 -0700274 ret = -EINVAL;
275 goto error;
Jack Phame32cf322011-09-26 10:20:17 -0700276 }
277
Jack Pham3ae820f2011-12-14 16:21:04 -0800278 /* if there was a previous unrecoverable error, just quit */
Jack Phamb1795542012-09-04 17:13:37 -0700279 if (dev->err) {
280 ret = -ENODEV;
281 goto error;
282 }
Jack Pham3ae820f2011-12-14 16:21:04 -0800283
Jack Pham76e61dd2012-06-14 18:48:53 -0700284 kref_get(&dev->kref);
285
Jack Phamb60775a2012-02-14 17:57:41 -0800286 urb = usb_alloc_urb(0, GFP_KERNEL);
Jack Phame32cf322011-09-26 10:20:17 -0700287 if (!urb) {
Jack Phame8741502012-06-13 17:34:07 -0700288 dev_err(&dev->ifc->dev, "unable to allocate urb\n");
Jack Pham76e61dd2012-06-14 18:48:53 -0700289 ret = -ENOMEM;
Jack Phamb1795542012-09-04 17:13:37 -0700290 goto put_error;
Jack Phame32cf322011-09-26 10:20:17 -0700291 }
292
Jack Phamb60775a2012-02-14 17:57:41 -0800293 ret = usb_autopm_get_interface(dev->ifc);
Jack Phamcca03322012-06-14 19:00:31 -0700294 if (ret < 0 && ret != -EAGAIN && ret != -EACCES) {
295 pr_err_ratelimited("write: autopm_get failed:%d", ret);
Jack Pham76e61dd2012-06-14 18:48:53 -0700296 goto free_error;
Jack Phamb60775a2012-02-14 17:57:41 -0800297 }
298
Jack Phame32cf322011-09-26 10:20:17 -0700299 pipe = usb_sndbulkpipe(dev->udev, dev->out_epAddr);
300 usb_fill_bulk_urb(urb, dev->udev, pipe, data, size,
Jack Phamf6ed5582011-11-02 16:08:31 -0700301 diag_bridge_write_cb, dev);
Jack Pham5a10c6f2012-06-26 11:41:28 -0700302 urb->transfer_flags |= URB_ZERO_PACKET;
Jack Phame32cf322011-09-26 10:20:17 -0700303 usb_anchor_urb(urb, &dev->submitted);
Jack Pham9a08de42012-02-06 15:43:23 -0800304 dev->pending_writes++;
Jack Phame32cf322011-09-26 10:20:17 -0700305
Jack Phamb60775a2012-02-14 17:57:41 -0800306 ret = usb_submit_urb(urb, GFP_KERNEL);
Jack Phame32cf322011-09-26 10:20:17 -0700307 if (ret) {
Jack Phamcca03322012-06-14 19:00:31 -0700308 pr_err_ratelimited("submitting urb failed err:%d", ret);
Jack Pham9a08de42012-02-06 15:43:23 -0800309 dev->pending_writes--;
Jack Phame32cf322011-09-26 10:20:17 -0700310 usb_unanchor_urb(urb);
Jack Phamb60775a2012-02-14 17:57:41 -0800311 usb_autopm_put_interface(dev->ifc);
Jack Pham76e61dd2012-06-14 18:48:53 -0700312 goto free_error;
Jack Phame32cf322011-09-26 10:20:17 -0700313 }
314
Jack Pham76e61dd2012-06-14 18:48:53 -0700315free_error:
Jack Phame32cf322011-09-26 10:20:17 -0700316 usb_free_urb(urb);
Jack Phamb1795542012-09-04 17:13:37 -0700317put_error:
Jack Pham76e61dd2012-06-14 18:48:53 -0700318 if (ret) /* otherwise this is done in the completion handler */
319 kref_put(&dev->kref, diag_bridge_delete);
Jack Phamb1795542012-09-04 17:13:37 -0700320error:
321 mutex_unlock(&dev->ifc_mutex);
Jack Pham76e61dd2012-06-14 18:48:53 -0700322 return ret;
Jack Phame32cf322011-09-26 10:20:17 -0700323}
Jack Phamf6ed5582011-11-02 16:08:31 -0700324EXPORT_SYMBOL(diag_bridge_write);
Jack Phame32cf322011-09-26 10:20:17 -0700325
Jack Pham9a08de42012-02-06 15:43:23 -0800326#if defined(CONFIG_DEBUG_FS)
327#define DEBUG_BUF_SIZE 512
328static ssize_t diag_read_stats(struct file *file, char __user *ubuf,
329 size_t count, loff_t *ppos)
330{
331 struct diag_bridge *dev = __dev;
332 char *buf;
333 int ret;
334
Jack Pham76e61dd2012-06-14 18:48:53 -0700335 if (!dev)
336 return -ENODEV;
337
Jack Pham9a08de42012-02-06 15:43:23 -0800338 buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
339 if (!buf)
340 return -ENOMEM;
341
342 ret = scnprintf(buf, DEBUG_BUF_SIZE,
343 "epin:%d, epout:%d\n"
344 "bytes to host: %lu\n"
345 "bytes to mdm: %lu\n"
346 "pending reads: %u\n"
347 "pending writes: %u\n"
348 "last error: %d\n",
349 dev->in_epAddr, dev->out_epAddr,
350 dev->bytes_to_host, dev->bytes_to_mdm,
351 dev->pending_reads, dev->pending_writes,
352 dev->err);
353
354 ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
355 kfree(buf);
356 return ret;
357}
358
359static ssize_t diag_reset_stats(struct file *file, const char __user *buf,
360 size_t count, loff_t *ppos)
361{
362 struct diag_bridge *dev = __dev;
363
Jack Pham76e61dd2012-06-14 18:48:53 -0700364 if (dev) {
365 dev->bytes_to_host = dev->bytes_to_mdm = 0;
366 dev->pending_reads = dev->pending_writes = 0;
367 }
Jack Pham9a08de42012-02-06 15:43:23 -0800368
369 return count;
370}
371
372const struct file_operations diag_stats_ops = {
373 .read = diag_read_stats,
374 .write = diag_reset_stats,
375};
376
377static struct dentry *dent;
378
379static void diag_bridge_debugfs_init(void)
380{
381 struct dentry *dfile;
382
383 dent = debugfs_create_dir("diag_bridge", 0);
384 if (IS_ERR(dent))
385 return;
386
387 dfile = debugfs_create_file("status", 0444, dent, 0, &diag_stats_ops);
388 if (!dfile || IS_ERR(dfile))
389 debugfs_remove(dent);
390}
391
392static void diag_bridge_debugfs_cleanup(void)
393{
394 if (dent) {
395 debugfs_remove_recursive(dent);
396 dent = NULL;
397 }
398}
399#else
400static inline void diag_bridge_debugfs_init(void) { }
401static inline void diag_bridge_debugfs_cleanup(void) { }
402#endif
403
Jack Phame32cf322011-09-26 10:20:17 -0700404static int
Jack Phamf6ed5582011-11-02 16:08:31 -0700405diag_bridge_probe(struct usb_interface *ifc, const struct usb_device_id *id)
Jack Phame32cf322011-09-26 10:20:17 -0700406{
407 struct diag_bridge *dev;
408 struct usb_host_interface *ifc_desc;
409 struct usb_endpoint_descriptor *ep_desc;
410 int i;
411 int ret = -ENOMEM;
412 __u8 ifc_num;
413
Jack Pham76e61dd2012-06-14 18:48:53 -0700414 pr_debug("id:%lu", id->driver_info);
Jack Phame32cf322011-09-26 10:20:17 -0700415
416 ifc_num = ifc->cur_altsetting->desc.bInterfaceNumber;
417
418 /* is this interface supported ? */
419 if (ifc_num != id->driver_info)
420 return -ENODEV;
421
422 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
423 if (!dev) {
Jack Pham76e61dd2012-06-14 18:48:53 -0700424 pr_err("unable to allocate dev");
Jack Phame32cf322011-09-26 10:20:17 -0700425 return -ENOMEM;
426 }
427 dev->pdev = platform_device_alloc("diag_bridge", -1);
428 if (!dev->pdev) {
Jack Pham76e61dd2012-06-14 18:48:53 -0700429 pr_err("unable to allocate platform device");
Jack Phame32cf322011-09-26 10:20:17 -0700430 kfree(dev);
431 return -ENOMEM;
432 }
433 __dev = dev;
434
435 dev->udev = usb_get_dev(interface_to_usbdev(ifc));
436 dev->ifc = ifc;
437 kref_init(&dev->kref);
Jack Phamb1795542012-09-04 17:13:37 -0700438 mutex_init(&dev->ifc_mutex);
Jack Phame32cf322011-09-26 10:20:17 -0700439 init_usb_anchor(&dev->submitted);
440
441 ifc_desc = ifc->cur_altsetting;
442 for (i = 0; i < ifc_desc->desc.bNumEndpoints; i++) {
443 ep_desc = &ifc_desc->endpoint[i].desc;
444
445 if (!dev->in_epAddr && usb_endpoint_is_bulk_in(ep_desc))
446 dev->in_epAddr = ep_desc->bEndpointAddress;
447
448 if (!dev->out_epAddr && usb_endpoint_is_bulk_out(ep_desc))
449 dev->out_epAddr = ep_desc->bEndpointAddress;
450 }
451
452 if (!(dev->in_epAddr && dev->out_epAddr)) {
Jack Pham76e61dd2012-06-14 18:48:53 -0700453 pr_err("could not find bulk in and bulk out endpoints");
Jack Phame32cf322011-09-26 10:20:17 -0700454 ret = -ENODEV;
455 goto error;
456 }
457
458 usb_set_intfdata(ifc, dev);
Jack Pham9a08de42012-02-06 15:43:23 -0800459 diag_bridge_debugfs_init();
Jack Phame32cf322011-09-26 10:20:17 -0700460 platform_device_add(dev->pdev);
461
Jack Phame8741502012-06-13 17:34:07 -0700462 dev_dbg(&dev->ifc->dev, "%s: complete\n", __func__);
Jack Phame32cf322011-09-26 10:20:17 -0700463
464 return 0;
465
466error:
467 if (dev)
Jack Phamf6ed5582011-11-02 16:08:31 -0700468 kref_put(&dev->kref, diag_bridge_delete);
Jack Phame32cf322011-09-26 10:20:17 -0700469
470 return ret;
471}
472
Jack Phamf6ed5582011-11-02 16:08:31 -0700473static void diag_bridge_disconnect(struct usb_interface *ifc)
Jack Phame32cf322011-09-26 10:20:17 -0700474{
475 struct diag_bridge *dev = usb_get_intfdata(ifc);
476
Jack Phame8741502012-06-13 17:34:07 -0700477 dev_dbg(&dev->ifc->dev, "%s:\n", __func__);
Jack Phame32cf322011-09-26 10:20:17 -0700478
Jack Pham1b1ba472012-06-13 16:40:15 -0700479 platform_device_unregister(dev->pdev);
Jack Phamb1795542012-09-04 17:13:37 -0700480 mutex_lock(&dev->ifc_mutex);
Jack Pham76e61dd2012-06-14 18:48:53 -0700481 dev->ifc = NULL;
Jack Phamb1795542012-09-04 17:13:37 -0700482 mutex_unlock(&dev->ifc_mutex);
Jack Pham9a08de42012-02-06 15:43:23 -0800483 diag_bridge_debugfs_cleanup();
Jack Phamf6ed5582011-11-02 16:08:31 -0700484 kref_put(&dev->kref, diag_bridge_delete);
Jack Phame32cf322011-09-26 10:20:17 -0700485 usb_set_intfdata(ifc, NULL);
486}
487
Jack Phamb60775a2012-02-14 17:57:41 -0800488static int diag_bridge_suspend(struct usb_interface *ifc, pm_message_t message)
489{
490 struct diag_bridge *dev = usb_get_intfdata(ifc);
491 struct diag_bridge_ops *cbs = dev->ops;
492 int ret = 0;
493
494 if (cbs && cbs->suspend) {
495 ret = cbs->suspend(cbs->ctxt);
496 if (ret) {
Jack Phame8741502012-06-13 17:34:07 -0700497 dev_dbg(&dev->ifc->dev,
Jack Phamb60775a2012-02-14 17:57:41 -0800498 "%s: diag veto'd suspend\n", __func__);
499 return ret;
500 }
501
502 usb_kill_anchored_urbs(&dev->submitted);
503 }
504
505 return ret;
506}
507
508static int diag_bridge_resume(struct usb_interface *ifc)
509{
510 struct diag_bridge *dev = usb_get_intfdata(ifc);
511 struct diag_bridge_ops *cbs = dev->ops;
512
513
514 if (cbs && cbs->resume)
515 cbs->resume(cbs->ctxt);
516
517 return 0;
518}
Jack Phame32cf322011-09-26 10:20:17 -0700519
520#define VALID_INTERFACE_NUM 0
Jack Phamf6ed5582011-11-02 16:08:31 -0700521static const struct usb_device_id diag_bridge_ids[] = {
Hemant Kumar7a067f12012-01-05 15:35:15 -0800522 { USB_DEVICE(0x5c6, 0x9001),
523 .driver_info = VALID_INTERFACE_NUM, },
524 { USB_DEVICE(0x5c6, 0x9034),
525 .driver_info = VALID_INTERFACE_NUM, },
Hemant Kumar7f236832011-12-16 12:13:21 -0800526 { USB_DEVICE(0x5c6, 0x9048),
Jack Phame32cf322011-09-26 10:20:17 -0700527 .driver_info = VALID_INTERFACE_NUM, },
Hemant Kumarcfc0dad2012-02-21 14:34:39 -0800528 { USB_DEVICE(0x5c6, 0x904C),
529 .driver_info = VALID_INTERFACE_NUM, },
Hemant Kumarce3c5bf2012-12-06 15:52:02 -0800530 { USB_DEVICE(0x5c6, 0x9075),
531 .driver_info = VALID_INTERFACE_NUM, },
Jack Phame32cf322011-09-26 10:20:17 -0700532
533 {} /* terminating entry */
534};
Jack Phamf6ed5582011-11-02 16:08:31 -0700535MODULE_DEVICE_TABLE(usb, diag_bridge_ids);
Jack Phame32cf322011-09-26 10:20:17 -0700536
Jack Phamf6ed5582011-11-02 16:08:31 -0700537static struct usb_driver diag_bridge_driver = {
538 .name = "diag_bridge",
539 .probe = diag_bridge_probe,
540 .disconnect = diag_bridge_disconnect,
Jack Phamb60775a2012-02-14 17:57:41 -0800541 .suspend = diag_bridge_suspend,
542 .resume = diag_bridge_resume,
Jack Phamf6ed5582011-11-02 16:08:31 -0700543 .id_table = diag_bridge_ids,
Jack Phamb60775a2012-02-14 17:57:41 -0800544 .supports_autosuspend = 1,
Jack Phame32cf322011-09-26 10:20:17 -0700545};
546
Jack Phamf6ed5582011-11-02 16:08:31 -0700547static int __init diag_bridge_init(void)
Jack Phame32cf322011-09-26 10:20:17 -0700548{
549 int ret;
550
Jack Phamf6ed5582011-11-02 16:08:31 -0700551 ret = usb_register(&diag_bridge_driver);
Jack Phame32cf322011-09-26 10:20:17 -0700552 if (ret) {
Jack Pham76e61dd2012-06-14 18:48:53 -0700553 pr_err("unable to register diag driver");
Jack Phame32cf322011-09-26 10:20:17 -0700554 return ret;
555 }
556
557 return 0;
558}
559
Jack Phamf6ed5582011-11-02 16:08:31 -0700560static void __exit diag_bridge_exit(void)
Jack Phame32cf322011-09-26 10:20:17 -0700561{
Jack Phamf6ed5582011-11-02 16:08:31 -0700562 usb_deregister(&diag_bridge_driver);
Jack Phame32cf322011-09-26 10:20:17 -0700563}
564
Jack Phamf6ed5582011-11-02 16:08:31 -0700565module_init(diag_bridge_init);
566module_exit(diag_bridge_exit);
Jack Phame32cf322011-09-26 10:20:17 -0700567
568MODULE_DESCRIPTION(DRIVER_DESC);
Jack Phamf6ed5582011-11-02 16:08:31 -0700569MODULE_VERSION(DRIVER_VERSION);
570MODULE_LICENSE("GPL v2");