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