~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/usb/class/cdc-wdm.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * cdc-wdm.c
 
3
 *
 
4
 * This driver supports USB CDC WCM Device Management.
 
5
 *
 
6
 * Copyright (c) 2007-2009 Oliver Neukum
 
7
 *
 
8
 * Some code taken from cdc-acm.c
 
9
 *
 
10
 * Released under the GPLv2.
 
11
 *
 
12
 * Many thanks to Carl Nordbeck
 
13
 */
 
14
#include <linux/kernel.h>
 
15
#include <linux/errno.h>
 
16
#include <linux/slab.h>
 
17
#include <linux/module.h>
 
18
#include <linux/mutex.h>
 
19
#include <linux/uaccess.h>
 
20
#include <linux/bitops.h>
 
21
#include <linux/poll.h>
 
22
#include <linux/usb.h>
 
23
#include <linux/usb/cdc.h>
 
24
#include <asm/byteorder.h>
 
25
#include <asm/unaligned.h>
 
26
 
 
27
/*
 
28
 * Version Information
 
29
 */
 
30
#define DRIVER_VERSION "v0.03"
 
31
#define DRIVER_AUTHOR "Oliver Neukum"
 
32
#define DRIVER_DESC "USB Abstract Control Model driver for USB WCM Device Management"
 
33
 
 
34
static const struct usb_device_id wdm_ids[] = {
 
35
        {
 
36
                .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS |
 
37
                                 USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 
38
                .bInterfaceClass = USB_CLASS_COMM,
 
39
                .bInterfaceSubClass = USB_CDC_SUBCLASS_DMM
 
40
        },
 
41
        { }
 
42
};
 
43
 
 
44
MODULE_DEVICE_TABLE (usb, wdm_ids);
 
45
 
 
46
#define WDM_MINOR_BASE  176
 
47
 
 
48
 
 
49
#define WDM_IN_USE              1
 
50
#define WDM_DISCONNECTING       2
 
51
#define WDM_RESULT              3
 
52
#define WDM_READ                4
 
53
#define WDM_INT_STALL           5
 
54
#define WDM_POLL_RUNNING        6
 
55
#define WDM_RESPONDING          7
 
56
#define WDM_SUSPENDING          8
 
57
 
 
58
#define WDM_MAX                 16
 
59
 
 
60
 
 
61
static DEFINE_MUTEX(wdm_mutex);
 
62
 
 
63
/* --- method tables --- */
 
64
 
 
65
struct wdm_device {
 
66
        u8                      *inbuf; /* buffer for response */
 
67
        u8                      *outbuf; /* buffer for command */
 
68
        u8                      *sbuf; /* buffer for status */
 
69
        u8                      *ubuf; /* buffer for copy to user space */
 
70
 
 
71
        struct urb              *command;
 
72
        struct urb              *response;
 
73
        struct urb              *validity;
 
74
        struct usb_interface    *intf;
 
75
        struct usb_ctrlrequest  *orq;
 
76
        struct usb_ctrlrequest  *irq;
 
77
        spinlock_t              iuspin;
 
78
 
 
79
        unsigned long           flags;
 
80
        u16                     bufsize;
 
81
        u16                     wMaxCommand;
 
82
        u16                     wMaxPacketSize;
 
83
        u16                     bMaxPacketSize0;
 
84
        __le16                  inum;
 
85
        int                     reslength;
 
86
        int                     length;
 
87
        int                     read;
 
88
        int                     count;
 
89
        dma_addr_t              shandle;
 
90
        dma_addr_t              ihandle;
 
91
        struct mutex            lock;
 
92
        wait_queue_head_t       wait;
 
93
        struct work_struct      rxwork;
 
94
        int                     werr;
 
95
        int                     rerr;
 
96
};
 
97
 
 
98
static struct usb_driver wdm_driver;
 
99
 
 
100
/* --- callbacks --- */
 
101
static void wdm_out_callback(struct urb *urb)
 
102
{
 
103
        struct wdm_device *desc;
 
104
        desc = urb->context;
 
105
        spin_lock(&desc->iuspin);
 
106
        desc->werr = urb->status;
 
107
        spin_unlock(&desc->iuspin);
 
108
        clear_bit(WDM_IN_USE, &desc->flags);
 
109
        kfree(desc->outbuf);
 
110
        wake_up(&desc->wait);
 
111
}
 
112
 
 
113
static void wdm_in_callback(struct urb *urb)
 
114
{
 
115
        struct wdm_device *desc = urb->context;
 
116
        int status = urb->status;
 
117
 
 
118
        spin_lock(&desc->iuspin);
 
119
        clear_bit(WDM_RESPONDING, &desc->flags);
 
120
 
 
121
        if (status) {
 
122
                switch (status) {
 
123
                case -ENOENT:
 
124
                        dev_dbg(&desc->intf->dev,
 
125
                                "nonzero urb status received: -ENOENT");
 
126
                        goto skip_error;
 
127
                case -ECONNRESET:
 
128
                        dev_dbg(&desc->intf->dev,
 
129
                                "nonzero urb status received: -ECONNRESET");
 
130
                        goto skip_error;
 
131
                case -ESHUTDOWN:
 
132
                        dev_dbg(&desc->intf->dev,
 
133
                                "nonzero urb status received: -ESHUTDOWN");
 
134
                        goto skip_error;
 
135
                case -EPIPE:
 
136
                        dev_err(&desc->intf->dev,
 
137
                                "nonzero urb status received: -EPIPE\n");
 
138
                        break;
 
139
                default:
 
140
                        dev_err(&desc->intf->dev,
 
141
                                "Unexpected error %d\n", status);
 
142
                        break;
 
143
                }
 
144
        }
 
145
 
 
146
        desc->rerr = status;
 
147
        desc->reslength = urb->actual_length;
 
148
        memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
 
149
        desc->length += desc->reslength;
 
150
skip_error:
 
151
        wake_up(&desc->wait);
 
152
 
 
153
        set_bit(WDM_READ, &desc->flags);
 
154
        spin_unlock(&desc->iuspin);
 
155
}
 
156
 
 
157
static void wdm_int_callback(struct urb *urb)
 
158
{
 
159
        int rv = 0;
 
160
        int status = urb->status;
 
161
        struct wdm_device *desc;
 
162
        struct usb_ctrlrequest *req;
 
163
        struct usb_cdc_notification *dr;
 
164
 
 
165
        desc = urb->context;
 
166
        req = desc->irq;
 
167
        dr = (struct usb_cdc_notification *)desc->sbuf;
 
168
 
 
169
        if (status) {
 
170
                switch (status) {
 
171
                case -ESHUTDOWN:
 
172
                case -ENOENT:
 
173
                case -ECONNRESET:
 
174
                        return; /* unplug */
 
175
                case -EPIPE:
 
176
                        set_bit(WDM_INT_STALL, &desc->flags);
 
177
                        dev_err(&desc->intf->dev, "Stall on int endpoint\n");
 
178
                        goto sw; /* halt is cleared in work */
 
179
                default:
 
180
                        dev_err(&desc->intf->dev,
 
181
                                "nonzero urb status received: %d\n", status);
 
182
                        break;
 
183
                }
 
184
        }
 
185
 
 
186
        if (urb->actual_length < sizeof(struct usb_cdc_notification)) {
 
187
                dev_err(&desc->intf->dev, "wdm_int_callback - %d bytes\n",
 
188
                        urb->actual_length);
 
189
                goto exit;
 
190
        }
 
191
 
 
192
        switch (dr->bNotificationType) {
 
193
        case USB_CDC_NOTIFY_RESPONSE_AVAILABLE:
 
194
                dev_dbg(&desc->intf->dev,
 
195
                        "NOTIFY_RESPONSE_AVAILABLE received: index %d len %d",
 
196
                        dr->wIndex, dr->wLength);
 
197
                break;
 
198
 
 
199
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
 
200
 
 
201
                dev_dbg(&desc->intf->dev,
 
202
                        "NOTIFY_NETWORK_CONNECTION %s network",
 
203
                        dr->wValue ? "connected to" : "disconnected from");
 
204
                goto exit;
 
205
        default:
 
206
                clear_bit(WDM_POLL_RUNNING, &desc->flags);
 
207
                dev_err(&desc->intf->dev,
 
208
                        "unknown notification %d received: index %d len %d\n",
 
209
                        dr->bNotificationType, dr->wIndex, dr->wLength);
 
210
                goto exit;
 
211
        }
 
212
 
 
213
        req->bRequestType = (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE);
 
214
        req->bRequest = USB_CDC_GET_ENCAPSULATED_RESPONSE;
 
215
        req->wValue = 0;
 
216
        req->wIndex = desc->inum;
 
217
        req->wLength = cpu_to_le16(desc->wMaxCommand);
 
218
 
 
219
        usb_fill_control_urb(
 
220
                desc->response,
 
221
                interface_to_usbdev(desc->intf),
 
222
                /* using common endpoint 0 */
 
223
                usb_rcvctrlpipe(interface_to_usbdev(desc->intf), 0),
 
224
                (unsigned char *)req,
 
225
                desc->inbuf,
 
226
                desc->wMaxCommand,
 
227
                wdm_in_callback,
 
228
                desc
 
229
        );
 
230
        desc->response->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
231
        spin_lock(&desc->iuspin);
 
232
        clear_bit(WDM_READ, &desc->flags);
 
233
        set_bit(WDM_RESPONDING, &desc->flags);
 
234
        if (!test_bit(WDM_DISCONNECTING, &desc->flags)
 
235
                && !test_bit(WDM_SUSPENDING, &desc->flags)) {
 
236
                rv = usb_submit_urb(desc->response, GFP_ATOMIC);
 
237
                dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d",
 
238
                        __func__, rv);
 
239
        }
 
240
        spin_unlock(&desc->iuspin);
 
241
        if (rv < 0) {
 
242
                clear_bit(WDM_RESPONDING, &desc->flags);
 
243
                if (rv == -EPERM)
 
244
                        return;
 
245
                if (rv == -ENOMEM) {
 
246
sw:
 
247
                        rv = schedule_work(&desc->rxwork);
 
248
                        if (rv)
 
249
                                dev_err(&desc->intf->dev,
 
250
                                        "Cannot schedule work\n");
 
251
                }
 
252
        }
 
253
exit:
 
254
        rv = usb_submit_urb(urb, GFP_ATOMIC);
 
255
        if (rv)
 
256
                dev_err(&desc->intf->dev,
 
257
                        "%s - usb_submit_urb failed with result %d\n",
 
258
                        __func__, rv);
 
259
 
 
260
}
 
261
 
 
262
static void kill_urbs(struct wdm_device *desc)
 
263
{
 
264
        /* the order here is essential */
 
265
        usb_kill_urb(desc->command);
 
266
        usb_kill_urb(desc->validity);
 
267
        usb_kill_urb(desc->response);
 
268
}
 
269
 
 
270
static void free_urbs(struct wdm_device *desc)
 
271
{
 
272
        usb_free_urb(desc->validity);
 
273
        usb_free_urb(desc->response);
 
274
        usb_free_urb(desc->command);
 
275
}
 
276
 
 
277
static void cleanup(struct wdm_device *desc)
 
278
{
 
279
        usb_free_coherent(interface_to_usbdev(desc->intf),
 
280
                          desc->wMaxPacketSize,
 
281
                          desc->sbuf,
 
282
                          desc->validity->transfer_dma);
 
283
        usb_free_coherent(interface_to_usbdev(desc->intf),
 
284
                          desc->bMaxPacketSize0,
 
285
                          desc->inbuf,
 
286
                          desc->response->transfer_dma);
 
287
        kfree(desc->orq);
 
288
        kfree(desc->irq);
 
289
        kfree(desc->ubuf);
 
290
        free_urbs(desc);
 
291
        kfree(desc);
 
292
}
 
293
 
 
294
static ssize_t wdm_write
 
295
(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
 
296
{
 
297
        u8 *buf;
 
298
        int rv = -EMSGSIZE, r, we;
 
299
        struct wdm_device *desc = file->private_data;
 
300
        struct usb_ctrlrequest *req;
 
301
 
 
302
        if (count > desc->wMaxCommand)
 
303
                count = desc->wMaxCommand;
 
304
 
 
305
        spin_lock_irq(&desc->iuspin);
 
306
        we = desc->werr;
 
307
        desc->werr = 0;
 
308
        spin_unlock_irq(&desc->iuspin);
 
309
        if (we < 0)
 
310
                return -EIO;
 
311
 
 
312
        desc->outbuf = buf = kmalloc(count, GFP_KERNEL);
 
313
        if (!buf) {
 
314
                rv = -ENOMEM;
 
315
                goto outnl;
 
316
        }
 
317
 
 
318
        r = copy_from_user(buf, buffer, count);
 
319
        if (r > 0) {
 
320
                kfree(buf);
 
321
                rv = -EFAULT;
 
322
                goto outnl;
 
323
        }
 
324
 
 
325
        /* concurrent writes and disconnect */
 
326
        r = mutex_lock_interruptible(&desc->lock);
 
327
        rv = -ERESTARTSYS;
 
328
        if (r) {
 
329
                kfree(buf);
 
330
                goto outnl;
 
331
        }
 
332
 
 
333
        if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
 
334
                kfree(buf);
 
335
                rv = -ENODEV;
 
336
                goto outnp;
 
337
        }
 
338
 
 
339
        r = usb_autopm_get_interface(desc->intf);
 
340
        if (r < 0) {
 
341
                kfree(buf);
 
342
                goto outnp;
 
343
        }
 
344
 
 
345
        if (!(file->f_flags & O_NONBLOCK))
 
346
                r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE,
 
347
                                                                &desc->flags));
 
348
        else
 
349
                if (test_bit(WDM_IN_USE, &desc->flags))
 
350
                        r = -EAGAIN;
 
351
        if (r < 0) {
 
352
                kfree(buf);
 
353
                goto out;
 
354
        }
 
355
 
 
356
        req = desc->orq;
 
357
        usb_fill_control_urb(
 
358
                desc->command,
 
359
                interface_to_usbdev(desc->intf),
 
360
                /* using common endpoint 0 */
 
361
                usb_sndctrlpipe(interface_to_usbdev(desc->intf), 0),
 
362
                (unsigned char *)req,
 
363
                buf,
 
364
                count,
 
365
                wdm_out_callback,
 
366
                desc
 
367
        );
 
368
 
 
369
        req->bRequestType = (USB_DIR_OUT | USB_TYPE_CLASS |
 
370
                             USB_RECIP_INTERFACE);
 
371
        req->bRequest = USB_CDC_SEND_ENCAPSULATED_COMMAND;
 
372
        req->wValue = 0;
 
373
        req->wIndex = desc->inum;
 
374
        req->wLength = cpu_to_le16(count);
 
375
        set_bit(WDM_IN_USE, &desc->flags);
 
376
 
 
377
        rv = usb_submit_urb(desc->command, GFP_KERNEL);
 
378
        if (rv < 0) {
 
379
                kfree(buf);
 
380
                clear_bit(WDM_IN_USE, &desc->flags);
 
381
                dev_err(&desc->intf->dev, "Tx URB error: %d\n", rv);
 
382
        } else {
 
383
                dev_dbg(&desc->intf->dev, "Tx URB has been submitted index=%d",
 
384
                        req->wIndex);
 
385
        }
 
386
out:
 
387
        usb_autopm_put_interface(desc->intf);
 
388
outnp:
 
389
        mutex_unlock(&desc->lock);
 
390
outnl:
 
391
        return rv < 0 ? rv : count;
 
392
}
 
393
 
 
394
static ssize_t wdm_read
 
395
(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
 
396
{
 
397
        int rv, cntr = 0;
 
398
        int i = 0;
 
399
        struct wdm_device *desc = file->private_data;
 
400
 
 
401
 
 
402
        rv = mutex_lock_interruptible(&desc->lock); /*concurrent reads */
 
403
        if (rv < 0)
 
404
                return -ERESTARTSYS;
 
405
 
 
406
        if (desc->length == 0) {
 
407
                desc->read = 0;
 
408
retry:
 
409
                if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
 
410
                        rv = -ENODEV;
 
411
                        goto err;
 
412
                }
 
413
                i++;
 
414
                if (file->f_flags & O_NONBLOCK) {
 
415
                        if (!test_bit(WDM_READ, &desc->flags)) {
 
416
                                rv = cntr ? cntr : -EAGAIN;
 
417
                                goto err;
 
418
                        }
 
419
                        rv = 0;
 
420
                } else {
 
421
                        rv = wait_event_interruptible(desc->wait,
 
422
                                test_bit(WDM_READ, &desc->flags));
 
423
                }
 
424
 
 
425
                /* may have happened while we slept */
 
426
                if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
 
427
                        rv = -ENODEV;
 
428
                        goto err;
 
429
                }
 
430
                usb_mark_last_busy(interface_to_usbdev(desc->intf));
 
431
                if (rv < 0) {
 
432
                        rv = -ERESTARTSYS;
 
433
                        goto err;
 
434
                }
 
435
 
 
436
                spin_lock_irq(&desc->iuspin);
 
437
 
 
438
                if (desc->rerr) { /* read completed, error happened */
 
439
                        desc->rerr = 0;
 
440
                        spin_unlock_irq(&desc->iuspin);
 
441
                        rv = -EIO;
 
442
                        goto err;
 
443
                }
 
444
                /*
 
445
                 * recheck whether we've lost the race
 
446
                 * against the completion handler
 
447
                 */
 
448
                if (!test_bit(WDM_READ, &desc->flags)) { /* lost race */
 
449
                        spin_unlock_irq(&desc->iuspin);
 
450
                        goto retry;
 
451
                }
 
452
                if (!desc->reslength) { /* zero length read */
 
453
                        spin_unlock_irq(&desc->iuspin);
 
454
                        goto retry;
 
455
                }
 
456
                clear_bit(WDM_READ, &desc->flags);
 
457
                spin_unlock_irq(&desc->iuspin);
 
458
        }
 
459
 
 
460
        cntr = count > desc->length ? desc->length : count;
 
461
        rv = copy_to_user(buffer, desc->ubuf, cntr);
 
462
        if (rv > 0) {
 
463
                rv = -EFAULT;
 
464
                goto err;
 
465
        }
 
466
 
 
467
        for (i = 0; i < desc->length - cntr; i++)
 
468
                desc->ubuf[i] = desc->ubuf[i + cntr];
 
469
 
 
470
        desc->length -= cntr;
 
471
        /* in case we had outstanding data */
 
472
        if (!desc->length)
 
473
                clear_bit(WDM_READ, &desc->flags);
 
474
        rv = cntr;
 
475
 
 
476
err:
 
477
        mutex_unlock(&desc->lock);
 
478
        return rv;
 
479
}
 
480
 
 
481
static int wdm_flush(struct file *file, fl_owner_t id)
 
482
{
 
483
        struct wdm_device *desc = file->private_data;
 
484
 
 
485
        wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags));
 
486
        if (desc->werr < 0)
 
487
                dev_err(&desc->intf->dev, "Error in flush path: %d\n",
 
488
                        desc->werr);
 
489
 
 
490
        return desc->werr;
 
491
}
 
492
 
 
493
static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait)
 
494
{
 
495
        struct wdm_device *desc = file->private_data;
 
496
        unsigned long flags;
 
497
        unsigned int mask = 0;
 
498
 
 
499
        spin_lock_irqsave(&desc->iuspin, flags);
 
500
        if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
 
501
                mask = POLLERR;
 
502
                spin_unlock_irqrestore(&desc->iuspin, flags);
 
503
                goto desc_out;
 
504
        }
 
505
        if (test_bit(WDM_READ, &desc->flags))
 
506
                mask = POLLIN | POLLRDNORM;
 
507
        if (desc->rerr || desc->werr)
 
508
                mask |= POLLERR;
 
509
        if (!test_bit(WDM_IN_USE, &desc->flags))
 
510
                mask |= POLLOUT | POLLWRNORM;
 
511
        spin_unlock_irqrestore(&desc->iuspin, flags);
 
512
 
 
513
        poll_wait(file, &desc->wait, wait);
 
514
 
 
515
desc_out:
 
516
        return mask;
 
517
}
 
518
 
 
519
static int wdm_open(struct inode *inode, struct file *file)
 
520
{
 
521
        int minor = iminor(inode);
 
522
        int rv = -ENODEV;
 
523
        struct usb_interface *intf;
 
524
        struct wdm_device *desc;
 
525
 
 
526
        mutex_lock(&wdm_mutex);
 
527
        intf = usb_find_interface(&wdm_driver, minor);
 
528
        if (!intf)
 
529
                goto out;
 
530
 
 
531
        desc = usb_get_intfdata(intf);
 
532
        if (test_bit(WDM_DISCONNECTING, &desc->flags))
 
533
                goto out;
 
534
        file->private_data = desc;
 
535
 
 
536
        rv = usb_autopm_get_interface(desc->intf);
 
537
        if (rv < 0) {
 
538
                dev_err(&desc->intf->dev, "Error autopm - %d\n", rv);
 
539
                goto out;
 
540
        }
 
541
        intf->needs_remote_wakeup = 1;
 
542
 
 
543
        mutex_lock(&desc->lock);
 
544
        if (!desc->count++) {
 
545
                desc->werr = 0;
 
546
                desc->rerr = 0;
 
547
                rv = usb_submit_urb(desc->validity, GFP_KERNEL);
 
548
                if (rv < 0) {
 
549
                        desc->count--;
 
550
                        dev_err(&desc->intf->dev,
 
551
                                "Error submitting int urb - %d\n", rv);
 
552
                }
 
553
        } else {
 
554
                rv = 0;
 
555
        }
 
556
        mutex_unlock(&desc->lock);
 
557
        usb_autopm_put_interface(desc->intf);
 
558
out:
 
559
        mutex_unlock(&wdm_mutex);
 
560
        return rv;
 
561
}
 
562
 
 
563
static int wdm_release(struct inode *inode, struct file *file)
 
564
{
 
565
        struct wdm_device *desc = file->private_data;
 
566
 
 
567
        mutex_lock(&wdm_mutex);
 
568
        mutex_lock(&desc->lock);
 
569
        desc->count--;
 
570
        mutex_unlock(&desc->lock);
 
571
 
 
572
        if (!desc->count) {
 
573
                dev_dbg(&desc->intf->dev, "wdm_release: cleanup");
 
574
                kill_urbs(desc);
 
575
                if (!test_bit(WDM_DISCONNECTING, &desc->flags))
 
576
                        desc->intf->needs_remote_wakeup = 0;
 
577
        }
 
578
        mutex_unlock(&wdm_mutex);
 
579
        return 0;
 
580
}
 
581
 
 
582
static const struct file_operations wdm_fops = {
 
583
        .owner =        THIS_MODULE,
 
584
        .read =         wdm_read,
 
585
        .write =        wdm_write,
 
586
        .open =         wdm_open,
 
587
        .flush =        wdm_flush,
 
588
        .release =      wdm_release,
 
589
        .poll =         wdm_poll,
 
590
        .llseek =       noop_llseek,
 
591
};
 
592
 
 
593
static struct usb_class_driver wdm_class = {
 
594
        .name =         "cdc-wdm%d",
 
595
        .fops =         &wdm_fops,
 
596
        .minor_base =   WDM_MINOR_BASE,
 
597
};
 
598
 
 
599
/* --- error handling --- */
 
600
static void wdm_rxwork(struct work_struct *work)
 
601
{
 
602
        struct wdm_device *desc = container_of(work, struct wdm_device, rxwork);
 
603
        unsigned long flags;
 
604
        int rv;
 
605
 
 
606
        spin_lock_irqsave(&desc->iuspin, flags);
 
607
        if (test_bit(WDM_DISCONNECTING, &desc->flags)) {
 
608
                spin_unlock_irqrestore(&desc->iuspin, flags);
 
609
        } else {
 
610
                spin_unlock_irqrestore(&desc->iuspin, flags);
 
611
                rv = usb_submit_urb(desc->response, GFP_KERNEL);
 
612
                if (rv < 0 && rv != -EPERM) {
 
613
                        spin_lock_irqsave(&desc->iuspin, flags);
 
614
                        if (!test_bit(WDM_DISCONNECTING, &desc->flags))
 
615
                                schedule_work(&desc->rxwork);
 
616
                        spin_unlock_irqrestore(&desc->iuspin, flags);
 
617
                }
 
618
        }
 
619
}
 
620
 
 
621
/* --- hotplug --- */
 
622
 
 
623
static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id)
 
624
{
 
625
        int rv = -EINVAL;
 
626
        struct usb_device *udev = interface_to_usbdev(intf);
 
627
        struct wdm_device *desc;
 
628
        struct usb_host_interface *iface;
 
629
        struct usb_endpoint_descriptor *ep;
 
630
        struct usb_cdc_dmm_desc *dmhd;
 
631
        u8 *buffer = intf->altsetting->extra;
 
632
        int buflen = intf->altsetting->extralen;
 
633
        u16 maxcom = 0;
 
634
 
 
635
        if (!buffer)
 
636
                goto out;
 
637
 
 
638
        while (buflen > 2) {
 
639
                if (buffer [1] != USB_DT_CS_INTERFACE) {
 
640
                        dev_err(&intf->dev, "skipping garbage\n");
 
641
                        goto next_desc;
 
642
                }
 
643
 
 
644
                switch (buffer [2]) {
 
645
                case USB_CDC_HEADER_TYPE:
 
646
                        break;
 
647
                case USB_CDC_DMM_TYPE:
 
648
                        dmhd = (struct usb_cdc_dmm_desc *)buffer;
 
649
                        maxcom = le16_to_cpu(dmhd->wMaxCommand);
 
650
                        dev_dbg(&intf->dev,
 
651
                                "Finding maximum buffer length: %d", maxcom);
 
652
                        break;
 
653
                default:
 
654
                        dev_err(&intf->dev,
 
655
                                "Ignoring extra header, type %d, length %d\n",
 
656
                                buffer[2], buffer[0]);
 
657
                        break;
 
658
                }
 
659
next_desc:
 
660
                buflen -= buffer[0];
 
661
                buffer += buffer[0];
 
662
        }
 
663
 
 
664
        rv = -ENOMEM;
 
665
        desc = kzalloc(sizeof(struct wdm_device), GFP_KERNEL);
 
666
        if (!desc)
 
667
                goto out;
 
668
        mutex_init(&desc->lock);
 
669
        spin_lock_init(&desc->iuspin);
 
670
        init_waitqueue_head(&desc->wait);
 
671
        desc->wMaxCommand = maxcom;
 
672
        /* this will be expanded and needed in hardware endianness */
 
673
        desc->inum = cpu_to_le16((u16)intf->cur_altsetting->desc.bInterfaceNumber);
 
674
        desc->intf = intf;
 
675
        INIT_WORK(&desc->rxwork, wdm_rxwork);
 
676
 
 
677
        rv = -EINVAL;
 
678
        iface = intf->cur_altsetting;
 
679
        if (iface->desc.bNumEndpoints != 1)
 
680
                goto err;
 
681
        ep = &iface->endpoint[0].desc;
 
682
        if (!ep || !usb_endpoint_is_int_in(ep))
 
683
                goto err;
 
684
 
 
685
        desc->wMaxPacketSize = usb_endpoint_maxp(ep);
 
686
        desc->bMaxPacketSize0 = udev->descriptor.bMaxPacketSize0;
 
687
 
 
688
        desc->orq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
 
689
        if (!desc->orq)
 
690
                goto err;
 
691
        desc->irq = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
 
692
        if (!desc->irq)
 
693
                goto err;
 
694
 
 
695
        desc->validity = usb_alloc_urb(0, GFP_KERNEL);
 
696
        if (!desc->validity)
 
697
                goto err;
 
698
 
 
699
        desc->response = usb_alloc_urb(0, GFP_KERNEL);
 
700
        if (!desc->response)
 
701
                goto err;
 
702
 
 
703
        desc->command = usb_alloc_urb(0, GFP_KERNEL);
 
704
        if (!desc->command)
 
705
                goto err;
 
706
 
 
707
        desc->ubuf = kmalloc(desc->wMaxCommand, GFP_KERNEL);
 
708
        if (!desc->ubuf)
 
709
                goto err;
 
710
 
 
711
        desc->sbuf = usb_alloc_coherent(interface_to_usbdev(intf),
 
712
                                        desc->wMaxPacketSize,
 
713
                                        GFP_KERNEL,
 
714
                                        &desc->validity->transfer_dma);
 
715
        if (!desc->sbuf)
 
716
                goto err;
 
717
 
 
718
        desc->inbuf = usb_alloc_coherent(interface_to_usbdev(intf),
 
719
                                         desc->bMaxPacketSize0,
 
720
                                         GFP_KERNEL,
 
721
                                         &desc->response->transfer_dma);
 
722
        if (!desc->inbuf)
 
723
                goto err2;
 
724
 
 
725
        usb_fill_int_urb(
 
726
                desc->validity,
 
727
                interface_to_usbdev(intf),
 
728
                usb_rcvintpipe(interface_to_usbdev(intf), ep->bEndpointAddress),
 
729
                desc->sbuf,
 
730
                desc->wMaxPacketSize,
 
731
                wdm_int_callback,
 
732
                desc,
 
733
                ep->bInterval
 
734
        );
 
735
        desc->validity->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
736
 
 
737
        usb_set_intfdata(intf, desc);
 
738
        rv = usb_register_dev(intf, &wdm_class);
 
739
        if (rv < 0)
 
740
                goto err3;
 
741
        else
 
742
                dev_info(&intf->dev, "cdc-wdm%d: USB WDM device\n",
 
743
                        intf->minor - WDM_MINOR_BASE);
 
744
out:
 
745
        return rv;
 
746
err3:
 
747
        usb_set_intfdata(intf, NULL);
 
748
        usb_free_coherent(interface_to_usbdev(desc->intf),
 
749
                          desc->bMaxPacketSize0,
 
750
                        desc->inbuf,
 
751
                        desc->response->transfer_dma);
 
752
err2:
 
753
        usb_free_coherent(interface_to_usbdev(desc->intf),
 
754
                          desc->wMaxPacketSize,
 
755
                          desc->sbuf,
 
756
                          desc->validity->transfer_dma);
 
757
err:
 
758
        free_urbs(desc);
 
759
        kfree(desc->ubuf);
 
760
        kfree(desc->orq);
 
761
        kfree(desc->irq);
 
762
        kfree(desc);
 
763
        return rv;
 
764
}
 
765
 
 
766
static void wdm_disconnect(struct usb_interface *intf)
 
767
{
 
768
        struct wdm_device *desc;
 
769
        unsigned long flags;
 
770
 
 
771
        usb_deregister_dev(intf, &wdm_class);
 
772
        mutex_lock(&wdm_mutex);
 
773
        desc = usb_get_intfdata(intf);
 
774
 
 
775
        /* the spinlock makes sure no new urbs are generated in the callbacks */
 
776
        spin_lock_irqsave(&desc->iuspin, flags);
 
777
        set_bit(WDM_DISCONNECTING, &desc->flags);
 
778
        set_bit(WDM_READ, &desc->flags);
 
779
        /* to terminate pending flushes */
 
780
        clear_bit(WDM_IN_USE, &desc->flags);
 
781
        spin_unlock_irqrestore(&desc->iuspin, flags);
 
782
        mutex_lock(&desc->lock);
 
783
        kill_urbs(desc);
 
784
        cancel_work_sync(&desc->rxwork);
 
785
        mutex_unlock(&desc->lock);
 
786
        wake_up_all(&desc->wait);
 
787
        if (!desc->count)
 
788
                cleanup(desc);
 
789
        mutex_unlock(&wdm_mutex);
 
790
}
 
791
 
 
792
#ifdef CONFIG_PM
 
793
static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
 
794
{
 
795
        struct wdm_device *desc = usb_get_intfdata(intf);
 
796
        int rv = 0;
 
797
 
 
798
        dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);
 
799
 
 
800
        /* if this is an autosuspend the caller does the locking */
 
801
        if (!PMSG_IS_AUTO(message))
 
802
                mutex_lock(&desc->lock);
 
803
        spin_lock_irq(&desc->iuspin);
 
804
 
 
805
        if (PMSG_IS_AUTO(message) &&
 
806
                        (test_bit(WDM_IN_USE, &desc->flags)
 
807
                        || test_bit(WDM_RESPONDING, &desc->flags))) {
 
808
                spin_unlock_irq(&desc->iuspin);
 
809
                rv = -EBUSY;
 
810
        } else {
 
811
 
 
812
                set_bit(WDM_SUSPENDING, &desc->flags);
 
813
                spin_unlock_irq(&desc->iuspin);
 
814
                /* callback submits work - order is essential */
 
815
                kill_urbs(desc);
 
816
                cancel_work_sync(&desc->rxwork);
 
817
        }
 
818
        if (!PMSG_IS_AUTO(message))
 
819
                mutex_unlock(&desc->lock);
 
820
 
 
821
        return rv;
 
822
}
 
823
#endif
 
824
 
 
825
static int recover_from_urb_loss(struct wdm_device *desc)
 
826
{
 
827
        int rv = 0;
 
828
 
 
829
        if (desc->count) {
 
830
                rv = usb_submit_urb(desc->validity, GFP_NOIO);
 
831
                if (rv < 0)
 
832
                        dev_err(&desc->intf->dev,
 
833
                                "Error resume submitting int urb - %d\n", rv);
 
834
        }
 
835
        return rv;
 
836
}
 
837
 
 
838
#ifdef CONFIG_PM
 
839
static int wdm_resume(struct usb_interface *intf)
 
840
{
 
841
        struct wdm_device *desc = usb_get_intfdata(intf);
 
842
        int rv;
 
843
 
 
844
        dev_dbg(&desc->intf->dev, "wdm%d_resume\n", intf->minor);
 
845
 
 
846
        clear_bit(WDM_SUSPENDING, &desc->flags);
 
847
        rv = recover_from_urb_loss(desc);
 
848
 
 
849
        return rv;
 
850
}
 
851
#endif
 
852
 
 
853
static int wdm_pre_reset(struct usb_interface *intf)
 
854
{
 
855
        struct wdm_device *desc = usb_get_intfdata(intf);
 
856
 
 
857
        mutex_lock(&desc->lock);
 
858
        kill_urbs(desc);
 
859
 
 
860
        /*
 
861
         * we notify everybody using poll of
 
862
         * an exceptional situation
 
863
         * must be done before recovery lest a spontaneous
 
864
         * message from the device is lost
 
865
         */
 
866
        spin_lock_irq(&desc->iuspin);
 
867
        desc->rerr = -EINTR;
 
868
        spin_unlock_irq(&desc->iuspin);
 
869
        wake_up_all(&desc->wait);
 
870
        return 0;
 
871
}
 
872
 
 
873
static int wdm_post_reset(struct usb_interface *intf)
 
874
{
 
875
        struct wdm_device *desc = usb_get_intfdata(intf);
 
876
        int rv;
 
877
 
 
878
        rv = recover_from_urb_loss(desc);
 
879
        mutex_unlock(&desc->lock);
 
880
        return 0;
 
881
}
 
882
 
 
883
static struct usb_driver wdm_driver = {
 
884
        .name =         "cdc_wdm",
 
885
        .probe =        wdm_probe,
 
886
        .disconnect =   wdm_disconnect,
 
887
#ifdef CONFIG_PM
 
888
        .suspend =      wdm_suspend,
 
889
        .resume =       wdm_resume,
 
890
        .reset_resume = wdm_resume,
 
891
#endif
 
892
        .pre_reset =    wdm_pre_reset,
 
893
        .post_reset =   wdm_post_reset,
 
894
        .id_table =     wdm_ids,
 
895
        .supports_autosuspend = 1,
 
896
};
 
897
 
 
898
/* --- low level module stuff --- */
 
899
 
 
900
static int __init wdm_init(void)
 
901
{
 
902
        int rv;
 
903
 
 
904
        rv = usb_register(&wdm_driver);
 
905
 
 
906
        return rv;
 
907
}
 
908
 
 
909
static void __exit wdm_exit(void)
 
910
{
 
911
        usb_deregister(&wdm_driver);
 
912
}
 
913
 
 
914
module_init(wdm_init);
 
915
module_exit(wdm_exit);
 
916
 
 
917
MODULE_AUTHOR(DRIVER_AUTHOR);
 
918
MODULE_DESCRIPTION(DRIVER_DESC);
 
919
MODULE_LICENSE("GPL");