Annotation of sys/dev/usb/usbf_subr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: usbf_subr.c,v 1.10 2007/07/27 09:16:09 mbalmer Exp $ */
2:
3: /*
4: * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org>
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice and this permission notice appear in all copies.
9: *
10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17: */
18:
19: /*
20: * USB function driver interface subroutines
21: */
22:
23: #include <sys/param.h>
24: #include <sys/malloc.h>
25: #include <sys/systm.h>
26: #include <sys/timeout.h>
27:
28: #include <machine/bus.h>
29:
30: #include <dev/usb/usb.h>
31: #include <dev/usb/usbdi.h>
32: #include <dev/usb/usbdivar.h>
33: #include <dev/usb/usb_mem.h>
34: #include <dev/usb/usbf.h>
35: #include <dev/usb/usbfvar.h>
36:
37: #ifndef USBF_DEBUG
38: #define DPRINTF(l, x) do {} while (0)
39: #else
40: extern int usbfdebug;
41: #define DPRINTF(l, x) if ((l) <= usbfdebug) printf x; else {}
42: #endif
43:
44: void *usbf_realloc(void **, size_t *, size_t);
45: size_t usbf_get_string(usbf_device_handle, u_int8_t, char *, size_t);
46: usbf_status usbf_open_pipe_ival(usbf_interface_handle, u_int8_t,
47: usbf_pipe_handle *, int);
48: usbf_status usbf_setup_pipe(usbf_device_handle, usbf_interface_handle,
49: struct usbf_endpoint *, int,
50: usbf_pipe_handle *);
51: void usbf_start_next(usbf_pipe_handle);
52: void usbf_set_endpoint_halt(usbf_endpoint_handle);
53: void usbf_clear_endpoint_halt(usbf_endpoint_handle);
54:
55: static const char * const usbf_error_strs[] = USBF_ERROR_STRS;
56:
57: const char *
58: usbf_errstr(usbf_status err)
59: {
60: static char buffer[5];
61:
62: if (err < USBF_ERROR_MAX)
63: return usbf_error_strs[err];
64:
65: snprintf(buffer, sizeof buffer, "%d", err);
66: return buffer;
67: }
68:
69: void *
70: usbf_realloc(void **pp, size_t *sizep, size_t newsize)
71: {
72: void *p;
73: size_t oldsize;
74:
75: if (newsize == 0) {
76: if (*sizep > 0)
77: free(*pp, M_USB);
78: *pp = NULL;
79: *sizep = 0;
80: return NULL;
81: }
82:
83: p = malloc(newsize, M_USB, M_NOWAIT);
84: if (p == NULL)
85: return NULL;
86:
87: oldsize = MIN(*sizep, newsize);
88: if (oldsize > 0)
89: bcopy(*pp, p, oldsize);
90: *pp = p;
91: *sizep = newsize;
92: return p;
93: }
94:
95: /*
96: * Attach a function driver.
97: */
98: static usbf_status
99: usbf_probe_and_attach(struct device *parent, usbf_device_handle dev, int port)
100: {
101: struct usbf_attach_arg uaa;
102: struct device *dv;
103:
104: KASSERT(dev->function == NULL);
105:
106: bzero(&uaa, sizeof uaa);
107: uaa.device = dev;
108:
109: /*
110: * The softc structure of a USB function driver must begin with a
111: * "struct usbf_function" member (instead of USBBASEDEV), which must
112: * be initialized in the function driver's attach routine. Also, it
113: * should use usbf_devinfo_setup() to set the device identification.
114: */
115: dv = config_found_sm(parent, &uaa, NULL, NULL);
116: if (dv != NULL) {
117: dev->function = (struct usbf_function *)dv;
118: return USBF_NORMAL_COMPLETION;
119: }
120:
121: /*
122: * We failed to attach a function driver for this device, but the
123: * device can still function as a generic USB device without any
124: * interfaces.
125: */
126: return USBF_NORMAL_COMPLETION;
127: }
128:
129: static void
130: usbf_remove_device(usbf_device_handle dev, struct usbf_port *up)
131: {
132: KASSERT(dev != NULL && dev == up->device);
133:
134: if (dev->function != NULL)
135: config_detach((struct device *)dev->function, DETACH_FORCE);
136: if (dev->default_pipe != NULL)
137: usbf_close_pipe(dev->default_pipe);
138: up->device = NULL;
139: free(dev, M_USB);
140: }
141:
142: usbf_status
143: usbf_new_device(struct device *parent, usbf_bus_handle bus, int depth,
144: int speed, int port, struct usbf_port *up)
145: {
146: struct usbf_device *dev;
147: usb_device_descriptor_t *ud;
148: usbf_status err;
149:
150: #ifdef DIAGNOSTIC
151: KASSERT(up->device == NULL);
152: #endif
153:
154: dev = malloc(sizeof(*dev), M_USB, M_NOWAIT);
155: if (dev == NULL)
156: return USBF_NOMEM;
157:
158: bzero(dev, sizeof *dev);
159: dev->bus = bus;
160: dev->string_id = USBF_STRING_ID_MIN;
161: SIMPLEQ_INIT(&dev->configs);
162:
163: /* Initialize device status. */
164: USETW(dev->status.wStatus, UDS_SELF_POWERED);
165:
166: /*
167: * Initialize device descriptor. The function driver for this
168: * device (attached below) must complete the device descriptor.
169: */
170: ud = &dev->ddesc;
171: ud->bLength = USB_DEVICE_DESCRIPTOR_SIZE;
172: ud->bDescriptorType = UDESC_DEVICE;
173: ud->bMaxPacketSize = bus->ep0_maxp;
174: if (bus->usbrev >= USBREV_2_0)
175: USETW(ud->bcdUSB, UD_USB_2_0);
176: else
177: USETW(ud->bcdUSB, 0x0101);
178:
179: /* Set up the default endpoint handle and descriptor. */
180: dev->def_ep.edesc = &dev->def_ep_desc;
181: dev->def_ep_desc.bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
182: dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
183: dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
184: dev->def_ep_desc.bmAttributes = UE_CONTROL;
185: USETW(dev->def_ep_desc.wMaxPacketSize, ud->bMaxPacketSize);
186: dev->def_ep_desc.bInterval = 0;
187:
188: /* Establish the default pipe. */
189: err = usbf_setup_pipe(dev, NULL, &dev->def_ep, 0,
190: &dev->default_pipe);
191: if (err) {
192: free(dev, M_USB);
193: return err;
194: }
195:
196: /* Preallocate xfers for default pipe. */
197: dev->default_xfer = usbf_alloc_xfer(dev);
198: dev->data_xfer = usbf_alloc_xfer(dev);
199: if (dev->default_xfer == NULL || dev->data_xfer == NULL) {
200: if (dev->default_xfer != NULL)
201: usbf_free_xfer(dev->default_xfer);
202: usbf_close_pipe(dev->default_pipe);
203: free(dev, M_USB);
204: return USBF_NOMEM;
205: }
206:
207: /* Insert device request xfer. */
208: usbf_setup_default_xfer(dev->default_xfer, dev->default_pipe,
209: NULL, &dev->def_req, 0, 0, usbf_do_request);
210: err = usbf_transfer(dev->default_xfer);
211: if (err && err != USBF_IN_PROGRESS) {
212: usbf_free_xfer(dev->default_xfer);
213: usbf_free_xfer(dev->data_xfer);
214: usbf_close_pipe(dev->default_pipe);
215: free(dev, M_USB);
216: return err;
217: }
218:
219: /* Associate the upstream port with the device. */
220: bzero(up, sizeof *up);
221: up->portno = port;
222: up->device = dev;
223:
224: /* Attach function driver. */
225: err = usbf_probe_and_attach(parent, dev, port);
226: if (err)
227: usbf_remove_device(dev, up);
228: return err;
229: }
230:
231: /*
232: * Should be called by the function driver in its attach routine to change
233: * the default device identification according to the particular function.
234: */
235: void
236: usbf_devinfo_setup(usbf_device_handle dev, u_int8_t devclass,
237: u_int8_t subclass, u_int8_t proto, u_int16_t vendor, u_int16_t product,
238: u_int16_t device, const char *manf, const char *prod, const char *ser)
239: {
240: usb_device_descriptor_t *dd;
241:
242: dd = usbf_device_descriptor(dev);
243: dd->bDeviceClass = devclass;
244: dd->bDeviceSubClass = subclass;
245: dd->bDeviceProtocol = proto;
246: if (vendor != 0)
247: USETW(dd->idVendor, vendor);
248: if (product != 0)
249: USETW(dd->idProduct, product);
250: if (device != 0)
251: USETW(dd->bcdDevice, device);
252: if (manf != NULL)
253: dd->iManufacturer = usbf_add_string(dev, manf);
254: if (prod != NULL)
255: dd->iProduct = usbf_add_string(dev, prod);
256: if (ser != NULL)
257: dd->iSerialNumber = usbf_add_string(dev, ser);
258: }
259:
260: char *
261: usbf_devinfo_alloc(usbf_device_handle dev)
262: {
263: char manf[40];
264: char prod[40];
265: usb_device_descriptor_t *dd;
266: size_t len;
267: char *devinfo;
268:
269: dd = usbf_device_descriptor(dev);
270: usbf_get_string(dev, dd->iManufacturer, manf, sizeof manf);
271: usbf_get_string(dev, dd->iProduct, prod, sizeof prod);
272:
273: len = strlen(manf) + strlen(prod) + 32;
274: devinfo = malloc(len, M_USB, M_NOWAIT);
275: if (devinfo == NULL)
276: return NULL;
277:
278: snprintf(devinfo, len, "%s %s, rev %d.%02d/%d.%02d", manf, prod,
279: (UGETW(dd->bcdUSB)>>8) & 0xff, UGETW(dd->bcdUSB) & 0xff,
280: (UGETW(dd->bcdDevice)>>8) & 0xff, UGETW(dd->bcdDevice) & 0xff);
281: return devinfo;
282: }
283:
284: void
285: usbf_devinfo_free(char *devinfo)
286: {
287: if (devinfo != NULL)
288: free(devinfo, M_USB);
289: }
290:
291: /*
292: * Add a string descriptor to a logical device and return the string's id.
293: *
294: * If there is not enough memory available for the new string descriptor, or
295: * if there is no unused string id left, return the id of the empty string
296: * instead of failing.
297: */
298: u_int8_t
299: usbf_add_string(usbf_device_handle dev, const char *string)
300: {
301: usb_string_descriptor_t *sd;
302: size_t oldsize;
303: size_t newsize;
304: size_t len, i;
305: u_int8_t id;
306:
307: if (string == NULL || *string == '\0' ||
308: dev->string_id == USBF_STRING_ID_MAX)
309: return USBF_EMPTY_STRING_ID;
310:
311: if ((len = strlen(string)) >= USB_MAX_STRING_LEN)
312: len = USB_MAX_STRING_LEN - 1;
313:
314: oldsize = dev->sdesc_size;
315: newsize = oldsize + 2 + 2 * len;
316:
317: sd = usbf_realloc((void **)&dev->sdesc, &dev->sdesc_size,
318: newsize);
319: if (sd == NULL)
320: return USBF_EMPTY_STRING_ID;
321:
322: sd = (usb_string_descriptor_t *)((char *)sd + oldsize);
323: sd->bLength = newsize - oldsize;
324: sd->bDescriptorType = UDESC_STRING;
325: for (i = 0; string[i] != '\0' && i < len; i++)
326: USETW(sd->bString[i], string[i]);
327:
328: id = dev->string_id++;
329: return id;
330: }
331:
332: usb_string_descriptor_t *
333: usbf_string_descriptor(usbf_device_handle dev, u_int8_t id)
334: {
335: static usb_string_descriptor_t sd0;
336: static usb_string_descriptor_t sd1;
337: usb_string_descriptor_t *sd;
338:
339: /* handle the special string ids */
340: switch (id) {
341: case USB_LANGUAGE_TABLE:
342: sd0.bLength = 4;
343: sd0.bDescriptorType = UDESC_STRING;
344: USETW(sd0.bString[0], 0x0409 /* en_US */);
345: return &sd0;
346:
347: case USBF_EMPTY_STRING_ID:
348: sd1.bLength = 2;
349: sd1.bDescriptorType = UDESC_STRING;
350: return &sd0;
351: }
352:
353: /* check if the string id is valid */
354: if (id > dev->string_id)
355: return NULL;
356:
357: /* seek and return the descriptor of a non-empty string */
358: id -= USBF_STRING_ID_MIN;
359: sd = dev->sdesc;
360: while (id-- > 0)
361: sd = (usb_string_descriptor_t *)((char *)sd + sd->bLength);
362: return sd;
363: }
364:
365: size_t
366: usbf_get_string(usbf_device_handle dev, u_int8_t id, char *s, size_t size)
367: {
368: usb_string_descriptor_t *sd = NULL;
369: size_t i, len;
370:
371: if (id != USB_LANGUAGE_TABLE)
372: sd = usbf_string_descriptor(dev, id);
373:
374: if (sd == NULL) {
375: if (size > 0)
376: *s = '\0';
377: return 0;
378: }
379:
380: len = (sd->bLength - 2) / 2;
381: if (size < 1)
382: return len;
383:
384: for (i = 0; i < (size - 1) && i < len; i++)
385: s[i] = UGETW(sd->bString[i]) & 0xff;
386: s[i] = '\0';
387: return len;
388: }
389:
390: /*
391: * Add a new device configuration to an existing USB logical device.
392: * The new configuration initially has zero interfaces.
393: */
394: usbf_status
395: usbf_add_config(usbf_device_handle dev, usbf_config_handle *ucp)
396: {
397: struct usbf_config *uc;
398: usb_config_descriptor_t *cd;
399:
400: uc = malloc(sizeof *uc, M_USB, M_NOWAIT);
401: if (uc == NULL)
402: return USBF_NOMEM;
403:
404: cd = malloc(sizeof *cd, M_USB, M_NOWAIT);
405: if (cd == NULL) {
406: free(uc, M_USB);
407: return USBF_NOMEM;
408: }
409:
410: bzero(uc, sizeof *uc);
411: uc->uc_device = dev;
412: uc->uc_cdesc = cd;
413: uc->uc_cdesc_size = sizeof *cd;
414: SIMPLEQ_INIT(&uc->iface_head);
415:
416: bzero(cd, sizeof *cd);
417: cd->bLength = USB_CONFIG_DESCRIPTOR_SIZE;
418: cd->bDescriptorType = UDESC_CONFIG;
419: USETW(cd->wTotalLength, USB_CONFIG_DESCRIPTOR_SIZE);
420: cd->bConfigurationValue = USB_UNCONFIG_NO + 1 +
421: dev->ddesc.bNumConfigurations;
422: cd->iConfiguration = 0;
423: cd->bmAttributes = UC_BUS_POWERED | UC_SELF_POWERED;
424: #if 0
425: cd->bMaxPower = 100 / UC_POWER_FACTOR; /* 100 mA */
426: #else
427: cd->bMaxPower = 0; /* XXX 0 mA */
428: #endif
429:
430: SIMPLEQ_INSERT_TAIL(&dev->configs, uc, next);
431: dev->ddesc.bNumConfigurations++;
432:
433: if (ucp != NULL)
434: *ucp = uc;
435: return USBF_NORMAL_COMPLETION;
436: }
437:
438: /*
439: * Allocate memory for a new descriptor at the end of the existing
440: * device configuration descriptor.
441: */
442: usbf_status
443: usbf_add_config_desc(usbf_config_handle uc, usb_descriptor_t *d,
444: usb_descriptor_t **dp)
445: {
446: usb_config_descriptor_t *cd;
447: size_t oldsize;
448: size_t newsize;
449:
450: oldsize = uc->uc_cdesc_size;
451: newsize = oldsize + d->bLength;
452: if (d->bLength < sizeof(usb_descriptor_t) || newsize > 65535)
453: return USBF_INVAL;
454:
455: cd = usbf_realloc((void **)&uc->uc_cdesc, &uc->uc_cdesc_size,
456: newsize);
457: if (cd == NULL)
458: return USBF_NOMEM;
459:
460: bcopy(d, (char *)cd + oldsize, d->bLength);
461: USETW(cd->wTotalLength, newsize);
462: if (dp != NULL)
463: *dp = (usb_descriptor_t *)((char *)cd + oldsize);
464: return USBF_NORMAL_COMPLETION;
465: }
466:
467: usbf_status
468: usbf_add_interface(usbf_config_handle uc, u_int8_t bInterfaceClass,
469: u_int8_t bInterfaceSubClass, u_int8_t bInterfaceProtocol,
470: const char *string, usbf_interface_handle *uip)
471: {
472: struct usbf_interface *ui;
473: usb_interface_descriptor_t *id;
474:
475: if (uc->uc_closed)
476: return USBF_INVAL;
477:
478: ui = malloc(sizeof *ui, M_USB, M_NOWAIT);
479: if (ui == NULL)
480: return USBF_NOMEM;
481:
482: id = malloc(sizeof *id, M_USB, M_NOWAIT);
483: if (id == NULL) {
484: free(ui, M_USB);
485: return USBF_NOMEM;
486: }
487:
488: bzero(ui, sizeof *ui);
489: ui->config = uc;
490: ui->idesc = id;
491: LIST_INIT(&ui->pipes);
492: SIMPLEQ_INIT(&ui->endpoint_head);
493:
494: bzero(id, sizeof *id);
495: id->bLength = USB_INTERFACE_DESCRIPTOR_SIZE;
496: id->bDescriptorType = UDESC_INTERFACE;
497: id->bInterfaceNumber = uc->uc_cdesc->bNumInterface;
498: id->bInterfaceClass = bInterfaceClass;
499: id->bInterfaceSubClass = bInterfaceSubClass;
500: id->bInterfaceProtocol = bInterfaceProtocol;
501: id->iInterface = 0; /*usbf_add_string(uc->uc_device, string);*/ /* XXX */
502:
503: SIMPLEQ_INSERT_TAIL(&uc->iface_head, ui, next);
504: uc->uc_cdesc->bNumInterface++;
505:
506: *uip = ui;
507: return USBF_NORMAL_COMPLETION;
508: }
509:
510: usbf_status
511: usbf_add_endpoint(usbf_interface_handle ui, u_int8_t bEndpointAddress,
512: u_int8_t bmAttributes, u_int16_t wMaxPacketSize, u_int8_t bInterval,
513: usbf_endpoint_handle *uep)
514: {
515: struct usbf_endpoint *ue;
516: usb_endpoint_descriptor_t *ed;
517:
518: if (ui->config->uc_closed)
519: return USBF_INVAL;
520:
521: ue = malloc(sizeof *ue, M_USB, M_NOWAIT);
522: if (ue == NULL)
523: return USBF_NOMEM;
524:
525: ed = malloc(sizeof *ed, M_USB, M_NOWAIT);
526: if (ed == NULL) {
527: free(ue, M_USB);
528: return USBF_NOMEM;
529: }
530:
531: bzero(ue, sizeof *ue);
532: ue->iface = ui;
533: ue->edesc = ed;
534:
535: bzero(ed, sizeof *ed);
536: ed->bLength = USB_ENDPOINT_DESCRIPTOR_SIZE;
537: ed->bDescriptorType = UDESC_ENDPOINT;
538: ed->bEndpointAddress = bEndpointAddress;
539: ed->bmAttributes = bmAttributes;
540: USETW(ed->wMaxPacketSize, wMaxPacketSize);
541: ed->bInterval = bInterval;
542:
543: SIMPLEQ_INSERT_TAIL(&ui->endpoint_head, ue, next);
544: ui->idesc->bNumEndpoints++;
545:
546: *uep = ue;
547: return USBF_NORMAL_COMPLETION;
548: }
549:
550: /*
551: * Close the configuration, thereby combining all descriptors and creating
552: * the real USB configuration descriptor that can be sent to the USB host.
553: */
554: usbf_status
555: usbf_end_config(usbf_config_handle uc)
556: {
557: struct usbf_interface *ui;
558: struct usbf_endpoint *ue;
559: usb_descriptor_t *d;
560: usbf_status err = USBF_NORMAL_COMPLETION;
561:
562: if (uc->uc_closed)
563: return USBF_INVAL;
564:
565: SIMPLEQ_FOREACH(ui, &uc->iface_head, next) {
566: err = usbf_add_config_desc(uc,
567: (usb_descriptor_t *)ui->idesc, &d);
568: if (err)
569: break;
570:
571: free(ui->idesc, M_USB);
572: ui->idesc = (usb_interface_descriptor_t *)d;
573:
574: SIMPLEQ_FOREACH(ue, &ui->endpoint_head, next) {
575: err = usbf_add_config_desc(uc,
576: (usb_descriptor_t *)ue->edesc, &d);
577: if (err)
578: break;
579:
580: free(ue->edesc, M_USB);
581: ue->edesc = (usb_endpoint_descriptor_t *)d;
582: }
583: }
584:
585: uc->uc_closed = 1;
586: return err;
587: }
588:
589: usb_device_descriptor_t *
590: usbf_device_descriptor(usbf_device_handle dev)
591: {
592: return &dev->ddesc;
593: }
594:
595: usb_config_descriptor_t *
596: usbf_config_descriptor(usbf_device_handle dev, u_int8_t index)
597: {
598: struct usbf_config *uc;
599:
600: SIMPLEQ_FOREACH(uc, &dev->configs, next) {
601: if (index-- == 0)
602: return uc->uc_cdesc;
603: }
604: return NULL;
605: }
606:
607: int
608: usbf_interface_number(usbf_interface_handle iface)
609: {
610: return iface->idesc->bInterfaceNumber;
611: }
612:
613: u_int8_t
614: usbf_endpoint_address(usbf_endpoint_handle endpoint)
615: {
616: return endpoint->edesc->bEndpointAddress;
617: }
618:
619: u_int8_t
620: usbf_endpoint_attributes(usbf_endpoint_handle endpoint)
621: {
622: return endpoint->edesc->bmAttributes;
623: }
624:
625: usbf_status
626: usbf_open_pipe(usbf_interface_handle iface, u_int8_t address,
627: usbf_pipe_handle *pipe)
628: {
629: return usbf_open_pipe_ival(iface, address, pipe, 0);
630: }
631:
632: usbf_status
633: usbf_open_pipe_ival(usbf_interface_handle iface, u_int8_t address,
634: usbf_pipe_handle *pipe, int ival)
635: {
636: struct usbf_endpoint *ep;
637: usbf_pipe_handle p;
638: usbf_status err;
639:
640: ep = usbf_iface_endpoint(iface, address);
641: if (ep == NULL)
642: return USBF_BAD_ADDRESS;
643:
644: err = usbf_setup_pipe(iface->config->uc_device, iface, ep,
645: ival, &p);
646: if (err)
647: return err;
648: LIST_INSERT_HEAD(&iface->pipes, p, next);
649: *pipe = p;
650: return USBF_NORMAL_COMPLETION;
651: }
652:
653: usbf_status
654: usbf_setup_pipe(usbf_device_handle dev, usbf_interface_handle iface,
655: struct usbf_endpoint *ep, int ival, usbf_pipe_handle *pipe)
656: {
657: struct usbf_pipe *p;
658: usbf_status err;
659:
660: p = malloc(dev->bus->pipe_size, M_USB, M_NOWAIT);
661: if (p == NULL)
662: return USBF_NOMEM;
663:
664: p->device = dev;
665: p->iface = iface;
666: p->endpoint = ep;
667: ep->refcnt++;
668: p->running = 0;
669: p->refcnt = 1;
670: p->repeat = 0;
671: p->interval = ival;
672: p->methods = NULL; /* set by bus driver in open_pipe() */
673: SIMPLEQ_INIT(&p->queue);
674: err = dev->bus->methods->open_pipe(p);
675: if (err) {
676: free(p, M_USB);
677: return err;
678: }
679: *pipe = p;
680: return USBF_NORMAL_COMPLETION;
681: }
682:
683: /* Dequeue all pipe operations. */
684: void
685: usbf_abort_pipe(usbf_pipe_handle pipe)
686: {
687: usbf_xfer_handle xfer;
688: int s;
689:
690: s = splusb();
691: pipe->repeat = 0;
692: pipe->aborting = 1;
693:
694: while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
695: DPRINTF(0,("usbf_abort_pipe: pipe=%p, xfer=%p\n", pipe,
696: xfer));
697: /* Make the DC abort it (and invoke the callback). */
698: pipe->methods->abort(xfer);
699: }
700:
701: pipe->aborting = 0;
702: splx(s);
703: }
704:
705: /* Abort all pipe operations and close the pipe. */
706: void
707: usbf_close_pipe(usbf_pipe_handle pipe)
708: {
709: usbf_abort_pipe(pipe);
710: pipe->methods->close(pipe);
711: pipe->endpoint->refcnt--;
712: free(pipe, M_USB);
713: }
714:
715: void
716: usbf_stall_pipe(usbf_pipe_handle pipe)
717: {
718: DPRINTF(0,("usbf_stall_pipe not implemented\n"));
719: }
720:
721: usbf_endpoint_handle
722: usbf_iface_endpoint(usbf_interface_handle iface, u_int8_t address)
723: {
724: usbf_endpoint_handle ep;
725:
726: SIMPLEQ_FOREACH(ep, &iface->endpoint_head, next) {
727: if (ep->edesc->bEndpointAddress == address)
728: return ep;
729: }
730: return NULL;
731: }
732:
733: usbf_endpoint_handle
734: usbf_config_endpoint(usbf_config_handle cfg, u_int8_t address)
735: {
736: usbf_interface_handle iface;
737: usbf_endpoint_handle ep;
738:
739: SIMPLEQ_FOREACH(iface, &cfg->iface_head, next) {
740: SIMPLEQ_FOREACH(ep, &iface->endpoint_head, next) {
741: if (ep->edesc->bEndpointAddress == address)
742: return ep;
743: }
744: }
745: return NULL;
746: }
747:
748: void
749: usbf_set_endpoint_halt(usbf_endpoint_handle endpoint)
750: {
751: }
752:
753: void
754: usbf_clear_endpoint_halt(usbf_endpoint_handle endpoint)
755: {
756: }
757:
758: usbf_status
759: usbf_set_endpoint_feature(usbf_config_handle cfg, u_int8_t address,
760: u_int16_t value)
761: {
762: usbf_endpoint_handle ep;
763:
764: DPRINTF(0,("usbf_set_endpoint_feature: cfg=%p address=%#x"
765: " value=%#x\n", cfg, address, value));
766:
767: ep = usbf_config_endpoint(cfg, address);
768: if (ep == NULL)
769: return USBF_BAD_ADDRESS;
770:
771: switch (value) {
772: case UF_ENDPOINT_HALT:
773: usbf_set_endpoint_halt(ep);
774: return USBF_NORMAL_COMPLETION;
775: default:
776: /* unsupported feature, send STALL in data/status phase */
777: return USBF_STALLED;
778: }
779: }
780:
781: usbf_status
782: usbf_clear_endpoint_feature(usbf_config_handle cfg, u_int8_t address,
783: u_int16_t value)
784: {
785: usbf_endpoint_handle ep;
786:
787: DPRINTF(0,("usbf_clear_endpoint_feature: cfg=%p address=%#x"
788: " value=%#x\n", cfg, address, value));
789:
790: ep = usbf_config_endpoint(cfg, address);
791: if (ep == NULL)
792: return USBF_BAD_ADDRESS;
793:
794: switch (value) {
795: case UF_ENDPOINT_HALT:
796: usbf_clear_endpoint_halt(ep);
797: return USBF_NORMAL_COMPLETION;
798: default:
799: /* unsupported feature, send STALL in data/status phase */
800: return USBF_STALLED;
801: }
802: }
803:
804: usbf_xfer_handle
805: usbf_alloc_xfer(usbf_device_handle dev)
806: {
807: struct usbf_xfer *xfer;
808:
809: /* allocate zero-filled buffer */
810: xfer = dev->bus->methods->allocx(dev->bus);
811: if (xfer == NULL)
812: return NULL;
813: xfer->device = dev;
814: timeout_set(&xfer->timeout_handle, NULL, NULL);
815: DPRINTF(1,("usbf_alloc_xfer() = %p\n", xfer));
816: return xfer;
817: }
818:
819: void
820: usbf_free_xfer(usbf_xfer_handle xfer)
821: {
822: DPRINTF(1,("usbf_free_xfer: %p\n", xfer));
823: if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
824: usbf_free_buffer(xfer);
825: xfer->device->bus->methods->freex(xfer->device->bus, xfer);
826: }
827:
828: usbf_status
829: usbf_allocmem(usbf_bus_handle bus, size_t size, size_t align, usb_dma_t *p)
830: {
831: struct usbd_bus dbus;
832: usbd_status err;
833:
834: /* XXX bad idea, fix usb_mem.c instead! */
835: dbus.dmatag = bus->dmatag;
836: err = usb_allocmem(&dbus, size, align, p);
837: return err ? USBF_NOMEM : USBF_NORMAL_COMPLETION;
838: }
839:
840: void
841: usbf_freemem(usbf_bus_handle bus, usb_dma_t *p)
842: {
843: usb_freemem((usbd_bus_handle)NULL, p);
844: }
845:
846: void *
847: usbf_alloc_buffer(usbf_xfer_handle xfer, u_int32_t size)
848: {
849: struct usbf_bus *bus = xfer->device->bus;
850: usbf_status err;
851:
852: #ifdef DIAGNOSTIC
853: if (xfer->rqflags & (URQ_DEV_DMABUF | URQ_AUTO_DMABUF))
854: printf("xfer %p already has a buffer\n", xfer);
855: #endif
856:
857: err = bus->methods->allocm(bus, &xfer->dmabuf, size);
858: if (err)
859: return NULL;
860:
861: xfer->rqflags |= URQ_DEV_DMABUF;
862: return KERNADDR(&xfer->dmabuf, 0);
863: }
864:
865: void
866: usbf_free_buffer(usbf_xfer_handle xfer)
867: {
868: #ifdef DIAGNOSTIC
869: if (!(xfer->rqflags & URQ_DEV_DMABUF)) {
870: printf("usbf_free_buffer: no buffer\n");
871: return;
872: }
873: #endif
874: xfer->rqflags &= ~URQ_DEV_DMABUF;
875: xfer->device->bus->methods->freem(xfer->device->bus, &xfer->dmabuf);
876: }
877:
878: #ifdef USBF_DEBUG
879: /*
880: * The dump format is similar to Linux' Gadget driver so that we can
881: * easily compare traces.
882: */
883: static void
884: usbf_dump_buffer(usbf_xfer_handle xfer)
885: {
886: struct device *dev = (struct device *)xfer->pipe->device->bus->usbfctl;
887: usbf_endpoint_handle ep = xfer->pipe->endpoint;
888: int index = usbf_endpoint_index(ep);
889: int dir = usbf_endpoint_dir(ep);
890: u_char *p = xfer->buffer;
891: u_int i;
892:
893: printf("%s: ep%d-%s, length=%u, %s", dev->dv_xname, index,
894: (xfer->rqflags & URQ_REQUEST) ? "setup" :
895: (index == 0 ? "in" : (dir == UE_DIR_IN ? "in" : "out")),
896: xfer->length, usbf_errstr(xfer->status));
897:
898: for (i = 0; i < xfer->length; i++) {
899: if ((i % 16) == 0)
900: printf("\n%4x:", i);
901: else if ((i % 8) == 0)
902: printf(" ");
903: printf(" %02x", p[i]);
904: }
905: printf("\n");
906: }
907: #endif
908:
909: void
910: usbf_setup_xfer(usbf_xfer_handle xfer, usbf_pipe_handle pipe,
911: usbf_private_handle priv, void *buffer, u_int32_t length,
912: u_int16_t flags, u_int32_t timeout, usbf_callback callback)
913: {
914: xfer->pipe = pipe;
915: xfer->priv = priv;
916: xfer->buffer = buffer;
917: xfer->length = length;
918: xfer->actlen = 0;
919: xfer->flags = flags;
920: xfer->timeout = timeout;
921: xfer->status = USBF_NOT_STARTED;
922: xfer->callback = callback;
923: xfer->rqflags &= ~URQ_REQUEST;
924: }
925:
926: void
927: usbf_setup_default_xfer(usbf_xfer_handle xfer, usbf_pipe_handle pipe,
928: usbf_private_handle priv, usb_device_request_t *req, u_int16_t flags,
929: u_int32_t timeout, usbf_callback callback)
930: {
931: xfer->pipe = pipe;
932: xfer->priv = priv;
933: xfer->buffer = req;
934: xfer->length = sizeof *req;
935: xfer->actlen = 0;
936: xfer->flags = flags;
937: xfer->timeout = timeout;
938: xfer->status = USBF_NOT_STARTED;
939: xfer->callback = callback;
940: xfer->rqflags |= URQ_REQUEST;
941: }
942:
943: void
944: usbf_get_xfer_status(usbf_xfer_handle xfer, usbf_private_handle *priv,
945: void **buffer, u_int32_t *actlen, usbf_status *status)
946: {
947: if (priv != NULL)
948: *priv = xfer->priv;
949: if (buffer != NULL)
950: *buffer = xfer->buffer;
951: if (actlen != NULL)
952: *actlen = xfer->actlen;
953: if (status != NULL)
954: *status = xfer->status;
955: }
956:
957: usbf_status
958: usbf_transfer(usbf_xfer_handle xfer)
959: {
960: usbf_pipe_handle pipe = xfer->pipe;
961: usbf_status err;
962:
963: err = pipe->methods->transfer(xfer);
964: if (err != USBF_IN_PROGRESS && err) {
965: if (xfer->rqflags & URQ_AUTO_DMABUF) {
966: usbf_free_buffer(xfer);
967: xfer->rqflags &= ~URQ_AUTO_DMABUF;
968: }
969: }
970: return err;
971: }
972:
973: usbf_status
974: usbf_insert_transfer(usbf_xfer_handle xfer)
975: {
976: usbf_pipe_handle pipe = xfer->pipe;
977: usbf_status err;
978: int s;
979:
980: DPRINTF(1,("usbf_insert_transfer: xfer=%p pipe=%p running=%d\n",
981: xfer, pipe, pipe->running));
982:
983: s = splusb();
984: SIMPLEQ_INSERT_TAIL(&pipe->queue, xfer, next);
985: if (pipe->running)
986: err = USBF_IN_PROGRESS;
987: else {
988: pipe->running = 1;
989: err = USBF_NORMAL_COMPLETION;
990: }
991: splx(s);
992: return err;
993: }
994:
995: void
996: usbf_start_next(usbf_pipe_handle pipe)
997: {
998: usbf_xfer_handle xfer;
999: usbf_status err;
1000:
1001: SPLUSBCHECK;
1002:
1003: /* Get next request in queue. */
1004: xfer = SIMPLEQ_FIRST(&pipe->queue);
1005: if (xfer == NULL)
1006: pipe->running = 0;
1007: else {
1008: err = pipe->methods->start(xfer);
1009: if (err != USBF_IN_PROGRESS) {
1010: printf("usbf_start_next: %s\n", usbf_errstr(err));
1011: pipe->running = 0;
1012: /* XXX do what? */
1013: }
1014: }
1015: }
1016:
1017: /* Called at splusb() */
1018: void
1019: usbf_transfer_complete(usbf_xfer_handle xfer)
1020: {
1021: usbf_pipe_handle pipe = xfer->pipe;
1022: int repeat = pipe->repeat;
1023:
1024: SPLUSBCHECK;
1025: DPRINTF(1,("usbf_transfer_complete: xfer=%p pipe=%p running=%d\n",
1026: xfer, pipe, pipe->running));
1027: #ifdef USBF_DEBUG
1028: if (usbfdebug > 0)
1029: usbf_dump_buffer(xfer);
1030: #endif
1031:
1032: if (!repeat) {
1033: /* Remove request from queue. */
1034: KASSERT(SIMPLEQ_FIRST(&pipe->queue) == xfer);
1035: SIMPLEQ_REMOVE_HEAD(&pipe->queue, next);
1036: }
1037:
1038: if (xfer->status == USBF_NORMAL_COMPLETION &&
1039: xfer->actlen < xfer->length &&
1040: !(xfer->flags & USBD_SHORT_XFER_OK)) {
1041: DPRINTF(0,("usbf_transfer_complete: short xfer=%p %u<%u\n",
1042: xfer, xfer->actlen, xfer->length));
1043: xfer->status = USBF_SHORT_XFER;
1044: }
1045:
1046: if (xfer->callback != NULL)
1047: xfer->callback(xfer, xfer->priv, xfer->status);
1048:
1049: pipe->methods->done(xfer);
1050:
1051: /* XXX wake up any processes waiting for the transfer to complete */
1052:
1053: if (!repeat) {
1054: if (xfer->status != USBF_NORMAL_COMPLETION &&
1055: pipe->iface != NULL) /* not control pipe */
1056: pipe->running = 0;
1057: else
1058: usbf_start_next(pipe);
1059: }
1060: }
1061:
1062: /*
1063: * Software interrupts
1064: */
1065:
1066: usbf_status
1067: usbf_softintr_establish(struct usbf_bus *bus)
1068: {
1069: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1070: KASSERT(bus->soft == NULL);
1071: /* XXX we should have our own level */
1072: bus->soft = softintr_establish(IPL_SOFTNET,
1073: bus->methods->soft_intr, bus);
1074: if (bus->soft == NULL)
1075: return USBF_INVAL;
1076: #endif
1077: return USBF_NORMAL_COMPLETION;
1078: }
1079:
1080: void
1081: usbf_schedsoftintr(struct usbf_bus *bus)
1082: {
1083: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1084: softintr_schedule(bus->soft);
1085: #else
1086: bus->methods->soft_intr(bus);
1087: #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
1088: }
CVSweb