Module Name:    src
Committed By:   pooka
Date:           Wed Feb 10 02:26:24 UTC 2010

Modified Files:
        src/sys/rump/dev/wip: Makefile files.rump
        src/sys/rump/dev/wip/libucom: ucom_at_usb.c
        src/sys/rump/dev/wip/libukbd: ukbd_at_usb.c
        src/sys/rump/dev/wip/libulpt: ulpt_at_usb.c
        src/sys/rump/dev/wip/libumass: sd_at_scsibus_at_umass.c
        src/sys/rump/dev/wip/libums: ums_at_usb.c
        src/sys/rump/dev/wip/libusbrum: rum_at_usb.c
        src/sys/rump/dev/wip/libwscons: component.c
Added Files:
        src/sys/rump/dev/wip/libugenhc: Makefile shlib_version ugenhc.c
Removed Files:
        src/sys/rump/dev/wip/librumpusbhc: Makefile rumpusbhc.c shlib_version

Log Message:
Rename rumpusbhc to ugenhc, as that better describes what it does.
(the full component name is rumpdev_ugenhc)


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/rump/dev/wip/Makefile
cvs rdiff -u -r1.1 -r1.2 src/sys/rump/dev/wip/files.rump
cvs rdiff -u -r1.2 -r0 src/sys/rump/dev/wip/librumpusbhc/Makefile
cvs rdiff -u -r1.15 -r0 src/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c
cvs rdiff -u -r1.1 -r0 src/sys/rump/dev/wip/librumpusbhc/shlib_version
cvs rdiff -u -r1.3 -r1.4 src/sys/rump/dev/wip/libucom/ucom_at_usb.c
cvs rdiff -u -r0 -r1.1 src/sys/rump/dev/wip/libugenhc/Makefile \
    src/sys/rump/dev/wip/libugenhc/shlib_version \
    src/sys/rump/dev/wip/libugenhc/ugenhc.c
cvs rdiff -u -r1.2 -r1.3 src/sys/rump/dev/wip/libukbd/ukbd_at_usb.c
cvs rdiff -u -r1.1 -r1.2 src/sys/rump/dev/wip/libulpt/ulpt_at_usb.c
cvs rdiff -u -r1.9 -r1.10 \
    src/sys/rump/dev/wip/libumass/sd_at_scsibus_at_umass.c
cvs rdiff -u -r1.2 -r1.3 src/sys/rump/dev/wip/libums/ums_at_usb.c
cvs rdiff -u -r1.2 -r1.3 src/sys/rump/dev/wip/libusbrum/rum_at_usb.c
cvs rdiff -u -r1.1 -r1.2 src/sys/rump/dev/wip/libwscons/component.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/Makefile
diff -u src/sys/rump/dev/wip/Makefile:1.5 src/sys/rump/dev/wip/Makefile:1.6
--- src/sys/rump/dev/wip/Makefile:1.5	Fri Feb  5 22:01:38 2010
+++ src/sys/rump/dev/wip/Makefile	Wed Feb 10 02:26:23 2010
@@ -1,7 +1,7 @@
-#	$NetBSD: Makefile,v 1.5 2010/02/05 22:01:38 pooka Exp $
+#	$NetBSD: Makefile,v 1.6 2010/02/10 02:26:23 pooka Exp $
 #
 
-SUBDIR=	librumpusbhc libucom libumass libulpt libusb libusbrum
+SUBDIR=	libugenhc libucom libumass libulpt libusb libusbrum
 SUBDIR+=libums libukbd
 
 SUBDIR+=libwscons

Index: src/sys/rump/dev/wip/files.rump
diff -u src/sys/rump/dev/wip/files.rump:1.1 src/sys/rump/dev/wip/files.rump:1.2
--- src/sys/rump/dev/wip/files.rump:1.1	Thu Feb  4 00:37:08 2010
+++ src/sys/rump/dev/wip/files.rump	Wed Feb 10 02:26:23 2010
@@ -1,20 +1,20 @@
-#	$NetBSD: files.rump,v 1.1 2010/02/04 00:37:08 pooka Exp $
+#	$NetBSD: files.rump,v 1.2 2010/02/10 02:26:23 pooka Exp $
 #
 
 device mainbus { }
 attach mainbus at root
-device rumpusbhc: usbus, usbroothub
-attach rumpusbhc at mainbus
+device ugenhc: usbus, usbroothub
+attach ugenhc at mainbus
 
 # ugen0 - ugen3
 mainbus0 at root
-rumpusbhc0 at mainbus0
-rumpusbhc1 at mainbus0
-rumpusbhc2 at mainbus0
-rumpusbhc3 at mainbus0
+ugenhc0 at mainbus0
+ugenhc1 at mainbus0
+ugenhc2 at mainbus0
+ugenhc3 at mainbus0
 
 # USB bus support
-usb*    at rumpusbhc?
+usb*    at ugenhc?
 
 # USB ROOT Hub
 #

Index: src/sys/rump/dev/wip/libucom/ucom_at_usb.c
diff -u src/sys/rump/dev/wip/libucom/ucom_at_usb.c:1.3 src/sys/rump/dev/wip/libucom/ucom_at_usb.c:1.4
--- src/sys/rump/dev/wip/libucom/ucom_at_usb.c:1.3	Wed Feb  3 21:18:38 2010
+++ src/sys/rump/dev/wip/libucom/ucom_at_usb.c	Wed Feb 10 02:26:23 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucom_at_usb.c,v 1.3 2010/02/03 21:18:38 pooka Exp $	*/
+/*	$NetBSD: ucom_at_usb.c,v 1.4 2010/02/10 02:26:23 pooka Exp $	*/
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -32,8 +32,8 @@
 	FLAWLESSCALL(config_cfdriver_attach(&mainbus_cd));
 	FLAWLESSCALL(config_cfattach_attach("mainbus", &mainbus_ca));
 
-	FLAWLESSCALL(config_cfdriver_attach(&rumpusbhc_cd));
-	FLAWLESSCALL(config_cfattach_attach("rumpusbhc", &rumpusbhc_ca));
+	FLAWLESSCALL(config_cfdriver_attach(&ugenhc_cd));
+	FLAWLESSCALL(config_cfattach_attach("ugenhc", &ugenhc_ca));
 
 	FLAWLESSCALL(config_cfdriver_attach(&usb_cd));
 	FLAWLESSCALL(config_cfattach_attach("usb", &usb_ca));

Index: src/sys/rump/dev/wip/libukbd/ukbd_at_usb.c
diff -u src/sys/rump/dev/wip/libukbd/ukbd_at_usb.c:1.2 src/sys/rump/dev/wip/libukbd/ukbd_at_usb.c:1.3
--- src/sys/rump/dev/wip/libukbd/ukbd_at_usb.c:1.2	Wed Feb  3 21:18:38 2010
+++ src/sys/rump/dev/wip/libukbd/ukbd_at_usb.c	Wed Feb 10 02:26:23 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ukbd_at_usb.c,v 1.2 2010/02/03 21:18:38 pooka Exp $	*/
+/*	$NetBSD: ukbd_at_usb.c,v 1.3 2010/02/10 02:26:23 pooka Exp $	*/
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -28,8 +28,8 @@
 	FLAWLESSCALL(config_cfdriver_attach(&mainbus_cd));
 	FLAWLESSCALL(config_cfattach_attach("mainbus", &mainbus_ca));
 
-	FLAWLESSCALL(config_cfdriver_attach(&rumpusbhc_cd));
-	FLAWLESSCALL(config_cfattach_attach("rumpusbhc", &rumpusbhc_ca));
+	FLAWLESSCALL(config_cfdriver_attach(&ugenhc_cd));
+	FLAWLESSCALL(config_cfattach_attach("ugenhc", &ugenhc_ca));
 
 	FLAWLESSCALL(config_cfdriver_attach(&usb_cd));
 	FLAWLESSCALL(config_cfattach_attach("usb", &usb_ca));

Index: src/sys/rump/dev/wip/libulpt/ulpt_at_usb.c
diff -u src/sys/rump/dev/wip/libulpt/ulpt_at_usb.c:1.1 src/sys/rump/dev/wip/libulpt/ulpt_at_usb.c:1.2
--- src/sys/rump/dev/wip/libulpt/ulpt_at_usb.c:1.1	Tue Dec 15 15:52:30 2009
+++ src/sys/rump/dev/wip/libulpt/ulpt_at_usb.c	Wed Feb 10 02:26:23 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ulpt_at_usb.c,v 1.1 2009/12/15 15:52:30 pooka Exp $	*/
+/*	$NetBSD: ulpt_at_usb.c,v 1.2 2010/02/10 02:26:23 pooka Exp $	*/
 
 /*
  * MACHINE GENERATED: DO NOT EDIT
@@ -347,15 +347,10 @@
 
 CFDRIVER_DECL(ulpt, DV_DULL, NULL);
 
-static const struct cfiattrdata * const rumpusbhc_attrs[] = { &usbuscf_iattrdata, NULL };
-CFDRIVER_DECL(rumpusbhc, DV_DULL, rumpusbhc_attrs);
-
-
 
 extern struct cfattach usb_ca;
 extern struct cfattach uroothub_ca;
 extern struct cfattach ulpt_ca;
-extern struct cfattach rumpusbhc_ca;
 
 /* locators */
 static int loc[6] = {

Index: src/sys/rump/dev/wip/libumass/sd_at_scsibus_at_umass.c
diff -u src/sys/rump/dev/wip/libumass/sd_at_scsibus_at_umass.c:1.9 src/sys/rump/dev/wip/libumass/sd_at_scsibus_at_umass.c:1.10
--- src/sys/rump/dev/wip/libumass/sd_at_scsibus_at_umass.c:1.9	Wed Feb 10 02:08:34 2010
+++ src/sys/rump/dev/wip/libumass/sd_at_scsibus_at_umass.c	Wed Feb 10 02:26:24 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: sd_at_scsibus_at_umass.c,v 1.9 2010/02/10 02:08:34 pooka Exp $	*/
+/*	$NetBSD: sd_at_scsibus_at_umass.c,v 1.10 2010/02/10 02:26:24 pooka Exp $	*/
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -21,7 +21,7 @@
 void
 rump_device_configuration(void)
 {
-	extern struct cfattach rumpusbhc_ca;
+	extern struct cfattach ugenhc_ca;
 	extern struct cfattach usb_ca, uhub_ca, uroothub_ca, umass_ca;
 	extern struct cfattach scsibus_ca, atapibus_ca, sd_ca, cd_ca;
 	extern struct bdevsw sd_bdevsw, cd_bdevsw;
@@ -33,8 +33,8 @@
 	FLAWLESSCALL(config_cfdriver_attach(&mainbus_cd));
 	FLAWLESSCALL(config_cfattach_attach("mainbus", &mainbus_ca));
 
-	FLAWLESSCALL(config_cfdriver_attach(&rumpusbhc_cd));
-	FLAWLESSCALL(config_cfattach_attach("rumpusbhc", &rumpusbhc_ca));
+	FLAWLESSCALL(config_cfdriver_attach(&ugenhc_cd));
+	FLAWLESSCALL(config_cfattach_attach("ugenhc", &ugenhc_ca));
 
 	FLAWLESSCALL(config_cfdriver_attach(&usb_cd));
 	FLAWLESSCALL(config_cfattach_attach("usb", &usb_ca));

Index: src/sys/rump/dev/wip/libums/ums_at_usb.c
diff -u src/sys/rump/dev/wip/libums/ums_at_usb.c:1.2 src/sys/rump/dev/wip/libums/ums_at_usb.c:1.3
--- src/sys/rump/dev/wip/libums/ums_at_usb.c:1.2	Wed Feb  3 21:18:38 2010
+++ src/sys/rump/dev/wip/libums/ums_at_usb.c	Wed Feb 10 02:26:24 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ums_at_usb.c,v 1.2 2010/02/03 21:18:38 pooka Exp $	*/
+/*	$NetBSD: ums_at_usb.c,v 1.3 2010/02/10 02:26:24 pooka Exp $	*/
 
 #include <sys/param.h>
 #include <sys/conf.h>
@@ -26,8 +26,8 @@
 	FLAWLESSCALL(config_cfdriver_attach(&mainbus_cd));
 	FLAWLESSCALL(config_cfattach_attach("mainbus", &mainbus_ca));
 
-	FLAWLESSCALL(config_cfdriver_attach(&rumpusbhc_cd));
-	FLAWLESSCALL(config_cfattach_attach("rumpusbhc", &rumpusbhc_ca));
+	FLAWLESSCALL(config_cfdriver_attach(&ugenhc_cd));
+	FLAWLESSCALL(config_cfattach_attach("ugenhc", &ugenhc_ca));
 
 	FLAWLESSCALL(config_cfdriver_attach(&usb_cd));
 	FLAWLESSCALL(config_cfattach_attach("usb", &usb_ca));

Index: src/sys/rump/dev/wip/libusbrum/rum_at_usb.c
diff -u src/sys/rump/dev/wip/libusbrum/rum_at_usb.c:1.2 src/sys/rump/dev/wip/libusbrum/rum_at_usb.c:1.3
--- src/sys/rump/dev/wip/libusbrum/rum_at_usb.c:1.2	Wed Feb  3 21:18:38 2010
+++ src/sys/rump/dev/wip/libusbrum/rum_at_usb.c	Wed Feb 10 02:26:24 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: rum_at_usb.c,v 1.2 2010/02/03 21:18:38 pooka Exp $	*/
+/*	$NetBSD: rum_at_usb.c,v 1.3 2010/02/10 02:26:24 pooka Exp $	*/
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -45,14 +45,14 @@
 
 CFDRIVER_DECL(rum, DV_IFNET, NULL);
 
-struct cfparent rumpusbhc_pspec = {
+struct cfparent ugenhc_pspec = {
 	"usbus",
-	"rumpusbhc",
+	"ugenhc",
 	DVUNIT_ANY
 };
 
 struct cfdata usb_cfdata[] = {
-	{ "usb", "usb", 0, FSTATE_STAR, NULL, 0, &rumpusbhc_pspec },
+	{ "usb", "usb", 0, FSTATE_STAR, NULL, 0, &ugenhc_pspec },
 };
 
 struct cfparent usb_pspec = {

Index: src/sys/rump/dev/wip/libwscons/component.c
diff -u src/sys/rump/dev/wip/libwscons/component.c:1.1 src/sys/rump/dev/wip/libwscons/component.c:1.2
--- src/sys/rump/dev/wip/libwscons/component.c:1.1	Mon Jan 11 02:12:51 2010
+++ src/sys/rump/dev/wip/libwscons/component.c	Wed Feb 10 02:26:24 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: component.c,v 1.1 2010/01/11 02:12:51 pooka Exp $	*/
+/*	$NetBSD: component.c,v 1.2 2010/02/10 02:26:24 pooka Exp $	*/
 
 /*
  * MACHINE GENERATED: DO NOT EDIT
@@ -380,9 +380,6 @@
 static const struct cfiattrdata * const mainbus_attrs[] = { &mainbuscf_iattrdata, NULL };
 CFDRIVER_DECL(mainbus, DV_DULL, mainbus_attrs);
 
-static const struct cfiattrdata * const rumpusbhc_attrs[] = { &usbuscf_iattrdata, NULL };
-CFDRIVER_DECL(rumpusbhc, DV_DULL, rumpusbhc_attrs);
-
 
 
 extern struct cfattach wskbd_ca;
@@ -395,7 +392,6 @@
 extern struct cfattach ukbd_ca;
 extern struct cfattach ums_ca;
 extern struct cfattach mainbus_ca;
-extern struct cfattach rumpusbhc_ca;
 
 /* locators */
 static int loc[18] = {

Added files:

Index: src/sys/rump/dev/wip/libugenhc/Makefile
diff -u /dev/null src/sys/rump/dev/wip/libugenhc/Makefile:1.1
--- /dev/null	Wed Feb 10 02:26:24 2010
+++ src/sys/rump/dev/wip/libugenhc/Makefile	Wed Feb 10 02:26:23 2010
@@ -0,0 +1,11 @@
+#	$NetBSD: Makefile,v 1.1 2010/02/10 02:26:23 pooka Exp $
+#
+
+LIB=	rumpdev_ugenhc
+
+SRCS=	ugenhc.c
+
+CPPFLAGS+=	-I${RUMPTOP}/librump/rumpkern
+
+.include <bsd.lib.mk>
+.include <bsd.klinks.mk>
Index: src/sys/rump/dev/wip/libugenhc/shlib_version
diff -u /dev/null src/sys/rump/dev/wip/libugenhc/shlib_version:1.1
--- /dev/null	Wed Feb 10 02:26:24 2010
+++ src/sys/rump/dev/wip/libugenhc/shlib_version	Wed Feb 10 02:26:23 2010
@@ -0,0 +1,4 @@
+#	$NetBSD: shlib_version,v 1.1 2010/02/10 02:26:23 pooka Exp $
+#
+major=0
+minor=0
Index: src/sys/rump/dev/wip/libugenhc/ugenhc.c
diff -u /dev/null src/sys/rump/dev/wip/libugenhc/ugenhc.c:1.1
--- /dev/null	Wed Feb 10 02:26:24 2010
+++ src/sys/rump/dev/wip/libugenhc/ugenhc.c	Wed Feb 10 02:26:23 2010
@@ -0,0 +1,995 @@
+/*	$NetBSD: ugenhc.c,v 1.1 2010/02/10 02:26:23 pooka Exp $	*/
+
+/*
+ * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lenn...@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This rump driver attaches ugen as a kernel usb host controller.
+ * It's still somewhat under the hammer ....
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.1 2010/02/10 02:26:23 pooka Exp $");
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#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>
+#include <dev/usb/usbhid.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usb_mem.h>
+#include <dev/usb/usbroothub_subr.h>
+
+#include <rump/rumpuser.h>
+
+#include "rump_private.h"
+#include "rump_dev_private.h"
+
+#define UGEN_NEPTS 16
+#define UGEN_EPT_CTRL 0 /* ugenx.00 is the control endpoint */
+
+struct ugenhc_softc {
+	struct usbd_bus sc_bus;
+	int sc_devnum;
+
+	int sc_ugenfd[UGEN_NEPTS];
+	int sc_fdmodes[UGEN_NEPTS];
+
+	int sc_port_status;
+	int sc_port_change;
+	int sc_addr;
+	int sc_conf;
+};
+
+static int	ugenhc_probe(struct device *, struct cfdata *, void *);
+static void	ugenhc_attach(struct device *, struct device *, void *);
+
+CFATTACH_DECL_NEW(ugenhc, sizeof(struct ugenhc_softc),
+	ugenhc_probe, ugenhc_attach, NULL, NULL);
+
+struct rusb_xfer {
+	struct usbd_xfer rusb_xfer;
+	int rusb_status; /* now this is a cheap trick */
+};
+#define RUSB(x) ((struct rusb_xfer *)x)
+
+#define UGENDEV_BASESTR "/dev/ugen"
+#define UGENDEV_BUFSIZE 32
+static void
+makeugendevstr(int devnum, int endpoint, char *buf)
+{
+
+	CTASSERT(UGENDEV_BUFSIZE > sizeof(UGENDEV_BASESTR)+sizeof("0.00")+1);
+	sprintf(buf, "%s%d.%02d", UGENDEV_BASESTR, devnum, endpoint);
+}
+
+/*
+ * Our fictional hubbie.
+ */
+
+static const usb_device_descriptor_t rumphub_udd = {
+	.bLength		= USB_DEVICE_DESCRIPTOR_SIZE,
+	.bDescriptorType	= UDESC_DEVICE,
+	.bDeviceClass		= UDCLASS_HUB,
+	.bDeviceSubClass	= UDSUBCLASS_HUB,
+	.bDeviceProtocol	= UDPROTO_FSHUB,
+	.bMaxPacketSize		= 64,
+	.bNumConfigurations	= 1,
+};
+
+static const usb_config_descriptor_t rumphub_ucd = {
+	.bLength		= USB_CONFIG_DESCRIPTOR_SIZE,
+	.bDescriptorType	= UDESC_CONFIG,
+	.wTotalLength		= { USB_CONFIG_DESCRIPTOR_SIZE
+				  + USB_INTERFACE_DESCRIPTOR_SIZE
+				  + USB_ENDPOINT_DESCRIPTOR_SIZE },
+	.bNumInterface		= 1,
+	.bmAttributes		= UC_SELF_POWERED | UC_ATTR_MBO,
+};
+/* XXX: spec says UC_ATTR_MBO is reserved and set to one.  required? */
+
+static const usb_interface_descriptor_t rumphub_uid = {
+	.bLength		= USB_INTERFACE_DESCRIPTOR_SIZE,
+	.bDescriptorType	= UDESC_INTERFACE,
+	.bInterfaceNumber	= 0,
+	.bNumEndpoints		= 1,
+	.bInterfaceClass	= UICLASS_HUB,
+	.bInterfaceSubClass	= UISUBCLASS_HUB,
+	.bInterfaceProtocol	= UIPROTO_FSHUB,
+};
+
+static const usb_endpoint_descriptor_t rumphub_epd = {
+	.bLength		= USB_ENDPOINT_DESCRIPTOR_SIZE,
+	.bDescriptorType	= UDESC_ENDPOINT,
+	.bmAttributes		= UE_INTERRUPT,
+	.wMaxPacketSize		= {64, 0},
+};
+
+static const usb_hub_descriptor_t rumphub_hdd = {
+	.bDescLength		= USB_HUB_DESCRIPTOR_SIZE,
+	.bDescriptorType	= UDESC_HUB,
+	.bNbrPorts		= 1,
+};
+
+static usbd_status
+rumpusb_root_ctrl_start(usbd_xfer_handle xfer)
+{
+	usb_device_request_t *req = &xfer->request;
+	struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
+	int len, totlen, value, curlen, err;
+	uint8_t *buf = NULL;
+
+	len = totlen = UGETW(req->wLength);
+	if (len)
+		buf = KERNADDR(&xfer->dmabuf, 0);
+	value = UGETW(req->wValue);
+
+#define C(x,y) ((x) | ((y) << 8))
+	switch(C(req->bRequest, req->bmRequestType)) {
+
+	case C(UR_GET_CONFIG, UT_READ_DEVICE):
+		if (len > 0) {
+			*buf = sc->sc_conf;
+			totlen = 1;
+		}
+		break;
+
+	case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
+		switch (value >> 8) {
+		case UDESC_DEVICE:
+			totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
+			memcpy(buf, &rumphub_udd, totlen);
+			break;
+
+		case UDESC_CONFIG:
+			totlen = 0;
+			curlen = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
+			memcpy(buf, &rumphub_ucd, curlen);
+			len -= curlen;
+			buf += curlen;
+			totlen += curlen;
+
+			curlen = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
+			memcpy(buf, &rumphub_uid, curlen);
+			len -= curlen;
+			buf += curlen;
+			totlen += curlen;
+
+			curlen = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
+			memcpy(buf, &rumphub_epd, curlen);
+			len -= curlen;
+			buf += curlen;
+			totlen += curlen;
+			break;
+
+		case UDESC_STRING:
+#define sd ((usb_string_descriptor_t *)buf)
+			switch (value & 0xff) {
+			case 0: /* Language table */
+				totlen = usb_makelangtbl(sd, len);
+				break;
+			case 1: /* Vendor */
+				totlen = usb_makestrdesc(sd, len, "rod nevada");
+				break;
+			case 2: /* Product */
+				totlen = usb_makestrdesc(sd, len,
+				    "RUMPUSBHC root hub");
+				break;
+			}
+#undef sd
+			break;
+
+		default:
+			panic("unhandled read device request");
+			break;
+		}
+		break;
+
+	case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
+		if (value >= USB_MAX_DEVICES) {
+			err = USBD_IOERROR;
+			goto ret;
+		}
+		sc->sc_addr = value;
+		break;
+
+	case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
+		if (value != 0 && value != 1) {
+			err = USBD_IOERROR;
+			goto ret;
+		}
+		sc->sc_conf = value;
+		break;
+
+	case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
+		switch (value) {
+		case UHF_PORT_RESET:
+			sc->sc_port_change |= UPS_C_PORT_RESET;
+			break;
+		case UHF_PORT_POWER:
+			break;
+		default:
+			panic("unhandled");
+		}
+		break;
+
+	case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
+		sc->sc_port_change &= ~value;
+		break;
+
+	case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
+		totlen = min(len, USB_HUB_DESCRIPTOR_SIZE);
+		memcpy(buf, &rumphub_hdd, totlen);
+		break;
+
+	case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
+		/* huh?  other hc's do this */
+		memset(buf, 0, len);
+		totlen = len;
+		break;
+
+	case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
+		{
+		usb_port_status_t ps;
+
+		USETW(ps.wPortStatus, sc->sc_port_status);
+		USETW(ps.wPortChange, sc->sc_port_change);
+		totlen = min(len, sizeof(ps));
+		memcpy(buf, &ps, totlen);
+		break;
+		}
+
+	default:
+		panic("unhandled request");
+		break;
+	}
+	err = USBD_NORMAL_COMPLETION;
+	xfer->actlen = totlen;
+
+ret:
+	xfer->status = err;
+	usb_transfer_complete(xfer);
+	return (USBD_IN_PROGRESS);
+}
+
+static usbd_status
+rumpusb_root_ctrl_transfer(usbd_xfer_handle xfer)
+{
+	usbd_status err;
+
+	err = usb_insert_transfer(xfer);
+	if (err)
+		return (err);
+
+	return (rumpusb_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+}
+
+static void
+rumpusb_root_ctrl_abort(usbd_xfer_handle xfer)
+{
+
+}
+
+static void
+rumpusb_root_ctrl_close(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_root_ctrl_cleartoggle(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_root_ctrl_done(usbd_xfer_handle xfer)
+{
+
+}
+
+static const struct usbd_pipe_methods rumpusb_root_ctrl_methods = {
+	.transfer =	rumpusb_root_ctrl_transfer,
+	.start =	rumpusb_root_ctrl_start,
+	.abort =	rumpusb_root_ctrl_abort,
+	.close =	rumpusb_root_ctrl_close,
+	.cleartoggle =	rumpusb_root_ctrl_cleartoggle,
+	.done =		rumpusb_root_ctrl_done,
+};
+
+static usbd_status
+rumpusb_device_ctrl_start(usbd_xfer_handle xfer)
+{
+	usb_device_request_t *req = &xfer->request;
+	struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
+	uint8_t *buf = NULL;
+	int len, totlen;
+	int value;
+	int err = 0;
+	int ru_error, mightfail = 0;
+
+	len = totlen = UGETW(req->wLength);
+	if (len)
+		buf = KERNADDR(&xfer->dmabuf, 0);
+	value = UGETW(req->wValue);
+
+#define C(x,y) ((x) | ((y) << 8))
+	switch(C(req->bRequest, req->bmRequestType)) {
+	case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
+		switch (value>>8) {
+		case UDESC_DEVICE:
+			{
+			usb_device_descriptor_t uddesc;
+			totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
+			memset(buf, 0, totlen);
+			if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
+			    USB_GET_DEVICE_DESC, &uddesc, &ru_error) == -1)
+				panic("%d", ru_error);
+			memcpy(buf, &uddesc, totlen);
+			}
+
+			break;
+		case UDESC_CONFIG:
+			{
+			struct usb_full_desc ufdesc;
+			ufdesc.ufd_config_index = 0;
+			ufdesc.ufd_size = len;
+			ufdesc.ufd_data = buf;
+			memset(buf, 0, totlen);
+			if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
+			    USB_GET_FULL_DESC, &ufdesc, &ru_error) == -1)
+				panic("%d", ru_error);
+			totlen = len;
+			}
+			break;
+
+		case UDESC_STRING:
+			{
+			struct usb_device_info udi;
+
+			if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
+			    USB_GET_DEVICEINFO, &udi, &ru_error) == -1) {
+				printf("ugenhc: get dev info failed: %d\n",
+				    ru_error);
+				err = USBD_IOERROR;
+				goto ret;
+			}
+
+			switch (value & 0xff) {
+#define sd ((usb_string_descriptor_t *)buf)
+			case 0: /* language table */
+				break;
+			case 1: /* vendor */
+				totlen = usb_makestrdesc(sd, len,
+				    udi.udi_vendor);
+				break;
+			case 2: /* product */
+				totlen = usb_makestrdesc(sd, len,
+				    udi.udi_product);
+				break;
+			}
+#undef sd
+			}
+			break;
+
+		default:
+			panic("not handled");
+		}
+		break;
+
+	case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
+		/* ignored, ugen won't let us */
+		break;
+
+	case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
+		/* ignored, ugen won't let us .... REALLY? */
+		break;
+
+	case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
+		{
+		struct usb_alt_interface uai;
+
+		totlen = 0;
+		uai.uai_interface_index = UGETW(req->wIndex);
+		uai.uai_alt_no = value;
+		if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
+		    USB_SET_ALTINTERFACE, &uai, &ru_error) == -1) {
+			printf("ugenhc: set alt interface failed: %d\n",
+			    ru_error);
+			err = USBD_IOERROR;
+			goto ret;
+		}
+		break;
+		}
+
+	/*
+	 * This request might fail unknown reasons.  "EIO" doesn't
+	 * give much help, and debugging the host ugen would be
+	 * necessary.  However, since it doesn't seem to really
+	 * affect anything, just let it fail for now.
+	 */
+	case C(0x00, UT_WRITE_CLASS_INTERFACE):
+		mightfail = 1;
+		/*FALLTHROUGH*/
+
+	/*
+	 * XXX: don't wildcard these yet.  I want to better figure
+	 * out what to trap here.  This is kinda silly, though ...
+	 */
+
+	case C(0x01, UT_WRITE_VENDOR_DEVICE):
+	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):
+	case C(0x01, UT_READ_CLASS_INTERFACE):
+	case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
+	case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
+	case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
+	case C(UR_GET_DESCRIPTOR, UT_READ_INTERFACE):
+	case C(0xff, UT_WRITE_CLASS_INTERFACE):
+	case C(0x20, UT_WRITE_CLASS_INTERFACE):
+	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(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
+	case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE):
+	case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
+		{
+		struct usb_ctl_request ucr;
+
+		memcpy(&ucr.ucr_request, req, sizeof(ucr.ucr_request));
+		ucr.ucr_data = buf;
+		if (rumpuser_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
+		    USB_DO_REQUEST, &ucr, &ru_error) == -1) {
+			if (!mightfail)
+				panic("request failed: %d", ru_error);
+			else
+				err = ru_error;
+		}
+		}
+		break;
+
+	default:
+		panic("unhandled request");
+		break;
+	}
+	xfer->actlen = totlen;
+	err = USBD_NORMAL_COMPLETION;
+
+ ret:
+	xfer->status = err;
+	usb_transfer_complete(xfer);
+	return (USBD_IN_PROGRESS);
+}
+
+static usbd_status
+rumpusb_device_ctrl_transfer(usbd_xfer_handle xfer)
+{
+	usbd_status err;
+
+	err = usb_insert_transfer(xfer);
+	if (err)
+		return (err);
+
+	return (rumpusb_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+}
+
+static void
+rumpusb_device_ctrl_abort(usbd_xfer_handle xfer)
+{
+
+}
+
+static void
+rumpusb_device_ctrl_close(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_device_ctrl_cleartoggle(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_device_ctrl_done(usbd_xfer_handle xfer)
+{
+
+}
+
+static const struct usbd_pipe_methods rumpusb_device_ctrl_methods = {
+	.transfer =	rumpusb_device_ctrl_transfer,
+	.start =	rumpusb_device_ctrl_start,
+	.abort =	rumpusb_device_ctrl_abort,
+	.close =	rumpusb_device_ctrl_close,
+	.cleartoggle =	rumpusb_device_ctrl_cleartoggle,
+	.done =		rumpusb_device_ctrl_done,
+};
+
+struct intrent {
+	usbd_xfer_handle xfer;
+	LIST_ENTRY(intrent) entries;
+};
+
+static LIST_HEAD(, intrent) intrlist = LIST_HEAD_INITIALIZER(intrlist);
+
+static void
+rhscintr(void)
+{
+	struct intrent *ie, *ie_next;
+	usbd_xfer_handle xfer;
+
+	for (ie = LIST_FIRST(&intrlist); ie; ie = ie_next) {
+		xfer = ie->xfer;
+		xfer->actlen = xfer->length;
+		xfer->status = USBD_NORMAL_COMPLETION;
+		usb_transfer_complete(xfer);
+
+		ie_next = LIST_NEXT(ie, entries);
+		LIST_REMOVE(ie, entries);
+		kmem_free(ie, sizeof(*ie));
+	}
+}
+
+static usbd_status
+rumpusb_root_intr_start(usbd_xfer_handle xfer)
+{
+	struct intrent *ie;
+
+	ie = kmem_alloc(sizeof(*ie), KM_SLEEP);
+	ie->xfer = xfer;
+	LIST_INSERT_HEAD(&intrlist, ie, entries);
+
+	return (USBD_IN_PROGRESS);
+}
+
+static usbd_status
+rumpusb_root_intr_transfer(usbd_xfer_handle xfer)
+{
+	usbd_status err;
+
+	err = usb_insert_transfer(xfer);
+	if (err)
+		return (err);
+
+	return (rumpusb_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
+}
+
+static void
+rumpusb_root_intr_abort(usbd_xfer_handle xfer)
+{
+
+}
+
+static void
+rumpusb_root_intr_close(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_root_intr_cleartoggle(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_root_intr_done(usbd_xfer_handle xfer)
+{
+
+}
+
+static const struct usbd_pipe_methods rumpusb_root_intr_methods = {
+	.transfer =	rumpusb_root_intr_transfer,
+	.start =	rumpusb_root_intr_start,
+	.abort =	rumpusb_root_intr_abort,
+	.close =	rumpusb_root_intr_close,
+	.cleartoggle =	rumpusb_root_intr_cleartoggle,
+	.done =		rumpusb_root_intr_done,
+};
+
+static usbd_status
+rumpusb_device_bulk_start(usbd_xfer_handle xfer)
+{
+	struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
+	ssize_t n;
+	ssize_t done;
+	bool isread;
+	int len, error, endpt;
+	uint8_t *buf;
+	int xfererr = 0;
+	int val;
+
+	endpt = xfer->pipe->endpoint->edesc->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;
+
+	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);
+			n = rumpuser_read(sc->sc_ugenfd[endpt],
+			    buf+done, len-done, &error);
+			if (n == -1) {
+				if (error == ETIMEDOUT)
+					continue;
+				n = 0;
+				xfer->status = USBD_IOERROR;
+				goto out;
+			}
+			done += n;
+			if (done == len)
+				break;
+		} else {
+			n = rumpuser_write(sc->sc_ugenfd[endpt],
+			    buf, len, &error);
+			done = n;
+			if (done == len)
+				break;
+			else
+				panic("short write");
+		}
+
+		if (xfer->flags & USBD_SHORT_XFER_OK)
+			break;
+	}
+
+	if (RUSB(xfer)->rusb_status == 0) {
+		xfer->actlen = done;
+		xfer->status = USBD_NORMAL_COMPLETION;
+		/* override */
+		if (xfererr) {
+			printf("err!\n");
+			xfer->status = xfererr;
+		}
+	} else {
+		xfer->status = USBD_CANCELLED;
+		RUSB(xfer)->rusb_status = 2;
+	}
+ out:
+	val = 0;
+	rumpuser_ioctl(sc->sc_ugenfd[endpt], USB_SET_SHORT_XFER, &val, &error);
+	usb_transfer_complete(xfer);
+	return (USBD_IN_PROGRESS);
+}
+
+static void
+doxfer_kth(void *arg)
+{
+	usbd_xfer_handle xfer = arg;
+
+	do {
+		rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
+	} while (!SIMPLEQ_EMPTY(&xfer->pipe->queue));
+	kthread_exit(0);
+}
+
+static usbd_status
+rumpusb_device_bulk_transfer(usbd_xfer_handle xfer)
+{
+	usbd_status err;
+
+	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;
+
+		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 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
+rumpusb_device_bulk_close(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_device_bulk_cleartoggle(usbd_pipe_handle pipe)
+{
+
+}
+
+static void
+rumpusb_device_bulk_done(usbd_xfer_handle xfer)
+{
+
+}
+
+static const struct usbd_pipe_methods rumpusb_device_bulk_methods = {
+	.transfer =	rumpusb_device_bulk_transfer,
+	.start =	rumpusb_device_bulk_start,
+	.abort =	rumpusb_device_bulk_abort,
+	.close =	rumpusb_device_bulk_close,
+	.cleartoggle =	rumpusb_device_bulk_cleartoggle,
+	.done =		rumpusb_device_bulk_done,
+};
+
+static const struct usbd_pipe_methods rumpusb_device_intr_methods = {
+	.transfer =	rumpusb_root_intr_transfer,
+	.start =	rumpusb_root_intr_start,
+	.abort =	rumpusb_root_intr_abort,
+	.close =	rumpusb_root_intr_close,
+	.cleartoggle =	rumpusb_root_intr_cleartoggle,
+	.done =		rumpusb_root_intr_done,
+};
+
+static usbd_status
+ugenhc_open(struct usbd_pipe *pipe)
+{
+	usbd_device_handle dev = pipe->device;
+	struct ugenhc_softc *sc = dev->bus->hci_private;
+	usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
+	u_int8_t addr = dev->address;
+	u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
+	char buf[UGENDEV_BUFSIZE];
+	int endpt, oflags, error;
+	int fd, val;
+
+	sc->sc_port_status = UPS_CURRENT_CONNECT_STATUS
+	    | UPS_PORT_ENABLED | UPS_PORT_POWER;
+	sc->sc_port_change = UPS_C_CONNECT_STATUS;
+
+	if (addr == sc->sc_addr) {
+		switch (xfertype) {
+		case UE_CONTROL:
+			pipe->methods = &rumpusb_root_ctrl_methods;
+			break;
+		case UE_INTERRUPT:
+			pipe->methods = &rumpusb_root_intr_methods;
+			break;
+		default:
+			panic("%d not supported", xfertype);
+			break;
+		}
+	} else {
+		switch (xfertype) {
+		case UE_CONTROL:
+			pipe->methods = &rumpusb_device_ctrl_methods;
+			break;
+		case UE_INTERRUPT:
+		case UE_BULK:
+			pipe->methods = &rumpusb_device_bulk_methods;
+			endpt = pipe->endpoint->edesc->bEndpointAddress;
+			if (UE_GET_DIR(endpt) == UE_DIR_IN) {
+				oflags = O_RDONLY;
+			} else {
+				oflags = O_WRONLY;
+			}
+			endpt = UE_GET_ADDR(endpt);
+
+			if (sc->sc_fdmodes[endpt] == oflags
+			    || sc->sc_fdmodes[endpt] == O_RDWR)
+				break;
+
+			if (sc->sc_fdmodes[endpt] != -1) {
+				/* XXX: closing from under someone? */
+				rumpuser_close(sc->sc_ugenfd[endpt], &error);
+				oflags = O_RDWR;
+			}
+
+			makeugendevstr(sc->sc_devnum, endpt, buf);
+			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;
+		default:
+			panic("%d not supported", xfertype);
+			break;
+
+		}
+	}
+	return 0;
+}
+
+static void
+ugenhc_softint(void *arg)
+{
+
+}
+
+static void
+ugenhc_poll(struct usbd_bus *ubus)
+{
+
+}
+
+static usbd_status
+ugenhc_allocm(struct usbd_bus *bus, usb_dma_t *dma, uint32_t size)
+{
+	struct ugenhc_softc *sc = bus->hci_private;
+
+	return usb_allocmem(&sc->sc_bus, size, 0, dma);
+}
+
+static void
+ugenhc_freem(struct usbd_bus *ubus, usb_dma_t *udma)
+{
+
+}
+
+static struct usbd_xfer *
+ugenhc_allocx(struct usbd_bus *bus)
+{
+	usbd_xfer_handle xfer;
+
+	xfer = kmem_zalloc(sizeof(struct usbd_xfer), KM_SLEEP);
+	xfer->busy_free = XFER_BUSY;
+
+	return xfer;
+}
+
+static void
+ugenhc_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
+{
+
+	kmem_free(xfer, sizeof(struct usbd_xfer));
+}
+
+struct ugenhc_pipe {
+	struct usbd_pipe pipe;
+};
+
+static const struct usbd_bus_methods ugenhc_bus_methods = {
+	.open_pipe =	ugenhc_open,
+	.soft_intr =	ugenhc_softint,
+	.do_poll =	ugenhc_poll,
+	.allocm = 	ugenhc_allocm,
+	.freem = 	ugenhc_freem,
+	.allocx = 	ugenhc_allocx,
+	.freex =	ugenhc_freex,
+};
+
+static int
+ugenhc_probe(struct device *parent, struct cfdata *match, void *aux)
+{
+	char buf[UGENDEV_BUFSIZE];
+	int fd, error;
+
+	makeugendevstr(match->cf_unit, 0, buf);
+	fd = rumpuser_open(buf, O_RDWR, &error);
+	if (fd == -1)
+		return 0;
+
+	rumpuser_close(fd, &error);
+	return 1;
+}
+
+static void
+ugenhc_attach(struct device *parent, struct device *self, void *aux)
+{
+	struct mainbus_attach_args *maa = aux;
+	struct ugenhc_softc *sc = device_private(self);
+	char buf[UGENDEV_BUFSIZE];
+	int error;
+
+	aprint_normal("\n");
+
+	memset(sc, 0, sizeof(*sc));
+	memset(&sc->sc_ugenfd, -1, sizeof(sc->sc_ugenfd));
+	memset(&sc->sc_fdmodes, -1, sizeof(sc->sc_fdmodes));
+
+	sc->sc_bus.usbrev = USBREV_2_0;
+	sc->sc_bus.methods = &ugenhc_bus_methods;
+	sc->sc_bus.hci_private = sc;
+	sc->sc_bus.pipe_size = sizeof(struct ugenhc_pipe);
+	sc->sc_devnum = maa->maa_unit;
+
+	makeugendevstr(sc->sc_devnum, 0, buf);
+	sc->sc_ugenfd[UGEN_EPT_CTRL] = rumpuser_open(buf, O_RDWR, &error);
+	if (error)
+		panic("ugenhc_attach: failed to open ctrl ept %s\n", buf);
+
+	config_found(self, &sc->sc_bus, usbctlprint);
+
+	/* whoah, like extreme XXX, bro */
+	rhscintr();
+	if (!rump_threads)
+		config_pending_decr();
+}

Reply via email to