📄 hub.c
字号:
#include <u.h>#include <libc.h>#include <thread.h>#include "usb.h"#include "dat.h"#include "fns.h"Hub*roothub(int ctlrno){ Hub *h; char name[100]; h = emallocz(sizeof(Hub), 1); h->isroot = 1; h->ctlrno = ctlrno; h->nport = 2; /* BUG */ h->port = emallocz(h->nport*sizeof(Port), 1); sprint(name, "/dev/usb%d/port", ctlrno); if((h->portfd = open(name, ORDWR)) < 0){ werrstr("open %s: %r", name); free(h); return nil; } h->dev0 = opendev(ctlrno, 0); h->d = h->dev0; incref(h->d); return h;}Hub*newhub(Hub *parent, Device *d){ Port *p; Hub *h; DHub *dd; byte buf[128], *PortPwrCtrlMask; int nr, nport, nmap, i, offset, mask; h = emallocz(sizeof(Hub), 1); h->d = d; h->ctlrno = parent->ctlrno; h->dev0 = parent->dev0; if (setupreq(d->ep[0], RD2H|Rclass|Rdevice, GET_DESCRIPTOR, (HUB<<8)|0, 0, DHUBLEN) < 0 || (nr = setupreply(d->ep[0], buf, sizeof(buf))) < DHUBLEN) { fprint(2, "usbd: error reading hub descriptor\n"); free(h); return nil; } pdesc(d, -1, -1, buf, nr); dd = (DHub*)buf; nport = dd->bNbrPorts; nmap = 1 + nport/8; if(nr < 7 + 2*nmap) { fprint(2, "usbd: hub descriptor too small\n"); free(h); return nil; } h->nport = nport; h->port = emallocz(nport*sizeof(Port), 1); h->pwrms = dd->bPwrOn2PwrGood*2; h->maxcurrent = dd->bHubContrCurrent; h->pwrmode = dd->wHubCharacteristics[0] & 3; h->compound = (dd->wHubCharacteristics[0] & (1<<2))!=0; PortPwrCtrlMask = dd->DeviceRemovable + nmap; for(i = 1; i <= nport; i++) { p = &h->port[i-1]; offset = i/8; mask = 1<<(i%8); p->removable = (dd->DeviceRemovable[offset] & mask) != 0; p->pwrctl = (PortPwrCtrlMask[offset] & mask) != 0; } incref(d); incref(h->dev0); return h;}voidfreehub(Hub *h){ int i; Port *p; if(h == nil) return; for(i = 1; i <= h->nport; i++) { p = &h->port[i-1]; freehub(p->hub); closedev(p->d); } free(h->port); if(h->isroot) close(h->portfd); else closedev(h->d); closedev(h->dev0); free(h);}intHfmt(Fmt *f){ Hub *h; h = va_arg(f->args, Hub*); return fmtprint(f, "usb%d/%d", h->ctlrno, h->d->id);}static voidhubfeature(Hub *h, int port, int feature, int on){ int cmd; cmd = CLEAR_FEATURE; if(on) cmd = SET_FEATURE; setup0(h->d, RH2D|Rclass|Rother, cmd, feature, port, 0);}voidportenable(Hub *h, int port, int on){ if(h->isroot) { if(fprint(h->portfd, "%s %d", on? "enable": "disable", port) < 0) sysfatal("usbd: portenable: write error: %r"); return; } if(port == 0) return; hubfeature(h, port, PORT_ENABLE, on);}voidportreset(Hub *h, int port){ if(h->isroot) { if(fprint(h->portfd, "reset %d", port) < 0) sysfatal("usbd: portreset: write error: %r"); sleep(100); return; } if(port == 0) return; hubfeature(h, port, PORT_RESET, 1);}voidportpower(Hub *h, int port, int on){ if(h->isroot) { /* no power control */ return; } if(port == 0) return; hubfeature(h, port, PORT_POWER, on);}static struct{ int bit; char *name;}statustab[] ={ { 1<<PORT_SUSPEND, "suspend", }, { 1<<PORT_RESET, "reset", }, { 1<<PORT_LOW_SPEED, "lowspeed", }, { 1<<PORT_ENABLE, "enable", }, { 1<<PORT_CONNECTION, "present", },};intportstatus(Hub *h, int port){ int x; Endpt *e; byte buf[4]; int n, nf, i, j; char *status, *q, *qe, *field[20]; if(h->isroot) { seek(h->portfd, 0, 0); status = malloc(8192); n = read(h->portfd, status, 8192); if (n <= 0) sysfatal("usbd: can't read usb port status: %r"); status[n] = '\0'; q = status; for(;;) { qe = strchr(q, '\n'); if(qe == nil) sysfatal("usbd: port %H.%d not found", h, port); *qe = '\0'; nf = tokenize(q, field, sizeof field); if(nf < 2) sysfatal("Ill-formed port status: %s", q); if(strtol(field[0], nil, 0) == port) break; q = qe+1; } x = 0; for(i = 2; i < nf; i++) { for(j = 0; j < nelem(statustab); j++) { if(strcmp(field[i], statustab[j].name) == 0) { x |= statustab[j].bit; break; } } } free(status); return x; } e = h->d->ep[0]; if (setupreq(e, RD2H|Rclass|Rother, GET_STATUS, 0, port, sizeof(buf)) < 0 || setupreply(e, buf, sizeof(buf)) < sizeof(buf)) { if (debug) sysfatal("usbd: error reading hub status %H.%d", h, port); return 0; } return GET2(buf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -