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

« back to all changes in this revision

Viewing changes to drivers/usb/gadget/dbgp.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
 * dbgp.c -- EHCI Debug Port device gadget
 
3
 *
 
4
 * Copyright (C) 2010 Stephane Duverger
 
5
 *
 
6
 * Released under the GPLv2.
 
7
 */
 
8
 
 
9
/* verbose messages */
 
10
#include <linux/kernel.h>
 
11
#include <linux/device.h>
 
12
#include <linux/module.h>
 
13
#include <linux/usb/ch9.h>
 
14
#include <linux/usb/gadget.h>
 
15
 
 
16
/* See comments in "zero.c" */
 
17
#include "epautoconf.c"
 
18
 
 
19
#ifdef CONFIG_USB_G_DBGP_SERIAL
 
20
#include "u_serial.c"
 
21
#endif
 
22
 
 
23
#define DRIVER_VENDOR_ID        0x0525 /* NetChip */
 
24
#define DRIVER_PRODUCT_ID       0xc0de /* undefined */
 
25
 
 
26
#define USB_DEBUG_MAX_PACKET_SIZE     8
 
27
#define DBGP_REQ_EP0_LEN              128
 
28
#define DBGP_REQ_LEN                  512
 
29
 
 
30
static struct dbgp {
 
31
        struct usb_gadget  *gadget;
 
32
        struct usb_request *req;
 
33
        struct usb_ep      *i_ep;
 
34
        struct usb_ep      *o_ep;
 
35
#ifdef CONFIG_USB_G_DBGP_SERIAL
 
36
        struct gserial     *serial;
 
37
#endif
 
38
} dbgp;
 
39
 
 
40
static struct usb_device_descriptor device_desc = {
 
41
        .bLength = sizeof device_desc,
 
42
        .bDescriptorType = USB_DT_DEVICE,
 
43
        .bcdUSB = __constant_cpu_to_le16(0x0200),
 
44
        .bDeviceClass = USB_CLASS_VENDOR_SPEC,
 
45
        .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID),
 
46
        .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID),
 
47
        .bNumConfigurations = 1,
 
48
};
 
49
 
 
50
static struct usb_debug_descriptor dbg_desc = {
 
51
        .bLength = sizeof dbg_desc,
 
52
        .bDescriptorType = USB_DT_DEBUG,
 
53
};
 
54
 
 
55
static struct usb_endpoint_descriptor i_desc = {
 
56
        .bLength = USB_DT_ENDPOINT_SIZE,
 
57
        .bDescriptorType = USB_DT_ENDPOINT,
 
58
        .bmAttributes = USB_ENDPOINT_XFER_BULK,
 
59
        .bEndpointAddress = USB_DIR_IN,
 
60
};
 
61
 
 
62
static struct usb_endpoint_descriptor o_desc = {
 
63
        .bLength = USB_DT_ENDPOINT_SIZE,
 
64
        .bDescriptorType = USB_DT_ENDPOINT,
 
65
        .bmAttributes = USB_ENDPOINT_XFER_BULK,
 
66
        .bEndpointAddress = USB_DIR_OUT,
 
67
};
 
68
 
 
69
#ifdef CONFIG_USB_G_DBGP_PRINTK
 
70
static int dbgp_consume(char *buf, unsigned len)
 
71
{
 
72
        char c;
 
73
 
 
74
        if (!len)
 
75
                return 0;
 
76
 
 
77
        c = buf[len-1];
 
78
        if (c != 0)
 
79
                buf[len-1] = 0;
 
80
 
 
81
        printk(KERN_NOTICE "%s%c", buf, c);
 
82
        return 0;
 
83
}
 
84
 
 
85
static void __disable_ep(struct usb_ep *ep)
 
86
{
 
87
        if (ep && ep->driver_data == dbgp.gadget) {
 
88
                usb_ep_disable(ep);
 
89
                ep->driver_data = NULL;
 
90
        }
 
91
}
 
92
 
 
93
static void dbgp_disable_ep(void)
 
94
{
 
95
        __disable_ep(dbgp.i_ep);
 
96
        __disable_ep(dbgp.o_ep);
 
97
}
 
98
 
 
99
static void dbgp_complete(struct usb_ep *ep, struct usb_request *req)
 
100
{
 
101
        int stp;
 
102
        int err = 0;
 
103
        int status = req->status;
 
104
 
 
105
        if (ep == dbgp.i_ep) {
 
106
                stp = 1;
 
107
                goto fail;
 
108
        }
 
109
 
 
110
        if (status != 0) {
 
111
                stp = 2;
 
112
                goto release_req;
 
113
        }
 
114
 
 
115
        dbgp_consume(req->buf, req->actual);
 
116
 
 
117
        req->length = DBGP_REQ_LEN;
 
118
        err = usb_ep_queue(ep, req, GFP_ATOMIC);
 
119
        if (err < 0) {
 
120
                stp = 3;
 
121
                goto release_req;
 
122
        }
 
123
 
 
124
        return;
 
125
 
 
126
release_req:
 
127
        kfree(req->buf);
 
128
        usb_ep_free_request(dbgp.o_ep, req);
 
129
        dbgp_disable_ep();
 
130
fail:
 
131
        dev_dbg(&dbgp.gadget->dev,
 
132
                "complete: failure (%d:%d) ==> %d\n", stp, err, status);
 
133
}
 
134
 
 
135
static int dbgp_enable_ep_req(struct usb_ep *ep)
 
136
{
 
137
        int err, stp;
 
138
        struct usb_request *req;
 
139
 
 
140
        req = usb_ep_alloc_request(ep, GFP_KERNEL);
 
141
        if (!req) {
 
142
                err = -ENOMEM;
 
143
                stp = 1;
 
144
                goto fail_1;
 
145
        }
 
146
 
 
147
        req->buf = kmalloc(DBGP_REQ_LEN, GFP_KERNEL);
 
148
        if (!req->buf) {
 
149
                err = -ENOMEM;
 
150
                stp = 2;
 
151
                goto fail_2;
 
152
        }
 
153
 
 
154
        req->complete = dbgp_complete;
 
155
        req->length = DBGP_REQ_LEN;
 
156
        err = usb_ep_queue(ep, req, GFP_ATOMIC);
 
157
        if (err < 0) {
 
158
                stp = 3;
 
159
                goto fail_3;
 
160
        }
 
161
 
 
162
        return 0;
 
163
 
 
164
fail_3:
 
165
        kfree(req->buf);
 
166
fail_2:
 
167
        usb_ep_free_request(dbgp.o_ep, req);
 
168
fail_1:
 
169
        dev_dbg(&dbgp.gadget->dev,
 
170
                "enable ep req: failure (%d:%d)\n", stp, err);
 
171
        return err;
 
172
}
 
173
 
 
174
static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
 
175
{
 
176
        int err;
 
177
        ep->desc = desc;
 
178
        err = usb_ep_enable(ep);
 
179
        ep->driver_data = dbgp.gadget;
 
180
        return err;
 
181
}
 
182
 
 
183
static int dbgp_enable_ep(void)
 
184
{
 
185
        int err, stp;
 
186
 
 
187
        err = __enable_ep(dbgp.i_ep, &i_desc);
 
188
        if (err < 0) {
 
189
                stp = 1;
 
190
                goto fail_1;
 
191
        }
 
192
 
 
193
        err = __enable_ep(dbgp.o_ep, &o_desc);
 
194
        if (err < 0) {
 
195
                stp = 2;
 
196
                goto fail_2;
 
197
        }
 
198
 
 
199
        err = dbgp_enable_ep_req(dbgp.o_ep);
 
200
        if (err < 0) {
 
201
                stp = 3;
 
202
                goto fail_3;
 
203
        }
 
204
 
 
205
        return 0;
 
206
 
 
207
fail_3:
 
208
        __disable_ep(dbgp.o_ep);
 
209
fail_2:
 
210
        __disable_ep(dbgp.i_ep);
 
211
fail_1:
 
212
        dev_dbg(&dbgp.gadget->dev, "enable ep: failure (%d:%d)\n", stp, err);
 
213
        return err;
 
214
}
 
215
#endif
 
216
 
 
217
static void dbgp_disconnect(struct usb_gadget *gadget)
 
218
{
 
219
#ifdef CONFIG_USB_G_DBGP_PRINTK
 
220
        dbgp_disable_ep();
 
221
#else
 
222
        gserial_disconnect(dbgp.serial);
 
223
#endif
 
224
}
 
225
 
 
226
static void dbgp_unbind(struct usb_gadget *gadget)
 
227
{
 
228
#ifdef CONFIG_USB_G_DBGP_SERIAL
 
229
        kfree(dbgp.serial);
 
230
#endif
 
231
        if (dbgp.req) {
 
232
                kfree(dbgp.req->buf);
 
233
                usb_ep_free_request(gadget->ep0, dbgp.req);
 
234
        }
 
235
 
 
236
        gadget->ep0->driver_data = NULL;
 
237
}
 
238
 
 
239
static int __init dbgp_configure_endpoints(struct usb_gadget *gadget)
 
240
{
 
241
        int stp;
 
242
 
 
243
        usb_ep_autoconfig_reset(gadget);
 
244
 
 
245
        dbgp.i_ep = usb_ep_autoconfig(gadget, &i_desc);
 
246
        if (!dbgp.i_ep) {
 
247
                stp = 1;
 
248
                goto fail_1;
 
249
        }
 
250
 
 
251
        dbgp.i_ep->driver_data = gadget;
 
252
        i_desc.wMaxPacketSize =
 
253
                __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
 
254
 
 
255
        dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
 
256
        if (!dbgp.o_ep) {
 
257
                dbgp.i_ep->driver_data = NULL;
 
258
                stp = 2;
 
259
                goto fail_2;
 
260
        }
 
261
 
 
262
        dbgp.o_ep->driver_data = gadget;
 
263
        o_desc.wMaxPacketSize =
 
264
                __constant_cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
 
265
 
 
266
        dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
 
267
        dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
 
268
 
 
269
#ifdef CONFIG_USB_G_DBGP_SERIAL
 
270
        dbgp.serial->in = dbgp.i_ep;
 
271
        dbgp.serial->out = dbgp.o_ep;
 
272
 
 
273
        dbgp.serial->in->desc = &i_desc;
 
274
        dbgp.serial->out->desc = &o_desc;
 
275
 
 
276
        if (gserial_setup(gadget, 1) < 0) {
 
277
                stp = 3;
 
278
                goto fail_3;
 
279
        }
 
280
 
 
281
        return 0;
 
282
 
 
283
fail_3:
 
284
        dbgp.o_ep->driver_data = NULL;
 
285
#else
 
286
        return 0;
 
287
#endif
 
288
fail_2:
 
289
        dbgp.i_ep->driver_data = NULL;
 
290
fail_1:
 
291
        dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp);
 
292
        return -ENODEV;
 
293
}
 
294
 
 
295
static int __init dbgp_bind(struct usb_gadget *gadget)
 
296
{
 
297
        int err, stp;
 
298
 
 
299
        dbgp.gadget = gadget;
 
300
 
 
301
        dbgp.req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
 
302
        if (!dbgp.req) {
 
303
                err = -ENOMEM;
 
304
                stp = 1;
 
305
                goto fail;
 
306
        }
 
307
 
 
308
        dbgp.req->buf = kmalloc(DBGP_REQ_EP0_LEN, GFP_KERNEL);
 
309
        if (!dbgp.req->buf) {
 
310
                err = -ENOMEM;
 
311
                stp = 2;
 
312
                goto fail;
 
313
        }
 
314
 
 
315
        dbgp.req->length = DBGP_REQ_EP0_LEN;
 
316
        gadget->ep0->driver_data = gadget;
 
317
 
 
318
#ifdef CONFIG_USB_G_DBGP_SERIAL
 
319
        dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
 
320
        if (!dbgp.serial) {
 
321
                stp = 3;
 
322
                err = -ENOMEM;
 
323
                goto fail;
 
324
        }
 
325
#endif
 
326
        err = dbgp_configure_endpoints(gadget);
 
327
        if (err < 0) {
 
328
                stp = 4;
 
329
                goto fail;
 
330
        }
 
331
 
 
332
        dev_dbg(&dbgp.gadget->dev, "bind: success\n");
 
333
        return 0;
 
334
 
 
335
fail:
 
336
        dev_dbg(&gadget->dev, "bind: failure (%d:%d)\n", stp, err);
 
337
        dbgp_unbind(gadget);
 
338
        return err;
 
339
}
 
340
 
 
341
static void dbgp_setup_complete(struct usb_ep *ep,
 
342
                                struct usb_request *req)
 
343
{
 
344
        dev_dbg(&dbgp.gadget->dev, "setup complete: %d, %d/%d\n",
 
345
                req->status, req->actual, req->length);
 
346
}
 
347
 
 
348
static int dbgp_setup(struct usb_gadget *gadget,
 
349
                      const struct usb_ctrlrequest *ctrl)
 
350
{
 
351
        struct usb_request *req = dbgp.req;
 
352
        u8 request = ctrl->bRequest;
 
353
        u16 value = le16_to_cpu(ctrl->wValue);
 
354
        u16 length = le16_to_cpu(ctrl->wLength);
 
355
        int err = -EOPNOTSUPP;
 
356
        void *data = NULL;
 
357
        u16 len = 0;
 
358
 
 
359
        gadget->ep0->driver_data = gadget;
 
360
 
 
361
        if (request == USB_REQ_GET_DESCRIPTOR) {
 
362
                switch (value>>8) {
 
363
                case USB_DT_DEVICE:
 
364
                        dev_dbg(&dbgp.gadget->dev, "setup: desc device\n");
 
365
                        len = sizeof device_desc;
 
366
                        data = &device_desc;
 
367
                        device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
 
368
                        break;
 
369
                case USB_DT_DEBUG:
 
370
                        dev_dbg(&dbgp.gadget->dev, "setup: desc debug\n");
 
371
                        len = sizeof dbg_desc;
 
372
                        data = &dbg_desc;
 
373
                        break;
 
374
                default:
 
375
                        goto fail;
 
376
                }
 
377
                err = 0;
 
378
        } else if (request == USB_REQ_SET_FEATURE &&
 
379
                   value == USB_DEVICE_DEBUG_MODE) {
 
380
                dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n");
 
381
#ifdef CONFIG_USB_G_DBGP_PRINTK
 
382
                err = dbgp_enable_ep();
 
383
#else
 
384
                err = gserial_connect(dbgp.serial, 0);
 
385
#endif
 
386
                if (err < 0)
 
387
                        goto fail;
 
388
        } else
 
389
                goto fail;
 
390
 
 
391
        req->length = min(length, len);
 
392
        req->zero = len < req->length;
 
393
        if (data && req->length)
 
394
                memcpy(req->buf, data, req->length);
 
395
 
 
396
        req->complete = dbgp_setup_complete;
 
397
        return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
 
398
 
 
399
fail:
 
400
        dev_dbg(&dbgp.gadget->dev,
 
401
                "setup: failure req %x v %x\n", request, value);
 
402
        return err;
 
403
}
 
404
 
 
405
static struct usb_gadget_driver dbgp_driver = {
 
406
        .function = "dbgp",
 
407
        .speed = USB_SPEED_HIGH,
 
408
        .unbind = dbgp_unbind,
 
409
        .setup = dbgp_setup,
 
410
        .disconnect = dbgp_disconnect,
 
411
        .driver = {
 
412
                .owner = THIS_MODULE,
 
413
                .name = "dbgp"
 
414
        },
 
415
};
 
416
 
 
417
static int __init dbgp_init(void)
 
418
{
 
419
        return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind);
 
420
}
 
421
 
 
422
static void __exit dbgp_exit(void)
 
423
{
 
424
        usb_gadget_unregister_driver(&dbgp_driver);
 
425
#ifdef CONFIG_USB_G_DBGP_SERIAL
 
426
        gserial_cleanup();
 
427
#endif
 
428
}
 
429
 
 
430
MODULE_AUTHOR("Stephane Duverger");
 
431
MODULE_LICENSE("GPL");
 
432
module_init(dbgp_init);
 
433
module_exit(dbgp_exit);