Merge branch 'drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied...
[cascardo/linux.git] / drivers / usb / gadget / f_loopback.c
1 /*
2  * f_loopback.c - USB peripheral loopback configuration driver
3  *
4  * Copyright (C) 2003-2008 David Brownell
5  * Copyright (C) 2008 by Nokia Corporation
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 /* #define VERBOSE_DEBUG */
23
24 #include <linux/kernel.h>
25 #include <linux/device.h>
26
27 #include "g_zero.h"
28 #include "gadget_chips.h"
29
30
31 /*
32  * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
33  *
34  * This takes messages of various sizes written OUT to a device, and loops
35  * them back so they can be read IN from it.  It has been used by certain
36  * test applications.  It supports limited testing of data queueing logic.
37  *
38  *
39  * This is currently packaged as a configuration driver, which can't be
40  * combined with other functions to make composite devices.  However, it
41  * can be combined with other independent configurations.
42  */
43 struct f_loopback {
44         struct usb_function     function;
45
46         struct usb_ep           *in_ep;
47         struct usb_ep           *out_ep;
48 };
49
50 static inline struct f_loopback *func_to_loop(struct usb_function *f)
51 {
52         return container_of(f, struct f_loopback, function);
53 }
54
55 static unsigned qlen = 32;
56 module_param(qlen, uint, 0);
57 MODULE_PARM_DESC(qlenn, "depth of loopback queue");
58
59 /*-------------------------------------------------------------------------*/
60
61 static struct usb_interface_descriptor loopback_intf = {
62         .bLength =              sizeof loopback_intf,
63         .bDescriptorType =      USB_DT_INTERFACE,
64
65         .bNumEndpoints =        2,
66         .bInterfaceClass =      USB_CLASS_VENDOR_SPEC,
67         /* .iInterface = DYNAMIC */
68 };
69
70 /* full speed support: */
71
72 static struct usb_endpoint_descriptor fs_loop_source_desc = {
73         .bLength =              USB_DT_ENDPOINT_SIZE,
74         .bDescriptorType =      USB_DT_ENDPOINT,
75
76         .bEndpointAddress =     USB_DIR_IN,
77         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
78 };
79
80 static struct usb_endpoint_descriptor fs_loop_sink_desc = {
81         .bLength =              USB_DT_ENDPOINT_SIZE,
82         .bDescriptorType =      USB_DT_ENDPOINT,
83
84         .bEndpointAddress =     USB_DIR_OUT,
85         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
86 };
87
88 static struct usb_descriptor_header *fs_loopback_descs[] = {
89         (struct usb_descriptor_header *) &loopback_intf,
90         (struct usb_descriptor_header *) &fs_loop_sink_desc,
91         (struct usb_descriptor_header *) &fs_loop_source_desc,
92         NULL,
93 };
94
95 /* high speed support: */
96
97 static struct usb_endpoint_descriptor hs_loop_source_desc = {
98         .bLength =              USB_DT_ENDPOINT_SIZE,
99         .bDescriptorType =      USB_DT_ENDPOINT,
100
101         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
102         .wMaxPacketSize =       cpu_to_le16(512),
103 };
104
105 static struct usb_endpoint_descriptor hs_loop_sink_desc = {
106         .bLength =              USB_DT_ENDPOINT_SIZE,
107         .bDescriptorType =      USB_DT_ENDPOINT,
108
109         .bmAttributes =         USB_ENDPOINT_XFER_BULK,
110         .wMaxPacketSize =       cpu_to_le16(512),
111 };
112
113 static struct usb_descriptor_header *hs_loopback_descs[] = {
114         (struct usb_descriptor_header *) &loopback_intf,
115         (struct usb_descriptor_header *) &hs_loop_source_desc,
116         (struct usb_descriptor_header *) &hs_loop_sink_desc,
117         NULL,
118 };
119
120 /* function-specific strings: */
121
122 static struct usb_string strings_loopback[] = {
123         [0].s = "loop input to output",
124         {  }                    /* end of list */
125 };
126
127 static struct usb_gadget_strings stringtab_loop = {
128         .language       = 0x0409,       /* en-us */
129         .strings        = strings_loopback,
130 };
131
132 static struct usb_gadget_strings *loopback_strings[] = {
133         &stringtab_loop,
134         NULL,
135 };
136
137 /*-------------------------------------------------------------------------*/
138
139 static int __init
140 loopback_bind(struct usb_configuration *c, struct usb_function *f)
141 {
142         struct usb_composite_dev *cdev = c->cdev;
143         struct f_loopback       *loop = func_to_loop(f);
144         int                     id;
145
146         /* allocate interface ID(s) */
147         id = usb_interface_id(c, f);
148         if (id < 0)
149                 return id;
150         loopback_intf.bInterfaceNumber = id;
151
152         /* allocate endpoints */
153
154         loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
155         if (!loop->in_ep) {
156 autoconf_fail:
157                 ERROR(cdev, "%s: can't autoconfigure on %s\n",
158                         f->name, cdev->gadget->name);
159                 return -ENODEV;
160         }
161         loop->in_ep->driver_data = cdev;        /* claim */
162
163         loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
164         if (!loop->out_ep)
165                 goto autoconf_fail;
166         loop->out_ep->driver_data = cdev;       /* claim */
167
168         /* support high speed hardware */
169         if (gadget_is_dualspeed(c->cdev->gadget)) {
170                 hs_loop_source_desc.bEndpointAddress =
171                                 fs_loop_source_desc.bEndpointAddress;
172                 hs_loop_sink_desc.bEndpointAddress =
173                                 fs_loop_sink_desc.bEndpointAddress;
174                 f->hs_descriptors = hs_loopback_descs;
175         }
176
177         DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
178                         gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full",
179                         f->name, loop->in_ep->name, loop->out_ep->name);
180         return 0;
181 }
182
183 static void
184 loopback_unbind(struct usb_configuration *c, struct usb_function *f)
185 {
186         kfree(func_to_loop(f));
187 }
188
189 static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
190 {
191         struct f_loopback       *loop = ep->driver_data;
192         struct usb_composite_dev *cdev = loop->function.config->cdev;
193         int                     status = req->status;
194
195         switch (status) {
196
197         case 0:                         /* normal completion? */
198                 if (ep == loop->out_ep) {
199                         /* loop this OUT packet back IN to the host */
200                         req->zero = (req->actual < req->length);
201                         req->length = req->actual;
202                         status = usb_ep_queue(loop->in_ep, req, GFP_ATOMIC);
203                         if (status == 0)
204                                 return;
205
206                         /* "should never get here" */
207                         ERROR(cdev, "can't loop %s to %s: %d\n",
208                                 ep->name, loop->in_ep->name,
209                                 status);
210                 }
211
212                 /* queue the buffer for some later OUT packet */
213                 req->length = buflen;
214                 status = usb_ep_queue(loop->out_ep, req, GFP_ATOMIC);
215                 if (status == 0)
216                         return;
217
218                 /* "should never get here" */
219                 /* FALLTHROUGH */
220
221         default:
222                 ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
223                                 status, req->actual, req->length);
224                 /* FALLTHROUGH */
225
226         /* NOTE:  since this driver doesn't maintain an explicit record
227          * of requests it submitted (just maintains qlen count), we
228          * rely on the hardware driver to clean up on disconnect or
229          * endpoint disable.
230          */
231         case -ECONNABORTED:             /* hardware forced ep reset */
232         case -ECONNRESET:               /* request dequeued */
233         case -ESHUTDOWN:                /* disconnect from host */
234                 free_ep_req(ep, req);
235                 return;
236         }
237 }
238
239 static void disable_loopback(struct f_loopback *loop)
240 {
241         struct usb_composite_dev        *cdev;
242
243         cdev = loop->function.config->cdev;
244         disable_endpoints(cdev, loop->in_ep, loop->out_ep);
245         VDBG(cdev, "%s disabled\n", loop->function.name);
246 }
247
248 static int
249 enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
250 {
251         int                                     result = 0;
252         const struct usb_endpoint_descriptor    *src, *sink;
253         struct usb_ep                           *ep;
254         struct usb_request                      *req;
255         unsigned                                i;
256
257         src = ep_choose(cdev->gadget,
258                         &hs_loop_source_desc, &fs_loop_source_desc);
259         sink = ep_choose(cdev->gadget,
260                         &hs_loop_sink_desc, &fs_loop_sink_desc);
261
262         /* one endpoint writes data back IN to the host */
263         ep = loop->in_ep;
264         result = usb_ep_enable(ep, src);
265         if (result < 0)
266                 return result;
267         ep->driver_data = loop;
268
269         /* one endpoint just reads OUT packets */
270         ep = loop->out_ep;
271         result = usb_ep_enable(ep, sink);
272         if (result < 0) {
273 fail0:
274                 ep = loop->in_ep;
275                 usb_ep_disable(ep);
276                 ep->driver_data = NULL;
277                 return result;
278         }
279         ep->driver_data = loop;
280
281         /* allocate a bunch of read buffers and queue them all at once.
282          * we buffer at most 'qlen' transfers; fewer if any need more
283          * than 'buflen' bytes each.
284          */
285         for (i = 0; i < qlen && result == 0; i++) {
286                 req = alloc_ep_req(ep);
287                 if (req) {
288                         req->complete = loopback_complete;
289                         result = usb_ep_queue(ep, req, GFP_ATOMIC);
290                         if (result)
291                                 ERROR(cdev, "%s queue req --> %d\n",
292                                                 ep->name, result);
293                 } else {
294                         usb_ep_disable(ep);
295                         ep->driver_data = NULL;
296                         result = -ENOMEM;
297                         goto fail0;
298                 }
299         }
300
301         DBG(cdev, "%s enabled\n", loop->function.name);
302         return result;
303 }
304
305 static int loopback_set_alt(struct usb_function *f,
306                 unsigned intf, unsigned alt)
307 {
308         struct f_loopback       *loop = func_to_loop(f);
309         struct usb_composite_dev *cdev = f->config->cdev;
310
311         /* we know alt is zero */
312         if (loop->in_ep->driver_data)
313                 disable_loopback(loop);
314         return enable_loopback(cdev, loop);
315 }
316
317 static void loopback_disable(struct usb_function *f)
318 {
319         struct f_loopback       *loop = func_to_loop(f);
320
321         disable_loopback(loop);
322 }
323
324 /*-------------------------------------------------------------------------*/
325
326 static int __init loopback_bind_config(struct usb_configuration *c)
327 {
328         struct f_loopback       *loop;
329         int                     status;
330
331         loop = kzalloc(sizeof *loop, GFP_KERNEL);
332         if (!loop)
333                 return -ENOMEM;
334
335         loop->function.name = "loopback";
336         loop->function.descriptors = fs_loopback_descs;
337         loop->function.bind = loopback_bind;
338         loop->function.unbind = loopback_unbind;
339         loop->function.set_alt = loopback_set_alt;
340         loop->function.disable = loopback_disable;
341
342         status = usb_add_function(c, &loop->function);
343         if (status)
344                 kfree(loop);
345         return status;
346 }
347
348 static struct usb_configuration loopback_driver = {
349         .label          = "loopback",
350         .strings        = loopback_strings,
351         .bind           = loopback_bind_config,
352         .bConfigurationValue = 2,
353         .bmAttributes   = USB_CONFIG_ATT_SELFPOWER,
354         /* .iConfiguration = DYNAMIC */
355 };
356
357 /**
358  * loopback_add - add a loopback testing configuration to a device
359  * @cdev: the device to support the loopback configuration
360  */
361 int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume)
362 {
363         int id;
364
365         /* allocate string ID(s) */
366         id = usb_string_id(cdev);
367         if (id < 0)
368                 return id;
369         strings_loopback[0].id = id;
370
371         loopback_intf.iInterface = id;
372         loopback_driver.iConfiguration = id;
373
374         /* support autoresume for remote wakeup testing */
375         if (autoresume)
376                 sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
377
378         /* support OTG systems */
379         if (gadget_is_otg(cdev->gadget)) {
380                 loopback_driver.descriptors = otg_desc;
381                 loopback_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP;
382         }
383
384         return usb_add_config(cdev, &loopback_driver);
385 }