drivers: power: report battery voltage in AOSP compatible format
[GitHub/mt8127/android_kernel_alcatel_ttab.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
13 /* #define VERBOSE_DEBUG */
14
15 #include <linux/slab.h>
16 #include <linux/kernel.h>
17 #include <linux/device.h>
18 #include <linux/module.h>
19 #include <linux/err.h>
20 #include <linux/usb/composite.h>
21
22 #include "g_zero.h"
23
24 /*
25 * LOOPBACK FUNCTION ... a testing vehicle for USB peripherals,
26 *
27 * This takes messages of various sizes written OUT to a device, and loops
28 * them back so they can be read IN from it. It has been used by certain
29 * test applications. It supports limited testing of data queueing logic.
30 *
31 *
32 * This is currently packaged as a configuration driver, which can't be
33 * combined with other functions to make composite devices. However, it
34 * can be combined with other independent configurations.
35 */
36 struct f_loopback {
37 struct usb_function function;
38
39 struct usb_ep *in_ep;
40 struct usb_ep *out_ep;
41 };
42
43 static inline struct f_loopback *func_to_loop(struct usb_function *f)
44 {
45 return container_of(f, struct f_loopback, function);
46 }
47
48 static unsigned qlen;
49 static unsigned buflen;
50
51 /*-------------------------------------------------------------------------*/
52
53 static struct usb_interface_descriptor loopback_intf = {
54 .bLength = sizeof loopback_intf,
55 .bDescriptorType = USB_DT_INTERFACE,
56
57 .bNumEndpoints = 2,
58 .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
59 /* .iInterface = DYNAMIC */
60 };
61
62 /* full speed support: */
63
64 static struct usb_endpoint_descriptor fs_loop_source_desc = {
65 .bLength = USB_DT_ENDPOINT_SIZE,
66 .bDescriptorType = USB_DT_ENDPOINT,
67
68 .bEndpointAddress = USB_DIR_IN,
69 .bmAttributes = USB_ENDPOINT_XFER_BULK,
70 };
71
72 static struct usb_endpoint_descriptor fs_loop_sink_desc = {
73 .bLength = USB_DT_ENDPOINT_SIZE,
74 .bDescriptorType = USB_DT_ENDPOINT,
75
76 .bEndpointAddress = USB_DIR_OUT,
77 .bmAttributes = USB_ENDPOINT_XFER_BULK,
78 };
79
80 static struct usb_descriptor_header *fs_loopback_descs[] = {
81 (struct usb_descriptor_header *) &loopback_intf,
82 (struct usb_descriptor_header *) &fs_loop_sink_desc,
83 (struct usb_descriptor_header *) &fs_loop_source_desc,
84 NULL,
85 };
86
87 /* high speed support: */
88
89 static struct usb_endpoint_descriptor hs_loop_source_desc = {
90 .bLength = USB_DT_ENDPOINT_SIZE,
91 .bDescriptorType = USB_DT_ENDPOINT,
92
93 .bmAttributes = USB_ENDPOINT_XFER_BULK,
94 .wMaxPacketSize = cpu_to_le16(512),
95 };
96
97 static struct usb_endpoint_descriptor hs_loop_sink_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_descriptor_header *hs_loopback_descs[] = {
106 (struct usb_descriptor_header *) &loopback_intf,
107 (struct usb_descriptor_header *) &hs_loop_source_desc,
108 (struct usb_descriptor_header *) &hs_loop_sink_desc,
109 NULL,
110 };
111
112 /* super speed support: */
113
114 static struct usb_endpoint_descriptor ss_loop_source_desc = {
115 .bLength = USB_DT_ENDPOINT_SIZE,
116 .bDescriptorType = USB_DT_ENDPOINT,
117
118 .bmAttributes = USB_ENDPOINT_XFER_BULK,
119 .wMaxPacketSize = cpu_to_le16(1024),
120 };
121
122 struct usb_ss_ep_comp_descriptor ss_loop_source_comp_desc = {
123 .bLength = USB_DT_SS_EP_COMP_SIZE,
124 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
125 .bMaxBurst = 0,
126 .bmAttributes = 0,
127 .wBytesPerInterval = 0,
128 };
129
130 static struct usb_endpoint_descriptor ss_loop_sink_desc = {
131 .bLength = USB_DT_ENDPOINT_SIZE,
132 .bDescriptorType = USB_DT_ENDPOINT,
133
134 .bmAttributes = USB_ENDPOINT_XFER_BULK,
135 .wMaxPacketSize = cpu_to_le16(1024),
136 };
137
138 struct usb_ss_ep_comp_descriptor ss_loop_sink_comp_desc = {
139 .bLength = USB_DT_SS_EP_COMP_SIZE,
140 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP,
141 .bMaxBurst = 0,
142 .bmAttributes = 0,
143 .wBytesPerInterval = 0,
144 };
145
146 static struct usb_descriptor_header *ss_loopback_descs[] = {
147 (struct usb_descriptor_header *) &loopback_intf,
148 (struct usb_descriptor_header *) &ss_loop_source_desc,
149 (struct usb_descriptor_header *) &ss_loop_source_comp_desc,
150 (struct usb_descriptor_header *) &ss_loop_sink_desc,
151 (struct usb_descriptor_header *) &ss_loop_sink_comp_desc,
152 NULL,
153 };
154
155 /* function-specific strings: */
156
157 static struct usb_string strings_loopback[] = {
158 [0].s = "loop input to output",
159 { } /* end of list */
160 };
161
162 static struct usb_gadget_strings stringtab_loop = {
163 .language = 0x0409, /* en-us */
164 .strings = strings_loopback,
165 };
166
167 static struct usb_gadget_strings *loopback_strings[] = {
168 &stringtab_loop,
169 NULL,
170 };
171
172 /*-------------------------------------------------------------------------*/
173
174 struct usb_request *alloc_ep_req(struct usb_ep *ep, int len)
175 {
176 struct usb_request *req;
177
178 req = usb_ep_alloc_request(ep, GFP_ATOMIC);
179 if (req) {
180 if (len)
181 req->length = len;
182 else
183 req->length = buflen;
184 req->buf = kmalloc(req->length, GFP_ATOMIC);
185 if (!req->buf) {
186 usb_ep_free_request(ep, req);
187 req = NULL;
188 }
189 }
190 return req;
191 }
192
193 void free_ep_req(struct usb_ep *ep, struct usb_request *req)
194 {
195 kfree(req->buf);
196 usb_ep_free_request(ep, req);
197 }
198
199 static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
200 {
201 int value;
202
203 if (ep->driver_data) {
204 value = usb_ep_disable(ep);
205 if (value < 0)
206 DBG(cdev, "disable %s --> %d\n",
207 ep->name, value);
208 ep->driver_data = NULL;
209 }
210 }
211
212 void disable_endpoints(struct usb_composite_dev *cdev,
213 struct usb_ep *in, struct usb_ep *out,
214 struct usb_ep *iso_in, struct usb_ep *iso_out)
215 {
216 disable_ep(cdev, in);
217 disable_ep(cdev, out);
218 if (iso_in)
219 disable_ep(cdev, iso_in);
220 if (iso_out)
221 disable_ep(cdev, iso_out);
222 }
223
224 static int loopback_bind(struct usb_configuration *c, struct usb_function *f)
225 {
226 struct usb_composite_dev *cdev = c->cdev;
227 struct f_loopback *loop = func_to_loop(f);
228 int id;
229 int ret;
230
231 /* allocate interface ID(s) */
232 id = usb_interface_id(c, f);
233 if (id < 0)
234 return id;
235 loopback_intf.bInterfaceNumber = id;
236
237 id = usb_string_id(cdev);
238 if (id < 0)
239 return id;
240 strings_loopback[0].id = id;
241 loopback_intf.iInterface = id;
242
243 /* allocate endpoints */
244
245 loop->in_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_source_desc);
246 if (!loop->in_ep) {
247 autoconf_fail:
248 ERROR(cdev, "%s: can't autoconfigure on %s\n",
249 f->name, cdev->gadget->name);
250 return -ENODEV;
251 }
252 loop->in_ep->driver_data = cdev; /* claim */
253
254 loop->out_ep = usb_ep_autoconfig(cdev->gadget, &fs_loop_sink_desc);
255 if (!loop->out_ep)
256 goto autoconf_fail;
257 loop->out_ep->driver_data = cdev; /* claim */
258
259 /* support high speed hardware */
260 hs_loop_source_desc.bEndpointAddress =
261 fs_loop_source_desc.bEndpointAddress;
262 hs_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
263
264 /* support super speed hardware */
265 ss_loop_source_desc.bEndpointAddress =
266 fs_loop_source_desc.bEndpointAddress;
267 ss_loop_sink_desc.bEndpointAddress = fs_loop_sink_desc.bEndpointAddress;
268
269 ret = usb_assign_descriptors(f, fs_loopback_descs, hs_loopback_descs,
270 ss_loopback_descs);
271 if (ret)
272 return ret;
273
274 DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
275 (gadget_is_superspeed(c->cdev->gadget) ? "super" :
276 (gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full")),
277 f->name, loop->in_ep->name, loop->out_ep->name);
278 return 0;
279 }
280
281 static void lb_free_func(struct usb_function *f)
282 {
283 usb_free_all_descriptors(f);
284 kfree(func_to_loop(f));
285 }
286
287 static void loopback_complete(struct usb_ep *ep, struct usb_request *req)
288 {
289 struct f_loopback *loop = ep->driver_data;
290 struct usb_composite_dev *cdev = loop->function.config->cdev;
291 int status = req->status;
292
293 switch (status) {
294
295 case 0: /* normal completion? */
296 if (ep == loop->out_ep) {
297 /* loop this OUT packet back IN to the host */
298 struct usb_request *in_req = req->context;
299 in_req->zero = (req->actual % ep->maxpacket == 0)?1:0;
300 in_req->length = req->actual;
301 in_req->actual = 0;
302
303 memcpy(in_req->buf, req->buf, req->length);
304
305 status = usb_ep_queue(loop->in_ep, in_req, GFP_ATOMIC);
306 if (status == 0)
307 return;
308
309 /* "should never get here" */
310 ERROR(cdev, "can't loop %s to %s: %d\n",
311 ep->name, loop->in_ep->name,
312 status);
313 }
314
315 if (ep == loop->in_ep) {
316 struct usb_request *out_req = req->context;
317 /* queue the buffer for some later OUT packet */
318 out_req->length = buflen;
319 status = usb_ep_queue(loop->out_ep, out_req, GFP_ATOMIC);
320 if (status == 0)
321 return;
322 }
323
324 /* "should never get here" */
325 /* FALLTHROUGH */
326
327 default:
328 ERROR(cdev, "%s loop complete --> %d, %d/%d\n", ep->name,
329 status, req->actual, req->length);
330 /* FALLTHROUGH */
331
332 /* NOTE: since this driver doesn't maintain an explicit record
333 * of requests it submitted (just maintains qlen count), we
334 * rely on the hardware driver to clean up on disconnect or
335 * endpoint disable.
336 */
337 case -ECONNABORTED: /* hardware forced ep reset */
338 case -ECONNRESET: /* request dequeued */
339 case -ESHUTDOWN: /* disconnect from host */
340 free_ep_req(ep, req);
341 return;
342 }
343 }
344
345 static void disable_loopback(struct f_loopback *loop)
346 {
347 struct usb_composite_dev *cdev;
348
349 cdev = loop->function.config->cdev;
350 disable_endpoints(cdev, loop->in_ep, loop->out_ep, NULL, NULL);
351 VDBG(cdev, "%s disabled\n", loop->function.name);
352 }
353
354 static int
355 enable_loopback(struct usb_composite_dev *cdev, struct f_loopback *loop)
356 {
357 int result = 0;
358 struct usb_ep *ep;
359 unsigned i;
360
361 /* one endpoint writes data back IN to the host */
362 ep = loop->in_ep;
363 result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
364 if (result)
365 return result;
366 result = usb_ep_enable(ep);
367 if (result < 0)
368 return result;
369 ep->driver_data = loop;
370
371 /* one endpoint just reads OUT packets */
372 ep = loop->out_ep;
373 result = config_ep_by_speed(cdev->gadget, &(loop->function), ep);
374 if (result)
375 goto fail0;
376
377 result = usb_ep_enable(ep);
378 if (result < 0) {
379 fail0:
380 ep = loop->in_ep;
381 usb_ep_disable(ep);
382 ep->driver_data = NULL;
383 return result;
384 }
385 ep->driver_data = loop;
386
387 /* allocate a bunch of read buffers and queue them all at once.
388 * we buffer at most 'qlen' transfers; fewer if any need more
389 * than 'buflen' bytes each.
390 */
391 for (i = 0; i < qlen && result == 0; i++) {
392 struct usb_request *out_req;
393 struct usb_request *in_req;
394 out_req = alloc_ep_req(loop->out_ep, 0);
395 if (out_req) {
396 out_req->complete = loopback_complete;
397 result = usb_ep_queue(loop->out_ep, out_req, GFP_ATOMIC);
398 if (result)
399 ERROR(cdev, "%s queue req --> %d\n",
400 loop->out_ep->name, result);
401 } else {
402 usb_ep_disable(loop->out_ep);
403 loop->out_ep->driver_data = NULL;
404 result = -ENOMEM;
405 goto fail0;
406 }
407 in_req = alloc_ep_req(loop->in_ep, 0);
408 if (in_req) {
409 in_req->complete = loopback_complete;
410 } else {
411 usb_ep_disable(loop->in_ep);
412 loop->in_ep->driver_data = NULL;
413 result = -ENOMEM;
414 goto fail0;
415 }
416 in_req->context = out_req;
417 out_req->context = in_req;
418 }
419
420 DBG(cdev, "%s enabled\n", loop->function.name);
421 return result;
422 }
423
424 static int loopback_set_alt(struct usb_function *f,
425 unsigned intf, unsigned alt)
426 {
427 struct f_loopback *loop = func_to_loop(f);
428 struct usb_composite_dev *cdev = f->config->cdev;
429
430 /* we know alt is zero */
431 if (loop->in_ep->driver_data)
432 disable_loopback(loop);
433 return enable_loopback(cdev, loop);
434 }
435
436 static void loopback_disable(struct usb_function *f)
437 {
438 struct f_loopback *loop = func_to_loop(f);
439
440 disable_loopback(loop);
441 }
442
443 static struct usb_function *loopback_alloc(struct usb_function_instance *fi)
444 {
445 struct f_loopback *loop;
446 struct f_lb_opts *lb_opts;
447
448 loop = kzalloc(sizeof *loop, GFP_KERNEL);
449 if (!loop)
450 return ERR_PTR(-ENOMEM);
451
452 lb_opts = container_of(fi, struct f_lb_opts, func_inst);
453 buflen = lb_opts->bulk_buflen;
454 if (!buflen)
455 buflen = 512;
456
457 qlen = lb_opts->qlen;
458 if (!qlen)
459 qlen = 8;
460
461 loop->function.name = "loopback";
462 loop->function.bind = loopback_bind;
463 loop->function.set_alt = loopback_set_alt;
464 loop->function.disable = loopback_disable;
465 loop->function.strings = loopback_strings;
466
467 loop->function.free_func = lb_free_func;
468
469 return &loop->function;
470 }
471
472 static void lb_free_instance(struct usb_function_instance *fi)
473 {
474 struct f_lb_opts *lb_opts;
475
476 lb_opts = container_of(fi, struct f_lb_opts, func_inst);
477 kfree(lb_opts);
478 }
479
480 static struct usb_function_instance *loopback_alloc_instance(void)
481 {
482 struct f_lb_opts *lb_opts;
483
484 lb_opts = kzalloc(sizeof(*lb_opts), GFP_KERNEL);
485 if (!lb_opts)
486 return ERR_PTR(-ENOMEM);
487 lb_opts->func_inst.free_func_inst = lb_free_instance;
488 return &lb_opts->func_inst;
489 }
490 DECLARE_USB_FUNCTION_INIT(loopback, loopback_alloc_instance, loopback_alloc);
491
492 #if 0
493 int __init lb_modinit(void)
494 {
495 int ret;
496
497 ret = usb_function_register(&Loopbackusb_func);
498 if (ret)
499 return ret;
500 return ret;
501 }
502 void __exit lb_modexit(void)
503 {
504 usb_function_unregister(&Loopbackusb_func);
505 }
506 #endif
507 MODULE_LICENSE("GPL");