version 1.8, 2010/02/23 14:05:04 |
version 1.8.2.3, 2010/08/11 22:55:02 |
Line 506 rumpusb_device_ctrl_start(usbd_xfer_hand |
|
Line 506 rumpusb_device_ctrl_start(usbd_xfer_hand |
|
case C(0x22, UT_WRITE_CLASS_INTERFACE): |
case C(0x22, UT_WRITE_CLASS_INTERFACE): |
case C(0x0a, UT_WRITE_CLASS_INTERFACE): |
case C(0x0a, UT_WRITE_CLASS_INTERFACE): |
case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER): |
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_SET_FEATURE, UT_WRITE_DEVICE): |
case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): |
case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER): |
case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE): |
case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE): |
Line 718 static usbd_status |
|
Line 719 static usbd_status |
|
rumpusb_device_bulk_start(usbd_xfer_handle xfer) |
rumpusb_device_bulk_start(usbd_xfer_handle xfer) |
{ |
{ |
struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; |
struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private; |
|
usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc; |
ssize_t n; |
ssize_t n; |
ssize_t done; |
ssize_t done; |
bool isread; |
bool isread; |
int len, error, endpt; |
int len, error, endpt; |
uint8_t *buf; |
uint8_t *buf; |
int xfererr = USBD_NORMAL_COMPLETION; |
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; |
isread = UE_GET_DIR(endpt) == UE_DIR_IN; |
endpt = UE_GET_ADDR(endpt); |
endpt = UE_GET_ADDR(endpt); |
KASSERT(endpt < UGEN_NEPTS); |
KASSERT(endpt < UGEN_NEPTS); |
|
|
KASSERT(xfer->length); |
|
len = xfer->length; |
|
buf = KERNADDR(&xfer->dmabuf, 0); |
buf = KERNADDR(&xfer->dmabuf, 0); |
done = 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) { |
while (RUSB(xfer)->rusb_status == 0) { |
if (isread) { |
if (isread) { |
if (xfer->flags & USBD_SHORT_XFER_OK) |
|
val = 1; |
|
else |
|
val = 0; |
|
rumpuser_ioctl(sc->sc_ugenfd[endpt], |
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], |
n = rumpuser_read(sc->sc_ugenfd[endpt], |
buf+done, len-done, &error); |
buf+done, len-done, &error); |
if (n == -1) { |
if (n == -1) { |
if (error == ETIMEDOUT) |
|
continue; |
|
n = 0; |
n = 0; |
xfererr = USBD_IOERROR; |
if (done == 0) { |
goto out; |
if (error == ETIMEDOUT) |
|
continue; |
|
xfererr = USBD_IOERROR; |
|
goto out; |
|
} |
} |
} |
done += n; |
done += n; |
if (done == len) |
if (done == len) |
Line 769 rumpusb_device_bulk_start(usbd_xfer_hand |
|
Line 776 rumpusb_device_bulk_start(usbd_xfer_hand |
|
goto out; |
goto out; |
} |
} |
|
|
if (xfer->flags & USBD_SHORT_XFER_OK) |
if (shortval) { |
break; |
/* |
|
* 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) { |
if (RUSB(xfer)->rusb_status == 0) { |
Line 780 rumpusb_device_bulk_start(usbd_xfer_hand |
|
Line 802 rumpusb_device_bulk_start(usbd_xfer_hand |
|
RUSB(xfer)->rusb_status = 2; |
RUSB(xfer)->rusb_status = 2; |
} |
} |
out: |
out: |
|
if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) |
|
if (done != len) |
|
panic("lazy bum"); |
xfer->status = xfererr; |
xfer->status = xfererr; |
usb_transfer_complete(xfer); |
usb_transfer_complete(xfer); |
return (USBD_IN_PROGRESS); |
return (USBD_IN_PROGRESS); |
Line 918 ugenhc_open(struct usbd_pipe *pipe) |
|
Line 943 ugenhc_open(struct usbd_pipe *pipe) |
|
break; |
break; |
case UE_INTERRUPT: |
case UE_INTERRUPT: |
case UE_BULK: |
case UE_BULK: |
|
case UE_ISOCHRONOUS: |
pipe->methods = &rumpusb_device_bulk_methods; |
pipe->methods = &rumpusb_device_bulk_methods; |
endpt = pipe->endpoint->edesc->bEndpointAddress; |
endpt = pipe->endpoint->edesc->bEndpointAddress; |
if (UE_GET_DIR(endpt) == UE_DIR_IN) { |
if (UE_GET_DIR(endpt) == UE_DIR_IN) { |
Line 927 ugenhc_open(struct usbd_pipe *pipe) |
|
Line 953 ugenhc_open(struct usbd_pipe *pipe) |
|
} |
} |
endpt = UE_GET_ADDR(endpt); |
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 |
if (sc->sc_fdmodes[endpt] == oflags |
|| sc->sc_fdmodes[endpt] == O_RDWR) |
|| sc->sc_fdmodes[endpt] == O_RDWR) |
break; |
break; |
Line 939 ugenhc_open(struct usbd_pipe *pipe) |
|
Line 970 ugenhc_open(struct usbd_pipe *pipe) |
|
|
|
makeugendevstr(sc->sc_devnum, endpt, buf); |
makeugendevstr(sc->sc_devnum, endpt, buf); |
fd = rumpuser_open(buf, oflags, &error); |
fd = rumpuser_open(buf, oflags, &error); |
if (fd == -1) |
if (fd == -1) { |
return USBD_INVAL; /* XXX: no mapping */ |
return USBD_INVAL; /* XXX: no mapping */ |
|
} |
val = 100; |
val = 100; |
if (rumpuser_ioctl(fd, USB_SET_TIMEOUT, &val, |
if (rumpuser_ioctl(fd, USB_SET_TIMEOUT, &val, |
&error) == -1) |
&error) == -1) |
panic("timeout set failed"); |
panic("timeout set failed"); |
sc->sc_ugenfd[endpt] = fd; |
sc->sc_ugenfd[endpt] = fd; |
sc->sc_fdmodes[endpt] = oflags; |
sc->sc_fdmodes[endpt] = oflags; |
|
|
break; |
break; |
default: |
default: |
panic("%d not supported", xfertype); |
panic("%d not supported", xfertype); |