shithub: riscv

Download patch

ref: 1404cc50772688f05ab65a9eb2d5c8d4b85b0375
parent: a6e3c9fd83e72e5c911e83f763e77ab6605a17d2
author: cinap_lenrek <cinap_lenrek@localhost>
date: Fri Aug 26 01:24:55 EDT 2011

nusb: fix documentation, cleanup, remove /sys/src/cmd/usb

--- a/rc/bin/usbeject
+++ /dev/null
@@ -1,41 +1,0 @@
-#!/bin/rc
-# usbeject - unmount usb disks given as arguments
-#	unmount all of them if no arguments given
-rfork e
-disk = ()
-mtpt = /n/usb
-
-test -e /dev/fs/ctl || bind -b '#k' /dev >[2]/dev/null
-
-test -e /dev/usb || bind -a '#u' /dev || {
-	echo $0: no '#u/usb' >[1=2]
-	exit nousb
-}
-test -e /dev/usbdctl || mount -a /srv/usb /dev || {
-	echo $0: cannot mount /srv/usb >[1=2]
-	exit nousbd
-}
-
-disks=()
-mtpt=()
-switch ($#*) {
-case 0
-	disks=`{ls -pd /n/sdU*}
-case *
-	disks=()
-	for (a) {
-		if(~ $a sd??)
-			disk=`{ls -pd /n/^$*^*}
-		if not
-			disk=$a
-		disks=($disks $disk)
-	}
-}
-if (~ $disks '''sdU*''')
-	exit ''
-for (disk in $disks) {
-	unmount /n/$disk >[2]/dev/null && echo $disk unmounted
-	if (test -e /dev/fs/ctl)
-		echo del $disk^parts/^'*' >/dev/fs/ctl >[2]/dev/null
-}
-exit ''
--- /dev/null
+++ b/sys/man/2/nusb
@@ -1,0 +1,386 @@
+.TH NUSB 2
+.SH NAME
+usbcmd,
+classname,
+closedev,
+configdev,
+devctl,
+getdev,
+loaddevstr,
+opendev,
+opendevdata,
+openep,
+unstall,
+class,
+subclass,
+proto,
+CSP \- USB device driver library
+.SH SYNOPSIS
+.EX
+.ta 8n +8n +8n +8n +8n +8n +8n
+#include <u.h>
+#include <libc.h>
+#include "../lib/usb.h"
+.sp 0.3v
+struct Dev {
+	Ref;
+	char*	dir;		/* path for the endpoint dir */
+	int	id;		/* usb id for device or ep. number */
+	int	dfd;		/* descriptor for the data file */
+	int	cfd;		/* descriptor for the control file */
+	int	maxpkt;		/* cached from usb description */
+	Usbdev*	usb;		/* USB description */
+	void*	aux;		/* for the device driver */
+	void	(*free)(void*);	/* idem. to release aux */
+};
+.sp 0.3v
+struct Usbdev {
+	ulong	csp;		/* USB class/subclass/proto */
+	int	vid;		/* vendor id */
+	int	did;		/* product (device) id */
+	int	dno;		/* device release number */
+	char*	vendor;
+	char*	product;
+	char*	serial;
+	int	ls;		/* low speed */
+	int	class;		/* from descriptor */
+	int	nconf;		/* from descriptor */
+	Conf*	conf[Nconf];	/* configurations */
+	Ep*	ep[Nep];	/* all endpoints in device */
+	Desc*	ddesc[Nddesc];	/* (raw) device specific descriptors */
+};
+.sp 0.3v
+struct Ep {
+	uchar	addr;		/* endpt address */
+	uchar	dir;		/* direction, Ein/Eout */
+	uchar	type;		/* Econtrol, Eiso, Ebulk, Eintr */
+	uchar	isotype;	/* Eunknown, Easync, Eadapt, Esync */
+	int	id;
+	int	maxpkt;		/* max. packet size */
+	Conf*	conf;		/* the endpoint belongs to */
+	Iface*	iface;		/* the endpoint belongs to */
+};
+.sp 0.3v
+struct Altc {
+	int	attrib;
+	int	interval;
+	void*	aux;		/* for the driver program */
+};
+.sp 0.3v
+struct Iface {
+	int 	id;		/* interface number */
+	ulong	csp;		/* USB class/subclass/proto */
+	Altc*	altc[Naltc];
+	Ep*	ep[Nep];
+	void*	aux;		/* for the driver program */
+};
+.sp 0.3v
+struct Conf {
+	int	cval;		/* value for set configuration */
+	int	attrib;
+	int	milliamps;	/* maximum power in this config. */
+	Iface*	iface[Niface];	/* up to 16 interfaces */
+};
+.sp 0.3v
+struct Desc {
+	Conf*	conf;		/* where this descriptor was read */
+	Iface*	iface;		/* last iface before desc in conf. */
+	Ep*	ep;		/* last endpt before desc in conf. */
+	Altc*	altc;		/* last alt.c. before desc in conf. */
+	DDesc	data;		/* unparsed standard USB descriptor */
+};
+.sp 0.3v
+struct DDesc {
+	uchar	bLength;
+	uchar	bDescriptorType;
+	uchar	bbytes[1];
+	/* extra bytes allocated here to keep the rest of it */
+};
+.sp 0.3v
+#define Class(csp)	((csp)&0xff)
+#define Subclass(csp)	(((csp)>>8)&0xff)
+#define Proto(csp)	(((csp)>>16)&0xff)
+#define CSP(c, s, p)	((c) | ((s)<<8) | ((p)<<16))
+#define	GET2(p)		...
+#define	PUT2(p,v)	...
+#define	GET4(p)		...
+#define	PUT4(p,v)	...
+#define dprint	 if(usbdebug)fprint
+#define ddprint if(usbdebug > 1)fprint
+.sp 0.3v
+int	Ufmt(Fmt *f);
+char*	classname(int c);
+void	closedev(Dev *d);
+int	configdev(Dev *d);
+int	devctl(Dev *dev, char *fmt, ...);
+void*	emallocz(ulong size, int zero);
+char*	estrdup(char *s);
+char*	hexstr(void *a, int n);
+char*	loaddevstr(Dev *d, int sid);
+Dev*	opendev(char *fn);
+int	opendevdata(Dev *d, int mode);
+Dev*	openep(Dev *d, int id);
+int	unstall(Dev *dev, Dev *ep, int dir);
+int	usbcmd(Dev *d, int type, int req,
+		int value, int index, uchar *data, int count);
+Dev*	getdev(int id);
+.sp 0.3v
+extern int usbdebug;	/* more messages for bigger values */
+.EE
+.SH DESCRIPTION
+This library provides convenience structures and functions to write
+USB device drivers.
+It is not intended for user programs using USB devices.
+See
+.IR usb (3)
+for a description of the interfaces provided for that purpose.
+.PP
+Usb drivers rely on
+.IR usb (3)
+to perform I/O through USB as well as on
+.IR usbd
+to perform the initial configuration for the device's setup endpoint.
+The rest of the work is up to the driver and is where this library may help.
+.PP
+An endpoint as provided by
+.IR usb (3)
+is represented by a
+.B Dev
+data structure.
+The setup endpoint for a
+device represents the USB device, because it is the means to
+configure and operate the device.
+This structure is reference counted.
+Functions creating
+.B Devs
+adjust the number of references to one, initially.
+The driver is free to call
+.IR incref
+(in
+.IR lock (2))
+to add references and
+.I closedev
+to drop references (and release resources when the last one vanishes).
+As an aid to the driver, the field
+.B aux
+may keep driver-specific data and the function
+.B free
+will be called (if not null) to release the
+.B aux
+structure when the reference count goes down to zero.
+.PP
+.I Dev.dir
+holds the path for the endpoint's directory.
+.PP
+The field
+.B id
+keeps the device number for setup endpoints and the endpoint number
+for all other endpoints.
+For example, it would be
+.B 3
+for
+.B /dev/usb/ep3.0
+and
+.B 1
+for
+.BR /dev/usb/ep3.1 .
+It is easy to remember this because the former is created to operate
+on the device, while the later has been created as a particular endpoint
+to perform I/O.
+.PP
+Fields
+.B dfd
+and
+.B cfd
+keep the data and
+control file descriptors, respectively.
+When a
+.B Dev
+is created the control file is open, initially.
+Opening the data
+file requires calling
+.I opendevdata
+with the appropriate mode.
+.PP
+When the device configuration information has been loaded (see below),
+.B maxpkt
+holds the maximum packet size (in bytes) for the endpoint and
+.B usb
+keeps the rest of the USB information.
+.PP
+Most of the information in
+.B usb
+comes from parsing
+various device and configuration descriptors provided by the device,
+by calling one of the functions described later.
+Only descriptors unknown
+to the library are kept unparsed at
+.B usb.ddesc
+as an aid for the driver
+(which should know how to parse them and what to do with the information).
+.SS Configuration
+.PP
+.I Opendev
+creates a
+.B Dev
+for the endpoint with directory
+.IR fn .
+Usually, the endpoint is a setup endpoint representing a device. The endpoint
+control file is open, but the data file is not. The USB description is void.
+In most cases drivers call
+.I startdevs
+and
+.I openep
+and do not call this function directly.
+.PP
+.I Configdev
+opens the data file for the device supplied and
+loads and parses its configuration information.
+After calling it, the device is ready for I/O and the USB description in
+.B Dev.usb
+is valid.
+.PP
+Control requests for an endpoint may be written by calling
+.I devctl
+in the style of
+.IR print (2).
+It is better not to call
+.I print
+directly because the control request should be issued as a single
+.I write
+system call.
+See
+.IR usb (3)
+for a list of available control requests (not to be confused with
+USB control transfers performed on a control endpoint).
+.SS Input/Output
+.I Opendevdata
+opens the data file for the device according to the given
+.IR mode .
+The mode must match that of the endpoint, doing otherwise is considered
+an error.
+Actual I/O is performed by reading/writing the descriptor kept in the
+.B dfd
+field of
+.BR Dev .
+.PP
+For control endpoints,
+it is not necessary to call
+.I read
+and
+.I write
+directly.
+Instead,
+.I usbcmd
+issues a USB control request to the device
+.I d
+(not to be confused with a
+.IR usb (3)
+control request sent to its control file).
+.I Usbcmd
+retries the control request several times upon failure because some devices
+require it.
+The format of requests is fixed per the USB standard:
+.I type
+is the type of request and
+.I req
+identifies the request. Arguments
+.I value
+and
+.I index
+are parameters to the request and the last two arguments,
+.I data
+and
+.IR count ,
+are similar to
+.I read
+and
+.I write
+arguments.
+However,
+.I data
+may be
+.B nil
+if no transfer (other than the control request) has to take place.
+The library header file includes numerous symbols defined to help writing
+the type and arguments for a request.
+.PP
+The return value from
+.I usbcmd
+is the number of bytes transferred, zero to indicate a stall and -1
+to indicate an error.
+.PP
+A common request is to unstall an endpoint that has been stalled
+due to some reason by the device (eg., when read or write indicate
+a count of zero bytes read or written on the endpoint). The function
+.I unstall
+does this.
+It is given the device that stalled the endpoint,
+.IR dev ,
+the
+stalled endpoint,
+.IR ep ,
+and the direction of the stall (one of
+.B Ein
+or
+.BR Eout ).
+The function takes care of notifying the device of the unstall as well
+as notifying the kernel.
+.SS Tools
+.I Class
+returns the class part of the number given, representing a CSP.
+.I Subclass
+does the same for the device subclass and
+.I Proto
+for the protocol.
+The counterpart is
+.IR CSP ,
+which builds a CSP from the device class, subclass, and protocol.
+For some classes,
+.I classname
+knows the name (for those with constants in the library header file).
+.PP
+The macros
+.I GET2
+and
+.I PUT2
+get and put a (little-endian) two-byte value and are useful to
+parse descriptors and replies for control requests.
+.PP
+Functions
+.I emallocz
+and
+.I estrdup
+are similar to
+.I mallocz
+and
+.I strdup
+but abort program operation upon failure.
+.PP
+The function
+.I Ufmt
+is a format routine suitable for
+.IR fmtinstall (2)
+to print a
+.B Dev
+data structure.
+The auxiliary
+.I hexstr
+returns a string representing a dump (in hexadecimal) of
+.I n
+bytes starting at
+.IR a .
+The string is allocated using
+.IR malloc (2)
+and memory must be released by the caller.
+.PP
+.I Loaddevstr
+returns the string obtained by reading the device string descriptor number
+.IR sid .
+.SH SOURCE
+.B /sys/src/cmd/nusb/lib
+.SH "SEE ALSO"
+.IR usb (3),
+.IR nusb (4).
+.SH BUGS
+Not heavily exercised yet.
--- a/sys/man/2/usb
+++ /dev/null
@@ -1,460 +1,0 @@
-.TH USB 2
-.SH NAME
-usbcmd,
-classname,
-closedev,
-configdev,
-devctl,
-finddevs,
-loaddevstr,
-matchdevcsp,
-opendev,
-opendevdata,
-openep,
-startdevs,
-unstall,
-class,
-subclass,
-proto,
-CSP \- USB device driver library
-.SH SYNOPSIS
-.EX
-.ta 8n +8n +8n +8n +8n +8n +8n
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../lib/usb.h"
-.sp 0.3v
-struct Dev {
-	Ref;
-	char*	dir;		/* path for the endpoint dir */
-	int	id;		/* usb id for device or ep. number */
-	int	dfd;		/* descriptor for the data file */
-	int	cfd;		/* descriptor for the control file */
-	int	maxpkt;		/* cached from usb description */
-	Usbdev*	usb;		/* USB description */
-	void*	aux;		/* for the device driver */
-	void	(*free)(void*);	/* idem. to release aux */
-};
-.sp 0.3v
-struct Usbdev {
-	ulong	csp;		/* USB class/subclass/proto */
-	int	vid;		/* vendor id */
-	int	did;		/* product (device) id */
-	int	dno;		/* device release number */
-	char*	vendor;
-	char*	product;
-	char*	serial;
-	int	ls;		/* low speed */
-	int	class;		/* from descriptor */
-	int	nconf;		/* from descriptor */
-	Conf*	conf[Nconf];	/* configurations */
-	Ep*	ep[Nep];	/* all endpoints in device */
-	Desc*	ddesc[Nddesc];	/* (raw) device specific descriptors */
-};
-.sp 0.3v
-struct Ep {
-	uchar	addr;		/* endpt address */
-	uchar	dir;		/* direction, Ein/Eout */
-	uchar	type;		/* Econtrol, Eiso, Ebulk, Eintr */
-	uchar	isotype;	/* Eunknown, Easync, Eadapt, Esync */
-	int	id;
-	int	maxpkt;		/* max. packet size */
-	Conf*	conf;		/* the endpoint belongs to */
-	Iface*	iface;		/* the endpoint belongs to */
-};
-.sp 0.3v
-struct Altc {
-	int	attrib;
-	int	interval;
-	void*	aux;		/* for the driver program */
-};
-.sp 0.3v
-struct Iface {
-	int 	id;		/* interface number */
-	ulong	csp;		/* USB class/subclass/proto */
-	Altc*	altc[Naltc];
-	Ep*	ep[Nep];
-	void*	aux;		/* for the driver program */
-};
-.sp 0.3v
-struct Conf {
-	int	cval;		/* value for set configuration */
-	int	attrib;
-	int	milliamps;	/* maximum power in this config. */
-	Iface*	iface[Niface];	/* up to 16 interfaces */
-};
-.sp 0.3v
-struct Desc {
-	Conf*	conf;		/* where this descriptor was read */
-	Iface*	iface;		/* last iface before desc in conf. */
-	Ep*	ep;		/* last endpt before desc in conf. */
-	Altc*	altc;		/* last alt.c. before desc in conf. */
-	DDesc	data;		/* unparsed standard USB descriptor */
-};
-.sp 0.3v
-struct DDesc {
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	bbytes[1];
-	/* extra bytes allocated here to keep the rest of it */
-};
-.sp 0.3v
-#define Class(csp)	((csp)&0xff)
-#define Subclass(csp)	(((csp)>>8)&0xff)
-#define Proto(csp)	(((csp)>>16)&0xff)
-#define CSP(c, s, p)	((c) | ((s)<<8) | ((p)<<16))
-#define	GET2(p)		...
-#define	PUT2(p,v)	...
-#define	GET4(p)		...
-#define	PUT4(p,v)	...
-#define dprint	 if(usbdebug)fprint
-#define ddprint if(usbdebug > 1)fprint
-.sp 0.3v
-int	Ufmt(Fmt *f);
-char*	classname(int c);
-void	closedev(Dev *d);
-int	configdev(Dev *d);
-int	devctl(Dev *dev, char *fmt, ...);
-void*	emallocz(ulong size, int zero);
-char*	estrdup(char *s);
-int	finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs);
-char*	hexstr(void *a, int n);
-char*	loaddevstr(Dev *d, int sid);
-int	matchdevcsp(char *info, void *a);
-Dev*	opendev(char *fn);
-int	opendevdata(Dev *d, int mode);
-Dev*	openep(Dev *d, int id);
-void	startdevs(char *args, char *argv[], int argc,
-		int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**));
-int	unstall(Dev *dev, Dev *ep, int dir);
-int	usbcmd(Dev *d, int type, int req,
-		int value, int index, uchar *data, int count);
-.sp 0.3v
-extern int usbdebug;	/* more messages for bigger values */
-.EE
-.SH DESCRIPTION
-This library provides convenience structures and functions to write
-USB device drivers.
-It is not intended for user programs using USB devices.
-See
-.IR usb (3)
-for a description of the interfaces provided for that purpose.
-For drivers that provide a file system and may be embedded into
-.IR usbd ,
-the library includes a file system implementation toolkit described in
-.IR usbfs (2).
-.PP
-Usb drivers rely on
-.IR usb (3)
-to perform I/O through USB as well as on
-.IR usbd (4)
-to perform the initial configuration for the device's setup endpoint.
-The rest of the work is up to the driver and is where this library may help.
-.PP
-In most cases, a driver locates the devices of interest and configures them
-by calling
-.I startdevs
-and
-then sets up additional endpoints as needed (by calling
-.IR openep )
-to finally perform I/O by reading and writing the
-data files for the endpoints.
-.PP
-An endpoint as provided by
-.IR usb (3)
-is represented by a
-.B Dev
-data structure.
-The setup endpoint for a
-device represents the USB device, because it is the means to
-configure and operate the device.
-This structure is reference counted.
-Functions creating
-.B Devs
-adjust the number of references to one, initially.
-The driver is free to call
-.IR incref
-(in
-.IR lock (2))
-to add references and
-.I closedev
-to drop references (and release resources when the last one vanishes).
-As an aid to the driver, the field
-.B aux
-may keep driver-specific data and the function
-.B free
-will be called (if not null) to release the
-.B aux
-structure when the reference count goes down to zero.
-.PP
-.I Dev.dir
-holds the path for the endpoint's directory.
-.PP
-The field
-.B id
-keeps the device number for setup endpoints and the endpoint number
-for all other endpoints.
-For example, it would be
-.B 3
-for
-.B /dev/usb/ep3.0
-and
-.B 1
-for
-.BR /dev/usb/ep3.1 .
-It is easy to remember this because the former is created to operate
-on the device, while the later has been created as a particular endpoint
-to perform I/O.
-.PP
-Fields
-.B dfd
-and
-.B cfd
-keep the data and
-control file descriptors, respectively.
-When a
-.B Dev
-is created the control file is open, initially.
-Opening the data
-file requires calling
-.I opendevdata
-with the appropriate mode.
-.PP
-When the device configuration information has been loaded (see below),
-.B maxpkt
-holds the maximum packet size (in bytes) for the endpoint and
-.B usb
-keeps the rest of the USB information.
-.PP
-Most of the information in
-.B usb
-comes from parsing
-various device and configuration descriptors provided by the device,
-by calling one of the functions described later.
-Only descriptors unknown
-to the library are kept unparsed at
-.B usb.ddesc
-as an aid for the driver
-(which should know how to parse them and what to do with the information).
-.SS Configuration
-.I Startdevs
-is a wrapper that locates devices of interest, loads their configuration
-information, and starts a
-.IR thread (2)'s
-.I proc
-for each device located so that it executes
-.I f
-as its main entry point. The entry point is called with a pointer to
-the
-.B Dev
-for the device it has to process,
-.BR argc ,
-and
-.BR argv .
-Devices are located either from the arguments (after options) in
-.IR argv ,
-if any,
-or by calling the helper function
-.I mf
-with the argument
-.I ma
-to determine (for each device available) if the device belongs to
-the driver or not. If the function returns -1 then the device is not for us.
-.PP
-In many cases,
-.I matchdevcsp
-may be supplied as
-.I mf
-along with a (null terminated) vector of CSP values supplied as
-.IR ma .
-This function returns 0 for any device with a CSP matching one in the
-vector supplied as an argument and -1 otherwise.
-In other cases (eg., when a particular vendor and device ids are the
-ones identifying the device) the driver must include its own function
-and supply it as an argument to
-.IR startdevs .
-The first argument of the function corresponds to the information
-known about the device (the second line in its
-.B ctl
-file).
-.I Openep
-creates the endpoint number
-.I id
-for the device
-.I d
-and returns a
-.B Dev
-structure to operate on it (with just the control file open).
-.PP
-.I Opendev
-creates a
-.B Dev
-for the endpoint with directory
-.IR fn .
-Usually, the endpoint is a setup endpoint representing a device. The endpoint
-control file is open, but the data file is not. The USB description is void.
-In most cases drivers call
-.I startdevs
-and
-.I openep
-and do not call this function directly.
-.PP
-.I Configdev
-opens the data file for the device supplied and
-loads and parses its configuration information.
-After calling it, the device is ready for I/O and the USB description in
-.B Dev.usb
-is valid.
-When using
-.IR startdevs
-it is not desirable to call this function (because
-.IR startdevs
-already calls it).
-.PP
-Control requests for an endpoint may be written by calling
-.I devctl
-in the style of
-.IR print (2).
-It is better not to call
-.I print
-directly because the control request should be issued as a single
-.I write
-system call.
-See
-.IR usb (3)
-for a list of available control requests (not to be confused with
-USB control transfers performed on a control endpoint).
-.SS Input/Output
-.I Opendevdata
-opens the data file for the device according to the given
-.IR mode .
-The mode must match that of the endpoint, doing otherwise is considered
-an error.
-Actual I/O is performed by reading/writing the descriptor kept in the
-.B dfd
-field of
-.BR Dev .
-.PP
-For control endpoints,
-it is not necessary to call
-.I read
-and
-.I write
-directly.
-Instead,
-.I usbcmd
-issues a USB control request to the device
-.I d
-(not to be confused with a
-.IR usb (3)
-control request sent to its control file).
-.I Usbcmd
-retries the control request several times upon failure because some devices
-require it.
-The format of requests is fixed per the USB standard:
-.I type
-is the type of request and
-.I req
-identifies the request. Arguments
-.I value
-and
-.I index
-are parameters to the request and the last two arguments,
-.I data
-and
-.IR count ,
-are similar to
-.I read
-and
-.I write
-arguments.
-However,
-.I data
-may be
-.B nil
-if no transfer (other than the control request) has to take place.
-The library header file includes numerous symbols defined to help writing
-the type and arguments for a request.
-.PP
-The return value from
-.I usbcmd
-is the number of bytes transferred, zero to indicate a stall and -1
-to indicate an error.
-.PP
-A common request is to unstall an endpoint that has been stalled
-due to some reason by the device (eg., when read or write indicate
-a count of zero bytes read or written on the endpoint). The function
-.I unstall
-does this.
-It is given the device that stalled the endpoint,
-.IR dev ,
-the
-stalled endpoint,
-.IR ep ,
-and the direction of the stall (one of
-.B Ein
-or
-.BR Eout ).
-The function takes care of notifying the device of the unstall as well
-as notifying the kernel.
-.SS Tools
-.I Class
-returns the class part of the number given, representing a CSP.
-.I Subclass
-does the same for the device subclass and
-.I Proto
-for the protocol.
-The counterpart is
-.IR CSP ,
-which builds a CSP from the device class, subclass, and protocol.
-For some classes,
-.I classname
-knows the name (for those with constants in the library header file).
-.PP
-The macros
-.I GET2
-and
-.I PUT2
-get and put a (little-endian) two-byte value and are useful to
-parse descriptors and replies for control requests.
-.PP
-Functions
-.I emallocz
-and
-.I estrdup
-are similar to
-.I mallocz
-and
-.I strdup
-but abort program operation upon failure.
-.PP
-The function
-.I Ufmt
-is a format routine suitable for
-.IR fmtinstall (2)
-to print a
-.B Dev
-data structure.
-The auxiliary
-.I hexstr
-returns a string representing a dump (in hexadecimal) of
-.I n
-bytes starting at
-.IR a .
-The string is allocated using
-.IR malloc (2)
-and memory must be released by the caller.
-.PP
-.I Loaddevstr
-returns the string obtained by reading the device string descriptor number
-.IR sid .
-.SH SOURCE
-.B /sys/src/cmd/usb/lib
-.SH "SEE ALSO"
-.IR usbfs (2),
-.IR usb (3),
-.IR usb (4),
-.IR usbd (4).
-.SH BUGS
-Not heavily exercised yet.
--- a/sys/man/2/usbfs
+++ /dev/null
@@ -1,341 +1,0 @@
-.TH USBFS 2
-.SH NAME
-usbreadbuf,
-usbfsadd,
-usbfsdel,
-usbdirread,
-usbfsinit,
-usbdirfs,
-usbfs \- USB device driver file system library
-.SH SYNOPSIS
-.EX
-.ta 8n +8n +8n +8n +8n +8n +8n
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "../lib/usb.h"
-#include "../lib/usbfs.h"
-.sp 0.3v
-enum {
-	Hdrsize	= 128,		/* plenty of room for headers */
-	Msgsize	= 8 * 1024,
-	Bufsize	= Hdrsize + Msgsize,
-	Namesz = 40,
-	Errmax = 128,
-	ONONE = ~0,		/* omode in Fid when not open */
-};
-.sp 0.3v
-struct Fid {
-	int	fid;
-	Qid	qid;
-	int	omode;
-	Fid*	next;
-	void*	aux;
-};
-.sp 0.3v
-struct Usbfs {
-	char	name[Namesz];
-	uvlong	qid;
-	Dev*	dev;
-	void*	aux;
-.sp 0.3v
-	int	(*walk)(Usbfs *fs, Fid *f, char *name);
-	void	(*clone)(Usbfs *fs, Fid *of, Fid *nf);
-	void	(*clunk)(Usbfs *fs, Fid *f);
-	int	(*open)(Usbfs *fs, Fid *f, int mode);
-	long	(*read)(Usbfs *fs, Fid *f,
-			void *data, long count, vlong offset);
-	long	(*write)(Usbfs *fs, Fid*f,
-			void *data, long count, vlong offset);
-	int	(*stat)(Usbfs *fs, Qid q, Dir *d);
-	void	(*end)(Usbfs *fs);
-};
-.sp 0.3v
-typedef int (*Dirgen)(Usbfs*, Qid, int, Dir*, void*);
-.sp 0.3v
-long	usbreadbuf(void *data, long count,
-		vlong offset, void *buf, long n);
-void	usbfsadd(Usbfs *dfs);
-void	usbfsdel(Usbfs *dfs);
-int	usbdirread(Usbfs*f, Qid q, char *data, long cnt,
-		vlong off, Dirgen gen, void *arg);
-void	usbfsinit(char* srv, char *mnt, Usbfs *f, int flag);
-void	usbfsdirdump(void);
-.sp 0.3v
-extern char Enotfound[], Etoosmall[], Eio[], Eperm[], Ebadcall[],
-	Ebadfid[], Einuse[], Eisopen[], Ebadctl[];
-.sp 0.3v
-extern Usbfs usbdirfs;
-extern int usbfsdebug;
-.EE
-.SH DESCRIPTION
-This library provides an alternative to
-.IR 9p (2)
-for implementing a file server within a USB driver.
-Drivers using this
-library may be embedded into
-.IR usbd (4).
-It may be also desirable to use this library when drivers are
-not embedded because it is tailored to work well with the
-library for handling USB devices.
-.PP
-A USB file system is described by a
-.I Usbfs
-structure.
-In most cases, the driver is not responsible for the root of the
-file tree.
-It is customary that a driver creates a file server
-for each device handled and links all of them to a root directory
-implemented by the
-.I usbdirfs
-file system implemented by the library.
-This root directory is bound to
-.B /dev
-in most cases.
-.PP
-.I Usbdirfs
-implements a root directory populated by named file trees,
-each one described by a
-.B Usbfs
-structure.
-.PP
-The field
-.B Usbfs.name
-contains the name for the root directory of the file system, usually
-a directory seen at
-.BI /dev/ name
-when the driver is embedded.
-.PP
-.B Usbfs.qid
-maintains a value used to decorate qids for the file tree.
-This may be ignored when
-.I usbdirfs
-is not used.
-Otherwise,
-.I usbdirfs
-assigns a unique value kept at the high 32 bits of
-.B Qid.path
-for all files on each file tree bound to it.
-Each
-.I Usbfs
-server must bitwise OR
-.B Usbfs.qid
-to all
-.B Qid.path
-values returned by its functions.
-In the same way,
-functions usually clear bits in
-.B Usbfs.qid
-before processing
-.B Qid.path
-values supplied as input.
-.PP
-The USB device handled by a file tree is referenced from
-.B Usbfs.dev
-(and a reference must be counted for it).
-This permits the following functions to quickly locate the device of
-interest, and also permits releasing the device when
-no request is outstanding.
-.PP
-The field
-.B Usbfs.aux
-is for the device to use.
-The rest of the fields implement the 9P protocol for the device.
-Not all the operations need be implemented.
-Only
-.IR walk ,
-.IR open ,
-.IR read ,
-.IR write ,
-and
-.IR stat ,
-must be implemented (and their corresponding fields in
-.B Usbfs
-may never be
-.BR nil ).
-These functions must return -1 upon failure
-and set the error string to reflect the cause of a failure.
-.PP
-In all the functions, a 9P fid is represented by a
-.B Fid
-structure.
-It contains the 9P
-.IR fid ,
-the corresponding
-.IR qid ,
-and an auxiliary pointer for the driver to use.
-Open
-.IR fid s
-have a valid open mode in
-.I omode
-while others have
-.B ONONE
-to indicate that the
-.I fid
-is not open.
-The library takes care of which
-fids
-exist and which ones do not.
-.PP
-.I Walk
-must walk
-.I f
-to
-.I name
-(a single name, not a file path)
-in the supplied
-.IR fs .
-Its implementation should update the qid in
-.I f
-to reflect the walk.
-This function must bitwise OR any returned Qid with
-.B Usbfs.qid ,
-if
-.I usbdirfs
-is used.
-.PP
-.I Clone
-must clone fid
-.I of
-onto
-.I nf
-so that,
-upon successful completion,
-.I nf
-also refers to the file that
-.I f
-refers to.
-An implementation must update the Qid of the cloned
-fid.
-If this function is not supplied, the library copies the
-.I aux
-field to the cloned fid.
-.PP
-.I Clunk
-clunks
-.IR f .
-It usually releases data kept in the
-.I aux
-field, but may be
-set to
-.B nil
-otherwise.
-.PP
-.I Open
-prepares the fid
-.I f
-for I/O according to
-.IR mode .
-The open mode in the fid is updated by the library upon return.
-The library checks trivial cases like opening already-open fids.
-The implementation performs most permission checking.
-.PP
-.I Read
-reads up to
-.I count
-bytes into
-.I data
-starting at
-.I offset
-in the file referenced by
-.IR f .
-.I Write
-is the counterpart.
-To read from directories,
-the function
-.I usbdirread
-may be called.
-It returns the return value of
-.I read
-or -1.
-.I usbdirread
-calls
-.I gen
-to iterate through files as needed.
-The
-.B Dirgen
-function will be called with index values of 0
-and up to ask for the first file and following files.
-To read from data already in buffers, the function
-.I usbreadbuf
-may help.
-It must be given the arguments supplied
-by the user, plus the buffer and buffer size.
-.PP
-.I Stat
-must fill
-.I d
-with the directory entry for the file identified by
-.IR q.
-As an aid,
-.I d
-is initialized to fake access and modification times,
-and user and group ids.
-Also, the field
-.B name
-in
-.I d
-is initialized to point to a 40-byte buffer.
-If the file name fits,
-it may be copied directly into
-.B d->name
-without allocating memory for that purpose.
-Otherwise
-.B d->name
-must be initialized to point to static memory.
-.PP
-The function
-.I end
-is called upon termination of the file tree to
-release resources.
-.PP
-Calling
-.I usbfsinit
-starts a file server for
-.I f
-that mounts itself at
-.I mnt
-and posts
-.I srv
-at
-.IR srv (3).
-In most cases, the file system supplied is
-.IR usbdirfs .
-The
-.I flag
-is used for
-.IR mount
-(see
-.IR bind (2)).
-Once
-.I usbdirfs
-is started, calls to
-.IR usbfsadd
-add a file tree implemented by
-.I dfs
-to the root directory of
-.I usbdirfs
-and
-calls to
-.I usbfsdel
-remove that binding (and release resources including
-the reference to the USB device).
-.PP
-Various error strings are declared as an aid.
-The global
-.B usbfsdebug
-may be set to trigger diagnostics and protocol tracing.
-.SH EXAMPLE
-See
-.B /sys/src/cmd/usb/disk
-for an example driver that uses this library.
-Looking at an example is strongly suggested
-to see how reference counts for the USB device
-and the file system are handled.
-.SH SOURCE
-.B /sys/src/cmd/usb/lib
-.SH "SEE ALSO"
-.IR usb (2),
-.IR usb (3),
-.IR usb (4),
-.IR usbd (4)
--- a/sys/man/3/audio
+++ b/sys/man/3/audio
@@ -126,4 +126,4 @@
 .SH SOURCE
 .B /sys/src/9/port/devaudio.c
 .SH SEE ALSO
-.IR usb (4)
+.IR nusb (4)
--- a/sys/man/3/usb
+++ b/sys/man/3/usb
@@ -58,7 +58,7 @@
 .PP
 Enumeration of the bus and initial configuration of devices is done
 by a user level program,
-.IR usbd (4).
+.IR usbd .
 Device drivers are implemented by separate user programs, although
 some of them may be statically linked into
 .IR usbd .
@@ -115,7 +115,7 @@
 as dictated by the device to perform actual I/O.
 .SS Operation
 Bus enumeration and device configuration is performed by
-.IR usbd (4)
+.IR usbd 
 and not by this driver.
 The driver provides an interface
 to access existing endpoints (initially those for the built-in root hubs),
@@ -130,7 +130,7 @@
 is a number identifying one of its endpoints.
 .PP
 For each device attached to the bus, and configured by
-.IR usbd (4),
+.IR usbd ,
 an endpoint zero (a
 .I setup
 endpoint)
@@ -212,7 +212,7 @@
 .LP
 The first line contains status information.
 The rest is information supplied by
-.IR usbd (4)
+.IR usbd
 as an aid to locate devices.
 The status information includes:
 .TF "\fREndpoint mode
@@ -346,7 +346,7 @@
 Endpoint control files accept the following requests.
 In most cases
 the driver does not issue them, leaving the task to either
-.IR usbd (4)
+.IR usbd
 or the usb driver library documented in
 .IR usb (2).
 .TF "\fLsamplehz\fI n
@@ -522,8 +522,7 @@
 .B /sys/src/9/pc/usb?hci.c
 .SH "SEE ALSO"
 .IR usb (2),
-.IR usb (4),
-.IR usbd (4),
+.IR nusb (4),
 .IR plan9.ini (8)
 .SH BUGS
 USB controllers limit the speed of all their ports
--- a/sys/man/4/usb
+++ /dev/null
@@ -1,516 +1,0 @@
-.TH USB 4
-.SH NAME
-audio,
-ccid,
-disk,
-ether,
-kb,
-print,
-probe,
-serial,
-usbeject,
-usbfat:
-\- Universal Serial Bus device drivers
-.SH SYNOPSIS
-.B usb/kb
-[
-.B -dkm
-] [
-.B -a
-.I accel
-] [
-.I dev ...
-]
-.PP
-.B usb/disk
-[
-.B -Dd
-] [
-.B -m
-.I mnt
-] [
-.B -s
-.I srv
-] [
-.I dev ...
-]
-.PP
-.B usbfat:
-[
-.I disk ...
-]
-.PP
-.B usbeject
-[
-.I disk ...
-]
-.PP
-.B usb/audio
-[
-.B -dpV
-] [
-.B -m
-.I mnt
-] [
-.B -s
-.I srv
-] [
-.B -v
-.I vol
-] [
-.I dev
-]
-.PP
-.B usb/ether
-[
-.B -Dd
-] [
-.B -m
-.I mnt
-] [
-.B -s
-.I srv
-] [
-.I dev ...
-]
-.PP
-.B usb/serial
-[
-.B -Dd
-] [
-.B -m
-.I mnt
-] [
-.B -s
-.I srv
-] [
-.I dev ...
-]
-.PP
-.B usb/print
-[
-.B -d
-] [
-.I dev ...
-]
-.PP
-.B usb/ccid
-[
-.B -d
-]
-.ig
-.PP
-.B usb/ibuddy
-[
-.B -Dd
-] [
-.B -m
-.I mnt
-] [
-.B -s
-.I srv
-] [
-.I dev ...
-]
-..
-.B usb/probe
-.SH DESCRIPTION
-These programs drive USB devices of specific classes via
-.IR usb (3).
-Usually they are started by
-.IR usbd (4)
-upon attachment of the device to the bus.
-Less often, users start them manually, depending on
-.IR usbd (4)'s
-configuration.
-Usually,
-.I kb
-and
-.I disk
-are started by
-.I usbd
-and other programs are started by hand.
-.PP
-Without arguments, the drivers handle all the devices (of
-the appropriate USB class) found on the bus.
-To make a driver handle only certain devices, supply as arguments
-the paths for the directories of the devices
-(actually of their zero endpoints).
-.PP
-Drivers that provide file systems accept options
-.B -s
-and
-.B -m
-to instruct them to post a 9P connection at
-.IR srv (3)
-with the given name and/or to mount themselves at
-.IR mnt .
-When embedded into
-.IR usbd
-these options may not be used.
-In this case,
-the file tree supplied by the device driver is
-available through the file system provided by
-.IR usbd ,
-usually mounted at
-.B /dev
-and reachable through the 9P connection posted at
-.BR /srv/usb .
-.PP
-Options
-.B -d
-and
-.B -D
-present on most drivers trigger debug diagnostics and
-file system debugging diagnostics.
-Repeating any one of these may increase verbosity.
-.PP
-To help locate devices of interest,
-.I probe
-lists all the USB devices available,
-including those with no driver started.
-.SS Keyboards and mice
-.I Kb
-supports USB keyboards and mice either as separate USB devices
-or as a single combined USB device.
-Scan codes from the keyboard are sent to
-.B /dev/kbin
-to let
-.IR kbdfs (8)
-process them.
-Mouse events are sent to
-.B /dev/mousein
-in the same way.
-.PP
-The following options are understood:
-.TF -k
-.TP
-.B \-a
-Accelerate the mouse to level
-.I n
-(similar to the kernel mouse driver acceleration).
-.TP
-.B \-k
-Serve just the keyboard (and not the mouse).
-.TP
-.B \-m
-Serve just the mouse (and not the keyboard).
-.SS Disks
-.I Disk
-configures and manages USB mass storage devices. It
-provides a file system (usually seen at
-.BR /dev )
-that includes one directory per storage device, named
-.BI sdU N . M
-in correspondence with the usb device number and the storage
-unit number (or LUN).
-For example, LUN number 2 on
-.B /dev/usb/ep3.0
-can be accessed through
-.BR /dev/sdU3.2 .
-.PP
-The storage device directory contains the usual files
-served by
-.IR sd (3):
-.BR data ,
-.BR raw ,
-and
-.BR ctl .
-.PP
-The
-.B ctl
-file supplies the device
-geometry when read.
-.PP
-The script
-.B usbfat:
-mounts the FAT file systems in the DOS partitions of the named
-.IR disk s;
-if none, it mounts those file systems found at
-.BR /dev/sdU*.*/data .
-When more than one partition is found, a suffix is appended to
-the disk name to identify the partition number.
-The script
-.B usbeject
-undoes the effect. If no argument is given, it unmounts all USB
-disks. An argument
-.BI sdU N
-unmounts all partitions from disk with USB target
-.IR N .
-.ig
-An argument
-.BI sdU N . M
-or
-.BI sdU N . M . P
-.\" TODO: fill in missing words
-..
-.SS Printers
-.I Print
-provides a single file can be written to print on a USB printer.
-Options are similar to those of
-.IR disk .
-The file is also bound at
-.B /dev/lp
-as is customary.
-.SS Ethernet adapters
-.I Ether
-provides a file interface similar to that of
-.IR ether (3)
-for each USB Ethernet adapter found.
-The name of an Ethernet device is
-.BI etherU N
-where
-.I N
-is the device name.
-When started manually, the file interface is mounted at
-.B /net
-as is customary.
-.
-.SS Serial and JTAG ports
-.I Serial
-provides a file system (usually mounted at
-.BR /dev )
-that includes one directory per USB serial port, named
-.BI eiaU N
-or
-.BI eiaU N . M.
-In this directory there are two files,
-.BR eiaU ,
-similar to
-.BI eia N
-in
-.IR uart (3),
-and
-.BR eiaUctl ,
-which admits writes in the same format as
-.BI eia N ctl
-in
-.IR uart (3).
-Reading from
-.B eiaUctl
-gives the serial port's settings in the same format as
-.BI eia N status
-in
-.IR uart (3).
-Options are similar to those of
-.IR disk .
-.PP
-JTAG ports are similar
-but the files are named
-.B jtag
-and
-.BR jtagctl .
-.
-.SS Audio devices
-.I Usbaudio
-configures and manages a USB audio device.
-It implements a file system,
-normally mounted on
-.BI /dev ,
-but this can be changed with
-.BR \-m ,
-containing files
-.BR volume ,
-.BR audioctl ,
-.BR audio ,
-and
-.BR audioin .
-The names
-.B volume
-and
-.B audio
-maintain backward compatibility with the Soundblaster driver.
-.PP
-The
-.B \-V
-option (verbose)
-causes
-.I audio
-to print information about the device on startup.
-The
-.B \-s
-option specifies a name for a file descriptor to be posted in
-.BR /srv .
-The
-.B \-v
-options sets initial
-.IR volume .
-.PP
-Reading
-.B volume
-or
-.B audioctl
-yields the device's settings.
-The data format of
-.B volume
-is compatible with the Soundblaster and produces output in this
-format:
-.IP
-.EX
-audio out 65
-treb out 0
-bass out 0
-speed out 44100
-.EE
-.PP
-This file can be written using the same syntax.
-The keyword
-.L out
-may be omitted.
-Settings are given as percentages of the range,
-except for speed which is in Hz.
-.PP
-The file
-.B audioctl
-provides more information, using up to 6 columns of 12 characters each.
-From left to right, the fields are:
-.IR "control name" ,
-.I in
-or
-.IR out ,
-.IR "current value" ,
-.IR "minimum value" ,
-.IR maximum ,
-and
-.IR resolution .
-There are 3, 5, or 6 columns present.
-Maxima and resolution are omitted when they are not available or not applicable.
-The resolution for
-.I speed
-is reported as 1 (one) if the sampling frequency is continuously variable.
-It is absent if it is settable at a fixed number of discrete values only.
-.PP
-When all values from
-.B audioctl
-have been read, a zero-length buffer is returned
-(the usual end-of-file indication).
-A new
-.I read
-will then block until one of the settings changes,
-then report its new value.
-.PP
-The file
-.B audioctl
-can be written like
-.BR volume .
-.PP
-Audio data is written to
-.B audio
-and read from
-.BR audioin .
-The data format is little-endian,
-samples ordered primarily by time and
-secondarily by channel.
-Samples occupy the minimum integral number of bytes.
-Read and write operations of arbitrary size are allowed.
-.
-.SS Ccid
-.I Ccid
-discovers and configures SIM or SAM cards using the CCID standard.
-It provides a file system (usually mounted at
-.BR /dev )
-that includes three files,
-.BI ctl ,
-.B raw
-and
-.BI rpc .
-Reading from
-.B ctl
-a description of the smartcard reader capabilities is printed.
-.B raw
-is just intended for debugging.
-Reads and writes to the
-raw file send and receive raw CCID packets.
-Smart cards identify themselves by giving out an ATR,
-an array of characters describing the card uniquely.
-Users of the driver write the ATR to the
-.B rpc
-file and are blocked until a card with that ATR is seen.
-From then on they can do ICC RPCs using whatever
-language the smart card speaks. A small write cancels
-an outstanding RPC.
-.PP
-The driver takes care of powering the card adequately, based
-on its ATR, and tunnelling the RPCs through the USB device.
-Only slot 0 is supported.
-.PP
-When the smartcard disappears,
-all reads and write fail until the file is reopened and
-a new ATR is written to it.
-.
-.ig
-.SS Ibuddy
-.PP
-Ibuddy supports a USB I-buddy toy, a little winged-demon.
-The driver provides one directory per attached toy with a single
-.BR ctl
-file to control the device.
-Directories are named
-.BR ibuddyN ,
-being
-.I N
-the corresponding usb device number.
-When read, the
-.BR ctl
-file provides the state of the device in this form:
-.IP
-.EX
-hips right|left
-wings open|close
-red on|off
-green on|off
-blue on|off
-heart on|off
-.EE
-.PP
-Each line describes the status of one feature.
-.IR  Red ,
-.IR  blue ,
-and
-.IR  green
-are the different leds in the head of
-the toy.
-.IR  Heart
-represents the red led in the chest of
-the toy.
-.IR  Wings
-represents the status of the wings, which
-can be closed or open.
-.IR  Hips
-represents the orientation
-of the toy (left or right, from the figure's point of view).
-.PP
-Lines can be written to the
-.BR ctl
-file to command the device.
-Multiple lines (six at most) can be written
-at once, with one action per line.
-..
-.SH SOURCE
-.B /sys/src/cmd/usb
-.SH "SEE ALSO"
-.IR mouse (3),
-.IR sd (3),
-.IR uart (3),
-.IR usb (3),
-.IR usbd (4),
-.IR partfs (8),
-.IR kbdfs (8)
-.SH BUGS
-The various device drivers are generic USB drivers and
-may work only for certain devices on each class.
-.PP
-USB ATA storage devices are not supported.
-.PP
-The Ethernet device works only for certain ASIX-based cards and for CDC devices.
-Both the Ethernet and printer drivers have not
-been tested and it is likely they will fail.
-.PP
-The serial driver works only for the Prolific chip and Ftdi,
-and control of the
-.B dcd
-and
-.B dsr
-signals and some of the extra features are unimplemented.
-For Ftdi, only the Sheevaplug and Guruplug have been tried.
-There is support for the EHCI debug port, but it loses bytes.
--- a/sys/man/4/usbd
+++ /dev/null
@@ -1,245 +1,0 @@
-.TH USBD 4
-.SH NAME
-usbd \- Universal Serial Bus daemon
-.SH SYNOPSIS
-.B usbd
-[
-.B -Dd
-]
-[
-.B -s
-.I srv
-]
-[
-.B -m
-.I mnt
-]
-[
-.I hub...
-]
-.SH DESCRIPTION
-.I Usbd
-complements
-.IR usb (3)
-to provide USB I/O for device drivers.
-It enumerates the bus, polling
-hub ports to detect device attachments and detachments, performs
-initial configuration of setup endpoints, and writes extra information into
-.IR usb (3)
-endpoint control files, to ease device location.
-.PP
-By default,
-.I usbd
-opens all setup endpoints found at
-.B #u/usb
-(which correspond to built-in hubs initialized by the kernel during boot).
-Paths to directories representing setup endpoints for hubs can be given
-as arguments to restrict
-.I usbd
-operation to such hubs.
-.PP
-When a device is attached,
-depending upon a configuration file compiled into
-.I usbd ,
-the appropriate device driver may be started without
-user intervention.
-This mechanism can be used to statically link some USB device drivers into
-.I usbd
-itself.
-Initial configuration for setup endpoints is performed independently
-of this configuration.
-.PP
-.I Usbd
-provides a file interface used to change debugging flags, and also used by
-USB device drivers statically linked into
-.IR usbd .
-By default, the file system is mounted (after) at
-.B /dev
-and a 9P connection is posted at
-.BR /srv/usb .
-.PP
-Besides files provided by device drivers, the file
-.B usbdctl
-is always present in the file interface.
-It accepts these control requests:
-.TF "fsdebug\fI n
-.TP
-.BI debug " n"
-Sets the debugging level to
-.IR n .
-.TP
-.BI fsdebug " n"
-Sets the file system debugging level to
-.IR n .
-.TP
-.B dump
-Prints the list of devices and file systems known by
-.IR usbd .
-.PD
-.PP
-.I Usbd
-recognizes the following options:
-.TF "-m\fI mnt
-.TP
-.B -d
-Print debugging diagnostics.
-Repeating the option increases verbosity.
-.TP
-.B -D
-Print debugging diagnostics for the file system interface.
-.TP
-.BI -m " mnt"
-Mount the served file system at
-.IR mnt .
-.TP
-.BI -s " srv"
-Post a 9P connection at
-.BI #s/ srv.
-.PD
-.SS Configuration
-.PP
-.I Usbd
-can be configured to start drivers for devices matching one or more CSPs
-(hex representation of USB class, subclass and protocol), class,
-subclass, protocol, vendor id, or device id.
-When a new device is attached,
-.I usbd
-scans the configuration and, if an entry matches the device descriptor, starts
-the driver.
-If no driver is configured, the setup endpoint for the device is left
-configured to let the user start the driver by hand.
-.PP
-Configuration is via compilation
-because one of the options is to embed (link) the driver into the
-.I usbd
-binary.
-If the driver is embedded,
-.I usbd
-creates a process for it and calls its main entry point.
-Otherwise,
-.I usbd
-tries to locate the driver binary in
-.B /bin/usb
-and creates a process to execute it.
-.PP
-The configuration file,
-.BR usbdb ,
-has two sections:
-.B embed
-and
-.BR auto .
-Each section includes lines to configure particular drivers.
-A driver may have more than one line if necessary.
-Each line includes the name of the
-driver (the base name of the binary) and one or more attributes of the form
-.IP
-.IR name = value
-.PP
-The following attributes exist:
-.TF subclass
-.TP
-.B class
-.I Value
-may be the name of the class
-or a number identifying the device class (using C syntax).
-The following class names are known:
-.BR audio ,
-.BR comms ,
-.BR hid ,
-.BR printer ,
-.BR storage ,
-.BR hub ,
-and
-.BR data .
-.TP
-.B subclass
-.I Value
-is the number of the device subclass.
-.TP
-.B proto
-.I Value
-is the number of the device protocol.
-.TP
-.B csp
-.I Value
-is the hexadecimal number describing the CSP for the device.
-.TP
-.B vid
-.I Value
-is the vendor id.
-.TP
-.B did
-.I Value
-is the device id.
-.TP
-.B args
-This must be the last field.
-The value is the rest of the line,
-and is supplied as arguments to the driver process.
-.PD
-.LP
-Several environment variables can be used to alter the behaviour of
-.IR usbd ,
-for example, for use in
-.IR plan9.ini (8).
-.B usbdebug
-sets a debug level (zero for no diagnostics and positive
-values for increasing verbosity).
-.B kbargs
-overrides the keyboard arguments as specified by the configuration file.
-.B diskargs
-overrides the disk arguments in the same way.
-.SH EXAMPLE
-This configuration file links
-.B usb/kb
-into
-.I usbd
-when it is compiled.
-It arranges for the driver's entry point,
-.B kbmain
-in this case,
-to be called for any device with CSPs matching either
-.B 0x010103
-or
-.BR 0x020103 .
-Option
-.B -d
-will be supplied as command line arguments for
-.BR kbmain .
-This configuration also arranges for
-.B /bin/usb/disk
-to start (with no arguments) whenever a device of class
-.B storage
-is attached.
-.IP
-.EX
-embed
-	kb	csp=0x010103 csp=0x020103	args=-d
-auto
-	disk	class=storage	args=
-.EE
-.SH FILES
-.TF /srv/usb
-.TP
-.B /srv/usb
-9P connection to the driver file system.
-.TP
-.B /dev
-mount point for the driver file system.
-.TP
-.B /sys/src/cmd/usb/usbd/usbdb
-Configuration file deciding which devices are included into
-.I usbd
-and which ones are started automatically.
-.SH SOURCE
-.B /sys/src/cmd/usb/usbd
-.SH "SEE ALSO"
-.IR usb (2),
-.IR usb (3),
-.IR usb (4)
-.SH BUGS
-.I Usbd
-is not supposed to be restarted.
-This is arguable.
-.PP
-Not heavily exercised yet.
--- a/sys/man/8/prep
+++ b/sys/man/8/prep
@@ -709,7 +709,7 @@
 .SH SEE ALSO
 .IR floppy (3),
 .IR sd (3),
-.IR usb (4),
+.IR nusb (4),
 .IR 9boot (8),
 .IR partfs (8)
 .SH BUGS
--- a/sys/src/cmd/nusb/lib/usb.h
+++ b/sys/src/cmd/nusb/lib/usb.h
@@ -339,8 +339,6 @@
 int	devctl(Dev *dev, char *fmt, ...);
 void*	emallocz(ulong size, int zero);
 char*	estrdup(char *s);
-int	matchdevcsp(char *info, void *a);
-int	finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs);
 char*	hexstr(void *a, int n);
 int	loaddevconf(Dev *d, int n);
 int	loaddevdesc(Dev *d);
@@ -351,7 +349,6 @@
 int	parseconf(Usbdev *d, Conf *c, uchar *b, int n);
 int	parsedesc(Usbdev *d, Conf *c, uchar *b, int n);
 int	parsedev(Dev *xd, uchar *b, int n);
-void	startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**));
 int	unstall(Dev *dev, Dev *ep, int dir);
 int	usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count);
 Dev*	getdev(int id);
--- a/sys/src/cmd/usb/audio/audio.c
+++ /dev/null
@@ -1,402 +1,0 @@
-/*
- * USB audio driver for Plan 9
- * This needs a full rewrite.
- * As it is, it does not check for all errors,
- * mixes the audio data structures with the usb configuration,
- * may cross nil pointers, and is hard to debug and fix.
- * Also, it does not issue a dettach request to the endpoint
- * after the device is unplugged. This means that the old
- * endpoint would still be around until manually reclaimed.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "audio.h"
-#include "audioctl.h"
-
-#define STACKSIZE 16*1024
-
-extern char* srvpost;
-char * mntpt;
-
-Channel *controlchan;
-
-int verbose;
-int setrec = 0;
-int defaultspeed[2] = {44100, 44100};
-Dev *buttondev;
-Dev *epdev[2];
-
-static void
-audio_endpoint(Dev *, Desc *dd)
-{
-	byte *b = (uchar*)&dd->data;
-	int n = dd->data.bLength;
-	char *hd;
-
-	switch(b[2]){
-	case 0x01:
-		if(usbdebug){
-			fprint(2, "CS_ENDPOINT for attributes 0x%x, lockdelayunits %d, lockdelay %#ux, ",
-				b[3], b[4], b[5] | (b[6]<<8));
-			if(b[3] & has_setspeed)
-				fprint(2, "has sampling-frequency control");
-			else
-				fprint(2, "does not have sampling-frequency control");
-			if(b[3] & 0x1<<1)
-				fprint(2, ", has pitch control");
-			else
-				fprint(2, ", does not have pitch control");
-			if(b[3] & 0x1<<7)
-				fprint(2, ", max packets only");
-			fprint(2, "\n");
-		}
-		if(dd->conf == nil)
-			sysfatal("conf == nil");
-		if(dd->iface == nil)
-			sysfatal("iface == nil");
-		if(dd->altc == nil)
-			sysfatal("alt == nil");
-		if(dd->altc->aux == nil)
-			dd->altc->aux= mallocz(sizeof(Audioalt),1);
-		((Audioalt*)dd->altc->aux)->caps |= b[3];
-		break;
-	case 0x02:
-		if(usbdebug){
-			fprint(2, "CS_INTERFACE FORMAT_TYPE %d, channels %d, subframesize %d, resolution %d, freqtype %d, ",
-				b[3], b[4], b[5], b[6], b[7]);
-			fprint(2, "freq0 %d, freq1 %d\n",
-				b[8] | (b[9]<<8) | (b[10]<<16), b[11] | (b[12]<<8) | (b[13]<<16));
-		}
-		break;
-	default:
-		if(usbdebug){
-			hd = hexstr(b, n);
-			fprint(2, "CS_INTERFACE: %s\n", hd);
-			free(hd);
-		}
-	}
-}
-
-enum {
-	None,
-	Volumeset,
-	Volumeget,
-	Altset,
-	Altget,
-	Speedget,
-};
-
-void
-controlproc(void *)
-{
-	/* Proc that looks after /dev/usb/%d/ctl */
-	int i, nf;
-	char *req, *args[8];
-	Audiocontrol *c;
-	long value[8];
-	Channel *replchan;
-
-	while(req = recvp(controlchan)){
-		int rec;
-
-		nf = tokenize(req, args, nelem(args));
-		if(nf < 3)
-			sysfatal("controlproc: not enough arguments");
-		replchan = (Channel*)strtol(args[0], nil, 0);
-		if(strcmp(args[2], "playback") == 0)
-			rec = Play;
-		else if(strcmp(args[2], "record") == 0)
-			rec = Record;
-		else{
-			/* illegal request */
-			dprint(2, "%s must be record or playback", args[2]);
-			if(replchan) chanprint(replchan, "%s must be record or playback", args[2]);
-			free(req);
-			continue;
-		}
-		c = nil;
-		for(i = 0; i < Ncontrol; i++){
-			c = &controls[rec][i];
-			if(strcmp(args[1], c->name) == 0)
-				break;
-		}
-		if(i == Ncontrol){
-			dprint(2, "Illegal control name: %s", args[1]);
-			if(replchan) chanprint(replchan, "Illegal control name: %s", args[1]);
-		}else if(!c->settable){
-			dprint(2, "%s %s is not settable", args[1], args[2]);
-			if(replchan)
-				chanprint(replchan, "%s %s is not settable", args[1], args[2]);
-		}else if(nf < 4){
-			dprint(2, "insufficient arguments for %s %s", args[1], args[2]);
-			if(replchan)
-				chanprint(replchan, "insufficient arguments for %s %s",
-					args[1], args[2]);
-		}else if(ctlparse(args[3], c, value) < 0){
-			if(replchan)
-				chanprint(replchan, "parse error in %s %s", args[1], args[2]);
-		}else{
-			dprint(2, "controlproc: setcontrol %s %s %s\n",
-					rec?"in":"out", args[1], args[3]);
-			if(setcontrol(rec, args[1], value) < 0){
-				if(replchan)
-					chanprint(replchan, "setting %s %s failed", args[1], args[2]);
-			}else{
-				if(replchan) chanprint(replchan, "ok");
-			}
-			ctlevent();
-		}
-		free(req);
-	}
-}
-
-void
-buttonproc(void *)
-{
-	int	i, fd, b;
-	char err[32];
-	byte buf[1];
-	Audiocontrol *c;
-
-	fd = buttondev->dfd;
-
-	c = &controls[Play][Volume_control];
-	for(;;){
-		if((b = read(fd, buf, 1)) < 0){
-			rerrstr(err, sizeof err);
-			if(strcmp(err, "interrupted") == 0){
-				dprint(2, "read interrupted\n");
-				continue;
-			}
-			sysfatal("read %s/data: %r", buttondev->dir);
-		}
-		if(b == 0 || buf[0] == 0){
-			continue;
-		}else if(buf[0] == 1){
-			if(c->chans == 0)
-				c->value[0] += c->step;
-			else
-				for(i = 1; i < 8; i++)
-					if(c->chans & 1 << i)
-						c->value[i] += c->step;
-			chanprint(controlchan, "0 volume playback %A", c);
-		}else if(buf[0] == 2){
-			if(c->chans == 0)
-				c->value[0] -= c->step;
-			else
-				for(i = 1; i < 8; i++)
-					if(c->chans & 1 << i)
-						c->value[i] -= c->step;
-			chanprint(controlchan, "0 volume playback %A", c);
-		}else if(usbdebug){
-			fprint(2, "button");
-			for(i = 0; i < b; i++)
-				fprint(2, " %#2.2x", buf[i]);
-			fprint(2, "\n");
-		}
-	}
-}
-
-
-void
-usage(void)
-{
-	fprint(2, "usage: usbaudio [-dpV] [-N nb] [-m mountpoint] [-s srvname] "
-		"[-v volume] [dev]\n");
-	threadexitsall("usage");
-}
-
-void
-threadmain(int argc, char **argv)
-{
-	char *devdir;
-	int i;
-	long value[8], volume[8];
-	Audiocontrol *c;
-	char *p;
-	extern int attachok;
-	Ep *ep;
-	int csps[] = { Audiocsp, 0};
-
-	devdir = nil;
-	volume[0] = Undef;
-	for(i = 0; i<8; i++)
-		value[i] = 0;
-	fmtinstall('A', Aconv);
-	fmtinstall('U', Ufmt);
-	quotefmtinstall();
-
-	ARGBEGIN{
-	case 'N':
-		p = EARGF(usage());	/* ignore dev nb */
-		break;
-	case 'd':
-		usbdebug++;
-		verbose++;
-		break;
-	case 'm':
-		mntpt = EARGF(usage());
-		break;
-	case 'p':
-		attachok++;
-		break;
-	case 's':
-		srvpost = EARGF(usage());
-		break;
-	case 'v':
-		volume[0] = strtol(EARGF(usage()), &p, 0);
-		for(i = 1; i < 8; i++)
-			volume[i] = volume[0];
-		break;
-	case 'V':
-		verbose++;
-		break;
-	default:
-		usage();
-	}ARGEND
-	switch(argc){
-	case 0:
-		break;
-	case 1:
-		devdir = argv[0];
-		break;
-	default:
-		usage();
-	}
-	if(devdir == nil)
-		if(finddevs(matchdevcsp, csps, &devdir, 1) < 1){
-			fprint(2, "No usb audio\n");
-			threadexitsall("usbaudio not found");
-		}
-	ad = opendev(devdir);
-	if(ad == nil)
-		sysfatal("opendev: %r");
-	if(configdev(ad) < 0)
-		sysfatal("configdev: %r");
-	
-	for(i = 0; i < nelem(ad->usb->ddesc); i++)
-		if(ad->usb->ddesc[i] != nil)
-		switch(ad->usb->ddesc[i]->data.bDescriptorType){
-		case AUDIO_INTERFACE:
-			audio_interface(ad, ad->usb->ddesc[i]);
-			break;
-		case AUDIO_ENDPOINT:
-			audio_endpoint(ad, ad->usb->ddesc[i]);
-			break;
-		}
-
-	controlchan = chancreate(sizeof(char*), 8);
-
-	for(i = 0; i < nelem(ad->usb->ep); i++)
-		if((ep = ad->usb->ep[i]) != nil){
-			if(ep->iface->csp == CSP(Claudio, 2, 0) && ep->dir == Eout)
-				endpt[0] = ep->id;
-			if(ep->iface->csp == CSP(Claudio, 2, 0) && ep->dir == Ein)
-				endpt[1] = ep->id;
-			if(buttonendpt<0 && Class(ep->iface->csp) == Clhid)
-				buttonendpt = ep->id;
-		}
-	if(endpt[0] != -1){
-		if(verbose)
-			fprint(2, "usb/audio: playback on ep %d\n", endpt[0]);
-		interface[0] = ad->usb->ep[endpt[0]]->iface->id;
-	}
-	if(endpt[1] != -1){
-		if(verbose)
-			fprint(2, "usb/audio: record on ep %d\n", endpt[0]);
-		interface[1] = ad->usb->ep[endpt[1]]->iface->id;
-	}
-	if(verbose && buttonendpt >= 0)
-		fprint(2, "usb/audio: buttons on ep %d\n", buttonendpt);
-
-	if(endpt[Play] >= 0){
-		if(verbose)
-			fprint(2, "Setting default play parameters: %d Hz, %d channels at %d bits\n",
-				defaultspeed[Play], 2, 16);
-		if(findalt(Play, 2, 16, defaultspeed[Play]) < 0){
-			if(findalt(Play, 2, 16, 48000) < 0)
-				sysfatal("Can't configure playout for %d or %d Hz", defaultspeed[Play], 48000);
-			fprint(2, "Warning, can't configure playout for %d Hz, configuring for %d Hz instead\n",
-				defaultspeed[Play], 48000);
-			defaultspeed[Play] = 48000;
-		}
-		value[0] = 2;
-		if(setcontrol(Play, "channels", value) == Undef)
-			sysfatal("Can't set play channels");
-		value[0] = 16;
-		if(setcontrol(Play, "resolution", value) == Undef)
-			sysfatal("Can't set play resolution");
-	}
-
-	if(endpt[Record] >= 0){
-		setrec = 1;
-		if(verbose)
-			fprint(2, "Setting default record parameters: "
-				"%d Hz, %d channels at %d bits\n",
-				defaultspeed[Record], 2, 16);
-		i = 2;
-		while(findalt(Record, i, 16, defaultspeed[Record]) < 0)
-			if(i == 2 && controls[Record][Channel_control].max == 1){
-				fprint(2, "Warning, can't configure stereo "
-					"recording, configuring mono instead\n");
-				i = 1;
-			}else
-				break;
-		if(findalt(Record, i, 16, 48000) < 0){
-			endpt[Record] = -1;	/* disable recording */
-			setrec = 0;
-			fprint(2, "Warning, can't configure record for %d Hz or %d Hz\n",
-				defaultspeed[Record], 48000);
-		}else
-			fprint(2, "Warning, can't configure record for %d Hz, "
-				"configuring for %d Hz instead\n",
-				defaultspeed[Record], 48000);
-		defaultspeed[Record] = 48000;
-		if(setrec){
-			value[0] = i;
-			if(setcontrol(Record, "channels", value) == Undef)
-				fprint(2, "%s: can't set record channels\n", argv0);
-			value[0] = 16;
-			if(setcontrol(Record, "resolution", value) == Undef)
-				fprint(2, "%s: can't set record resolution\n", argv0);
-		}
-	}
-
-	getcontrols();	/* Get the initial value of all controls */
-	value[0] = defaultspeed[Play];
-	if(endpt[Play] >= 0 && setcontrol(Play, "speed", value) < 0)
-		fprint(2, "%s: can't set play speed\n", argv0);
-	value[0] = defaultspeed[Record];
-	if(endpt[Record] >= 0 && setcontrol(Record, "speed", value) < 0)
-		fprint(2, "%s: can't set record speed\n", argv0);
-	value[0] = 0;
-	setcontrol(Play, "mute", value);
-
-	if(volume[0] != Undef){
-		c = &controls[Play][Volume_control];
-		if(*p == '%' && c->min != Undef)
-			for(i = 0; i < 8; i++)
-				volume[i] = (volume[i]*c->max + (100-volume[i])*c->min)/100;
-		if(c->settable)
-			setcontrol(Play, "volume", volume);
-		c = &controls[Record][Volume_control];
-		if(c->settable && setrec)
-			setcontrol(Record, "volume", volume);
-	}
-
-	if(buttonendpt > 0){
-		buttondev = openep(ad, buttonendpt);
-		if(buttondev == nil)
-			sysfatal("openep: buttons: %r");
-		if(opendevdata(buttondev, OREAD) < 0)
-			sysfatal("open buttons fd: %r");
-		proccreate(buttonproc, nil, STACKSIZE);
-	}
-	proccreate(controlproc, nil, STACKSIZE);
-	proccreate(serve, nil, STACKSIZE);
-
-	threadexits(nil);
-}
--- a/sys/src/cmd/usb/audio/audio.h
+++ /dev/null
@@ -1,84 +1,0 @@
-enum {
-	master_chan		= 0x00,
-	Speed_control		= 0x00,
-	/* Items below are  defined by USB standard: */
-	Mute_control		= 0x01,
-	Volume_control		= 0x02,
-	Bass_control		= 0x03,
-	Mid_control		= 0x04,
-	Treble_control		= 0x05,
-	Equalizer_control	= 0x06,
-	Agc_control		= 0x07,
-	Delay_control		= 0x08,
-	Bassboost_control	= 0x09,
-	Loudness_control	= 0x0a,
-	/* Items below are defined by implementation: */
-	Channel_control		= 0x0b,
-	Resolution_control	= 0x0c,
-	Ncontrol,
-	Selector_control	= 0x0d,
-
-	sampling_freq_control	= 0x01,
-
-	Audiocsp = 0x000101, /* audio.control.0 */
-
-	AUDIO_INTERFACE = 0x24,
-	AUDIO_ENDPOINT = 0x25,
-};
-
-
-#define AS_GENERAL 1
-#define FORMAT_TYPE 2
-#define FORMAT_SPECIFIC 3
-
-#define PCM 1
-#define PCM8 2
-#define IEEE_FLOAT 3
-#define ALAW 4
-#define MULAW 5
-
-#define SAMPLING_FREQ_CONTROL 0x01
-
-typedef struct Audioalt Audioalt;
-
-struct Audioalt {
-	int		nchan;
-	int		res;
-	int		subframesize;
-	int		minfreq, maxfreq;	/* continuous freqs */
-	int		freqs[8];		/* discrete freqs */
-	int		caps;		/* see below for meanings */
-};
-
-enum {
-	/* Audioalt->caps bits */
-	has_setspeed = 0x1,		/* has a speed_set command */
-	has_pitchset = 0x2,		/* has a pitch_set command */
-	has_contfreq = 0x4,		/* frequency continuously variable */
-	has_discfreq = 0x8,		/* discrete set of frequencies */
-	onefreq = 0x10,		/* only one frequency */
-	maxpkt_only = 0x80,	/* packets must be padded to max size */
-};
-
-typedef uchar byte;
-
-extern int setrec;
-extern int verbose;
-extern int defaultspeed[2];
-extern Dev *ad;
-extern Dev *buttondev;
-extern Channel *controlchan;
-extern Dev *epdev[2];
-
-void	audio_interface(Dev *d, Desc *dd);
-void	setalt(Dev *d, int endpt, int value);
-int	getalt(Dev *d, int endpt);
-int	setspeed(int rec, int speed);
-int	setcontrol(int rec, char *name, long *value);
-int	getspecialcontrol(int rec, int ctl, int req, long *value);
-int	getcontrol(int rec, char *name, long *value);
-int	findalt(int rec, int nchan, int res, int speed);
-void	getcontrols(void);
-void	serve(void *);
-int	nbchanprint(Channel *c, char *fmt, ...);
-int	Aconv(Fmt *fp);
--- a/sys/src/cmd/usb/audio/audioctl.c
+++ /dev/null
@@ -1,688 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "audio.h"
-#include "audioctl.h"
-
-int endpt[2] =		{-1, -1};
-int interface[2] =	{-1, -1};
-int featureid[2] =	{-1, -1};
-int selectorid[2] =	{-1, -1};
-int mixerid[2] =	{-1, -1};
-int curalt[2] =		{-1, -1};
-int buttonendpt =	-1;
-
-int id;
-Dev *ad;
-
-Audiocontrol controls[2][Ncontrol] = {
-	{
-	[Speed_control] = {		"speed",	0, {0}, 0,	44100,	Undef},
-	[Mute_control] = {		"mute",		0, {0}, 0,	0,	Undef},
-	[Volume_control] = {		"volume",	0, {0}, 0,	0,	Undef},
-	[Bass_control] = {		"bass",		0, {0}, 0,	0,	Undef},
-	[Mid_control] = {		"mid",		0, {0}, 0,	0,	Undef},
-	[Treble_control] = {		"treble",	0, {0}, 0,	0,	Undef},
-	[Equalizer_control] = {		"equalizer",	0, {0}, 0,	0,	Undef},
-	[Agc_control] = {		"agc",		0, {0}, 0,	0,	Undef},
-	[Delay_control] = {		"delay",	0, {0}, 0,	0,	Undef},
-	[Bassboost_control] = {		"bassboost",	0, {0}, 0,	0,	Undef},
-	[Loudness_control] = {		"loudness",	0, {0}, 0,	0,	Undef},
-	[Channel_control] = {		"channels",	0, {0}, 0,	2,	Undef},
-	[Resolution_control] = {	"resolution",	0, {0}, 0,	16,	Undef},
-//	[Selector_control] = {		"selector",	0, {0}, 0,	0,	Undef},
-	}, {
-	[Speed_control] = {		"speed",	0, {0}, 0,	44100,	Undef},
-	[Mute_control] = {		"mute",		0, {0}, 0,	0,	Undef},
-	[Volume_control] = {		"volume",	0, {0}, 0,	0,	Undef},
-	[Bass_control] = {		"bass",		0, {0}, 0,	0,	Undef},
-	[Mid_control] = {		"mid",		0, {0}, 0,	0,	Undef},
-	[Treble_control] = {		"treble",	0, {0}, 0,	0,	Undef},
-	[Equalizer_control] = {		"equalizer",	0, {0}, 0,	0,	Undef},
-	[Agc_control] = {		"agc",		0, {0}, 0,	0,	Undef},
-	[Delay_control] = {		"delay",	0, {0}, 0,	0,	Undef},
-	[Bassboost_control] = {		"bassboost",	0, {0}, 0,	0,	Undef},
-	[Loudness_control] = {		"loudness",	0, {0}, 0,	0,	Undef},
-	[Channel_control] = {		"channels",	0, {0}, 0,	2,	Undef},
-	[Resolution_control] = {	"resolution",	0, {0}, 0,	16,	Undef},
-//	[Selector_control] = {		"selector",	0, {0}, 0,	0,	Undef},
-	}
-};
-
-int
-setaudioalt(int rec, Audiocontrol *c, int control)
-{
-	dprint(2, "setcontrol %s: Set alt %d\n", c->name, control);
-	curalt[rec] = control;
-	if(usbcmd(ad, Rh2d|Rstd|Riface, Rsetiface, control, interface[rec], nil, 0) < 0){
-		dprint(2, "setcontrol: setupcmd %s failed\n", c->name);
-		return -1;
-	}
-	return control;
-}
-
-int
-findalt(int rec, int nchan, int res, int speed)
-{
-	Ep *ep;
-	Audioalt *a;
-	Altc *da;
-	int i, j, k, retval;
-
-	retval = -1;
-	controls[rec][Channel_control].min = 1000000;
-	controls[rec][Channel_control].max = 0;
-	controls[rec][Channel_control].step = Undef;
-	controls[rec][Resolution_control].min = 1000000;
-	controls[rec][Resolution_control].max = 0;
-	controls[rec][Resolution_control].step = Undef;
-	for(i = 0; i < nelem(ad->usb->ep); i++){
-		if((ep = ad->usb->ep[i]) == nil)
-			continue;
-		if(ep->iface == nil){
-			fprint(2, "\tno interface\n");
-			return 0;
-		}
-		if(ep->iface->csp != CSP(Claudio, 2, 0))
-			continue;
-		if((rec == Play && (ep->addr &  0x80))
-		|| (rec == Record && (ep->addr &  0x80) == 0))
-			continue;
-		for(j = 0; j < 16; j++){
-			if((da = ep->iface->altc[j]) == nil || (a = da->aux) == nil)
-				continue;
-			if(a->nchan < controls[rec][Channel_control].min)
-				controls[rec][Channel_control].min = a->nchan;
-			if(a->nchan > controls[rec][Channel_control].max)
-				controls[rec][Channel_control].max = a->nchan;
-			if(a->res < controls[rec][Resolution_control].min)
-				controls[rec][Resolution_control].min = a->res;
-			if(a->res > controls[rec][Resolution_control].max)
-				controls[rec][Resolution_control].max = a->res;
-			controls[rec][Channel_control].settable = 1;
-			controls[rec][Channel_control].readable = 1;
-			controls[rec][Resolution_control].settable = 1;
-			controls[rec][Resolution_control].readable = 1;
-			controls[rec][Speed_control].settable = 1;
-			controls[rec][Speed_control].readable = 1;
-			if(a->nchan == nchan && a->res == res){
-				if(speed == Undef)
-					retval = j;
-				else if(a->caps & (has_discfreq|onefreq)){
-					for(k = 0; k < nelem(a->freqs); k++){
-						if(a->freqs[k] == speed){
-							retval = j;
-							break;
-						}
-					}
-				}else{
-					if(speed >= a->minfreq && speed <= a->maxfreq)
-						retval = j;
-				}
-			}
-		}
-	}
-	if(usbdebug && retval < 0)
-		fprint(2, "findalt(%d, %d, %d, %d) failed\n", rec, nchan, res, speed);
-	return retval;
-}
-
-int
-setspeed(int rec, int speed)
-{
-	int n, no, dist, i;
-	Audioalt *a;
-	Altc *da;
-	Ep *ep;
-	uchar buf[3];
-
-	if(rec == Record && !setrec)
-		return Undef;
-	if(curalt[rec] < 0){
-		fprint(2, "Must set channels and resolution before speed\n");
-		return Undef;
-	}
-	if(endpt[rec] < 0)
-		sysfatal("endpt[%s] not set", rec?"Record":"Playback");
-	ep = ad->usb->ep[endpt[rec]];
-	if(ep->iface == nil)
-		sysfatal("no interface");
-	if(curalt[rec] < 0)
-		sysfatal("curalt[%s] not set", rec?"Record":"Playback");
-	da = ep->iface->altc[curalt[rec]];
-	a = da->aux;
-	if(a->caps & onefreq){
-		dprint(2, "setspeed %d: onefreq\n", speed);
-		/* speed not settable, but packet size must still be set */
-		speed = a->freqs[0];
-	}else if(a->caps & has_contfreq){
-		dprint(2, "setspeed %d: contfreq\n", speed);
-		if(speed < a->minfreq)
-			speed = a->minfreq;
-		else if(speed > a->maxfreq)
-			speed = a->maxfreq;
-		dprint(2, "Setting continuously variable %s speed to %d\n",
-				rec?"record":"playback", speed);
-	}else if(a->caps & has_discfreq){
-		dprint(2, "setspeed %d: discfreq\n", speed);
-		dist = 1000000;
-		no = -1;
-		for(i = 0; a->freqs[i] > 0; i++)
-			if(abs(a->freqs[i] - speed) < dist){
-				dist = abs(a->freqs[i] - speed);
-				no = i;
-			}
-		if(no == -1){
-			dprint(2, "no = -1\n");
-			return Undef;
-		}
-		speed = a->freqs[no];
-		dprint(2, "Setting discreetly variable %s speed to %d\n",
-				rec?"record":"playback", speed);
-	}else{
-		dprint(2, "can't happen\n?");
-		return Undef;
-	}
-	if(a->caps & has_setspeed){
-		dprint(2, "Setting %s speed to %d Hz;", rec?"record":"playback", speed);
-		buf[0] = speed;
-		buf[1] = speed >> 8;
-		buf[2] = speed >> 16;
-		n = endpt[rec];
-		if(rec)
-			n |= 0x80;
-		if(usbcmd(ad, Rh2d|Rclass|Rep, Rsetcur, sampling_freq_control<<8, n, buf, 3) < 0){
-			fprint(2, "Error in setupcmd\n");
-			return Undef;
-		}
-		if((n=usbcmd(ad, Rd2h|Rclass|Rep, Rgetcur, sampling_freq_control<<8, n, buf, 3)) < 0){
-			fprint(2, "Error in setupreq\n");
-			return Undef;
-		}
-		if(n != 3)
-			fprint(2, "Error in setupreply: %d\n", n);
-		else{
-			n = buf[0] | buf[1] << 8 | buf[2] << 16;
-			if(buf[2] || n == 0){
-				dprint(2, "Speed out of bounds %d (0x%x)\n", n, n);
-			}else if(n != speed && ad->usb->vid == 0x077d &&
-			    (ad->usb->did == 0x0223 || ad->usb->did == 0x07af)){
-				/* Griffin iMic responds incorrectly to sample rate inquiry */
-				dprint(2, " reported as %d (iMic bug?);", n);
-			}else
-				speed = n;
-		}
-		dprint(2, " speed now %d Hz;", speed);
-	}
-	dprint(2, "Configuring %s endpoint for %d Hz\n",
-				rec?"record":"playback", speed);
-	epdev[rec] = openep(ad, endpt[rec]);
-	if(epdev[rec] == nil)
-		sysfatal("openep rec %d: %r", rec);
-
-	devctl(epdev[rec], "pollival %d", da->interval);
-	devctl(epdev[rec], "samplesz %ld", controls[rec][Channel_control].value[0] *
-				controls[rec][Resolution_control].value[0]/8);
-	devctl(epdev[rec], "hz %d", speed);
-
-	/* NO: the client uses the endpoint file directly
-	if(opendevdata(epdev[rec], rec ? OREAD : OWRITE) < 0)
-		sysfatal("openep rec %d: %r", rec);
-	*/
-	return speed;
-}
-
-long
-getspeed(int rec, int which)
-{
-	int i, n;
-	Audioalt *a;
-	Altc *da;
-	Ep *ep;
-	uchar buf[3];
-	int r;
-
-	if(curalt[rec] < 0){
-		fprint(2, "Must set channels and resolution before getspeed\n");
-		return Undef;
-	}
-	if(endpt[rec] < 0)
-		sysfatal("endpt[%s] not set", rec?"Record":"Playback");
-	dprint(2, "getspeed: endpt[%d] == %d\n", rec, endpt[rec]);
-	ep = ad->usb->ep[endpt[rec]];
-	if(ep->iface == nil)
-		sysfatal("no interface");
-	if(curalt[rec] < 0)
-		sysfatal("curalt[%s] not set", rec?"Record":"Playback");
-	da = ep->iface->altc[curalt[rec]];
-	a = da->aux;
-	if(a->caps & onefreq){
-		dprint(2, "getspeed: onefreq\n");
-		if(which == Rgetres)
-			return Undef;
-		return a->freqs[0];		/* speed not settable */
-	}
-	if(a->caps & has_setspeed){
-		dprint(2, "getspeed: has_setspeed, ask\n");
-		n = endpt[rec];
-		if(rec)
-			n |= 0x80;
-		r = Rd2h|Rclass|Rep;
-		if(usbcmd(ad,r,which,sampling_freq_control<<8, n, buf, 3) < 0)
-			return Undef;
-		if(n == 3){
-			if(buf[2]){
-				dprint(2, "Speed out of bounds\n");
-				if((a->caps & has_discfreq) && (buf[0] | buf[1] << 8) < 8)
-					return a->freqs[buf[0] | buf[1] << 8];
-			}
-			return buf[0] | buf[1] << 8 | buf[2] << 16;
-		}
-		dprint(2, "getspeed: n = %d\n", n);
-	}
-	if(a->caps & has_contfreq){
-		dprint(2, "getspeed: has_contfreq\n");
-		if(which == Rgetcur)
-			return controls[rec][Speed_control].value[0];
-		if(which == Rgetmin)
-			return a->minfreq;
-		if(which == Rgetmax)
-			return a->maxfreq;
-		if(which == Rgetres)
-			return 1;
-	}
-	if(a->caps & has_discfreq){
-		dprint(2, "getspeed: has_discfreq\n");
-		if(which == Rgetcur)
-			return controls[rec][Speed_control].value[0];
-		if(which == Rgetmin)
-			return a->freqs[0];
-		for(i = 0; i < 8 && a->freqs[i] > 0; i++)
-			;
-		if(which == Rgetmax)
-			return a->freqs[i-1];
-		if(which == Rgetres)
-			return Undef;
-	}
-	dprint(2, "can't happen\n?");
-	return Undef;
-}
-
-int
-setcontrol(int rec, char *name, long *value)
-{
-	int i, ctl, m;
-	byte buf[3];
-	int type, req, control, index, count;
-	Audiocontrol *c;
-
-	c = nil;
-	for(ctl = 0; ctl < Ncontrol; ctl++){
-		c = &controls[rec][ctl];
-		if(strcmp(name, c->name) == 0)
-			break;
-	}
-	if(ctl == Ncontrol){
-		dprint(2, "setcontrol: control not found\n");
-		return -1;
-	}
-	if(c->settable == 0){
-		dprint(2, "setcontrol: control %d.%d not settable\n", rec, ctl);
-		if(c->chans){
-			for(i = 0; i < 8; i++)
-				if((c->chans & 1 << i) && c->value[i] != value[i])
-					return -1;
-			return 0;
-		}
-		if(c->value[0] != value[0])
-			return -1;
-		return 0;
-	}
-	if(c->chans){
-		value[0] = 0;	// set to average
-		m = 0;
-		for(i = 1; i < 8; i++)
-			if(c->chans & 1 << i){
-				if(c->min != Undef && value[i] < c->min)
-					value[i] = c->min;
-				if(c->max != Undef && value[i] > c->max)
-					value[i] = c->max;
-				value[0] += value[i];
-				m++;
-			}else
-				value[i] = Undef;
-		if(m) value[0] /= m;
-	}else{
-		if(c->min != Undef && value[0] < c->min)
-			value[0] = c->min;
-		if(c->max != Undef && value[0] > c->max)
-			value[0] = c->max;
-	}
-	req = Rsetcur;
-	count = 1;
-	switch(ctl){
-	default:
-		dprint(2, "setcontrol: can't happen\n");
-		return -1;
-	case Speed_control:
-		if((rec != Record || setrec) && (value[0] = setspeed(rec, value[0])) < 0)
-			return -1;
-		c->value[0] = value[0];
-		return 0;
-	case Equalizer_control:
-		/* not implemented */
-		return -1;
-	case Resolution_control:
-		control = findalt(rec, controls[rec][Channel_control].value[0], value[0], defaultspeed[rec]);
-		if(control < 0 || setaudioalt(rec, c, control) < 0){
-			dprint(2, "setcontrol: can't find setting for %s\n", c->name);
-			return -1;
-		}
-		c->value[0] = value[0];
-		controls[rec][Speed_control].value[0] = defaultspeed[rec];
-		return 0;
-	case Volume_control:
-	case Delay_control:
-		count = 2;
-		/* fall through */
-	case Mute_control:
-	case Bass_control:
-	case Mid_control:
-	case Treble_control:
-	case Agc_control:
-	case Bassboost_control:
-	case Loudness_control:
-		type = Rh2d|Rclass|Riface;
-		control = ctl<<8;
-		index = featureid[rec]<<8;
-		break;
-	case Selector_control:
-		type = Rh2d|Rclass|Riface;
-		control = 0;
-		index = selectorid[rec]<<8;
-		break;
-	case Channel_control:
-		control = findalt(rec, value[0], controls[rec][Resolution_control].value[0], defaultspeed[rec]);
-		if(control < 0 || setaudioalt(rec, c, control) < 0){
-			dprint(2, "setcontrol: can't find setting for %s\n", c->name);
-			return -1;
-		}
-		c->value[0] = value[0];
-		controls[rec][Speed_control].value[0] = defaultspeed[rec];
-		return 0;
-	}
-	if(c->chans){
-		for(i = 1; i < 8; i++)
-			if(c->chans & 1 << i){
-				switch(count){
-				case 2:
-					buf[1] = value[i] >> 8;
-				case 1:
-					buf[0] = value[i];
-				}
-				if(usbcmd(ad, type, req, control | i, index, buf, count) < 0){
-					dprint(2, "setcontrol: setupcmd %s failed\n",
-						controls[rec][ctl].name);
-					return -1;
-				}
-				c->value[i] = value[i];
-			}
-	}else{
-		switch(count){
-		case 2:
-			buf[1] = value[0] >> 8;
-		case 1:
-			buf[0] = value[0];
-		}
-		if(usbcmd(ad, type, req, control, index, buf, count) < 0){
-			dprint(2, "setcontrol: setupcmd %s failed\n", c->name);
-			return -1;
-		}
-	}
-	c->value[0] = value[0];
-	return 0;
-}
-
-int
-getspecialcontrol(int rec, int ctl, int req, long *value)
-{
-	byte buf[3];
-	int m, n, i;
-	int type, control, index, count, signedbyte;
-	short svalue;
-
-	count = 1;
-	signedbyte = 0;
-	switch(ctl){
-	default:
-		return Undef;
-	case Speed_control:
-		value[0] =  getspeed(rec, req);
-		return 0;
-	case Channel_control:
-	case Resolution_control:
-		if(req == Rgetmin)
-			value[0] = controls[rec][ctl].min;
-		if(req == Rgetmax)
-			value[0] = controls[rec][ctl].max;
-		if(req == Rgetres)
-			value[0] = controls[rec][ctl].step;
-		if(req == Rgetcur)
-			value[0] = controls[rec][ctl].value[0];
-		return 0;
-	case Volume_control:
-	case Delay_control:
-		count = 2;
-		/* fall through */
-	case Bass_control:
-	case Mid_control:
-	case Treble_control:
-	case Equalizer_control:
-		signedbyte = 1;
-		type = Rd2h|Rclass|Riface;
-		control = ctl<<8;
-		index = featureid[rec]<<8;
-		break;
-	case Selector_control:
-		type = Rd2h|Rclass|Riface;
-		control = 0;
-		index = selectorid[rec]<<8;
-		break;
-	case Mute_control:
-	case Agc_control:
-	case Bassboost_control:
-	case Loudness_control:
-		if(req != Rgetcur)
-			return Undef;
-		type = Rd2h|Rclass|Riface;
-		control = ctl<<8;
-		index = featureid[rec]<<8;
-		break;
-	}
-	if(controls[rec][ctl].chans){
-		m = 0;
-		value[0] = 0; // set to average
-		for(i = 1; i < 8; i++){
-			value[i] = Undef;
-			if(controls[rec][ctl].chans & 1 << i){
-				n=usbcmd(ad, type,req, control|i,index,buf,count);
-				if(n < 0)
-					return Undef;
-				if(n != count)
-					return -1;
-				switch (count){
-				case 2:
-					svalue = buf[1] << 8 | buf[0];
-					if(req == Rgetcur){
-						value[i] = svalue;
-						value[0] += svalue;
-						m++;
-					}else
-						value[0] = svalue;
-					break;
-				case 1:
-					svalue = buf[0];
-					if(signedbyte && (svalue&0x80))
-						svalue |= 0xFF00;
-					if(req == Rgetcur){
-						value[i] = svalue;
-						value[0] += svalue;
-						m++;
-					}else
-						value[0] = svalue;
-				}
-			}
-		}
-		if(m) value[0] /= m;
-		return 0;
-	}
-	value[0] = Undef;
-	if(usbcmd(ad, type, req, control, index, buf, count) != count)
-		return -1;
-	switch (count){
-	case 2:
-		svalue = buf[1] << 8 | buf[0];
-		value[0] = svalue;
-		break;
-	case 1:
-		svalue = buf[0];
-		if(signedbyte && (svalue&0x80))
-			svalue |= 0xFF00;
-		value[0] = svalue;
-	}
-	return 0;
-}
-
-int
-getcontrol(int rec, char *name, long *value)
-{
-	int i;
-
-	for(i = 0; i < Ncontrol; i++){
-		if(strcmp(name, controls[rec][i].name) == 0)
-			break;
-	}
-	if(i == Ncontrol)
-		return -1;
-	if(controls[rec][i].readable == 0)
-		return -1;
-	if(getspecialcontrol(rec, i, Rgetcur, value) < 0)
-		return -1;
-	memmove(controls[rec][i].value, value, sizeof controls[rec][i].value);
-	return 0;
-}
-
-void
-getcontrols(void)
-{
-	int rec, ctl, i;
-	Audiocontrol *c;
-	long v[8];
-
-	for(rec = 0; rec < 2; rec++){
-		if(rec == Record && !setrec)
-			continue;
-		for(ctl = 0; ctl < Ncontrol; ctl++){
-			c = &controls[rec][ctl];
-			if(c->readable){
-				if(verbose)
-					fprint(2, "%s %s control",
-						rec?"Record":"Playback", controls[rec][ctl].name);
-				c->min = (getspecialcontrol(rec, ctl, Rgetmin, v) < 0) ? Undef : v[0];
-				if(verbose && c->min != Undef)
-					fprint(2, ", min %ld", c->min);
-				c->max = (getspecialcontrol(rec, ctl, Rgetmax, v) < 0) ? Undef : v[0];
-				if(verbose && c->max != Undef)
-					fprint(2, ", max %ld", c->max);
-				c->step = (getspecialcontrol(rec, ctl, Rgetres, v) < 0) ? Undef : v[0];
-				if(verbose && c->step != Undef)
-					fprint(2, ", step %ld", c->step);
-				if(getspecialcontrol(rec, ctl, Rgetcur, c->value) == 0){
-					if(verbose){
-						if(c->chans){
-							fprint(2, ", values");
-							for(i = 1; i < 8; i++)
-								if(c->chans & 1 << i)
-									fprint(2, "[%d] %ld  ", i, c->value[i]);
-						}else
-							fprint(2, ", value %ld", c->value[0]);
-					}
-				}
-				if(verbose)
-					fprint(2, "\n");
-			}else{
-				c->min = Undef;
-				c->max = Undef;
-				c->step = Undef;
-				c->value[0] = Undef;
-				dprint(2, "%s %s control not settable\n",
-					rec?"Playback":"Record", controls[rec][ctl].name);
-			}
-		}
-	}
-}
-
-int
-ctlparse(char *s, Audiocontrol *c, long *v)
-{
-	int i, j, nf, m;
-	char *vals[9];
-	char *p;
-	long val;
-
-	nf = tokenize(s, vals, nelem(vals));
-	if(nf <= 0)
-		return -1;
-	if(c->chans){
-		j = 0;
-		m = 0;
-		SET(val);
-		v[0] = 0;	// will compute average of v[i]
-		for(i = 1; i < 8; i++)
-			if(c->chans & 1 << i){
-				if(j < nf){
-					val = strtol(vals[j], &p, 0);
-					if(val == 0 && *p != '\0' && *p != '%')
-						return -1;
-					if(*p == '%' && c->min != Undef)
-						val = (val*c->max + (100-val)*c->min)/100;
-					j++;
-				}
-				v[i] = val;
-				v[0] += val;
-				m++;
-			}else
-				v[i] = Undef;
-		if(m) v[0] /= m;
-	}else{
-		val = strtol(vals[0], &p, 0);
-		if(*p == '%' && c->min != Undef)
-			val = (val*c->max + (100-val)*c->min)/100;
-		v[0] = val;
-	}
-	return 0;
-}
-
-int
-Aconv(Fmt *fp)
-{
-	char str[256];
-	Audiocontrol *c;
-	int fst, i;
-	char *p;
-
-	c = va_arg(fp->args, Audiocontrol*);
-	p = str;
-	if(c->chans){
-		fst = 1;
-		for(i = 1; i < 8; i++)
-			if(c->chans & 1 << i){
-				p = seprint(p, str+sizeof str, "%s%ld", fst?"'":" ", c->value[i]);
-				fst = 0;
-			}
-		seprint(p, str+sizeof str, "'");
-	}else
-		seprint(p, str+sizeof str, "%ld", c->value[0]);
-	return fmtstrcpy(fp, str);
-}
--- a/sys/src/cmd/usb/audio/audioctl.h
+++ /dev/null
@@ -1,29 +1,0 @@
-enum{
-	Undef = 0x80000000,
-	Play = 0,
-	Record = 1,
-};
-
-typedef struct Audiocontrol Audiocontrol;
-
-struct Audiocontrol {
-	char	*name;
-	uchar	readable;
-	uchar	settable;
-	uchar	chans;		/* 0 is master, non-zero is bitmap */
-	long	value[8];	/* 0 is master; value[0] == Undef -> all values Undef */
-	long	min, max, step;
-};
-
-extern Audiocontrol controls[2][Ncontrol];
-extern int endpt[2];
-extern int interface[2];
-extern int featureid[2];
-extern int selectorid[2];
-extern int mixerid[2];
-extern int buttonendpt;
-
-int	ctlparse(char *s, Audiocontrol *c, long *v);
-void	ctlevent(void);
-
-#pragma	varargck	type	"A"	Audiocontrol*
--- a/sys/src/cmd/usb/audio/audiofs.c
+++ /dev/null
@@ -1,939 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <auth.h>
-#include <fcall.h>
-#include <libsec.h>
-#include "usb.h"
-#include "audio.h"
-#include "audioctl.h"
-
-int attachok;
-
-#define STACKSIZE 16*1024
-
-enum
-{
-	OPERM	= 0x3,	/* mask of all permission types in open mode */
-};
-
-typedef struct Fid Fid;
-typedef struct Audioctldata Audioctldata;
-typedef struct Worker Worker;
-
-struct Audioctldata
-{
-	long	offoff;			/* offset of the offset for audioctl */
-	long	values[2][Ncontrol][8];	/* last values transmitted */
-	char	*s;
-	int	ns;
-};
-
-enum {
-	Busy =	0x01,
-	Open =	0x02,
-	Eof =	0x04,
-};
-
-struct Fid
-{
-	QLock;
-	int	fid;
-	Dir	*dir;
-	ushort	flags;
-	short	readers;
-	void	*fiddata;  /* file specific per-fid data (used for audioctl) */
-	Fid	*next;
-};
-
-struct Worker
-{
-	Fid	*fid;
-	ushort	tag;
-	Fcall	*rhdr;
-	Dir	*dir;
-	Channel	*eventc;
-	Worker	*next;
-};
-
-enum {
-	/* Event channel messages for worker */
-	Work =	0x01,
-	Check =	0x02,
-	Flush =	0x03,
-};
-
-enum {
-	Qdir,
-	Qvolume,
-	Qaudioctl,
-	Qaudiostat,
-	Nqid,
-};
-
-Dir dirs[] = {
-[Qdir] =		{0,0,{Qdir,      0,QTDIR},0555|DMDIR,0,0,0, ".",  nil,nil,nil},
-[Qvolume] =	{0,0,{Qvolume,   0,QTFILE},0666,0,0,0,	"volume", nil,nil,nil},
-[Qaudioctl] =	{0,0,{Qaudioctl, 0,QTFILE},0666,0,0,0,	"audioctl",nil,nil,nil},
-[Qaudiostat] =	{0,0,{Qaudiostat,0,QTFILE},0666,0,0,0,	"audiostat",nil,nil,nil},
-};
-
-int	messagesize = 4*1024+IOHDRSZ;
-uchar	mdata[8*1024+IOHDRSZ];
-uchar	mbuf[8*1024+IOHDRSZ];
-
-Fcall	thdr;
-Fcall	rhdr;
-Worker *workers;
-
-char srvfile[64], mntdir[64], epdata[64], audiofile[64];
-int mfd[2], p[2];
-char user[32];
-char *srvpost;
-
-Channel *procchan;
-Channel *replchan;
-
-Fid *fids;
-
-Fid*		newfid(int);
-void		io(void *);
-void		usage(void);
-
-extern char *mntpt;
-
-char	*rflush(Fid*), *rauth(Fid*),
-	*rattach(Fid*), *rwalk(Fid*),
-	*ropen(Fid*), *rcreate(Fid*),
-	*rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
-	*rremove(Fid*), *rstat(Fid*), *rwstat(Fid*),
-	*rversion(Fid*);
-
-char 	*(*fcalls[])(Fid*) = {
-	[Tflush]	rflush,
-	[Tversion]	rversion,
-	[Tauth]		rauth,
-	[Tattach]	rattach,
-	[Twalk]		rwalk,
-	[Topen]		ropen,
-	[Tcreate]	rcreate,
-	[Tread]		rread,
-	[Twrite]	rwrite,
-	[Tclunk]	rclunk,
-	[Tremove]	rremove,
-	[Tstat]		rstat,
-	[Twstat]	rwstat,
-};
-
-char	Eperm[] =	"permission denied";
-char	Enotdir[] =	"not a directory";
-char	Enoauth[] =	"no authentication in ramfs";
-char	Enotexist[] =	"file does not exist";
-char	Einuse[] =	"file in use";
-char	Eexist[] =	"file exists";
-char	Enotowner[] =	"not owner";
-char	Eisopen[] = 	"file already open for I/O";
-char	Excl[] = 	"exclusive use file already open";
-char	Ename[] = 	"illegal name";
-char	Ebadctl[] =	"unknown control message";
-
-int
-notifyf(void *, char *s)
-{
-	if(strncmp(s, "interrupt", 9) == 0)
-		return 1;
-	return 0;
-}
-
-void
-post(char *name, char *envname, int srvfd)
-{
-	int fd;
-	char buf[32];
-
-	fd = create(name, OWRITE, attachok?0666:0600);
-	if(fd < 0)
-		return;
-	snprint(buf, sizeof buf, "%d", srvfd);
-	if(write(fd, buf, strlen(buf)) != strlen(buf))
-		sysfatal("srv write");
-	close(fd);
-	putenv(envname, name);
-}
-
-/*
- * BUG: If audio is later used on a different name space, the
- * audio/audioin files are not there because of the bind trick.
- * We should actually implement those files despite the binds.
- * If audio is used from within the same ns nothing would change,
- * otherwise, whoever would mount the audio files could still
- * play/record audio (unlike now).
- */
-void
-serve(void *)
-{
-	int i;
-	ulong t;
-
-	if(pipe(p) < 0)
-		sysfatal("pipe failed");
-	mfd[0] = p[0];
-	mfd[1] = p[0];
-
-	atnotify(notifyf, 1);
-	strcpy(user, getuser());
-	t = time(nil);
-	for(i = 0; i < Nqid; i++){
-		dirs[i].uid = user;
-		dirs[i].gid = user;
-		dirs[i].muid = user;
-		dirs[i].atime = t;
-		dirs[i].mtime = t;
-	}
-	if(mntpt == nil){
-		snprint(mntdir, sizeof(mntdir), "/dev");
-		mntpt = mntdir;
-	}
-
-	if(usbdebug)
-		fmtinstall('F', fcallfmt);
-
-	procrfork(io, nil, STACKSIZE, RFFDG|RFNAMEG);
-
-	close(p[0]);	/* don't deadlock if child fails */
-	if(srvpost){
-		snprint(srvfile, sizeof srvfile, "/srv/%s", srvpost);
-		remove(srvfile);
-		post(srvfile, "usbaudio", p[1]);
-	}
-	if(mount(p[1], -1, mntpt, MBEFORE, "") < 0)
-		sysfatal("mount failed");
-	if(endpt[Play] >= 0 && devctl(epdev[Play], "name audio") < 0)
-		fprint(2, "audio: name audio: %r\n");
-	if(endpt[Record] >= 0 && devctl(epdev[Record], "name audioin") < 0)
-		fprint(2, "audio: name audioin: %r\n");
-	threadexits(nil);
-}
-
-char*
-rversion(Fid*)
-{
-	Fid *f;
-
-	if(thdr.msize < 256)
-		return "max messagesize too small";
-	if(thdr.msize < messagesize)
-		messagesize = thdr.msize;
-	rhdr.msize = messagesize;
-	if(strncmp(thdr.version, "9P2000", 6) != 0)
-		return "unknown 9P version";
-	else
-		rhdr.version = "9P2000";
-	for(f = fids; f; f = f->next)
-		if(f->flags & Busy)
-			rclunk(f);
-	return nil;
-}
-
-char*
-rauth(Fid*)
-{
-	return "usbaudio: no authentication required";
-}
-
-char*
-rflush(Fid *)
-{
-	Worker *w;
-	int waitflush;
-
-	do {
-		waitflush = 0;
-		for(w = workers; w; w = w->next)
-			if(w->tag == thdr.oldtag){
-				waitflush++;
-				nbsendul(w->eventc, thdr.oldtag << 16 | Flush);
-			}
-		if(waitflush)
-			sleep(50);
-	} while(waitflush);
-	dprint(2, "flush done on tag %d\n", thdr.oldtag);
-	return 0;
-}
-
-char*
-rattach(Fid *f)
-{
-	f->flags |= Busy;
-	f->dir = &dirs[Qdir];
-	rhdr.qid = f->dir->qid;
-	if(attachok == 0 && strcmp(thdr.uname, user) != 0)
-		return Eperm;
-	return 0;
-}
-
-static Fid*
-doclone(Fid *f, int nfid)
-{
-	Fid *nf;
-
-	nf = newfid(nfid);
-	if(nf->flags & Busy)
-		return nil;
-	nf->flags |= Busy;
-	nf->flags &= ~Open;
-	nf->dir = f->dir;
-	return nf;
-}
-
-char*
-dowalk(Fid *f, char *name)
-{
-	int t;
-
-	if(strcmp(name, ".") == 0)
-		return nil;
-	if(strcmp(name, "..") == 0){
-		f->dir = &dirs[Qdir];
-		return nil;
-	}
-	if(f->dir != &dirs[Qdir])
-		return Enotexist;
-	for(t = 1; t < Nqid; t++){
-		if(strcmp(name, dirs[t].name) == 0){
-			f->dir = &dirs[t];
-			return nil;
-		}
-	}
-	return Enotexist;
-}
-
-char*
-rwalk(Fid *f)
-{
-	Fid *nf;
-	char *rv;
-	int i;
-	Dir *savedir;
-
-	if(f->flags & Open)
-		return Eisopen;
-
-	rhdr.nwqid = 0;
-	nf = nil;
-	savedir = f->dir;
-	/* clone if requested */
-	if(thdr.newfid != thdr.fid){
-		nf = doclone(f, thdr.newfid);
-		if(nf == nil)
-			return "new fid in use";
-		f = nf;
-	}
-
-	/* if it's just a clone, return */
-	if(thdr.nwname == 0 && nf != nil)
-		return nil;
-
-	/* walk each element */
-	rv = nil;
-	for(i = 0; i < thdr.nwname; i++){
-		rv = dowalk(f, thdr.wname[i]);
-		if(rv != nil){
-			if(nf != nil)
-				rclunk(nf);
-			else
-				f->dir = savedir;
-			break;
-		}
-		rhdr.wqid[i] = f->dir->qid;
-	}
-	rhdr.nwqid = i;
-
-	/* we only error out if no walk  */
-	if(i > 0)
-		rv = nil;
-
-	return rv;
-}
-
-Audioctldata *
-allocaudioctldata(void)
-{
-	int i, j, k;
-	Audioctldata *a;
-
-	a = emallocz(sizeof(Audioctldata), 1);
-	for(i = 0; i < 2; i++)
-		for(j=0; j < Ncontrol; j++)
-			for(k=0; k < 8; k++)
-				a->values[i][j][k] = Undef;
-	return a;
-}
-
-char *
-ropen(Fid *f)
-{
-	if(f->flags & Open)
-		return Eisopen;
-
-	if(thdr.mode != OREAD && (f->dir->mode & 0x2) == 0)
-		return Eperm;
-	qlock(f);
-	if(f->dir == &dirs[Qaudioctl] && f->fiddata == nil)
-		f->fiddata = allocaudioctldata();
-	qunlock(f);
-	rhdr.iounit = 0;
-	rhdr.qid = f->dir->qid;
-	f->flags |= Open;
-	return nil;
-}
-
-char *
-rcreate(Fid*)
-{
-	return Eperm;
-}
-
-int
-readtopdir(Fid*, uchar *buf, long off, int cnt, int blen)
-{
-	int i, m, n;
-	long pos;
-
-	n = 0;
-	pos = 0;
-	for(i = 1; i < Nqid; i++){
-		m = convD2M(&dirs[i], &buf[n], blen-n);
-		if(off <= pos){
-			if(m <= BIT16SZ || m > cnt)
-				break;
-			n += m;
-			cnt -= m;
-		}
-		pos += m;
-	}
-	return n;
-}
-
-enum { Chunk = 1024, };
-
-int
-makeaudioctldata(Fid *f)
-{
-	int rec, ctl, i, diff;
-	long *actls;		/* 8 of them */
-	char *p, *e;
-	Audiocontrol *c;
-	Audioctldata *a;
-
-	if((a = f->fiddata) == nil)
-		sysfatal("fiddata");
-	if((p = a->s) == nil)
-		a->s = p = emallocz(Chunk, 0);
-	e = p + Chunk - 1;	/* e must point *at* last byte, not *after* */
-	for(rec = 0; rec < 2; rec++)
-		for(ctl = 0; ctl < Ncontrol; ctl++){
-			c = &controls[rec][ctl];
-			actls = a->values[rec][ctl];
-			diff = 0;
-			if(c->chans){
-				for(i = 1; i < 8; i++)
-					if((c->chans & 1<<i) &&
-					    c->value[i] != actls[i])
-						diff = 1;
-			}else
-				if(c->value[0] != actls[0])
-					diff = 1;
-			if(diff){
-				p = seprint(p, e, "%s %s %A", c->name,
-					rec? "in": "out", c);
-				memmove(actls, c->value, sizeof c->value);
-				if(c->min != Undef){
-					p = seprint(p, e, " %ld %ld", c->min,
-						c->max);
-					if(c->step != Undef)
-						p = seprint(p, e, " %ld",
-							c->step);
-				}
-				p = seprint(p, e, "\n");
-			}
-		}
-	assert(strlen(a->s) < Chunk);
-	a->ns = p - a->s;
-	return a->ns;
-}
-
-void
-readproc(void *x)
-{
-	int n, cnt;
-	ulong event;
-	vlong off;
-	uchar *mdata;
-	Audioctldata *a;
-	Fcall *rhdr;
-	Fid *f;
-	Worker *w;
-
-	w = x;
-	mdata = emallocz(8*1024+IOHDRSZ, 0);
-	while(event = recvul(w->eventc)){
-		if(event != Work)
-			continue;
-		f = w->fid;
-		rhdr = w->rhdr;
-		a = f->fiddata;
-		off = rhdr->offset;
-		cnt = rhdr->count;
-		assert(a->offoff == off);
-		/* f is already locked */
-		for(;;){
-			qunlock(f);
-			event = recvul(w->eventc);
-			qlock(f);
-			ddprint(2, "readproc unblocked fid %d %lld\n",
-					f->fid, f->dir->qid.path);
-			switch (event & 0xffff){
-			case Work:
-				sysfatal("readproc phase error");
-			case Check:
-				if(f->fiddata && makeaudioctldata(f) == 0)
-					continue;
-				break;
-			case Flush:
-				if((event >> 16) == rhdr->tag){
-					ddprint(2, "readproc flushing fid %d, tag %d\n",
-						f->fid, rhdr->tag);
-					goto flush;
-				}
-				continue;
-			}
-			if(f->fiddata){
-				rhdr->data = a->s;
-				rhdr->count = a->ns;
-				break;
-			}
-			yield();
-		}
-		if(rhdr->count > cnt)
-			rhdr->count = cnt;
-		if(rhdr->count)
-			f->flags &= ~Eof;
-		ddprint(2, "readproc:->%F\n", rhdr);
-		n = convS2M(rhdr, mdata, messagesize);
-		if(write(mfd[1], mdata, n) != n)
-			sysfatal("mount write");
-flush:
-		w->tag = NOTAG;
-		f->readers--;
-		assert(f->readers == 0);
-		free(rhdr);
-		w->rhdr = nil;
-		qunlock(f);
-		sendp(procchan, w);
-	}
-	threadexits(nil);
-}
-
-char*
-rread(Fid *f)
-{
-	int i, n, cnt, rec, div;
-	vlong off;
-	char *p;
-	Audiocontrol *c;
-	Audioctldata *a;
-	Worker *w;
-	static char buf[1024];
-
-	rhdr.count = 0;
-	off = thdr.offset;
-	cnt = thdr.count;
-
-	if(cnt > messagesize - IOHDRSZ)
-		cnt = messagesize - IOHDRSZ;
-
-	rhdr.data = (char*)mbuf;
-
-	if(f->dir == &dirs[Qdir]){
-		n = readtopdir(f, mbuf, off, cnt, messagesize - IOHDRSZ);
-		rhdr.count = n;
-		return nil;
-	}
-
-	if(f->dir == &dirs[Qvolume]){
-		p = buf;
-		n = sizeof buf;
-		for(rec = 0; rec < 2; rec++){
-			c = &controls[rec][Volume_control];
-			if(c->readable){
-				div = c->max - c->min;
-				i = snprint(p, n, "audio %s %ld\n",
-					rec? "in": "out", (c->min != Undef?
-					100*(c->value[0]-c->min)/(div? div: 1):
-					c->value[0]));
-				p += i;
-				n -= i;
-			}
-			c = &controls[rec][Treble_control];
-			if(c->readable){
-				div = c->max - c->min;
-				i = snprint(p, n, "treb %s %ld\n",
-					rec? "in": "out", (c->min != Undef?
-					100*(c->value[0]-c->min)/(div? div: 1):
-					c->value[0]));
-				p += i;
-				n -= i;
-			}
-			c = &controls[rec][Bass_control];
-			if(c->readable){
-				div = c->max - c->min;
-				i = snprint(p, n, "bass %s %ld\n",
-					rec? "in": "out", (c->min != Undef?
-					100*(c->value[0]-c->min)/(div? div: 1):
-					c->value[0]));
-				p += i;
-				n -= i;
-			}
-			c = &controls[rec][Speed_control];
-			if(c->readable){
-				i = snprint(p, n, "speed %s %ld\n",
-					rec? "in": "out", c->value[0]);
-				p += i;
-				n -= i;
-			}
-		}
-		n = sizeof buf - n;
-		if(off > n)
-			rhdr.count = 0;
-		else{
-			rhdr.data = buf + off;
-			rhdr.count = n - off;
-			if(rhdr.count > cnt)
-				rhdr.count = cnt;
-		}
-		return nil;
-	}
-
-	if(f->dir == &dirs[Qaudioctl]){
-		Fcall *hdr;
-
-		qlock(f);
-		a = f->fiddata;
-		if(off - a->offoff < 0){
-			/* there was a seek */
-			a->offoff = off;
-			a->ns = 0;
-		}
-		do {
-			if(off - a->offoff < a->ns){
-				rhdr.data = a->s + (off - a->offoff);
-				rhdr.count = a->ns - (off - a->offoff);
-				if(rhdr.count > cnt)
-					rhdr.count = cnt;
-				qunlock(f);
-				return nil;
-			}
-			if(a->offoff != off){
-				a->ns = 0;
-				a->offoff = off;
-				rhdr.count = 0;
-				qunlock(f);
-				return nil;
-			}
-		} while(makeaudioctldata(f) != 0);
-
-		assert(a->offoff == off);
-		/* Wait for data off line */
-		f->readers++;
-		w = nbrecvp(procchan);
-		if(w == nil){
-			w = emallocz(sizeof(Worker), 1);
-			w->eventc = chancreate(sizeof(ulong), 1);
-			w->next = workers;
-			workers = w;
-			proccreate(readproc, w, 4096);
-		}
-		hdr = emallocz(sizeof(Fcall), 0);
-		w->fid = f;
-		w->tag = thdr.tag;
-		assert(w->rhdr == nil);
-		w->rhdr = hdr;
-		hdr->count = cnt;
-		hdr->offset = off;
-		hdr->type = thdr.type+1;
-		hdr->fid = thdr.fid;
-		hdr->tag = thdr.tag;
-		sendul(w->eventc, Work);
-		return (char*)~0;
-	}
-
-	return Eperm;
-}
-
-char*
-rwrite(Fid *f)
-{
-	long cnt, value;
-	char *lines[2*Ncontrol], *fields[4], *subfields[9], *err, *p;
-	int nlines, i, nf, nnf, rec, ctl;
-	Audiocontrol *c;
-	Worker *w;
-	static char buf[256];
-
-	rhdr.count = 0;
-	cnt = thdr.count;
-
-	if(cnt > messagesize - IOHDRSZ)
-		cnt = messagesize - IOHDRSZ;
-
-	err = nil;
-	if(f->dir == &dirs[Qvolume] || f->dir == &dirs[Qaudioctl]){
-		thdr.data[cnt] = '\0';
-		nlines = getfields(thdr.data, lines, 2*Ncontrol, 1, "\n");
-		for(i = 0; i < nlines; i++){
-			dprint(2, "line: %s\n", lines[i]);
-			nf = tokenize(lines[i], fields, 4);
-			if(nf == 0)
-				continue;
-			if(nf == 3)
-				if(strcmp(fields[1], "in") == 0 ||
-				    strcmp(fields[1], "record") == 0)
-					rec = 1;
-				else if(strcmp(fields[1], "out") == 0 ||
-				    strcmp(fields[1], "playback") == 0)
-					rec = 0;
-				else{
-					dprint(2, "bad1\n");
-					return Ebadctl;
-				}
-			else if(nf == 2)
-				rec = 0;
-			else{
-				dprint(2, "bad2 %d\n", nf);
-				return Ebadctl;
-			}
-			c = nil;
-			if(strcmp(fields[0], "audio") == 0) /* special case */
-				fields[0] = "volume";
-			for(ctl = 0; ctl < Ncontrol; ctl++){
-				c = &controls[rec][ctl];
-				if(strcmp(fields[0], c->name) == 0)
-					break;
-			}
-			if(ctl == Ncontrol){
-				dprint(2, "bad3\n");
-				return Ebadctl;
-			}
-			if(f->dir == &dirs[Qvolume] && ctl != Speed_control &&
-			    c->min != Undef && c->max != Undef){
-				nnf = tokenize(fields[nf-1], subfields,
-					nelem(subfields));
-				if(nnf <= 0 || nnf > 8){
-					dprint(2, "bad4\n");
-					return Ebadctl;
-				}
-				p = buf;
-				for(i = 0; i < nnf; i++){
-					value = strtol(subfields[i], nil, 0);
-					value = ((100 - value)*c->min +
-						value*c->max) / 100;
-					if(p == buf){
-						dprint(2, "rwrite: %s %s '%ld",
-								c->name, rec?
-								"record":
-								"playback",
-								value);
-					}else
-						dprint(2, " %ld", value);
-					if(p == buf)
-						p = seprint(p, buf+sizeof buf,
-							"0x%p %s %s '%ld",
-							replchan, c->name, rec?
-							"record": "playback",
-							value);
-					else
-						p = seprint(p, buf+sizeof buf,
-							" %ld", value);
-				}
-				dprint(2, "'\n");
-				seprint(p, buf+sizeof buf-1, "'");
-				chanprint(controlchan, buf);
-			}else{
-				dprint(2, "rwrite: %s %s %q", c->name,
-						rec? "record": "playback",
-						fields[nf-1]);
-				chanprint(controlchan, "0x%p %s %s %q",
-					replchan, c->name, rec? "record":
-					"playback", fields[nf-1]);
-			}
-			p = recvp(replchan);
-			if(p){
-				if(strcmp(p, "ok") == 0){
-					free(p);
-					p = nil;
-				}
-				if(err == nil)
-					err = p;
-			}
-		}
-		for(w = workers; w; w = w->next)
-			nbsendul(w->eventc, Qaudioctl << 16 | Check);
-		rhdr.count = thdr.count;
-		return err;
-	}
-	return Eperm;
-}
-
-char *
-rclunk(Fid *f)
-{
-	Audioctldata *a;
-
-	qlock(f);
-	f->flags &= ~(Open|Busy);
-	assert(f->readers ==0);
-	if(f->fiddata){
-		a = f->fiddata;
-		if(a->s)
-			free(a->s);
-		free(a);
-		f->fiddata = nil;
-	}
-	qunlock(f);
-	return 0;
-}
-
-char *
-rremove(Fid *)
-{
-	return Eperm;
-}
-
-char *
-rstat(Fid *f)
-{
-	Audioctldata *a;
-
-	if(f->dir == &dirs[Qaudioctl]){
-		qlock(f);
-		if(f->fiddata == nil)
-			f->fiddata = allocaudioctldata();
-		a = f->fiddata;
-		if(a->ns == 0)
-			makeaudioctldata(f);
-		f->dir->length = a->offoff + a->ns;
-		qunlock(f);
-	}
-	rhdr.nstat = convD2M(f->dir, mbuf, messagesize - IOHDRSZ);
-	rhdr.stat = mbuf;
-	return 0;
-}
-
-char *
-rwstat(Fid*)
-{
-	return Eperm;
-}
-
-Fid *
-newfid(int fid)
-{
-	Fid *f, *ff;
-
-	ff = nil;
-	for(f = fids; f; f = f->next)
-		if(f->fid == fid)
-			return f;
-		else if(ff == nil && (f->flags & Busy) == 0)
-			ff = f;
-	if(ff == nil){
-		ff = emallocz(sizeof *ff, 1);
-		ff->next = fids;
-		fids = ff;
-	}
-	ff->fid = fid;
-	ff->flags &= ~(Busy|Open);
-	ff->dir = nil;
-	return ff;
-}
-
-void
-io(void *)
-{
-	char *err, e[32];
-	int n;
-
-	close(p[1]);
-
-	procchan = chancreate(sizeof(Channel*), 8);
-	replchan = chancreate(sizeof(char*), 0);
-	for(;;){
-		/*
-		 * reading from a pipe or a network device
-		 * will give an error after a few eof reads
-		 * however, we cannot tell the difference
-		 * between a zero-length read and an interrupt
-		 * on the processes writing to us,
-		 * so we wait for the error
-		 */
-		n = read9pmsg(mfd[0], mdata, messagesize);
-		if(n == 0)
-			continue;
-		if(n < 0){
-			rerrstr(e, sizeof e);
-			if(strcmp(e, "interrupted") == 0){
-				dprint(2, "read9pmsg interrupted\n");
-				continue;
-			}
-			return;
-		}
-		if(convM2S(mdata, n, &thdr) == 0)
-			continue;
-
-		ddprint(2, "io:<-%F\n", &thdr);
-
-		rhdr.data = (char*)mdata + messagesize;
-		if(!fcalls[thdr.type])
-			err = "bad fcall type";
-		else
-			err = (*fcalls[thdr.type])(newfid(thdr.fid));
-		if(err == (char*)~0)
-			continue;	/* handled off line */
-		if(err){
-			rhdr.type = Rerror;
-			rhdr.ename = err;
-		}else{
-			rhdr.type = thdr.type + 1;
-			rhdr.fid = thdr.fid;
-		}
-		rhdr.tag = thdr.tag;
-		ddprint(2, "io:->%F\n", &rhdr);
-		n = convS2M(&rhdr, mdata, messagesize);
-		if(write(mfd[1], mdata, n) != n)
-			sysfatal("mount write");
-	}
-}
-
-int
-newid(void)
-{
-	int rv;
-	static int id;
-	static Lock idlock;
-
-	lock(&idlock);
-	rv = ++id;
-	unlock(&idlock);
-
-	return rv;
-}
-
-void
-ctlevent(void)
-{
-	Worker *w;
-
-	for(w = workers; w; w = w->next)
-		nbsendul(w->eventc, Qaudioctl << 16 | Check);
-}
--- a/sys/src/cmd/usb/audio/audiosub.c
+++ /dev/null
@@ -1,300 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "audio.h"
-#include "audioctl.h"
-
-typedef struct Namelist Namelist;
-
-struct Namelist
-{
-	short	index;
-	char		*name;
-};
-
-Namelist terminal_types[] = {
-	{	0x100, "USB Terminal, undefined type"},
-	{	0x101, "USB Streaming"},
-	{	0x201, "Microphone"},
-	{	0x301, "Speaker"},
-	{	0x603, "Line connector"},
-	{	0x605, "S/PDIF"},
-	{	0, nil }
-};
-
-units[2][8];	/* rec and play units */
-nunits[2];		/* number in use */
-
-char *
-namefor(Namelist *list, int item)
-{
-	while(list->name){
-		if(list->index == item)
-			return list->name;
-		list++;
-	}
-	return "<unnamed>";
-}
-
-static int
-findunit(int nr)
-{
-	int rec, i;
-	for(rec = 0; rec < 2; rec++)
-		for(i = 0; i < nunits[rec]; i++)
-			if(units[rec][i] == nr)
-				return rec;
-	return -1;
-}
-
-void
-audio_interface(Dev *, Desc *dd)
-{
-	byte *b = (uchar*)&dd->data;
-	byte *bb = b;
-	int nb = dd->data.bLength;
-	int ctl, ch, u, x;
-	byte *p;
-	int class, subclass;
-	Audioalt *aa;
-	char *hd;
-
-	class = Class(dd->iface->csp);
-	subclass = Subclass(dd->iface->csp);
-
-	dprint(2, "%d.%d: ", class, subclass);
-	switch (subclass){
-	case 1:	// control
-		switch (b[2]){
-		case 0x01:
-			dprint(2, "Class-Specific AC Interface Header Descriptor\n");
-			dprint(2, "\tAudioDevClass release (bcd)%c%c%c%c, "
-				"TotalLength %d, InCollection %d aInterfaceNr %d\n",
-					'0'+((b[4]>>4)&0xf), '0'+(b[4]&0xf),
-					'0'+((b[3]>>4)&0xf), '0'+(b[3]&0xf),
-					b[5]|(b[6]<<8), b[7], b[8]);
-			break;
-		case 0x02:	// input
-			dprint(2, "Audio Input Terminal Descriptor\n");
-			dprint(2, "\tbTerminalId %d, wTerminalType "
-				"0x%x (%s), bAssocTerminal %d bNrChannels %d, "
-				"wChannelConfig %d, iChannelNames %d iTerminal %d\n",
-					b[3], b[4]|(b[5]<<8),
-					namefor(terminal_types, b[4]|(b[5]<<8)),
-					b[6], b[7], b[8]|(b[9]<<8), b[10], b[11]);
-			if((b[4]|b[5]<<8) == 0x101){
-				if(verbose)
-					fprint(2, "Audio output unit %d\n", b[3]);
-				/* USB streaming input: play interface */
-				units[Play][nunits[Play]++] = b[3];
-			}else{
-				if(verbose)
-					fprint(2, "Dev can record from %s\n",
-						namefor(terminal_types, b[4]|(b[5]<<8)));
-				/* Non-USB input: record interface */
-				units[Record][nunits[Record]++] = b[3];
-			}
-			break;
-		case 0x03:	// output
-			if(usbdebug){
-				fprint(2, "Audio Output Terminal Descriptor\n");
-				fprint(2, "\tbTerminalId %d, wTerminalType 0x%x (%s), bAssocTerminal %d bSourceId %d, iTerminal %d\n",
-					b[3], b[4]|(b[5]<<8),
-					namefor(terminal_types, b[4]|(b[5]<<8)),
-					b[6], b[7], b[8]);
-			}
-			if((b[4]|b[5]<<8) == 0x101){
-				if(verbose)
-					fprint(2, "Audio input unit %d\n", b[3]);
-				/* USB streaming output: record interface */
-				units[Record][nunits[Record]++] = b[3];
-				if(verbose)
-					fprint(2, "Dev can play to %s\n",
-						namefor(terminal_types, b[4]|(b[5]<<8)));
-				/* Non-USB output: play interface */
-				units[Play][nunits[Play]++] = b[3];
-			}
-			break;
-		case 0x04:
-			if(verbose)
-				fprint(2, "Audio Mixer Unit %d\n", b[3]);
-			if(usbdebug){
-				fprint(2, "\t%d bytes:", nb);
-				for(ctl = 0; ctl < nb; ctl++)
-					fprint(2, " 0x%2.2x", b[ctl]);
-				fprint(2, "\n\tbUnitId %d, bNrInPins %d", b[3], b[4]);
-			}
-			if(b[4]){
-				dprint(2, ", baSourceIDs: [%d", b[5]);
-				u = findunit(b[5]);
-				for(ctl = 1; ctl < b[4]; ctl++){
-					if(u < 0)
-						u = findunit(b[5+ctl]);
-					else if((x = findunit(b[5+ctl])) >= 0 && u != x && verbose)
-						fprint(2, "\tMixer %d for I & O \n", b[3]);
-					dprint(2, ", %d", b[5+ctl]);
-				}
-				dprint(2, "]\n");
-				if(u >= 0){
-					units[u][nunits[u]++] = b[3];
-					if(mixerid[u] >= 0)
-						fprint(2, "Second mixer (%d, %d) on %s\n",
-						 mixerid[u], b[3], u?"record":"playback");
-					mixerid[u] = b[3];
-				}
-				if(usbdebug){
-					fprint(2, "Channels %d, config %d, ",
-						b[ctl+5], b[ctl+5+1] | b[ctl+5+2] << 8);
-					x = b[ctl+5] * b[4];
-					fprint(2, "programmable: %d bits, 0x", x);
-					x = (x + 7) >> 3;
-					while(x--)
-						fprint(2, "%2.2x", b[ctl+x+5+4]);
-				}
-			}
-			break;
-		case 0x05:
-			if(verbose)
-				fprint(2, "Audio Selector Unit %d\n", b[3]);
-			dprint(2, "\tbUnitId %d, bNrInPins %d", b[3], b[4]);
-			if(b[4]){
-				u = findunit(b[5]);
-				dprint(2, ", baSourceIDs: %s [%d",
-					u?"record":"playback", b[5]);
-				for(ctl = 1; ctl < b[4]; ctl++){
-					if(u < 0)
-						u = findunit(b[5+ctl]);
-					else if((x = findunit(b[5+ctl])) >= 0 &&
-						u != x && verbose)
-						fprint(2, "\tSelector %d for I & O\n", b[3]);
-					dprint(2, ", %d", b[5+ctl]);
-				}
-				dprint(2, "]\n");
-				if(u >= 0){
-					units[u][nunits[u]++] = b[3];
-					if(selectorid[u] >= 0)
-						fprint(2, "Second selector (%d, %d) on %s\n", selectorid[u], b[3], u?"record":"playback");
-					selectorid[u] = b[3];
-					controls[u][Selector_control].readable = 1;
-					controls[u][Selector_control].settable = 1;
-					controls[u][Selector_control].chans = 0;
-				}
-			}
-			break;
-		case 0x06:	// feature
-			if(verbose) fprint(2, "Audio Feature Unit %d", b[3]);
-			dprint(2, "\tbUnitId %d, bSourceId %d, bControlSize %d\n",
-				b[3], b[4], b[5]);
-			u = findunit(b[4]);
-			if(u >= 0){
-				if(verbose) fprint(2, " for %s\n", u?"Record":"Playback");
-				units[u][nunits[u]++] = b[3];
-				if(featureid[u] >= 0)
-					if(verbose)
-						fprint(2, "Second feature unit (%d, %d)"
-							" on %s\n", featureid[u], b[3],
-							u?"record":"playback");
-				featureid[u] = b[3];
-			}else
-				if(verbose) fprint(2, ", not known what for\n");
-			p = b + 6;
-			for(ctl = 1; ctl < 0x0b; ctl++)
-				if((1<<(ctl-1)) & (b[6] | ((b[5]>1)?(b[7]<<8):0))){
-					if(verbose)
-						fprint(2, "\t%s control on master channel\n",
-							controls[0][ctl].name);
-					if(u >= 0){
-						controls[u][ctl].readable = 1;
-						controls[u][ctl].settable = 1;
-						controls[u][ctl].chans = 0;
-					}
-				}
-			p += (b[5]>1)?2:1;
-			for(ch = 0; ch < (nb - 8)/b[5]; ch++){
-				for(ctl = 1; ctl < 0x0b; ctl++)
-					if((1<<(ctl-1)) & (p[0] | ((b[5]>1)?(p[1]<<8):0))){
-						if(verbose)
-						  fprint(2, "\t%s control on channel %d\n",
-							controls[0][ctl].name, ch+1);
-						if(u >= 0){
-							controls[u][ctl].readable = 1;
-							controls[u][ctl].settable = 1;
-							controls[u][ctl].chans |= 1 <<(ch+1);
-						}
-					}
-				p += (b[5]>1)?2:1;
-			}
-			break;
-		default:
-			hd = hexstr(bb, nb);
-			fprint(2, "audio control unknown: %s\n", hd);
-			free(hd);
-		}
-		break;
-	case 2: // stream
-		switch (b[2]){
-		case 0x01:
-			dprint(2, "Audio stream for TerminalID %d, delay %d, format_tag %#ux\n",
-				b[3], b[4], b[5] | (b[6]<<8));
-			break;
-		case 0x02:
-			aa = (Audioalt *)dd->altc->aux;
-			if(aa == nil){
-				aa = mallocz(sizeof(Audioalt), 1);
-				dd->altc->aux = aa;
-			}
-			if(verbose){
-				if(b[4] <= 2)
-					fprint(2, "Interface %d: %s, %d bits, ",
-						dd->iface->id, (b[4] == 1)?"mono":"stereo", b[6]);
-				else
-					fprint(2, "Interface %d, %d channels, %d bits, ",
-						dd->iface->id, b[4], b[6]);
-			}
-			if(b[7] == 0){
-				if(verbose)
-					fprint(2, "frequency variable between %d and %d\n",
-						b[8] | b[9]<<8 | b[10]<<16, b[11] | b[12]<<8 | b[13]<<16);
-				aa->minfreq = b[8] | b[9]<<8 | b[10]<<16;
-				aa->maxfreq = b[11] | b[12]<<8 | b[13]<<16;
-				aa->caps |= has_contfreq;
-			}else{
-				if(verbose)
-					fprint(2, "discrete frequencies are:");
-				for(ch = 0; ch < b[7] && ch < 8; ch++){
-					aa->freqs[ch] = b[8+3*ch] | b[9+3*ch]<<8 | b[10+3*ch]<<16;
-					if(verbose)
-						fprint(2, " %d", b[8+3*ch] | b[9+3*ch]<<8 | b[10+3*ch]<<16);
-				}
-				if(ch < 8)
-					aa->freqs[ch] = -1;
-				if(verbose)
-					fprint(2, "\n");
-				if(ch > 1)
-					aa->caps |= has_discfreq;	/* more than one frequency */
-				else
-					aa->caps |= onefreq;		/* only one frequency */
-			}
-			aa->nchan = b[4];
-			aa->res = b[6];
-			aa->subframesize = b[5];
-			break;
-		default:
-			if(usbdebug){
-				hd = hexstr(bb, nb);
-				fprint(2, "audio stream unknown: %s\n", hd);
-				free(hd);
-			}
-		}
-		break;
-	case 3: // midi
-	default:
-		if(usbdebug){
-			hd = hexstr(bb, nb);
-			fprint(2, "Unknown audio stream type: CS_INTERFACE: %s\n", hd);
-			free(hd);
-		}
-	}
-}
-
--- a/sys/src/cmd/usb/audio/mkfile
+++ /dev/null
@@ -1,31 +1,0 @@
-</$objtype/mkfile
-
-TARG=audio
-OFILES=\
-	audiofs.$O\
-	audiosub.$O\
-	audio.$O\
-	audioctl.$O\
-
-HFILES=\
-	audio.h\
-	audioctl.h\
-	../lib/usb.h\
-
-UPDATE=\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-	mkfile\
-	/sys/man/3/usb\
-
-LIB=../lib/usb.a$O
-
-BIN=/$objtype/bin/usb
-</sys/src/cmd/mkone
-
-CFLAGS=-I../lib $CFLAGS
-
-$LIB:
-	cd ../lib
-	mk install
-	mk clean
--- a/sys/src/cmd/usb/disk/disk.c
+++ /dev/null
@@ -1,982 +1,0 @@
-/*
- * usb/disk - usb mass storage file server
- *
- * supports only the scsi command interface, not ata.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <ctype.h>
-#include <fcall.h>
-#include <thread.h>
-#include "scsireq.h"
-#include "usb.h"
-#include "usbfs.h"
-#include "ums.h"
-
-enum
-{
-	Qdir = 0,
-	Qctl,
-	Qraw,
-	Qdata,
-	Qpart,
-	Qmax = Maxparts,
-};
-
-typedef struct Dirtab Dirtab;
-struct Dirtab
-{
-	char	*name;
-	int	mode;
-};
-
-ulong ctlmode = 0664;
-
-/*
- * Partition management (adapted from disk/partfs)
- */
-
-Part *
-lookpart(Umsc *lun, char *name)
-{
-	Part *part, *p;
-	
-	part = lun->part;
-	for(p=part; p < &part[Qmax]; p++){
-		if(p->inuse && strcmp(p->name, name) == 0)
-			return p;
-	}
-	return nil;
-}
-
-Part *
-freepart(Umsc *lun)
-{
-	Part *part, *p;
-	
-	part = lun->part;
-	for(p=part; p < &part[Qmax]; p++){
-		if(!p->inuse)
-			return p;
-	}
-	return nil;
-}
-
-int
-addpart(Umsc *lun, char *name, vlong start, vlong end, ulong mode)
-{
-	Part *p;
-
-	if(start < 0 || start > end || end > lun->blocks){
-		werrstr("bad partition boundaries");
-		return -1;
-	}
-	if(lookpart(lun, name) != nil) {
-		werrstr("partition name already in use");
-		return -1;
-	}
-	p = freepart(lun);
-	if(p == nil){
-		werrstr("no free partition slots");
-		return -1;
-	}
-	p->inuse = 1;
-	free(p->name);
-	p->id = p - lun->part;
-	p->name = estrdup(name);
-	p->offset = start;
-	p->length = end - start;
-	p->mode = mode;
-	return 0;
-}
-
-int
-delpart(Umsc *lun, char *s)
-{
-	Part *p;
-
-	p = lookpart(lun, s);
-	if(p == nil || p->id <= Qdata){
-		werrstr("partition not found");
-		return -1;
-	}
-	p->inuse = 0;
-	free(p->name);
-	p->name = nil;
-	p->vers++;
-	return 0;
-}
-
-void
-fixlength(Umsc *lun, vlong blocks)
-{
-	Part *part, *p;
-	
-	part = lun->part;
-	part[Qdata].length = blocks;
-	for(p=&part[Qdata+1]; p < &part[Qmax]; p++){
-		if(p->inuse && p->offset + p->length > blocks){
-			if(p->offset > blocks){
-				p->offset =blocks;
-				p->length = 0;
-			}else
-				p->length = blocks - p->offset;
-		}
-	}
-}
-
-void
-makeparts(Umsc *lun)
-{
-	addpart(lun, "/", 0, 0, DMDIR | 0555);
-	addpart(lun, "ctl", 0, 0, 0664);
-	addpart(lun, "raw", 0, 0, 0640);
-	addpart(lun, "data", 0, lun->blocks, 0640);
-}
-
-/*
- * ctl parsing & formatting (adapted from partfs)
- */
-
-static char*
-ctlstring(Usbfs *fs)
-{
-	Part *p, *part;
-	Fmt fmt;
-	Umsc *lun;
-	Ums *ums;
-	
-	ums = fs->dev->aux;
-	lun = fs->aux;
-	part = &lun->part[0];
-
-	fmtstrinit(&fmt);
-	fmtprint(&fmt, "dev %s\n", fs->dev->dir);
-	fmtprint(&fmt, "lun %ld\n", lun - &ums->lun[0]);
-	if(lun->flags & Finqok)
-		fmtprint(&fmt, "inquiry %s\n", lun->inq);
-	if(lun->blocks > 0)
-		fmtprint(&fmt, "geometry %llud %ld\n", lun->blocks, lun->lbsize);
-	for (p = &part[Qdata+1]; p < &part[Qmax]; p++)
-		if (p->inuse)
-			fmtprint(&fmt, "part %s %lld %lld\n",
-				p->name, p->offset, p->offset + p->length);
-	return fmtstrflush(&fmt);
-}
-
-static int
-ctlparse(Usbfs *fs, char *msg)
-{
-	vlong start, end;
-	char *argv[16];
-	int argc;
-	Umsc *lun;
-	
-	lun = fs->aux;
-	argc = tokenize(msg, argv, nelem(argv));
-
-	if(argc < 1){
-		werrstr("empty control message");
-		return -1;
-	}
-
-	if(strcmp(argv[0], "part") == 0){
-		if(argc != 4){
-			werrstr("part takes 3 args");
-			return -1;
-		}
-		start = strtoll(argv[2], 0, 0);
-		end = strtoll(argv[3], 0, 0);
-		return addpart(lun, argv[1], start, end, 0640);
-	}else if(strcmp(argv[0], "delpart") == 0){
-		if(argc != 2){
-			werrstr("delpart takes 1 arg");
-			return -1;
-		}
-		return delpart(lun, argv[1]);
-	}
-	werrstr("unknown ctl");
-	return -1;
-}
-
-/*
- * These are used by scuzz scsireq
- */
-int exabyte, force6bytecmds;
-
-int diskdebug;
-
-static void
-ding(void *, char *msg)
-{
-	if(strstr(msg, "alarm") != nil)
-		noted(NCONT);
-	noted(NDFLT);
-}
-
-static int
-getmaxlun(Dev *dev)
-{
-	uchar max;
-	int r;
-
-	max = 0;
-	r = Rd2h|Rclass|Riface;
-	if(usbcmd(dev, r, Getmaxlun, 0, 0, &max, 1) < 0){
-		dprint(2, "disk: %s: getmaxlun failed: %r\n", dev->dir);
-	}else{
-		max &= 017;			/* 15 is the max. allowed */
-		dprint(2, "disk: %s: maxlun %d\n", dev->dir, max);
-	}
-	return max;
-}
-
-static int
-umsreset(Ums *ums)
-{
-	int r;
-
-	r = Rh2d|Rclass|Riface;
-	if(usbcmd(ums->dev, r, Umsreset, 0, 0, nil, 0) < 0){
-		fprint(2, "disk: reset: %r\n");
-		return -1;
-	}
-	return 0;
-}
-
-static int
-umsrecover(Ums *ums)
-{
-	if(umsreset(ums) < 0)
-		return -1;
-	if(unstall(ums->dev, ums->epin, Ein) < 0)
-		dprint(2, "disk: unstall epin: %r\n");
-
-	/* do we need this when epin == epout? */
-	if(unstall(ums->dev, ums->epout, Eout) < 0)
-		dprint(2, "disk: unstall epout: %r\n");
-	return 0;
-}
-
-static void
-umsfatal(Ums *ums)
-{
-	int i;
-
-	devctl(ums->dev, "detach");
-	for(i = 0; i < ums->maxlun; i++)
-		usbfsdel(&ums->lun[i].fs);
-}
-
-static int
-ispow2(uvlong ul)
-{
-	return (ul & (ul - 1)) == 0;
-}
-
-/*
- * return smallest power of 2 >= n
- */
-static int
-log2(int n)
-{
-	int i;
-
-	for(i = 0; (1 << i) < n; i++)
-		;
-	return i;
-}
-
-static int
-umscapacity(Umsc *lun)
-{
-	uchar data[32];
-
-	lun->blocks = 0;
-	lun->capacity = 0;
-	lun->lbsize = 0;
-	memset(data, 0, sizeof data);
-	if(SRrcapacity(lun, data) < 0 && SRrcapacity(lun, data)  < 0)
-		return -1;
-	lun->blocks = GETBELONG(data);
-	lun->lbsize = GETBELONG(data+4);
-	if(lun->blocks == 0xFFFFFFFF){
-		if(SRrcapacity16(lun, data) < 0){
-			lun->lbsize = 0;
-			lun->blocks = 0;
-			return -1;
-		}else{
-			lun->lbsize = GETBELONG(data + 8);
-			lun->blocks = (uvlong)GETBELONG(data)<<32 |
-				GETBELONG(data + 4);
-		}
-	}
-	lun->blocks++; /* SRcapacity returns LBA of last block */
-	lun->capacity = (vlong)lun->blocks * lun->lbsize;
-	fixlength(lun, lun->blocks);
-	if(diskdebug)
-		fprint(2, "disk: logical block size %lud, # blocks %llud\n",
-			lun->lbsize, lun->blocks);
-	return 0;
-}
-
-static int
-umsinit(Ums *ums)
-{
-	uchar i;
-	Umsc *lun;
-	int some;
-
-	umsreset(ums);
-	ums->maxlun = getmaxlun(ums->dev);
-	ums->lun = mallocz((ums->maxlun+1) * sizeof(*ums->lun), 1);
-	some = 0;
-	for(i = 0; i <= ums->maxlun; i++){
-		lun = &ums->lun[i];
-		lun->ums = ums;
-		lun->umsc = lun;
-		lun->lun = i;
-		lun->flags = Fopen | Fusb | Frw10;
-		if(SRinquiry(lun) < 0 && SRinquiry(lun) < 0){
-			dprint(2, "disk: lun %d inquiry failed\n", i);
-			continue;
-		}
-		switch(lun->inquiry[0]){
-		case Devdir:
-		case Devworm:		/* a little different than the others */
-		case Devcd:
-		case Devmo:
-			break;
-		default:
-			fprint(2, "disk: lun %d is not a disk (type %#02x)\n",
-				i, lun->inquiry[0]);
-			continue;
-		}
-		SRstart(lun, 1);
-		/*
-		 * we ignore the device type reported by inquiry.
-		 * Some devices return a wrong value but would still work.
-		 */
-		some++;
-		lun->inq = smprint("%.48s", (char *)lun->inquiry+8);
-		umscapacity(lun);
-	}
-	if(some == 0){
-		dprint(2, "disk: all luns failed\n");
-		devctl(ums->dev, "detach");
-		return -1;
-	}
-	return 0;
-}
-
-
-/*
- * called by SR*() commands provided by scuzz's scsireq
- */
-long
-umsrequest(Umsc *umsc, ScsiPtr *cmd, ScsiPtr *data, int *status)
-{
-	Cbw cbw;
-	Csw csw;
-	int n, nio, left;
-	Ums *ums;
-
-	ums = umsc->ums;
-
-	memcpy(cbw.signature, "USBC", 4);
-	cbw.tag = ++ums->seq;
-	cbw.datalen = data->count;
-	cbw.flags = data->write? CbwDataOut: CbwDataIn;
-	cbw.lun = umsc->lun;
-	if(cmd->count < 1 || cmd->count > 16)
-		print("disk: umsrequest: bad cmd count: %ld\n", cmd->count);
-
-	cbw.len = cmd->count;
-	assert(cmd->count <= sizeof(cbw.command));
-	memcpy(cbw.command, cmd->p, cmd->count);
-	memset(cbw.command + cmd->count, 0, sizeof(cbw.command) - cmd->count);
-
-	werrstr("");		/* we use %r later even for n == 0 */
-	if(diskdebug){
-		fprint(2, "disk: cmd: tag %#lx: ", cbw.tag);
-		for(n = 0; n < cbw.len; n++)
-			fprint(2, " %2.2x", cbw.command[n]&0xFF);
-		fprint(2, " datalen: %ld\n", cbw.datalen);
-	}
-
-	/* issue tunnelled scsi command */
-	if(write(ums->epout->dfd, &cbw, CbwLen) != CbwLen){
-		fprint(2, "disk: cmd: %r\n");
-		goto Fail;
-	}
-
-	/* transfer the data */
-	nio = data->count;
-	if(nio != 0){
-		if(data->write)
-			n = write(ums->epout->dfd, data->p, nio);
-		else{
-			n = read(ums->epin->dfd, data->p, nio);
-			left = nio - n;
-			if (n >= 0 && left > 0)	/* didn't fill data->p? */
-				memset(data->p + n, 0, left);
-		}
-		nio = n;
-		if(diskdebug)
-			if(n < 0)
-				fprint(2, "disk: data: %r\n");
-			else
-				fprint(2, "disk: data: %d bytes\n", n);
-		if(n <= 0)
-			if(data->write == 0)
-				unstall(ums->dev, ums->epin, Ein);
-	}
-
-	/* read the transfer's status */
-	n = read(ums->epin->dfd, &csw, CswLen);
-	if(n <= 0){
-		/* n == 0 means "stalled" */
-		unstall(ums->dev, ums->epin, Ein);
-		n = read(ums->epin->dfd, &csw, CswLen);
-	}
-
-	if(n != CswLen || strncmp(csw.signature, "USBS", 4) != 0){
-		dprint(2, "disk: read n=%d: status: %r\n", n);
-		goto Fail;
-	}
-	if(csw.tag != cbw.tag){
-		dprint(2, "disk: status tag mismatch\n");
-		goto Fail;
-	}
-	if(csw.status >= CswPhaseErr){
-		dprint(2, "disk: phase error\n");
-		goto Fail;
-	}
-	if(csw.dataresidue == 0 || ums->wrongresidues)
-		csw.dataresidue = data->count - nio;
-	if(diskdebug){
-		fprint(2, "disk: status: %2.2ux residue: %ld\n",
-			csw.status, csw.dataresidue);
-		if(cbw.command[0] == ScmdRsense){
-			fprint(2, "sense data:");
-			for(n = 0; n < data->count - csw.dataresidue; n++)
-				fprint(2, " %2.2x", data->p[n]);
-			fprint(2, "\n");
-		}
-	}
-	switch(csw.status){
-	case CswOk:
-		*status = STok;
-		break;
-	case CswFailed:
-		*status = STcheck;
-		break;
-	default:
-		dprint(2, "disk: phase error\n");
-		goto Fail;
-	}
-	ums->nerrs = 0;
-	return data->count - csw.dataresidue;
-
-Fail:
-	*status = STharderr;
-	if(ums->nerrs++ > 15){
-		fprint(2, "disk: %s: too many errors: device detached\n", ums->dev->dir);
-		umsfatal(ums);
-	}else
-		umsrecover(ums);
-	return -1;
-}
-
-static int
-dwalk(Usbfs *fs, Fid *fid, char *name)
-{
-	Umsc *lun;
-	Part *p;
-	
-	lun = fs->aux;
-	
-	if((fid->qid.type & QTDIR) == 0){
-		werrstr("walk in non-directory");
-		return -1;
-	}
-	if(strcmp(name, "..") == 0)
-		return 0;
-	
-	p = lookpart(lun, name);
-	if(p == nil){
-		werrstr(Enotfound);
-		return -1;
-	}
-	fid->qid.path = p->id | fs->qid;
-	fid->qid.vers = p->vers;
-	fid->qid.type = p->mode >> 24;
-	return 0;
-}
-static int
-dstat(Usbfs *fs, Qid qid, Dir *d);
-
-static void
-dostat(Usbfs *fs, int path, Dir *d)
-{
-	Umsc *lun;
-	Part *p;
-
-	lun = fs->aux;
-	p = &lun->part[path];
-	d->qid.path = path;
-	d->qid.vers = p->vers;
-	d->qid.type =p->mode >> 24;
-	d->mode = p->mode;
-	d->length = (vlong) p->length * lun->lbsize;
-	strecpy(d->name, d->name + Namesz - 1, p->name);
-}
-
-static int
-dirgen(Usbfs *fs, Qid, int n, Dir *d, void*)
-{
-	Umsc *lun;
-	int i;
-	
-	lun = fs->aux;
-	for(i = Qctl; i < Qmax; i++){
-		if(lun->part[i].inuse == 0)
-			continue;
-		if(n-- == 0)
-			break;
-	}
-	if(i == Qmax)
-		return -1;
-	dostat(fs, i, d);
-	d->qid.path |= fs->qid;
-	return 0;
-}
-
-static int
-dstat(Usbfs *fs, Qid qid, Dir *d)
-{
-	int path;
-
-	path = qid.path & ~fs->qid;
-	dostat(fs, path, d);
-	d->qid.path |= fs->qid;
-	return 0;
-}
-
-static int
-dopen(Usbfs *fs, Fid *fid, int)
-{
-	ulong path;
-	Umsc *lun;
-
-	path = fid->qid.path & ~fs->qid;
-	lun = fs->aux;
-	switch(path){
-	case Qraw:
-		lun->phase = Pcmd;
-		break;
-	}
-	return 0;
-}
-
-/*
- * check i/o parameters and compute values needed later.
- * we shift & mask manually to avoid run-time calls to _divv and _modv,
- * since we don't need general division nor its cost.
- */
-static int
-setup(Umsc *lun, Part *p, char *data, int count, vlong offset)
-{
-	long nb, lbsize, lbshift, lbmask;
-	uvlong bno;
-
-	if(count < 0 || lun->lbsize <= 0 && umscapacity(lun) < 0 ||
-	    lun->lbsize == 0)
-		return -1;
-	lbsize = lun->lbsize;
-	assert(ispow2(lbsize));
-	lbshift = log2(lbsize);
-	lbmask = lbsize - 1;
-
-	bno = offset >> lbshift;	/* offset / lbsize */
-	nb = ((offset + count + lbsize - 1) >> lbshift) - bno;
-
-	if(bno + nb > p->length)		/* past end of partition? */
-		nb = p->length - bno;
-	if(nb * lbsize > Maxiosize)
-		nb = Maxiosize / lbsize;
-	lun->nb = nb;
-	if(bno >= p->length || nb == 0)
-		return 0;
-
-	bno += p->offset;		/* start of partition */
-	lun->offset = bno;
-	lun->off = offset & lbmask;		/* offset % lbsize */
-	if(lun->off == 0 && (count & lbmask) == 0)
-		lun->bufp = data;
-	else
-		/* not transferring full, aligned blocks; need intermediary */
-		lun->bufp = lun->buf;
-	return count;
-}
-
-/*
- * Upon SRread/SRwrite errors we assume the medium may have changed,
- * and ask again for the capacity of the media.
- * BUG: How to proceed to avoid confussing dossrv??
- */
-static long
-dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
-{
-	long n;
-	ulong path;
-	char buf[64];
-	char *s;
-	Part *p;
-	Umsc *lun;
-	Ums *ums;
-	Qid q;
-
-	q = fid->qid;
-	path = fid->qid.path & ~fs->qid;
-	ums = fs->dev->aux;
-	lun = fs->aux;
-
-	qlock(ums);
-	switch(path){
-	case Qdir:
-		count = usbdirread(fs, q, data, count, offset, dirgen, nil);
-		break;
-	case Qctl:
-		s = ctlstring(fs);
-		count = usbreadbuf(data, count, offset, s, strlen(s));
-		free(s);
-		break;
-	case Qraw:
-		if(lun->lbsize <= 0 && umscapacity(lun) < 0){
-			count = -1;
-			break;
-		}
-		switch(lun->phase){
-		case Pcmd:
-			qunlock(ums);
-			werrstr("phase error");
-			return -1;
-		case Pdata:
-			lun->data.p = data;
-			lun->data.count = count;
-			lun->data.write = 0;
-			count = umsrequest(lun,&lun->cmd,&lun->data,&lun->status);
-			lun->phase = Pstatus;
-			if(count < 0)
-				lun->lbsize = 0;  /* medium may have changed */
-			break;
-		case Pstatus:
-			n = snprint(buf, sizeof buf, "%11.0ud ", lun->status);
-			count = usbreadbuf(data, count, 0LL, buf, n);
-			lun->phase = Pcmd;
-			break;
-		}
-		break;
-	case Qdata:
-	default:
-		p = &lun->part[path];
-		if(!p->inuse){
-			count = -1;
-			werrstr(Eperm);
-			break;
-		}
-		count = setup(lun, p, data, count, offset);
-		if (count <= 0)
-			break;
-		n = SRread(lun, lun->bufp, lun->nb * lun->lbsize);
-		if(n < 0){
-			lun->lbsize = 0;	/* medium may have changed */
-			count = -1;
-		} else if (lun->bufp == data)
-			count = n;
-		else{
-			/*
-			 * if n == lun->nb*lun->lbsize (as expected),
-			 * just copy count bytes.
-			 */
-			if(lun->off + count > n)
-				count = n - lun->off; /* short read */
-			if(count > 0)
-				memmove(data, lun->bufp + lun->off, count);
-		}
-		break;
-	}
-	qunlock(ums);
-	return count;
-}
-
-static long
-dwrite(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
-{
-	long len, ocount;
-	ulong path;
-	uvlong bno;
-	Ums *ums;
-	Part *p;
-	Umsc *lun;
-	char *s;
-
-	ums = fs->dev->aux;
-	lun = fs->aux;
-	path = fid->qid.path & ~fs->qid;
-
-	qlock(ums);
-	switch(path){
-	case Qdir:
-		count = -1;
-		werrstr(Eperm);
-		break;
-	case Qctl:
-		s = emallocz(count+1, 1);
-		memmove(s, data, count);
-		if(s[count-1] == '\n')
-			s[count-1] = 0;
-		if(ctlparse(fs, s) == -1)
-			count = -1;
-		free(s);
-		break;
-	case Qraw:
-		if(lun->lbsize <= 0 && umscapacity(lun) < 0){
-			count = -1;
-			break;
-		}
-		switch(lun->phase){
-		case Pcmd:
-			if(count != 6 && count != 10){
-				qunlock(ums);
-				werrstr("bad command length");
-				return -1;
-			}
-			memmove(lun->rawcmd, data, count);
-			lun->cmd.p = lun->rawcmd;
-			lun->cmd.count = count;
-			lun->cmd.write = 1;
-			lun->phase = Pdata;
-			break;
-		case Pdata:
-			lun->data.p = data;
-			lun->data.count = count;
-			lun->data.write = 1;
-			count = umsrequest(lun,&lun->cmd,&lun->data,&lun->status);
-			lun->phase = Pstatus;
-			if(count < 0)
-				lun->lbsize = 0;  /* medium may have changed */
-			break;
-		case Pstatus:
-			lun->phase = Pcmd;
-			werrstr("phase error");
-			count = -1;
-			break;
-		}
-		break;
-	case Qdata:
-	default:
-		p = &lun->part[path];
-		if(!p->inuse){
-			count = -1;
-			werrstr(Eperm);
-			break;
-		}
-		len = ocount = count;
-		count = setup(lun, p, data, count, offset);
-		if (count <= 0)
-			break;
-		bno = lun->offset;
-		if (lun->bufp == lun->buf) {
-			count = SRread(lun, lun->bufp, lun->nb * lun->lbsize);
-			if(count < 0) {
-				lun->lbsize = 0;  /* medium may have changed */
-				break;
-			}
-			/*
-			 * if count == lun->nb*lun->lbsize, as expected, just
-			 * copy len (the original count) bytes of user data.
-			 */
-			if(lun->off + len > count)
-				len = count - lun->off; /* short read */
-			if(len > 0)
-				memmove(lun->bufp + lun->off, data, len);
-		}
-
-		lun->offset = bno;
-		count = SRwrite(lun, lun->bufp, lun->nb * lun->lbsize);
-		if(count < 0)
-			lun->lbsize = 0;	/* medium may have changed */
-		else{
-			if(lun->off + len > count)
-				count -= lun->off; /* short write */
-			/* never report more bytes written than requested */
-			if(count < 0)
-				count = 0;
-			else if(count > ocount)
-				count = ocount;
-		}
-		break;
-	}
-	qunlock(ums);
-	return count;
-}
-
-int
-findendpoints(Ums *ums)
-{
-	Ep *ep;
-	Usbdev *ud;
-	ulong csp, sc;
-	int i, epin, epout;
-
-	epin = epout = -1;
-	ud = ums->dev->usb;
-	for(i = 0; i < nelem(ud->ep); i++){
-		if((ep = ud->ep[i]) == nil)
-			continue;
-		csp = ep->iface->csp;
-		sc = Subclass(csp);
-		if(!(Class(csp) == Clstorage && (Proto(csp) == Protobulk)))
-			continue;
-		if(sc != Subatapi && sc != Sub8070 && sc != Subscsi)
-			fprint(2, "disk: subclass %#ulx not supported. trying anyway\n", sc);
-		if(ep->type == Ebulk){
-			if(ep->dir == Eboth || ep->dir == Ein)
-				if(epin == -1)
-					epin =  ep->id;
-			if(ep->dir == Eboth || ep->dir == Eout)
-				if(epout == -1)
-					epout = ep->id;
-		}
-	}
-	dprint(2, "disk: ep ids: in %d out %d\n", epin, epout);
-	if(epin == -1 || epout == -1)
-		return -1;
-	ums->epin = openep(ums->dev, epin);
-	if(ums->epin == nil){
-		fprint(2, "disk: openep %d: %r\n", epin);
-		return -1;
-	}
-	if(epout == epin){
-		incref(ums->epin);
-		ums->epout = ums->epin;
-	}else
-		ums->epout = openep(ums->dev, epout);
-	if(ums->epout == nil){
-		fprint(2, "disk: openep %d: %r\n", epout);
-		closedev(ums->epin);
-		return -1;
-	}
-	if(ums->epin == ums->epout)
-		opendevdata(ums->epin, ORDWR);
-	else{
-		opendevdata(ums->epin, OREAD);
-		opendevdata(ums->epout, OWRITE);
-	}
-	if(ums->epin->dfd < 0 || ums->epout->dfd < 0){
-		fprint(2, "disk: open i/o ep data: %r\n");
-		closedev(ums->epin);
-		closedev(ums->epout);
-		return -1;
-	}
-	dprint(2, "disk: ep in %s out %s\n", ums->epin->dir, ums->epout->dir);
-
-	devctl(ums->epin, "timeout 2000");
-	devctl(ums->epout, "timeout 2000");
-
-	if(usbdebug > 1 || diskdebug > 2){
-		devctl(ums->epin, "debug 1");
-		devctl(ums->epout, "debug 1");
-		devctl(ums->dev, "debug 1");
-	}
-	return 0;
-}
-
-static int
-usage(void)
-{
-	werrstr("usage: usb/disk [-d] [-N nb]");
-	return -1;
-}
-
-static void
-umsdevfree(void *a)
-{
-	Ums *ums = a;
-
-	if(ums == nil)
-		return;
-	closedev(ums->epin);
-	closedev(ums->epout);
-	ums->epin = ums->epout = nil;
-	free(ums->lun);
-	free(ums);
-}
-
-static Usbfs diskfs = {
-	.walk = dwalk,
-	.open =	 dopen,
-	.read =	 dread,
-	.write = dwrite,
-	.stat =	 dstat,
-};
-
-int
-diskmain(Dev *dev, int argc, char **argv)
-{
-	Ums *ums;
-	Umsc *lun;
-	int i, devid;
-
-	devid = dev->id;
-	ARGBEGIN{
-	case 'd':
-		scsidebug(diskdebug);
-		diskdebug++;
-		break;
-	case 'N':
-		devid = atoi(EARGF(usage()));
-		break;
-	default:
-		return usage();
-	}ARGEND
-	if(argc != 0) {
-		return usage();
-	}
-	
-//	notify(ding);
-	ums = dev->aux = emallocz(sizeof(Ums), 1);
-	ums->maxlun = -1;
-	ums->dev = dev;
-	dev->free = umsdevfree;
-	if(findendpoints(ums) < 0){
-		werrstr("disk: endpoints not found");
-		return -1;
-	}
-
-	/*
-	 * SanDISK 512M gets residues wrong.
-	 */
-	if(dev->usb->vid == 0x0781 && dev->usb->did == 0x5150)
-		ums->wrongresidues = 1;
-
-	if(umsinit(ums) < 0){
-		dprint(2, "disk: umsinit: %r\n");
-		return -1;
-	}
-
-	for(i = 0; i <= ums->maxlun; i++){
-		lun = &ums->lun[i];
-		lun->fs = diskfs;
-		snprint(lun->fs.name, sizeof(lun->fs.name), "sdU%d.%d", devid, i);
-		lun->fs.dev = dev;
-		incref(dev);
-		lun->fs.aux = lun;
-		makeparts(lun);
-		usbfsadd(&lun->fs);
-	}
-	return 0;
-}
--- a/sys/src/cmd/usb/disk/main.c
+++ /dev/null
@@ -1,71 +1,0 @@
-/*
- * usb/disk - usb mass storage file server
- */
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include "scsireq.h"
-#include "usb.h"
-#include "usbfs.h"
-#include "ums.h"
-
-enum
-{
-	Arglen = 80,
-};
-
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-Dd] [-N nb] [-m mnt] [-s srv] [dev...]\n", argv0);
-	threadexitsall("usage");
-}
-
-static int csps[] = {
-	CSP(Clstorage,Subatapi,Protobulk),
-	CSP(Clstorage,Sub8070,Protobulk),
-	CSP(Clstorage,Subscsi,Protobulk),
-	0,
-};
-
-void
-threadmain(int argc, char **argv)
-{
-	char args[Arglen];
-	char *as, *ae, *srv, *mnt;
-
-	srv = nil;
-	mnt = "/n/disk";
-
-	quotefmtinstall();
-	ae = args+sizeof(args);
-	as = seprint(args, ae, "disk");
-	ARGBEGIN{
-	case 'D':
-		usbfsdebug++;
-		break;
-	case 'd':
-		usbdebug++;
-		as = seprint(as, ae, " -d");
-		break;
-	case 'N':
-		as = seprint(as, ae, " -N %s", EARGF(usage()));
-		break;
-	case 'm':
-		mnt = EARGF(usage());
-		break;
-	case 's':
-		srv = EARGF(usage());
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	rfork(RFNOTEG);
-	threadsetgrp(threadid());
-	fmtinstall('U', Ufmt);
-	usbfsinit(srv, mnt, &usbdirfs, MBEFORE);
-	startdevs(args, argv, argc, matchdevcsp, csps, diskmain);
-	threadexits(nil);
-}
--- a/sys/src/cmd/usb/disk/mkfile
+++ /dev/null
@@ -1,41 +1,0 @@
-</$objtype/mkfile
-
-TARG=disk
-OFILES=\
-	main.$O
-
-LIBDOFILES=\
-	disk.$O\
-	scsireq.$O\
-	scsierrs.$O\
-
-HFILES =\
-	scsireq.h\
-	../lib/usb.h\
-	../lib/usbfs.h\
-	ums.h\
-
-LIBD=../lib/usbdev.a$O
-LIBU=../lib/usb.a$O
-LIB=\
-	$LIBD\
-	$LIBU\
-
-BIN=/$objtype/bin/usb
-
-</sys/src/cmd/mkone
-CFLAGS=-I../lib $CFLAGS
-CLEANFILES=scsierrs.c
-
-$LIBU:
-	cd ../lib
-	mk install
-	mk clean
-
-$LIBD:V: $LIBDOFILES
-	ar vu $LIBD $newprereq
-	rm $newprereq
-
-scsierrs.c: /sys/lib/scsicodes mkscsierrs
-	mkscsierrs >scsierrs.c
-
--- a/sys/src/cmd/usb/disk/mkscsierrs
+++ /dev/null
@@ -1,32 +1,0 @@
-#!/bin/rc
-
-cat <<EOF
-#include <u.h>
-#include <libc.h>
-
-typedef struct Err Err;
-struct Err
-{
-	int n;
-	char *s;
-};
-
-static Err scsierrs[] = {
-EOF
-
-grep '^[0-9a-c][0-9a-c][0-9a-c][0-9a-c][ 	]' /sys/lib/scsicodes |
-	sed -e 's/^(....) (.*)/	{0x\1,	"\2"},\n/'
-cat <<EOF
-};
-
-char*
-scsierrmsg(int n)
-{
-	int i;
-
-	for(i = 0; i < nelem(scsierrs); i++)
-		if(scsierrs[i].n == n)
-			return scsierrs[i].s;
-	return "scsi error";
-}
-EOF
--- a/sys/src/cmd/usb/disk/scsireq.c
+++ /dev/null
@@ -1,986 +1,0 @@
-/*
- * This is /sys/src/cmd/scuzz/scsireq.c
- * changed to add more debug support, to keep
- * disk compiling without a scuzz that includes these changes.
- * Also, this includes minor tweaks for usb:
- *	we set req.lun/unit to rp->lun/unit in SRreqsense
- *	we set the rp->sense[0] bit Sd0valid in SRreqsense
- * This does not use libdisk to retrieve the scsi error to make
- * user see the diagnostics if we boot with debug enabled.
- *
- * BUGS:
- *	no luns
- *	and incomplete in many other ways
- */
-
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include "scsireq.h"
-
-enum {
-	Debug = 0,
-};
-
-/*
- * exabyte tape drives, at least old ones like the 8200 and 8505,
- * are dumb: you have to read the exact block size on the tape,
- * they don't take 10-byte SCSI commands, and various other fine points.
- */
-extern int exabyte, force6bytecmds;
-
-static int debug = Debug;
-
-static char *scmdnames[256] = {
-[ScmdTur]	"Tur",
-[ScmdRewind]	"Rewind",
-[ScmdRsense]	"Rsense",
-[ScmdFormat]	"Format",
-[ScmdRblimits]	"Rblimits",
-[ScmdRead]	"Read",
-[ScmdWrite]	"Write",
-[ScmdSeek]	"Seek",
-[ScmdFmark]	"Fmark",
-[ScmdSpace]	"Space",
-[ScmdInq]	"Inq",
-[ScmdMselect6]	"Mselect6",
-[ScmdMselect10]	"Mselect10",
-[ScmdMsense6]	"Msense6",
-[ScmdMsense10]	"Msense10",
-[ScmdStart]	"Start",
-[ScmdRcapacity]	"Rcapacity",
-[ScmdRcapacity16]	"Rcap16",
-[ScmdExtread]	"Extread",
-[ScmdExtwrite]	"Extwrite",
-[ScmdExtseek]	"Extseek",
-
-[ScmdSynccache]	"Synccache",
-[ScmdRTOC]	"RTOC",
-[ScmdRdiscinfo]	"Rdiscinfo",
-[ScmdRtrackinfo]	"Rtrackinfo",
-[ScmdReserve]	"Reserve",
-[ScmdBlank]	"Blank",
-
-[ScmdCDpause]	"CDpause",
-[ScmdCDstop]	"CDstop",
-[ScmdCDplay]	"CDplay",
-[ScmdCDload]	"CDload",
-[ScmdCDscan]	"CDscan",
-[ScmdCDstatus]	"CDstatus",
-[Scmdgetconf]	"getconf",
-};
-
-long
-SRready(ScsiReq *rp)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = cmd;
-	rp->data.count = 0;
-	rp->data.write = 1;
-	return SRrequest(rp);
-}
-
-long
-SRrewind(ScsiReq *rp)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdRewind;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = cmd;
-	rp->data.count = 0;
-	rp->data.write = 1;
-	if(SRrequest(rp) >= 0){
-		rp->offset = 0;
-		return 0;
-	}
-	return -1;
-}
-
-long
-SRreqsense(ScsiReq *rp)
-{
-	uchar cmd[6];
-	ScsiReq req;
-	long status;
-
-	if(rp->status == Status_SD){
-		rp->status = STok;
-		return 0;
-	}
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdRsense;
-	cmd[4] = sizeof(req.sense);
-	memset(&req, 0, sizeof(req));
-	if(rp->flags&Fusb)
-		req.flags |= Fusb;
-	req.lun = rp->lun;
-	req.unit = rp->unit;
-	req.fd = rp->fd;
-	req.umsc = rp->umsc;
-	req.cmd.p = cmd;
-	req.cmd.count = sizeof cmd;
-	req.data.p = rp->sense;
-	req.data.count = sizeof(rp->sense);
-	req.data.write = 0;
-	status = SRrequest(&req);
-	rp->status = req.status;
-	if(status != -1)
-		rp->sense[0] |= Sd0valid;
-	return status;
-}
-
-long
-SRformat(ScsiReq *rp)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdFormat;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = cmd;
-	rp->data.count = 6;
-	rp->data.write = 0;
-	return SRrequest(rp);
-}
-
-long
-SRrblimits(ScsiReq *rp, uchar *list)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdRblimits;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = list;
-	rp->data.count = 6;
-	rp->data.write = 0;
-	return SRrequest(rp);
-}
-
-static int
-dirdevrw(ScsiReq *rp, uchar *cmd, long nbytes)
-{
-	long n;
-
-	n = nbytes / rp->lbsize;
-	if(rp->offset <= Max24off && n <= 256 && (rp->flags & Frw10) == 0){
-		PUTBE24(cmd+1, rp->offset);
-		cmd[4] = n;
-		cmd[5] = 0;
-		return 6;
-	}
-	cmd[0] |= ScmdExtread;
-	cmd[1] = 0;
-	PUTBELONG(cmd+2, rp->offset);
-	cmd[6] = 0;
-	cmd[7] = n>>8;
-	cmd[8] = n;
-	cmd[9] = 0;
-	return 10;
-}
-
-static int
-seqdevrw(ScsiReq *rp, uchar *cmd, long nbytes)
-{
-	long n;
-
-	/* don't set Cmd1sili; we want the ILI bit instead of a fatal error */
-	cmd[1] = rp->flags&Fbfixed? Cmd1fixed: 0;
-	n = nbytes / rp->lbsize;
-	PUTBE24(cmd+2, n);
-	cmd[5] = 0;
-	return 6;
-}
-
-extern int diskdebug;
-
-long
-SRread(ScsiReq *rp, void *buf, long nbytes)
-{
-	uchar cmd[10];
-	long n;
-
-	if(rp->lbsize == 0 || (nbytes % rp->lbsize) || nbytes > Maxiosize){
-		if(diskdebug)
-			if (nbytes % rp->lbsize)
-				fprint(2, "disk: i/o size %ld %% %ld != 0\n",
-					nbytes, rp->lbsize);
-			else
-				fprint(2, "disk: i/o size %ld > %d\n",
-					nbytes, Maxiosize);
-		rp->status = Status_BADARG;
-		return -1;
-	}
-
-	/* set up scsi read cmd */
-	cmd[0] = ScmdRead;
-	if(rp->flags & Fseqdev)
-		rp->cmd.count = seqdevrw(rp, cmd, nbytes);
-	else
-		rp->cmd.count = dirdevrw(rp, cmd, nbytes);
-	rp->cmd.p = cmd;
-	rp->data.p = buf;
-	rp->data.count = nbytes;
-	rp->data.write = 0;
-
-	/* issue it */
-	n = SRrequest(rp);
-	if(n != -1){			/* it worked? */
-		rp->offset += n / rp->lbsize;
-		return n;
-	}
-
-	/* request failed; maybe we just read a short record? */
-	if (exabyte) {
-		fprint(2, "read error\n");
-		rp->status = STcheck;
-		return n;
-	}
-	if(rp->status != Status_SD || !(rp->sense[0] & Sd0valid))
-		return -1;
-	/* compute # of bytes not read */
-	n = GETBELONG(rp->sense+3) * rp->lbsize;
-	if(!(rp->flags & Fseqdev))
-		return -1;
-
-	/* device is a tape or something similar */
-	if (rp->sense[2] == Sd2filemark || rp->sense[2] == 0x08 ||
-	    rp->sense[2] & Sd2ili && n > 0)
-		rp->data.count = nbytes - n;
-	else
-		return -1;
-	n = rp->data.count;
-	if (!rp->readblock++ || debug)
-		fprint(2, "SRread: tape data count %ld%s\n", n,
-			(rp->sense[2] & Sd2ili? " with ILI": ""));
-	rp->status = STok;
-	rp->offset += n / rp->lbsize;
-	return n;
-}
-
-long
-SRwrite(ScsiReq *rp, void *buf, long nbytes)
-{
-	uchar cmd[10];
-	long n;
-
-	if(rp->lbsize == 0 || (nbytes % rp->lbsize) || nbytes > Maxiosize){
-		if(diskdebug)
-			if (nbytes % rp->lbsize)
-				fprint(2, "disk: i/o size %ld %% %ld != 0\n",
-					nbytes, rp->lbsize);
-			else
-				fprint(2, "disk: i/o size %ld > %d\n",
-					nbytes, Maxiosize);
-		rp->status = Status_BADARG;
-		return -1;
-	}
-
-	/* set up scsi write cmd */
-	cmd[0] = ScmdWrite;
-	if(rp->flags & Fseqdev)
-		rp->cmd.count = seqdevrw(rp, cmd, nbytes);
-	else
-		rp->cmd.count = dirdevrw(rp, cmd, nbytes);
-	rp->cmd.p = cmd;
-	rp->data.p = buf;
-	rp->data.count = nbytes;
-	rp->data.write = 1;
-
-	/* issue it */
-	if((n = SRrequest(rp)) == -1){
-		if (exabyte) {
-			fprint(2, "write error\n");
-			rp->status = STcheck;
-			return n;
-		}
-		if(rp->status != Status_SD || rp->sense[2] != Sd2eom)
-			return -1;
-		if(rp->sense[0] & Sd0valid){
-			n -= GETBELONG(rp->sense+3) * rp->lbsize;
-			rp->data.count = nbytes - n;
-		}
-		else
-			rp->data.count = nbytes;
-		n = rp->data.count;
-	}
-	rp->offset += n / rp->lbsize;
-	return n;
-}
-
-long
-SRseek(ScsiReq *rp, long offset, int type)
-{
-	uchar cmd[10];
-
-	switch(type){
-
-	case 0:
-		break;
-
-	case 1:
-		offset += rp->offset;
-		if(offset >= 0)
-			break;
-		/*FALLTHROUGH*/
-
-	default:
-		if(diskdebug)
-			fprint(2, "disk: seek failed\n");
-		rp->status = Status_BADARG;
-		return -1;
-	}
-	memset(cmd, 0, sizeof cmd);
-	if(offset <= Max24off && (rp->flags & Frw10) == 0){
-		cmd[0] = ScmdSeek;
-		PUTBE24(cmd+1, offset & Max24off);
-		rp->cmd.count = 6;
-	}else{
-		cmd[0] = ScmdExtseek;
-		PUTBELONG(cmd+2, offset);
-		rp->cmd.count = 10;
-	}
-	rp->cmd.p = cmd;
-	rp->data.p = cmd;
-	rp->data.count = 0;
-	rp->data.write = 1;
-	SRrequest(rp);
-	if(rp->status == STok) {
-		rp->offset = offset;
-		return offset;
-	}
-	return -1;
-}
-
-long
-SRfilemark(ScsiReq *rp, ulong howmany)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdFmark;
-	PUTBE24(cmd+2, howmany);
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = cmd;
-	rp->data.count = 0;
-	rp->data.write = 1;
-	return SRrequest(rp);
-}
-
-long
-SRspace(ScsiReq *rp, uchar code, long howmany)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdSpace;
-	cmd[1] = code;
-	PUTBE24(cmd+2, howmany);
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = cmd;
-	rp->data.count = 0;
-	rp->data.write = 1;
-	/*
-	 * what about rp->offset?
-	 */
-	return SRrequest(rp);
-}
-
-long
-SRinquiry(ScsiReq *rp)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdInq;
-	cmd[4] = sizeof rp->inquiry;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	memset(rp->inquiry, 0, sizeof rp->inquiry);
-	rp->data.p = rp->inquiry;
-	rp->data.count = sizeof rp->inquiry;
-	rp->data.write = 0;
-	if(SRrequest(rp) >= 0){
-		rp->flags |= Finqok;
-		return 0;
-	}
-	rp->flags &= ~Finqok;
-	return -1;
-}
-
-long
-SRmodeselect6(ScsiReq *rp, uchar *list, long nbytes)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdMselect6;
-	if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
-		cmd[1] = 0x10;
-	cmd[4] = nbytes;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = list;
-	rp->data.count = nbytes;
-	rp->data.write = 1;
-	return SRrequest(rp);
-}
-
-long
-SRmodeselect10(ScsiReq *rp, uchar *list, long nbytes)
-{
-	uchar cmd[10];
-
-	memset(cmd, 0, sizeof cmd);
-	if((rp->flags & Finqok) && (rp->inquiry[2] & 0x07) >= 2)
-		cmd[1] = 0x10;
-	cmd[0] = ScmdMselect10;
-	cmd[7] = nbytes>>8;
-	cmd[8] = nbytes;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = list;
-	rp->data.count = nbytes;
-	rp->data.write = 1;
-	return SRrequest(rp);
-}
-
-long
-SRmodesense6(ScsiReq *rp, uchar page, uchar *list, long nbytes)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdMsense6;
-	cmd[2] = page;
-	cmd[4] = nbytes;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = list;
-	rp->data.count = nbytes;
-	rp->data.write = 0;
-	return SRrequest(rp);
-}
-
-long
-SRmodesense10(ScsiReq *rp, uchar page, uchar *list, long nbytes)
-{
-	uchar cmd[10];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdMsense10;
-	cmd[2] = page;
-	cmd[7] = nbytes>>8;
-	cmd[8] = nbytes;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = list;
-	rp->data.count = nbytes;
-	rp->data.write = 0;
-	return SRrequest(rp);
-}
-
-long
-SRstart(ScsiReq *rp, uchar code)
-{
-	uchar cmd[6];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdStart;
-	cmd[4] = code;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = cmd;
-	rp->data.count = 0;
-	rp->data.write = 1;
-	return SRrequest(rp);
-}
-
-long
-SRrcapacity(ScsiReq *rp, uchar *data)
-{
-	uchar cmd[10];
-
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdRcapacity;
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = data;
-	rp->data.count = 8;
-	rp->data.write = 0;
-	return SRrequest(rp);
-}
-
-long
-SRrcapacity16(ScsiReq *rp, uchar *data)
-{
-	uchar cmd[16];
-	uint i;
-
-	i = 32;
-	memset(cmd, 0, sizeof cmd);
-	cmd[0] = ScmdRcapacity16;
-	cmd[1] = 0x10;
-	cmd[10] = i>>24;
-	cmd[11] = i>>16;
-	cmd[12] = i>>8;
-	cmd[13] = i;
-
-	rp->cmd.p = cmd;
-	rp->cmd.count = sizeof cmd;
-	rp->data.p = data;
-	rp->data.count = i;
-	rp->data.write = 0;
-	return SRrequest(rp);
-}
-
-void
-scsidebug(int d)
-{
-	debug = d;
-	if(debug)
-		fprint(2, "scsidebug on\n");
-}
-
-static long
-request(int fd, ScsiPtr *cmd, ScsiPtr *data, int *status)
-{
-	long n, r;
-	char buf[16];
-
-	/* this was an experiment but it seems to be a good idea */
-	*status = STok;
-
-	/* send SCSI command */
-	if(write(fd, cmd->p, cmd->count) != cmd->count){
-		fprint(2, "scsireq: write cmd: %r\n");
-		*status = Status_SW;
-		return -1;
-	}
-
-	/* read or write actual data */
-	werrstr("");
-//	alarm(5*1000);
-	if(data->write)
-		n = write(fd, data->p, data->count);
-	else {
-		n = read(fd, data->p, data->count);
-		if (n < 0)
-			memset(data->p, 0, data->count);
-		else if (n < data->count)
-			memset(data->p + n, 0, data->count - n);
-	}
-//	alarm(0);
-	if (n != data->count && n <= 0) {
-		if (debug)
-			fprint(2,
-	"request: tried to %s %ld bytes of data for cmd 0x%x but got %r\n",
-				(data->write? "write": "read"),
-				data->count, cmd->p[0]);
-	} else if (n != data->count && (data->write || debug))
-		fprint(2, "request: %s %ld of %ld bytes of actual data\n",
-			(data->write? "wrote": "read"), n, data->count);
-
-	/* read status */
-	buf[0] = '\0';
-	r = read(fd, buf, sizeof buf-1);
-	if(exabyte && r <= 0 || !exabyte && r < 0){
-		fprint(2, "scsireq: read status: %r\n");
-		*status = Status_SW;
-		return -1;
-	}
-	if (r >= 0)
-		buf[r] = '\0';
-	*status = atoi(buf);
-	if(n < 0 && (exabyte || *status != STcheck))
-		fprint(2, "scsireq: status 0x%2.2uX: data transfer: %r\n",
-			*status);
-	return n;
-}
-
-static char*
-seprintcmd(char *s, char* e, char *cmd, int count, int args)
-{
-	uint c;
-
-	if(count < 6)
-		return seprint(s, e, "<short cmd>");
-	c = cmd[0];
-	if(scmdnames[c] != nil)
-		s = seprint(s, e, "%s", scmdnames[c]);
-	else
-		s = seprint(s, e, "cmd:%#02uX", c);
-	if(args != 0)
-		switch(c){
-		case ScmdRsense:
-		case ScmdInq:
-		case ScmdMselect6:
-		case ScmdMsense6:
-			s = seprint(s, e, " sz %d", cmd[4]);
-			break;
-		case ScmdSpace:
-			s = seprint(s, e, " code %d", cmd[1]);
-			break;
-		case ScmdStart:
-			s = seprint(s, e, " code %d", cmd[4]);
-			break;
-	
-		}
-	return s;
-}
-
-static char*
-seprintdata(char *s, char *se, uchar *p, int count)
-{
-	int i;
-
-	if(count == 0)
-		return s;
-	for(i = 0; i < 20 && i < count; i++)
-		s = seprint(s, se, " %02x", p[i]);
-	return s;
-}
-
-static void
-SRdumpReq(ScsiReq *rp)
-{
-	char buf[128];
-	char *s;
-	char *se;
-
-	se = buf+sizeof(buf);
-	s = seprint(buf, se, "lun %d ", rp->lun);
-	s = seprintcmd(s, se, (char*)rp->cmd.p, rp->cmd.count, 1);
-	s = seprint(s, se, " [%ld]", rp->data.count);
-	if(rp->cmd.write)
-		seprintdata(s, se, rp->data.p, rp->data.count);
-	fprint(2, "scsi⇒ %s\n", buf);
-}
-
-static void
-SRdumpRep(ScsiReq *rp)
-{
-	char buf[128];
-	char *s;
-	char *se;
-
-	se = buf+sizeof(buf);
-	s = seprint(buf, se, "lun %d ", rp->lun);
-	s = seprintcmd(s, se, (char*)rp->cmd.p, rp->cmd.count, 0);
-	switch(rp->status){
-	case STok:
-		s = seprint(s, se, " good [%ld] ", rp->data.count);
-		if(rp->cmd.write == 0)
-			s = seprintdata(s, se, rp->data.p, rp->data.count);
-		break;
-	case STnomem:
-		s = seprint(s, se, " buffer allocation failed");
-		break;
-	case STharderr:
-		s = seprint(s, se, " controller error");
-		break;
-	case STtimeout:
-		s = seprint(s, se, " bus timeout");
-		break;
-	case STcheck:
-		s = seprint(s, se, " check condition");
-		break;
-	case STcondmet:
-		s = seprint(s, se, " condition met/good");
-		break;
-	case STbusy:
-		s = seprint(s, se, " busy");
-		break;
-	case STintok:
-		s = seprint(s, se, " intermediate/good");
-		break;
-	case STintcondmet:
-		s = seprint(s, se, " intermediate/condition met/good");
-		break;
-	case STresconf:
-		s = seprint(s, se, " reservation conflict");
-		break;
-	case STterminated:
-		s = seprint(s, se, " command terminated");
-		break;
-	case STqfull:
-		s = seprint(s, se, " queue full");
-		break;
-	default:
-		s = seprint(s, se, " sts=%#x", rp->status);
-	}
-	USED(s);
-	fprint(2, "scsi← %s\n", buf);
-}
-
-static char*
-scsierr(ScsiReq *rp)
-{
-	int ec;
-
-	switch(rp->status){
-	case 0:
-		return "";
-	case Status_SD:
-		ec = (rp->sense[12] << 8) | rp->sense[13];
-		return scsierrmsg(ec);
-	case Status_SW:
-		return "software error";
-	case Status_BADARG:
-		return "bad argument";
-	case Status_RO:
-		return "device is read only";
-	default:
-		return "unknown";
-	}
-}
-
-static void
-SRdumpErr(ScsiReq *rp)
-{
-	char buf[128];
-	char *se;
-
-	se = buf+sizeof(buf);
-	seprintcmd(buf, se, (char*)rp->cmd.p, rp->cmd.count, 0);
-	print("\t%s status: %s\n", buf, scsierr(rp));
-}
-
-long
-SRrequest(ScsiReq *rp)
-{
-	long n;
-	int status;
-
-retry:
-	if(debug)
-		SRdumpReq(rp);
-	if(rp->flags&Fusb)
-		n = umsrequest(rp->umsc, &rp->cmd, &rp->data, &status);
-	else
-		n = request(rp->fd, &rp->cmd, &rp->data, &status);
-	rp->status = status;
-	if(status == STok)
-		rp->data.count = n;
-	if(debug)
-		SRdumpRep(rp);
-	switch(status){
-	case STok:
-		break;
-	case STcheck:
-		if(rp->cmd.p[0] != ScmdRsense && SRreqsense(rp) != -1)
-			rp->status = Status_SD;
-		if(debug || exabyte)
-			SRdumpErr(rp);
-		werrstr("%s", scsierr(rp));
-		return -1;
-	case STbusy:
-		sleep(1000);		/* TODO: try a shorter sleep? */
-		goto retry;
-	default:
-		if(debug || exabyte)
-			SRdumpErr(rp);
-		werrstr("%s", scsierr(rp));
-		return -1;
-	}
-	return n;
-}
-
-int
-SRclose(ScsiReq *rp)
-{
-	if((rp->flags & Fopen) == 0){
-		if(diskdebug)
-			fprint(2, "disk: closing closed file\n");
-		rp->status = Status_BADARG;
-		return -1;
-	}
-	close(rp->fd);
-	rp->flags = 0;
-	return 0;
-}
-
-static int
-dirdevopen(ScsiReq *rp)
-{
-	uvlong blocks;
-	uchar data[8+4+20];	/* 16-byte result: lba, blksize, reserved */
-
-	memset(data, 0, sizeof data);
-	if(SRstart(rp, 1) == -1 || SRrcapacity(rp, data) == -1)
-		return -1;
-	rp->lbsize = GETBELONG(data+4);
-	blocks =     GETBELONG(data);
-	if(debug)
-		fprint(2, "disk: dirdevopen: 10-byte logical block size %lud, "
-			"# blocks %llud\n", rp->lbsize, blocks);
-	if(blocks == 0xffffffff){
-		if(SRrcapacity16(rp, data) == -1)
-			return -1;
-		rp->lbsize = GETBELONG(data + 8);
-		blocks = (vlong)GETBELONG(data)<<32 | GETBELONG(data + 4);
-		if(debug)
-			fprint(2, "disk: dirdevopen: 16-byte logical block size"
-				" %lud, # blocks %llud\n", rp->lbsize, blocks);
-	}
-	/* some newer dev's don't support 6-byte commands */
-	if(blocks > Max24off && !force6bytecmds)
-		rp->flags |= Frw10;
-	return 0;
-}
-
-static int
-seqdevopen(ScsiReq *rp)
-{
-	uchar mode[16], limits[6];
-
-	if(SRrblimits(rp, limits) == -1)
-		return -1;
-	if(limits[1] == 0 && limits[2] == limits[4] && limits[3] == limits[5]){
-		rp->flags |= Fbfixed;
-		rp->lbsize = limits[4]<<8 | limits[5];
-		if(debug)
-			fprint(2, "disk: seqdevopen: 10-byte logical block size %lud\n",
-				rp->lbsize);
-		return 0;
-	}
-	/*
-	 * On some older hardware the optional 10-byte
-	 * modeselect command isn't implemented.
-	 */
-	if (force6bytecmds)
-		rp->flags |= Fmode6;
-	if(!(rp->flags & Fmode6)){
-		/* try 10-byte command first */
-		memset(mode, 0, sizeof mode);
-		mode[3] = 0x10;		/* device-specific param. */
-		mode[7] = 8;		/* block descriptor length */
-		/*
-		 * exabytes can't handle this, and
-		 * modeselect(10) is optional.
-		 */
-		if(SRmodeselect10(rp, mode, sizeof mode) != -1){
-			rp->lbsize = 1;
-			return 0;	/* success */
-		}
-		/* can't do 10-byte commands, back off to 6-byte ones */
-		rp->flags |= Fmode6;
-	}
-
-	/* 6-byte command */
-	memset(mode, 0, sizeof mode);
-	mode[2] = 0x10;		/* device-specific param. */
-	mode[3] = 8;		/* block descriptor length */
-	/*
-	 * bsd sez exabytes need this bit (NBE: no busy enable) in
-	 * vendor-specific page (0), but so far we haven't needed it.
-	mode[12] |= 8;
-	 */
-	if(SRmodeselect6(rp, mode, 4+8) == -1)
-		return -1;
-	rp->lbsize = 1;
-	return 0;
-}
-
-static int
-wormdevopen(ScsiReq *rp)
-{
-	long status;
-	uchar list[MaxDirData];
-
-	if (SRstart(rp, 1) == -1 ||
-	    (status = SRmodesense10(rp, Allmodepages, list, sizeof list)) == -1)
-		return -1;
-	/* nbytes = list[0]<<8 | list[1]; */
-
-	/* # of bytes of block descriptors of 8 bytes each; not even 1? */
-	if((list[6]<<8 | list[7]) < 8)
-		rp->lbsize = 2048;
-	else
-		/* last 3 bytes of block 0 descriptor */
-		rp->lbsize = GETBE24(list+13);
-	if(debug)
-		fprint(2, "disk: wormdevopen: 10-byte logical block size %lud\n",
-			rp->lbsize);
-	return status;
-}
-
-int
-SRopenraw(ScsiReq *rp, char *unit)
-{
-	char name[128];
-
-	if(rp->flags & Fopen){
-		if(diskdebug)
-			fprint(2, "disk: opening open file\n");
-		rp->status = Status_BADARG;
-		return -1;
-	}
-	memset(rp, 0, sizeof *rp);
-	rp->unit = unit;
-
-	snprint(name, sizeof name, "%s/raw", unit);
-	if((rp->fd = open(name, ORDWR)) == -1){
-		rp->status = STtimeout;
-		return -1;
-	}
-	rp->flags = Fopen;
-	return 0;
-}
-
-int
-SRopen(ScsiReq *rp, char *unit)
-{
-	if(SRopenraw(rp, unit) == -1)
-		return -1;
-	SRready(rp);
-	if(SRinquiry(rp) >= 0){
-		switch(rp->inquiry[0]){
-
-		default:
-			fprint(2, "unknown device type 0x%.2x\n", rp->inquiry[0]);
-			rp->status = Status_SW;
-			break;
-
-		case Devdir:
-		case Devcd:
-		case Devmo:
-			if(dirdevopen(rp) == -1)
-				break;
-			return 0;
-
-		case Devseq:
-			rp->flags |= Fseqdev;
-			if(seqdevopen(rp) == -1)
-				break;
-			return 0;
-
-		case Devprint:
-			rp->flags |= Fprintdev;
-			return 0;
-
-		case Devworm:
-			rp->flags |= Fwormdev;
-			if(wormdevopen(rp) == -1)
-				break;
-			return 0;
-
-		case Devjuke:
-			rp->flags |= Fchanger;
-			return 0;
-		}
-	}
-	SRclose(rp);
-	return -1;
-}
--- a/sys/src/cmd/usb/disk/scsireq.h
+++ /dev/null
@@ -1,238 +1,0 @@
-/*
- * This is /sys/src/cmd/scuzz/scsireq.h
- * changed to add more debug support, and to keep
- * disk compiling without a scuzz that includes these changes.
- *
- * scsireq.h is also included by usb/disk and cdfs.
- */
-typedef struct Umsc Umsc;
-#pragma incomplete Umsc
-
-enum {					/* fundamental constants/defaults */
-	MaxDirData	= 255,		/* max. direct data returned */
-	/*
-	 * Because we are accessed via devmnt, we can never get i/o counts
-	 * larger than 8216 (Msgsize and devmnt's offered iounit) - 24
-	 * (IOHDRSZ) = 8K.
-	 */
-	Maxiosize	= 8216 - IOHDRSZ, /* max. I/O transfer size */
-};
-
-typedef struct {
-	uchar	*p;
-	long	count;
-	uchar	write;
-} ScsiPtr;
-
-typedef struct {
-	int	flags;
-	char	*unit;			/* unit directory */
-	int	lun;
-	ulong	lbsize;
-	uvlong	offset;			/* in blocks of lbsize bytes */
-	int	fd;
-	Umsc	*umsc;			/* lun */
-	ScsiPtr	cmd;
-	ScsiPtr	data;
-	int	status;			/* returned status */
-	uchar	sense[MaxDirData];	/* returned sense data */
-	uchar	inquiry[MaxDirData];	/* returned inquiry data */
-	int	readblock;		/* flag: read a block since open */
-} ScsiReq;
-
-enum {					/* software flags */
-	Fopen		= 0x0001,	/* open */
-	Fseqdev		= 0x0002,	/* sequential-access device */
-	Fwritten	= 0x0004,	/* device written */
-	Fronly		= 0x0008,	/* device is read-only */
-	Fwormdev	= 0x0010,	/* write-once read-multiple device */
-	Fprintdev	= 0x0020,	/* printer */
-	Fbfixed		= 0x0040,	/* fixed block size */
-	Fchanger	= 0x0080,	/* medium-changer device */
-	Finqok		= 0x0100,	/* inquiry data is OK */
-	Fmode6		= 0x0200,	/* use 6-byte modeselect */
-	Frw10		= 0x0400,	/* use 10-byte read/write */
-	Fusb		= 0x0800,	/* USB transparent scsi */
-};
-
-enum {
-	STnomem		=-4,		/* buffer allocation failed */
-	STharderr	=-3,		/* controller error of some kind */
-	STtimeout	=-2,		/* bus timeout */
-	STok		= 0,		/* good */
-	STcheck		= 0x02,		/* check condition */
-	STcondmet	= 0x04,		/* condition met/good */
-	STbusy		= 0x08,		/* busy */
-	STintok		= 0x10,		/* intermediate/good */
-	STintcondmet	= 0x14,		/* intermediate/condition met/good */
-	STresconf	= 0x18,		/* reservation conflict */
-	STterminated	= 0x22,		/* command terminated */
-	STqfull		= 0x28,		/* queue full */
-};
-
-enum {					/* status */
-	Status_SD	= 0x80,		/* sense-data available */
-	Status_SW	= 0x83,		/* internal software error */
-	Status_BADARG	= 0x84,		/* bad argument to request */
-	Status_RO	= 0x85,		/* device is read-only */
-};
-
-enum {					/* SCSI command codes */
-	ScmdTur		= 0x00,		/* test unit ready */
-	ScmdRewind	= 0x01,		/* rezero/rewind */
-	ScmdRsense	= 0x03,		/* request sense */
-	ScmdFormat	= 0x04,		/* format unit */
-	ScmdRblimits	= 0x05,		/* read block limits */
-	ScmdRead	= 0x08,		/* read */
-	ScmdWrite	= 0x0A,		/* write */
-	ScmdSeek	= 0x0B,		/* seek */
-	ScmdFmark	= 0x10,		/* write filemarks */
-	ScmdSpace	= 0x11,		/* space forward/backward */
-	ScmdInq		= 0x12,		/* inquiry */
-	ScmdMselect6	= 0x15,		/* mode select */
-	ScmdMselect10	= 0x55,		/* mode select */
-	ScmdMsense6	= 0x1A,		/* mode sense */
-	ScmdMsense10	= 0x5A,		/* mode sense */
-	ScmdStart	= 0x1B,		/* start/stop unit */
-	ScmdRcapacity	= 0x25,		/* read capacity */
-	ScmdRcapacity16	= 0x9e,		/* long read capacity */
-	ScmdExtread	= 0x28,		/* extended read */
-	ScmdExtwrite	= 0x2A,		/* extended write */
-	ScmdExtseek	= 0x2B,		/* extended seek */
-
-	ScmdSynccache	= 0x35,		/* flush cache */
-	ScmdRTOC	= 0x43,		/* read TOC data */
-	ScmdRdiscinfo	= 0x51,		/* read disc information */
-	ScmdRtrackinfo	= 0x52,		/* read track information */
-	ScmdReserve	= 0x53,		/* reserve track */
-	ScmdBlank	= 0xA1,		/* blank *-RW media */
-
-	ScmdCDpause	= 0x4B,		/* pause/resume */
-	ScmdCDstop	= 0x4E,		/* stop play/scan */
-	ScmdCDplay	= 0xA5,		/* play audio */
-	ScmdCDload	= 0xA6,		/* load/unload */
-	ScmdCDscan	= 0xBA,		/* fast forward/reverse */
-	ScmdCDstatus	= 0xBD,		/* mechanism status */
-	Scmdgetconf	= 0x46,		/* get configuration */
-
-	ScmdEInitialise	= 0x07,		/* initialise element status */
-	ScmdMMove	= 0xA5,		/* move medium */
-	ScmdEStatus	= 0xB8,		/* read element status */
-	ScmdMExchange	= 0xA6,		/* exchange medium */
-	ScmdEposition	= 0x2B,		/* position to element */
-
-	ScmdReadDVD	= 0xAD,		/* read dvd structure */
-	ScmdReportKey	= 0xA4,		/* read dvd key */
-	ScmdSendKey	= 0xA3,		/* write dvd key */
-
-	ScmdClosetracksess= 0x5B,
-	ScmdRead12	= 0xA8,
-	ScmdSetcdspeed	= 0xBB,
-	ScmdReadcd	= 0xBE,
-
-	/* vendor-specific */
-	ScmdFwaddr	= 0xE2,		/* first writeable address */
-	ScmdTreserve	= 0xE4,		/* reserve track */
-	ScmdTinfo	= 0xE5,		/* read track info */
-	ScmdTwrite	= 0xE6,		/* write track */
-	ScmdMload	= 0xE7,		/* medium load/unload */
-	ScmdFixation	= 0xE9,		/* fixation */
-};
-
-enum {
-	/* sense data byte 0 */
-	Sd0valid	= 0x80,		/* valid sense data present */
-
-	/* sense data byte 2 */
-	/* incorrect-length indicator, difference in bytes 3—6 */
-	Sd2ili		= 0x20,
-	Sd2eom		= 0x40,		/* end of medium (tape) */
-	Sd2filemark	= 0x80,		/* at a filemark (tape) */
-
-	/* command byte 1 */
-	Cmd1fixed	= 1,		/* use fixed-length blocks */
-	Cmd1sili	= 2,		/* don't set Sd2ili */
-
-	/* limit of block #s in 24-bit ccbs */
-	Max24off	= (1<<21) - 1,	/* 2⁲ⁱ - 1 */
-
-	/* mode pages */
-	Allmodepages = 0x3F,
-};
-
-/* scsi device types, from the scsi standards */
-enum {
-	Devdir,			/* usually disk */
-	Devseq,			/* usually tape */
-	Devprint,
-	Dev3,
-	Devworm,		/* also direct, but special */
-	Devcd,			/* also direct */
-	Dev6,
-	Devmo,			/* also direct */
-	Devjuke,
-};
-
-/* p arguments should be of type uchar* */
-#define GETBELONG(p) ((ulong)(p)[0]<<24 | (ulong)(p)[1]<<16 | (p)[2]<<8 | (p)[3])
-#define PUTBELONG(p, ul) ((p)[0] = (ul)>>24, (p)[1] = (ul)>>16, \
-			  (p)[2] = (ul)>>8,  (p)[3] = (ul))
-#define GETBE24(p)	((ulong)(p)[0]<<16 | (p)[1]<<8 | (p)[2])
-#define PUTBE24(p, ul)	((p)[0] = (ul)>>16, (p)[1] = (ul)>>8, (p)[2] = (ul))
-
-long	SRready(ScsiReq*);
-long	SRrewind(ScsiReq*);
-long	SRreqsense(ScsiReq*);
-long	SRformat(ScsiReq*);
-long	SRrblimits(ScsiReq*, uchar*);
-long	SRread(ScsiReq*, void*, long);
-long	SRwrite(ScsiReq*, void*, long);
-long	SRseek(ScsiReq*, long, int);
-long	SRfilemark(ScsiReq*, ulong);
-long	SRspace(ScsiReq*, uchar, long);
-long	SRinquiry(ScsiReq*);
-long	SRmodeselect6(ScsiReq*, uchar*, long);
-long	SRmodeselect10(ScsiReq*, uchar*, long);
-long	SRmodesense6(ScsiReq*, uchar, uchar*, long);
-long	SRmodesense10(ScsiReq*, uchar, uchar*, long);
-long	SRstart(ScsiReq*, uchar);
-long	SRrcapacity(ScsiReq*, uchar*);
-long	SRrcapacity16(ScsiReq*, uchar*);
-
-long	SRblank(ScsiReq*, uchar, uchar);	/* MMC CD-R/CD-RW commands */
-long	SRsynccache(ScsiReq*);
-long	SRTOC(ScsiReq*, void*, int, uchar, uchar);
-long	SRrdiscinfo(ScsiReq*, void*, int);
-long	SRrtrackinfo(ScsiReq*, void*, int, int);
-
-long	SRcdpause(ScsiReq*, int);		/* MMC CD audio commands */
-long	SRcdstop(ScsiReq*);
-long	SRcdload(ScsiReq*, int, int);
-long	SRcdplay(ScsiReq*, int, long, long);
-long	SRcdstatus(ScsiReq*, uchar*, int);
-long	SRgetconf(ScsiReq*, uchar*, int);
-
-/*	old CD-R/CD-RW commands */
-long	SRfwaddr(ScsiReq*, uchar, uchar, uchar, uchar*);
-long	SRtreserve(ScsiReq*, long);
-long	SRtinfo(ScsiReq*, uchar, uchar*);
-long	SRwtrack(ScsiReq*, void*, long, uchar, uchar);
-long	SRmload(ScsiReq*, uchar);
-long	SRfixation(ScsiReq*, uchar);
-
-long	SReinitialise(ScsiReq*);		/* CHANGER commands */
-long	SRestatus(ScsiReq*, uchar, uchar*, int);
-long	SRmmove(ScsiReq*, int, int, int, int);
-
-long	SRrequest(ScsiReq*);
-int	SRclose(ScsiReq*);
-int	SRopenraw(ScsiReq*, char*);
-int	SRopen(ScsiReq*, char*);
-
-void	makesense(ScsiReq*);
-
-long	umsrequest(struct Umsc*, ScsiPtr*, ScsiPtr*, int*);
-
-void	scsidebug(int);
-
-char*	scsierrmsg(int n);
--- a/sys/src/cmd/usb/disk/ums.h
+++ /dev/null
@@ -1,125 +1,0 @@
-/*
- * mass storage transport protocols and subclasses,
- * from usb mass storage class specification overview rev 1.2
- */
-
-typedef struct Umsc Umsc;
-typedef struct Ums Ums;
-typedef struct Cbw Cbw;			/* command block wrapper */
-typedef struct Csw Csw;			/* command status wrapper */
-typedef struct Part Part;
-
-enum
-{
-	Protocbi =	0,	/* control/bulk/interrupt; mainly floppies */
-	Protocb =	1,	/*   "  with no interrupt; mainly floppies */
-	Protobulk =	0x50,	/* bulk only */
-
-	Subrbc =	1,	/* reduced blk cmds */
-	Subatapi =	2,	/* cd/dvd using sff-8020i or mmc-2 cmd blks */
-	Subqic 	=	3,	/* QIC-157 tapes */
-	Subufi =	4,	/* floppy */
-	Sub8070 =	5,	/* removable media, atapi-like */
-	Subscsi =	6,	/* scsi transparent cmd set */
-	Subisd200 =	7,	/* ISD200 ATA */
-	Subdev =	0xff,	/* use device's value */
-
-	Umsreset =	0xFF,
-	Getmaxlun =	0xFE,
-
-//	Maxlun		= 256,
-	Maxlun		= 32,
-
-	CMreset = 1,
-
-	Pcmd = 0,
-	Pdata,
-	Pstatus,
-
-	CbwLen		= 31,
-	CbwDataIn	= 0x80,
-	CbwDataOut	= 0x00,
-	CswLen		= 13,
-	CswOk		= 0,
-	CswFailed	= 1,
-	CswPhaseErr	= 2,
-	
-	Maxparts		= 16,
-};
-
-/*
- * corresponds to a lun.
- * these are ~600+Maxiosize bytes each; ScsiReq is not tiny.
- */
-
-struct Part
-{
-	int id;
-	int inuse;
-	int vers;
-	ulong mode;
-	char	*name;
-	vlong offset;		/* in lbsize units */
-	vlong length;		/* in lbsize units */
-};
-
-
-struct Umsc
-{
-	ScsiReq;
-	uvlong	blocks;
-	vlong	capacity;
-
-	/* from setup */
-	char	*bufp;
-	long	off;		/* offset within a block */
-	long	nb;		/* byte count */
-
-	/* partitions */
-	Part part[Maxparts];
-
-	uchar 	rawcmd[10];
-	uchar	phase;
-	char	*inq;
-	Ums	*ums;
-	Usbfs	fs;
-	char	buf[Maxiosize];
-};
-
-struct Ums
-{
-	QLock;
-	Dev	*dev;
-	Dev	*epin;
-	Dev	*epout;
-	Umsc	*lun;
-	uchar	maxlun;
-	int	seq;
-	int	nerrs;
-	int	wrongresidues;
-};
-
-/*
- * USB transparent SCSI devices
- */
-struct Cbw
-{
-	char	signature[4];		/* "USBC" */
-	long	tag;
-	long	datalen;
-	uchar	flags;
-	uchar	lun;
-	uchar	len;
-	char	command[16];
-};
-
-struct Csw
-{
-	char	signature[4];		/* "USBS" */
-	long	tag;
-	long	dataresidue;
-	uchar	status;
-};
-
-
-int	diskmain(Dev*, int, char**);
--- a/sys/src/cmd/usb/ether/asix.c
+++ /dev/null
@@ -1,484 +1,0 @@
-/*
- * Asix USB ether adapters
- * I got no documentation for it, thus the bits
- * come from other systems; it's likely this is
- * doing more than needed in some places and
- * less than required in others.
- */
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "ether.h"
-
-enum
-{
-
-	/* Asix commands */
-	Cswmii		= 0x06,		/* set sw mii */
-	Crmii		= 0x07,		/* read mii reg */
-	Cwmii		= 0x08,		/* write mii reg */
-	Chwmii		= 0x0a,		/* set hw mii */
-	Creeprom	= 0x0b,		/* read eeprom */
-	Cwdis		= 0x0e,		/* write disable */
-	Cwena		= 0x0d,		/* write enable */
-	Crrxctl		= 0x0f,		/* read rx ctl */
-	Cwrxctl		= 0x10,		/* write rx ctl */
-	Cwipg		= 0x12,		/* write ipg */
-	Crmac		= 0x13,		/* read mac addr */
-	Crphy		= 0x19,		/* read phy id */
-	Cwmedium		= 0x1b,		/* write medium mode */
-	Crgpio		= 0x1e,		/* read gpio */
-	Cwgpio		= 0x1f,		/* write gpios */
-	Creset		= 0x20,		/* reset */
-	Cwphy		= 0x22,		/* select phy */
-
-	/* reset codes */
-	Rclear		= 0x00,
-	Rprte		= 0x04,
-	Rprl		= 0x08,
-	Riprl		= 0x20,
-	Rippd		= 0x40,
-
-	Gpiogpo1en	= 0x04,	/* gpio1 enable */,
-	Gpiogpo1		= 0x08,	/* gpio1 value */
-	Gpiogpo2en	= 0x10,	/* gpio2 enable */
-	Gpiogpo2		= 0x20,	/* gpio2 value */
-	Gpiorse		= 0x80,	/* gpio reload serial eeprom */
-
-	Pmask		= 0x1F,
-	Pembed		= 0x10,			/* embedded phy */
-
-	Mfd		= 0x002,		/* media */
-	Mac		= 0x004,
-	Mrfc		= 0x010,
-	Mtfc		= 0x020,
-	Mjfe		= 0x040,
-	Mre		= 0x100,
-	Mps		= 0x200,
-	Mall772		= Mfd|Mrfc|Mtfc|Mps|Mac|Mre,
-	Mall178		= Mps|Mfd|Mac|Mrfc|Mtfc|Mjfe|Mre,
-
-	Ipgdflt		= 0x15|0x0c|0x12,	/* default ipg0, 1, 2 */
-	Rxctlso		= 0x80,
-	Rxctlab		= 0x08,
-	Rxctlsep	= 0x04,
-	Rxctlamall	= 0x02,			/* all multicast */
-	Rxctlprom	= 0x01,			/* promiscuous */
-
-	/* MII */
-	Miibmcr			= 0x00,		/* basic mode ctrl reg. */
-		Bmcrreset	= 0x8000,	/* reset */
-		Bmcranena	= 0x1000,	/* auto neg. enable */
-		Bmcrar		= 0x0200,	/* announce restart */
-
-	Miiad			= 0x04,		/* advertise reg. */
-		Adcsma		= 0x0001,
-		Ad1000f		= 0x0200,
-		Ad1000h		= 0x0100,
-		Ad10h		= 0x0020,
-		Ad10f		= 0x0040,
-		Ad100h		= 0x0080,
-		Ad100f		= 0x0100,
-		Adpause		= 0x0400,
-		Adall		= Ad10h|Ad10f|Ad100h|Ad100f,
-
-	Miimctl			= 0x14,		/* marvell ctl */
-		Mtxdly		= 0x02,
-		Mrxdly		= 0x80,
-		Mtxrxdly	= 0x82,
-
-	Miic1000			= 0x09,
-
-};
-
-static int
-asixset(Dev *d, int c, int v)
-{
-	int r;
-	int ec;
-
-	r = Rh2d|Rvendor|Rdev;
-	ec = usbcmd(d, r, c, v, 0, nil, 0);
-	if(ec < 0)
-		deprint(2, "%s: asixset %x %x: %r\n", argv0, c, v);
-	return ec;
-}
-
-static int
-asixget(Dev *d, int c, uchar *buf, int l)
-{
-	int r;
-	int ec;
-
-	r = Rd2h|Rvendor|Rdev;
-	ec = usbcmd(d, r, c, 0, 0, buf, l);
-	if(ec < 0)
-		deprint(2, "%s: asixget %x: %r\n", argv0, c);
-	return ec;
-}
-
-static int
-getgpio(Dev *d)
-{
-	uchar c;
-
-	if(asixget(d, Crgpio, &c, 1) < 0)
-		return -1;
-	return c;
-}
-
-static int
-getphy(Dev *d)
-{
-	uchar buf[2];
-
-	if(asixget(d, Crphy, buf, sizeof(buf)) < 0)
-		return -1;
-	deprint(2, "%s: phy addr %#ux\n", argv0, buf[1]);
-	return buf[1];
-}
-
-static int
-getrxctl(Dev *d)
-{
-	uchar buf[2];
-	int r;
-
-	memset(buf, 0, sizeof(buf));
-	if(asixget(d, Crrxctl, buf, sizeof(buf)) < 0)
-		return -1;
-	r = GET2(buf);
-	deprint(2, "%s: rxctl %#x\n", argv0, r);
-	return r;
-}
-
-static int
-getmac(Dev *d, uchar buf[])
-{
-	if(asixget(d, Crmac, buf, Eaddrlen) < 0)
-		return -1;
-	return Eaddrlen;
-}
-
-static int
-miiread(Dev *d, int phy, int reg)
-{
-	int r;
-	uchar v[2];
-
-	r = Rd2h|Rvendor|Rdev;
-	if(usbcmd(d, r, Crmii, phy, reg, v, 2) < 0){
-		dprint(2, "%s: miiwrite: %r\n", argv0);
-		return -1;
-	}
-	r = GET2(v);
-	if(r == 0xFFFF)
-		return -1;
-	return r;
-}
-
-
-static int
-miiwrite(Dev *d, int phy, int reg, int val)
-{
-	int r;
-	uchar v[2];
-
-	if(asixset(d, Cswmii, 0) < 0)
-		return -1;
-	r = Rh2d|Rvendor|Rdev;
-	PUT2(v, val);
-	if(usbcmd(d, r, Cwmii, phy, reg, v, 2) < 0){
-		deprint(2, "%s: miiwrite: %#x %#x %r\n", argv0, reg, val);
-		return -1;
-	}
-	if(asixset(d, Chwmii, 0) < 0)
-		return -1;
-	return 0;
-}
-
-static int
-eepromread(Dev *d, int i)
-{
-	int r;
-	int ec;
-	uchar buf[2];
-
-	r = Rd2h|Rvendor|Rdev;
-	ec = usbcmd(d, r, Creeprom, i, 0, buf, sizeof(buf));
-	if(ec < 0)
-		deprint(2, "%s: eepromread %d: %r\n", argv0, i);
-	ec = GET2(buf);
-	deprint(2, "%s: eeprom %#x = %#x\n", argv0, i, ec);
-	if(ec == 0xFFFF)
-		ec = -1;
-	return ec;
-}
-
-/*
- * No doc. we are doing what Linux does as closely
- * as we can.
- */
-static int
-ctlrinit(Ether *ether)
-{
-	Dev *d;
-	int i;
-	int bmcr;
-	int gpio;
-	int ee17;
-	int rc;
-
-	d = ether->dev;
-	switch(ether->cid){
-	default:
-		fprint(2, "%s: card known but not implemented\n", argv0);
-		return -1;
-
-	case A88178:
-		deprint(2, "%s: setting up A88178\n", argv0);
-		gpio = getgpio(d);
-		if(gpio < 0)
-			return -1;
-		deprint(2, "%s: gpio sts %#x\n", argv0, gpio);
-		asixset(d, Cwena, 0);
-		ee17 = eepromread(d, 0x0017);
-		asixset(d, Cwdis, 0);
-		asixset(d, Cwgpio, Gpiorse|Gpiogpo1|Gpiogpo1en);
-		if((ee17 >> 8) != 1){
-			asixset(d, Cwgpio, 0x003c);
-			asixset(d, Cwgpio, 0x001c);
-			asixset(d, Cwgpio, 0x003c);
-		}else{
-			asixset(d, Cwgpio, Gpiogpo1en);
-			asixset(d, Cwgpio, Gpiogpo1|Gpiogpo1en);
-		}
-		asixset(d, Creset, Rclear);
-		sleep(150);
-		asixset(d, Creset, Rippd|Rprl);
-		sleep(150);
-		asixset(d, Cwrxctl, 0);
-		if(getmac(d, ether->addr) < 0)
-			return -1;
-		ether->phy = getphy(d);
-		if(ee17 < 0 || (ee17 & 0x7) == 0){
-			miiwrite(d, ether->phy, Miimctl, Mtxrxdly);
-			sleep(60);
-		}
-		miiwrite(d, ether->phy, Miibmcr, Bmcrreset|Bmcranena);
-		miiwrite(d, ether->phy, Miiad, Adall|Adcsma|Adpause);
-		miiwrite(d, ether->phy, Miic1000, Ad1000f);
-		bmcr = miiread(d, ether->phy, Miibmcr);
-		if((bmcr & Bmcranena) != 0){
-			bmcr |= Bmcrar;
-			miiwrite(d, ether->phy, Miibmcr, bmcr);
-		}
-		asixset(d, Cwmedium, Mall178);
-		asixset(d, Cwrxctl, Rxctlso|Rxctlab);
-		break;
-
-	case A88772:
-		deprint(2, "%s: setting up A88772\n", argv0);
-		if(asixset(d, Cwgpio, Gpiorse|Gpiogpo2|Gpiogpo2en) < 0)
-			return -1;
-		ether->phy = getphy(d);
-		dprint(2, "%s: phy %#x\n", argv0, ether->phy);
-		if((ether->phy & Pmask) == Pembed){
-			/* embedded 10/100 ethernet */
-			rc = asixset(d, Cwphy, 1);
-		}else
-			rc = asixset(d, Cwphy, 0);
-		if(rc < 0)
-			return -1;
-		if(asixset(d, Creset, Rippd|Rprl) < 0)
-			return -1;
-		sleep(150);
-		if((ether->phy & Pmask) == Pembed)
-			rc = asixset(d, Creset, Riprl);
-		else
-			rc = asixset(d, Creset, Rprte);
-		if(rc < 0)
-			return -1;
-		sleep(150);
-		rc = getrxctl(d);
-		deprint(2, "%s: rxctl is %#x\n", argv0, rc);
-		if(asixset(d, Cwrxctl, 0) < 0)
-			return -1;
-		if(getmac(d, ether->addr) < 0)
-			return -1;
-
-
-		if(asixset(d, Creset, Rprl) < 0)
-			return -1;
-		sleep(150);
-		if(asixset(d, Creset, Riprl|Rprl) < 0)
-			return -1;
-		sleep(150);
-
-		miiwrite(d, ether->phy, Miibmcr, Bmcrreset);
-		miiwrite(d, ether->phy, Miiad, Adall|Adcsma);
-		bmcr = miiread(d, ether->phy, Miibmcr);
-		if((bmcr & Bmcranena) != 0){
-			bmcr |= Bmcrar;
-			miiwrite(d, ether->phy, Miibmcr, bmcr);
-		}
-		if(asixset(d, Cwmedium, Mall772) < 0)
-			return -1;
-		if(asixset(d, Cwipg, Ipgdflt) < 0)
-			return -1;
-		if(asixset(d, Cwrxctl, Rxctlso|Rxctlab) < 0)
-			return -1;
-		deprint(2, "%s: final rxctl: %#x\n", argv0, getrxctl(d));
-		break;
-	}
-
-	if(etherdebug){
-		fprint(2, "%s: ether: phy %#x addr ", argv0, ether->phy);
-		for(i = 0; i < sizeof(ether->addr); i++)
-			fprint(2, "%02x", ether->addr[i]);
-		fprint(2, "\n");
-	}
-	return 0;
-}
-
-
-static long
-asixbread(Ether *e, Buf *bp)
-{
-	ulong nr;
-	ulong hd;
-	Buf *rbp;
-
-	rbp = e->aux;
-	if(rbp == nil || rbp->ndata < 4){
-		rbp->rp = rbp->data;
-		rbp->ndata = read(e->epin->dfd, rbp->rp, sizeof(bp->data));
-		if(rbp->ndata < 0)
-			return -1;
-	}
-	if(rbp->ndata < 4){
-		werrstr("short frame");
-		deprint(2, "%s: asixbread got %d bytes\n", argv0, rbp->ndata);
-		rbp->ndata = 0;
-		return 0;
-	}
-	hd = GET4(rbp->rp);
-	nr = hd & 0xFFFF;
-	hd = (hd>>16) & 0xFFFF;
-	if(nr != (~hd & 0xFFFF)){
-		if(0)deprint(2, "%s: asixread: bad header %#ulx %#ulx\n",
-			argv0, nr, (~hd & 0xFFFF));
-		werrstr("bad usb packet header");
-		rbp->ndata = 0;
-		return 0;
-	}
-	rbp->rp += 4;
-	if(nr < 6 || nr > Epktlen){
-		if(nr < 6)
-			werrstr("short frame");
-		else
-			werrstr("long frame");
-		deprint(2, "%s: asixbread %r (%ld)\n", argv0, nr);
-		rbp->ndata = 0;
-		return 0;
-	}
-	bp->rp = bp->data + Hdrsize;
-	memmove(bp->rp, rbp->rp, nr);
-	bp->ndata = nr;
-	rbp->rp += 4 + nr;
-	rbp->ndata -= (4 + nr);
-	return bp->ndata;
-}
-
-static long
-asixbwrite(Ether *e, Buf *bp)
-{
-	ulong len;
-	long n;
-
-	deprint(2, "%s: asixbwrite %d bytes\n", argv0, bp->ndata);
-	assert(bp->rp - bp->data >= Hdrsize);
-	bp->ndata &= 0xFFFF;
-	len = (0xFFFF0000 & ~(bp->ndata<<16))  | bp->ndata;
-	bp->rp -= 4;
-	PUT4(bp->rp, len);
-	bp->ndata += 4;
-	if((bp->ndata % e->epout->maxpkt) == 0){
-		PUT4(bp->rp+bp->ndata, 0xFFFF0000);
-		bp->ndata += 4;
-	}
-	n = write(e->epout->dfd, bp->rp, bp->ndata);
-	deprint(2, "%s: asixbwrite wrote %ld bytes\n", argv0, n);
-	if(n <= 0)
-		return n;
-	return n;
-}
-
-static int
-asixpromiscuous(Ether *e, int on)
-{
-	int rxctl;
-
-	deprint(2, "%s: aixprompiscuous %d\n", argv0, on);
-	rxctl = getrxctl(e->dev);
-	if(on != 0)
-		rxctl |= Rxctlprom;
-	else
-		rxctl &= ~Rxctlprom;
-	return asixset(e->dev, Cwrxctl, rxctl);
-}
-
-static int
-asixmulticast(Ether *e, uchar *addr, int on)
-{
-	int rxctl;
-
-	USED(addr);
-	USED(on);
-	/* BUG: should write multicast filter */
-	rxctl = getrxctl(e->dev);
-	if(e->nmcasts != 0)
-		rxctl |= Rxctlamall;
-	else
-		rxctl &= ~Rxctlamall;
-	deprint(2, "%s: asixmulticast %d\n", argv0, e->nmcasts);
-	return asixset(e->dev, Cwrxctl, rxctl);
-}
-
-static void
-asixfree(Ether *ether)
-{
-	deprint(2, "%s: aixfree %#p\n", argv0, ether);
-	free(ether->aux);
-	ether->aux = nil;
-}
-
-int
-asixreset(Ether *ether)
-{
-	Cinfo *ip;
-	Dev *dev;
-
-	dev = ether->dev;
-	for(ip = cinfo; ip->vid != 0; ip++)
-		if(ip->vid == dev->usb->vid && ip->did == dev->usb->did){
-			ether->cid = ip->cid;
-			if(ctlrinit(ether) < 0){
-				deprint(2, "%s: init failed: %r\n", argv0);
-				return -1;
-			}
-			deprint(2, "%s: asix reset done\n", argv0);
-			ether->aux = emallocz(sizeof(Buf), 1);
-			ether->bread = asixbread;
-			ether->bwrite = asixbwrite;
-			ether->free = asixfree;
-			ether->promiscuous = asixpromiscuous;
-			ether->multicast = asixmulticast;
-			ether->mbps = 100;	/* BUG */
-			return 0;
-		}
-	return -1;
-}
--- a/sys/src/cmd/usb/ether/cdc.c
+++ /dev/null
@@ -1,60 +1,0 @@
-/*
- * Standard usb ethernet communications device.
- */
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "ether.h"
-
-static int
-okclass(Iface *iface)
-{
-	return Class(iface->csp) == Clcomms && Subclass(iface->csp) == Scether;
-}
-
-static int
-getmac(Ether *ether)
-{
-	int i;
-	Usbdev *ud;
-	uchar *b;
-	Desc *dd;
-	char *mac;
-
-	ud = ether->dev->usb;
-
-	for(i = 0; i < nelem(ud->ddesc); i++)
-		if((dd = ud->ddesc[i]) != nil && okclass(dd->iface)){
-			b = (uchar*)&dd->data;
-			if(b[1] == Dfunction && b[2] == Fnether){
-				mac = loaddevstr(ether->dev, b[3]);
-				if(mac != nil && strlen(mac) != 12){
-					free(mac);
-					mac = nil;
-				}
-				if(mac != nil){
-					parseaddr(ether->addr, mac);
-					free(mac);
-					return 0;
-				}
-			}
-		}
-	return -1;
-}
-
-int
-cdcreset(Ether *ether)
-{
-	/*
-	 * Assume that all communication devices are going to
-	 * be std. ethernet communication devices. Specific controllers
-	 * must have been probed first.
-	 * NB: This ignores unions.
-	 */
-	if(ether->dev->usb->class == Clcomms)
-		return getmac(ether);
-	return -1;
-}
--- a/sys/src/cmd/usb/ether/ether.c
+++ /dev/null
@@ -1,1185 +1,0 @@
-/*
- * usb/ether - usb ethernet adapter.
- * BUG: This should use /dev/etherfile to
- * use the kernel ether device code.
- */
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "ether.h"
-
-typedef struct Dirtab Dirtab;
-
-enum
-{
-	/* Qids. Maintain order (relative to dirtabs structs) */
-	Qroot	= 0,
-	Qclone,
-	Qaddr,
-	Qifstats,
-	Qstats,
-	Qndir,
-	Qndata,
-	Qnctl,
-	Qnifstats,
-	Qnstats,
-	Qntype,
-	Qmax,
-};
-
-struct Dirtab
-{
-	char	*name;
-	int	qid;
-	int	mode;
-};
-
-typedef int (*Resetf)(Ether*);
-
-/*
- * Controllers by vid/vid. Used to locate
- * specific adapters that do not implement cdc ethernet
- * Keep null terminated.
- */
-Cinfo cinfo[] =
-{
-	/* Asix controllers.
-	 * Only A88178 and A881772 are implemented.
-	 * Others are easy to add by borrowing code
-	 * from other systems.
-	 */
-	{0x077b, 0x2226, A8817x},
-	{0x0b95, 0x1720, A8817x},
-	{0x0557, 0x2009, A8817x},
-	{0x0411, 0x003d, A8817x},
-	{0x0411, 0x006e, A88178},
-	{0x6189, 0x182d, A8817x},
-	{0x07aa, 0x0017, A8817x},
-	{0x1189, 0x0893, A8817x},
-	{0x1631, 0x6200, A8817x},
-	{0x04f1, 0x3008, A8817x},
-	{0x0b95, 0x1780, A88178},	/* Geoff */
-	{0x13b1, 0x0018, A88772},
-	{0x1557, 0x7720, A88772},
-	{0x07d1, 0x3c05, A88772},
-	{0x2001, 0x3c05, A88772},
-	{0x1737, 0x0039, A88178},
-	{0x050d, 0x5055, A88178},
-	{0x05ac, 0x1402, A88772},	/* Apple */
-	{0x0b95, 0x772a, A88772},
-	{0x14ea, 0xab11, A88178},
-	{0x0db0, 0xa877, A88772},
-	{0, 0, 0},
-};
-
-/*
- * Each etherU%d is the root of our file system,
- * which is added to the usb root directory. We only
- * have to concern ourselfs with each /etherU%d subtree.
- *
- * NB: Maintain order in dirtabs, relative to the Qids enum.
- */
-
-static Dirtab rootdirtab[] =
-{
-	"/",		Qroot,		DMDIR|0555,	/* etherU%d */
-	"clone",	Qclone,		0666,
-	"addr",		Qaddr,		0444,
-	"ifstats",	Qifstats,	0444,
-	"stats",	Qstats,		0444,
-	/* one dir per connection here */
-	nil, 0, 0,
-};
-
-static Dirtab conndirtab[] =
-{
-	"%d",		Qndir,		DMDIR|0555,
-	"data",		Qndata,		0666,
-	"ctl",		Qnctl,		0666,
-	"ifstats",	Qnifstats,	0444,
-	"stats",	Qnstats,	0444,
-	"type",		Qntype,		0444,
-	nil, 0,
-};
-
-int etherdebug;
-
-Resetf ethers[] =
-{
-	asixreset,
-	cdcreset,	/* keep last */
-};
-
-static int
-qtype(vlong q)
-{
-	return q&0xFF;
-}
-
-static int
-qnum(vlong q)
-{
-	return (q >> 8) & 0xFFFFFF;
-}
-
-static uvlong
-mkqid(int n, int t)
-{
-	uvlong q;
-
-	q = (n&0xFFFFFF) << 8 | t&0xFF;
-	return q;
-}
-
-static void
-freebuf(Ether *e, Buf *bp)
-{
-	if(0)deprint(2, "%s: freebuf %#p\n", argv0, bp);
-	if(bp != nil){
-		qlock(e);
-		e->nbufs--;
-		qunlock(e);
-		sendp(e->bc, bp);
-	}
-}
-
-static Buf*
-allocbuf(Ether *e)
-{
-	Buf *bp;
-
-	bp = nbrecvp(e->bc);
-	if(bp == nil){
-		qlock(e);
-		if(e->nabufs < Nconns){
-			bp = emallocz(sizeof(Buf), 1);
-			e->nabufs++;
-			setmalloctag(bp, getcallerpc(&e));
-			deprint(2, "%s: %d buffers\n", argv0, e->nabufs);
-		}
-		qunlock(e);
-	}
-	if(bp == nil)
-		bp = recvp(e->bc);
-	bp->rp = bp->data + Hdrsize;
-	bp->ndata = 0;
-	if(0)deprint(2, "%s: allocbuf %#p\n", argv0, bp);
-	qlock(e);
-	e->nbufs++;
-	qunlock(e);
-	return bp;
-}
-
-static Conn*
-newconn(Ether *e)
-{
-	int i;
-	Conn *c;
-
-	qlock(e);
-	for(i = 0; i < nelem(e->conns); i++){
-		c = e->conns[i];
-		if(c == nil || c->ref == 0){
-			if(c == nil){
-				c = emallocz(sizeof(Conn), 1);
-				c->rc = chancreate(sizeof(Buf*), 2);
-				c->nb = i;
-			}
-			c->ref = 1;
-			if(i == e->nconns)
-				e->nconns++;
-			e->conns[i] = c;
-			deprint(2, "%s: newconn %d\n", argv0, i);
-			qunlock(e);
-			return c;
-		}
-	}
-	qunlock(e);
-	return nil;
-}
-
-static char*
-seprintaddr(char *s, char *se, uchar *addr)
-{
-	int i;
-
-	for(i = 0; i < Eaddrlen; i++)
-		s = seprint(s, se, "%02x", addr[i]);
-	return s;
-}
-
-void
-dumpframe(char *tag, void *p, int n)
-{
-	Etherpkt *ep;
-	char buf[128];
-	char *s, *se;
-	int i;
-
-	ep = p;
-	if(n < Eaddrlen * 2 + 2){
-		fprint(2, "short packet (%d bytes)\n", n);
-		return;
-	}
-	se = buf+sizeof(buf);
-	s = seprint(buf, se, "%s [%d]: ", tag, n);
-	s = seprintaddr(s, se, ep->s);
-	s = seprint(s, se, " -> ");
-	s = seprintaddr(s, se, ep->d);
-	s = seprint(s, se, " type 0x%02ux%02ux ", ep->type[0], ep->type[1]);
-	n -= Eaddrlen * 2 + 2;
-	for(i = 0; i < n && i < 16; i++)
-		s = seprint(s, se, "%02x", ep->data[i]);
-	if(n >= 16)
-		fprint(2, "%s...\n", buf);
-	else
-		fprint(2, "%s\n", buf);
-}
-
-static char*
-seprintstats(char *s, char *se, Ether *e)
-{
-	qlock(e);
-	s = seprint(s, se, "in: %ld\n", e->nin);
-	s = seprint(s, se, "out: %ld\n", e->nout);
-	s = seprint(s, se, "input errs: %ld\n", e->nierrs);
-	s = seprint(s, se, "output errs: %ld\n", e->noerrs);
-	s = seprint(s, se, "mbps: %d\n", e->mbps);
-	s = seprint(s, se, "prom: %ld\n", e->prom.ref);
-	s = seprint(s, se, "addr: ");
-	s = seprintaddr(s, se, e->addr);
-	s = seprint(s, se, "\n");
-	qunlock(e);
-	return s;
-}
-
-static char*
-seprintifstats(char *s, char *se, Ether *e)
-{
-	int i;
-	Conn *c;
-
-	qlock(e);
-	s = seprint(s, se, "ctlr id: %#x\n", e->cid);
-	s = seprint(s, se, "phy: %#x\n", e->phy);
-	s = seprint(s, se, "exiting: %s\n", e->exiting ? "y" : "n");
-	s = seprint(s, se, "conns: %d\n", e->nconns);
-	s = seprint(s, se, "allocated bufs: %d\n", e->nabufs);
-	s = seprint(s, se, "used bufs: %d\n", e->nbufs);
-	for(i = 0; i < nelem(e->conns); i++){
-		c = e->conns[i];
-		if(c == nil)
-			continue;
-		if(c->ref == 0)
-			s = seprint(s, se, "c[%d]: free\n", i);
-		else{
-			s = seprint(s, se, "c[%d]: refs %ld t %#x h %d p %d\n",
-				c->nb, c->ref, c->type, c->headersonly, c->prom);
-		}
-	}
-	qunlock(e);
-	return s;
-}
-
-static void
-etherdump(Ether *e)
-{
-	char buf[256];
-
-	if(etherdebug == 0)
-		return;
-	seprintifstats(buf, buf+sizeof(buf), e);
-	fprint(2, "%s: ether %#p:\n%s\n", argv0, e, buf);
-}
-
-static Conn*
-getconn(Ether *e, int i, int idleok)
-{
-	Conn *c;
-
-	qlock(e);
-	if(i < 0 || i >= e->nconns)
-		c = nil;
-	else{
-		c = e->conns[i];
-		if(idleok == 0 && c != nil && c->ref == 0)
-			c = nil;
-	}
-	qunlock(e);
-	return c;
-}
-
-static void
-filldir(Usbfs *fs, Dir *d, Dirtab *tab, int cn)
-{
-	d->qid.path = mkqid(cn, tab->qid);
-	d->qid.path |= fs->qid;
-	d->mode = tab->mode;
-	if((d->mode & DMDIR) != 0)
-		d->qid.type = QTDIR;
-	else
-		d->qid.type = QTFILE;
-	if(tab->qid == Qndir)
-		snprint(d->name, Namesz, "%d", cn);
-	else
-		d->name = tab->name;
-}
-
-static int
-rootdirgen(Usbfs *fs, Qid, int i, Dir *d, void *)
-{
-	Ether *e;
-	Dirtab *tab;
-	int cn;
-
-	e = fs->aux;
-	i++;				/* skip root */
-	cn = 0;
-	if(i < nelem(rootdirtab) - 1)	/* null terminated */
-		tab = &rootdirtab[i];
-	else{
-		cn = i - nelem(rootdirtab) + 1;
-		if(cn < e->nconns)
-			tab = &conndirtab[0];
-		else
-			return -1;
-	}
-	filldir(fs, d, tab, cn);
-	return 0;
-}
-
-static int
-conndirgen(Usbfs *fs, Qid q, int i, Dir *d, void *)
-{
-	Dirtab *tab;
-
-	i++;				/* skip root */
-	if(i < nelem(conndirtab) - 1)	/* null terminated */
-		tab = &conndirtab[i];
-	else
-		return -1;
-	filldir(fs, d, tab, qnum(q.path));
-	return 0;
-}
-
-static int
-fswalk(Usbfs *fs, Fid *fid, char *name)
-{
-	int cn, i;
-	char *es;
-	Dirtab *tab;
-	Ether *e;
-	Qid qid;
-
-	e = fs->aux;
-	qid = fid->qid;
-	qid.path &= ~fs->qid;
-	if((qid.type & QTDIR) == 0){
-		werrstr("walk in non-directory");
-		return -1;
-	}
-
-	if(strcmp(name, "..") == 0){
-		/* must be /etherU%d; i.e. our root dir. */
-		fid->qid.path = mkqid(0, Qroot) | fs->qid;
-		fid->qid.vers = 0;
-		fid->qid.type = QTDIR;
-		return 0;
-	}
-	switch(qtype(qid.path)){
-	case Qroot:
-		if(name[0] >= '0' && name[0] <= '9'){
-			es = name;
-			cn = strtoul(name, &es, 10);
-			if(cn >= e->nconns || *es != 0){
-				werrstr(Enotfound);
-				return -1;
-			}
-			fid->qid.path = mkqid(cn, Qndir) | fs->qid;
-			fid->qid.vers = 0;
-			return 0;
-		}
-		/* fall */
-	case Qndir:
-		if(qtype(qid.path) == Qroot)
-			tab = rootdirtab;
-		else
-			tab = conndirtab;
-		cn = qnum(qid.path);
-		for(i = 0; tab[i].name != nil; tab++)
-			if(strcmp(tab[i].name, name) == 0){
-				fid->qid.path = mkqid(cn, tab[i].qid)|fs->qid;
-				fid->qid.vers = 0;
-				if((tab[i].mode & DMDIR) != 0)
-					fid->qid.type = QTDIR;
-				else
-					fid->qid.type = QTFILE;
-				return 0;
-			}
-		break;
-	default:
-		sysfatal("usb: ether: fswalk bug");
-	}
-	return -1;
-}
-
-static Dirtab*
-qdirtab(vlong q)
-{
-	int i, qt;
-	Dirtab *tab;
-
-	qt = qtype(q);
-	if(qt < nelem(rootdirtab) - 1){	/* null terminated */
-		tab = rootdirtab;
-		i = qt;
-	}else{
-		tab = conndirtab;
-		i = qt - (nelem(rootdirtab) - 1);
-		assert(i < nelem(conndirtab) - 1);
-	}
-	return &tab[i];
-}
-
-static int
-fsstat(Usbfs *fs, Qid qid, Dir *d)
-{
-	filldir(fs, d, qdirtab(qid.path), qnum(qid.path));
-	return 0;
-}
-
-static int
-fsopen(Usbfs *fs, Fid *fid, int omode)
-{
-	int qt;
-	vlong qid;
-	Conn *c;
-	Dirtab *tab;
-	Ether *e;
-
-	qid = fid->qid.path & ~fs->qid;
-	e = fs->aux;
-	qt = qtype(qid);
-	tab = qdirtab(qid);
-	omode &= 3;
-	if(omode != OREAD && (tab->mode&0222) == 0){
-		werrstr(Eperm);
-		return -1;
-	}
-	switch(qt){
-	case Qclone:
-		c = newconn(e);
-		if(c == nil){
-			werrstr("no more connections");
-			return -1;
-		}
-		fid->qid.type = QTFILE;
-		fid->qid.path = mkqid(c->nb, Qnctl)|fs->qid;
-		fid->qid.vers = 0;
-		break;
-	case Qndata:
-	case Qnctl:
-	case Qnifstats:
-	case Qnstats:
-	case Qntype:
-		c = getconn(e, qnum(qid), 1);
-		if(c == nil)
-			sysfatal("usb: ether: fsopen bug");
-		incref(c);
-		break;
-	}
-	etherdump(e);
-	return 0;
-}
-
-static int
-prom(Ether *e, int set)
-{
-	if(e->promiscuous != nil)
-		return e->promiscuous(e, set);
-	return 0;
-}
-
-static void
-fsclunk(Usbfs *fs, Fid *fid)
-{
-	int qt;
-	vlong qid;
-	Buf *bp;
-	Conn *c;
-	Ether *e;
-
-	e = fs->aux;
-	qid = fid->qid.path & ~fs->qid;
-	qt = qtype(qid);
-	switch(qt){
-	case Qndata:
-	case Qnctl:
-	case Qnifstats:
-	case Qnstats:
-	case Qntype:
-		if(fid->omode != ONONE){
-			c = getconn(e, qnum(qid), 0);
-			if(c == nil)
-				sysfatal("usb: ether: fsopen bug");
-			if(decref(c) == 0){
-				while((bp = nbrecvp(c->rc)) != nil)
-					freebuf(e, bp);
-				qlock(e);
-				if(c->prom != 0)
-					if(decref(&e->prom) == 0)
-						prom(e, 0);
-				c->prom = c->type = 0;
-				qunlock(e);
-			}
-		}
-		break;
-	}
-	etherdump(e);
-}
-
-int
-parseaddr(uchar *m, char *s)
-{
-	int i, n;
-	uchar v;
-
-	if(strlen(s) < 12)
-		return -1;
-	if(strlen(s) > 12 && strlen(s) < 17)
-		return -1;
-	for(i = n = 0; i < strlen(s); i++){
-		if(s[i] == ':')
-			continue;
-		if(s[i] >= 'A' && s[i] <= 'F')
-			v = 10 + s[i] - 'A';
-		else if(s[i] >= 'a' && s[i] <= 'f')
-			v = 10 + s[i] - 'a';
-		else if(s[i] >= '0' && s[i] <= '9')
-			v = s[i] - '0';
-		else
-			return -1;
-		if(n&1)
-			m[n/2] |= v;
-		else
-			m[n/2] = v<<4;
-		n++;
-	}
-	return 0;
-}
-
-static long
-fsread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
-{
-	int cn, qt;
-	char *s, *se;
-	char buf[2048];		/* keep this large for ifstats */
-	Buf *bp;
-	Conn *c;
-	Ether *e;
-	Qid q;
-
-	q = fid->qid;
-	q.path &= ~fs->qid;
-	e = fs->aux;
-	s = buf;
-	se = buf+sizeof(buf);
-	qt = qtype(q.path);
-	cn = qnum(q.path);
-	switch(qt){
-	case Qroot:
-		count = usbdirread(fs, q, data, count, offset, rootdirgen, nil);
-		break;
-	case Qaddr:
-		s = seprintaddr(s, se, e->addr);
-		count = usbreadbuf(data, count, offset, buf, s - buf);
-		break;
-	case Qnifstats:
-		/* BUG */
-	case Qifstats:
-		s = seprintifstats(s, se, e);
-		if(e->seprintstats != nil)
-			s = e->seprintstats(s, se, e);
-		count = usbreadbuf(data, count, offset, buf, s - buf);
-		break;
-	case Qnstats:
-		/* BUG */
-	case Qstats:
-		s = seprintstats(s, se, e);
-		count = usbreadbuf(data, count, offset, buf, s - buf);
-		break;
-
-	case Qndir:
-		count = usbdirread(fs, q, data, count, offset, conndirgen, nil);
-		break;
-	case Qndata:
-		c = getconn(e, cn, 0);
-		if(c == nil){
-			werrstr(Eio);
-			return -1;
-		}
-		bp = recvp(c->rc);
-		if(bp == nil)
-			return -1;
-		if(etherdebug > 1)
-			dumpframe("etherin", bp->rp, bp->ndata);
-		count = usbreadbuf(data, count, 0LL, bp->rp, bp->ndata);
-		freebuf(e, bp);
-		break;
-	case Qnctl:
-		s = seprint(s, se, "%11d ", cn);
-		count = usbreadbuf(data, count, offset, buf, s - buf);
-		break;
-	case Qntype:
-		c = getconn(e, cn, 0);
-		if(c == nil)
-			s = seprint(s, se, "%11d ", 0);
-		else
-			s = seprint(s, se, "%11d ", c->type);
-		count = usbreadbuf(data, count, offset, buf, s - buf);
-		break;
-	default:
-		sysfatal("usb: ether: fsread bug");
-	}
-	return count;
-}
-
-static int
-typeinuse(Ether *e, int t)
-{
-	int i;
-
-	for(i = 0; i < e->nconns; i++)
-		if(e->conns[i]->ref > 0 && e->conns[i]->type == t)
-			return 1;
-	return 0;
-}
-
-static int
-isloopback(Ether *e, Buf *)
-{
-	return e->prom.ref > 0; /* BUG: also loopbacks and broadcasts */
-}
-
-static int
-etherctl(Ether *e, Conn *c, char *buf)
-{
-	uchar addr[Eaddrlen];
-	int t;
-
-	deprint(2, "%s: etherctl: %s\n", argv0, buf);
-	if(strncmp(buf, "connect ", 8) == 0){
-		t = atoi(buf+8);
-		qlock(e);
-		if(typeinuse(e, t)){
-			werrstr("type already in use");
-			qunlock(e);
-			return -1;
-		}
-		c->type = atoi(buf+8);
-		qunlock(e);
-		return 0;
-	}
-	if(strncmp(buf, "nonblocking", 11) == 0){
-		if(buf[11] == '\n' || buf[11] == 0)
-			e->nblock = 1;
-		else
-			e->nblock = atoi(buf + 12);
-		deprint(2, "%s: nblock %d\n", argv0, e->nblock);
-		return 0;
-	}
-	if(strncmp(buf, "promiscuous", 11) == 0){
-		if(c->prom == 0)
-			incref(&e->prom);
-		c->prom = 1;
-		return prom(e, 1);
-	}
-	if(strncmp(buf, "headersonly", 11) == 0){
-		c->headersonly = 1;
-		return 0;
-	}
-	if(strncmp(buf, "addmulti ", 9) == 0 || strncmp(buf, "remmulti ", 9) == 0){
-		if(parseaddr(addr, buf+9) < 0){
-			werrstr("bad address");
-			return -1;
-		}
-		if(e->multicast == nil)
-			return 0;
-		if(strncmp(buf, "add", 3) == 0){
-			e->nmcasts++;
-			return e->multicast(e, addr, 1);
-		}else{
-			e->nmcasts--;
-			return e->multicast(e, addr, 0);
-		}
-	}
-
-	if(e->ctl != nil)
-		return e->ctl(e, buf);
-	werrstr(Ebadctl);
-	return -1;
-}
-
-static long
-etherbread(Ether *e, Buf *bp)
-{
-	deprint(2, "%s: etherbread\n", argv0);
-	bp->rp = bp->data + Hdrsize;
-	bp->ndata = -1;
-	bp->ndata = read(e->epin->dfd, bp->rp, sizeof(bp->data)-Hdrsize);
-	if(bp->ndata < 0){
-		deprint(2, "%s: etherbread: %r\n", argv0);	/* keep { and }  */
-	}else
-		deprint(2, "%s: etherbread: got %d bytes\n", argv0, bp->ndata);
-	return bp->ndata;
-}
-
-static long
-etherbwrite(Ether *e, Buf *bp)
-{
-	long n;
-
-	deprint(2, "%s: etherbwrite %d bytes\n", argv0, bp->ndata);
-	n = write(e->epout->dfd, bp->rp, bp->ndata);
-	if(n < 0){
-		deprint(2, "%s: etherbwrite: %r\n", argv0);	/* keep { and }  */
-	}else
-		deprint(2, "%s: etherbwrite wrote %ld bytes\n", argv0, n);
-	if(n <= 0)
-		return n;
-	if((bp->ndata % e->epout->maxpkt) == 0){
-		deprint(2, "%s: short pkt write\n", argv0);
-		write(e->epout->dfd, "", 1);
-	}
-	return n;
-}
-
-static long
-fswrite(Usbfs *fs, Fid *fid, void *data, long count, vlong)
-{
-	int cn, qt;
-	char buf[128];
-	Buf *bp;
-	Conn *c;
-	Ether *e;
-	Qid q;
-
-	q = fid->qid;
-	q.path &= ~fs->qid;
-	e = fs->aux;
-	qt = qtype(q.path);
-	cn = qnum(q.path);
-	switch(qt){
-	case Qndata:
-		c = getconn(e, cn, 0);
-		if(c == nil){
-			werrstr(Eio);
-			return -1;
-		}
-		bp = allocbuf(e);
-		if(count > sizeof(bp->data)-Hdrsize)
-			count = sizeof(bp->data)-Hdrsize;
-		memmove(bp->rp, data, count);
-		bp->ndata = count;
-		if(etherdebug > 1)
-			dumpframe("etherout", bp->rp, bp->ndata);
-		if(e->nblock == 0)
-			sendp(e->wc, bp);
-		else if(nbsendp(e->wc, bp) == 0){
-			deprint(2, "%s: (out) packet lost\n", argv0);
-			freebuf(e, bp);
-		}
-		break;
-	case Qnctl:
-		c = getconn(e, cn, 0);
-		if(c == nil){
-			werrstr(Eio);
-			return -1;
-		}
-		if(count > sizeof(buf) - 1)
-			count = sizeof(buf) - 1;
-		memmove(buf, data, count);
-		buf[count] = 0;
-		if(etherctl(e, c, buf) < 0)
-			return -1;
-		break;
-	default:
-		sysfatal("usb: ether: fsread bug");
-	}
-	return count;
-}
-
-static int
-openeps(Ether *e, int epin, int epout)
-{
-	e->epin = openep(e->dev, epin);
-	if(e->epin == nil){
-		fprint(2, "ether: in: openep %d: %r\n", epin);
-		return -1;
-	}
-	if(epout == epin){
-		incref(e->epin);
-		e->epout = e->epin;
-	}else
-		e->epout = openep(e->dev, epout);
-	if(e->epout == nil){
-		fprint(2, "ether: out: openep %d: %r\n", epout);
-		closedev(e->epin);
-		return -1;
-	}
-	if(e->epin == e->epout)
-		opendevdata(e->epin, ORDWR);
-	else{
-		opendevdata(e->epin, OREAD);
-		opendevdata(e->epout, OWRITE);
-	}
-	if(e->epin->dfd < 0 || e->epout->dfd < 0){
-		fprint(2, "ether: open i/o ep data: %r\n");
-		closedev(e->epin);
-		closedev(e->epout);
-		return -1;
-	}
-	dprint(2, "ether: ep in %s maxpkt %d; ep out %s maxpkt %d\n",
-		e->epin->dir, e->epin->maxpkt, e->epout->dir, e->epout->maxpkt);
-
-	/* time outs are not activated for I/O endpoints */
-
-	if(usbdebug > 2 || etherdebug > 2){
-		devctl(e->epin, "debug 1");
-		devctl(e->epout, "debug 1");
-		devctl(e->dev, "debug 1");
-	}
-
-	return 0;
-}
-
-static int
-usage(void)
-{
-	werrstr("usage: usb/ether [-d] [-N nb]");
-	return -1;
-}
-
-static Usbfs etherfs = {
-	.walk = fswalk,
-	.open =	 fsopen,
-	.read =	 fsread,
-	.write = fswrite,
-	.stat =	 fsstat,
-	.clunk = fsclunk,
-};
-
-static void
-shutdownchan(Channel *c)
-{
-	Buf *bp;
-
-	while((bp=nbrecvp(c)) != nil)
-		free(bp);
-	chanfree(c);
-}
-
-static void
-etherfree(Ether *e)
-{
-	int i;
-	Buf *bp;
-
-	if(e->free != nil)
-		e->free(e);
-	closedev(e->epin);
-	closedev(e->epout);
-	if(e->rc == nil){	/* not really started */
-		free(e);
-		return;
-	}
-	for(i = 0; i < e->nconns; i++)
-		if(e->conns[i] != nil){
-			while((bp = nbrecvp(e->conns[i]->rc)) != nil)
-				free(bp);
-			chanfree(e->conns[i]->rc);
-			free(e->conns[i]);
-		}
-	shutdownchan(e->bc);
-	shutdownchan(e->rc);
-	shutdownchan(e->wc);
-	e->epin = e->epout = nil;
-	devctl(e->dev, "detach");
-	free(e);
-}
-
-static void
-etherdevfree(void *a)
-{
-	Ether *e = a;
-
-	if(e != nil)
-		etherfree(e);
-}
-
-/* must return 1 if c wants bp; 0 if not */
-static int
-cwantsbp(Conn *c, Buf *bp)
-{
-	if(c->ref != 0 && (c->prom != 0 || c->type < 0 || c->type == bp->type))
-		return 1;
-	return 0;
-}
-
-static void
-etherwriteproc(void *a)
-{
-	Ether *e = a;
-	Buf *bp;
-	Channel *wc;
-
-	wc = e->wc;
-	while(e->exiting == 0){
-		bp = recvp(wc);
-		if(bp == nil || e->exiting != 0){
-			free(bp);
-			break;
-		}
-		e->nout++;
-		if(e->bwrite(e, bp) < 0)
-			e->noerrs++;
-		if(isloopback(e, bp) && e->exiting == 0)
-			sendp(e->rc, bp); /* send to input queue */
-		else
-			freebuf(e, bp);
-	}
-	deprint(2, "%s: writeproc exiting\n", argv0);
-	closedev(e->dev);
-}
-
-static void
-setbuftype(Buf *bp)
-{
-	uchar *p;
-
-	bp->type = 0;
-	if(bp->ndata >= Ehdrsize){
-		p = bp->rp + Eaddrlen*2;
-		bp->type = p[0]<<8 | p[1];
-	}
-}
-
-static void
-etherexiting(Ether *e)
-{
-	devctl(e->dev, "detach");
-	e->exiting = 1;
-	close(e->epin->dfd);
-	e->epin->dfd = -1;
-	close(e->epout->dfd);
-	e->epout->dfd = -1;
-	nbsend(e->wc, nil);
-}
-
-static void
-etherreadproc(void *a)
-{
-	int i, n, nwants;
-	Buf *bp, *dbp;
-	Ether *e = a;
-
-	while(e->exiting == 0){
-		bp = nbrecvp(e->rc);
-		if(bp == nil){
-			bp = allocbuf(e);	/* leak() may think we leak */
-			if(e->bread(e, bp) < 0){
-				freebuf(e, bp);
-				break;
-			}
-			if(bp->ndata == 0){
-				/* may be a short packet; continue */
-				if(0)dprint(2, "%s: read: short\n", argv0);
-				freebuf(e, bp);
-				continue;
-			}else
-				setbuftype(bp);
-		}
-		e->nin++;
-		nwants = 0;
-		for(i = 0; i < e->nconns; i++)
-			nwants += cwantsbp(e->conns[i], bp);
-		for(i = 0; nwants > 0 && i < e->nconns; i++)
-			if(cwantsbp(e->conns[i], bp)){
-				n = bp->ndata;
-				if(e->conns[i]->type == -2 && n > 64)
-					n = 64;
-				if(nwants-- == 1){
-					bp->ndata = n;
-					dbp = bp;
-					bp = nil;
-				}else{
-					dbp = allocbuf(e);
-					memmove(dbp->rp, bp->rp, n);
-					dbp->ndata = n;
-					dbp->type = bp->type;
-				}
-				if(nbsendp(e->conns[i]->rc, dbp) == 0){
-					e->nierrs++;
-					freebuf(e, dbp);
-				}
-			}
-		freebuf(e, bp);
-	}
-	deprint(2, "%s: writeproc exiting\n", argv0);
-	etherexiting(e);
-	closedev(e->dev);
-	usbfsdel(&e->fs);
-}
-
-static void
-setalt(Dev *d, int ifcid, int altid)
-{
-	if(usbcmd(d, Rh2d|Rstd|Riface, Rsetiface, altid, ifcid, nil, 0) < 0)
-		dprint(2, "%s: setalt ifc %d alt %d: %r\n", argv0, ifcid, altid);
-}
-
-static int
-ifaceinit(Ether *e, Iface *ifc, int *ei, int *eo)
-{
-	Ep *ep;
-	int epin, epout, i;
-
-	if(ifc == nil)
-		return -1;
-
-	epin = epout = -1;
-	for(i = 0; (epin < 0 || epout < 0) && i < nelem(ifc->ep); i++)
-		if((ep = ifc->ep[i]) != nil && ep->type == Ebulk){
-			if(ep->dir == Eboth || ep->dir == Ein)
-				if(epin == -1)
-					epin =  ep->id;
-			if(ep->dir == Eboth || ep->dir == Eout)
-				if(epout == -1)
-					epout = ep->id;
-		}
-	if(epin == -1 || epout == -1)
-		return -1;
-
-	dprint(2, "ether: ep ids: in %d out %d\n", epin, epout);
-	for(i = 0; i < nelem(ifc->altc); i++)
-		if(ifc->altc[i] != nil)
-			setalt(e->dev, ifc->id, i);
-
-	*ei = epin;
-	*eo = epout;
-	return 0;
-}
-
-static int
-etherinit(Ether *e, int *ei, int *eo)
-{
-	int ctlid, datid, i, j;
-	Conf *c;
-	Desc *desc;
-	Iface *ctlif, *datif;
-	Usbdev *ud;
-
-	*ei = *eo = -1;
-	ud = e->dev->usb;
-
-	/* look for union descriptor with ethernet ctrl interface */
-	for(i = 0; i < nelem(ud->ddesc); i++){
-		if((desc = ud->ddesc[i]) == nil)
-			continue;
-		if(desc->data.bLength < 5 || desc->data.bbytes[0] != Cdcunion)
-			continue;
-
-		ctlid = desc->data.bbytes[1];
-		datid = desc->data.bbytes[2];
-
-		if((c = desc->conf) == nil)
-			continue;
-
-		ctlif = datif = nil;
-		for(j = 0; j < nelem(c->iface); j++){
-			if(c->iface[j] == nil)
-				continue;
-			if(c->iface[j]->id == ctlid)
-				ctlif = c->iface[j];
-			if(c->iface[j]->id == datid)
-				datif = c->iface[j];
-
-			if(datif != nil && ctlif != nil){
-				if(Subclass(ctlif->csp) == Scether &&
-				    ifaceinit(e, datif, ei, eo) != -1)
-					return 0;
-				break;
-			}
-		}
-	}
-	/* try any other one that seems to be ok */
-	for(i = 0; i < nelem(ud->conf); i++)
-		if((c = ud->conf[i]) != nil)
-			for(j = 0; j < nelem(c->iface); j++)
-				if(ifaceinit(e, c->iface[j], ei, eo) != -1)
-					return 0;
-	dprint(2, "%s: no valid endpoints", argv0);
-	return -1;
-}
-
-int
-ethermain(Dev *dev, int argc, char **argv)
-{
-	int epin, epout, i, devid;
-	Ether *e;
-
-	devid = dev->id;
-	ARGBEGIN{
-	case 'd':
-		if(etherdebug == 0)
-			fprint(2, "ether debug on\n");
-		etherdebug++;
-		break;
-	case 'N':
-		devid = atoi(EARGF(usage()));
-		break;
-	default:
-		return usage();
-	}ARGEND
-	if(argc != 0) {
-		return usage();
-	}
-	e = dev->aux = emallocz(sizeof(Ether), 1);
-	e->dev = dev;
-	dev->free = etherdevfree;
-
-	for(i = 0; i < nelem(ethers); i++)
-		if(ethers[i](e) == 0)
-			break;
-	if(i == nelem(ethers))
-		return -1;
-	if(e->init == nil)
-		e->init = etherinit;
-	if(e->init(e, &epin, &epout) < 0)
-		return -1;
-	if(e->bwrite == nil)
-		e->bwrite = etherbwrite;
-	if(e->bread == nil)
-		e->bread = etherbread;
-
-	if(openeps(e, epin, epout) < 0)
-		return -1;
-	e->fs = etherfs;
-	snprint(e->fs.name, sizeof(e->fs.name), "etherU%d", devid);
-	e->fs.dev = dev;
-	e->fs.aux = e;
-	e->bc = chancreate(sizeof(Buf*), Nconns);
-	e->rc = chancreate(sizeof(Buf*), Nconns/2);
-	e->wc = chancreate(sizeof(Buf*), Nconns*2);
-	incref(e->dev);
-	proccreate(etherwriteproc, e, 16*1024);
-	incref(e->dev);
-	proccreate(etherreadproc, e, 16*1024);
-	deprint(2, "%s: dev ref %ld\n", argv0, dev->ref);
-	incref(e->dev);
-	usbfsadd(&e->fs);
-	return 0;
-}
--- a/sys/src/cmd/usb/ether/ether.h
+++ /dev/null
@@ -1,120 +1,0 @@
-typedef struct Ether Ether;
-typedef struct Etherops Etherops;
-typedef struct Conn Conn;
-typedef struct Cinfo Cinfo;
-typedef struct Buf Buf;
-typedef struct Etherpkt Etherpkt;
-
-enum
-{
-	/* controller ids */
-	Cdc = 0,
-	A8817x,		/* Asis */
-	A88178,
-	A88179,
-	A88772,
-
-	Eaddrlen = 6,
-	Epktlen = 1514,
-	Ehdrsize = 2*Eaddrlen + 2,
-
-	Maxpkt	= 2000,	/* no jumbo packets here */
-	Nconns	= 8,	/* max number of connections */
-	Nbufs	= 8,	/* max number of buffers */
-	Scether = 6,	/* ethernet cdc subclass */
-	Fnheader = 0,	/* Functions */
-	Fnunion = 6,
-	Fnether = 15,
-
-	Cdcunion	= 6,	/* CDC Union descriptor subtype */
-};
-
-struct Buf
-{
-	int	type;
-	int	ndata;
-	uchar*	rp;
-	uchar	data[Hdrsize+Maxpkt];
-};
-
-struct Conn
-{
-	Ref;			/* one per file in use */
-	int	nb;
-	int	type;
-	int	headersonly;
-	int	prom;
-	Channel*rc;		/* [2] of Buf* */
-};
-
-struct Etherops
-{
-	int	(*init)(Ether*, int *epin, int *epout);
-	long	(*bread)(Ether*, Buf*);
-	long	(*bwrite)(Ether*, Buf*);
-	int	(*ctl)(Ether*, char*);
-	int	(*promiscuous)(Ether*, int);
-	int	(*multicast)(Ether*, uchar*, int);
-	char*	(*seprintstats)(char*, char*, Ether*);
-	void	(*free)(Ether*);
-	void*	aux;
-};
-
-struct Ether
-{
-	QLock;
-	QLock	wlck;			/* write one at a time */
-	int	epinid;			/* epin address */
-	int	epoutid;			/* epout address */
-	Dev*	dev;
-	Dev*	epin;
-	Dev*	epout;
-	int	cid;			/* ctlr id */
-	int	phy;			/* phy id */
-	Ref	prom;			/* nb. of promiscuous conns */
-	int	exiting;			/* shutting down */
-	int	wrexited;			/* write process died */
-	uchar	addr[Eaddrlen];		/* mac */
-	int	nconns;			/* nb. of entries used in... */
-	Conn*	conns[Nconns];		/* connections */
-	int	nabufs;			/* nb. of allocated buffers */
-	int	nbufs;			/* nb. of buffers in use */
-	int	nblock;			/* nonblocking (output)? */
-	long	nin;
-	long	nout;
-	long	nierrs;
-	long	noerrs;
-	int	mbps;
-	int	nmcasts;
-	Channel*rc;			/* read channel (of Buf*) */
-	Channel*wc;			/* write channel (of Buf*) */
-	Channel*bc;			/* free buf. chan. (of Buf*) */
-	Etherops;
-	Usbfs	fs;
-};
-
-struct Cinfo
-{
-	int vid;		/* usb vendor id */
-	int did;		/* usb device/product id */
-	int cid;		/* controller id assigned by us */
-};
-
-struct Etherpkt
-{
-	uchar d[Eaddrlen];
-	uchar s[Eaddrlen];
-	uchar type[2];
-	uchar data[1500];
-};
-
-int	ethermain(Dev *dev, int argc, char **argv);
-int	asixreset(Ether*);
-int	cdcreset(Ether*);
-int	parseaddr(uchar *m, char *s);
-void	dumpframe(char *tag, void *p, int n);
-
-extern Cinfo cinfo[];
-extern int etherdebug;
-
-#define	deprint	if(etherdebug)fprint
--- a/sys/src/cmd/usb/ether/main.c
+++ /dev/null
@@ -1,90 +1,0 @@
-/*
- * usb/ether - usb ethernet adapter.
- * BUG: This should use /dev/etherfile to
- * use the kernel ether device code.
- */
-#include <u.h>
-#include <libc.h>
-#include <fcall.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "ether.h"
-
-enum
-{
-	Arglen = 80,
-};
-
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-Dd] [-N nb] [-m mnt] [-s srv] [dev...]\n", argv0);
-	threadexitsall("usage");
-}
-
-/*
- * Ether devices may be weird.
- * Be optimistic and try to use any communication
- * device or one of the `vendor specific class' devices
- * that we know are ethernets.
- */
-static int
-matchether(char *info, void*)
-{
-	Cinfo *ip;
-	char buf[50];
-
-	/*
-	 * I have an ether reporting comms.0.0
-	 */
-	if(strstr(info, "comms") != nil)
-		return 0;
-	for(ip = cinfo; ip->vid != 0; ip++){
-		snprint(buf, sizeof(buf), "vid %#06x did %#06x", ip->vid, ip->did);
-		if(strstr(info, buf) != nil)
-			return 0;
-	}
-	return -1;
-}
-
-void
-threadmain(int argc, char **argv)
-{
-	char args[Arglen];
-	char *as, *ae, *srv, *mnt;
-
-	srv = nil;
-	mnt = "/net";
-
-	quotefmtinstall();
-	ae = args+sizeof(args);
-	as = seprint(args, ae, "ether");
-	ARGBEGIN{
-	case 'D':
-		usbfsdebug++;
-		break;
-	case 'd':
-		usbdebug++;
-		as = seprint(as, ae, " -d");
-		break;
-	case 'N':
-		as = seprint(as, ae, " -N %s", EARGF(usage()));
-		break;
-	case 'm':
-		mnt = EARGF(usage());
-		break;
-	case 's':
-		srv = EARGF(usage());
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	rfork(RFNOTEG);
-	threadsetgrp(threadid());
-	fmtinstall('U', Ufmt);
-	usbfsinit(srv, mnt, &usbdirfs, MAFTER|MCREATE);
-	startdevs(args, argv, argc, matchether, nil, ethermain);
-	threadexits(nil);
-}
--- a/sys/src/cmd/usb/ether/mkfile
+++ /dev/null
@@ -1,35 +1,0 @@
-</$objtype/mkfile
-
-TARG=ether
-OFILES=\
-	main.$O\
-
-LIBDOFILES=\
-	ether.$O\
-	asix.$O\
-	cdc.$O\
-
-HFILES=\
-	ether.h\
-	../lib/usb.h\
-	../lib/usbfs.h\
-
-LIBD=../lib/usbdev.a$O
-LIBU=../lib/usb.a$O
-LIB=\
-	$LIBD\
-	$LIBU\
-
-BIN=/$objtype/bin/usb
-
-</sys/src/cmd/mkone
-CFLAGS=-I../lib $CFLAGS
-
-$LIBU:
-	cd ../lib
-	mk install
-	mk clean
-
-$LIBD:V: $LIBDOFILES
-	ar vu $LIBD $newprereq
-	rm $newprereq
--- a/sys/src/cmd/usb/kb/hid.h
+++ /dev/null
@@ -1,65 +1,0 @@
-/*
- * USB keyboard/mouse constants
- */
-enum {
-
-	Stack = 32 * 1024,
-
-	/* HID class subclass protocol ids */
-	PtrCSP		= 0x020103,	/* mouse.boot.hid */
-	KbdCSP		= 0x010103,	/* keyboard.boot.hid */
-
-	/* Requests */
-	Getreport = 0x01,
-	Setreport = 0x09,
-	Getproto	= 0x03,
-	Setproto	= 0x0b,
-
-	/* protocols for SET_PROTO request */
-	Bootproto	= 0,
-	Reportproto	= 1,
-
-	/* protocols for SET_REPORT request */
-	Reportout = 0x0200,
-};
-
-enum {
-	/* keyboard modifier bits */
-	Mlctrl		= 0,
-	Mlshift		= 1,
-	Mlalt		= 2,
-	Mlgui		= 3,
-	Mrctrl		= 4,
-	Mrshift		= 5,
-	Mralt		= 6,
-	Mrgui		= 7,
-
-	/* masks for byte[0] */
-	Mctrl		= 1<<Mlctrl | 1<<Mrctrl,
-	Mshift		= 1<<Mlshift | 1<<Mrshift,
-	Malt		= 1<<Mlalt | 1<<Mralt,
-	Mcompose	= 1<<Mlalt,
-	Maltgr		= 1<<Mralt,
-	Mgui		= 1<<Mlgui | 1<<Mrgui,
-
-	MaxAcc = 3,			/* max. ptr acceleration */
-	PtrMask= 0xf,			/* 4 buttons: should allow for more. */
-
-};
-
-/*
- * Plan 9 keyboard driver constants.
- */
-enum {
-	/* Scan codes (see kbd.c) */
-	SCesc1		= 0xe0,		/* first of a 2-character sequence */
-	SCesc2		= 0xe1,
-	SClshift		= 0x2a,
-	SCrshift		= 0x36,
-	SCctrl		= 0x1d,
-	SCcompose	= 0x38,
-	Keyup		= 0x80,		/* flag bit */
-	Keymask		= 0x7f,		/* regular scan code bits */
-};
-
-int kbmain(Dev *d, int argc, char*argv[]);
--- a/sys/src/cmd/usb/kb/kb.c
+++ /dev/null
@@ -1,610 +1,0 @@
-/*
- * USB Human Interaction Device: keyboard and mouse.
- *
- * If there's no usb keyboard, it tries to setup the mouse, if any.
- * It should be started at boot time.
- *
- * Mouse events are converted to the format of mouse(3)'s
- * mousein file.
- * Keyboard keycodes are translated to scan codes and sent to kbin(3).
- *
- */
-
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "hid.h"
-
-enum
-{
-	Awakemsg=0xdeaddead,
-	Diemsg = 0xbeefbeef,
-};
-
-typedef struct KDev KDev;
-typedef struct Kin Kin;
-
-struct KDev
-{
-	Dev*	dev;		/* usb device*/
-	Dev*	ep;		/* endpoint to get events */
-	Kin*	in;		/* used to send events to kernel */
-	Channel*repeatc;	/* only for keyboard */
-	int	accel;		/* only for mouse */
-};
-
-/*
- * Kbdin and mousein files must be shared among all instances.
- */
-struct Kin
-{
-	int	ref;
-	int	fd;
-	char*	name;
-};
-
-/*
- * Map for the logitech bluetooth mouse with 8 buttons and wheels.
- *	{ ptr ->mouse}
- *	{ 0x01, 0x01 },	// left
- *	{ 0x04, 0x02 },	// middle
- *	{ 0x02, 0x04 },	// right
- *	{ 0x40, 0x08 },	// up
- *	{ 0x80, 0x10 },	// down
- *	{ 0x10, 0x08 },	// side up
- *	{ 0x08, 0x10 },	// side down
- *	{ 0x20, 0x02 }, // page
- * besides wheel and regular up/down report the 4th byte as 1/-1
- */
-
-/*
- * key code to scan code; for the page table used by
- * the logitech bluetooth keyboard.
- */
-static char sctab[256] = 
-{
-[0x00]	0x0,	0x0,	0x0,	0x0,	0x1e,	0x30,	0x2e,	0x20,
-[0x08]	0x12,	0x21,	0x22,	0x23,	0x17,	0x24,	0x25,	0x26,
-[0x10]	0x32,	0x31,	0x18,	0x19,	0x10,	0x13,	0x1f,	0x14,
-[0x18]	0x16,	0x2f,	0x11,	0x2d,	0x15,	0x2c,	0x2,	0x3,
-[0x20]	0x4,	0x5,	0x6,	0x7,	0x8,	0x9,	0xa,	0xb,
-[0x28]	0x1c,	0x1,	0xe,	0xf,	0x39,	0xc,	0xd,	0x1a,
-[0x30]	0x1b,	0x2b,	0x2b,	0x27,	0x28,	0x29,	0x33,	0x34,
-[0x38]	0x35,	0x3a,	0x3b,	0x3c,	0x3d,	0x3e,	0x3f,	0x40,
-[0x40]	0x41,	0x42,	0x43,	0x44,	0x57,	0x58,	0x63,	0x46,
-[0x48]	0x77,	0x52,	0x47,	0x49,	0x53,	0x4f,	0x51,	0x4d,
-[0x50]	0x4b,	0x50,	0x48,	0x45,	0x35,	0x37,	0x4a,	0x4e,
-[0x58]	0x1c,	0x4f,	0x50,	0x51,	0x4b,	0x4c,	0x4d,	0x47,
-[0x60]	0x48,	0x49,	0x52,	0x53,	0x56,	0x7f,	0x74,	0x75,
-[0x68]	0x55,	0x59,	0x5a,	0x5b,	0x5c,	0x5d,	0x5e,	0x5f,
-[0x70]	0x78,	0x79,	0x7a,	0x7b,	0x0,	0x0,	0x0,	0x0,
-[0x78]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x71,
-[0x80]	0x73,	0x72,	0x0,	0x0,	0x0,	0x7c,	0x0,	0x0,
-[0x88]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0x90]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0x98]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xa0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xa8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xb0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xb8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xc0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xc8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xd0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xd8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xe0]	0x1d,	0x2a,	0x38,	0x7d,	0x61,	0x36,	0x64,	0x7e,
-[0xe8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x73,	0x72,	0x71,
-[0xf0]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-[0xf8]	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,	0x0,
-};
-
-static QLock inlck;
-static Kin kbdin =
-{
-	.ref = 0,
-	.name = "/dev/kbin",
-	.fd = -1,
-};
-static Kin ptrin =
-{
-	.ref = 0,
-	.name = "#m/mousein",
-	.fd = -1,
-};
-
-static int kbdebug;
-
-static int
-setbootproto(KDev* f, int eid)
-{
-	int r, id;
-
-	r = Rh2d|Rclass|Riface;
-	id = f->dev->usb->ep[eid]->iface->id;
-	return usbcmd(f->dev, r, Setproto, Bootproto, id, nil, 0);
-}
-
-static int
-setleds(KDev* f, int eid, uchar leds)
-{
-	return usbcmd(f->dev, Rh2d|Rclass|Riface, Setreport, Reportout, 0, &leds, 1);
-}
-
-/*
- * Try to recover from a babble error. A port reset is the only way out.
- * BUG: we should be careful not to reset a bundle with several devices.
- */
-static void
-recoverkb(KDev *f)
-{
-	int i;
-
-	close(f->dev->dfd);		/* it's for usbd now */
-	devctl(f->dev, "reset");
-	for(i = 0; i < 10; i++){
-		sleep(500);
-		if(opendevdata(f->dev, ORDWR) >= 0){
-			setbootproto(f, f->ep->id);
-			break;
-		}
-		/* else usbd still working... */
-	}
-}
-
-static void
-kbfatal(KDev *kd, char *sts)
-{
-	Dev *dev;
-
-	if(sts != nil)
-		fprint(2, "kb: fatal: %s\n", sts);
-	else
-		fprint(2, "kb: exiting\n");
-	if(kd->repeatc != nil)
-		nbsendul(kd->repeatc, Diemsg);
-	dev = kd->dev;
-	kd->dev = nil;
-	if(kd->ep != nil)
-		closedev(kd->ep);
-	kd->ep = nil;
-	devctl(dev, "detach");
-	closedev(dev);
-	/*
-	 * free(kd); done by closedev.
-	 */
-	threadexits(sts);
-}
-
-static int
-scale(KDev *f, int x)
-{
-	int sign = 1;
-
-	if(x < 0){
-		sign = -1;
-		x = -x;
-	}
-	switch(x){
-	case 0:
-	case 1:
-	case 2:
-	case 3:
-		break;
-	case 4:
-		x = 6 + (f->accel>>2);
-		break;
-	case 5:
-		x = 9 + (f->accel>>1);
-		break;
-	default:
-		x *= MaxAcc;
-		break;
-	}
-	return sign*x;
-}
-
-/*
- * ps2 mouse is processed mostly at interrupt time.
- * for usb we do what we can.
- */
-static void
-sethipri(void)
-{
-	char fn[30];
-	int fd;
-
-	snprint(fn, sizeof(fn), "/proc/%d/ctl", getpid());
-	fd = open(fn, OWRITE);
-	if(fd < 0)
-		return;
-	fprint(fd, "pri 13");
-	close(fd);
-}
-
-static void
-ptrwork(void* a)
-{
-	static char maptab[] = {0x0, 0x1, 0x4, 0x5, 0x2, 0x3, 0x6, 0x7};
-	int x, y, b, c, ptrfd;
-	int	mfd, nerrs;
-	char	buf[32];
-	char	mbuf[80];
-	KDev*	f = a;
-	int	hipri;
-
-	hipri = nerrs = 0;
-	ptrfd = f->ep->dfd;
-	mfd = f->in->fd;
-
-	if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf)
-		kbfatal(f, "weird mouse maxpkt");
-	for(;;){
-		memset(buf, 0, sizeof buf);
-		if(f->ep == nil)
-			kbfatal(f, nil);
-		c = read(ptrfd, buf, f->ep->maxpkt);
-		assert(f->dev != nil);
-		assert(f->ep != nil);
-		if(c < 0){
-			dprint(2, "kb: mouse: %s: read: %r\n", f->ep->dir);
-			if(++nerrs < 3){
-				recoverkb(f);
-				continue;
-			}
-		}
-		if(c <= 0)
-			kbfatal(f, nil);
-		if(c < 3)
-			continue;
-		if(f->accel){
-			x = scale(f, buf[1]);
-			y = scale(f, buf[2]);
-		}else{
-			x = buf[1];
-			y = buf[2];
-		}
-		b = maptab[buf[0] & 0x7];
-		if(c > 3 && buf[3] == 1)	/* up */
-			b |= 0x08;
-		if(c > 3 && buf[3] == -1)	/* down */
-			b |= 0x10;
-		if(kbdebug > 1)
-			fprint(2, "kb: m%11d %11d %11d\n", x, y, b);
-		seprint(mbuf, mbuf+sizeof(mbuf), "m%11d %11d %11d", x, y,b);
-		if(write(mfd, mbuf, strlen(mbuf)) < 0)
-			kbfatal(f, "mousein i/o");
-		if(hipri == 0){
-			sethipri();
-			hipri = 1;
-		}
-	}
-}
-
-static void
-stoprepeat(KDev *f)
-{
-	sendul(f->repeatc, Awakemsg);
-}
-
-static void
-startrepeat(KDev *f, uchar esc1, uchar sc)
-{
-	ulong c;
-
-	if(esc1)
-		c = SCesc1 << 8 | (sc & 0xff);
-	else
-		c = sc;
-	sendul(f->repeatc, c);
-}
-
-static void
-putscan(int kbinfd, uchar esc, uchar sc)
-{
-	uchar s[2] = {SCesc1, 0};
-
-	if(sc == 0x41){
-		kbdebug += 2;
-		return;
-	}
-	if(sc == 0x42){
-		kbdebug = 0;
-		return;
-	}
-	if(kbdebug)
-		fprint(2, "sc: %x %x\n", (esc? SCesc1: 0), sc);
-	s[1] = sc;
-	if(esc && sc != 0)
-		write(kbinfd, s, 2);
-	else if(sc != 0)
-		write(kbinfd, s+1, 1);
-}
-
-static void
-repeatproc(void* a)
-{
-	KDev *f;
-	Channel *repeatc;
-	int kbdinfd;
-	ulong l, t, i;
-	uchar esc1, sc;
-
-	/*
-	 * too many jumps here.
-	 * Rewrite instead of debug, if needed.
-	 */
-	f = a;
-	repeatc = f->repeatc;
-	kbdinfd = f->in->fd;
-	l = Awakemsg;
-Repeat:
-	if(l == Diemsg)
-		goto Abort;
-	while(l == Awakemsg)
-		l = recvul(repeatc);
-	if(l == Diemsg)
-		goto Abort;
-	esc1 = l >> 8;
-	sc = l;
-	t = 160;
-	for(;;){
-		for(i = 0; i < t; i += 5){
-			if(l = nbrecvul(repeatc))
-				goto Repeat;
-			sleep(5);
-		}
-		putscan(kbdinfd, esc1, sc);
-		t = 30;
-	}
-Abort:
-	chanfree(repeatc);
-	threadexits("aborted");
-
-}
-
-
-#define hasesc1(sc)	(((sc) > 0x47) || ((sc) == 0x38))
-
-static void
-putmod(int fd, uchar mods, uchar omods, uchar mask, uchar esc, uchar sc)
-{
-	/* BUG: Should be a single write */
-	if((mods&mask) && !(omods&mask))
-		putscan(fd, esc, sc);
-	if(!(mods&mask) && (omods&mask))
-		putscan(fd, esc, Keyup|sc);
-}
-
-/*
- * This routine diffs the state with the last known state
- * and invents the scan codes that would have been sent
- * by a non-usb keyboard in that case. This also requires supplying
- * the extra esc1 byte as well as keyup flags.
- * The aim is to allow future addition of other keycode pages
- * for other keyboards.
- */
-static uchar
-putkeys(KDev *f, uchar buf[], uchar obuf[], int n, uchar dk)
-{
-	int i, j;
-	uchar uk;
-	int fd;
-
-	fd = f->in->fd;
-	putmod(fd, buf[0], obuf[0], Mctrl, 0, SCctrl);
-	putmod(fd, buf[0], obuf[0], (1<<Mlshift), 0, SClshift);
-	putmod(fd, buf[0], obuf[0], (1<<Mrshift), 0, SCrshift);
-	putmod(fd, buf[0], obuf[0], Mcompose, 0, SCcompose);
-	putmod(fd, buf[0], obuf[0], Maltgr, 1, SCcompose);
-
-	/* Report key downs */
-	for(i = 2; i < n; i++){
-		for(j = 2; j < n; j++)
-			if(buf[i] == obuf[j])
-			 	break;
-		if(j == n && buf[i] != 0){
-			dk = sctab[buf[i]];
-			putscan(fd, hasesc1(dk), dk);
-			startrepeat(f, hasesc1(dk), dk);
-		}
-	}
-
-	/* Report key ups */
-	uk = 0;
-	for(i = 2; i < n; i++){
-		for(j = 2; j < n; j++)
-			if(obuf[i] == buf[j])
-				break;
-		if(j == n && obuf[i] != 0){
-			uk = sctab[obuf[i]];
-			putscan(fd, hasesc1(uk), uk|Keyup);
-		}
-	}
-	if(uk && (dk == 0 || dk == uk)){
-		stoprepeat(f);
-		dk = 0;
-	}
-	return dk;
-}
-
-static int
-kbdbusy(uchar* buf, int n)
-{
-	int i;
-
-	for(i = 1; i < n; i++)
-		if(buf[i] == 0 || buf[i] != buf[0])
-			return 0;
-	return 1;
-}
-
-static void
-kbdwork(void *a)
-{
-	int c, i, kbdfd, nerrs;
-	uchar dk, buf[64], lbuf[64];
-	char err[128];
-	KDev *f = a;
-
-	kbdfd = f->ep->dfd;
-
-	if(f->ep->maxpkt < 3 || f->ep->maxpkt > sizeof buf)
-		kbfatal(f, "weird maxpkt");
-
-	f->repeatc = chancreate(sizeof(ulong), 0);
-	if(f->repeatc == nil)
-		kbfatal(f, "chancreate failed");
-
-	proccreate(repeatproc, f, Stack);
-	memset(lbuf, 0, sizeof lbuf);
-	dk = nerrs = 0;
-	for(;;){
-		memset(buf, 0, sizeof buf);
-		c = read(kbdfd, buf, f->ep->maxpkt);
-		assert(f->dev != nil);
-		assert(f->ep != nil);
-		if(c < 0){
-			rerrstr(err, sizeof(err));
-			fprint(2, "kb: %s: read: %s\n", f->ep->dir, err);
-			if(strstr(err, "babble") != 0 && ++nerrs < 3){
-				recoverkb(f);
-				continue;
-			}
-		}
-		if(c <= 0)
-			kbfatal(f, nil);
-		if(c < 3)
-			continue;
-		if(kbdbusy(buf + 2, c - 2))
-			continue;
-		if(usbdebug > 2 || kbdebug > 1){
-			fprint(2, "kbd mod %x: ", buf[0]);
-			for(i = 2; i < c; i++)
-				fprint(2, "kc %x ", buf[i]);
-			fprint(2, "\n");
-		}
-		dk = putkeys(f, buf, lbuf, f->ep->maxpkt, dk);
-		memmove(lbuf, buf, c);
-		nerrs = 0;
-	}
-}
-
-static void
-freekdev(void *a)
-{
-	KDev *kd;
-
-	kd = a;
-	if(kd->in != nil){
-		qlock(&inlck);
-		if(--kd->in->ref == 0){
-			close(kd->in->fd);
-			kd->in->fd = -1;
-		}
-		qunlock(&inlck);
-	}
-	dprint(2, "freekdev\n");
-	free(kd);
-}
-
-static void
-kbstart(Dev *d, Ep *ep, Kin *in, void (*f)(void*), int accel)
-{
-	KDev *kd;
-
-	qlock(&inlck);
-	if(in->fd < 0){
-		in->fd = open(in->name, OWRITE);
-		if(in->fd < 0){
-			fprint(2, "kb: %s: %r\n", in->name);
-			qunlock(&inlck);
-			return;
-		}
-	}
-	in->ref++;	/* for kd->in = in */
-	qunlock(&inlck);
-	kd = d->aux = emallocz(sizeof(KDev), 1);
-	d->free = freekdev;
-	kd->in = in;
-	kd->dev = d;
-	if(setbootproto(kd, ep->id) < 0){
-		fprint(2, "kb: %s: bootproto: %r\n", d->dir);
-		return;
-	}
-	kd->accel = accel;
-	kd->ep = openep(d, ep->id);
-	if(kd->ep == nil){
-		fprint(2, "kb: %s: openep %d: %r\n", d->dir, ep->id);
-		return;
-	}
-	if(opendevdata(kd->ep, OREAD) < 0){
-		fprint(2, "kb: %s: opendevdata: %r\n", kd->ep->dir);
-		closedev(kd->ep);
-		kd->ep = nil;
-		return;
-	}
-	if(setleds(kd, ep->id, 0) < 0){
-		fprint(2, "kb: %s: setleds: %r\n", d->dir);
-		return;
-	}
-	incref(d);
-	proccreate(f, kd, Stack);
-}
-
-static int
-usage(void)
-{
-	werrstr("usage: usb/kb [-dkm] [-a n] [-N nb]");
-	return -1;
-}
-
-int
-kbmain(Dev *d, int argc, char* argv[])
-{
-	int i, kena, pena, accel, devid;
-	Usbdev *ud;
-	Ep *ep;
-
-	kena = pena = 1;
-	accel = 0;
-	devid = d->id;
-	ARGBEGIN{
-	case 'a':
-		accel = strtol(EARGF(usage()), nil, 0);
-		break;
-	case 'd':
-		kbdebug++;
-		break;
-	case 'k':
-		kena = 1;
-		pena = 0;
-		break;
-	case 'm':
-		kena = 0;
-		pena = 1;
-		break;
-	case 'N':
-		devid = atoi(EARGF(usage()));		/* ignore dev number */
-		break;
-	default:
-		return usage();
-	}ARGEND;
-	if(argc != 0){
-		return usage();
-	}
-	USED(devid);
-	ud = d->usb;
-	d->aux = nil;
-	dprint(2, "kb: main: dev %s ref %ld\n", d->dir, d->ref);
-	for(i = 0; i < nelem(ud->ep); i++){
-		if((ep = ud->ep[i]) == nil)
-			break;
-		if(kena && ep->type == Eintr && ep->dir == Ein)
-		if(ep->iface->csp == KbdCSP)
-			kbstart(d, ep, &kbdin, kbdwork, accel);
-		if(pena && ep->type == Eintr && ep->dir == Ein)
-		if(ep->iface->csp == PtrCSP)
-			kbstart(d, ep, &ptrin, ptrwork, accel);
-	}
-	return 0;
-}
--- a/sys/src/cmd/usb/kb/main.c
+++ /dev/null
@@ -1,67 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "hid.h"
-
-typedef struct Parg Parg;
-
-enum
-{
-	Ndevs = 10,
-	Arglen = 80,
-	Nargs = 10,
-};
-
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-dkm] [-a n] [-N nb] [dev...]\n", argv0);
-	threadexitsall("usage");
-}
-
-void
-threadmain(int argc, char **argv)
-{
-	char args[Arglen];
-	char *as, *ae;
-	int accel, pena, devid;
-	int csps[] = { KbdCSP, PtrCSP, 0 };
-
-	quotefmtinstall();
-	pena = 1;
-	ae = args+sizeof(args);
-	as = seprint(args, ae, "kb");
-	ARGBEGIN{
-	case 'a':
-		accel = strtol(EARGF(usage()), nil, 0);
-		as = seprint(as, ae, " -a %d", accel);
-		break;
-	case 'd':
-		usbdebug++;
-		as = seprint(as, ae, " -d");
-		break;
-	case 'k':
-		as = seprint(as, ae, " -k");
-		pena = 0;
-		break;
-	case 'm':
-		as = seprint(as, ae, " -m");
-		pena = 1;
-		break;
-	case 'N':
-		devid = atoi(EARGF(usage()));		/* ignore dev number */
-		USED(devid);
-		break;
-	default:
-		usage();
-	}ARGEND;
-
-	rfork(RFNOTEG);
-	fmtinstall('U', Ufmt);
-	threadsetgrp(threadid());
-	if(pena == 0)
-		csps[1] = 0;
-	startdevs(args, argv, argc, matchdevcsp, csps, kbmain);
-	threadexits(nil);
-}
--- a/sys/src/cmd/usb/kb/mkfile
+++ /dev/null
@@ -1,35 +1,0 @@
-</$objtype/mkfile
-
-TARG=kb
-OFILES=main.$O
-LIBDOFILES=kb.$O
-HFILES=\
-	../lib/usb.h\
-	hid.h\
-
-LIBD=../lib/usbdev.a$O
-LIBU=../lib/usb.a$O
-LIB=\
-	$LIBD\
-	$LIBU\
-
-BIN=/$objtype/bin/usb
-
-
-UPDATE=\
-	mkfile\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-
-</sys/src/cmd/mkone
-CFLAGS=-I../lib $CFLAGS
-
-$LIBU:
-	cd ../lib
-	mk install
-	mk clean
-
-$LIBD:V: $LIBDOFILES
-	ar vu $LIBD $newprereq
-	rm $newprereq
-
--- a/sys/src/cmd/usb/lib/dev.c
+++ /dev/null
@@ -1,493 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-
-/*
- * epN.M -> N
- */
-static int
-nameid(char *s)
-{
-	char *r;
-	char nm[20];
-
-	r = strrchr(s, 'p');
-	if(r == nil)
-		return -1;
-	strecpy(nm, nm+sizeof(nm), r+1);
-	r = strchr(nm, '.');
-	if(r == nil)
-		return -1;
-	*r = 0;
-	return atoi(nm);
-}
-
-Dev*
-openep(Dev *d, int id)
-{
-	char *mode;	/* How many modes? */
-	Ep *ep;
-	Altc *ac;
-	Dev *epd;
-	Usbdev *ud;
-	char name[40];
-
-	if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
-		return nil;
-	if(d->cfd < 0 || d->usb == nil){
-		werrstr("device not configured");
-		return nil;
-	}
-	ud = d->usb;
-	if(id < 0 || id >= nelem(ud->ep) || ud->ep[id] == nil){
-		werrstr("bad enpoint number");
-		return nil;
-	}
-	ep = ud->ep[id];
-	mode = "rw";
-	if(ep->dir == Ein)
-		mode = "r";
-	if(ep->dir == Eout)
-		mode = "w";
-	snprint(name, sizeof(name), "/dev/usb/ep%d.%d", d->id, id);
-	if(access(name, AEXIST) == 0){
-		dprint(2, "%s: %s already exists; trying to open\n", argv0, name);
-		epd = opendev(name);
-		if(epd != nil)
-			epd->maxpkt = ep->maxpkt;	/* guess */
-		return epd;
-	}
-	if(devctl(d, "new %d %d %s", id, ep->type, mode) < 0){
-		dprint(2, "%s: %s: new: %r\n", argv0, d->dir);
-		return nil;
-	}
-	epd = opendev(name);
-	if(epd == nil)
-		return nil;
-	epd->id = id;
-	if(devctl(epd, "maxpkt %d", ep->maxpkt) < 0)
-		fprint(2, "%s: %s: openep: maxpkt: %r\n", argv0, epd->dir);
-	else
-		dprint(2, "%s: %s: maxpkt %d\n", argv0, epd->dir, ep->maxpkt);
-	epd->maxpkt = ep->maxpkt;
-	ac = ep->iface->altc[0];
-	if(ep->ntds > 1 && devctl(epd, "ntds %d", ep->ntds) < 0)
-		fprint(2, "%s: %s: openep: ntds: %r\n", argv0, epd->dir);
-	else
-		dprint(2, "%s: %s: ntds %d\n", argv0, epd->dir, ep->ntds);
-
-	/*
-	 * For iso endpoints and high speed interrupt endpoints the pollival is
-	 * actually 2ⁿ and not n.
-	 * The kernel usb driver must take that into account.
-	 * It's simpler this way.
-	 */
-
-	if(ac != nil && (ep->type == Eintr || ep->type == Eiso) && ac->interval != 0)
-		if(devctl(epd, "pollival %d", ac->interval) < 0)
-			fprint(2, "%s: %s: openep: pollival: %r\n", argv0, epd->dir);
-	return epd;
-}
-
-Dev*
-opendev(char *fn)
-{
-	Dev *d;
-	int l;
-
-	if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
-		return nil;
-	d = emallocz(sizeof(Dev), 1);
-	incref(d);
-
-	l = strlen(fn);
-	d->dfd = -1;
-	/*
-	 * +30 to allocate extra size to concat "/<epfilename>"
-	 * we should probably remove that feature from the manual
-	 * and from the code after checking out that nobody relies on
-	 * that.
-	 */
-	d->dir = emallocz(l + 30, 0);
-	strcpy(d->dir, fn);
-	strcpy(d->dir+l, "/ctl");
-	d->cfd = open(d->dir, ORDWR|OCEXEC);
-	d->dir[l] = 0;
-	d->id = nameid(fn);
-	if(d->cfd < 0){
-		werrstr("can't open endpoint %s: %r", d->dir);
-		free(d->dir);
-		free(d);
-		return nil;
-	}
-	dprint(2, "%s: opendev %#p %s\n", argv0, d, fn);
-	return d;
-}
-
-int
-opendevdata(Dev *d, int mode)
-{
-	char buf[80]; /* more than enough for a usb path */
-
-	seprint(buf, buf+sizeof(buf), "%s/data", d->dir);
-	d->dfd = open(buf, mode|OCEXEC);
-	return d->dfd;
-}
-
-enum
-{
-	/*
-	 * Max device conf is also limited by max control request size as
-	 * limited by Maxctllen in the kernel usb.h (both limits are arbitrary).
-	 */
-	Maxdevconf = 4 * 1024,	/* asking for 16K kills Newsham's disk */
-};
-
-int
-loaddevconf(Dev *d, int n)
-{
-	uchar *buf;
-	int nr;
-	int type;
-
-	if(n >= nelem(d->usb->conf)){
-		werrstr("loaddevconf: bug: out of configurations in device");
-		fprint(2, "%s: %r\n", argv0);
-		return -1;
-	}
-	buf = emallocz(Maxdevconf, 0);
-	type = Rd2h|Rstd|Rdev;
-	nr = usbcmd(d, type, Rgetdesc, Dconf<<8|n, 0, buf, Maxdevconf);
-	if(nr < Dconflen){
-		free(buf);
-		return -1;
-	}
-	if(d->usb->conf[n] == nil)
-		d->usb->conf[n] = emallocz(sizeof(Conf), 1);
-	nr = parseconf(d->usb, d->usb->conf[n], buf, nr);
-	free(buf);
-	return nr;
-}
-
-Ep*
-mkep(Usbdev *d, int id)
-{
-	Ep *ep;
-
-	d->ep[id] = ep = emallocz(sizeof(Ep), 1);
-	ep->id = id;
-	return ep;
-}
-
-static char*
-mkstr(uchar *b, int n)
-{
-	Rune r;
-	char *us;
-	char *s;
-	char *e;
-
-	if(n <= 2 || (n & 1) != 0)
-		return strdup("none");
-	n = (n - 2)/2;
-	b += 2;
-	us = s = emallocz(n*UTFmax+1, 0);
-	e = s + n*UTFmax+1;
-	for(; --n >= 0; b += 2){
-		r = GET2(b);
-		s = seprint(s, e, "%C", r);
-	}
-	return us;
-}
-
-char*
-loaddevstr(Dev *d, int sid)
-{
-	uchar buf[128];
-	int type;
-	int nr;
-
-	if(sid == 0)
-		return estrdup("none");
-	type = Rd2h|Rstd|Rdev;
-	nr=usbcmd(d, type, Rgetdesc, Dstr<<8|sid, 0, buf, sizeof(buf));
-	return mkstr(buf, nr);
-}
-
-int
-loaddevdesc(Dev *d)
-{
-	uchar buf[Ddevlen+255];
-	int nr;
-	int type;
-	Ep *ep0;
-
-	type = Rd2h|Rstd|Rdev;
-	nr = sizeof(buf);
-	memset(buf, 0, Ddevlen);
-	if((nr=usbcmd(d, type, Rgetdesc, Ddev<<8|0, 0, buf, nr)) < 0)
-		return -1;
-	/*
-	 * Several hubs are returning descriptors of 17 bytes, not 18.
-	 * We accept them and leave number of configurations as zero.
-	 * (a get configuration descriptor also fails for them!)
-	 */
-	if(nr < Ddevlen){
-		print("%s: %s: warning: device with short descriptor\n",
-			argv0, d->dir);
-		if(nr < Ddevlen-1){
-			werrstr("short device descriptor (%d bytes)", nr);
-			return -1;
-		}
-	}
-	d->usb = emallocz(sizeof(Usbdev), 1);
-	ep0 = mkep(d->usb, 0);
-	ep0->dir = Eboth;
-	ep0->type = Econtrol;
-	ep0->maxpkt = d->maxpkt = 8;		/* a default */
-	nr = parsedev(d, buf, nr);
-	if(nr >= 0){
-		d->usb->vendor = loaddevstr(d, d->usb->vsid);
-		if(strcmp(d->usb->vendor, "none") != 0){
-			d->usb->product = loaddevstr(d, d->usb->psid);
-			d->usb->serial = loaddevstr(d, d->usb->ssid);
-		}
-	}
-	return nr;
-}
-
-int
-configdev(Dev *d)
-{
-	int i;
-
-	if(d->dfd < 0)
-		opendevdata(d, ORDWR);
-	if(loaddevdesc(d) < 0)
-		return -1;
-	for(i = 0; i < d->usb->nconf; i++)
-		if(loaddevconf(d, i) < 0)
-			return -1;
-	return 0;
-}
-
-static void
-closeconf(Conf *c)
-{
-	int i;
-	int a;
-
-	if(c == nil)
-		return;
-	for(i = 0; i < nelem(c->iface); i++)
-		if(c->iface[i] != nil){
-			for(a = 0; a < nelem(c->iface[i]->altc); a++)
-				free(c->iface[i]->altc[a]);
-			free(c->iface[i]);
-		}
-	free(c);
-}
-
-void
-closedev(Dev *d)
-{
-	int i;
-	Usbdev *ud;
-
-	if(d==nil || decref(d) != 0)
-		return;
-	dprint(2, "%s: closedev %#p %s\n", argv0, d, d->dir);
-	if(d->free != nil)
-		d->free(d->aux);
-	if(d->cfd >= 0)
-		close(d->cfd);
-	if(d->dfd >= 0)
-		close(d->dfd);
-	d->cfd = d->dfd = -1;
-	free(d->dir);
-	d->dir = nil;
-	ud = d->usb;
-	d->usb = nil;
-	if(ud != nil){
-		free(ud->vendor);
-		free(ud->product);
-		free(ud->serial);
-		for(i = 0; i < nelem(ud->ep); i++)
-			free(ud->ep[i]);
-		for(i = 0; i < nelem(ud->ddesc); i++)
-			free(ud->ddesc[i]);
-
-		for(i = 0; i < nelem(ud->conf); i++)
-			closeconf(ud->conf[i]);
-		free(ud);
-	}
-	free(d);
-}
-
-static char*
-reqstr(int type, int req)
-{
-	char *s;
-	static char* ds[] = { "dev", "if", "ep", "oth" };
-	static char buf[40];
-
-	if(type&Rd2h)
-		s = seprint(buf, buf+sizeof(buf), "d2h");
-	else
-		s = seprint(buf, buf+sizeof(buf), "h2d");
-	if(type&Rclass)
-		s = seprint(s, buf+sizeof(buf), "|cls");
-	else if(type&Rvendor)
-		s = seprint(s, buf+sizeof(buf), "|vnd");
-	else
-		s = seprint(s, buf+sizeof(buf), "|std");
-	s = seprint(s, buf+sizeof(buf), "|%s", ds[type&3]);
-
-	switch(req){
-	case Rgetstatus: s = seprint(s, buf+sizeof(buf), " getsts"); break;
-	case Rclearfeature: s = seprint(s, buf+sizeof(buf), " clrfeat"); break;
-	case Rsetfeature: s = seprint(s, buf+sizeof(buf), " setfeat"); break;
-	case Rsetaddress: s = seprint(s, buf+sizeof(buf), " setaddr"); break;
-	case Rgetdesc: s = seprint(s, buf+sizeof(buf), " getdesc"); break;
-	case Rsetdesc: s = seprint(s, buf+sizeof(buf), " setdesc"); break;
-	case Rgetconf: s = seprint(s, buf+sizeof(buf), " getcnf"); break;
-	case Rsetconf: s = seprint(s, buf+sizeof(buf), " setcnf"); break;
-	case Rgetiface: s = seprint(s, buf+sizeof(buf), " getif"); break;
-	case Rsetiface: s = seprint(s, buf+sizeof(buf), " setif"); break;
-	}
-	USED(s);
-	return buf;
-}
-
-static int
-cmdreq(Dev *d, int type, int req, int value, int index, uchar *data, int count)
-{
-	int ndata, n;
-	uchar *wp;
-	uchar buf[8];
-	char *hd, *rs;
-
-	assert(d != nil);
-	if(data == nil){
-		wp = buf;
-		ndata = 0;
-	}else{
-		ndata = count;
-		wp = emallocz(8+ndata, 0);
-	}
-	wp[0] = type;
-	wp[1] = req;
-	PUT2(wp+2, value);
-	PUT2(wp+4, index);
-	PUT2(wp+6, count);
-	if(data != nil)
-		memmove(wp+8, data, ndata);
-	if(usbdebug>2){
-		hd = hexstr(wp, ndata+8);
-		rs = reqstr(type, req);
-		fprint(2, "%s: %s val %d|%d idx %d cnt %d out[%d] %s\n",
-			d->dir, rs, value>>8, value&0xFF,
-			index, count, ndata+8, hd);
-		free(hd);
-	}
-	n = write(d->dfd, wp, 8+ndata);
-	if(wp != buf)
-		free(wp);
-	if(n < 0)
-		return -1;
-	if(n != 8+ndata){
-		dprint(2, "%s: cmd: short write: %d\n", argv0, n);
-		return -1;
-	}
-	return n;
-}
-
-static int
-cmdrep(Dev *d, void *buf, int nb)
-{
-	char *hd;
-
-	nb = read(d->dfd, buf, nb);
-	if(nb >0 && usbdebug > 2){
-		hd = hexstr(buf, nb);
-		fprint(2, "%s: in[%d] %s\n", d->dir, nb, hd);
-		free(hd);
-	}
-	return nb;
-}
-
-int
-usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count)
-{
-	int i, r, nerr;
-	char err[64];
-
-	/*
-	 * Some devices do not respond to commands some times.
-	 * Others even report errors but later work just fine. Retry.
-	 */
-	r = -1;
-	*err = 0;
-	for(i = nerr = 0; i < Uctries; i++){
-		if(type & Rd2h)
-			r = cmdreq(d, type, req, value, index, nil, count);
-		else
-			r = cmdreq(d, type, req, value, index, data, count);
-		if(r > 0){
-			if((type & Rd2h) == 0)
-				break;
-			r = cmdrep(d, data, count);
-			if(r > 0)
-				break;
-			if(r == 0)
-				werrstr("no data from device");
-		}
-		nerr++;
-		if(*err == 0)
-			rerrstr(err, sizeof(err));
-		sleep(Ucdelay);
-	}
-	if(r > 0 && i >= 2)
-		/* let the user know the device is not in good shape */
-		fprint(2, "%s: usbcmd: %s: required %d attempts (%s)\n",
-			argv0, d->dir, i, err);
-	return r;
-}
-
-int
-unstall(Dev *dev, Dev *ep, int dir)
-{
-	int r;
-
-	if(dir == Ein)
-		dir = 0x80;
-	else
-		dir = 0;
-	r = Rh2d|Rstd|Rep;
-	if(usbcmd(dev, r, Rclearfeature, Fhalt, ep->id|dir, nil, 0)<0){
-		werrstr("unstall: %s: %r", ep->dir);
-		return -1;
-	}
-	if(devctl(ep, "clrhalt") < 0){
-		werrstr("clrhalt: %s: %r", ep->dir);
-		return -1;
-	}
-	return 0;
-}
-
-/*
- * To be sure it uses a single write.
- */
-int
-devctl(Dev *dev, char *fmt, ...)
-{
-	char buf[128];
-	va_list arg;
-	char *e;
-
-	va_start(arg, fmt);
-	e = vseprint(buf, buf+sizeof(buf), fmt, arg);
-	va_end(arg);
-	return write(dev->cfd, buf, e-buf);
-}
--- a/sys/src/cmd/usb/lib/devs.c
+++ /dev/null
@@ -1,159 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-
-typedef struct Parg Parg;
-
-enum {
-	Ndevs = 32,
-	Arglen = 500,
-	Nargs = 64,
-	Stack = 16 * 1024,
-};
-
-struct Parg {
-	char*	args;
-	Dev*	dev;
-	int 	(*f)(Dev*,int,char**);
-	Channel*rc;
-};
-
-static void
-workproc(void *a)
-{
-	Parg *pa;
-	char args[Arglen];
-	char *argv[Nargs];
-	int argc;
-	Channel *rc;
-	Dev *d;
-	int (*f)(Dev*,int,char**);
-
-	pa = a;
-	strecpy(args, args+sizeof(args), pa->args);	/* don't leak */
-	d = pa->dev;
-	f = pa->f;
-	rc = pa->rc;
-	free(pa->args);
-	free(pa);
-	argc = tokenize(args, argv, nelem(argv)-1);
-	argv[argc] = nil;
-	if(f(d, argc, argv) < 0){
-		closedev(d);
-		fprint(2, "%s: devmain: %r\n", argv0);
-		sendul(rc, -1);
-		threadexits("devmain: %r");
-	}
-	sendul(rc, 0);
-	threadexits(nil);
-	
-}
-
-int
-matchdevcsp(char *info, void *a)
-{
-	char sbuf[40];
-	int *csps;
-
-	csps = a;
-	for(; *csps != 0; csps++){
-		snprint(sbuf, sizeof(sbuf), "csp %#08ux", *csps);
-		if(strstr(info, sbuf) != nil)
-			return 0;
-	}
-	return -1;
-}
-
-int
-finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs)
-{
-	int fd, i, n, nd, nr;
-	char *nm;
-	char dbuf[512], fbuf[40];
-	Dir *d;
-
-	fd = open("/dev/usb", OREAD);
-	if(fd < 0)
-		sysfatal("/dev/usb: %r");
-	nd = dirreadall(fd, &d);
-	close(fd);
-	if(nd < 2)
-		sysfatal("/dev/usb: no devs");
-	for(i = n = 0; i < nd && n < ndirs; i++){
-		nm = d[i].name;
-		if(strcmp(nm, "ctl") == 0 || strstr(nm, ".0") == nil)
-			continue;
-		snprint(fbuf, sizeof(fbuf), "/dev/usb/%s/ctl", nm);
-		fd = open(fbuf, OREAD);
-		if(fd < 0)
-			continue;	/* may be gone */
-		nr = read(fd, dbuf, sizeof(dbuf)-1);
-		close(fd);
-		if(nr < 0)
-			continue;
-		dbuf[nr] = 0;
-		if(strstr(dbuf, "enabled ") != nil && strstr(dbuf, " busy") == nil)
-			if(matchf(dbuf, farg) == 0)
-				dirs[n++] = smprint("/dev/usb/%s", nm);
-	}
-	free(d);
-	if(usbdebug > 1)
-		for(nd = 0; nd < n; nd++)
-			fprint(2, "finddevs: %s\n", dirs[nd]);
-	return n;
-}
-
-void
-startdevs(char *args, char *argv[], int argc, int (*mf)(char*, void*),
-	void *ma, int (*df)(Dev*, int, char**))
-{
-	int i, ndirs, ndevs;
-	char *dirs[Ndevs];
-	char **dp;
-	Parg *parg;
-	Dev *dev;
-	Channel *rc;
-
-	if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
-		sysfatal("#u: %r");
-
-	if(argc > 0){
-		ndirs = argc;
-		dp = argv;
-	}else{
-		dp = dirs;
-		ndirs = finddevs(mf, ma, dp, Ndevs);
-		if(ndirs == nelem(dirs))
-			fprint(2, "%s: too many devices\n", argv0);
-	}
-	ndevs = 0;
-	rc = chancreate(sizeof(ulong), 0);
-	if(rc == nil)
-		sysfatal("no memory");
-	for(i = 0; i < ndirs; i++){
-		fprint(2, "%s: startdevs: opening #%d %s\n", argv0, i, dp[i]);
-		dev = opendev(dp[i]);
-		if(dev == nil)
-			fprint(2, "%s: %s: %r\n", argv0, dp[i]);
-		else if(configdev(dev) < 0){
-			fprint(2, "%s: %s: config: %r\n", argv0, dp[i]);
-			closedev(dev);
-		}else{
-			dprint(2, "%s: %U", argv0, dev);
-			parg = emallocz(sizeof(Parg), 0);
-			parg->args = estrdup(args);
-			parg->dev = dev;
-			parg->rc = rc;
-			parg->f = df;
-			proccreate(workproc, parg, Stack);
-			if(recvul(rc) == 0)
-				ndevs++;
-		}
-		if(dp != argv)
-			free(dirs[i]);
-	}
-	chanfree(rc);
-	if(ndevs == 0)
-		sysfatal("no unhandled devices found");
-}
--- a/sys/src/cmd/usb/lib/dump.c
+++ /dev/null
@@ -1,176 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <bio.h>
-#include "usb.h"
-
-int usbdebug;
-
-static char *edir[] = {"in", "out", "inout"};
-static char *etype[] = {"ctl", "iso", "bulk", "intr"};
-static char* cnames[] =
-{
-	"none", "audio", "comms", "hid", "",
-	"", "", "printer", "storage", "hub", "data"
-};
-static char* devstates[] =
-{
-	"detached", "attached", "enabled", "assigned", "configured"
-};
-
-char*
-classname(int c)
-{
-	static char buf[30];
-
-	if(c >= 0 && c < nelem(cnames))
-		return cnames[c];
-	else{
-		seprint(buf, buf+30, "%d", c);
-		return buf;
-	}
-}
-
-char *
-hexstr(void *a, int n)
-{
-	int i;
-	char *dbuff, *s, *e;
-	uchar *b;
-
-	b = a;
-	dbuff = s = emallocz(1024, 0);
-	*s = 0;
-	e = s + 1024;
-	for(i = 0; i < n; i++)
-		s = seprint(s, e, " %.2ux", b[i]);
-	if(s == e)
-		fprint(2, "%s: usb/lib: hexdump: bug: small buffer\n", argv0);
-	return dbuff;
-}
-
-static char *
-seprintiface(char *s, char *e, Iface *i)
-{
-	int	j;
-	Altc	*a;
-	Ep	*ep;
-	char	*eds, *ets;
-
-	s = seprint(s, e, "\t\tiface csp %s.%uld.%uld\n",
-		classname(Class(i->csp)), Subclass(i->csp), Proto(i->csp));
-	for(j = 0; j < Naltc; j++){
-		a=i->altc[j];
-		if(a == nil)
-			break;
-		s = seprint(s, e, "\t\t  alt %d attr %d ival %d",
-			j, a->attrib, a->interval);
-		if(a->aux != nil)
-			s = seprint(s, e, " devspec %p\n", a->aux);
-		else
-			s = seprint(s, e, "\n");
-	}
-	for(j = 0; j < Nep; j++){
-		ep = i->ep[j];
-		if(ep == nil)
-			break;
-		eds = ets = "";
-		if(ep->dir <= nelem(edir))
-			eds = edir[ep->dir];
-		if(ep->type <= nelem(etype))
-			ets = etype[ep->type];
-		s = seprint(s, e, "\t\t  ep id %d addr %d dir %s type %s"
-			" itype %d maxpkt %d ntds %d\n",
-			ep->id, ep->addr, eds, ets, ep->isotype,
-			ep->maxpkt, ep->ntds);
-	}
-	return s;
-}
-
-static char*
-seprintconf(char *s, char *e, Usbdev *d, int ci)
-{
-	int i;
-	Conf *c;
-	char *hd;
-
-	c = d->conf[ci];
-	s = seprint(s, e, "\tconf: cval %d attrib %x %d mA\n",
-		c->cval, c->attrib, c->milliamps);
-	for(i = 0; i < Niface; i++)
-		if(c->iface[i] == nil)
-			break;
-		else
-			s = seprintiface(s, e, c->iface[i]);
-	for(i = 0; i < Nddesc; i++)
-		if(d->ddesc[i] == nil)
-			break;
-		else if(d->ddesc[i]->conf == c){
-			hd = hexstr((uchar*)&d->ddesc[i]->data,
-				d->ddesc[i]->data.bLength);
-			s = seprint(s, e, "\t\tdev desc %x[%d]: %s\n",
-				d->ddesc[i]->data.bDescriptorType,
-				d->ddesc[i]->data.bLength, hd);
-			free(hd);
-		}
-	return s;
-}
-
-int
-Ufmt(Fmt *f)
-{
-	int i;
-	Dev *d;
-	Usbdev *ud;
-	char buf[1024];
-	char *s, *e;
-
-	s = buf;
-	e = buf+sizeof(buf);
-	d = va_arg(f->args, Dev*);
-	if(d == nil)
-		return fmtprint(f, "<nildev>\n");
-	s = seprint(s, e, "%s", d->dir);
-	ud = d->usb;
-	if(ud == nil)
-		return fmtprint(f, "%s %ld refs\n", buf, d->ref);
-	s = seprint(s, e, " csp %s.%uld.%uld",
-		classname(Class(ud->csp)), Subclass(ud->csp), Proto(ud->csp));
-	s = seprint(s, e, " vid %#ux did %#ux", ud->vid, ud->did);
-	s = seprint(s, e, " refs %ld\n", d->ref);
-	s = seprint(s, e, "\t%s %s %s\n", ud->vendor, ud->product, ud->serial);
-	for(i = 0; i < Nconf; i++){
-		if(ud->conf[i] == nil)
-			break;
-		else
-			s = seprintconf(s, e, ud, i);
-	}
-	return fmtprint(f, "%s", buf);
-}
-
-char*
-estrdup(char *s)
-{
-	char *d;
-
-	d = strdup(s);
-	if(d == nil)
-		sysfatal("strdup: %r");
-	setmalloctag(d, getcallerpc(&s));
-	return d;
-}
-
-void*
-emallocz(ulong size, int zero)
-{
-	void *x;
-
-	x = malloc(size);
-	if(x == nil)
-		sysfatal("malloc: %r");
-	if(zero)
-		memset(x, 0, size);
-	setmalloctag(x, getcallerpc(&size));
-	return x;
-}
-
--- a/sys/src/cmd/usb/lib/fs.c
+++ /dev/null
@@ -1,673 +1,0 @@
-/*
- * Framework for USB devices that provide a file tree.
- * The main process (usbd or the driver's main proc)
- * calls fsinit() to start FS operation.
- *
- * One or more drivers call fsstart/fsend to register
- * or unregister their operations for their subtrees.
- *
- * root dir has qids with 0 in high 32 bits.
- * for other files we keep the device id in there.
- * The low 32 bits for directories at / must be 0.
- */
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "usb.h"
-#include "usbfs.h"
-
-#undef dprint
-#define dprint if(usbfsdebug)fprint
-
-typedef struct Rpc Rpc;
-
-enum
-{
-	Nproc = 3,		/* max nb. of cached FS procs */
-
-	Nofid = ~0,		/* null value for fid number */
-	Notag = ~0,		/* null value for tags */
-	Dietag = 0xdead,		/* fake tag to ask outproc to die */
-
-	Stack = 16 * 1024,
-
-	/* Fsproc requests */
-	Run = 0,		/* call f(r) */
-	Exit,			/* terminate */
-
-};
-
-struct Rpc
-{
-	Fcall	t;
-	Fcall	r;
-	Fid*	fid;
-	int	flushed;
-	Rpc*	next;
-	char	data[Bufsize];
-};
-
-int usbfsdebug;
-
-char Enotfound[] = "file not found";
-char Etoosmall[] = "parameter too small";
-char Eio[] = "i/o error";
-char Eperm[] = "permission denied";
-char Ebadcall[] = "unknown fs call";
-char Ebadfid[] = "fid not found";
-char Einuse[] = "fid already in use";
-char Eisopen[] = "it is already open";
-char Ebadctl[] = "unknown control request";
-
-static char *user;
-static ulong epoch;
-static ulong msgsize = Msgsize;
-static int fsfd = -1;
-static Channel *outc;	/* of Rpc* */
-
-static QLock rpclck;	/* protect vars in this block */
-static Fid *freefids;
-static Fid *fids;
-static Rpc *freerpcs;
-static Rpc *rpcs;
-
-static Channel*procc;
-static Channel*endc;
-
-static Usbfs* fsops;
-
-static void fsioproc(void*);
-
-static void
-schedproc(void*)
-{
-	Channel *proc[Nproc];
-	int nproc;
-	Channel *p;
-
-	Alt a[] =
-	{
-		{procc, &proc[0], CHANSND},
-		{endc, &p, CHANRCV},
-		{nil, nil, CHANEND}
-	};
-	memset(proc, 0, sizeof(proc));
-	nproc = 0;
-	for(;;){
-		if(nproc == 0){
-			proc[0] = chancreate(sizeof(Rpc*), 0);
-			proccreate(fsioproc, proc[0], Stack);
-			nproc++;
-		}
-		switch(alt(a)){
-		case 0:
-			proc[0] = nil;
-			if(nproc > 1){
-				proc[0] = proc[nproc-1];
-				proc[nproc-1] = nil;
-			}
-			nproc--;
-			break;
-		case 1:
-			if(nproc < nelem(proc))
-				proc[nproc++] = p;
-			else
-				sendp(p, nil);
-			break;
-		default:
-			sysfatal("alt");
-		}
-	}
-}
-
-static void
-dump(void)
-{
-	Rpc *rpc;
-	Fid *fid;
-
-	qlock(&rpclck);
-	fprint(2, "dump:\n");
-	for(rpc = rpcs; rpc != nil; rpc = rpc->next)
-		fprint(2, "rpc %#p %F next %#p\n", rpc, &rpc->t, rpc->next);
-	for(fid = fids; fid != nil; fid = fid->next)
-		fprint(2, "fid %d qid %#llux omode %d aux %#p\n",
-			fid->fid, fid->qid.path, fid->omode, fid->aux);
-	fprint(2, "\n");
-	qunlock(&rpclck);
-}
-
-static Rpc*
-newrpc(void)
-{
-	Rpc *r;
-
-	qlock(&rpclck);
-	r = freerpcs;
-	if(r != nil)
-		freerpcs = r->next;
-	else
-		r = emallocz(sizeof(Rpc), 0);
-	r->next = rpcs;
-	rpcs = r;
-	r->t.tag = r->r.tag = Notag;
-	r->t.fid = r->r.fid = Nofid;
-	r->t.type = r->r.type = 0;
-	r->flushed = 0;
-	r->fid = nil;
-	r->r.data = (char*)r->data;
-	qunlock(&rpclck);
-	return r;
-}
-
-static void
-freerpc(Rpc *r)
-{
-	Rpc **l;
-	if(r == nil)
-		return;
-	qlock(&rpclck);
-	for(l = &rpcs; *l != nil && *l != r; l = &(*l)->next)
-		;
-	assert(*l == r);
-	*l = r->next;
-	r->next = freerpcs;
-	freerpcs = r;
-	r->t.type = 0;
-	r->t.tag = 0x77777777;
-	qunlock(&rpclck);
-}
-
-static void
-flushrpc(int tag)
-{
-	Rpc *r;
-
-	qlock(&rpclck);
-	for(r = rpcs; r != nil; r = r->next)
-		if(r->t.tag == tag){
-			r->flushed = 1;
-			break;
-		}
-	qunlock(&rpclck);
-}
-
-static Fid*
-getfid(int fid, int alloc)
-{
-	Fid *f;
-
-	qlock(&rpclck);
-	for(f = fids; f != nil && f->fid != fid; f = f->next)
-		;
-	if(f != nil && alloc != 0){	/* fid in use */
-		qunlock(&rpclck);
-		return nil;
-	}
-	if(f == nil && alloc != 0){
-		if(freefids != nil){
-			f = freefids;
-			freefids = freefids->next;
-		}else
-			f = emallocz(sizeof(Fid), 1);
-		f->fid = fid;
-		f->aux = nil;
-		f->omode = ONONE;
-		f->next = fids;
-		fids = f;
-	}
-	qunlock(&rpclck);
-	return f;
-}
-
-static void
-freefid(Fid *f)
-{
-	Fid **l;
-
-	if(f == nil)
-		return;
-	if(fsops->clunk != nil)
-		fsops->clunk(fsops, f);
-	qlock(&rpclck);
-	for(l = &fids; *l != nil && *l != f; l = &(*l)->next)
-		;
-	assert(*l == f);
-	*l = f->next;
-	f->next = freefids;
-	freefids = f;
-	qunlock(&rpclck);
-}
-
-static Rpc*
-fserror(Rpc *rpc, char* fmt, ...)
-{
-	va_list arg;
-	char *c;
-
-	va_start(arg, fmt);
-	c = (char*)rpc->data;
-	vseprint(c, c+sizeof(rpc->data), fmt, arg);
-	va_end(arg);
-	rpc->r.type = Rerror;
-	rpc->r.ename = (char*)rpc->data;
-	return rpc;
-}
-
-static Rpc*
-fsversion(Rpc *r)
-{
-	if(r->t.msize < 256)
-		return fserror(r, Etoosmall);
-	if(strncmp(r->t.version, "9P2000", 6) != 0)
-		return fserror(r, "wrong version");
-	if(r->t.msize < msgsize)
-		msgsize = r->t.msize;
-	r->r.msize = msgsize;
-	r->r.version = "9P2000";
-	return r;
-}
-
-static Rpc*
-fsattach(Rpc *r)
-{
-	static int already;
-
-	/* Reload user because at boot it could be still none */
-	user=getuser();
-	if(already++ > 0 && strcmp(r->t.uname, user) != 0)
-		return fserror(r, Eperm);
-	if(r->fid == nil)
-		return fserror(r, Einuse);
-
-	r->r.qid.type = QTDIR;
-	r->r.qid.path = fsops->qid;
-	r->r.qid.vers = 0;
-	r->fid->qid = r->r.qid;
-	return r;
-}
-
-static Rpc*
-fswalk(Rpc *r)
-{
-	int i;
-	Fid *nfid, *ofid;
-
-	if(r->fid->omode != ONONE)
-		return fserror(r, Eisopen);
-
-	nfid = nil;
-	ofid = r->fid;
-	if(r->t.newfid != r->t.fid){
-		nfid = getfid(r->t.newfid, 1);
-		if(nfid == nil)
-			return fserror(r, Einuse);
-		nfid->qid = r->fid->qid;
-		if(fsops->clone != nil)
-			fsops->clone(fsops, ofid, nfid);
-		else
-			nfid->aux = r->fid->aux;
-		r->fid = nfid;
-	}
-	r->r.nwqid = 0;
-	for(i = 0; i < r->t.nwname; i++)
-		if(fsops->walk(fsops, r->fid, r->t.wname[i]) < 0)
-			break;
-		else
-			r->r.wqid[i] = r->fid->qid;
-	r->r.nwqid = i;
-	if(i != r->t.nwname && r->t.nwname > 0){
-		if(nfid != nil)
-			freefid(nfid);
-		r->fid = ofid;
-	}
-	if(i == 0 && r->t.nwname > 0)
-		return fserror(r, "%r");
-	return r;
-}
-
-static void
-fsioproc(void* a)
-{
-	long rc;
-	Channel *p = a;
-	Rpc *rpc;
-	Fcall *t, *r;
-	Fid *fid;
-
-	dprint(2, "%s: fsioproc pid %d\n", argv0, getpid());
-	while((rpc = recvp(p)) != nil){
-		t = &rpc->t;
-		r = &rpc->r;
-		fid = rpc->fid;
-		rc = -1;
-		dprint(2, "%s: fsioproc pid %d: req %d\n", argv0, getpid(), t->type);
-		switch(t->type){
-		case Topen:
-			rc = fsops->open(fsops, fid, t->mode);
-			if(rc >= 0){
-				r->iounit = 0;
-				r->qid = fid->qid;
-				fid->omode = t->mode & 3;
-			}
-			break;
-		case Tread:
-			rc = fsops->read(fsops, fid, r->data, t->count, t->offset);
-			if(rc >= 0){
-				if(rc > t->count)
-					print("%s: bug: read %ld bytes > %ud wanted\n",
-						argv0, rc, t->count);
-				r->count = rc;
-			}
-			/*
-			 * TODO: if we encounter a long run of continuous read
-			 * errors, we should do something more drastic so that
-			 * our caller doesn't just spin its wheels forever.
-			 */
-			break;
-		case Twrite:
-			rc = fsops->write(fsops, fid, t->data, t->count, t->offset);
-			r->count = rc;
-			break;
-		default:
-			sysfatal("fsioproc: bad type");
-		}
-		if(rc < 0)
-			sendp(outc, fserror(rpc, "%r"));
-		else
-			sendp(outc, rpc);
-		sendp(endc, p);
-	}
-	chanfree(p);
-	dprint(2, "%s: fsioproc %d exiting\n", argv0, getpid());
-	threadexits(nil);
-}
-
-static Rpc*
-fsopen(Rpc *r)
-{
-	Channel *p;
-
-	if(r->fid->omode != ONONE)
-		return fserror(r, Eisopen);
-	if((r->t.mode & 3) != OREAD && (r->fid->qid.type & QTDIR) != 0)
-		return fserror(r, Eperm);
-	p = recvp(procc);
-	sendp(p, r);
-	return nil;
-}
-
-int
-usbdirread(Usbfs*f, Qid q, char *data, long cnt, vlong off, Dirgen gen, void *arg)
-{
-	int i, n, nd;
-	char name[Namesz];
-	Dir d;
-
-	memset(&d, 0, sizeof(d));
-	d.name = name;
-	d.uid = d.gid = d.muid = user;
-	d.atime = time(nil);
-	d.mtime = epoch;
-	d.length = 0;
-	for(i = n = 0; gen(f, q, i, &d, arg) >= 0; i++){
-		if(usbfsdebug > 1)
-			fprint(2, "%s: dir %d q %#llux: %D\n", argv0, i, q.path, &d);
-		nd = convD2M(&d, (uchar*)data+n, cnt-n);
-		if(nd <= BIT16SZ)
-			break;
-		if(off > 0)
-			off -= nd;
-		else
-			n += nd;
-		d.name = name;
-		d.uid = d.gid = d.muid = user;
-		d.atime = time(nil);
-		d.mtime = epoch;
-		d.length = 0;
-	}
-	return n;
-}
-
-long
-usbreadbuf(void *data, long count, vlong offset, void *buf, long n)
-{
-	if(offset >= n)
-		return 0;
-	if(offset + count > n)
-		count = n - offset;
-	memmove(data, (char*)buf + offset, count);
-	return count;
-}
-
-static Rpc*
-fsread(Rpc *r)
-{
-	Channel *p;
-
-	if(r->fid->omode != OREAD && r->fid->omode != ORDWR)
-		return fserror(r, Eperm);
-	p = recvp(procc);
-	sendp(p, r);
-	return nil;
-}
-
-static Rpc*
-fswrite(Rpc *r)
-{
-	Channel *p;
-
-	if(r->fid->omode != OWRITE && r->fid->omode != ORDWR)
-		return fserror(r, Eperm);
-	p = recvp(procc);
-	sendp(p, r);
-	return nil;
-}
-
-static Rpc*
-fsclunk(Rpc *r)
-{
-	freefid(r->fid);
-	return r;
-}
-
-static Rpc*
-fsno(Rpc *r)
-{
-	return fserror(r, Eperm);
-}
-
-static Rpc*
-fsstat(Rpc *r)
-{
-	Dir d;
-	char name[Namesz];
-
-	memset(&d, 0, sizeof(d));
-	d.name = name;
-	d.uid = d.gid = d.muid = user;
-	d.atime = time(nil);
-	d.mtime = epoch;
-	d.length = 0;
-	if(fsops->stat(fsops, r->fid->qid, &d) < 0)
-		return fserror(r, "%r");
-	r->r.stat = (uchar*)r->data;
-	r->r.nstat = convD2M(&d, (uchar*)r->data, msgsize);
-	return r;
-}
-
-static Rpc*
-fsflush(Rpc *r)
-{
-	/*
-	 * Flag it as flushed and respond.
-	 * Either outproc will reply to the flushed request
-	 * before responding to flush, or it will never reply to it.
-	 * Note that we do NOT abort the ongoing I/O.
-	 * That might leave the affected endpoints in a failed
-	 * state. Instead, we pretend the request is aborted.
-	 *
-	 * Only open, read, and write are processed
-	 * by auxiliary processes and other requests wil never be
-	 * flushed in practice.
-	 */
-	flushrpc(r->t.oldtag);
-	return r;
-}
-
-Rpc* (*fscalls[])(Rpc*) = {
-	[Tversion]	fsversion,
-	[Tauth]		fsno,
-	[Tattach]	fsattach,
-	[Twalk]		fswalk,
-	[Topen]		fsopen,
-	[Tcreate]	fsno,
-	[Tread]		fsread,
-	[Twrite]	fswrite,
-	[Tclunk]	fsclunk,
-	[Tremove]	fsno,
-	[Tstat]		fsstat,
-	[Twstat]	fsno,
-	[Tflush]	fsflush,
-};
-
-static void
-outproc(void*)
-{
-	static uchar buf[Bufsize];
-	Rpc *rpc;
-	int nw;
-	static int once = 0;
-
-	if(once++ != 0)
-		sysfatal("more than one outproc");
-	for(;;){
-		do
-			rpc = recvp(outc);
-		while(rpc == nil);		/* a delayed reply */
-		if(rpc->t.tag == Dietag)
-			break;
-		if(rpc->flushed){
-			dprint(2, "outproc: tag %d flushed\n", rpc->t.tag);
-			freerpc(rpc);
-			continue;
-		}
-		dprint(2, "-> %F\n", &rpc->r);
-		nw = convS2M(&rpc->r, buf, sizeof(buf));
-		if(nw == sizeof(buf))
-			fprint(2, "%s: outproc: buffer is too small\n", argv0);
-		if(nw <= BIT16SZ)
-			fprint(2, "%s: conS2M failed\n", argv0);
-		else if(write(fsfd, buf, nw) != nw){
-			fprint(2, "%s: outproc: write: %r", argv0);
-			/* continue and let the reader abort us */
-		}
-		if(usbfsdebug > 1)
-			dump();
-		freerpc(rpc);
-	}
-	dprint(2, "%s: outproc: exiting\n", argv0);
-}
-
-static void
-usbfs(void*)
-{
-	Rpc *rpc;
-	int nr;
-	static int once = 0;
-
-	if(once++ != 0)
-		sysfatal("more than one usbfs proc");
-
-	outc = chancreate(sizeof(Rpc*), 1);
-	procc = chancreate(sizeof(Channel*), 0);
-	endc = chancreate(sizeof(Channel*), 0);
-	if(outc == nil || procc == nil || endc == nil)
-		sysfatal("chancreate: %r");
-	threadcreate(schedproc, nil, Stack);
-	proccreate(outproc, nil, Stack);
-	for(;;){
-		rpc = newrpc();
-		do{
-			nr = read9pmsg(fsfd, rpc->data, sizeof(rpc->data));
-		}while(nr == 0);
-		if(nr < 0){
-			dprint(2, "%s: usbfs: read: '%r'", argv0);
-			if(fsops->end != nil)
-				fsops->end(fsops);
-			else
-				closedev(fsops->dev);
-			rpc->t.tag = Dietag;
-			sendp(outc, rpc);
-			break;
-		}
-		if(convM2S((uchar*)rpc->data, nr, &rpc->t) <=0){
-			dprint(2, "%s: convM2S failed\n", argv0);
-			freerpc(rpc);
-			continue;
-		}
-		dprint(2, "<- %F\n", &rpc->t);
-		rpc->r.tag = rpc->t.tag;
-		rpc->r.type = rpc->t.type + 1;
-		rpc->r.fid = rpc->t.fid;
-		if(fscalls[rpc->t.type] == nil){
-			sendp(outc, fserror(rpc, Ebadcall));
-			continue;
-		}
-		if(rpc->t.fid != Nofid){
-			if(rpc->t.type == Tattach)
-				rpc->fid = getfid(rpc->t.fid, 1);
-			else
-				rpc->fid = getfid(rpc->t.fid, 0);
-			if(rpc->fid == nil){
-				sendp(outc, fserror(rpc, Ebadfid));
-				continue;
-			}
-		}
-		sendp(outc, fscalls[rpc->t.type](rpc));
-	}
-	dprint(2, "%s: ubfs: eof: exiting\n", argv0);
-}
-
-void
-usbfsinit(char* srv, char *mnt, Usbfs *f, int flag)
-{
-	int fd[2];
-	int sfd;
-	int afd;
-	char sfile[40];
-
-	fsops = f;
-	if(pipe(fd) < 0)
-		sysfatal("pipe: %r");
-	user = getuser();
-	epoch = time(nil);
-
-	fmtinstall('D', dirfmt);
-	fmtinstall('M', dirmodefmt);
-	fmtinstall('F', fcallfmt);
-	fsfd = fd[1];
-	procrfork(usbfs, nil, Stack, RFNAMEG);	/* no RFFDG */
-	if(srv != nil){
-		snprint(sfile, sizeof(sfile), "#s/%s", srv);
-		remove(sfile);
-		sfd = create(sfile, OWRITE, 0660);
-		if(sfd < 0)
-			sysfatal("post: %r");
-		snprint(sfile, sizeof(sfile), "%d", fd[0]);
-		if(write(sfd, sfile, strlen(sfile)) != strlen(sfile))
-			sysfatal("post: %r");
-		close(sfd);
-	}
-	if(mnt != nil){
-		sfd = dup(fd[0], -1);	/* debug */
-		afd = fauth(sfd, "");
-		if(afd >= 0)
-			sysfatal("authentication required??");
-		if(mount(sfd, -1, mnt, flag, "") < 0)
-			sysfatal("mount: %r");
-	}
-	close(fd[0]);
-}
-
--- a/sys/src/cmd/usb/lib/fsdir.c
+++ /dev/null
@@ -1,420 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "usb.h"
-#include "usbfs.h"
-
-typedef struct Rpc Rpc;
-
-enum
-{
-	Incr = 3,	/* increments for fs array */
-	Dtop = 0,	/* high 32 bits for / 	*/
-	Qdir = 0,	/* low 32 bits for /devdir */
-};
-
-QLock fslck;
-static Usbfs** fs;
-static int nfs;
-static int fsused;
-static int exitonclose = 1;
-
-void
-usbfsexits(int y)
-{
-	exitonclose = y;
-}
-
-static int
-qiddev(uvlong path)
-{
-	return (int)(path>>32) & 0xFF;
-}
-
-static int
-qidfile(uvlong path)
-{
-	return (int)(path & 0xFFFFFFFFULL);
-}
-
-static uvlong
-mkqid(int qd, int qf)
-{
-	return ((uvlong)qd << 32) | (uvlong)qf;
-}
-
-void
-usbfsdirdump(void)
-{
-	int i;
-
-	qlock(&fslck);
-	fprint(2, "%s: fs list: (%d used %d total)\n", argv0, fsused, nfs);
-	for(i = 1; i < nfs; i++)
-		if(fs[i] != nil)
-			if(fs[i]->dev != nil)
-				fprint(2, "%s\t%s dev %#p refs %ld\n",
-					argv0, fs[i]->name, fs[i]->dev, fs[i]->dev->ref);
-			else
-				fprint(2, "%s:\t%s\n", argv0, fs[i]->name);
-	qunlock(&fslck);
-}
-
-void
-usbfsadd(Usbfs *dfs)
-{
-	int i, j;
-
-	dprint(2, "%s: fsadd %s\n", argv0, dfs->name);
-	qlock(&fslck);
-	for(i = 1; i < nfs; i++)
-		if(fs[i] == nil)
-			break;
-	if(i >= nfs){
-		if((nfs%Incr) == 0){
-			fs = realloc(fs, sizeof(Usbfs*) * (nfs+Incr));
-			if(fs == nil)
-				sysfatal("realloc: %r");
-			for(j = nfs; j < nfs+Incr; j++)
-				fs[j] = nil;
-		}
-		if(nfs == 0)	/* do not use entry 0 */
-			nfs++;
-		fs[nfs++] = dfs;
-	}else
-		fs[i] = dfs;
-	dfs->qid = mkqid(i, 0);
-	fsused++;
-	qunlock(&fslck);
-}
-
-static void
-usbfsdelnth(int i)
-{
-	if(fs[i] != nil){
-		dprint(2, "%s: fsdel %s", argv0, fs[i]->name);
-		if(fs[i]->dev != nil){
-			dprint(2, " dev %#p ref %ld\n",
-				fs[i]->dev, fs[i]->dev->ref);
-		}else
-			dprint(2, "no dev\n");
-		if(fs[i]->end != nil)
-			fs[i]->end(fs[i]);
-		closedev(fs[i]->dev);
-		fsused--;
-	}
-	fs[i] = nil;
-	if(fsused == 0 && exitonclose != 0){
-		fprint(2, "%s: all file systems gone: exiting\n", argv0);
-		threadexitsall(nil);
-	}
-}
-
-void
-usbfsdel(Usbfs *dfs)
-{
-	int i;
-
-	qlock(&fslck);
-	for(i = 0; i < nfs; i++)
-		if(dfs == nil || fs[i] == dfs){
-			usbfsdelnth(i);
-			if(dfs != nil)
-				break;
-		}
-	qunlock(&fslck);
-}
-
-static void
-fsend(Usbfs*)
-{
-	dprint(2, "%s: fsend\n", argv0);
-	usbfsdel(nil);
-}
-
-void
-usbfsgone(char *dir)
-{
-	int i;
-
-	qlock(&fslck);
-	/* devices may have more than one fs */
-	for(i = 0; i < nfs; i++)
-		if(fs[i] != nil && fs[i]->dev != nil)
-		if(strcmp(fs[i]->dev->dir, dir) == 0)
-			usbfsdelnth(i);
-	qunlock(&fslck);
-}
-
-static void
-fsclone(Usbfs*, Fid *o, Fid *n)
-{
-	int qd;
-	Dev *dev;
-	void (*xfsclone)(Usbfs *fs, Fid *of, Fid *nf);
-
-	xfsclone = nil;
-	dev = nil;
-	qd = qiddev(o->qid.path);
-	qlock(&fslck);
-	if(qd != Dtop && fs[qd] != nil && fs[qd]->clone != nil){
-		dev = fs[qd]->dev;
-		if(dev != nil)
-			incref(dev);
-		xfsclone = fs[qd]->clone;
-	}
-	qunlock(&fslck);
-	if(xfsclone != nil){
-		xfsclone(fs[qd], o, n);
-	}
-	if(dev != nil)
-		closedev(dev);
-}
-
-static int
-fswalk(Usbfs*, Fid *fid, char *name)
-{
-	Qid q;
-	int qd, qf;
-	int i;
-	int rc;
-	Dev *dev;
-	Dir d;
-	char dname[Namesz];
-	
-	int (*xfswalk)(Usbfs *fs, Fid *f, char *name);
-
-	q = fid->qid;
-	qd = qiddev(q.path);
-	qf = qidfile(q.path);
-
-	q.type = QTDIR;
-	q.vers = 0;
-	if(strcmp(name, "..") == 0)
-		if(qd == Dtop || qf == Qdir){
-			q.path = mkqid(Dtop, Qdir);
-			fid->qid = q;
-			return 0;
-		}
-	if(qd != 0){
-		qlock(&fslck);
-		if(fs[qd] == nil){
-			qunlock(&fslck);
-			werrstr(Eio);
-			return -1;
-		}
-		dev = fs[qd]->dev;
-		if(dev != nil)
-			incref(dev);
-		xfswalk = fs[qd]->walk;
-		qunlock(&fslck);
-		rc = xfswalk(fs[qd], fid, name);
-		if(dev != nil)
-			closedev(dev);
-		return rc;
-	}
-	qlock(&fslck);
-	for(i = 0; i < nfs; i++)
-		if(fs[i] != nil && strcmp(name, fs[i]->name) == 0){
-			q.path = mkqid(i, Qdir);
-			d.name = dname;
-			fs[i]->stat(fs[i], q, &d); /* may be a file */
-			fid->qid = d.qid;
-			qunlock(&fslck);
-			return 0;
-		}
-	qunlock(&fslck);
-	werrstr(Enotfound);
-	return -1;
-}
-
-static int
-fsopen(Usbfs*, Fid *fid, int mode)
-{
-	int qd;
-	int rc;
-	Dev *dev;
-	int (*xfsopen)(Usbfs *fs, Fid *f, int mode);
-
-	qd = qiddev(fid->qid.path);
-	if(qd == Dtop)
-		return 0;
-	qlock(&fslck);
-	if(fs[qd] == nil){
-		qunlock(&fslck);
-		werrstr(Eio);
-		return -1;
-	}
-	dev = fs[qd]->dev;
-	if(dev != nil)
-		incref(dev);
-	xfsopen = fs[qd]->open;
-	qunlock(&fslck);
-	if(xfsopen != nil)
-		rc = xfsopen(fs[qd], fid, mode);
-	else
-		rc = 0;
-	if(dev != nil)
-		closedev(dev);
-	return rc;
-}
-
-static int
-dirgen(Usbfs*, Qid, int n, Dir *d, void *)
-{
-	int i;
-	Dev *dev;
-	char *nm;
-
-	qlock(&fslck);
-	for(i = 0; i < nfs; i++)
-		if(fs[i] != nil && n-- == 0){
-			d->qid.type = QTDIR;
-			d->qid.path = mkqid(i, Qdir);
-			d->qid.vers = 0;
-			dev = fs[i]->dev;
-			if(dev != nil)
-				incref(dev);
-			nm = d->name;
-			fs[i]->stat(fs[i], d->qid, d);
-			d->name = nm;
-			strncpy(d->name, fs[i]->name, Namesz);
-			if(dev != nil)
-				closedev(dev);
-			qunlock(&fslck);
-			return 0;
-		}
-	qunlock(&fslck);
-	return -1;
-}
-
-static long
-fsread(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
-{
-	int qd;
-	int rc;
-	Dev *dev;
-	Qid q;
-	long (*xfsread)(Usbfs *fs, Fid *f, void *data, long count, vlong );
-
-	q = fid->qid;
-	qd = qiddev(q.path);
-	if(qd == Dtop)
-		return usbdirread(nil, q, data, cnt, off, dirgen, nil);
-	qlock(&fslck);
-	if(fs[qd] == nil){
-		qunlock(&fslck);
-		werrstr(Eio);
-		return -1;
-	}
-	dev = fs[qd]->dev;
-	if(dev != nil)
-		incref(dev);
-	xfsread = fs[qd]->read;
-	qunlock(&fslck);
-	rc = xfsread(fs[qd], fid, data, cnt, off);
-	if(dev != nil)
-		closedev(dev);
-	return rc;
-}
-
-static long
-fswrite(Usbfs*, Fid *fid, void *data, long cnt, vlong off)
-{
-	int qd;
-	int rc;
-	Dev *dev;
-	long (*xfswrite)(Usbfs *fs, Fid *f, void *data, long count, vlong );
-
-	qd = qiddev(fid->qid.path);
-	if(qd == Dtop)
-		sysfatal("fswrite: not for usbd /");
-	qlock(&fslck);
-	if(fs[qd] == nil){
-		qunlock(&fslck);
-		werrstr(Eio);
-		return -1;
-	}
-	dev = fs[qd]->dev;
-	if(dev != nil)
-		incref(dev);
-	xfswrite = fs[qd]->write;
-	qunlock(&fslck);
-	rc = xfswrite(fs[qd], fid, data, cnt, off);
-	if(dev != nil)
-		closedev(dev);
-	return rc;
-}
-
-
-static void
-fsclunk(Usbfs*, Fid* fid)
-{
-	int qd;
-	Dev *dev;
-	void (*xfsclunk)(Usbfs *fs, Fid *f);
-
-	dev = nil;
-	qd = qiddev(fid->qid.path);
-	qlock(&fslck);
-	if(qd != Dtop && fs[qd] != nil){
-		dev=fs[qd]->dev;
-		if(dev != nil)
-			incref(dev);
-		xfsclunk = fs[qd]->clunk;
-	}else
-		xfsclunk = nil;
-	qunlock(&fslck);
-	if(xfsclunk != nil){
-		xfsclunk(fs[qd], fid);
-	}
-	if(dev != nil)
-		closedev(dev);
-}
-
-static int
-fsstat(Usbfs*, Qid qid, Dir *d)
-{
-	int qd;
-	int rc;
-	Dev *dev;
-	int (*xfsstat)(Usbfs *fs, Qid q, Dir *d);
-
-	qd = qiddev(qid.path);
-	if(qd == Dtop){
-		d->qid = qid;
-		d->name = "usb";
-		d->length = 0;
-		d->mode = 0555|DMDIR;
-		return 0;
-	}
-	qlock(&fslck);
-	if(fs[qd] == nil){
-		qunlock(&fslck);
-		werrstr(Eio);
-		return -1;
-	}
-	xfsstat = fs[qd]->stat;
-	dev = fs[qd]->dev;
-	if(dev != nil)
-		incref(dev);
-	qunlock(&fslck);
-	rc = xfsstat(fs[qd], qid, d);
-	if(dev != nil)
-		closedev(dev);
-	return rc;
-}
-
-Usbfs usbdirfs =
-{
-	.walk = fswalk,
-	.clone = fsclone,
-	.clunk = fsclunk,
-	.open = fsopen,
-	.read = fsread,
-	.write = fswrite,
-	.stat = fsstat,
-	.end = fsend,
-};
-
--- a/sys/src/cmd/usb/lib/mkfile
+++ /dev/null
@@ -1,29 +1,0 @@
-</$objtype/mkfile
-
-LIB=usb.a$O
-OFILES=\
-	dev.$O\
-	devs.$O\
-	dump.$O\
-	parse.$O\
-	fs.$O\
-	fsdir.$O\
-
-HFILES=\
-	usb.h\
-	usbfs.h\
-
-
-UPDATE=\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-	mkfile\
-
-</sys/src/cmd/mklib
-
-install:V:	$LIB
-	date
-safeinstall:V: install
-safeinstallall:V: installall
-nuke:V:
-	rm -f *.[$OS] y.tab.? y.output y.error *.a[$OS]
--- a/sys/src/cmd/usb/lib/parse.c
+++ /dev/null
@@ -1,270 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <bio.h>
-#include "usb.h"
-
-int
-parsedev(Dev *xd, uchar *b, int n)
-{
-	Usbdev *d;
-	DDev *dd;
-	char *hd;
-
-	d = xd->usb;
-	assert(d != nil);
-	dd = (DDev*)b;
-	if(usbdebug>1){
-		hd = hexstr(b, Ddevlen);
-		fprint(2, "%s: parsedev %s: %s\n", argv0, xd->dir, hd);
-		free(hd);
-	}
-	if(dd->bLength < Ddevlen){
-		werrstr("short dev descr. (%d < %d)", dd->bLength, Ddevlen);
-		return -1;
-	}
-	if(dd->bDescriptorType != Ddev){
-		werrstr("%d is not a dev descriptor", dd->bDescriptorType);
-		return -1;
-	}
-	d->csp = CSP(dd->bDevClass, dd->bDevSubClass, dd->bDevProtocol);
-	d->ep[0]->maxpkt = xd->maxpkt = dd->bMaxPacketSize0;
-	d->class = dd->bDevClass;
-	d->nconf = dd->bNumConfigurations;
-	if(d->nconf == 0)
-		dprint(2, "%s: %s: no configurations\n", argv0, xd->dir);
-	d->vid = GET2(dd->idVendor);
-	d->did = GET2(dd->idProduct);
-	d->dno = GET2(dd->bcdDev);
-	d->vsid = dd->iManufacturer;
-	d->psid = dd->iProduct;
-	d->ssid = dd->iSerialNumber;
-	if(n > Ddevlen && usbdebug>1)
-		fprint(2, "%s: %s: parsedev: %d bytes left",
-			argv0, xd->dir, n - Ddevlen);
-	return Ddevlen;
-}
-
-static int
-parseiface(Usbdev *d, Conf *c, uchar *b, int n, Iface **ipp, Altc **app)
-{
-	int class, subclass, proto;
-	int ifid, altid;
-	DIface *dip;
-	Iface *ip;
-
-	assert(d != nil && c != nil);
-	if(n < Difacelen){
-		werrstr("short interface descriptor");
-		return -1;
-	}
-	dip = (DIface *)b;
-	ifid = dip->bInterfaceNumber;
-	if(ifid < 0 || ifid >= nelem(c->iface)){
-		werrstr("bad interface number %d", ifid);
-		return -1;
-	}
-	if(c->iface[ifid] == nil)
-		c->iface[ifid] = emallocz(sizeof(Iface), 1);
-	ip = c->iface[ifid];
-	class = dip->bInterfaceClass;
-	subclass = dip->bInterfaceSubClass;
-	proto = dip->bInterfaceProtocol;
-	ip->csp = CSP(class, subclass, proto);
-	if(d->csp == 0)				/* use csp from 1st iface */
-		d->csp = ip->csp;		/* if device has none */
-	if(d->class == 0)
-		d->class = class;
-	ip->id = ifid;
-	if(c == d->conf[0] && ifid == 0)	/* ep0 was already there */
-		d->ep[0]->iface = ip;
-	altid = dip->bAlternateSetting;
-	if(altid < 0 || altid >= nelem(ip->altc)){
-		werrstr("bad alternate conf. number %d", altid);
-		return -1;
-	}
-	if(ip->altc[altid] == nil)
-		ip->altc[altid] = emallocz(sizeof(Altc), 1);
-	*ipp = ip;
-	*app = ip->altc[altid];
-	return Difacelen;
-}
-
-extern Ep* mkep(Usbdev *, int);
-
-static int
-parseendpt(Usbdev *d, Conf *c, Iface *ip, Altc *altc, uchar *b, int n, Ep **epp)
-{
-	int i, dir, epid;
-	Ep *ep;
-	DEp *dep;
-
-	assert(d != nil && c != nil && ip != nil && altc != nil);
-	if(n < Deplen){
-		werrstr("short endpoint descriptor");
-		return -1;
-	}
-	dep = (DEp *)b;
-	altc->attrib = dep->bmAttributes;	/* here? */
-	altc->interval = dep->bInterval;
-
-	epid = dep->bEndpointAddress & 0xF;
-	assert(epid < nelem(d->ep));
-	if(dep->bEndpointAddress & 0x80)
-		dir = Ein;
-	else
-		dir = Eout;
-	ep = d->ep[epid];
-	if(ep == nil){
-		ep = mkep(d, epid);
-		ep->dir = dir;
-	}else if((ep->addr & 0x80) != (dep->bEndpointAddress & 0x80))
-		ep->dir = Eboth;
-	ep->maxpkt = GET2(dep->wMaxPacketSize);
-	ep->ntds = 1 + ((ep->maxpkt >> 11) & 3);
-	ep->maxpkt &= 0x7FF;
-	ep->addr = dep->bEndpointAddress;
-	ep->type = dep->bmAttributes & 0x03;
-	ep->isotype = (dep->bmAttributes>>2) & 0x03;
-	ep->conf = c;
-	ep->iface = ip;
-	for(i = 0; i < nelem(ip->ep); i++)
-		if(ip->ep[i] == nil)
-			break;
-	if(i == nelem(ip->ep)){
-		werrstr("parseendpt: bug: too many end points on interface "
-			"with csp %#lux", ip->csp);
-		fprint(2, "%s: %r\n", argv0);
-		return -1;
-	}
-	*epp = ip->ep[i] = ep;
-	return Dep;
-}
-
-static char*
-dname(int dtype)
-{
-	switch(dtype){
-	case Ddev:	return "device";
-	case Dconf: 	return "config";
-	case Dstr: 	return "string";
-	case Diface:	return "interface";
-	case Dep:	return "endpoint";
-	case Dreport:	return "report";
-	case Dphysical:	return "phys";
-	default:	return "desc";
-	}
-}
-
-int
-parsedesc(Usbdev *d, Conf *c, uchar *b, int n)
-{
-	int	len, nd, tot;
-	Iface	*ip;
-	Ep 	*ep;
-	Altc	*altc;
-	char	*hd;
-
-	assert(d != nil && c != nil);
-	tot = 0;
-	ip = nil;
-	ep = nil;
-	altc = nil;
-	for(nd = 0; nd < nelem(d->ddesc); nd++)
-		if(d->ddesc[nd] == nil)
-			break;
-
-	while(n > 2 && b[0] != 0 && b[0] <= n){
-		len = b[0];
-		if(usbdebug>1){
-			hd = hexstr(b, len);
-			fprint(2, "%s:\t\tparsedesc %s %x[%d] %s\n",
-				argv0, dname(b[1]), b[1], b[0], hd);
-			free(hd);
-		}
-		switch(b[1]){
-		case Ddev:
-		case Dconf:
-			werrstr("unexpected descriptor %d", b[1]);
-			ddprint(2, "%s\tparsedesc: %r", argv0);
-			break;
-		case Diface:
-			if(parseiface(d, c, b, n, &ip, &altc) < 0){
-				ddprint(2, "%s\tparsedesc: %r\n", argv0);
-				return -1;
-			}
-			break;
-		case Dep:
-			if(ip == nil || altc == nil){
-				werrstr("unexpected endpoint descriptor");
-				break;
-			}
-			if(parseendpt(d, c, ip, altc, b, n, &ep) < 0){
-				ddprint(2, "%s\tparsedesc: %r\n", argv0);
-				return -1;
-			}
-			break;
-		default:
-			if(nd == nelem(d->ddesc)){
-				fprint(2, "%s: parsedesc: too many "
-					"device-specific descriptors for device"
-					" %s %s\n",
-					argv0, d->vendor, d->product);
-				break;
-			}
-			d->ddesc[nd] = emallocz(sizeof(Desc)+b[0], 0);
-			d->ddesc[nd]->iface = ip;
-			d->ddesc[nd]->ep = ep;
-			d->ddesc[nd]->altc = altc;
-			d->ddesc[nd]->conf = c;
-			memmove(&d->ddesc[nd]->data, b, len);
-			++nd;
-		}
-		n -= len;
-		b += len;
-		tot += len;
-	}
-	return tot;
-}
-
-int
-parseconf(Usbdev *d, Conf *c, uchar *b, int n)
-{
-	DConf* dc;
-	int	l;
-	int	nr;
-	char	*hd;
-
-	assert(d != nil && c != nil);
-	dc = (DConf*)b;
-	if(usbdebug>1){
-		hd = hexstr(b, Dconflen);
-		fprint(2, "%s:\tparseconf  %s\n", argv0, hd);
-		free(hd);
-	}
-	if(dc->bLength < Dconflen){
-		werrstr("short configuration descriptor");
-		return -1;
-	}
-	if(dc->bDescriptorType != Dconf){
-		werrstr("not a configuration descriptor");
-		return -1;
-	}
-	c->cval = dc->bConfigurationValue;
-	c->attrib = dc->bmAttributes;
-	c->milliamps = dc->MaxPower*2;
-	l = GET2(dc->wTotalLength);
-	if(n < l){
-		werrstr("truncated configuration info");
-		return -1;
-	}
-	n -= Dconflen;
-	b += Dconflen;
-	nr = 0;
-	if(n > 0 && (nr=parsedesc(d, c, b, n)) < 0)
-		return -1;
-	n -= nr;
-	if(n > 0 && usbdebug>1)
-		fprint(2, "%s:\tparseconf: %d bytes left\n", argv0, n);
-	return l;
-}
--- a/sys/src/cmd/usb/lib/usb.h
+++ /dev/null
@@ -1,361 +1,0 @@
-typedef struct Altc Altc;
-typedef struct Conf Conf;
-typedef struct DConf DConf;
-typedef struct DDesc DDesc;
-typedef struct DDev DDev;
-typedef struct DEp DEp;
-typedef struct DIface DIface;
-typedef struct Desc Desc;
-typedef struct Dev Dev;
-typedef struct Ep Ep;
-typedef struct Iface Iface;
-typedef struct Usbdev Usbdev;
-
-enum {
-	/* fundamental constants */
-	Nep	= 256,	/* max. endpoints per usb device & per interface */
-
-	/* tunable parameters */
-	Nconf	= 16,	/* max. configurations per usb device */
-	Nddesc	= 8*Nep, /* max. device-specific descriptors per usb device */
-	Niface	= 16,	/* max. interfaces per configuration */
-	Naltc	= 256,	/* max. alt configurations per interface */
-	Uctries	= 4,	/* no. of tries for usbcmd */
-	Ucdelay	= 50,	/* delay before retrying */
-
-	/* request type */
-	Rh2d	= 0<<7,		/* host to device */
-	Rd2h	= 1<<7,		/* device to host */ 
-
-	Rstd	= 0<<5,		/* types */
-	Rclass	= 1<<5,
-	Rvendor	= 2<<5,
-
-	Rdev	= 0,		/* recipients */
-	Riface	= 1,
-	Rep	= 2,		/* endpoint */
-	Rother	= 3,
-
-	/* standard requests */
-	Rgetstatus	= 0,
-	Rclearfeature	= 1,
-	Rsetfeature	= 3,
-	Rsetaddress	= 5,
-	Rgetdesc	= 6,
-	Rsetdesc	= 7,
-	Rgetconf	= 8,
-	Rsetconf	= 9,
-	Rgetiface	= 10,
-	Rsetiface	= 11,
-	Rsynchframe	= 12,
-
-	Rgetcur	= 0x81,
-	Rgetmin	= 0x82,
-	Rgetmax	= 0x83,
-	Rgetres	= 0x84,
-	Rsetcur	= 0x01,
-	Rsetmin	= 0x02,
-	Rsetmax	= 0x03,
-	Rsetres	= 0x04,
-
-	/* dev classes */
-	Clnone		= 0,		/* not in usb */
-	Claudio		= 1,
-	Clcomms		= 2,
-	Clhid		= 3,
-	Clprinter	= 7,
-	Clstorage	= 8,
-	Clhub		= 9,
-	Cldata		= 10,
-
-	/* standard descriptor sizes */
-	Ddevlen		= 18,
-	Dconflen	= 9,
-	Difacelen	= 9,
-	Deplen		= 7,
-
-	/* descriptor types */
-	Ddev		= 1,
-	Dconf		= 2,
-	Dstr		= 3,
-	Diface		= 4,
-	Dep		= 5,
-	Dreport		= 0x22,
-	Dfunction	= 0x24,
-	Dphysical	= 0x23,
-
-	/* feature selectors */
-	Fdevremotewakeup = 1,
-	Fhalt 	= 0,
-
-	/* device state */
-	Detached = 0,
-	Attached,
-	Enabled,
-	Assigned,
-	Configured,
-
-	/* endpoint direction */
-	Ein = 0,
-	Eout,
-	Eboth,
-
-	/* endpoint type */
-	Econtrol = 0,
-	Eiso = 1,
-	Ebulk = 2,
-	Eintr = 3,
-
-	/* endpoint isotype */
-	Eunknown = 0,
-	Easync = 1,
-	Eadapt = 2,
-	Esync = 3,
-
-	/* config attrib */
-	Cbuspowered = 1<<7,
-	Cselfpowered = 1<<6,
-	Cremotewakeup = 1<<5,
-
-	/* report types */
-	Tmtype	= 3<<2,
-	Tmitem	= 0xF0,
-	Tmain	= 0<<2,
-		Tinput	= 0x80,
-		Toutput	= 0x90,
-		Tfeature = 0xB0,
-		Tcoll	= 0xA0,
-		Tecoll	= 0xC0,
-	 Tglobal	= 1<<2,
-		Tusagepage = 0x00,
-		Tlmin	= 0x10,
-		Tlmax	= 0x20,
-		Tpmin	= 0x30,
-		Tpmax	= 0x40,
-		Tunitexp	= 0x50,
-		Tunit	= 0x60,
-		Trepsize	= 0x70,
-		TrepID	= 0x80,
-		Trepcount = 0x90,
-		Tpush	= 0xA0,
-		Tpop	= 0xB0,
-	 Tlocal	= 2<<2,
-		Tusage	= 0x00,
-		Tumin	= 0x10,
-		Tumax	= 0x20,
-		Tdindex	= 0x30,
-		Tdmin	= 0x40,
-		Tdmax	= 0x50,
-		Tsindex	= 0x70,
-		Tsmin	= 0x80,
-		Tsmax	= 0x90,
-		Tsetdelim = 0xA0,
-	 Treserved	= 3<<2,
-	 Tlong	= 0xFE,
-
-};
-
-/*
- * Usb device (when used for ep0s) or endpoint.
- * RC: One ref because of existing, another one per ogoing I/O.
- * per-driver resources (including FS if any) are released by aux
- * once the last ref is gone. This may include other Devs using
- * to access endpoints for actual I/O.
- */
-struct Dev
-{
-	Ref;
-	char*	dir;		/* path for the endpoint dir */
-	int	id;		/* usb id for device or ep. number */
-	int	dfd;		/* descriptor for the data file */
-	int	cfd;		/* descriptor for the control file */
-	int	maxpkt;		/* cached from usb description */
-	Ref	nerrs;		/* number of errors in requests */
-	Usbdev*	usb;		/* USB description */
-	void*	aux;		/* for the device driver */
-	void	(*free)(void*);	/* idem. to release aux */
-};
-
-/*
- * device description as reported by USB (unpacked).
- */
-struct Usbdev
-{
-	ulong	csp;		/* USB class/subclass/proto */
-	int	vid;		/* vendor id */
-	int	did;		/* product (device) id */
-	int	dno;		/* device release number */
-	char*	vendor;
-	char*	product;
-	char*	serial;
-	int	vsid;
-	int	psid;
-	int	ssid;
-	int	class;		/* from descriptor */
-	int	nconf;		/* from descriptor */
-	Conf*	conf[Nconf];	/* configurations */
-	Ep*	ep[Nep];	/* all endpoints in device */
-	Desc*	ddesc[Nddesc];	/* (raw) device specific descriptors */
-};
-
-struct Ep
-{
-	uchar	addr;		/* endpt address, 0-15 (|0x80 if Ein) */
-	uchar	dir;		/* direction, Ein/Eout */
-	uchar	type;		/* Econtrol, Eiso, Ebulk, Eintr */
-	uchar	isotype;		/* Eunknown, Easync, Eadapt, Esync */
-	int	id;
-	int	maxpkt;		/* max. packet size */
-	int	ntds;		/* nb. of Tds per µframe */
-	Conf*	conf;		/* the endpoint belongs to */
-	Iface*	iface;		/* the endpoint belongs to */
-};
-
-struct Altc
-{
-	int	attrib;
-	int	interval;
-	void*	aux;		/* for the driver program */
-};
-
-struct Iface
-{
-	int 	id;		/* interface number */
-	ulong	csp;		/* USB class/subclass/proto */
-	Altc*	altc[Naltc];
-	Ep*	ep[Nep];
-	void*	aux;		/* for the driver program */
-};
-
-struct Conf
-{
-	int	cval;		/* value for set configuration */
-	int	attrib;
-	int	milliamps;	/* maximum power in this config. */
-	Iface*	iface[Niface];
-};
-
-/*
- * Device-specific descriptors.
- * They show up mixed with other descriptors
- * within a configuration.
- * These are unknown to the library but handed to the driver.
- */
-struct DDesc
-{
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	bbytes[1];
-	/* extra bytes allocated here to keep the rest of it */
-};
-
-struct Desc
-{
-	Conf*	conf;		/* where this descriptor was read */
-	Iface*	iface;		/* last iface before desc in conf. */
-	Ep*	ep;		/* last endpt before desc in conf. */
-	Altc*	altc;		/* last alt.c. before desc in conf. */
-	DDesc	data;		/* unparsed standard USB descriptor */
-};
-
-/*
- * layout of standard descriptor types
- */
-struct DDev
-{
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	bcdUSB[2];
-	uchar	bDevClass;
-	uchar	bDevSubClass;
-	uchar	bDevProtocol;
-	uchar	bMaxPacketSize0;
-	uchar	idVendor[2];
-	uchar	idProduct[2];
-	uchar	bcdDev[2];
-	uchar	iManufacturer;
-	uchar	iProduct;
-	uchar	iSerialNumber;
-	uchar	bNumConfigurations;
-};
-
-struct DConf
-{
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	wTotalLength[2];
-	uchar	bNumInterfaces;
-	uchar	bConfigurationValue;
-	uchar	iConfiguration;
-	uchar	bmAttributes;
-	uchar	MaxPower;
-};
-
-struct DIface
-{
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	bInterfaceNumber;
-	uchar	bAlternateSetting;
-	uchar	bNumEndpoints;
-	uchar	bInterfaceClass;
-	uchar	bInterfaceSubClass;
-	uchar	bInterfaceProtocol;
-	uchar	iInterface;
-};
-
-struct DEp
-{
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	bEndpointAddress;
-	uchar	bmAttributes;
-	uchar	wMaxPacketSize[2];
-	uchar	bInterval;
-};
-
-#define Class(csp)	((csp) & 0xff)
-#define Subclass(csp)	(((csp)>>8) & 0xff)
-#define Proto(csp)	(((csp)>>16) & 0xff)
-#define CSP(c, s, p)	((c) | (s)<<8 | (p)<<16)
-
-#define	GET2(p)		(((p)[1] & 0xFF)<<8 | ((p)[0] & 0xFF))
-#define	PUT2(p,v)	{(p)[0] = (v); (p)[1] = (v)>>8;}
-#define	GET4(p)		(((p)[3]&0xFF)<<24 | ((p)[2]&0xFF)<<16 | \
-			 ((p)[1]&0xFF)<<8  | ((p)[0]&0xFF))
-#define	PUT4(p,v)	{(p)[0] = (v);     (p)[1] = (v)>>8; \
-			 (p)[2] = (v)>>16; (p)[3] = (v)>>24;}
-
-#define dprint if(usbdebug)fprint
-#define ddprint if(usbdebug > 1)fprint
-
-#pragma	varargck	type  "U"	Dev*
-#pragma	varargck	argpos	devctl	2
-
-int	Ufmt(Fmt *f);
-char*	classname(int c);
-void	closedev(Dev *d);
-int	configdev(Dev *d);
-int	devctl(Dev *dev, char *fmt, ...);
-void*	emallocz(ulong size, int zero);
-char*	estrdup(char *s);
-int	matchdevcsp(char *info, void *a);
-int	finddevs(int (*matchf)(char*,void*), void *farg, char** dirs, int ndirs);
-char*	hexstr(void *a, int n);
-int	loaddevconf(Dev *d, int n);
-int	loaddevdesc(Dev *d);
-char*	loaddevstr(Dev *d, int sid);
-Dev*	opendev(char *fn);
-int	opendevdata(Dev *d, int mode);
-Dev*	openep(Dev *d, int id);
-int	parseconf(Usbdev *d, Conf *c, uchar *b, int n);
-int	parsedesc(Usbdev *d, Conf *c, uchar *b, int n);
-int	parsedev(Dev *xd, uchar *b, int n);
-void	startdevs(char *args, char *argv[], int argc, int (*mf)(char*,void*), void*ma, int (*df)(Dev*,int,char**));
-int	unstall(Dev *dev, Dev *ep, int dir);
-int	usbcmd(Dev *d, int type, int req, int value, int index, uchar *data, int count);
-
-
-extern int usbdebug;	/* more messages for bigger values */
-
-
--- a/sys/src/cmd/usb/lib/usbfs.h
+++ /dev/null
@@ -1,61 +1,0 @@
-typedef struct Usbfs Usbfs;
-typedef struct Fid Fid;
-
-enum
-{
-	Hdrsize	= 128,		/* plenty of room for headers */
-	Msgsize	= 8216,		/* our preferred iounit (also devmnt's) */
-	Bufsize	= Hdrsize + Msgsize,
-	Namesz = 40,
-	Errmax = 128,
-	ONONE = ~0,		/* omode in Fid when not open */
-};
-
-struct Fid
-{
-	int	fid;
-	Qid	qid;
-	int	omode;
-	Fid*	next;
-	void*	aux;
-};
-
-struct Usbfs
-{
-	char	name[Namesz];
-	uvlong	qid;
-	Dev*	dev;
-	void*	aux;
-
-	int	(*walk)(Usbfs *fs, Fid *f, char *name);
-	void	(*clone)(Usbfs *fs, Fid *of, Fid *nf);
-	void	(*clunk)(Usbfs *fs, Fid *f);
-	int	(*open)(Usbfs *fs, Fid *f, int mode);
-	long	(*read)(Usbfs *fs, Fid *f, void *data, long count, vlong offset);
-	long	(*write)(Usbfs *fs, Fid*f, void *data, long count, vlong offset);
-	int	(*stat)(Usbfs *fs, Qid q, Dir *d);
-	void	(*end)(Usbfs *fs);
-};
-
-typedef int (*Dirgen)(Usbfs*, Qid, int, Dir*, void*);
-
-long	usbreadbuf(void *data, long count, vlong offset, void *buf, long n);
-void	usbfsadd(Usbfs *dfs);
-void	usbfsdel(Usbfs *dfs);
-int	usbdirread(Usbfs*f, Qid q, char *data, long cnt, vlong off, Dirgen gen, void *arg);
-void	usbfsinit(char* srv, char *mnt, Usbfs *f, int flag);
-
-void	usbfsdirdump(void);
-
-extern char Enotfound[];
-extern char Etoosmall[];
-extern char Eio[];
-extern char Eperm[];
-extern char Ebadcall[];
-extern char Ebadfid[];
-extern char Einuse[];
-extern char Eisopen[];
-extern char Ebadctl[];
-
-extern Usbfs usbdirfs;
-extern int usbfsdebug;
--- a/sys/src/cmd/usb/mkfile
+++ /dev/null
@@ -1,38 +1,0 @@
-</$objtype/mkfile
-
-# order matters here.  build lib first and usbd last.
-DIRS=\
-	lib\
-	audio\
-	disk\
-	ether\
-	kb\
-	print\
-	serial\
-	usbd\
-
-UPDATE=\
-	mkfile\
-
-default:V: all
-
-none:VQ:
-	echo mk all, install, installall, safeinstall, safeinstallall, clean, nuke, or update
-
-all clean nuke:VQ:
-	for (i in $DIRS) @{
-		cd $i && echo $i: && mk $target
-	}
-
-install installall safeinstall safeinstallall:V:
-	for (i in $DIRS) @{
-		cd $i && mk $target
-	}
-	cp probe /$objtype/bin/usb/probe
-
-update:V:
-	update $UPDATEFLAGS $UPDATE
-	for (i in $DIRS) @{
-		echo update $i
-		cd $i && mk 'UPDATEFLAGS='$"UPDATEFLAGS update
-	}
--- a/sys/src/cmd/usb/print/main.c
+++ /dev/null
@@ -1,51 +1,0 @@
-/*
- * usb/print - usb printer
- */
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-
-enum
-{
-	Arglen = 80,
-};
-
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-d] [-N nb] [dev...]\n", argv0);
-	threadexitsall("usage");
-}
-
-static int csps[] = { 0x020107, 0 };
-
-extern int printmain(Dev*, int, char**);
-
-void
-threadmain(int argc, char **argv)
-{
-	char args[Arglen];
-	char *as;
-	char *ae;
-
-	quotefmtinstall();
-	ae = args+sizeof(args);
-	as = seprint(args, ae, "print");
-	ARGBEGIN{
-	case 'd':
-		usbdebug++;
-		break;
-	case 'N':
-		as = seprint(as, ae, " -N %s", EARGF(usage()));
-		break;
-	default:
-		usage();
-	}ARGEND
-
-	rfork(RFNOTEG);
-	threadsetgrp(threadid());
-	fmtinstall('U', Ufmt);
-	startdevs(args, argv, argc, matchdevcsp, csps, printmain);
-	threadexits(nil);
-}
--- a/sys/src/cmd/usb/print/mkfile
+++ /dev/null
@@ -1,22 +1,0 @@
-</$objtype/mkfile
-
-TARG=print
-LIB=../lib/usb.a$O
-
-HFILES=\
-	../lib/usb.h\
-	../lib/usbfs.h\
-
-OFILES=\
-	main.$O\
-	print.$O\
-
-BIN=/$objtype/bin/usb
-</sys/src/cmd/mkone
-CFLAGS=-I../lib $CFLAGS
-
-$LIB:
-	cd ../lib
-	mk install
-	mk clean
-
--- a/sys/src/cmd/usb/print/print.c
+++ /dev/null
@@ -1,91 +1,0 @@
-/*
- * usb/print - usb printer file server
- * BUG: Assumes the printer will be always connected and
- * not hot-plugged. (Otherwise should stay running and
- * listen to errors to keep the device there as long as it has
- * not failed). Also, this is untested and done ad-hoc to
- * replace the print script.
- */
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-
-enum
-{
-	Qdir = 0,
-	Qctl,
-	Qraw,
-	Qdata,
-	Qmax,
-};
-
-int
-findendpoints(Dev *dev, int devid)
-{
-	Ep *ep;
-	Dev *d;
-	Usbdev *ud;
-	int i, epout;
-
-	epout = -1;
-	ud = dev->usb;
-	for(i = 0; i < nelem(ud->ep); i++){
-		if((ep = ud->ep[i]) == nil)
-			break;
-		if(ep->iface->csp != 0x020107)
-			continue;
-		if(ep->type == Ebulk && (ep->dir == Eboth || ep->dir == Eout))
-			if(epout == -1)
-				epout = ep->id;
-	}
-	dprint(2, "print: ep ids: out %d\n", epout);
-	if(epout == -1)
-		return -1;
-	d = openep(dev, epout);
-	if(d == nil){
-		fprint(2, "print: openep %d: %r\n", epout);
-		return -1;
-	}
-	opendevdata(d, OWRITE);
-	if(d->dfd < 0){
-		fprint(2, "print: open i/o ep data: %r\n");
-		closedev(d);
-		return -1;
-	}
-	dprint(2, "print: ep out %s\n", d->dir);
-	if(usbdebug > 1)
-		devctl(d, "debug 1");
-	devctl(d, "name lp%d", devid);
-	return 0;
-}
-
-static int
-usage(void)
-{
-	werrstr("usage: usb/print [-N id]");
-	return -1;
-}
-
-int
-printmain(Dev *dev, int argc, char **argv)
-{
-	int devid;
-
-	devid = dev->id;
-	ARGBEGIN{
-	case 'N':
-		devid = atoi(EARGF(usage()));
-		break;
-	default:
-		return usage();
-	}ARGEND
-	if(argc != 0)
-		return usage();
-
-	if(findendpoints(dev, devid) < 0){
-		werrstr("print: endpoints not found");
-		return -1;
-	}
-	return 0;
-}
--- a/sys/src/cmd/usb/probe
+++ /dev/null
@@ -1,26 +1,0 @@
-#!/bin/rc
-# usb/probe [-h] - list all usb devices, including hubs
-rfork e
-test -e /dev/usb || bind -a '#u' /dev || {
-	echo no '#u/usb' >[1=2]
-	exit nousb
-}
-
-filter = cat
-if (~ $1 -h)
-	filter = (grep -v ' (root)?hub ')
-
-awk 'BEGIN	{ ep = "" }
-$1 ~ /ep[0-9]+\.0/ && $2 == "enabled" && $NF ~ /busy|idle/ {
-	ep=$1
-	next
-}
-{
-	if(ep != ""){
-		printf "%s %s\n", ep, $0
-		ep = ""
-	}
-}
-' /dev/usb/ctl | $filter
-
-exit ''
--- a/sys/src/cmd/usb/serial/ftdi.c
+++ /dev/null
@@ -1,961 +1,0 @@
-/* Future Technology Devices International serial ports */
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "serial.h"
-#include "ftdi.h"
-
-/*
- * BUG: This keeps growing, there has to be a better way, but without
- * devices to try it...  We can probably simply look for FTDI in the
- * string, or use regular expressions somehow.
- */
-Cinfo ftinfo[] = {
-	{ FTVid, FTACTZWAVEDid },
-	{ FTSheevaVid, FTSheevaDid },
-	{ FTVid, FTOpenRDUltDid},
-	{ FTVid, FTIRTRANSDid },
-	{ FTVid, FTIPLUSDid },
-	{ FTVid, FTSIODid },
-	{ FTVid, FT8U232AMDid },
-	{ FTVid, FT8U232AMALTDid },
-	{ FTVid, FT8U2232CDid },
-	{ FTVid, FTRELAISDid },
-	{ INTERBIOMVid, INTERBIOMIOBRDDid },
-	{ INTERBIOMVid, INTERBIOMMINIIOBRDDid },
-	{ FTVid, FTXF632Did },
-	{ FTVid, FTXF634Did },
-	{ FTVid, FTXF547Did },
-	{ FTVid, FTXF633Did },
-	{ FTVid, FTXF631Did },
-	{ FTVid, FTXF635Did },
-	{ FTVid, FTXF640Did },
-	{ FTVid, FTXF642Did },
-	{ FTVid, FTDSS20Did },
-	{ FTNFRICVid, FTNFRICDid },
-	{ FTVid, FTVNHCPCUSBDDid },
-	{ FTVid, FTMTXORB0Did },
-	{ FTVid, FTMTXORB1Did },
-	{ FTVid, FTMTXORB2Did },
-	{ FTVid, FTMTXORB3Did },
-	{ FTVid, FTMTXORB4Did },
-	{ FTVid, FTMTXORB5Did },
-	{ FTVid, FTMTXORB6Did },
-	{ FTVid, FTPERLEULTRAPORTDid },
-	{ FTVid, FTPIEGROUPDid },
-	{ SEALEVELVid, SEALEVEL2101Did },
-	{ SEALEVELVid, SEALEVEL2102Did },
-	{ SEALEVELVid, SEALEVEL2103Did },
-	{ SEALEVELVid, SEALEVEL2104Did },
-	{ SEALEVELVid, SEALEVEL22011Did },
-	{ SEALEVELVid, SEALEVEL22012Did },
-	{ SEALEVELVid, SEALEVEL22021Did },
-	{ SEALEVELVid, SEALEVEL22022Did },
-	{ SEALEVELVid, SEALEVEL22031Did },
-	{ SEALEVELVid, SEALEVEL22032Did },
-	{ SEALEVELVid, SEALEVEL24011Did },
-	{ SEALEVELVid, SEALEVEL24012Did },
-	{ SEALEVELVid, SEALEVEL24013Did },
-	{ SEALEVELVid, SEALEVEL24014Did },
-	{ SEALEVELVid, SEALEVEL24021Did },
-	{ SEALEVELVid, SEALEVEL24022Did },
-	{ SEALEVELVid, SEALEVEL24023Did },
-	{ SEALEVELVid, SEALEVEL24024Did },
-	{ SEALEVELVid, SEALEVEL24031Did },
-	{ SEALEVELVid, SEALEVEL24032Did },
-	{ SEALEVELVid, SEALEVEL24033Did },
-	{ SEALEVELVid, SEALEVEL24034Did },
-	{ SEALEVELVid, SEALEVEL28011Did },
-	{ SEALEVELVid, SEALEVEL28012Did },
-	{ SEALEVELVid, SEALEVEL28013Did },
-	{ SEALEVELVid, SEALEVEL28014Did },
-	{ SEALEVELVid, SEALEVEL28015Did },
-	{ SEALEVELVid, SEALEVEL28016Did },
-	{ SEALEVELVid, SEALEVEL28017Did },
-	{ SEALEVELVid, SEALEVEL28018Did },
-	{ SEALEVELVid, SEALEVEL28021Did },
-	{ SEALEVELVid, SEALEVEL28022Did },
-	{ SEALEVELVid, SEALEVEL28023Did },
-	{ SEALEVELVid, SEALEVEL28024Did },
-	{ SEALEVELVid, SEALEVEL28025Did },
-	{ SEALEVELVid, SEALEVEL28026Did },
-	{ SEALEVELVid, SEALEVEL28027Did },
-	{ SEALEVELVid, SEALEVEL28028Did },
-	{ SEALEVELVid, SEALEVEL28031Did },
-	{ SEALEVELVid, SEALEVEL28032Did },
-	{ SEALEVELVid, SEALEVEL28033Did },
-	{ SEALEVELVid, SEALEVEL28034Did },
-	{ SEALEVELVid, SEALEVEL28035Did },
-	{ SEALEVELVid, SEALEVEL28036Did },
-	{ SEALEVELVid, SEALEVEL28037Did },
-	{ SEALEVELVid, SEALEVEL28038Did },
-	{ IDTECHVid, IDTECHIDT1221UDid },
-	{ OCTVid, OCTUS101Did },
-	{ FTVid, FTHETIRA1Did }, /* special quirk div = 240 baud = B38400 rtscts = 1 */
-	{ FTVid, FTUSBUIRTDid }, /* special quirk div = 77, baud = B38400 */
-	{ FTVid, PROTEGOSPECIAL1 },
-	{ FTVid, PROTEGOR2X0 },
-	{ FTVid, PROTEGOSPECIAL3 },
-	{ FTVid, PROTEGOSPECIAL4 },
-	{ FTVid, FTGUDEADSE808Did },
-	{ FTVid, FTGUDEADSE809Did },
-	{ FTVid, FTGUDEADSE80ADid },
-	{ FTVid, FTGUDEADSE80BDid },
-	{ FTVid, FTGUDEADSE80CDid },
-	{ FTVid, FTGUDEADSE80DDid },
-	{ FTVid, FTGUDEADSE80EDid },
-	{ FTVid, FTGUDEADSE80FDid },
-	{ FTVid, FTGUDEADSE888Did },
-	{ FTVid, FTGUDEADSE889Did },
-	{ FTVid, FTGUDEADSE88ADid },
-	{ FTVid, FTGUDEADSE88BDid },
-	{ FTVid, FTGUDEADSE88CDid },
-	{ FTVid, FTGUDEADSE88DDid },
-	{ FTVid, FTGUDEADSE88EDid },
-	{ FTVid, FTGUDEADSE88FDid },
-	{ FTVid, FTELVUO100Did },
-	{ FTVid, FTELVUM100Did },
-	{ FTVid, FTELVUR100Did },
-	{ FTVid, FTELVALC8500Did },
-	{ FTVid, FTPYRAMIDDid },
-	{ FTVid, FTELVFHZ1000PCDid },
-	{ FTVid, FTELVCLI7000Did },
-	{ FTVid, FTELVPPS7330Did },
-	{ FTVid, FTELVTFM100Did },
-	{ FTVid, FTELVUDF77Did },
-	{ FTVid, FTELVUIO88Did },
-	{ FTVid, FTELVUAD8Did },
-	{ FTVid, FTELVUDA7Did },
-	{ FTVid, FTELVUSI2Did },
-	{ FTVid, FTELVT1100Did },
-	{ FTVid, FTELVPCD200Did },
-	{ FTVid, FTELVULA200Did },
-	{ FTVid, FTELVCSI8Did },
-	{ FTVid, FTELVEM1000DLDid },
-	{ FTVid, FTELVPCK100Did },
-	{ FTVid, FTELVRFP500Did },
-	{ FTVid, FTELVFS20SIGDid },
-	{ FTVid, FTELVWS300PCDid },
-	{ FTVid, FTELVFHZ1300PCDid },
-	{ FTVid, FTELVWS500Did },
-	{ FTVid, LINXSDMUSBQSSDid },
-	{ FTVid, LINXMASTERDEVEL2Did },
-	{ FTVid, LINXFUTURE0Did },
-	{ FTVid, LINXFUTURE1Did },
-	{ FTVid, LINXFUTURE2Did },
-	{ FTVid, FTCCSICDU200Did },
-	{ FTVid, FTCCSICDU401Did },
-	{ FTVid, INSIDEACCESSO },
-	{ INTREDidVid, INTREDidVALUECANDid },
-	{ INTREDidVid, INTREDidNEOVIDid },
-	{ FALCOMVid, FALCOMTWISTDid },
-	{ FALCOMVid, FALCOMSAMBADid },
-	{ FTVid, FTSUUNTOSPORTSDid },
-	{ FTVid, FTRMCANVIEWDid },
-	{ BANDBVid, BANDBUSOTL4Did },
-	{ BANDBVid, BANDBUSTL4Did },
-	{ BANDBVid, BANDBUSO9ML2Did },
-	{ FTVid, EVERECOPROCDSDid },
-	{ FTVid, FT4NGALAXYDE0Did },
-	{ FTVid, FT4NGALAXYDE1Did },
-	{ FTVid, FT4NGALAXYDE2Did },
-	{ FTVid, XSENSCONVERTER0Did },
-	{ FTVid, XSENSCONVERTER1Did },
-	{ FTVid, XSENSCONVERTER2Did },
-	{ FTVid, XSENSCONVERTER3Did },
-	{ FTVid, XSENSCONVERTER4Did },
-	{ FTVid, XSENSCONVERTER5Did },
-	{ FTVid, XSENSCONVERTER6Did },
-	{ FTVid, XSENSCONVERTER7Did },
-	{ MOBILITYVid, MOBILITYUSBSERIALDid },
-	{ FTVid, FTACTIVEROBOTSDid },
-	{ FTVid, FTMHAMKWDid },
-	{ FTVid, FTMHAMYSDid },
-	{ FTVid, FTMHAMY6Did },
-	{ FTVid, FTMHAMY8Did },
-	{ FTVid, FTMHAMICDid },
-	{ FTVid, FTMHAMDB9Did },
-	{ FTVid, FTMHAMRS232Did },
-	{ FTVid, FTMHAMY9Did },
-	{ FTVid, FTTERATRONIKVCPDid },
-	{ FTVid, FTTERATRONIKD2XXDid },
-	{ EVOLUTIONVid, EVOLUTIONER1Did },
-	{ FTVid, FTARTEMISDid },
-	{ FTVid, FTATIKATK16Did },
-	{ FTVid, FTATIKATK16CDid },
-	{ FTVid, FTATIKATK16HRDid },
-	{ FTVid, FTATIKATK16HRCDid },
-	{ KOBILVid, KOBILCONVB1Did },
-	{ KOBILVid, KOBILCONVKAANDid },
-	{ POSIFLEXVid, POSIFLEXPP7000Did },
-	{ FTVid, FTTTUSBDid },
-	{ FTVid, FTECLOCOM1WIREDid },
-	{ FTVid, FTWESTREXMODEL777Did },
-	{ FTVid, FTWESTREXMODEL8900FDid },
-	{ FTVid, FTPCDJDAC2Did },
-	{ FTVid, FTRRCIRKITSLOCOBUFFERDid },
-	{ FTVid, FTASKRDR400Did },
-	{ ICOMID1Vid, ICOMID1Did },
-	{ PAPOUCHVid, PAPOUCHTMUDid },
-	{ FTVid, FTACGHFDUALDid },
-	{ FT8U232AMDid, FT4232HDid },
-	{ 0,	0 },
-};
-
-enum {
-	Packsz		= 64,		/* default size */
-	Maxpacksz	= 512,
-	Bufsiz		= 4 * 1024,
-};
-
-static int
-ftdiread(Serialport *p, int index, int req, uchar *buf, int len)
-{
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-	if(req != FTGETE2READ)
-		index |= p->interfc + 1;
-	dsprint(2, "serial: ftdiread %#p [%d] req: %#x val: %#x idx:%d buf:%p len:%d\n",
-		p, p->interfc, req, 0, index, buf, len);
-	res = usbcmd(ser->dev,  Rd2h | Rftdireq | Rdev, req, 0, index, buf, len);
-	dsprint(2, "serial: ftdiread res:%d\n", res);
-	return res;
-}
-
-static int
-ftdiwrite(Serialport *p, int val, int index, int req)
-{
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-	if(req != FTGETE2READ || req != FTSETE2ERASE || req != FTSETBAUDRATE)
-		index |= p->interfc + 1;
-	dsprint(2, "serial: ftdiwrite %#p [%d] req: %#x val: %#x idx:%d\n",
-		p, p->interfc, req, val, index);
-	res = usbcmd(ser->dev, Rh2d | Rftdireq | Rdev, req, val, index, nil, 0);
-	dsprint(2, "serial: ftdiwrite res:%d\n", res);
-	return res;
-}
-
-static int
-ftmodemctl(Serialport *p, int set)
-{
-	if(set == 0){
-		p->mctl = 0;
-		ftdiwrite(p, 0, 0, FTSETMODEMCTRL);
-		return 0;
-	}
-	p->mctl = 1;
-	ftdiwrite(p, 0, FTRTSCTSHS, FTSETFLOWCTRL);
-	return 0;
-}
-
-static ushort
-ft232ambaudbase2div(int baud, int base)
-{
-	int divisor3;
-	ushort divisor;
-
-	divisor3 = (base / 2) / baud;
-	if((divisor3 & 7) == 7)
-		divisor3++;			/* round x.7/8 up to x+1 */
-	divisor = divisor3 >> 3;
-	divisor3 &= 7;
-
-	if(divisor3 == 1)
-		divisor |= 0xc000;		/*	0.125 */
-	else if(divisor3 >= 4)
-		divisor |= 0x4000;		/*	0.5	*/
-	else if(divisor3 != 0)
-		divisor |= 0x8000;		/*	0.25	*/
-	if( divisor == 1)
-		divisor = 0;		/* special case for maximum baud rate */
-	return divisor;
-}
-
-enum{
-	ClockNew	= 48000000,
-	ClockOld	= 12000000 / 16,
-	HetiraDiv	= 240,
-	UirtDiv		= 77,
-};
-
-static ushort
-ft232ambaud2div(int baud)
-{
-	return ft232ambaudbase2div(baud, ClockNew);
-}
-
-static ulong divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7};
-
-static ulong
-ft232bmbaudbase2div(int baud, int base)
-{
-	int divisor3;
-	u32int divisor;
-
-	divisor3 = (base / 2) / baud;
-	divisor = divisor3 >> 3 | divfrac[divisor3 & 7] << 14;
-
-	/* Deal with special cases for highest baud rates. */
-	if( divisor == 1)
-		divisor = 0;			/* 1.0 */
-	else if( divisor == 0x4001)
-		divisor = 1;			/* 1.5 */
-	return divisor;
-}
-
-static ulong
-ft232bmbaud2div (int baud)
-{
-	return ft232bmbaudbase2div (baud, ClockNew);
-}
-
-static int
-customdiv(Serial *ser)
-{
-	if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTHETIRA1Did)
-		return HetiraDiv;
-	else if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTUSBUIRTDid)
-		return UirtDiv;
-
-	fprint(2, "serial: weird custom divisor\n");
-	return 0;		/* shouldn't happen, break as much as I can */
-}
-
-static ulong
-ftbaudcalcdiv(Serial *ser, int baud)
-{
-	int cusdiv;
-	ulong divval;
-
-	if(baud == 38400 && (cusdiv = customdiv(ser)) != 0)
-		baud = ser->baudbase / cusdiv;
-
-	if(baud == 0)
-		baud = 9600;
-
-	switch(ser->type) {
-	case SIO:
-		switch(baud) {
-		case 300:
-			divval = FTb300;
-			break;
-		case 600:
-			divval = FTb600;
-			break;
-		case 1200:
-			divval = FTb1200;
-			break;
-		case 2400:
-			divval = FTb2400;
-			break;
-		case 4800:
-			divval = FTb4800;
-			break;
-		case 9600:
-			divval = FTb9600;
-			break;
-		case 19200:
-			divval = FTb19200;
-			break;
-		case 38400:
-			divval = FTb38400;
-			break;
-		case 57600:
-			divval = FTb57600;
-			break;
-		case 115200:
-			divval = FTb115200;
-			break;
-		default:
-			divval = FTb9600;
-			break;
-		}
-		break;
-	case FT8U232AM:
-		if(baud <= 3000000)
-			divval = ft232ambaud2div(baud);
-		else
-			divval = ft232ambaud2div(9600);
-		break;
-	case FT232BM:
-	case FT2232C:
-	case FTKINDR:
-	case FT2232H:
-	case FT4232H:
-		if(baud <= 3000000)
-			divval = ft232bmbaud2div(baud);
-		else
-			divval = ft232bmbaud2div(9600);
-		break;
-	default:
-		divval = ft232bmbaud2div(9600);
-		break;
-	}
-	return divval;
-}
-
-static int
-ftsetparam(Serialport *p)
-{
-	int res;
-	ushort val;
-	ulong bauddiv;
-
-	val = 0;
-	if(p->stop == 1)
-		val |= FTSETDATASTOPBITS1;
-	else if(p->stop == 2)
-		val |= FTSETDATASTOPBITS2;
-	else if(p->stop == 15)
-		val |= FTSETDATASTOPBITS15;
-	switch(p->parity){
-	case 0:
-		val |= FTSETDATAParNONE;
-		break;
-	case 1:
-		val |= FTSETDATAParODD;
-		break;
-	case 2:
-		val |= FTSETDATAParEVEN;
-		break;
-	case 3:
-		val |= FTSETDATAParMARK;
-		break;
-	case 4:
-		val |= FTSETDATAParSPACE;
-		break;
-	};
-
-	dsprint(2, "serial: setparam\n");
-
-	res = ftdiwrite(p, val, 0, FTSETDATA);
-	if(res < 0)
-		return res;
-
-	res = ftmodemctl(p, p->mctl);
-	if(res < 0)
-		return res;
-
-	bauddiv = ftbaudcalcdiv(p->s, p->baud);
-	res = ftdiwrite(p, bauddiv, (bauddiv>>16) & 1, FTSETBAUDRATE);
-
-	dsprint(2, "serial: setparam res: %d\n", res);
-	return res;
-}
-
-static int
-hasjtag(Usbdev *udev)
-{
-	/* no string, for now, by default we detect no jtag */
-	if(udev->product != nil && cistrstr(udev->product, "jtag") != nil)
-		return 1;
-	return 0;
-}
-
-/* ser locked */
-static void
-ftgettype(Serial *ser)
-{
-	int i, outhdrsz, dno, pksz;
-	ulong baudbase;
-	Conf *cnf;
-
-	pksz = Packsz;
-	/* Assume it is not the original SIO device for now. */
-	baudbase = ClockNew / 2;
-	outhdrsz = 0;
-	dno = ser->dev->usb->dno;
-	cnf = ser->dev->usb->conf[0];
-	ser->nifcs = 0;
-	for(i = 0; i < Niface; i++)
-		if(cnf->iface[i] != nil)
-			ser->nifcs++;
-	if(ser->nifcs > 1) {
-		/*
-		 * Multiple interfaces.  default assume FT2232C,
-		 */
-		if(dno == 0x500)
-			ser->type = FT2232C;
-		else if(dno == 0x600)
-			ser->type = FTKINDR;
-		else if(dno == 0x700){
-			ser->type = FT2232H;
-			pksz = Maxpacksz;
-		} else if(dno == 0x800){
-			ser->type = FT4232H;
-			pksz = Maxpacksz;
-		} else
-			ser->type = FT2232C;
-
-		if(hasjtag(ser->dev->usb))
-			ser->jtag = 0;
-
-		/*
-		 * BM-type devices have a bug where dno gets set
-		 * to 0x200 when serial is 0.
-		 */
-		if(dno < 0x500)
-			fprint(2, "serial: warning: dno %d too low for "
-				"multi-interface device\n", dno);
-	} else if(dno < 0x200) {
-		/* Old device.  Assume it is the original SIO. */
-		ser->type = SIO;
-		baudbase = ClockOld/16;
-		outhdrsz = 1;
-	} else if(dno < 0x400)
-		/*
-		 * Assume its an FT8U232AM (or FT8U245AM)
-		 * (It might be a BM because of the iSerialNumber bug,
-		 * but it will still work as an AM device.)
-		 */
-		ser->type = FT8U232AM;
-	else			/* Assume it is an FT232BM (or FT245BM) */
-		ser->type = FT232BM;
-
-	ser->maxrtrans = ser->maxwtrans = pksz;
-	ser->baudbase = baudbase;
-	ser->outhdrsz = outhdrsz;
-	ser->inhdrsz = 2;
-
-	dsprint (2, "serial: detected type: %#x\n", ser->type);
-}
-
-int
-ftmatch(Serial *ser, char *info)
-{
-	Cinfo *ip;
-	char buf[50];
-
-	for(ip = ftinfo; ip->vid != 0; ip++){
-		snprint(buf, sizeof buf, "vid %#06x did %#06x", ip->vid, ip->did);
-		dsprint(2, "serial: %s %s\n", buf, info);
-		if(strstr(info, buf) != nil){
-			if(ser != nil){
-				qlock(ser);
-				ftgettype(ser);
-				qunlock(ser);
-			}
-			return 0;
-		}
-	}
-	return -1;
-}
-
-static int
-ftuseinhdr(Serialport *p, uchar *b)
-{
-	if(b[0] & FTICTS)
-		p->cts = 1;
-	else
-		p->cts = 0;
-	if(b[0] & FTIDSR)
-		p->dsr = 1;
-	else
-		p->dsr = 0;
-	if(b[0] & FTIRI)
-		p->ring = 1;
-	else
-		p->ring = 0;
-	if(b[0] & FTIRLSD)
-		p->rlsd = 1;
-	else
-		p->rlsd = 0;
-
-	if(b[1] & FTIOE)
-		p->novererr++;
-	if(b[1] & FTIPE)
-		p->nparityerr++;
-	if(b[1] & FTIFE)
-		p->nframeerr++;
-	if(b[1] & FTIBI)
-		p->nbreakerr++;
-	return 0;
-}
-
-static int
-ftsetouthdr(Serialport *p, uchar *b, int len)
-{
-	if(p->s->outhdrsz != 0)
-		b[0] = FTOPORT | (FTOLENMSK & len);
-	return p->s->outhdrsz;
-}
-
-static int
-wait4data(Serialport *p, uchar *data, int count)
-{
-	int d;
-	Serial *ser;
-
-	ser = p->s;
-
-	qunlock(ser);
-	d = sendul(p->w4data, 1);
-	qlock(ser);
-	if(d <= 0)
-		return -1;
-	if(p->ndata >= count)
-		p->ndata -= count;
-	else{
-		count = p->ndata;
-		p->ndata = 0;
-	}
-	assert(count >= 0);
-	assert(p->ndata >= 0);
-	memmove(data, p->data, count);
-	if(p->ndata != 0)
-		memmove(p->data, p->data+count, p->ndata);
-
-	recvul(p->gotdata);
-	return count;
-}
-
-static int
-wait4write(Serialport *p, uchar *data, int count)
-{
-	int off, fd;
-	uchar *b;
-	Serial *ser;
-
-	ser = p->s;
-
-	b = emallocz(count+ser->outhdrsz, 1);
-	off = ftsetouthdr(p, b, count);
-	memmove(b+off, data, count);
-
-	fd = p->epout->dfd;
-	qunlock(ser);
-	count = write(fd, b, count+off);
-	qlock(ser);
-	free(b);
-	return count;
-}
-
-typedef struct Packser Packser;
-struct Packser{
-	int	nb;
-	uchar	b[Bufsiz];
-};
-
-typedef struct Areader Areader;
-struct Areader{
-	Serialport	*p;
-	Channel	*c;
-};
-
-static void
-shutdownchan(Channel *c)
-{
-	Packser *bp;
-
-	while((bp=nbrecvp(c)) != nil)
-		free(bp);
-	chanfree(c);
-}
-
-int
-cpdata(Serial *ser, Serialport *port, uchar *out, uchar *in, int sz)
-{
-	int i, ncp, ntotcp, pksz;
-
-	pksz = ser->maxrtrans;
-	ntotcp = 0;
-
-	for(i = 0; i < sz; i+= pksz){
-		ftuseinhdr(port, in + i);
-		if(sz - i > pksz)
-			ncp = pksz - ser->inhdrsz;
-		else
-			ncp = sz - i - ser->inhdrsz;
-		memmove(out, in + i + ser->inhdrsz, ncp);
-		out += ncp;
-		ntotcp += ncp;
-	}
-	return ntotcp;
-}
-
-static void
-epreader(void *u)
-{
-	int dfd, rcount, cl, ntries, recov;
-	char err[40];
-	Areader *a;
-	Channel *c;
-	Packser *pk;
-	Serial *ser;
-	Serialport *p;
-
-	threadsetname("epreader proc");
-	a = u;
-	p = a->p;
-	ser = p->s;
-	c = a->c;
-	free(a);
-
-	qlock(ser);	/* this makes the reader wait end of initialization too */
-	dfd = p->epin->dfd;
-	qunlock(ser);
-
-	ntries = 0;
-	pk = nil;
-	do {
-		if (pk == nil)
-			pk = emallocz(sizeof(Packser), 1);
-Eagain:
-		rcount = read(dfd, pk->b, sizeof pk->b);
-		if(serialdebug > 5)
-			dsprint(2, "%d %#ux%#ux ", rcount, p->data[0],
-				p->data[1]);
-
-		if(rcount < 0){
-			if(ntries++ > 100)
-				break;
-			qlock(ser);
-			recov = serialrecover(ser, p, nil, "epreader: bulkin error");
-			qunlock(ser);
-			if(recov >= 0)
-				goto Eagain;
-		}
-		if(rcount == 0)
-			continue;
-		if(rcount >= ser->inhdrsz){
-			rcount = cpdata(ser, p, pk->b, pk->b, rcount);
-			if(rcount != 0){
-				pk->nb = rcount;
-				cl = sendp(c, pk);
-				if(cl < 0){
-					/*
-					 * if it was a time-out, I don't want
-					 * to give back an error.
-					 */
-					rcount = 0;
-					break;
-				}
-			}else
-				free(pk);
-			qlock(ser);
-			ser->recover = 0;
-			qunlock(ser);
-			ntries = 0;
-			pk = nil;
-		}
-	} while(rcount >= 0 || (rcount < 0 && strstr(err, "timed out") != nil));
-
-	if(rcount < 0)
-		fprint(2, "%s: error reading %s: %r\n", argv0, p->fs.name);
-	free(pk);
-	nbsendp(c, nil);
-	if(p->w4data != nil)
-		chanclose(p->w4data);
-	if(p->gotdata != nil)
-		chanclose(p->gotdata);
-	devctl(ser->dev, "detach");
-	closedev(ser->dev);
-	usbfsdel(&p->fs);
-}
-
-static void
-statusreader(void *u)
-{
-	Areader *a;
-	Channel *c;
-	Packser *pk;
-	Serialport *p;
-	Serial *ser;
-	int cl;
-
-	p = u;
-	ser = p->s;
-	threadsetname("statusreader thread");
-	/* big buffering, fewer bytes lost */
-	c = chancreate(sizeof(Packser *), 128);
-	a = emallocz(sizeof(Areader), 1);
-	a->p = p;
-	a->c = c;
-	incref(ser->dev);
-	proccreate(epreader, a, 16*1024);
-
-	while((pk = recvp(c)) != nil){
-		memmove(p->data, pk->b, pk->nb);
-		p->ndata = pk->nb;
-		free(pk);
-		dsprint(2, "serial %p: status reader %d \n", p, p->ndata);
-		/* consume it all */
-		while(p->ndata != 0){
-			dsprint(2, "serial %p: status reader to consume: %d\n",
-				p, p->ndata);
-			cl = recvul(p->w4data);
-			if(cl  < 0)
-				break;
-			cl = sendul(p->gotdata, 1);
-			if(cl  < 0)
-				break;
-		}
-	}
-
-	shutdownchan(c);
-	devctl(ser->dev, "detach");
-	closedev(ser->dev);
-	usbfsdel(&p->fs);
-}
-
-static int
-ftreset(Serial *ser, Serialport *p)
-{
-	int i;
-
-	if(p != nil){
-		ftdiwrite(p, FTRESETCTLVAL, 0, FTRESET);
-		return 0;
-	}
-	p = ser->p;
-	for(i = 0; i < Maxifc; i++)
-		if(p[i].s != nil)
-			ftdiwrite(&p[i], FTRESETCTLVAL, 0, FTRESET);
-	return 0;
-}
-
-static int
-ftinit(Serialport *p)
-{
-	Serial *ser;
-	uint timerval;
-	int res;
-
-	ser = p->s;
-	if(p->isjtag){
-		res = ftdiwrite(p, FTSETFLOWCTRL, 0, FTDISABLEFLOWCTRL);
-		if(res < 0)
-			return -1;
-		res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
-			FTLATENCYTIMERSZ);
-		if(res < 0)
-			return -1;
-		dsprint(2, "serial: jtag latency timer is %d\n", timerval);
-		timerval = 2;
-		ftdiwrite(p, FTLATENCYDEFAULT, 0, FTSETLATENCYTIMER);
-		res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
-			FTLATENCYTIMERSZ);
-		if(res < 0)
-			return -1;
-
-		dsprint(2, "serial: jtag latency timer set to %d\n", timerval);
-		/* may be unnecessary */
-		devctl(p->epin,  "timeout 5000");
-		devctl(p->epout, "timeout 5000");
-		/* 0xb is the mask for lines. plug dependant? */
-		ftdiwrite(p, BMMPSSE|0x0b, 0, FTSETBITMODE);
-	}
-	incref(ser->dev);
-	threadcreate(statusreader, p, 8*1024);
-	return 0;
-}
-
-static int
-ftsetbreak(Serialport *p, int val)
-{
-	return ftdiwrite(p, (val != 0? FTSETBREAK: 0), 0, FTSETDATA);
-}
-
-static int
-ftclearpipes(Serialport *p)
-{
-	/* maybe can be done in one... */
-	ftdiwrite(p, FTRESETCTLVALPURGETX, 0, FTRESET);
-	ftdiwrite(p, FTRESETCTLVALPURGERX, 0, FTRESET);
-	return 0;
-}
-
-static int
-setctlline(Serialport *p, uchar val)
-{
-	return ftdiwrite(p, val | (val << 8), 0, FTSETMODEMCTRL);
-}
-
-static void
-updatectlst(Serialport *p, int val)
-{
-	if(p->rts)
-		p->ctlstate |= val;
-	else
-		p->ctlstate &= ~val;
-}
-
-static int
-setctl(Serialport *p)
-{
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-	if(ser->dev->usb->vid == FTVid && ser->dev->usb->did ==  FTHETIRA1Did){
-		fprint(2, "serial: cannot set lines for this device\n");
-		updatectlst(p, CtlRTS|CtlDTR);
-		p->rts = p->dtr = 1;
-		return -1;
-	}
-
-	/* NB: you can not set DTR and RTS with one control message */
-	updatectlst(p, CtlRTS);
-	res = setctlline(p, (CtlRTS<<8)|p->ctlstate);
-	if(res < 0)
-		return res;
-
-	updatectlst(p, CtlDTR);
-	res = setctlline(p, (CtlDTR<<8)|p->ctlstate);
-	if(res < 0)
-		return res;
-
-	return 0;
-}
-
-static int
-ftsendlines(Serialport *p)
-{
-	int res;
-
-	dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate);
-	res = setctl(p);
-	dsprint(2, "serial: sendlines res: %d\n", res);
-	return 0;
-}
-
-static int
-ftseteps(Serialport *p)
-{
-	char *s;
-	Serial *ser;
-
-	ser = p->s;
-
-	s = smprint("maxpkt %d", ser->maxrtrans);
-	devctl(p->epin, s);
-	free(s);
-
-	s = smprint("maxpkt %d", ser->maxwtrans);
-	devctl(p->epout, s);
-	free(s);
-	return 0;
-}
-
-Serialops ftops = {
-	.init		= ftinit,
-	.seteps		= ftseteps,
-	.setparam	= ftsetparam,
-	.clearpipes	= ftclearpipes,
-	.reset		= ftreset,
-	.sendlines	= ftsendlines,
-	.modemctl	= ftmodemctl,
-	.setbreak	= ftsetbreak,
-	.wait4data	= wait4data,
-	.wait4write	= wait4write,
-};
--- a/sys/src/cmd/usb/serial/ftdi.h
+++ /dev/null
@@ -1,632 +1,0 @@
-enum {
-	/* used by devices which don't provide their own Vid */
-	FTVid		= 0x0403,
-
-	FTSheevaVid	= 0x9E88,
-	FTSheevaDid	= 0x9E8F,
-	FTOpenRDUltDid	= 0x9E90,
-
-	FTSIODid	= 0x8372,	/* Product Id SIO appl'n of 8U100AX */
-	FT8U232AMDid	= 0x6001,	/* Similar device to SIO above */
-	FT8U232AMALTDid	= 0x6006,	/* FT's alternate Did for above*/
-	FT8U2232CDid	= 0x6010,	/* Dual channel device */
-	FTRELAISDid	= 0xFA10,	/* Relais device */
-
-	/* NF reader */
-	FTNFRICVid	= 0x0DCD,
-	FTNFRICDid	= 0x0001,
-
-	FTACTZWAVEDid	= 0xF2D0,		/* www.irtrans.de device */
-
-	/*
-	 * ACT Solutions HomePro ZWave interface
-	 * http://www.act-solutions.com/HomePro.htm)
-	 */
-	FTIRTRANSDid	= 0xFC60,
-
-	/*
-	 * www.thoughttechnology.com/ TT-USB
-	 */
-	FTTTUSBDid	= 0xFF20,
-
-	/* iPlus device */
-	FTIPLUSDid	= 0xD070,
-
-	/* www.crystalfontz.com devices */
-	FTXF632Did = 0xFC08,	/* 632: 16x2 Character Display */
-	FTXF634Did = 0xFC09,	/* 634: 20x4 Character Display */
-	FTXF547Did = 0xFC0A,	/* 547: Two line Display */
-	FTXF633Did = 0xFC0B,	/* 633: 16x2 Character Display with Keys */
-	FTXF631Did = 0xFC0C,	/* 631: 20x2 Character Display */
-	FTXF635Did = 0xFC0D,	/* 635: 20x4 Character Display */
-	FTXF640Did = 0xFC0E,	/* 640: Two line Display */
-	FTXF642Did = 0xFC0F,	/* 642: Two line Display */
-
-	/*
-	 * Video Networks Limited / Homechoice in the UK
-	 * use an ftdi-based device for their 1Mb broadband
-	 */
-	FTVNHCPCUSBDDid	= 0xfe38,
-
-	/*
-	 * PCDJ use ftdi based dj-controllers
-	 * DAC-2 device http://www.pcdjhardware.com/DAC2.asp
-	 */
-	FTPCDJDAC2Did = 0xFA88,
-
-	/*
-	 * Matrix Orbital LCD displays,
-	 * which are the FT232BM (similar to the 8U232AM)
-	 */
-	FTMTXORB0Did = 0xFA00,
-	FTMTXORB1Did = 0xFA01,
-	FTMTXORB2Did = 0xFA02,
-	FTMTXORB3Did = 0xFA03,
-	FTMTXORB4Did = 0xFA04,
-	FTMTXORB5Did = 0xFA05,
-	FTMTXORB6Did = 0xFA06,
-
-	/* Interbiometrics USB I/O Board */
-	INTERBIOMVid		= 0x1209,
-	INTERBIOMIOBRDDid	= 0x1002,
-	INTERBIOMMINIIOBRDDid	= 0x1006,
-
-	/*
-	 * The following are the values for the Perle Systems
-	 * UltraPort USB serial converters
-	 */
-	FTPERLEULTRAPORTDid = 0xF0C0,
-
-	/*
-	 * Sealevel SeaLINK+ adapters.
-	 */
-
-	SEALEVELVid = 0x0c52,
-
-	SEALEVEL2101Did = 0x2101,	/* SeaLINK+232 (2101/2105) */
-	SEALEVEL2102Did = 0x2102,	/* SeaLINK+485 (2102) */
-	SEALEVEL2103Did = 0x2103,	/* SeaLINK+232I (2103) */
-	SEALEVEL2104Did = 0x2104,	/* SeaLINK+485I (2104) */
-	SEALEVEL22011Did = 0x2211,	/* SeaPORT+2/232 (2201) Port 1 */
-	SEALEVEL22012Did = 0x2221,	/* SeaPORT+2/232 (2201) Port 2 */
-	SEALEVEL22021Did = 0x2212,	/* SeaPORT+2/485 (2202) Port 1 */
-	SEALEVEL22022Did = 0x2222,	/* SeaPORT+2/485 (2202) Port 2 */
-	SEALEVEL22031Did = 0x2213,	/* SeaPORT+2 (2203) Port 1 */
-	SEALEVEL22032Did = 0x2223,	/* SeaPORT+2 (2203) Port 2 */
-	SEALEVEL24011Did = 0x2411,	/* SeaPORT+4/232 (2401) Port 1 */
-	SEALEVEL24012Did = 0x2421,	/* SeaPORT+4/232 (2401) Port 2 */
-	SEALEVEL24013Did = 0x2431,	/* SeaPORT+4/232 (2401) Port 3 */
-	SEALEVEL24014Did = 0x2441,	/* SeaPORT+4/232 (2401) Port 4 */
-	SEALEVEL24021Did = 0x2412,	/* SeaPORT+4/485 (2402) Port 1 */
-	SEALEVEL24022Did = 0x2422,	/* SeaPORT+4/485 (2402) Port 2 */
-	SEALEVEL24023Did = 0x2432,	/* SeaPORT+4/485 (2402) Port 3 */
-	SEALEVEL24024Did = 0x2442,	/* SeaPORT+4/485 (2402) Port 4 */
-	SEALEVEL24031Did = 0x2413,	/* SeaPORT+4 (2403) Port 1 */
-	SEALEVEL24032Did = 0x2423,	/* SeaPORT+4 (2403) Port 2 */
-	SEALEVEL24033Did = 0x2433,	/* SeaPORT+4 (2403) Port 3 */
-	SEALEVEL24034Did = 0x2443,	/* SeaPORT+4 (2403) Port 4 */
-	SEALEVEL28011Did = 0x2811,	/* SeaLINK+8/232 (2801) Port 1 */
-	SEALEVEL28012Did = 0x2821,	/* SeaLINK+8/232 (2801) Port 2 */
-	SEALEVEL28013Did = 0x2831,	/* SeaLINK+8/232 (2801) Port 3 */
-	SEALEVEL28014Did = 0x2841,	/* SeaLINK+8/232 (2801) Port 4 */
-	SEALEVEL28015Did = 0x2851,	/* SeaLINK+8/232 (2801) Port 5 */
-	SEALEVEL28016Did = 0x2861,	/* SeaLINK+8/232 (2801) Port 6 */
-	SEALEVEL28017Did = 0x2871,	/* SeaLINK+8/232 (2801) Port 7 */
-	SEALEVEL28018Did = 0x2881,	/* SeaLINK+8/232 (2801) Port 8 */
-	SEALEVEL28021Did = 0x2812,	/* SeaLINK+8/485 (2802) Port 1 */
-	SEALEVEL28022Did = 0x2822,	/* SeaLINK+8/485 (2802) Port 2 */
-	SEALEVEL28023Did = 0x2832,	/* SeaLINK+8/485 (2802) Port 3 */
-	SEALEVEL28024Did = 0x2842,	/* SeaLINK+8/485 (2802) Port 4 */
-	SEALEVEL28025Did = 0x2852,	/* SeaLINK+8/485 (2802) Port 5 */
-	SEALEVEL28026Did = 0x2862,	/* SeaLINK+8/485 (2802) Port 6 */
-	SEALEVEL28027Did = 0x2872,	/* SeaLINK+8/485 (2802) Port 7 */
-	SEALEVEL28028Did = 0x2882,	/* SeaLINK+8/485 (2802) Port 8 */
-	SEALEVEL28031Did = 0x2813,	/* SeaLINK+8 (2803) Port 1 */
-	SEALEVEL28032Did = 0x2823,	/* SeaLINK+8 (2803) Port 2 */
-	SEALEVEL28033Did = 0x2833,	/* SeaLINK+8 (2803) Port 3 */
-	SEALEVEL28034Did = 0x2843,	/* SeaLINK+8 (2803) Port 4 */
-	SEALEVEL28035Did = 0x2853,	/* SeaLINK+8 (2803) Port 5 */
-	SEALEVEL28036Did = 0x2863,	/* SeaLINK+8 (2803) Port 6 */
-	SEALEVEL28037Did = 0x2873,	/* SeaLINK+8 (2803) Port 7 */
-	SEALEVEL28038Did = 0x2883,	/* SeaLINK+8 (2803) Port 8 */
-
-	/* KOBIL Vendor ID chipcard terminals */
-	KOBILVid	= 0x0d46,
-	KOBILCONVB1Did	= 0x2020,	/* KOBIL Konverter for B1 */
-	KOBILCONVKAANDid = 0x2021,	/* KOBILKonverter for KAAN */
-
-	/* Icom ID-1 digital transceiver */
-	ICOMID1Vid	= 0x0C26,
-	ICOMID1Did	= 0x0004,
-
-	FTASKRDR400Did	= 0xC991,	/* ASK RDR 400 series card reader */
-	FTDSS20Did	= 0xFC82,	/* DSS-20 Sync Station for Sony Ericsson P800 */
-
-	/*
-	 * Home Electronics (www.home-electro.com) USB gadgets
-	 */
-	FTHETIRA1Did	= 0xFA78,	/* Tira-1 IR transceiver */
-
-	/*
-	 * An infrared receiver and transmitter using the 8U232AM chip
-	 * http://www.usbuirt.com
-	 */
-	FTUSBUIRTDid	= 0xF850,
-
-	FTELVUR100Did	= 0xFB58,	/* USB-RS232-Umsetzer (UR 100) */
-	FTELVUM100Did	= 0xFB5A,	/* USB-Modul UM 100 */
-	FTELVUO100Did	= 0xFB5B,	/* USB-Modul UO 100 */
-	FTELVALC8500Did	= 0xF06E,	/* ALC 8500 Expert */
-	FTELVCLI7000Did	= 0xFB59,	/* Computer-Light-Interface */
-	FTELVPPS7330Did	= 0xFB5C,	/* Processor-Power-Supply (PPS 7330) */
-	FTELVTFM100Did	= 0xFB5D,	/* Temperartur-Feuchte Messgeraet (TFM 100) */
-	FTELVUDF77Did	= 0xFB5E,	/* USB DCF Funkurh (UDF 77) */
-	FTELVUIO88Did	= 0xFB5F,	/* USB-I/O Interface (UIO 88) */
-	FTELVUAD8Did	= 0xF068,	/* USB-AD-Wandler (UAD 8) */
-	FTELVUDA7Did	= 0xF069,	/* USB-DA-Wandler (UDA 7) */
-	FTELVUSI2Did	= 0xF06A,	/* USB-Schrittmotoren-Interface (USI 2) */
-	FTELVT1100Did	= 0xF06B,	/* Thermometer (T 1100) */
-	FTELVPCD200Did	= 0xF06C,	/* PC-Datenlogger (PCD 200) */
-	FTELVULA200Did	= 0xF06D,	/* USB-LCD-Ansteuerung (ULA 200) */
-	FTELVFHZ1000PCDid= 0xF06F,	/* FHZ 1000 PC */
-	FTELVCSI8Did	= 0xE0F0,	/* Computer-Schalt-Interface (CSI 8) */
-	FTELVEM1000DLDid= 0xE0F1,	/* PC-Datenlogger fuer Energiemonitor (EM 1000 DL) */
-	FTELVPCK100Did	= 0xE0F2,	/* PC-Kabeltester (PCK 100) */
-	FTELVRFP500Did	= 0xE0F3,	/* HF-Leistungsmesser (RFP 500) */
-	FTELVFS20SIGDid	= 0xE0F4,	/* Signalgeber (FS 20 SIG) */
-	FTELVWS300PCDid	= 0xE0F6,	/* PC-Wetterstation (WS 300 PC) */
-	FTELVFHZ1300PCDid= 0xE0E8,	/* FHZ 1300 PC */
-	FTELVWS500Did	= 0xE0E9,	/* PC-Wetterstation (WS 500) */
-
-	/*
-	 * Definitions for ID TECH (http://www.idt-net.com) devices
-	 */
-	IDTECHVid	= 0x0ACD,	/* ID TECH Vendor ID */
-	IDTECHIDT1221UDid= 0x0300,	/* IDT1221U USB to RS-232 */
-
-	/*
-	 * Definitions for Omnidirectional Control Technology, Inc. devices
-	 */
-	OCTVid		= 0x0B39,	/* OCT vendor ID */
-
-	/*
-	 * Note: OCT US101 is also rebadged as Dick Smith Electronics
-	 * (NZ) XH6381, Dick Smith Electronics (Aus) XH6451, and SIIG
-	 * Inc. model US2308 hardware version 1.
-	 */
-	OCTUS101Did	= 0x0421,	/* OCT US101 USB to RS-232 */
-
-	/*
-	 *	infrared receiver for access control with IR tags
-	 */
-	FTPIEGROUPDid	= 0xF208,
-
-	/*
-	 * Definitions for Artemis astronomical USB based cameras
-	 * http://www.artemisccd.co.uk/
-	 */
-
-	FTARTEMISDid	= 0xDF28,	/* All Artemis Cameras */
-
-	FTATIKATK16Did	= 0xDF30,	/* ATIK ATK-16 Grayscale Camera */
-	FTATIKATK16CDid = 0xDF32,	/* ATIK ATK-16C Colour Camera */
-	FTATIKATK16HRDid= 0xDF31,	/* ATIK ATK-16HR Grayscale */
-	FTATIKATK16HRCDid= 0xDF33,	/* ATIK ATK-16HRC Colour Camera */
-
-	/*
-	 * Protego products
-	 */
-	PROTEGOSPECIAL1	= 0xFC70,	/* special/unknown device */
-	PROTEGOR2X0	= 0xFC71,	/* R200-USB TRNG unit (R210, R220, and R230) */
-	PROTEGOSPECIAL3	= 0xFC72,	/* special/unknown device */
-	PROTEGOSPECIAL4	= 0xFC73,	/* special/unknown device */
-
-	/*
-	 * Gude Analog- und Digitalsysteme GmbH
-	 */
-	FTGUDEADSE808Did = 0xE808,
-	FTGUDEADSE809Did = 0xE809,
-	FTGUDEADSE80ADid = 0xE80A,
-	FTGUDEADSE80BDid = 0xE80B,
-	FTGUDEADSE80CDid = 0xE80C,
-	FTGUDEADSE80DDid = 0xE80D,
-	FTGUDEADSE80EDid = 0xE80E,
-	FTGUDEADSE80FDid = 0xE80F,
-	FTGUDEADSE888Did = 0xE888,	/* Expert ISDN Control USB */
-	FTGUDEADSE889Did = 0xE889,	/* USB RS-232 OptoBridge */
-	FTGUDEADSE88ADid = 0xE88A,
-	FTGUDEADSE88BDid = 0xE88B,
-	FTGUDEADSE88CDid = 0xE88C,
-	FTGUDEADSE88DDid = 0xE88D,
-	FTGUDEADSE88EDid = 0xE88E,
-	FTGUDEADSE88FDid = 0xE88F,
-
-	/*
-	 * Linx Technologies
-	 */
-	LINXSDMUSBQSSDid= 0xF448,	/* Linx SDM-USB-QS-S */
-	LINXMASTERDEVEL2Did= 0xF449,	/* Linx Master Development.0 */
-	LINXFUTURE0Did	= 0xF44A,	/* Linx future device */
-	LINXFUTURE1Did	= 0xF44B,	/* Linx future device */
-	LINXFUTURE2Did	= 0xF44C,	/* Linx future device */
-
-	/*
-	 * CCS Inc. ICDU/ICDU40 - the FT232BM used in a in-circuit-debugger
-	 * unit for PIC16's/PIC18's
-	 */
-	FTCCSICDU200Did	= 0xF9D0,
-	FTCCSICDU401Did	= 0xF9D1,
-
-	/* Inside Accesso contactless reader (http://www.insidefr.com) */
-	INSIDEACCESSO	= 0xFAD0,
-
-	/*
-	 * Intrepid Control Systems (http://www.intrepidcs.com/)
-	 * ValueCAN and NeoVI
-	 */
-	INTREDidVid	= 0x093C,
-	INTREDidVALUECANDid= 0x0601,
-	INTREDidNEOVIDid= 0x0701,
-
-	/*
-	 * Falcom Wireless Communications GmbH
-	 */
-	FALCOMVid	= 0x0F94,
-	FALCOMTWISTDid	= 0x0001,	/* Falcom Twist USB GPRS modem */
-	FALCOMSAMBADid	= 0x0005,	/* Falcom Samba USB GPRS modem */
-
-	/*
-	 * SUUNTO
-	 */
-	FTSUUNTOSPORTSDid= 0xF680,	/* Suunto Sports instrument */
-
-	/*
-	 * B&B Electronics
-	 */
-	BANDBVid	= 0x0856,	/* B&B Electronics Vendor ID */
-	BANDBUSOTL4Did	= 0xAC01,	/* USOTL4 Isolated RS-485 */
-	BANDBUSTL4Did	= 0xAC02,	/* USTL4 RS-485 Converter */
-	BANDBUSO9ML2Did	= 0xAC03,	/* USO9ML2 Isolated RS-232 */
-
-	/*
-	 * RM Michaelides CANview USB (http://www.rmcan.com)
-	 * CAN fieldbus interface adapter
-	 */
-	FTRMCANVIEWDid	= 0xfd60,
-
-	/*
-	 * EVER Eco Pro UPS (http://www.ever.com.pl/)
-	 */
-	EVERECOPROCDSDid = 0xe520,	/* RS-232 converter */
-
-	/*
-	 * 4N-GALAXY.DE PIDs for CAN-USB, USB-RS232, USB-RS422, USB-RS485,
-	 * USB-TTY activ, USB-TTY passiv. Some PIDs are used by several devices
-	 */
-	FT4NGALAXYDE0Did = 0x8372,
-	FT4NGALAXYDE1Did = 0xF3C0,
-	FT4NGALAXYDE2Did = 0xF3C1,
-
-	/*
-	 * Mobility Electronics products.
-	 */
-	MOBILITYVid	= 0x1342,
-	MOBILITYUSBSERIALDid= 0x0202,	/* EasiDock USB 200 serial */
-
-	/*
-	 * microHAM product IDs (http://www.microham.com)
-	 */
-	FTMHAMKWDid	= 0xEEE8,	/* USB-KW interface */
-	FTMHAMYSDid	= 0xEEE9,	/* USB-YS interface */
-	FTMHAMY6Did	= 0xEEEA,	/* USB-Y6 interface */
-	FTMHAMY8Did	= 0xEEEB,	/* USB-Y8 interface */
-	FTMHAMICDid	= 0xEEEC,	/* USB-IC interface */
-	FTMHAMDB9Did	= 0xEEED,	/* USB-DB9 interface */
-	FTMHAMRS232Did	= 0xEEEE,	/* USB-RS232 interface */
-	FTMHAMY9Did	= 0xEEEF,	/* USB-Y9 interface */
-
-	/*
-	 * Active Robots product ids.
-	 */
-	FTACTIVEROBOTSDid	= 0xE548,	/* USB comms board */
-	XSENSCONVERTER0Did	= 0xD388,
-	XSENSCONVERTER1Did	= 0xD389,
-	XSENSCONVERTER2Did	= 0xD38A,
-	XSENSCONVERTER3Did	= 0xD38B,
-	XSENSCONVERTER4Did	= 0xD38C,
-	XSENSCONVERTER5Did	= 0xD38D,
-	XSENSCONVERTER6Did	= 0xD38E,
-	XSENSCONVERTER7Did	= 0xD38F,
-
-	/*
-	 * Xsens Technologies BV products (http://www.xsens.com).
-	 */
-	FTTERATRONIKVCPDid	= 0xEC88,	/* Teratronik device */
-	FTTERATRONIKD2XXDid	= 0xEC89,	/* Teratronik device */
-
-	/*
-	 * Evolution Robotics products (http://www.evolution.com/).
-	 */
-	EVOLUTIONVid	= 0xDEEE,
-	EVOLUTIONER1Did	= 0x0300,		/* ER1 Control Module */
-
-	/* Pyramid Computer GmbH */
-	FTPYRAMIDDid	= 0xE6C8,		/* Pyramid Appliance Display */
-
-	/*
-	 * Posiflex inc retail equipment (http://www.posiflex.com.tw)
-	 */
-	POSIFLEXVid	= 0x0d3a,
-	POSIFLEXPP7000Did= 0x0300,		/* PP-7000II thermal printer */
-
-	/*
-	 * Westrex International devices
-	 */
-	FTWESTREXMODEL777Did	= 0xDC00,	/* Model 777 */
-	FTWESTREXMODEL8900FDid	= 0xDC01,	/* Model 8900F */
-
-	/*
-	 * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
-	 */
-	FTRRCIRKITSLOCOBUFFERDid= 0xc7d0,	/* LocoBuffer USB */
-	FTECLOCOM1WIREDid	= 0xEA90,	/* COM to 1-Wire USB */
-
-	/*
-	 * Papouch products (http://www.papouch.com/)
-	 */
-	PAPOUCHVid	= 0x5050,
-	PAPOUCHTMUDid	= 0x0400,		/* TMU USB Thermometer */
-
-	/*
-	 * ACG Identification Technologies GmbH products http://www.acg.de/
-	 */
-	FTACGHFDUALDid	= 0xDD20,		/* HF Dual ISO Reader (RFID) */
-	/*
-	 * new high speed devices
-	 */
-	FT4232HDid	= 0x6011,		/* FTDI FT4232H based device */
-
-};
-
-/* Commands */
-enum {
-	FTRESET		= 0,		/* Reset the port */
-	FTSETMODEMCTRL,			/* Set the modem control register */
-	FTSETFLOWCTRL,			/* Set flow control register */
-	FTSETBAUDRATE,			/* Set baud rate */
-	FTSETDATA,			/* Set the parameters, parity */
-	FTGETMODEMSTATUS,		/* Retrieve current value of modem ctl */
-	FTSETEVENTCHAR,			/* Set the event character */
-	FTSETERRORCHAR,			/* Set the error character */
-	FTUNKNOWN,
-	FTSETLATENCYTIMER,		/* Set the latency timer */
-	FTGETLATENCYTIMER,		/* Get the latency timer */
-	FTSETBITMODE,			/* Set bit mode */
-	FTGETPINS,			/* Read pins state */
-	FTGETE2READ	= 0x90,		/* Read address from 128-byte I2C EEPROM */
-	FTSETE2WRITE,			/* Write to address on 128-byte I2C EEPROM */
-	FTSETE2ERASE,			/* Erase address on 128-byte I2C EEPROM */
-};
-
-/* Port Identifier Table, index for interfaces */
-enum {
-	PITDEFAULT = 0,		/* SIOA */
-	PITA,			/* SIOA jtag if there is one */
-};
-
-enum {
-	Rftdireq = 1<<6,		/* bit for type of request */
-};
-
-/*
- * Commands Data size
- * Sets have wLength = 0
- * Gets have wValue = 0
- */
-enum {
-	FTMODEMSTATUSSZ	= 1,
-	FTLATENCYTIMERSZ= 1,
-	FTPINSSZ	= 1,
-	FTE2READSZ	= 2,
-};
-
-/*
- * bRequest: FTGETE2READ
- * wIndex: Address of word to read
- * Data: Will return a word (2 bytes) of data from E2Address
- * Results put in the I2C 128 byte EEPROM string eeprom+(2*index)
- */
-
-/*
- * bRequest: FTSETE2WRITE
- * wIndex: Address of word to read
- * wValue: Value of the word
- * Data: Will return a word (2 bytes) of data from E2Address
- */
-
-/*
- * bRequest: FTSETE2ERASE
- * Erases the EEPROM
- * wIndex: 0
- */
-
-/*
- * bRequest: FTRESET
- * wValue: Ctl Val
- * wIndex: Port
- */
-enum {
-	FTRESETCTLVAL		= 0,
-	FTRESETCTLVALPURGERX	= 1,
-	FTRESETCTLVALPURGETX	= 2,
-};
-
-/*
- * BmRequestType: SET
- * bRequest: FTSETBAUDRATE
- * wValue: BaudDivisor value - see below
- * Bits 15 to 0 of the 17-bit divisor are placed in the request value.
- * Bit 16 is placed in bit 0 of the request index.
- */
-
-/* chip type */
-enum {
-	SIO		= 1,
-	FT8U232AM	= 2,
-	FT232BM		= 3,
-	FT2232C		= 4,
-	FTKINDR		= 5,
-	FT2232H		= 6,
-	FT4232H		= 7,
-};
-
-enum {
-	 FTb300		= 0,
-	 FTb600		= 1,
-	 FTb1200	= 2,
-	 FTb2400	= 3,
-	 FTb4800	= 4,
-	 FTb9600	= 5,
-	 FTb19200	= 6,
-	 FTb38400	= 7,
-	 FTb57600	= 8,
-	 FTb115200	= 9,
-};
-
-/*
- * bRequest: FTSETDATA
- * wValue: Data characteristics
- *	bits 0-7 number of data bits
- * wIndex: Port
- */
-enum {
-	FTSETDATAParNONE	= 0 << 8,
-	FTSETDATAParODD		= 1 << 8,
-	FTSETDATAParEVEN	= 2 << 8,
-	FTSETDATAParMARK	= 3 << 8,
-	FTSETDATAParSPACE	= 4 << 8,
-	FTSETDATASTOPBITS1	= 0 << 11,
-	FTSETDATASTOPBITS15	= 1 << 11,
-	FTSETDATASTOPBITS2	= 2 << 11,
-	FTSETBREAK		= 1 << 14,
-};
-
-/*
- * bRequest: FTSETMODEMCTRL
- * wValue: ControlValue (see below)
- * wIndex: Port
- */
-
-/*
- * bRequest: FTSETFLOWCTRL
- * wValue: Xoff/Xon
- * wIndex: Protocol/Port - hIndex is protocol; lIndex is port
- */
-enum {
-	FTDISABLEFLOWCTRL= 0,
-	FTRTSCTSHS	= 1 << 8,
-	FTDTRDSRHS	= 2 << 8,
-	FTXONXOFFHS	= 4 << 8,
-};
-
-/*
- * bRequest: FTGETLATENCYTIMER
- * wIndex: Port
- * wLength: 0
- * Data: latency (on return)
- */
-
-/*
- * bRequest: FTSETBITMODE
- * wIndex: Port
- * either it is big bang mode, in which case
- * wValue: 1 byte L is the big bang mode BIG*
- *	or BM is
- * wValue: 1 byte bitbang mode H, 1 byte bitmask for lines L
- */
-enum {
-	BMSERIAL	= 0,		/* reset, turn off bit-bang mode */
-
-	BIGBMNORMAL	= 1,		/* normal bit-bang mode */
-	BIGBMSPI	= 2,		/* spi bit-bang mode */
-
-	BMABM		= 1<<8,		/* async mode */
-	BMMPSSE		= 2<<8,
-	BMSYNCBB	= 4<<8,		/* sync bit-bang -- 2232x and R-type */
-	BMMCU		= 8<<8,		/* MCU Host Bus -- 2232x */
-	BMOPTO		= 0x10<<8,	/* opto-isolated<<8, 2232x */
-	BMCBUS		= 0x20<<8,	/* CBUS pins of R-type chips */
-	BMSYNCFF	= 0x40<<8,	/* Single Channel Sync FIFO, 2232H only */
-};
-
-/*
- * bRequest: FTSETLATENCYTIMER
- * wValue: Latency (milliseconds 1-255)
- * wIndex: Port
- */
-enum {
-	FTLATENCYDEFAULT = 2,
-};
-
-/*
- * BmRequestType: SET
- * bRequest: FTSETEVENTCHAR
- * wValue: EventChar
- * wIndex: Port
- * 0-7 lower bits event char
- * 8 enable
- */
-enum {
-	FTEVCHARENAB = 1<<8,
-};
-
-/*
- * BmRequestType: SET
- * bRequest: FTSETERRORCHAR
- * wValue: Error Char
- * wIndex: Port
- * 0-7 lower bits event char
- * 8 enable
- */
-enum {
-	FTERRCHARENAB = 1<<8,
-};
-/*
- * BmRequestType: GET
- * bRequest: FTGETMODEMSTATUS
- * wIndex: Port
- * wLength: 1
- * Data: Status
- */
-enum {
-	FTCTSMASK	= 0x10,
-	FTDSRMASK	= 0x20,
-	FTRIMASK	= 0x40,
-	FTRLSDMASK	= 0x80,
-};
-
-enum {
-	/* byte 0 of in data hdr */
-	FTICTS	= 1 << 4,
-	FTIDSR	= 1 << 5,
-	FTIRI	= 1 << 6,
-	FTIRLSD	= 1 << 7,	/* receive line signal detect */
-
-	/* byte 1 of in data hdr */
-	FTIDR	= 1<<0,		/* data ready */
-	FTIOE	= 1<<1,		/* overrun error */
-	FTIPE	= 1<<2,		/* parity error */
-	FTIFE	= 1<<3,		/* framing error */
-	FTIBI	= 1<<4,		/* break interrupt */
-	FTITHRE	= 1<<5,		/* xmitter holding register */
-	FTITEMT	= 1<<6,		/* xmitter empty */
-	FTIFIFO	= 1<<7,		/* error in rcv fifo */
-
-	/* byte 0 of out data hdr len does not include byte 0 */
-	FTOLENMSK= 0x3F,
-	FTOPORT	= 0x80,		/* must be set */
-};
-
-extern Serialops ftops;
-
-int	ftmatch(Serial *ser, char *info);
--- a/sys/src/cmd/usb/serial/main.c
+++ /dev/null
@@ -1,75 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "serial.h"
-#include "ucons.h"
-#include "prolific.h"
-#include "ftdi.h"
-
-enum {
-	Arglen = 80,
-};
-
-typedef struct Parg Parg;
-
-/* keep in sync with serial.c */
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-dD] [-N nb] [-m mtpt] [-s srv] [dev...]\n", argv0);
-	threadexitsall("usage");
-}
-
-static int
-matchserial(char *info, void*)
-{
-	if(uconsmatch(info) == 0 || plmatch(info) == 0 ||
-	    ftmatch(nil, info) == 0)
-		return 0;
-	return -1;
-}
-
-void
-threadmain(int argc, char **argv)
-{
-	char *mnt, *srv, *as, *ae;
-	char args[Arglen];
-
-	mnt = "/dev";
-	srv = nil;
-
-	quotefmtinstall();
-	ae = args + sizeof args;
-	as = seprint(args, ae, "serial");
-	ARGBEGIN{
-	case 'D':
-		usbfsdebug++;
-		break;
-	case 'd':
-		usbdebug++;
-		as = seprint(as, ae, " -d");
-		break;
-	case 'N':
-		as = seprint(as, ae, " -N %s", EARGF(usage()));
-		break;
-	case 'm':
-		mnt = EARGF(usage());
-		break;
-	case 's':
-		srv = EARGF(usage());
-		break;
-	default:
-		usage();
-		break;
-	}ARGEND;
-
-	rfork(RFNOTEG);
-	fmtinstall('U', Ufmt);
-	threadsetgrp(threadid());
-
-	usbfsinit(srv, mnt, &usbdirfs, MAFTER|MCREATE);
-	startdevs(args, argv, argc, matchserial, nil, serialmain);
-	threadexits(nil);
-}
--- a/sys/src/cmd/usb/serial/mkfile
+++ /dev/null
@@ -1,37 +1,0 @@
-</$objtype/mkfile
-
-TARG=serial
-OFILES=main.$O
-LIBDOFILES=ftdi.$O serial.$O prolific.$O ucons.$O
-HFILES=\
-	../lib/usb.h\
-	ftdi.h\
-	prolific.h\
-	serial.h\
-	ucons.h\
-
-LIBD=../lib/usbdev.a$O
-LIBU=../lib/usb.a$O
-LIB=\
-	$LIBD\
-	$LIBU\
-
-BIN=/$objtype/bin/usb
-
-UPDATE=\
-	mkfile\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-
-</sys/src/cmd/mkone
-
-CFLAGS=-I../lib $CFLAGS
-
-$LIBU:
-	cd ../lib
-	mk install
-	mk clean
-
-$LIBD:V: $LIBDOFILES
-	ar vu $LIBD $newprereq
-	rm $newprereq
--- a/sys/src/cmd/usb/serial/prolific.c
+++ /dev/null
@@ -1,438 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "serial.h"
-#include "prolific.h"
-
-Cinfo plinfo[] = {
-	{ PL2303Vid,	PL2303Did },
-	{ PL2303Vid,	PL2303DidRSAQ2 },
-	{ PL2303Vid,	PL2303DidDCU11 },
-	{ PL2303Vid,	PL2303DidRSAQ3 },
-	{ PL2303Vid,	PL2303DidPHAROS },
-	{ PL2303Vid,	PL2303DidALDIGA },
-	{ PL2303Vid,	PL2303DidMMX },
-	{ PL2303Vid,	PL2303DidGPRS },
-	{ IODATAVid,	IODATADid },
-	{ IODATAVid,	IODATADidRSAQ5 },
-	{ ATENVid,	ATENDid },
-	{ ATENVid2,	ATENDid },
-	{ ELCOMVid,	ELCOMDid },
-	{ ELCOMVid,	ELCOMDidUCSGT },
-	{ ITEGNOVid,	ITEGNODid },
-	{ ITEGNOVid,	ITEGNODid2080 },
-	{ MA620Vid,	MA620Did },
-	{ RATOCVid,	RATOCDid },
-	{ TRIPPVid,	TRIPPDid },
-	{ RADIOSHACKVid,RADIOSHACKDid },
-	{ DCU10Vid,	DCU10Did },
-	{ SITECOMVid,	SITECOMDid },
-	{ ALCATELVid,	ALCATELDid },
-	{ SAMSUNGVid,	SAMSUNGDid },
-	{ SIEMENSVid,	SIEMENSDidSX1 },
-	{ SIEMENSVid,	SIEMENSDidX65 },
-	{ SIEMENSVid,	SIEMENSDidX75 },
-	{ SIEMENSVid,	SIEMENSDidEF81 },
-	{ SYNTECHVid,	SYNTECHDid },
-	{ NOKIACA42Vid,	NOKIACA42Did },
-	{ CA42CA42Vid,	CA42CA42Did },
-	{ SAGEMVid,	SAGEMDid },
-	{ LEADTEKVid,	LEADTEK9531Did },
-	{ SPEEDDRAGONVid,SPEEDDRAGONDid },
-	{ DATAPILOTU2Vid,DATAPILOTU2Did },
-	{ BELKINVid,	BELKINDid },
-	{ ALCORVid,	ALCORDid },
-	{ WS002INVid,	WS002INDid },
-	{ COREGAVid,	COREGADid },
-	{ YCCABLEVid,	YCCABLEDid },
-	{ SUPERIALVid,	SUPERIALDid },
-	{ HPVid,	HPLD220Did },
-	{ 0,		0 },
-};
-
-int
-plmatch(char *info)
-{
-	Cinfo *ip;
-	char buf[50];
-
-	for(ip = plinfo; ip->vid != 0; ip++){
-		snprint(buf, sizeof buf, "vid %#06x did %#06x",
-			ip->vid, ip->did);
-		dsprint(2, "serial: %s %s\n", buf, info);
-		if(strstr(info, buf) != nil)
-			return 0;
-	}
-	return -1;
-}
-
-static void	statusreader(void *u);
-
-static void
-dumpbuf(uchar *buf, int bufsz)
-{
-	int i;
-
-	for(i=0; i<bufsz; i++)
-		print("buf[%d]=%#ux ", i, buf[i]);
-	print("\n");
-}
-
-static int
-vendorread(Serialport *p, int val, int index, uchar *buf)
-{
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-	dsprint(2, "serial: vendorread val: 0x%x idx:%d buf:%p\n",
-		val, index, buf);
-	res = usbcmd(ser->dev,  Rd2h | Rvendor | Rdev, VendorReadReq,
-		val, index, buf, 1);
-	dsprint(2, "serial: vendorread res:%d\n", res);
-	return res;
-}
-
-static int
-vendorwrite(Serialport *p, int val, int index)
-{
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-	dsprint(2, "serial: vendorwrite val: 0x%x idx:%d\n", val, index);
-	res = usbcmd(ser->dev, Rh2d | Rvendor | Rdev, VendorWriteReq,
-		val, index, nil, 0);
-	dsprint(2, "serial: vendorwrite res:%d\n", res);
-	return res;
-}
-
-/* BUG: I could probably read Dcr0 and set only the bits */
-static int
-plmodemctl(Serialport *p, int set)
-{
-	Serial *ser;
-
-	ser = p->s;
-
-	if(set == 0){
-		p->mctl = 0;
-		vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init);
-		return 0;
-	}
-
-	p->mctl = 1;
-	if(ser->type == TypeHX)
-		vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init|Dcr0HwFcX);
-	else
-		vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init|Dcr0HwFcH);
-	return 0;
-}
-
-static int
-plgetparam(Serialport *p)
-{
-	uchar buf[ParamReqSz];
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-
-	res = usbcmd(ser->dev, Rd2h | Rclass | Riface, GetLineReq,
-		0, 0, buf, sizeof buf);
-	p->baud = GET4(buf);
-
-	/*
-	 * with the Pl9 interface it is not possible to set `1.5' as stop bits
-	 * for the prologic:
-	 *	0 is 1 stop bit
-	 *	1 is 1.5 stop bits
-	 *	2 is 2 stop bits
-	 */
-	if(buf[4] == 1)
-		fprint(2, "warning, stop bit set to 1.5 unsupported");
-	else if(buf[4] == 0)
-		p->stop = 1;
-	else if(buf[4] == 2)
-		p->stop = 2;
-	p->parity = buf[5];
-	p->bits = buf[6];
-
-	dsprint(2, "serial: getparam: ");
-	if(serialdebug)
-		dumpbuf(buf, sizeof buf);
-	dsprint(2, "serial: getparam res: %d\n", res);
-	return res;
-}
-
-static int
-plsetparam(Serialport *p)
-{
-	uchar buf[ParamReqSz];
-	int res;
-	Serial *ser;
-
-	ser = p->s;
-
-	PUT4(buf, p->baud);
-
-	if(p->stop == 1)
-		buf[4] = 0;
-	else if(p->stop == 2)
-		buf[4] = 2; 			/* see comment in getparam */
-	buf[5] = p->parity;
-	buf[6] = p->bits;
-
-	dsprint(2, "serial: setparam: ");
-	if(serialdebug)
-		dumpbuf(buf, sizeof buf);
-	res = usbcmd(ser->dev, Rh2d | Rclass | Riface, SetLineReq,
-		0, 0, buf, sizeof buf);
-	plmodemctl(p, p->mctl);
-	plgetparam(p);		/* make sure our state corresponds */
-
-	dsprint(2, "serial: setparam res: %d\n", res);
-	return res;
-}
-
-static int
-revid(ulong devno)
-{
-	switch(devno){
-	case RevH:
-		return TypeH;
-	case RevX:
-	case RevHX:
-	case Rev1:
-		return TypeHX;
-	default:
-		return TypeUnk;
-	}
-}
-
-/* linux driver says the release id is not always right */
-static int
-heuristicid(ulong csp, ulong maxpkt)
-{
-	if(Class(csp) == 0x02)
-		return TypeH;
-	else if(maxpkt == 0x40)
-		return TypeHX;
-	else if(Class(csp) == 0x00 || Class(csp) == 0xFF)
-		return TypeH;
-	else{
-		fprint(2, "serial: chip unknown, setting to HX version\n");
-		return TypeHX;
-	}
-}
-
-static int
-plinit(Serialport *p)
-{
-	char *st;
-	uchar *buf;
-	ulong csp, maxpkt, dno;
-	Serial *ser;
-
-	ser = p->s;
-	buf = emallocz(VendorReqSz, 1);
-	dsprint(2, "plinit\n");
-
-	csp = ser->dev->usb->csp;
-	maxpkt = ser->dev->maxpkt;
-	dno = ser->dev->usb->dno;
-
-	if((ser->type = revid(dno)) == TypeUnk)
-		ser->type = heuristicid(csp, maxpkt);
-
-	dsprint(2, "serial: type %d\n", ser->type);
-
-	vendorread(p, 0x8484, 0, buf);
-	vendorwrite(p, 0x0404, 0);
-	vendorread(p, 0x8484, 0, buf);
-	vendorread(p, 0x8383, 0, buf);
-	vendorread(p, 0x8484, 0, buf);
-	vendorwrite(p, 0x0404, 1);
-	vendorread(p, 0x8484, 0, buf);
-	vendorread(p, 0x8383, 0, buf);
-
-	vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init);
-	vendorwrite(p, Dcr1Idx|DcrSet, Dcr1Init);
-
-	if(ser->type == TypeHX)
-		vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitX);
-	else
-		vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitH);
-
-	plgetparam(p);
-	qunlock(ser);
-	free(buf);
-	st = emallocz(255, 1);
-	qlock(ser);
-	if(serialdebug)
-		serdumpst(p, st, 255);
-	dsprint(2, st);
-	free(st);
-	/* p gets freed by closedev, the process has a reference */
-	incref(ser->dev);
-	proccreate(statusreader, p, 8*1024);
-	return 0;
-}
-
-static int
-plsetbreak(Serialport *p, int val)
-{
-	Serial *ser;
-
-	ser = p->s;
-	return usbcmd(ser->dev, Rh2d | Rclass | Riface,
-		(val != 0? BreakOn: BreakOff), val, 0, nil, 0);
-}
-
-static int
-plclearpipes(Serialport *p)
-{
-	Serial *ser;
-
-	ser = p->s;
-
-	if(ser->type == TypeHX){
-		vendorwrite(p, PipeDSRst, 0);
-		vendorwrite(p, PipeUSRst, 0);
-	}else{
-		if(unstall(ser->dev, p->epout, Eout) < 0)
-			dprint(2, "disk: unstall epout: %r\n");
-		if(unstall(ser->dev, p->epin, Ein) < 0)
-			dprint(2, "disk: unstall epin: %r\n");
-		if(unstall(ser->dev, p->epintr, Ein) < 0)
-			dprint(2, "disk: unstall epintr: %r\n");
-	}
-	return 0;
-}
-
-static int
-setctlline(Serialport *p, uchar val)
-{
-	Serial *ser;
-
-	ser = p->s;
-	return usbcmd(ser->dev, Rh2d | Rclass | Riface, SetCtlReq,
-		val, 0, nil, 0);
-}
-
-static void
-composectl(Serialport *p)
-{
-	if(p->rts)
-		p->ctlstate |= CtlRTS;
-	else
-		p->ctlstate &= ~CtlRTS;
-	if(p->dtr)
-		p->ctlstate |= CtlDTR;
-	else
-		p->ctlstate &= ~CtlDTR;
-}
-
-static int
-plsendlines(Serialport *p)
-{
-	int res;
-
-	dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate);
-	composectl(p);
-	res = setctlline(p, p->ctlstate);
-	dsprint(2, "serial: sendlines res: %d\n", res);
-	return 0;
-}
-
-static int
-plreadstatus(Serialport *p)
-{
-	int nr, dfd;
-	char err[40];
-	uchar buf[VendorReqSz];
-	Serial *ser;
-
-	ser = p->s;
-
-	qlock(ser);
-	dsprint(2, "serial: reading from interrupt\n");
-	dfd = p->epintr->dfd;
-
-	qunlock(ser);
-	nr = read(dfd, buf, sizeof buf);
-	qlock(ser);
-	snprint(err, sizeof err, "%r");
-	dsprint(2, "serial: interrupt read %d %r\n", nr);
-
-	if(nr < 0 && strstr(err, "timed out") == nil){
-		dsprint(2, "serial: need to recover, status read %d %r\n", nr);
-		if(serialrecover(ser, nil, nil, err) < 0){
-			qunlock(ser);
-			return -1;
-		}
-	}
-	if(nr < 0)
-		dsprint(2, "serial: reading status: %r");
-	else if(nr >= sizeof buf - 1){
-		p->dcd = buf[8] & DcdStatus;
-		p->dsr = buf[8] & DsrStatus;
-		p->cts = buf[8] & BreakerrStatus;
-		p->ring = buf[8] & RingStatus;
-		p->cts = buf[8] & CtsStatus;
-		if(buf[8] & FrerrStatus)
-			p->nframeerr++;
-		if(buf[8] & ParerrStatus)
-			p->nparityerr++;
-		if(buf[8] & OvererrStatus)
-			p->novererr++;
-	} else
-		dsprint(2, "serial: bad status read %d\n", nr);
-	dsprint(2, "serial: finished read from interrupt %d\n", nr);
-	qunlock(ser);
-	return 0;
-}
-
-static void
-statusreader(void *u)
-{
-	Serialport *p;
-	Serial *ser;
-
-	p = u;
-	ser = p->s;
-	threadsetname("statusreaderproc");
-	while(plreadstatus(p) >= 0)
-		;
-	fprint(2, "serial: statusreader exiting\n");
-	closedev(ser->dev);
-}
-
-/*
- * Maximum number of bytes transferred per frame
- * The output buffer size cannot be increased due to the size encoding
- */
-
-static int
-plseteps(Serialport *p)
-{
-	devctl(p->epin,  "maxpkt 256");
-	devctl(p->epout, "maxpkt 256");
-	return 0;
-}
-
-Serialops plops = {
-	.init		= plinit,
-	.getparam	= plgetparam,
-	.setparam	= plsetparam,
-	.clearpipes	= plclearpipes,
-	.sendlines	= plsendlines,
-	.modemctl	= plmodemctl,
-	.setbreak	= plsetbreak,
-	.seteps		= plseteps,
-};
--- a/sys/src/cmd/usb/serial/prolific.h
+++ /dev/null
@@ -1,178 +1,0 @@
-enum {
-	/* flavours of the device */
-	TypeH,
-	TypeHX,
-	TypeUnk,
-
-	RevH		= 0x0202,
-	RevX		= 0x0300,
-	RevHX		= 0x0400,
-	Rev1		= 0x0001,
-
-	/* usbcmd parameters */
-	SetLineReq	= 0x20,
-
-	SetCtlReq	= 0x22,
-
-	BreakReq	= 0x23,
-	BreakOn		= 0xffff,
-	BreakOff	= 0x0000,
-
-	GetLineReq	= 0x21,
-
-	VendorWriteReq	= 0x01,		/* BUG: is this a standard request? */
-	VendorReadReq	= 0x01,
-
-	ParamReqSz	= 7,
-	VendorReqSz	= 10,
-
-	/* status read from interrupt endpoint */
-	DcdStatus	= 0x01,
-	DsrStatus	= 0x02,
-	BreakerrStatus	= 0x04,
-	RingStatus	= 0x08,
-	FrerrStatus	= 0x10,
-	ParerrStatus	= 0x20,
-	OvererrStatus	= 0x40,
-	CtsStatus	= 0x80,
-
-	DcrGet		= 0x80,
-	DcrSet		= 0x00,
-
-	Dcr0Idx		= 0x00,
-
-	Dcr0Init	= 0x0001,
-	Dcr0HwFcH	= 0x0040,
-	Dcr0HwFcX	= 0x0060,
-
-	Dcr1Idx		= 0x01,
-
-	Dcr1Init	= 0x0000,
-	Dcr1InitH	= 0x0080,
-	Dcr1InitX	= 0x0000,
-
-	Dcr2Idx		= 0x02,
-
-	Dcr2InitH	= 0x0024,
-	Dcr2InitX	= 0x0044,
-
-	PipeDSRst	= 0x08,
-	PipeUSRst	= 0x09,
-
-};
-
-enum {
-	PL2303Vid	= 0x067b,
-	PL2303Did	= 0x2303,
-	PL2303DidRSAQ2	= 0x04bb,
-	PL2303DidDCU11	= 0x1234,
-	PL2303DidPHAROS	= 0xaaa0,
-	PL2303DidRSAQ3	= 0xaaa2,
-	PL2303DidALDIGA	= 0x0611,
-	PL2303DidMMX	= 0x0612,
-	PL2303DidGPRS	= 0x0609,
-
-	ATENVid		= 0x0557,
-	ATENVid2	= 0x0547,
-	ATENDid		= 0x2008,
-
-	IODATAVid	= 0x04bb,
-	IODATADid	= 0x0a03,
-	IODATADidRSAQ5	= 0x0a0e,
-
-	ELCOMVid	= 0x056e,
-	ELCOMDid	= 0x5003,
-	ELCOMDidUCSGT	= 0x5004,
-
-	ITEGNOVid	= 0x0eba,
-	ITEGNODid	= 0x1080,
-	ITEGNODid2080	= 0x2080,
-
-	MA620Vid	= 0x0df7,
-	MA620Did	= 0x0620,
-
-	RATOCVid	= 0x0584,
-	RATOCDid	= 0xb000,
-
-	TRIPPVid	= 0x2478,
-	TRIPPDid	= 0x2008,
-
-	RADIOSHACKVid	= 0x1453,
-	RADIOSHACKDid	= 0x4026,
-
-	DCU10Vid	= 0x0731,
-	DCU10Did	= 0x0528,
-
-	SITECOMVid	= 0x6189,
-	SITECOMDid	= 0x2068,
-
-	 /* Alcatel OT535/735 USB cable */
-	ALCATELVid	= 0x11f7,
-	ALCATELDid	= 0x02df,
-
-	/* Samsung I330 phone cradle */
-	SAMSUNGVid	= 0x04e8,
-	SAMSUNGDid	= 0x8001,
-
-	SIEMENSVid	= 0x11f5,
-	SIEMENSDidSX1	= 0x0001,
-	SIEMENSDidX65	= 0x0003,
-	SIEMENSDidX75	= 0x0004,
-	SIEMENSDidEF81	= 0x0005,
-
-	SYNTECHVid	= 0x0745,
-	SYNTECHDid	= 0x0001,
-
-	/* Nokia CA-42 Cable */
-	NOKIACA42Vid	= 0x078b,
-	NOKIACA42Did	= 0x1234,
-
-	/* CA-42 CLONE Cable www.ca-42.com chipset: Prolific Technology Inc */
-	CA42CA42Vid	= 0x10b5,
-	CA42CA42Did	= 0xac70,
-
-	SAGEMVid	= 0x079b,
-	SAGEMDid	= 0x0027,
-
-	/* Leadtek GPS 9531 (ID 0413:2101) */
-	LEADTEKVid	= 0x0413,
-	LEADTEK9531Did	= 0x2101,
-
-	 /* USB GSM cable from Speed Dragon Multimedia, Ltd */
-	SPEEDDRAGONVid	= 0x0e55,
-	SPEEDDRAGONDid	= 0x110b,
-
-	/* DATAPILOT Universal-2 Phone Cable */
-	BELKINVid	= 0x050d,
-	BELKINDid	= 0x0257,
-
-	/* Belkin "F5U257" Serial Adapter */
-	DATAPILOTU2Vid	= 0x0731,
-	DATAPILOTU2Did	= 0x2003,
-
-	ALCORVid	= 0x058F,
-	ALCORDid	= 0x9720,
-
-	/* Willcom WS002IN Data Driver (by NetIndex Inc.) */,
-	WS002INVid	= 0x11f6,
-	WS002INDid	= 0x2001,
-
-	/* Corega CG-USBRS232R Serial Adapter */,
-	COREGAVid	= 0x07aa,
-	COREGADid	= 0x002a,
-
-	/* Y.C. Cable U.S.A., Inc - USB to RS-232 */,
-	YCCABLEVid	= 0x05ad,
-	YCCABLEDid	= 0x0fba,
-
-	/* "Superial" USB - Serial */,
-	SUPERIALVid	= 0x5372,
-	SUPERIALDid	= 0x2303,
-
-	/* Hewlett-Packard LD220-HP POS Pole Display */,
-	HPVid		= 0x03f0,
-	HPLD220Did	= 0x3524,
-};
-
-extern Serialops plops;
-int	plmatch(char *info);
--- a/sys/src/cmd/usb/serial/serial.c
+++ /dev/null
@@ -1,890 +1,0 @@
-/*
- * This part takes care of locking except for initialization and
- * other threads created by the hw dep. drivers.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <ctype.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "serial.h"
-#include "prolific.h"
-#include "ucons.h"
-#include "ftdi.h"
-
-int serialdebug;
-
-enum {
-	/* Qids. Maintain order (relative to dirtabs structs) */
-	Qroot	= 0,
-	Qctl,
-	Qdata,
-	Qmax,
-};
-
-typedef struct Dirtab Dirtab;
-struct Dirtab {
-	char	*name;
-	int	mode;
-};
-
-static Dirtab dirtab[] = {
-	[Qroot]	"/",		DMDIR|0555,
-	[Qdata]	"%s",		0660,
-	[Qctl]	"%sctl",	0664,
-};
-
-static int sdebug;
-
-static void
-serialfatal(Serial *ser)
-{
-	Serialport *p;
-	int i;
-
-	dsprint(2, "serial: fatal error, detaching\n");
-	devctl(ser->dev, "detach");
-
-	for(i = 0; i < ser->nifcs; i++){
-		p = &ser->p[i];
-		usbfsdel(&p->fs);
-		if(p->w4data != nil)
-			chanclose(p->w4data);
-		if(p->gotdata != nil)
-			chanclose(p->gotdata);
-		if(p->readc)
-			chanclose(p->readc);
-	}
-}
-
-/* I sleep with the lock... only way to drain in general */
-static void
-serialdrain(Serialport *p)
-{
-	Serial *ser;
-	uint baud, pipesize;
-
-	ser = p->s;
-	baud = p->baud;
-
-	if(p->baud == ~0)
-		return;
-	if(ser->maxwtrans < 256)
-		pipesize = 256;
-	else
-		pipesize = ser->maxwtrans;
-	/* wait for the at least 256-byte pipe to clear */
-	sleep(10 + pipesize/((1 + baud)*1000));
-	if(ser->clearpipes != nil)
-		ser->clearpipes(p);
-}
-
-int
-serialreset(Serial *ser)
-{
-	Serialport *p;
-	int i, res;
-
-	res = 0;
-	/* cmd for reset */
-	for(i = 0; i < ser->nifcs; i++){
-		p = &ser->p[i];
-		serialdrain(p);
-	}
-	if(ser->reset != nil)
-		res = ser->reset(ser, nil);
-	return res;
-}
-
-/* call this if something goes wrong, must be qlocked */
-int
-serialrecover(Serial *ser, Serialport *p, Dev *ep, char *err)
-{
-	if(p != nil)
-		dprint(2, "serial[%d], %s: %s, level %d\n", p->interfc,
-			p->name, err, ser->recover);
-	else
-		dprint(2, "serial[%s], global error, level %d\n",
-			ser->p[0].name, ser->recover);
-	ser->recover++;
-	if(strstr(err, "detached") != nil)
-		return -1;
-	if(ser->recover < 3){
-		if(p != nil){	
-			if(ep != nil){
-				if(ep == p->epintr)
-					unstall(ser->dev, p->epintr, Ein);
-				if(ep == p->epin)
-					unstall(ser->dev, p->epin, Ein);
-				if(ep == p->epout)
-					unstall(ser->dev, p->epout, Eout);
-				return 0;
-			}
-
-			if(p->epintr != nil)
-				unstall(ser->dev, p->epintr, Ein);
-			if(p->epin != nil)
-				unstall(ser->dev, p->epin, Ein);
-			if(p->epout != nil)
-				unstall(ser->dev, p->epout, Eout);
-		}
-		return 0;
-	}
-	if(ser->recover > 4 && ser->recover < 8)
-		serialfatal(ser);
-	if(ser->recover > 8){
-		ser->reset(ser, p);
-		return 0;
-	}
-	if(serialreset(ser) < 0)
-		return -1;
-	return 0;
-}
-
-static int
-serialctl(Serialport *p, char *cmd)
-{
-	Serial *ser;
-	int c, i, n, nf, nop, nw, par, drain, set, lines;
-	char *f[16];
-	uchar x;
-
-	ser = p->s;
-	drain = set = lines = 0;
-	nf = tokenize(cmd, f, nelem(f));
-	for(i = 0; i < nf; i++){
-		if(strncmp(f[i], "break", 5) == 0){
-			if(ser->setbreak != nil)
-				ser->setbreak(p, 1);
-			continue;
-		}
-
-		nop = 0;
-		n = atoi(f[i]+1);
-		c = *f[i];
-		if (isascii(c) && isupper(c))
-			c = tolower(c);
-		switch(c){
-		case 'b':
-			drain++;
-			p->baud = n;
-			set++;
-			break;
-		case 'c':
-			p->dcd = n;
-			// lines++;
-			++nop;
-			break;
-		case 'd':
-			p->dtr = n;
-			lines++;
-			break;
-		case 'e':
-			p->dsr = n;
-			// lines++;
-			++nop;
-			break;
-		case 'f':		/* flush the pipes */
-			drain++;
-			break;
-		case 'h':		/* hangup?? */
-			p->rts = p->dtr = 0;
-			lines++;
-			fprint(2, "serial: %c, unsure ctl\n", c);
-			break;
-		case 'i':
-			++nop;
-			break;
-		case 'k':
-			drain++;
-			ser->setbreak(p, 1);
-			sleep(n);
-			ser->setbreak(p, 0);
-			break;
-		case 'l':
-			drain++;
-			p->bits = n;
-			set++;
-			break;
-		case 'm':
-			drain++;
-			if(ser->modemctl != nil)
-				ser->modemctl(p, n);
-			if(n == 0)
-				p->cts = 0;
-			break;
-		case 'n':
-			p->blocked = n;
-			++nop;
-			break;
-		case 'p':		/* extended... */
-			if(strlen(f[i]) != 2)
-				return -1;
-			drain++;
-			par = f[i][1];
-			if(par == 'n')
-				p->parity = 0;
-			else if(par == 'o')
-				p->parity = 1;
-			else if(par == 'e')
-				p->parity = 2;
-			else if(par == 'm')	/* mark parity */
-				p->parity = 3;
-			else if(par == 's')	/* space parity */
-				p->parity = 4;
-			else
-				return -1;
-			set++;
-			break;
-		case 'q':
-			// drain++;
-			p->limit = n;
-			++nop;
-			break;
-		case 'r':
-			drain++;
-			p->rts = n;
-			lines++;
-			break;
-		case 's':
-			drain++;
-			p->stop = n;
-			set++;
-			break;
-		case 'w':
-			/* ?? how do I put this */
-			p->timer = n * 100000LL;
-			++nop;
-			break;
-		case 'x':
-			if(n == 0)
-				x = CTLS;
-			else
-				x = CTLQ;
-			if(ser->wait4write != nil)
-				nw = ser->wait4write(p, &x, 1);
-			else
-				nw = write(p->epout->dfd, &x, 1);
-			if(nw != 1){
-				serialrecover(ser, p, p->epout, "");
-				return -1;
-			}
-			break;
-		}
-		/*
-		 * don't print.  the condition is harmless and the print
-		 * splatters all over the display.
-		 */
-		USED(nop);
-		if (0 && nop)
-			fprint(2, "serial: %c, unsupported nop ctl\n", c);
-	}
-	if(drain)
-		serialdrain(p);
-	if(lines && !set){
-		if(ser->sendlines != nil && ser->sendlines(p) < 0)
-			return -1;
-	} else if(set){
-		if(ser->setparam != nil && ser->setparam(p) < 0)
-			return -1;
-	}
-	ser->recover = 0;
-	return 0;
-}
-
-char *pformat = "noems";
-
-char *
-serdumpst(Serialport *p, char *buf, int bufsz)
-{
-	char *e, *s;
-	Serial *ser;
-
-	ser = p->s;
-
-	e = buf + bufsz;
-	s = seprint(buf, e, "b%d ", p->baud);
-	s = seprint(s, e, "c%d ", p->dcd);	/* unimplemented */
-	s = seprint(s, e, "d%d ", p->dtr);
-	s = seprint(s, e, "e%d ", p->dsr);	/* unimplemented */
-	s = seprint(s, e, "l%d ", p->bits);
-	s = seprint(s, e, "m%d ", p->mctl);
-	if(p->parity >= 0 || p->parity < strlen(pformat))
-		s = seprint(s, e, "p%c ", pformat[p->parity]);
-	else
-		s = seprint(s, e, "p%c ", '?');
-	s = seprint(s, e, "r%d ", p->rts);
-	s = seprint(s, e, "s%d ", p->stop);
-	s = seprint(s, e, "i%d ", p->fifo);
-	s = seprint(s, e, "\ndev(%d) ", 0);
-	s = seprint(s, e, "type(%d)  ", ser->type);
-	s = seprint(s, e, "framing(%d) ", p->nframeerr);
-	s = seprint(s, e, "overruns(%d) ", p->novererr);
-	s = seprint(s, e, "berr(%d) ", p->nbreakerr);
-	s = seprint(s, e, " serr(%d)\n", p->nparityerr);
-	return s;
-}
-
-static int
-serinit(Serialport *p)
-{
-	int res;
-	res = 0;
-	Serial *ser;
-
-	ser = p->s;
-
-	if(ser->init != nil)
-		res = ser->init(p);
-	if(ser->getparam != nil)
-		ser->getparam(p);
-	p->nframeerr = p->nparityerr = p->nbreakerr = p->novererr = 0;
-
-	return res;
-}
-
-static int
-dwalk(Usbfs *fs, Fid *fid, char *name)
-{
-	int i;
-	char *dname;
-	Qid qid;
-	Serialport *p;
-
-	qid = fid->qid;
-	if((qid.type & QTDIR) == 0){
-		werrstr("walk in non-directory");
-		return -1;
-	}
-
-	if(strcmp(name, "..") == 0){
-		/* must be /eiaU%d; i.e. our root dir. */
-		fid->qid.path = Qroot | fs->qid;
-		fid->qid.vers = 0;
-		fid->qid.type = QTDIR;
-		return 0;
-	}
-
-	p = fs->aux;
-	for(i = 1; i < nelem(dirtab); i++){
-		dname = smprint(dirtab[i].name, p->name);
-		if(strcmp(name, dname) == 0){
-			qid.path = i | fs->qid;
-			qid.vers = 0;
-			qid.type = dirtab[i].mode >> 24;
-			fid->qid = qid;
-			free(dname);
-			return 0;
-		} else
-			free(dname);
-	}
-	werrstr(Enotfound);
-	return -1;
-}
-
-static void
-dostat(Usbfs *fs, int path, Dir *d)
-{
-	Dirtab *t;
-	Serialport *p;
-
-	t = &dirtab[path];
-	d->qid.path = path;
-	d->qid.type = t->mode >> 24;
-	d->mode = t->mode;
-	p = fs->aux;
-
-	if(strcmp(t->name, "/") == 0)
-		d->name = t->name;
-	else
-		snprint(d->name, Namesz, t->name, p->fs.name);
-	d->length = 0;
-}
-
-static int
-dstat(Usbfs *fs, Qid qid, Dir *d)
-{
-	int path;
-
-	path = qid.path & ~fs->qid;
-	dostat(fs, path, d);
-	d->qid.path |= fs->qid;
-	return 0;
-}
-
-static int
-dopen(Usbfs *fs, Fid *fid, int)
-{
-	ulong path;
-	Serialport *p;
-
-	path = fid->qid.path & ~fs->qid;
-	p = fs->aux;
-	switch(path){		/* BUG: unneeded? */
-	case Qdata:
-		dsprint(2, "serial, opened data\n");
-		break;
-	case Qctl:
-		dsprint(2, "serial, opened ctl\n");
-		if(p->isjtag)
-			return 0;
-		serialctl(p, "l8 i1");	/* default line parameters */
-		break;
-	}
-	return 0;
-}
-
-
-static void
-filldir(Usbfs *fs, Dir *d, Dirtab *tab, int i, void *v)
-{
-	Serialport *p;
-
-	p = v;
-	d->qid.path = i | fs->qid;
-	d->mode = tab->mode;
-	if((d->mode & DMDIR) != 0)
-		d->qid.type = QTDIR;
-	else
-		d->qid.type = QTFILE;
-	sprint(d->name, tab->name, p->name);	/* hope it fits */
-}
-
-static int
-dirgen(Usbfs *fs, Qid, int i, Dir *d, void *p)
-{
-	i++;				/* skip root */
-	if(i >= nelem(dirtab))
-		return -1;
-	filldir(fs, d, &dirtab[i], i, p);
-	return 0;
-}
-
-enum {
-	Serbufsize	= 255,
-};
-
-static long
-dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
-{
-	int dfd;
-	long rcount;
-	ulong path;
-	char *e, *buf, *err;	/* change */
-	Qid q;
-	Serialport *p;
-	Serial *ser;
-	static int errrun, good;
-
-	q = fid->qid;
-	path = fid->qid.path & ~fs->qid;
-	p = fs->aux;
-	ser = p->s;
-
-	buf = emallocz(Serbufsize, 1);
-	err = emallocz(Serbufsize, 1);
-	qlock(ser);
-	switch(path){
-	case Qroot:
-		count = usbdirread(fs, q, data, count, offset, dirgen, p);
-		break;
-	case Qdata:
-		if(count > ser->maxread)
-			count = ser->maxread;
-		dsprint(2, "serial: reading from data\n");
-		do {
-			err[0] = 0;
-			dfd = p->epin->dfd;
-			if(usbdebug >= 3)
-				dsprint(2, "serial: reading: %ld\n", count);
-
-			assert(count > 0);
-			if(ser->wait4data != nil)
-				rcount = ser->wait4data(p, data, count);
-			else{
-				qunlock(ser);
-				rcount = read(dfd, data, count);
-				qlock(ser);
-			}
-			/*
-			 * if we encounter a long run of continuous read
-			 * errors, do something drastic so that our caller
-			 * doesn't just spin its wheels forever.
-			 */
-			if(rcount < 0) {
-				snprint(err, Serbufsize, "%r");
-				++errrun;
-				sleep(20);
-				if (good > 0 && errrun > 10000) {
-					/* the line has been dropped; give up */
-					qunlock(ser);
-					fprint(2, "%s: line %s is gone: %r\n",
-						argv0, p->fs.name);
-					threadexitsall("serial line gone");
-				}
-			} else {
-				errrun = 0;
-				good++;
-			}
-			if(usbdebug >= 3)
-				dsprint(2, "serial: read: %s %ld\n", err, rcount);
-		} while(rcount < 0 && strstr(err, "timed out") != nil);
-
-		dsprint(2, "serial: read from bulk %ld, %10.10s\n", rcount, err);
-		if(rcount < 0){
-			dsprint(2, "serial: need to recover, data read %ld %r\n",
-				count);
-			serialrecover(ser, p, p->epin, err);
-		}
-		dsprint(2, "serial: read from bulk %ld\n", rcount);
-		count = rcount;
-		break;
-	case Qctl:
-		if(offset != 0)
-			count = 0;
-		else {
-			if(!p->isjtag){
-				e = serdumpst(p, buf, Serbufsize);
-				count = usbreadbuf(data, count, 0, buf, e - buf);
-			}
-		}
-		break;
-	}
-	if(count >= 0)
-		ser->recover = 0;
-	qunlock(ser);
-	free(err);
-	free(buf);
-	return count;
-}
-
-static long
-altwrite(Serialport *p, uchar *buf, long count)
-{
-	int nw, dfd;
-	char err[128];
-	Serial *ser;
-
-	ser = p->s;
-	do{
-		dsprint(2, "serial: write to bulk %ld\n", count);
-
-		if(ser->wait4write != nil)
-			/* unlocked inside later */
-			nw = ser->wait4write(p, buf, count);
-		else{
-			dfd = p->epout->dfd;
-			qunlock(ser);
-			nw = write(dfd, buf, count);
-			qlock(ser);
-		}
-		rerrstr(err, sizeof err);
-		dsprint(2, "serial: written %s %d\n", err, nw);
-	} while(nw < 0 && strstr(err, "timed out") != nil);
-
-	if(nw != count){
-		dsprint(2, "serial: need to recover, status in write %d %r\n",
-			nw);
-		snprint(err, sizeof err, "%r");
-		serialrecover(p->s, p, p->epout, err);
-	}
-	return nw;
-}
-
-static long
-dwrite(Usbfs *fs, Fid *fid, void *buf, long count, vlong)
-{
-	ulong path;
-	char *cmd;
-	Serialport *p;
-	Serial *ser;
-
-	p = fs->aux;
-	ser = p->s;
-	path = fid->qid.path & ~fs->qid;
-
-	qlock(ser);
-	switch(path){
-	case Qdata:
-		count = altwrite(p, (uchar *)buf, count);
-		break;
-	case Qctl:
-		if(p->isjtag)
-			break;
-		cmd = emallocz(count+1, 1);
-		memmove(cmd, buf, count);
-		cmd[count] = 0;
-		if(serialctl(p, cmd) < 0){
-			qunlock(ser);
-			werrstr(Ebadctl);
-			free(cmd);
-			return -1;
-		}
-		free(cmd);
-		break;
-	default:
-		qunlock(ser);
-		werrstr(Eperm);
-		return -1;
-	}
-	if(count >= 0)
-		ser->recover = 0;
-	else
-		serialrecover(ser, p, p->epout, "writing");
-	qunlock(ser);
-	return count;
-}
-
-static int
-openeps(Serialport *p, int epin, int epout, int epintr)
-{
-	Serial *ser;
-
-	ser = p->s;
-	p->epin = openep(ser->dev, epin);
-	if(p->epin == nil){
-		fprint(2, "serial: openep %d: %r\n", epin);
-		return -1;
-	}
-	p->epout = openep(ser->dev, epout);
-	if(p->epout == nil){
-		fprint(2, "serial: openep %d: %r\n", epout);
-		closedev(p->epin);
-		return -1;
-	}
-
-	if(!p->isjtag){
-		devctl(p->epin,  "timeout 1000");
-		devctl(p->epout, "timeout 1000");
-	}
-
-	if(ser->hasepintr){
-		p->epintr = openep(ser->dev, epintr);
-		if(p->epintr == nil){
-			fprint(2, "serial: openep %d: %r\n", epintr);
-			closedev(p->epin);
-			closedev(p->epout);
-			return -1;
-		}
-		opendevdata(p->epintr, OREAD);
-		devctl(p->epintr, "timeout 1000");
-	}
-
-	if(ser->seteps!= nil)
-		ser->seteps(p);
-	opendevdata(p->epin, OREAD);
-	opendevdata(p->epout, OWRITE);
-	if(p->epin->dfd < 0 ||p->epout->dfd < 0 ||
-	    (ser->hasepintr && p->epintr->dfd < 0)){
-		fprint(2, "serial: open i/o ep data: %r\n");
-		closedev(p->epin);
-		closedev(p->epout);
-		if(ser->hasepintr)
-			closedev(p->epintr);
-		return -1;
-	}
-	return 0;
-}
-
-static int
-findendpoints(Serial *ser, int ifc)
-{
-	int i, epin, epout, epintr;
-	Ep *ep, **eps;
-
-	epintr = epin = epout = -1;
-
-	/*
-	 * interfc 0 means start from the start which is equiv to
-	 * iterate through endpoints probably, could be done better
-	 */
-	eps = ser->dev->usb->conf[0]->iface[ifc]->ep;
-
-	for(i = 0; i < Nep; i++){
-		if((ep = eps[i]) == nil)
-			continue;
-		if(ser->hasepintr && ep->type == Eintr &&
-		    ep->dir == Ein && epintr == -1)
-			epintr = ep->id;
-		if(ep->type == Ebulk){
-			if(ep->dir == Ein && epin == -1)
-				epin = ep->id;
-			if(ep->dir == Eout && epout == -1)
-				epout = ep->id;
-		}
-	}
-	dprint(2, "serial[%d]: ep ids: in %d out %d intr %d\n", ifc, epin, epout, epintr);
-	if(epin == -1 || epout == -1 || (ser->hasepintr && epintr == -1))
-		return -1;
-
-	if(openeps(&ser->p[ifc], epin, epout, epintr) < 0)
-		return -1;
-
-	dprint(2, "serial: ep in %s out %s\n", ser->p[ifc].epin->dir, ser->p[ifc].epout->dir);
-	if(ser->hasepintr)
-		dprint(2, "serial: ep intr %s\n", ser->p[ifc].epintr->dir);
-
-	if(usbdebug > 1 || serialdebug > 2){
-		devctl(ser->p[ifc].epin,  "debug 1");
-		devctl(ser->p[ifc].epout, "debug 1");
-		if(ser->hasepintr)
-			devctl(ser->p[ifc].epintr, "debug 1");
-		devctl(ser->dev, "debug 1");
-	}
-	return 0;
-}
-
-/* keep in sync with main.c */
-static int
-usage(void)
-{
-	werrstr("usage: usb/serial [-dD] [-m mtpt] [-s srv]");
-	return -1;
-}
-
-static void
-serdevfree(void *a)
-{
-	Serial *ser = a;
-	Serialport *p;
-	int i;
-
-	if(ser == nil)
-		return;
-
-	for(i = 0; i < ser->nifcs; i++){
-		p = &ser->p[i];
-
-		if(ser->hasepintr)
-			closedev(p->epintr);
-		closedev(p->epin);
-		closedev(p->epout);
-		p->epintr = p->epin = p->epout = nil;
-		if(p->w4data != nil)
-			chanfree(p->w4data);
-		if(p->gotdata != nil)
-			chanfree(p->gotdata);
-		if(p->readc)
-			chanfree(p->readc);
-
-	}
-	free(ser);
-}
-
-static Usbfs serialfs = {
-	.walk =	dwalk,
-	.open =	dopen,
-	.read =	dread,
-	.write=	dwrite,
-	.stat =	dstat,
-};
-
-static void
-serialfsend(Usbfs *fs)
-{
-	Serialport *p;
-
-	p = fs->aux;
-
-	if(p->w4data != nil)
-		chanclose(p->w4data);
-	if(p->gotdata != nil)
-		chanclose(p->gotdata);
-	if(p->readc)
-		chanclose(p->readc);
-}
-
-int
-serialmain(Dev *dev, int argc, char* argv[])
-{
-	Serial *ser;
-	Serialport *p;
-	char buf[50];
-	int i, devid;
-
-	devid = dev->id;
-	ARGBEGIN{
-	case 'd':
-		serialdebug++;
-		break;
-	case 'N':
-		devid = atoi(EARGF(usage()));
-		break;
-	default:
-		return usage();
-	}ARGEND
-	if(argc != 0)
-		return usage();
-
-	ser = dev->aux = emallocz(sizeof(Serial), 1);
-	ser->maxrtrans = ser->maxwtrans = sizeof ser->p[0].data;
-	ser->maxread = ser->maxwrite = sizeof ser->p[0].data;
-	ser->dev = dev;
-	dev->free = serdevfree;
-	ser->jtag = -1;
-	ser->nifcs = 1;
-
-	snprint(buf, sizeof buf, "vid %#06x did %#06x",
-		dev->usb->vid, dev->usb->did);
-	if(plmatch(buf) == 0){
-		ser->hasepintr = 1;
-		ser->Serialops = plops;
-	} else if(uconsmatch(buf) == 0)
-		ser->Serialops = uconsops;
-	else if(ftmatch(ser, buf) == 0)
-		ser->Serialops = ftops;
-	else {
-		werrstr("serial: no serial devices found");
-		return -1;
-	}
-	for(i = 0; i < ser->nifcs; i++){
-		p = &ser->p[i];
-		p->interfc = i;
-		p->s = ser;
-		p->fs = serialfs;
-		if(i == ser->jtag){
-			p->isjtag++;
-		}
-		if(findendpoints(ser, i) < 0){
-			werrstr("serial: no endpoints found for ifc %d", i);
-			return -1;
-		}
-		p->w4data  = chancreate(sizeof(ulong), 0);
-		p->gotdata = chancreate(sizeof(ulong), 0);
-	}
-
-	qlock(ser);
-	serialreset(ser);
-	for(i = 0; i < ser->nifcs; i++){
-		p = &ser->p[i];
-		dprint(2, "serial: valid interface, calling serinit\n");
-		if(serinit(p) < 0){
-			dprint(2, "serial: serinit: %r\n");
-			return -1;
-		}
-
-		dsprint(2, "serial: adding interface %d, %p\n", p->interfc, p);
-		if(p->isjtag){
-			snprint(p->name, sizeof p->name, "jtag");
-			dsprint(2, "serial: JTAG interface %d %p\n", i, p);
-			snprint(p->fs.name, sizeof p->fs.name, "jtag%d.%d", devid, i);
-		} else {
-			snprint(p->name, sizeof p->name, "eiaU");
-			if(i == 0)
-				snprint(p->fs.name, sizeof p->fs.name, "eiaU%d", devid);
-			else
-				snprint(p->fs.name, sizeof p->fs.name, "eiaU%d.%d", devid, i);
-		}
-		fprint(2, "%s...", p->fs.name);
-		p->fs.dev = dev;
-		incref(dev);
-		p->fs.aux = p;
-		p->fs.end = serialfsend;
-		usbfsadd(&p->fs);
-	}
-
-	qunlock(ser);
-	return 0;
-}
--- a/sys/src/cmd/usb/serial/serial.h
+++ /dev/null
@@ -1,126 +1,0 @@
-typedef struct Serial Serial;
-typedef struct Serialops Serialops;
-typedef struct Serialport Serialport;
-
-struct Serialops {
-	int	(*seteps)(Serialport*);
-	int	(*init)(Serialport*);
-	int	(*getparam)(Serialport*);
-	int	(*setparam)(Serialport*);
-	int	(*clearpipes)(Serialport*);
-	int	(*reset)(Serial*, Serialport*);
-	int	(*sendlines)(Serialport*);
-	int	(*modemctl)(Serialport*, int);
-	int	(*setbreak)(Serialport*, int);
-	int	(*readstatus)(Serialport*);
-	int	(*wait4data)(Serialport*, uchar *, int);
-	int	(*wait4write)(Serialport*, uchar *, int);
-};
-
-enum {
-	DataBufSz = 8*1024,
-	Maxifc = 16,
-};
-
-
-struct Serialport {
-	char name[32];
-	Serial	*s;		/* device we belong to */
-	int	isjtag;
-
-	Dev	*epintr;	/* may not exist */
-
-	Dev	*epin;
-	Dev	*epout;
-
-	Usbfs	fs;
-	uchar	ctlstate;
-
-	/* serial parameters */
-	uint	baud;
-	int	stop;
-	int	mctl;
-	int	parity;
-	int	bits;
-	int	fifo;
-	int	limit;
-	int	rts;
-	int	cts;
-	int	dsr;
-	int	dcd;
-	int	dtr;
-	int	rlsd;
-
-	vlong	timer;
-	int	blocked;	/* for sw flow ctl. BUG: not implemented yet */
-	int	nbreakerr;
-	int	ring;
-	int	nframeerr;
-	int	nparityerr;
-	int	novererr;
-	int	enabled;
-
-	int	interfc;	/* interfc on the device for ftdi */
-
-	Channel *w4data;
-	Channel *gotdata;
-	Channel *readc;		/* to uncouple reads, only used in ftdi... */
-	int	ndata;
-	uchar	data[DataBufSz];
-};
-
-struct Serial {
-	QLock;
-	Dev	*dev;		/* usb device*/
-
-	int	type;		/* serial model subtype */
-	int	recover;	/* # of non-fatal recovery tries */
-	Serialops;
-
-	int	hasepintr;
-
-	int	jtag;		/* index of jtag interface, -1 none */
-	int	nifcs;		/* # of serial interfaces, including JTAG */
-	Serialport p[Maxifc];
-	int	maxrtrans;
-	int	maxwtrans;
-
-	int	maxread;
-	int	maxwrite;
-
-	int	inhdrsz;
-	int	outhdrsz;
-	int	baudbase;	/* for special baud base settings, see ftdi */
-};
-
-enum {
-	/* soft flow control chars */
-	CTLS	= 023,
-	CTLQ	= 021,
-	CtlDTR	= 1,
-	CtlRTS	= 2,
-};
-
-/*
- * !hget http://lxr.linux.no/source/drivers/usb/serial/pl2303.h|htmlfmt
- * !hget http://lxr.linux.no/source/drivers/usb/serial/pl2303.c|htmlfmt
- */
-
-int serialmain(Dev *d, int argc, char *argv[]);
-
-typedef struct Cinfo Cinfo;
-struct Cinfo {
-	int	vid;		/* usb vendor id */
-	int	did;		/* usb device/product id */
-	int	cid;		/* controller id assigned by us */
-};
-
-extern Cinfo plinfo[];
-extern Cinfo uconsinfo[];
-extern int serialdebug;
-
-#define	dsprint	if(serialdebug)fprint
-
-int	serialrecover(Serial *ser, Serialport *p, Dev *ep, char *err);
-int	serialreset(Serial *ser);
-char	*serdumpst(Serialport *p, char *buf, int bufsz);
--- a/sys/src/cmd/usb/serial/ucons.c
+++ /dev/null
@@ -1,47 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "serial.h"
-#include "ucons.h"
-
-Cinfo uconsinfo[] = {
-	{ Net20DCVid,	Net20DCDid },
-	{ 0,		0 },
-};
-
-int
-uconsmatch(char *info)
-{
-	Cinfo *ip;
-	char buf[50];
-
-	for(ip = uconsinfo; ip->vid != 0; ip++){
-		snprint(buf, sizeof buf, "vid %#06x did %#06x",
-			ip->vid, ip->did);
-		dsprint(2, "serial: %s %s\n", buf, info);
-		if(strstr(info, buf) != nil)
-			return 0;
-	}
-	return -1;
-}
-
-static int
-ucseteps(Serialport *p)
-{
-	Serial *ser;
-
-	ser = p->s;
-
-	p->baud = ~0;	/* not real port */
-	ser->maxrtrans = ser->maxwtrans = 8;
-	devctl(p->epin,  "maxpkt 8");
-	devctl(p->epout, "maxpkt 8");
-	return 0;
-}
-
-/* all nops */
-Serialops uconsops = {
-	.seteps = ucseteps,
-};
--- a/sys/src/cmd/usb/serial/ucons.h
+++ /dev/null
@@ -1,9 +1,0 @@
-
-
-enum {
-	Net20DCVid =	0x0525,	/* Ajays usb debug cable */
-	Net20DCDid =	0x127a,
-};
-
-int	uconsmatch(char *info);
-extern Serialops uconsops;
--- a/sys/src/cmd/usb/usbd/dev.c
+++ /dev/null
@@ -1,283 +1,0 @@
-/*
- * Framework for USB devices.
- * Some of them may be embedded into usbd and some of
- * them may exist as /bin/usb/* binaries on their own.
- *
- * When embedded, devmain() is given a ref of an already
- * configured and open Dev. If devmain()
- * does not fail it should release this ref when done and
- * use incref to add further refs to it.
- */
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbd.h"
-
-static Lock masklck;
-extern Devtab devtab[];
-static char* cputype;
-
-int
-getdevnb(uvlong *maskp)
-{
-	int i;
-
-	lock(&masklck);
-	for(i = 0; i < 8 * sizeof *maskp; i++)
-		if((*maskp & (1ULL<<i)) == 0){
-			*maskp |= 1ULL<<i;
-			unlock(&masklck);
-			return i;
-		}
-	unlock(&masklck);
-	return -1;
-}
-
-void
-putdevnb(uvlong *maskp, int id)
-{
-	lock(&masklck);
-	if(id >= 0)
-		*maskp &= ~(1ULL<<id);
-	unlock(&masklck);
-}
-		
-static int
-cspmatch(Devtab *dt, int dcsp)
-{
-	int	i;
-	int	csp;
-
-	for(i = 0; i < nelem(dt->csps); i++)
-		if((csp=dt->csps[i]) != 0)
-		if(csp == dcsp)
-			return 1;
-		else if((csp&DCL) && (csp&~DCL) == Class(dcsp))
-			return 1;
-	return 0;
-}
-
-static int
-devmatch(Devtab *dt, Usbdev *d)
-{
-	int i;
-	int c;
-	Conf *cp;
-
-	if(dt->vid != -1 && d->vid != dt->vid)
-		return 0;
-	if(dt->did != -1 && d->did != dt->did)
-		return 0;
-	if(cspmatch(dt, d->csp))
-		return 1;
-	for(c = 0; c < Nconf; c++)
-		if((cp=d->conf[c]) != nil)
-			for(i = 0; i < Niface; i++)
-				if(cp->iface[i] != nil)
-					if(cspmatch(dt, cp->iface[i]->csp))
-						return 1;
-	return 0;
-}
-
-/* We can't use procexec to execute drivers, because
- * procexec mounts #| at /mnt/temp and we do *not*
- * have /mnt/temp at boot time.
- * Instead, we use access to guess if we can execute the file.
- * and reply as procexec. Be careful that the child inherits
- * all the shared state of the thread library. It should run unnoticed.
- */
-static void
-xexec(Channel *c, char *nm, char *args[])
-{
-	int	pid;
-
-	if(access(nm, AEXEC) == 0){
-		pid = rfork(RFFDG|RFREND|RFPROC);
-		switch(pid){
-		case 0:
-			exec(nm, args);
-			_exits("exec");
-		case -1:
-			break;
-		default:
-			sendul(c, pid);
-			threadexits(nil);
-		}
-	}
-}
-
-typedef struct Sarg Sarg;
-struct Sarg{
-	Port *pp;
-	Devtab* dt;
-	Channel*rc;
-	char fname[80];
-	char	args[128];
-	char	*argv[40];
-};
-
-static void
-startdevproc(void *a)
-{
-	Sarg	*sa = a;
-	Dev	*d;
-	Devtab *dt;
-	int	argc;
-	char *args, *argse, **argv;
-	char *fname;
-
-	threadsetgrp(threadid());
-	d = sa->pp->dev;
-	dt = sa->dt;
-	args = sa->args;
-	argse = sa->args + sizeof sa->args;
-	argv = sa->argv;
-	fname = sa->fname;
-	sa->pp->devmaskp = &dt->devmask;
-	sa->pp->devnb = getdevnb(&dt->devmask);
-	if(sa->pp->devnb < 0){
-		sa->pp->devmaskp = nil;
-		sa->pp->devnb = 0;
-	}else
-		args = seprint(args, argse, "-N %d", sa->pp->devnb);
-	if(dt->args != nil)
-		seprint(args, argse, " %s", dt->args);
-	args = sa->args;
-	dprint(2, "%s: start: %s %s\n", argv0, dt->name, args);
-	argv[0] = dt->name;
-	argc = 1;
-	if(args[0] != 0)
-		argc += tokenize(args, argv+1, nelem(sa->argv)-2);
-	argv[argc] = nil;
-	if(dt->init == nil){
-		if(d->dfd > 0 ){
-			close(d->dfd);
-			d->dfd = -1;
-		}
-		rfork(RFCFDG);
-		open("/dev/null", OREAD);
-		open("/dev/cons", OWRITE);
-		open("/dev/cons", OWRITE);
-
-		xexec(sa->rc, argv[0], argv);
-		snprint(fname, sizeof(sa->fname), "/bin/usb/%s", dt->name);
-		xexec(sa->rc, fname, argv);
-		snprint(fname, sizeof(sa->fname), "/boot/%s", dt->name);
-		xexec(sa->rc, fname, argv);
-		if(cputype == nil)
-			cputype = getenv("cputype");
-		if(cputype != nil){
-			snprint(fname, sizeof(sa->fname), "/%s/bin/%s",
-				cputype, dt->name);
-			argv[0] = fname;
-			xexec(sa->rc, fname, argv);
-		}
-		fprint(2, "%s: %s: not found. can't exec\n", argv0, dt->name);
-		sendul(sa->rc, -1);
-		threadexits("exec");
-	}else{
-		sa->pp->dev = opendev(d->dir);
-		sendul(sa->rc, 0);
-		if(dt->init(d, argc, argv) < 0)
-			fprint(2, "%s: %s: %r\n", argv0, dt->name);
-		closedev(d);
-		free(sa);
-	}
-	threadexits(nil);
-}
-
-static void
-writeinfo(Dev *d)
-{
-	char buf[128];
-	char *s;
-	char *se;
-	Usbdev *ud;
-	Conf *c;
-	Iface *ifc;
-	int i, j;
-
-	ud = d->usb;
-	s = buf;
-	se = buf+sizeof(buf);
-	s = seprint(s, se, "info %s csp %#08ulx", classname(ud->class), ud->csp);
-	for(i = 0; i < ud->nconf; i++){
-		c = ud->conf[i];
-		if(c == nil)
-			break;
-		for(j = 0; j < nelem(c->iface); j++){
-			ifc = c->iface[j];
-			if(ifc == nil)
-				break;
-			if(ifc->csp != ud->csp)
-				s = seprint(s, se, " csp %#08ulx", ifc->csp);
-		}
-	}
-	s = seprint(s, se, " vid %06#x did %06#x", ud->vid, ud->did);
-	seprint(s, se, " %q %q", ud->vendor, ud->product);
-	devctl(d, "%s", buf);
-}
-
-int
-startdev(Port *pp)
-{
-	Dev *d;
-	Usbdev *ud;
-	Devtab *dt;
-	Sarg *sa;
-	Channel *rc;
-
-	d = pp->dev;
-	assert(d);
-	ud = d->usb;
-	assert(ud != nil);
-
-	writeinfo(d);
-
-	if(ud->class == Clhub){
-		/*
-		 * Hubs are handled directly by this process avoiding
-		 * concurrent operation so that at most one device
-		 * has the config address in use.
-		 * We cancel kernel debug for these eps. too chatty.
-		 */
-		pp->hub = newhub(d->dir, d);
-		if(pp->hub == nil)
-			fprint(2, "%s: %s: %r\n", argv0, d->dir);
-		else
-			fprint(2, "usb/hub... ");
-		if(usbdebug > 1)
-			devctl(d, "debug 0");	/* polled hubs are chatty */
-		return pp->hub == nil ? -1 : 0;
-	}
-
-	for(dt = devtab; dt->name != nil; dt++)
-		if(devmatch(dt, ud))
-			break;
-	/*
-	 * From here on the device is for the driver.
-	 * When we return pp->dev contains a Dev just for us
-	 * with only the ctl open. Both devs are released on the last closedev:
-	 * driver's upon I/O errors and ours upon port dettach.
-	 */
-	if(dt->name == nil){
-		dprint(2, "%s: no configured entry for %s (csp %#08lx)\n",
-			argv0, d->dir, ud->csp);
-		close(d->dfd);
-		d->dfd = -1;
-		return 0;
-	}
-	sa = emallocz(sizeof(Sarg), 1);
-	sa->pp = pp;
-	sa->dt = dt;
-	rc = sa->rc = chancreate(sizeof(ulong), 1);
-	procrfork(startdevproc, sa, Stack, RFNOTEG);
-	if(recvul(rc) != 0)
-		free(sa);
-	chanfree(rc);
-	fprint(2, "usb/%s... ", dt->name);
-
-	sleep(Spawndelay);		/* in case we re-spawn too fast */
-	return 0;
-}
--- a/sys/src/cmd/usb/usbd/mkdev
+++ /dev/null
@@ -1,115 +1,0 @@
-#!/bin/rc
-rfork e
-
-DB=usbdb
-HDR=../lib/usb.h
-
-subs=`{	grep '^	Cl.*' $HDR | 
-		sed -e 's/.*Cl([a-z]+)[ 	]+=[ 	]+([0-9]+).*/-e s.\1,.\2,./' |
-		tr A-Z a-z
-}
-cat<<EOF
-/* machine generated. do not edit */
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include "usb.h"
-#include "usbd.h"
-
-EOF
-
-awk '
-/^#|^$/	{ next }
-collect && /^[^ \t]/{
-	collect = 0;
-}
-$0 ~ /^(embed|auto)/{
-	section = $0;
-	collect = 1;
-	next;
-}
-collect {
-	if(section ~ "embed"){
-		printf("extern int %smain(Dev*, int, char**);\n", $1);
-	}
-}
-' $DB
-cat <<EOF
-
-Devtab devtab[] = {
-	/* device, entrypoint, {csp, csp, csp csp}, vid, did */
-EOF
-
-awk '
-/^#|^$/	{ next }
-collect && /^[^ \t]/{
-	collect = 0;
-}
-$0 ~ /^(embed|auto)/{
-	section = $0;
-	collect = 1;
-	next;
-}
-collect {
-	printf("	{\"%s\"", $1);
-	if(section ~ "embed"){
-		fns[nfns++] = $1;
-		printf(",\t%smain", $1);
-	} else
-		printf(", nil");
-	printf(",\t{");
-	ncsp = 0;
-	vid="-1";
-	did="-1";
-	args="";
-	for(i = 2; i <= NF; i++)
-		if($i ~ "^args="){
-			sub("args=", "", $i);
-			for(j = i; j <= NF; j++)
-				if(j > i)
-					args = args  " " $j;
-				else
-					args = $j
-		}
-	for(i = 2; i <= NF; i++){
-		if($i ~ "^csp="){
-			ncsp++;
-			sub("csp=", "", $i);
-			printf("%s, ", $i);
-		} else
-		if($i ~ "^subclass="){
-			ncsp++;
-			sub("subclass=", "", $i);
-			printf("DSC|%s, ", $i);
-		} else
-		if($i ~ "^class="){
-			ncsp++;
-			sub("class=", "", $i);
-			printf("DCL|%s, ", $i);
-		} else
-		if($i ~ "^proto="){
-			ncsp++;
-			sub("proto=", "", $i);
-			printf("DPT|%s, ", $i);
-		} else
-		if($i ~ "^vid="){
-			sub("vid=", "", $i);
-			vid=$i
-		} else
-		if($i ~ "did="){
-			sub("did=", "", $i);
-			did=$i
-		}
-	}
-	for(i = ncsp; i < 4; i++)
-		printf("0, ");
-	printf("}, %s, %s, \"%s\"},\n", vid, did, args);
-}
-' $DB | sed $subs
-
-cat <<EOF
-	{nil, nil,	{0, 0, 0, 0, }, -1, -1, nil},
-};
-
-/* end of machine generated */
-EOF
--- a/sys/src/cmd/usb/usbd/mkfile
+++ /dev/null
@@ -1,39 +1,0 @@
-</$objtype/mkfile
-
-TARG=usbd
-OFILES=\
-	usbd.$O\
-	dev.$O\
-	devtab.$O\
-
-HFILES=\
-	usbd.h\
-	../lib/usb.h\
-	../lib/usbfs.h\
-
-LIBD=../lib/usbdev.a$O
-LIBU=../lib/usb.a$O
-LIB=\
-	$LIBD\
-	$LIBU\
-
-UPDATE=\
-	$HFILES\
-	${OFILES:%.$O=%.c}\
-	mkfile\
-	/sys/man/3/usb\
-
-BIN=/$objtype/bin/usb
-</sys/src/cmd/mkone
-
-CFLAGS=-I../lib $CFLAGS
-CLEANFILES=devtab.c
-
-$LIBU:
-	cd ../lib
-	mk install
-	mk clean
-
-devtab.c: usbdb ../lib/usb.h mkdev
-	mkdev >$target
-
--- a/sys/src/cmd/usb/usbd/usbd.c
+++ /dev/null
@@ -1,875 +1,0 @@
-#include <u.h>
-#include <libc.h>
-#include <thread.h>
-#include <fcall.h>
-#include "usb.h"
-#include "usbfs.h"
-#include "usbd.h"
-
-static Channel *portc;
-static int win;
-static int verbose;
-
-int mainstacksize = Stack;
-static Hub *hubs;
-static int nhubs;
-static int mustdump;
-static int pollms = Pollms;
-
-static char *dsname[] = { "disabled", "attached", "configed" };
-
-static int
-hubfeature(Hub *h, int port, int f, int on)
-{
-	int cmd;
-
-	if(on)
-		cmd = Rsetfeature;
-	else
-		cmd = Rclearfeature;
-	return usbcmd(h->dev, Rh2d|Rclass|Rother, cmd, f, port, nil, 0);
-}
-
-/*
- * This may be used to detect overcurrent on the hub
- */
-static void
-checkhubstatus(Hub *h)
-{
-	uchar buf[4];
-	int sts;
-
-	if(h->isroot)	/* not for root hubs */
-		return;
-	if(usbcmd(h->dev, Rd2h|Rclass|Rdev, Rgetstatus, 0, 0, buf, 4) < 0){
-		dprint(2, "%s: get hub status: %r\n", h->dev->dir);
-		return;
-	}
-	sts = GET2(buf);
-	dprint(2, "hub %s: status %#ux\n", h->dev->dir, sts);
-}
-
-static int
-confighub(Hub *h)
-{
-	int type;
-	uchar buf[128];	/* room for extra descriptors */
-	int i;
-	Usbdev *d;
-	DHub *dd;
-	Port *pp;
-	int nr;
-	int nmap;
-	uchar *PortPwrCtrlMask;
-	int offset;
-	int mask;
-
-	d = h->dev->usb;
-	for(i = 0; i < nelem(d->ddesc); i++)
-		if(d->ddesc[i] == nil)
-			break;
-		else if(d->ddesc[i]->data.bDescriptorType == Dhub){
-			dd = (DHub*)&d->ddesc[i]->data;
-			nr = Dhublen;
-			goto Config;
-		}
-	type = Rd2h|Rclass|Rdev;
-	nr = usbcmd(h->dev, type, Rgetdesc, Dhub<<8|0, 0, buf, sizeof buf);
-	if(nr < Dhublen){
-		dprint(2, "%s: %s: getdesc hub: %r\n", argv0, h->dev->dir);
-		return -1;
-	}
-	dd = (DHub*)buf;
-Config:
-	h->nport = dd->bNbrPorts;
-	nmap = 1 + h->nport/8;
-	if(nr < 7 + 2*nmap){
-		fprint(2, "%s: %s: descr. too small\n", argv0, h->dev->dir);
-		return -1;
-	}
-	h->port = emallocz((h->nport+1)*sizeof(Port), 1);
-	h->pwrms = dd->bPwrOn2PwrGood*2;
-	if(h->pwrms < Powerdelay)
-		h->pwrms = Powerdelay;
-	h->maxcurrent = dd->bHubContrCurrent;
-	h->pwrmode = dd->wHubCharacteristics[0] & 3;
-	h->compound = (dd->wHubCharacteristics[0] & (1<<2))!=0;
-	h->leds = (dd->wHubCharacteristics[0] & (1<<7)) != 0;
-	PortPwrCtrlMask = dd->DeviceRemovable + nmap;
-	for(i = 1; i <= h->nport; i++){
-		pp = &h->port[i];
-		offset = i/8;
-		mask = 1<<(i%8);
-		pp->removable = (dd->DeviceRemovable[offset] & mask) != 0;
-		pp->pwrctl = (PortPwrCtrlMask[offset] & mask) != 0;
-	}
-	return 0;
-}
-
-static void
-configroothub(Hub *h)
-{
-	Dev *d;
-	char buf[128];
-	char *p;
-	int nr;
-
-	d = h->dev;
-	h->nport = 2;
-	h->maxpkt = 8;
-	seek(d->cfd, 0, 0);
-	nr = read(d->cfd, buf, sizeof(buf)-1);
-	if(nr < 0)
-		goto Done;
-	buf[nr] = 0;
-
-	p = strstr(buf, "ports ");
-	if(p == nil)
-		fprint(2, "%s: %s: no port information\n", argv0, d->dir);
-	else
-		h->nport = atoi(p+6);
-	p = strstr(buf, "maxpkt ");
-	if(p == nil)
-		fprint(2, "%s: %s: no maxpkt information\n", argv0, d->dir);
-	else
-		h->maxpkt = atoi(p+7);
-Done:
-	h->port = emallocz((h->nport+1)*sizeof(Port), 1);
-	dprint(2, "%s: %s: ports %d maxpkt %d\n", argv0, d->dir, h->nport, h->maxpkt);
-}
-
-Hub*
-newhub(char *fn, Dev *d)
-{
-	Hub *h;
-	int i;
-	Usbdev *ud;
-
-	h = emallocz(sizeof(Hub), 1);
-	h->isroot = (d == nil);
-	if(h->isroot){
-		h->dev = opendev(fn);
-		if(h->dev == nil){
-			fprint(2, "%s: opendev: %s: %r", argv0, fn);
-			goto Fail;
-		}
-		if(opendevdata(h->dev, ORDWR) < 0){
-			fprint(2, "%s: opendevdata: %s: %r\n", argv0, fn);
-			goto Fail;
-		}
-		configroothub(h);	/* never fails */
-	}else{
-		h->dev = d;
-		if(confighub(h) < 0){
-			fprint(2, "%s: %s: config: %r\n", argv0, fn);
-			goto Fail;
-		}
-	}
-	if(h->dev == nil){
-		fprint(2, "%s: opendev: %s: %r\n", argv0, fn);
-		goto Fail;
-	}
-	devctl(h->dev, "hub");
-	ud = h->dev->usb;
-	if(h->isroot)
-		devctl(h->dev, "info roothub csp %#08ux ports %d",
-			0x000009, h->nport);
-	else{
-		devctl(h->dev, "info hub csp %#08ulx ports %d %q %q",
-			ud->csp, h->nport, ud->vendor, ud->product);
-		for(i = 1; i <= h->nport; i++)
-			if(hubfeature(h, i, Fportpower, 1) < 0)
-				fprint(2, "%s: %s: power: %r\n", argv0, fn);
-		sleep(h->pwrms);
-		for(i = 1; i <= h->nport; i++)
-			if(h->leds != 0)
-				hubfeature(h, i, Fportindicator, 1);
-	}
-	h->next = hubs;
-	hubs = h;
-	nhubs++;
-	dprint(2, "%s: hub %#p allocated:", argv0, h);
-	dprint(2, " ports %d pwrms %d max curr %d pwrm %d cmp %d leds %d\n",
-		h->nport, h->pwrms, h->maxcurrent,
-		h->pwrmode, h->compound, h->leds);
-	incref(h->dev);
-	return h;
-Fail:
-	if(d != nil)
-		devctl(d, "detach");
-	free(h->port);
-	free(h);
-	dprint(2, "%s: hub %#p failed to start:", argv0, h);
-	return nil;
-}
-
-static void portdetach(Hub *h, int p);
-
-/*
- * If during enumeration we get an I/O error the hub is gone or
- * in pretty bad shape. Because of retries of failed usb commands
- * (and the sleeps they include) it can take a while to detach all
- * ports for the hub. This detaches all ports and makes the hub void.
- * The parent hub will detect a detach (probably right now) and
- * close it later.
- */
-static void
-hubfail(Hub *h)
-{
-	int i;
-
-	for(i = 1; i <= h->nport; i++)
-		portdetach(h, i);
-	h->failed = 1;
-}
-
-static void
-closehub(Hub *h)
-{
-	Hub **hl;
-
-	dprint(2, "%s: closing hub %#p\n", argv0, h);
-	for(hl = &hubs; *hl != nil; hl = &(*hl)->next)
-		if(*hl == h)
-			break;
-	if(*hl == nil)
-		sysfatal("closehub: no hub");
-	*hl = h->next;
-	nhubs--;
-	hubfail(h);		/* detach all ports */
-	free(h->port);
-	assert(h->dev != nil);
-	devctl(h->dev, "detach");
-	closedev(h->dev);
-	free(h);
-}
-
-static int
-portstatus(Hub *h, int p)
-{
-	Dev *d;
-	uchar buf[4];
-	int t;
-	int sts;
-	int dbg;
-
-	dbg = usbdebug;
-	if(dbg != 0 && dbg < 4)
-		usbdebug = 1;	/* do not be too chatty */
-	d = h->dev;
-	t = Rd2h|Rclass|Rother;
-	if(usbcmd(d, t, Rgetstatus, 0, p, buf, sizeof(buf)) < 0)
-		sts = -1;
-	else
-		sts = GET2(buf);
-	usbdebug = dbg;
-	return sts;
-}
-
-static char*
-stsstr(int sts)
-{
-	static char s[80];
-	char *e;
-
-	e = s;
-	if(sts&PSsuspend)
-		*e++ = 'z';
-	if(sts&PSreset)
-		*e++ = 'r';
-	if(sts&PSslow)
-		*e++ = 'l';
-	if(sts&PShigh)
-		*e++ = 'h';
-	if(sts&PSchange)
-		*e++ = 'c';
-	if(sts&PSenable)
-		*e++ = 'e';
-	if(sts&PSstatuschg)
-		*e++ = 's';
-	if(sts&PSpresent)
-		*e++ = 'p';
-	if(e == s)
-		*e++ = '-';
-	*e = 0;
-	return s;
-}
-
-static int
-getmaxpkt(Dev *d, int islow)
-{
-	uchar buf[64];	/* More room to try to get device-specific descriptors */
-	DDev *dd;
-
-	dd = (DDev*)buf;
-	if(islow)
-		dd->bMaxPacketSize0 = 8;
-	else
-		dd->bMaxPacketSize0 = 64;
-	if(usbcmd(d, Rd2h|Rstd|Rdev, Rgetdesc, Ddev<<8|0, 0, buf, sizeof(buf)) < 0)
-		return -1;
-	return dd->bMaxPacketSize0;
-}
-
-/*
- * BUG: does not consider max. power avail.
- */
-static Dev*
-portattach(Hub *h, int p, int sts)
-{
-	Dev *d;
-	Port *pp;
-	Dev *nd;
-	char fname[80];
-	char buf[40];
-	char *sp;
-	int mp;
-	int nr;
-
-	d = h->dev;
-	pp = &h->port[p];
-	nd = nil;
-	pp->state = Pattached;
-	dprint(2, "%s: %s: port %d attach sts %#ux\n", argv0, d->dir, p, sts);
-	sleep(Connectdelay);
-	if(hubfeature(h, p, Fportenable, 1) < 0)
-		dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
-	sleep(Enabledelay);
-	if(hubfeature(h, p, Fportreset, 1) < 0){
-		dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	sleep(Resetdelay);
-	sts = portstatus(h, p);
-	if(sts < 0)
-		goto Fail;
-	if((sts & PSenable) == 0){
-		dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
-		hubfeature(h, p, Fportenable, 1);
-		sts = portstatus(h, p);
-		if((sts & PSenable) == 0)
-			goto Fail;
-	}
-	sp = "full";
-	if(sts & PSslow)
-		sp = "low";
-	if(sts & PShigh)
-		sp = "high";
-	dprint(2, "%s: %s: port %d: attached status %#ux\n", argv0, d->dir, p, sts);
-
-	if(devctl(d, "newdev %s %d", sp, p) < 0){
-		fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	seek(d->cfd, 0, 0);
-	nr = read(d->cfd, buf, sizeof(buf)-1);
-	if(nr == 0){
-		fprint(2, "%s: %s: port %d: newdev: eof\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	if(nr < 0){
-		fprint(2, "%s: %s: port %d: newdev: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	buf[nr] = 0;
-	snprint(fname, sizeof(fname), "/dev/usb/%s", buf);
-	nd = opendev(fname);
-	if(nd == nil){
-		fprint(2, "%s: %s: port %d: opendev: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	if(usbdebug > 2)
-		devctl(nd, "debug 1");
-	if(opendevdata(nd, ORDWR) < 0){
-		fprint(2, "%s: %s: opendevdata: %r\n", argv0, nd->dir);
-		goto Fail;
-	}
-	if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){
-		dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	if(devctl(nd, "address") < 0){
-		dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-
-	mp=getmaxpkt(nd, strcmp(sp, "low") == 0);
-	if(mp < 0){
-		dprint(2, "%s: %s: port %d: getmaxpkt: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}else{
-		dprint(2, "%s; %s: port %d: maxpkt %d\n", argv0, d->dir, p, mp);
-		devctl(nd, "maxpkt %d", mp);
-	}
-	if((sts & PSslow) != 0 && strcmp(sp, "full") == 0)
-		dprint(2, "%s: %s: port %d: %s is full speed when port is low\n",
-			argv0, d->dir, p, nd->dir);
-	if(configdev(nd) < 0){
-		dprint(2, "%s: %s: port %d: configdev: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	/*
-	 * We always set conf #1. BUG.
-	 */
-	if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){
-		dprint(2, "%s: %s: port %d: setconf: %r\n", argv0, d->dir, p);
-		unstall(nd, nd, Eout);
-		if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0)
-			goto Fail;
-	}
-	dprint(2, "%s: %U", argv0, nd);
-	pp->state = Pconfiged;
-	dprint(2, "%s: %s: port %d: configed: %s\n",
-			argv0, d->dir, p, nd->dir);
-	return pp->dev = nd;
-Fail:
-	pp->state = Pdisabled;
-	pp->sts = 0;
-	if(pp->hub != nil)
-		pp->hub = nil;	/* hub closed by enumhub */
-	hubfeature(h, p, Fportenable, 0);
-	if(nd != nil)
-		devctl(nd, "detach");
-	closedev(nd);
-	return nil;
-}
-
-static void
-portdetach(Hub *h, int p)
-{
-	Dev *d;
-	Port *pp;
-	extern void usbfsgone(char*);
-	d = h->dev;
-	pp = &h->port[p];
-
-	/*
-	 * Clear present, so that we detect an attach on reconnects.
-	 */
-	pp->sts &= ~(PSpresent|PSenable);
-
-	if(pp->state == Pdisabled)
-		return;
-	pp->state = Pdisabled;
-	dprint(2, "%s: %s: port %d: detached\n", argv0, d->dir, p);
-
-	if(pp->hub != nil){
-		closehub(pp->hub);
-		pp->hub = nil;
-	}
-	if(pp->devmaskp != nil)
-		putdevnb(pp->devmaskp, pp->devnb);
-	pp->devmaskp = nil;
-	if(pp->dev != nil){
-		devctl(pp->dev, "detach");
-		usbfsgone(pp->dev->dir);
-		closedev(pp->dev);
-		pp->dev = nil;
-	}
-}
-
-/*
- * The next two functions are included to
- * perform a port reset asked for by someone (usually a driver).
- * This must be done while no other device is in using the
- * configuration address and with care to keep the old address.
- * To keep drivers decoupled from usbd they write the reset request
- * to the #u/usb/epN.0/ctl file and then exit.
- * This is unfortunate because usbd must now poll twice as much.
- *
- * An alternative to this reset process would be for the driver to detach
- * the device. The next function could see that, issue a port reset, and
- * then restart the driver once to see if it's a temporary error.
- *
- * The real fix would be to use interrupt endpoints for non-root hubs
- * (would probably make some hubs fail) and add an events file to
- * the kernel to report events to usbd. This is a severe change not
- * yet implemented.
- */
-static int
-portresetwanted(Hub *h, int p)
-{
-	char buf[5];
-	Port *pp;
-	Dev *nd;
-
-	pp = &h->port[p];
-	nd = pp->dev;
-	if(nd != nil && nd->cfd >= 0 && pread(nd->cfd, buf, 5, 0LL) == 5)
-		return strncmp(buf, "reset", 5) == 0;
-	else
-		return 0;
-}
-
-static void
-portreset(Hub *h, int p)
-{
-	int sts;
-	Dev *d, *nd;
-	Port *pp;
-
-	d = h->dev;
-	pp = &h->port[p];
-	nd = pp->dev;
-	dprint(2, "%s: %s: port %d: resetting\n", argv0, d->dir, p);
-	if(hubfeature(h, p, Fportreset, 1) < 0){
-		dprint(2, "%s: %s: port %d: reset: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	sleep(Resetdelay);
-	sts = portstatus(h, p);
-	if(sts < 0)
-		goto Fail;
-	if((sts & PSenable) == 0){
-		dprint(2, "%s: %s: port %d: not enabled?\n", argv0, d->dir, p);
-		hubfeature(h, p, Fportenable, 1);
-		sts = portstatus(h, p);
-		if((sts & PSenable) == 0)
-			goto Fail;
-	}
-	nd = pp->dev;
-	opendevdata(nd, ORDWR);
-	if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetaddress, nd->id, 0, nil, 0) < 0){
-		dprint(2, "%s: %s: port %d: setaddress: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	if(devctl(nd, "address") < 0){
-		dprint(2, "%s: %s: port %d: set address: %r\n", argv0, d->dir, p);
-		goto Fail;
-	}
-	if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0){
-		dprint(2, "%s: %s: port %d: setconf: %r\n", argv0, d->dir, p);
-		unstall(nd, nd, Eout);
-		if(usbcmd(nd, Rh2d|Rstd|Rdev, Rsetconf, 1, 0, nil, 0) < 0)
-			goto Fail;
-	}
-	if(nd->dfd >= 0)
-		close(nd->dfd);
-	return;
-Fail:
-	pp->state = Pdisabled;
-	pp->sts = 0;
-	if(pp->hub != nil)
-		pp->hub = nil;	/* hub closed by enumhub */
-	hubfeature(h, p, Fportenable, 0);
-	if(nd != nil)
-		devctl(nd, "detach");
-	closedev(nd);
-}
-
-static int
-portgone(Port *pp, int sts)
-{
-	if(sts < 0)
-		return 1;
-	/*
-	 * If it was enabled and it's not now then it may be reconnect.
-	 * We pretend it's gone and later we'll see it as attached.
-	 */
-	if((pp->sts & PSenable) != 0 && (sts & PSenable) == 0)
-		return 1;
-	return (pp->sts & PSpresent) != 0 && (sts & PSpresent) == 0;
-}
-
-static int
-enumhub(Hub *h, int p)
-{
-	int sts;
-	Dev *d;
-	Port *pp;
-	int onhubs;
-
-	if(h->failed)
-		return 0;
-	d = h->dev;
-	if(usbdebug > 3)
-		fprint(2, "%s: %s: port %d enumhub\n", argv0, d->dir, p);
-
-	sts = portstatus(h, p);
-	if(sts < 0){
-		hubfail(h);		/* avoid delays on detachment */
-		return -1;
-	}
-	pp = &h->port[p];
-	onhubs = nhubs;
-	if((sts & PSsuspend) != 0){
-		if(hubfeature(h, p, Fportenable, 1) < 0)
-			dprint(2, "%s: %s: port %d: enable: %r\n", argv0, d->dir, p);
-		sleep(Enabledelay);
-		sts = portstatus(h, p);
-		fprint(2, "%s: %s: port %d: resumed (sts %#ux)\n", argv0, d->dir, p, sts);
-	}
-	if((pp->sts & PSpresent) == 0 && (sts & PSpresent) != 0){
-		if(portattach(h, p, sts) != nil)
-			if(startdev(pp) < 0)
-				portdetach(h, p);
-	}else if(portgone(pp, sts))
-		portdetach(h, p);
-	else if(portresetwanted(h, p))
-		portreset(h, p);
-	else if(pp->sts != sts){
-		dprint(2, "%s: %s port %d: sts %s %#x ->",
-			argv0, d->dir, p, stsstr(pp->sts), pp->sts);
-		dprint(2, " %s %#x\n",stsstr(sts), sts);
-	}
-	pp->sts = sts;
-	if(onhubs != nhubs)
-		return -1;
-	return 0;
-}
-
-static void
-dump(void)
-{
-	Hub *h;
-	int i;
-
-	mustdump = 0;
-	for(h = hubs; h != nil; h = h->next)
-		for(i = 1; i <= h->nport; i++)
-			fprint(2, "%s: hub %#p %s port %d: %U",
-				argv0, h, h->dev->dir, i, h->port[i].dev);
-	usbfsdirdump();
-
-}
-
-static void
-work(void *a)
-{
-	Channel *portc;
-	char *fn;
-	Hub *h;
-	int i;
-
-	portc = a;
-	hubs = nil;
-	/*
-	 * Receive requests for root hubs
-	 */
-	while((fn = recvp(portc)) != nil){
-		dprint(2, "%s: %s starting\n", argv0, fn);
-		h = newhub(fn, nil);
-		if(h == nil)
-			fprint(2, "%s: %s: newhub failed: %r\n", argv0, fn);
-		free(fn);
-	}
-	/*
-	 * Enumerate (and acknowledge after first enumeration).
-	 * Do NOT perform enumeration concurrently for the same
-	 * controller. new devices attached respond to a default
-	 * address (0) after reset, thus enumeration has to work
-	 * one device at a time at least before addresses have been
-	 * assigned.
-	 * Do not use hub interrupt endpoint because we
-	 * have to poll the root hub(s) in any case.
-	 */
-	for(;;){
-Again:
-		for(h = hubs; h != nil; h = h->next)
-			for(i = 1; i <= h->nport; i++)
-				if(enumhub(h, i) < 0){
-					/* changes in hub list; repeat */
-					goto Again;
-				}
-		if(portc != nil){
-			sendp(portc, nil);
-			portc = nil;
-		}
-		sleep(pollms);
-		if(mustdump)
-			dump();
-	}
-}
-
-static int
-cfswalk(Usbfs*, Fid *, char *)
-{
-	werrstr(Enotfound);
-	return -1;
-}
-
-static int
-cfsopen(Usbfs*, Fid *, int)
-{
-	return 0;
-}
-
-static long
-cfsread(Usbfs*, Fid *, void *, long , vlong )
-{
-	return 0;
-}
-
-static void
-setdrvargs(char *name, char *args)
-{
-	Devtab *dt;
-	extern Devtab devtab[];
-
-	for(dt = devtab; dt->name != nil; dt++)
-		if(strstr(dt->name, name) != nil)
-			dt->args = estrdup(args);
-}
-
-static long
-cfswrite(Usbfs*, Fid *, void *data, long cnt, vlong )
-{
-	char buf[80];
-	char *toks[4];
-
-	if(cnt > sizeof(buf))
-		cnt = sizeof(buf) - 1;
-	strncpy(buf, data, cnt);
-	buf[cnt] = 0;
-	if(cnt > 0 && buf[cnt-1] == '\n')
-		buf[cnt-1] = 0;
-	if(strncmp(buf, "dump", 4) == 0){
-		mustdump = 1;
-		return cnt;
-	}
-	if(strncmp(buf, "reset", 5) == 0){
-		werrstr("reset not implemented");
-		return -1;
-	}
-	if(tokenize(buf, toks, nelem(toks)) != 2){
-		werrstr("usage: debug|fsdebug n");
-		return -1;
-	}
-	if(strcmp(toks[0], "debug") == 0)
-		usbdebug = atoi(toks[1]);
-	else if(strcmp(toks[0], "fsdebug") == 0)
-		usbfsdebug = atoi(toks[1]);
-	else if(strcmp(toks[0], "kbargs") == 0)
-		setdrvargs("kb", toks[1]);
-	else if(strcmp(toks[0], "diskargs") == 0)
-		setdrvargs("disk", toks[1]);
-	else{
-		werrstr("unkown ctl '%s'", buf);
-		return -1;
-	}
-	fprint(2, "%s: debug %d fsdebug %d\n", argv0, usbdebug, usbfsdebug);
-	return cnt;
-}
-
-static int
-cfsstat(Usbfs* fs, Qid qid, Dir *d)
-{
-	d->qid = qid;
-	d->qid.path |= fs->qid;
-	d->qid.type = 0;
-	d->qid.vers = 0;
-	d->name = "usbdctl";
-	d->length = 0;
-	d->mode = 0664;
-	return 0;
-}
-
-static Usbfs ctlfs =
-{
-	.walk = cfswalk,
-	.open = cfsopen,
-	.read = cfsread,
-	.write = cfswrite,
-	.stat = cfsstat
-};
-
-static void
-args(void)
-{
-	char *s;
-
-	s = getenv("usbdebug");
-	if(s != nil)
-		usbdebug = atoi(s);
-	free(s);
-	s = getenv("usbfsdebug");
-	if(s != nil)
-		usbfsdebug = atoi(s);
-	free(s);
-	s = getenv("kbargs");
-	if(s != nil)
-		setdrvargs("kb", s);
-	free(s);
-	s = getenv("diskargs");
-	if(s != nil)
-		setdrvargs("disk", s);
-	free(s);
-}
-
-static void
-usage(void)
-{
-	fprint(2, "usage: %s [-Dd] [-s srv] [-m mnt] [dev...]\n", argv0);
-	threadexitsall("usage");
-}
-
-extern void usbfsexits(int);
-
-void
-threadmain(int argc, char **argv)
-{
-	int i;
-	Dir *d;
-	int fd;
-	int nd;
-	char *err;
-	char *srv;
-	char *mnt;
-
-	srv = "usb";
-	mnt = "/dev";
-	ARGBEGIN{
-	case 'D':
-		usbfsdebug++;
-		break;
-	case 'd':
-		usbdebug++;
-		break;
-	case 's':
-		srv = EARGF(usage());
-		break;
-	case 'i':
-		pollms = atoi(EARGF(usage()));
-		break;
-	case 'm':
-		mnt = EARGF(usage());
-		break;
-	default:
-		usage();
-	}ARGEND;
-	if(access("/dev/usb", AEXIST) < 0 && bind("#u", "/dev", MBEFORE) < 0)
-		sysfatal("#u: %r");
-
-	args();
-
-	fmtinstall('U', Ufmt);
-	quotefmtinstall();
-	rfork(RFNOTEG);
-	portc = chancreate(sizeof(char *), 0);
-	if(portc == nil)
-		sysfatal("chancreate");
-	proccreate(work, portc, Stack);
-	if(argc == 0){
-		fd = open("/dev/usb", OREAD);
-		if(fd < 0)
-			sysfatal("/dev/usb: %r");
-		nd = dirreadall(fd, &d);
-		close(fd);
-		if(nd < 2)
-			sysfatal("/dev/usb: no hubs");
-		for(i = 0; i < nd; i++)
-			if(strcmp(d[i].name, "ctl") != 0)
-				sendp(portc, smprint("/dev/usb/%s", d[i].name));
-		free(d);
-	}else
-		for(i = 0; i < argc; i++)
-			sendp(portc, strdup(argv[i]));
-	sendp(portc, nil);
-	err = recvp(portc);
-	chanfree(portc);
-	usbfsexits(0);
-	usbfsinit(srv, mnt, &usbdirfs, MAFTER);
-	snprint(ctlfs.name, sizeof(ctlfs.name), "usbdctl");
-	usbfsadd(&ctlfs);
-	threadexits(err);
-}
--- a/sys/src/cmd/usb/usbd/usbd.h
+++ /dev/null
@@ -1,134 +1,0 @@
-typedef struct Hub Hub;
-typedef struct Port Port;
-typedef struct DHub DHub;
-typedef struct Devtab Devtab;
-typedef struct Usbfs Usbfs;
-
-enum
-{
-	Stack	= 32*1024,
-
-	Dhub	= 0x29,		/* hub descriptor type */
-	Dhublen = 9,		/* hub descriptor length */
-
-	/* hub class feature selectors */
-	Fhublocalpower	= 0,
-	Fhubovercurrent	= 1,
-
-	Fportconnection	= 0,
-	Fportenable	= 1,
-	Fportsuspend	= 2,
-	Fportovercurrent = 3,
-	Fportreset	= 4,
-	Fportpower	= 8,
-	Fportlowspeed	= 9,
-	Fcportconnection	= 16,
-	Fcportenable	= 17,
-	Fcportsuspend	= 18,
-	Fcportovercurrent= 19,
-	Fcportreset	= 20,
-	Fportindicator	= 22,
-
-	/* Port status and status change bits
-	 * Constants at /sys/src/9/pc/usb.h starting with HP-
-	 * must have the same values or root hubs won't work.
-	 */
-	PSpresent	= 0x0001,
-	PSenable	= 0x0002,
-	PSsuspend	= 0x0004,
-	PSovercurrent	= 0x0008,
-	PSreset		= 0x0010,
-	PSpower		= 0x0100,
-	PSslow		= 0x0200,
-	PShigh		= 0x0400,
-
-	PSstatuschg	= 0x10000,	/* PSpresent changed */
-	PSchange	= 0x20000,	/* PSenable changed */
-
-
-	/* port/device state */
-	Pdisabled = 0,		/* must be 0 */
-	Pattached,
-	Pconfiged,
-
-	/* Delays, timeouts (ms) */
-//	Spawndelay	= 1000,		/* how often may we re-spawn a driver */
-	Spawndelay	= 250,		/* how often may we re-spawn a driver */
-//	Connectdelay	= 1000,		/* how much to wait after a connect */
-	Connectdelay	= 500,		/* how much to wait after a connect */
-	Resetdelay	= 20,		/* how much to wait after a reset */
-	Enabledelay	= 20,		/* how much to wait after an enable */
-	Powerdelay	= 100,		/* after powering up ports */
-	Pollms		= 250, 		/* port poll interval */
-	Chgdelay	= 100,		/* waiting for port become stable */
-	Chgtmout	= 1000,		/* ...but at most this much */
-
-	/*
-	 * device tab for embedded usb drivers.
-	 */
-	DCL = 0x01000000,		/* csp identifies just class */
-	DSC = 0x02000000,		/* csp identifies just subclass */
-	DPT = 0x04000000,		/* csp identifies just proto */
-
-};
-
-struct Hub
-{
-	uchar	pwrmode;
-	uchar	compound;
-	uchar	pwrms;		/* time to wait in ms */
-	uchar	maxcurrent;	/*    after powering port*/
-	int	leds;		/* has port indicators? */
-	int	maxpkt;
-	uchar	nport;
-	Port	*port;
-	int	failed;		/* I/O error while enumerating */
-	int	isroot;		/* set if root hub */
-	Dev	*dev;		/* for this hub */
-	Hub	*next;		/* in list of hubs */
-};
-
-struct Port
-{
-	int	state;		/* state of the device */
-	int	sts;		/* old port status */
-	uchar	removable;
-	uchar	pwrctl;
-	Dev	*dev;		/* attached device (if non-nil) */
-	Hub	*hub;		/* non-nil if hub attached */
-	int	devnb;		/* device number */
-	uvlong	*devmaskp;	/* ptr to dev mask */
-};
-
-
-/* USB HUB descriptor */
-struct DHub
-{
-	uchar	bLength;
-	uchar	bDescriptorType;
-	uchar	bNbrPorts;
-	uchar	wHubCharacteristics[2];
-	uchar	bPwrOn2PwrGood;
-	uchar	bHubContrCurrent;
-	uchar	DeviceRemovable[1];	/* variable length */
-};
-
-struct Devtab
-{
-	char	*name;
-	int	(*init)(Dev*, int, char**);	/* nil if external */
-	int	csps[4];
-	int	vid;
-	int	did;
-	char	*args;
-	uvlong	devmask;
-};
-
-
-Hub*	newhub(char *fn, Dev *d);
-int	startdev(Port *pp);
-int	getdevnb(uvlong *maskp);
-void	putdevnb(uvlong *maskp, int nb);
-void	threadmain(int argc, char **argv);
-
-extern Usbfs usbdfsops;
--- a/sys/src/cmd/usb/usbd/usbdb
+++ /dev/null
@@ -1,11 +1,0 @@
-# only kb, disk, and ether are prepared for embedding.
-# others are not yet converted to sit in the usbd device driver library.
-embed
-	kb	csp=0x010103 csp=0x020103	args=
-	disk	class=storage			args=
-	ether	class=255 csp=0x00ffff vid=0x0b95		args=
-	serial	class=255 csp=0xffffff vid=0x9e88 did=0x9e8f	args=
-	serial	class=255 csp=0xffffff vid=0x0403		args=
-#	wifi	class=0 csp=0 vid=0x0bda did=0x8192		args=
-#	wifi	class=0 csp=0 vid=0x148f did=0x2870		args=
-auto