nusb/usbd: use per hname collision counter instead of device address to resolve collisions

The device address is highly variable and depends on
all prior enumerated devices.

This can happen with some devices that do not have
a serial number and all devices of the same type
having the same hname.

Using a counter of collisions per hname makes more sense
and is more stable (given that the order devices are
enumerated is deterministic).
This commit is contained in:
cinap_lenrek 2022-02-06 01:19:01 +00:00
parent fc0357b3de
commit 4ab2d149d4
3 changed files with 14 additions and 10 deletions

View file

@ -2,5 +2,5 @@ int attachdev(Port*);
void detachdev(Port*);
void work(void);
Hub* newhub(char *, Dev*);
void hname(char *);
int hname(char *);
void checkidle(void);

View file

@ -3,7 +3,7 @@
#include <mp.h>
#include <libsec.h>
void
int
hname(char *buf)
{
uchar d[SHA1dlen];
@ -13,5 +13,5 @@ hname(char *buf)
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);
return snprint(buf, n+1, "%.5ux", x & 0xfffff);
}

View file

@ -363,7 +363,8 @@ assignhname(Dev *dev)
char buf[64];
Usbdev *ud;
Hub *h;
int i;
int col;
int i, n;
ud = dev->usb;
@ -371,22 +372,25 @@ assignhname(Dev *dev)
snprint(buf, sizeof(buf), "%.4x%.4x%.4x%.6lx%s",
ud->vid, ud->did, ud->dno, ud->csp, ud->serial);
hname(buf);
n = hname(buf);
/* check for collisions */
col = 0;
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;
}
if(strncmp(h->port[i].dev->hname, buf, n) == 0)
col++;
}
}
dev->hname = strdup(buf);
if(col == 0)
dev->hname = strdup(buf);
else
dev->hname = smprint("%s%d", buf, col);
}
int