Module Name: src Committed By: pooka Date: Mon Mar 22 12:05:45 UTC 2010
Modified Files: src/sys/rump/dev/lib/libugenhc: ugenhc.c Log Message: * support isochronous transfers (for as much as they can be supported considering our ugen driver doesn't support isochronous write. kern/25960 seems to contain a patch and could be investigated for that) * add a dirty rotten hack which makes interrupt transfers of >16 work for me To generate a diff of this commit: cvs rdiff -u -r1.8 -r1.9 src/sys/rump/dev/lib/libugenhc/ugenhc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/rump/dev/lib/libugenhc/ugenhc.c diff -u src/sys/rump/dev/lib/libugenhc/ugenhc.c:1.8 src/sys/rump/dev/lib/libugenhc/ugenhc.c:1.9 --- src/sys/rump/dev/lib/libugenhc/ugenhc.c:1.8 Tue Feb 23 14:05:04 2010 +++ src/sys/rump/dev/lib/libugenhc/ugenhc.c Mon Mar 22 12:05:45 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: ugenhc.c,v 1.8 2010/02/23 14:05:04 pooka Exp $ */ +/* $NetBSD: ugenhc.c,v 1.9 2010/03/22 12:05:45 pooka Exp $ */ /* * Copyright (c) 2009, 2010 Antti Kantee. All Rights Reserved. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.8 2010/02/23 14:05:04 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.9 2010/03/22 12:05:45 pooka Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -506,6 +506,7 @@ case C(0x22, UT_WRITE_CLASS_INTERFACE): case C(0x0a, UT_WRITE_CLASS_INTERFACE): case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): + case C(0x00, UT_WRITE_CLASS_DEVICE): case C(UR_SET_FEATURE, UT_WRITE_DEVICE): case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE): @@ -718,40 +719,46 @@ rumpusb_device_bulk_start(usbd_xfer_handle xfer) { struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; + usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc; ssize_t n; ssize_t done; bool isread; int len, error, endpt; uint8_t *buf; int xfererr = USBD_NORMAL_COMPLETION; - int val; + int shortval, i; - endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; + ed = xfer->pipe->endpoint->edesc; + endpt = ed->bEndpointAddress; isread = UE_GET_DIR(endpt) == UE_DIR_IN; endpt = UE_GET_ADDR(endpt); KASSERT(endpt < UGEN_NEPTS); - KASSERT(xfer->length); - len = xfer->length; buf = KERNADDR(&xfer->dmabuf, 0); done = 0; + if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) { + for (i = 0, len = 0; i < xfer->nframes; i++) + len += xfer->frlengths[i]; + } else { + KASSERT(xfer->length); + len = xfer->length; + } + shortval = (xfer->flags & USBD_SHORT_XFER_OK) != 0; while (RUSB(xfer)->rusb_status == 0) { if (isread) { - if (xfer->flags & USBD_SHORT_XFER_OK) - val = 1; - else - val = 0; rumpuser_ioctl(sc->sc_ugenfd[endpt], - USB_SET_SHORT_XFER, &val, &error); + USB_SET_SHORT_XFER, &shortval, &error); n = rumpuser_read(sc->sc_ugenfd[endpt], buf+done, len-done, &error); if (n == -1) { - if (error == ETIMEDOUT) - continue; n = 0; - xfererr = USBD_IOERROR; - goto out; + if (done == 0) { + if (error == ETIMEDOUT) + continue; + xfererr = USBD_IOERROR; + goto out; + } } done += n; if (done == len) @@ -769,8 +776,23 @@ goto out; } - if (xfer->flags & USBD_SHORT_XFER_OK) - break; + if (shortval) { + /* + * Holy XXX, bitman. I get >16byte interrupt + * transfers from ugen in 16 byte chunks. + * Don't know how to better fix this for now. + * Of course this hack will fail e.g. if someone + * sports other magic values or if the transfer + * happens to be an integral multiple of 16 + * in size .... + */ + if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT + && n == 16) { + continue; + } else { + break; + } + } } if (RUSB(xfer)->rusb_status == 0) { @@ -780,6 +802,9 @@ RUSB(xfer)->rusb_status = 2; } out: + if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) + if (done != len) + panic("lazy bum"); xfer->status = xfererr; usb_transfer_complete(xfer); return (USBD_IN_PROGRESS); @@ -918,6 +943,7 @@ break; case UE_INTERRUPT: case UE_BULK: + case UE_ISOCHRONOUS: pipe->methods = &rumpusb_device_bulk_methods; endpt = pipe->endpoint->edesc->bEndpointAddress; if (UE_GET_DIR(endpt) == UE_DIR_IN) { @@ -927,6 +953,11 @@ } endpt = UE_GET_ADDR(endpt); + if (oflags != O_RDONLY && xfertype == UE_ISOCHRONOUS) { + printf("WARNING: faking isoc write open\n"); + oflags = O_RDONLY; + } + if (sc->sc_fdmodes[endpt] == oflags || sc->sc_fdmodes[endpt] == O_RDWR) break; @@ -939,14 +970,16 @@ makeugendevstr(sc->sc_devnum, endpt, buf); fd = rumpuser_open(buf, oflags, &error); - if (fd == -1) + if (fd == -1) { return USBD_INVAL; /* XXX: no mapping */ + } val = 100; if (rumpuser_ioctl(fd, USB_SET_TIMEOUT, &val, &error) == -1) panic("timeout set failed"); sc->sc_ugenfd[endpt] = fd; sc->sc_fdmodes[endpt] = oflags; + break; default: panic("%d not supported", xfertype);