Module Name: src Committed By: pooka Date: Mon Oct 5 13:00:38 UTC 2009
Modified Files: src/sys/rump/dev/wip/librumpusbhc: Makefile rumpusbhc.c Log Message: * support async transfers * make it possible to abort transfers (these are all cheap hacks, but make things work) To generate a diff of this commit: cvs rdiff -u -r1.1 -r1.2 src/sys/rump/dev/wip/librumpusbhc/Makefile cvs rdiff -u -r1.5 -r1.6 src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.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/wip/librumpusbhc/Makefile diff -u src/sys/rump/dev/wip/librumpusbhc/Makefile:1.1 src/sys/rump/dev/wip/librumpusbhc/Makefile:1.2 --- src/sys/rump/dev/wip/librumpusbhc/Makefile:1.1 Fri Oct 2 15:35:46 2009 +++ src/sys/rump/dev/wip/librumpusbhc/Makefile Mon Oct 5 13:00:37 2009 @@ -1,9 +1,11 @@ -# $NetBSD: Makefile,v 1.1 2009/10/02 15:35:46 pooka Exp $ +# $NetBSD: Makefile,v 1.2 2009/10/05 13:00:37 pooka Exp $ # LIB= rumpdev_usbhc SRCS= rumpusbhc.c +CPPFLAGS+= -I${RUMPTOP}/librump/rumpkern + .include <bsd.lib.mk> .include <bsd.klinks.mk> Index: src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c diff -u src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c:1.5 src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c:1.6 --- src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c:1.5 Sun Oct 4 17:46:58 2009 +++ src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c Mon Oct 5 13:00:37 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: rumpusbhc.c,v 1.5 2009/10/04 17:46:58 pooka Exp $ */ +/* $NetBSD: rumpusbhc.c,v 1.6 2009/10/05 13:00:37 pooka Exp $ */ /* * Copyright (c) 2009 Antti Kantee. All Rights Reserved. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: rumpusbhc.c,v 1.5 2009/10/04 17:46:58 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rumpusbhc.c,v 1.6 2009/10/05 13:00:37 pooka Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -69,6 +69,8 @@ #include <sys/device.h> #include <sys/fcntl.h> #include <sys/kmem.h> +#include <sys/kernel.h> +#include <sys/kthread.h> #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> @@ -78,6 +80,7 @@ #include <rump/rumpuser.h> +#include "rump_private.h" #include "rump_dev_private.h" #define UGEN_NEPTS 16 @@ -119,12 +122,20 @@ DVUNIT_ANY }; +struct rusb_xfer { + struct usbd_xfer rusb_xfer; + int rusb_status; /* now this is a cheap trick */ +}; +#define RUSB(x) ((struct rusb_xfer *)x) + /* probe ugen0 through ugen3 */ struct cfdata rumpusbhc_cfdata[] = { +#if 0 { "rumpusbhc", "rumpusbhc", 0, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar}, { "rumpusbhc", "rumpusbhc", 1, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar}, - { "rumpusbhc", "rumpusbhc", 2, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar}, { "rumpusbhc", "rumpusbhc", 3, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar}, +#endif + { "rumpusbhc", "rumpusbhc", 2, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar}, }; #define UGENDEV_BASESTR "/dev/ugen" @@ -465,10 +476,6 @@ case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT): printf("clear feature UNIMPL\n"); - break; - - case C(0xfe, UT_READ_CLASS_INTERFACE): - /* XXX: what is this? */ totlen = 0; break; @@ -480,6 +487,7 @@ case C(0x06, UT_WRITE_VENDOR_DEVICE): case C(0x07, UT_READ_VENDOR_DEVICE): case C(0x09, UT_READ_VENDOR_DEVICE): + case C(0xfe, UT_READ_CLASS_INTERFACE): { struct usb_ctl_request ucr; @@ -631,44 +639,87 @@ len = xfer->length; buf = KERNADDR(&xfer->dmabuf, 0); - if (isread) { - n = rumpuser_read(sc->sc_ugenfd[endpt], buf, len, &error); - if (n != len) - n = 0; - } else { - n = rumpuser_write(sc->sc_ugenfd[endpt], buf, len, &error); - if (n != len) - panic("short write"); + while (RUSB(xfer)->rusb_status == 0) { + if (isread) { + n = rumpuser_read(sc->sc_ugenfd[endpt], + buf, len, &error); + if (n == len) + break; + if (error != EAGAIN) { + n = 0; + break; + } + } else { + n = rumpuser_write(sc->sc_ugenfd[endpt], + buf, len, &error); + if (n == len) + break; + else + panic("short write"); + } } - xfer->actlen = n; - xfer->status = USBD_NORMAL_COMPLETION; + if (RUSB(xfer)->rusb_status == 0) { + xfer->actlen = n; + xfer->status = USBD_NORMAL_COMPLETION; + } else { + xfer->status = USBD_CANCELLED; + RUSB(xfer)->rusb_status = 2; + } usb_transfer_complete(xfer); return (USBD_IN_PROGRESS); } +static void +doxfer_kth(void *arg) +{ + usbd_xfer_handle xfer = arg; + + rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); + kthread_exit(0); +} + static usbd_status rumpusb_device_bulk_transfer(usbd_xfer_handle xfer) { usbd_status err; - /* XXX: lie about supporting async transfers */ - if ((xfer->flags & USBD_SYNCHRONOUS) == 0) { - printf("rumpusbhc does not support async transfers. LIAR!\n"); - return USBD_IN_PROGRESS; - } + if (!rump_threads) { + /* XXX: lie about supporting async transfers */ + if ((xfer->flags & USBD_SYNCHRONOUS) == 0) { + printf("non-threaded rump does not support " + "async transfers.\n"); + return USBD_IN_PROGRESS; + } - err = usb_insert_transfer(xfer); - if (err) - return (err); + err = usb_insert_transfer(xfer); + if (err) + return err; + + return rumpusb_device_bulk_start( + SIMPLEQ_FIRST(&xfer->pipe->queue)); + } else { + /* biglocked */ + err = usb_insert_transfer(xfer); + if (err) + return err; + kthread_create(PRI_NONE, 0, NULL, doxfer_kth, xfer, NULL, + "rusbhcxf"); - return (rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); + return USBD_IN_PROGRESS; + } } +/* wait for transfer to abort. yea, this is cheesy (from a spray can) */ static void rumpusb_device_bulk_abort(usbd_xfer_handle xfer) { + struct rusb_xfer *rx = RUSB(xfer); + rx->rusb_status = 1; + while (rx->rusb_status < 2) { + kpause("jopo", false, hz/10, NULL); + } } static void @@ -708,7 +759,7 @@ u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; char buf[UGENDEV_BUFSIZE]; int endpt, oflags, error; - int fd; + int fd, val; sc->sc_port_status = UPS_CURRENT_CONNECT_STATUS | UPS_PORT_ENABLED | UPS_PORT_POWER | UPS_HIGH_SPEED; @@ -755,6 +806,10 @@ fd = rumpuser_open(buf, oflags, &error); 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; @@ -885,4 +940,6 @@ /* whoah, like extreme XXX, bro */ rhscintr(); + if (!rump_threads) + config_pending_decr(); }