ref: 4275c49e72544d5b92512e41ddecbd6af5bee6c3
parent: d8c75e45de9483881f782be0b5e7113e625db571
author: cinap_lenrek <[email protected]>
date: Sat Jun 28 14:09:43 EDT 2014
nusb: implement aijus stable uniqueue device names instead of naming devices by ther dynamically assigned device address, we hash device uniqueue fields from the device descriptor and produce a 5 digit hex string that will identify the device across machines. when there is a collision (less than 1% chance with 100 devices), usbd will append the device address to the name to make it uniqueue for this machine. the hname is passed to drivers in the devid argument, which now has the form addr:hname, where the colon and hname can be omited (for backwards compatibility). when the new behaviour isnt desired, nousbhname= environment variable can be defined giving the old behaviour.
--- a/rc/bin/nusbrc
+++ b/rc/bin/nusbrc
@@ -7,22 +7,25 @@
@{
rfork ne
fn attach {
+ id=$1
+ if(~ $#* 5 && ! test -e /env/nousbhname)
+ id=$1:$5
switch($4){
case *01
- nusb/audio $1
+ nusb/audio $id
case *02
# serial and ethernet
- nusb/serial $1
+ nusb/serial $id
# handled /sys/src/9/boot/nusbrc
- # nusb/ether $1
+ # nusb/ether $id
case *03
# handled /sys/src/9/boot/nusbrc
- # nusb/kb $1
+ # nusb/kb $id
case *08
# handled /sys/src/9/boot/nusbrc
- # nusb/disk $1
- case *10106
- nusb/ptp $1
+ # nusb/disk $id
+ case 010106
+ nusb/ptp $id
}
}
fn detach {
--- a/sys/man/2/nusb
+++ b/sys/man/2/nusb
@@ -28,6 +28,7 @@
Usbdev* usb; /* USB description */
void* aux; /* for the device driver */
void (*free)(void*); /* idem. to release aux */
+ char* hname; /* hash name, uniqueue for device */
};
.sp 0.3v
struct Usbdev {
@@ -119,7 +120,7 @@
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);
+Dev* getdev(char *devid);
.sp 0.3v
extern int usbdebug; /* more messages for bigger values */
.EE
--- a/sys/man/4/nusb
+++ b/sys/man/4/nusb
@@ -88,23 +88,41 @@
.B usbevent
(usually seen as
.BR /dev/usbevent )
-which, when read, returns a 5 column, space separated line of
+which, when read, returns a 6 column, space separated line of
text, one for each event. The columns are:
.B attach
or
.B detach
-.I devid
+followed by
+.I addr
.I vid
.I did
+.I csp
and
-.I csp .
-All but
-.I devid
-are formatted as 4 digit hexadecimal. This file is read by
+.I hname .
+The
+.I addr
+is the decimal device address assigned.
+.I Vid
+and
+.I did
+are formatted as 4 digit hexadecimal.
+.I Csp
+is the device class, subclass, protocol indentifier
+formatd as 6 digit hexadecimal.
+.I Usbd
+assigns a stable device uniqueue name based on the
+device descriptor for
+.I hname .
+This information is read by
.IR nusbrc (8)
and the
+.I addr
+and
+.I hname
+are passed to a suitable driver as
.I devid
-is passed to a suitable driver.
+in the form \fIaddr\fB:\fIhname
.SS Keyboards and mice
.I Kb
supports USB keyboards and mice either as separate USB devices
@@ -123,13 +141,10 @@
provides a file system (usually seen under
.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 .
+.BI sdU N [. M ]
+in correspondence with the usb device uniqueue name
+and the storage unit number (or LUN). The LUN is omited
+for single lun devices.
.PP
The storage device directory contains the usual files
served by
@@ -183,7 +198,7 @@
that includes one directory per USB serial port, named
.BI eiaU N
or
-.BI eiaU N . M.
+.BI eiaU N [. M ].
In this directory there are two files,
.BR eiaU ,
similar to
--- a/sys/man/8/nusbrc
+++ b/sys/man/8/nusbrc
@@ -15,9 +15,21 @@
.IR cpurc (8)),
.I nusbrc
handles the startup and shutdown of usb drivers on physical
-device attach and detach events.
+device attach and detach events by reading
+.B /dev/usbevent
+file.
.SH SOURCE
.B /rc/bin/nusbrc
.B /sys/src/9/boot/nusbrc
.SH "SEE ALSO"
.IR nusb (4)
+.SH BUGS
+Usb devices appear as files under
+.B /dev
+and
+.B /shr
+identified by the devices uniqueue name assigned by usbd.
+When the environment variable
+.I nousbhname
+is defined, devies are named by ther dynamically assigned
+usb device address instead. This emulates the old behaviour.
--- a/sys/man/8/plan9.ini
+++ b/sys/man/8/plan9.ini
@@ -812,6 +812,11 @@
.SS \fLusbwait=\fIvalue\fP
This changes the sleep time from the default 2 to value in cases of
USB devices taking a long time to come online.
+.SS \fLnousbhname=\fP
+When defined,
+.IR nusbrc (8)
+will use the dynamically assigned usb device address to name
+usb devices instead of the device uniqueue name.
.SS VIDEO
.SS \fLmonitor=\fIvalue\fP
.SS \fLvgasize=\fIvalue\fP
--- a/sys/src/9/boot/nusbrc
+++ b/sys/src/9/boot/nusbrc
@@ -11,29 +11,33 @@
@{
rfork ne
fn attach {
+ id=$1
+ if(~ $#* 5 && ! test -e /env/nousbhname)
+ id=$1:$5
switch($2$3){
case 0b957720 0b95772a 0db0a877 13b10018 15577720 20013c05 07d13c05 05ac1402
- nusb/ether -t a88772 $etherargs $1
+ nusb/ether -t a88772 $etherargs $id
case 0b951780 14eaab11 17370039 0411006e 050d5055
- nusb/ether -t a88178 $etherargs $1
+ nusb/ether -t a88178 $etherargs $id
case 2001abc1
- nusb/ether -t aue $etherargs $1
+ nusb/ether -t aue $etherargs $id
case 0bda8150
- nusb/ether -t url $etherargs $1
+ nusb/ether -t url $etherargs $id
case 18d14ee3 0bb40003
- nusb/ether -t rndis $etherargs $1
+ nusb/ether -t rndis $etherargs $id
case *
switch($4){
case *03
- nusb/kb $1
+ nusb/kb $id
case *02
# CDC ethernet
- nusb/ether $etherargs $1
+ nusb/ether $etherargs $id
case *08
- if(nusb/disk $1) {@{
+ if(nusb/disk $id) {@{
rfork ne
cd '#σ/usb'
- for(dev in sdU^$1.*) if(test -d $dev) {
+ devs=sdU^($1 $5)
+ for(dev in $devs $devs.*) if(test -d $dev) {
diskparts $dev
for(part in $dev/dos* $dev/9fat) if(test -r $part) {
mkdir -m 0700 '#σc/'^$dev || exit
@@ -45,12 +49,13 @@
}&}
case *
if(~ $2 0424)
- nusb/ether -t smsc $etherargs $1
+ nusb/ether -t smsc $etherargs $id
}
}
}
fn detach {
- rm -rf '#σc/usb/'^$1.* '#σc/sdU'^$1.* '#σc/usbnet/'^$1.*
+ devs='#σc/sdU'^($1 $5)
+ rm -rf '#σc/usb/'^$1.* '#σc/usbnet/'^$1.* $devs $devs.*
}
rc < '#σ/usb/usbevent' &
}
--- a/sys/src/cmd/nusb/audio/audio.c
+++ b/sys/src/cmd/nusb/audio/audio.c
@@ -184,7 +184,7 @@
if(argc == 0)
usage();
- if((d = getdev(atoi(*argv))) == nil)
+ if((d = getdev(*argv)) == nil)
sysfatal("getdev: %r");
audiodev = d;
--- a/sys/src/cmd/nusb/disk/disk.c
+++ b/sys/src/cmd/nusb/disk/disk.c
@@ -1042,7 +1042,7 @@
if(argc != 1)
usage();
- dev = getdev(atoi(*argv));
+ dev = getdev(*argv);
if(dev == nil)
sysfatal("getdev: %r");
ums = dev->aux = emallocz(sizeof(Ums), 1);
@@ -1062,7 +1062,10 @@
for(i = 0; i <= ums->maxlun; i++){
lun = &ums->lun[i];
- snprint(lun->name, sizeof(lun->name), "sdU%d.%d", dev->id, i);
+ if(ums->maxlun > 0)
+ snprint(lun->name, sizeof(lun->name), "sdU%s.%d", dev->hname, i);
+ else
+ snprint(lun->name, sizeof(lun->name), "sdU%s", dev->hname);
makeparts(lun);
}
snprint(buf, sizeof buf, "%d.disk", dev->id);
--- a/sys/src/cmd/nusb/ether/ether.c
+++ b/sys/src/cmd/nusb/ether/ether.c
@@ -819,7 +819,7 @@
if(argc != 1)
usage();
- if((d = getdev(atoi(*argv))) == nil)
+ if((d = getdev(*argv)) == nil)
sysfatal("getdev: %r");
if(findendpoints(d, &ei, &eo) < 0)
sysfatal("no endpoints found");
@@ -847,7 +847,7 @@
atnotify(inote, 1);
time0 = time(0);
- tab[Qiface].name = smprint("etherU%d", d->id);
+ tab[Qiface].name = smprint("etherU%s", d->hname);
snprint(s, sizeof(s), "%d.ether", d->id);
closedev(d);
threadpostsharesrv(&fs, nil, "usbnet", s);
--- a/sys/src/cmd/nusb/joy/joy.c
+++ b/sys/src/cmd/nusb/joy/joy.c
@@ -410,7 +410,7 @@
}ARGEND;
if(argc != 1)
usage();
- d = getdev(atoi(*argv));
+ d = getdev(*argv);
if(d == nil)
sysfatal("getdev: %r");
ud = d->usb;
--- a/sys/src/cmd/nusb/kb/kb.c
+++ b/sys/src/cmd/nusb/kb/kb.c
@@ -794,7 +794,7 @@
}ARGEND;
if(argc != 1)
usage();
- d = getdev(atoi(*argv));
+ d = getdev(*argv);
if(d == nil)
sysfatal("getdev: %r");
ud = d->usb;
--- a/sys/src/cmd/nusb/lib/dev.c
+++ b/sys/src/cmd/nusb/lib/dev.c
@@ -121,6 +121,7 @@
free(d);
return nil;
}
+ d->hname = nil;
dprint(2, "%s: opendev %#p %s\n", argv0, d, fn);
return d;
}
@@ -323,6 +324,8 @@
d->cfd = d->dfd = -1;
free(d->dir);
d->dir = nil;
+ free(d->hname);
+ d->hname = nil;
ud = d->usb;
d->usb = nil;
if(ud != nil){
@@ -509,12 +512,26 @@
}
Dev *
-getdev(int id)
+getdev(char *devid)
{
+ char buf[40], *p;
Dev *d;
- char buf[40];
-
- snprint(buf, sizeof buf, "/dev/usb/ep%d.0", id);
+
+ if(devid[0] == '/' || devid[0] == '#'){
+ snprint(buf, sizeof buf, "%s", devid);
+ p = strrchr(buf, '/');
+ if(p != nil){
+ p = strrchr(buf, ':');
+ if(p != nil)
+ *p = 0;
+ }
+ } else {
+ p = nil;
+ snprint(buf, sizeof buf, "/dev/usb/ep%ld.0", strtol(devid, &p, 10));
+ if(*p != ':')
+ p = nil;
+ }
+
d = opendev(buf);
if(d == nil)
return nil;
@@ -522,5 +539,12 @@
closedev(d);
return nil;
}
+
+ if(p == nil){
+ snprint(buf, sizeof buf, ":%d", d->id);
+ p = buf;
+ }
+ d->hname = strdup(p+1);
+
return d;
}
--- a/sys/src/cmd/nusb/lib/usb.h
+++ b/sys/src/cmd/nusb/lib/usb.h
@@ -174,6 +174,7 @@
Usbdev* usb; /* USB description */
void* aux; /* for the device driver */
void (*free)(void*); /* idem. to release aux */
+ char* hname; /* hash name, uniqueue for device */
};
/*
@@ -351,7 +352,7 @@
int parsedev(Dev *xd, uchar *b, int n);
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);
+Dev* getdev(char *devid);
extern int usbdebug; /* more messages for bigger values */
--- a/sys/src/cmd/nusb/ptp/ptp.c
+++ b/sys/src/cmd/nusb/ptp/ptp.c
@@ -1011,7 +1011,7 @@
if(argc == 0)
usage();
- if((d = getdev(atoi(*argv))) == nil)
+ if((d = getdev(*argv)) == nil)
sysfatal("opendev: %r");
if(findendpoints(d, &epin, &epout, &epint) < 0)
sysfatal("findendpoints: %r");
@@ -1037,7 +1037,7 @@
time0 = time(0);
- snprint(name, sizeof name, "sdU%d", d->id);
+ snprint(name, sizeof name, "sdU%s", d->hname);
snprint(desc, sizeof desc, "%d.ptp", d->id);
threadpostsharesrv(&fs, nil, name, desc);
--- a/sys/src/cmd/nusb/serial/serial.c
+++ b/sys/src/cmd/nusb/serial/serial.c
@@ -810,7 +810,7 @@
}ARGEND
if(argc != 1)
usage();
- dev = getdev(atoi(*argv));
+ dev = getdev(*argv);
if(dev == nil)
sysfatal("getdev: %r");
@@ -859,17 +859,10 @@
}
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->name, sizeof p->name, "jtag%d.%d", dev->id, i);
- } else {
- snprint(p->name, sizeof p->name, "eiaU");
- if(i == 0)
- snprint(p->name, sizeof p->name, "eiaU%d", dev->id);
- else
- snprint(p->name, sizeof p->name, "eiaU%d.%d", dev->id, i);
- }
+ if(ser->nifcs == 1)
+ snprint(p->name, sizeof p->name, "%s%s", p->isjtag ? "jtag" : "eiaU", dev->hname);
+ else
+ snprint(p->name, sizeof p->name, "%s%s.%d", p->isjtag ? "jtag" : "eiaU", dev->hname, i);
fprint(2, "%s...", p->name);
incref(dev);
p->readrend.l = &p->readq;
--- a/sys/src/cmd/nusb/usbd/fns.h
+++ b/sys/src/cmd/nusb/usbd/fns.h
@@ -2,3 +2,4 @@
void detachdev(Port*);
void work(void);
Hub* newhub(char *, Dev *);
+void hname(char *);
--- /dev/null
+++ b/sys/src/cmd/nusb/usbd/hname.c
@@ -1,0 +1,17 @@
+#include <u.h>
+#include <libc.h>
+#include <mp.h>
+#include <libsec.h>
+
+void
+hname(char *buf)
+{
+ uchar d[SHA1dlen];
+ u32int x;
+ int n;
+
+ n = strlen(buf);
+ sha1((uchar*)buf, n, d, nil);
+ x = d[0] | d[1]<<8 | d[2]<<16;
+ snprint(buf, n+1, "%.5ux", x & 0xfffff);
+}
--- a/sys/src/cmd/nusb/usbd/mkfile
+++ b/sys/src/cmd/nusb/usbd/mkfile
@@ -3,6 +3,7 @@
OFILES=\
usbd.$O\
hub.$O\
+ hname.$O\
HFILES=\
dat.h\
--- a/sys/src/cmd/nusb/usbd/usbd.c
+++ b/sys/src/cmd/nusb/usbd/usbd.c
@@ -221,8 +221,10 @@
formatdev(Dev *d, int type)
{
Usbdev *u = d->usb;
-
- return smprint("%s %d %.4x %.4x %.8lx\n", type ? "detach" : "attach", d->id, u->vid, u->did, u->csp);
+ return smprint("%s %d %.4x %.4x %.6lx %s\n",
+ type ? "detach" : "attach",
+ d->id, u->vid, u->did, u->csp,
+ d->hname != nil ? d->hname : "");
}
static void
@@ -335,6 +337,39 @@
.destroyfid = usbddestroyfid,
};
+static void
+assignhname(Dev *dev)
+{
+ extern Hub *hubs;
+ char buf[64];
+ Usbdev *ud;
+ Hub *h;
+ int i;
+
+ ud = dev->usb;
+
+ /* build string of device uniqueue stuff */
+ snprint(buf, sizeof(buf), "%.4x%.4x%.4x%.6lx%s",
+ ud->vid, ud->did, ud->dno, ud->csp, ud->serial);
+
+ hname(buf);
+
+ /* check for collisions */
+ for(h = hubs; h != nil; h = h->next){
+ for(i = 1; i <= h->nport; i++){
+ if(h->port[i].dev == nil)
+ continue;
+ if(h->port[i].dev->hname == nil || h->port[i].dev == dev)
+ continue;
+ if(strcmp(h->port[i].dev->hname, buf) == 0){
+ dev->hname = smprint("%s%d", buf, dev->id);
+ return;
+ }
+ }
+ }
+ dev->hname = strdup(buf);
+}
+
int
attachdev(Port *p)
{
@@ -355,6 +390,9 @@
/* close control endpoint so driver can open it */
close(d->dfd);
d->dfd = -1;
+
+ /* assign stable name based on device descriptor */
+ assignhname(d);
pushevent(d, formatdev(d, 0));
return 0;