21 static char Enonexist[] = "does not exist";
23 typedef struct Event Event;
29 int ref; /* number of readers which will read this one
30 the next time they'll read */
31 int prev; /* number of events pointing to this one with
32 their link pointers */
36 static Req *reqfirst, *reqlast;
51 fulfill(Req *req, Event *e)
56 if(n > req->ifcall.count)
57 n = req->ifcall.count;
58 memmove(req->ofcall.data, e->data, n);
59 req->ofcall.count = n;
65 evlast = emallocz(sizeof(Event), 1);
81 req->fid->aux = e->link;
83 if(--e->ref == 0 && e->prev == 0){
100 ee = emallocz(sizeof(Event), 1);
103 e->len = strlen(data);
106 for(r = reqfirst; r != nil; r = rr){
115 if(e->ref == 0 && e->prev == 0){
126 dirgen(int n, Dir *d, void *)
136 d->uid = strdup(getuser());
137 d->gid = strdup(d->uid);
138 d->muid = strdup(d->uid);
139 d->name = strdup(names[n+1]);
140 d->mode = 0555 | (d->qid.type << 24);
141 d->atime = d->mtime = time(0);
149 req->fid->qid = (Qid) {Qroot, 0, QTDIR};
150 req->ofcall.qid = req->fid->qid;
155 usbdwalk(Fid *fid, char *name, Qid *qid)
159 if(strcmp(name, "..") == 0){
160 fid->qid = (Qid) {Qroot, 0, QTDIR};
164 if(fid->qid.path != Qroot)
165 return "not a directory";
166 for(i = 0; i < Qmax; i++)
167 if(strcmp(name, names[i]) == 0){
168 fid->qid = (Qid) {i, 0, 0};
172 return "does not exist";
178 switch((long)req->fid->qid.path){
180 dirread9p(req, dirgen, nil);
184 if(req->fid->aux == nil){
185 respond(req, "the front fell off");
191 respond(req, Enonexist);
199 if(dirgen(req->fid->qid.path - 1, &req->d, nil) < 0)
200 respond(req, "the front fell off");
211 return smprint("in id %d vid 0x%.4x did 0x%.4x csp 0x%.8lx\n",
212 d->id, u->vid, u->did, u->csp);
223 for(h = hubs; h != nil; h = h->next){
224 for(p = h->port; p < h->port + h->nport; p++){
225 if(p->dev == nil || p->dev->usb == nil || p->hub != nil)
227 e = emallocz(sizeof(Event), 1);
228 e->data = formatdev(p->dev);
229 e->len = strlen(e->data);
242 extern QLock hublock;
244 if(req->fid->qid.path == Qusbevent){
247 enumerate(&req->fid->aux);
248 ((Event *)req->fid->aux)->ref++;
249 ((Event *)req->fid->aux)->prev--;
257 usbddestroyfid(Fid *fid)
261 if(fid->qid.path == Qusbevent && fid->aux != nil){
264 if(--e->ref == 0 && e->prev == 0){
265 while(e->ref == 0 && e->prev == 0 && e != evlast){
284 if(r == req->oldreq){
291 respond(req->oldreq, "interrupted");
296 .attach = usbdattach,
302 .destroyfid = usbddestroyfid,
310 if((d = p->dev) == nil || p->dev->usb == nil){
311 fprint(2, "okay what?\n");
314 if(d->usb->class == Clhub){
316 * Hubs are handled directly by this process avoiding
317 * concurrent operation so that at most one device
318 * has the config address in use.
319 * We cancel kernel debug for these eps. too chatty.
321 if((p->hub = newhub(d->dir, d)) == nil)
327 pushevent(formatdev(d));
332 main(int argc, char **argv)
340 switch(rfork(RFPROC|RFMEM)){
341 case -1: sysfatal("rfork: %r");
342 case 0: work(); exits(nil);
345 fd = open("/dev/usb", OREAD);
347 sysfatal("/dev/usb: %r");
348 nd = dirreadall(fd, &d);
351 sysfatal("/dev/usb: no hubs");
352 for(i = 0; i < nd; i++)
353 if(strcmp(d[i].name, "ctl") != 0)
354 rendezvous(work, smprint("/dev/usb/%s", d[i].name));
357 for(i = 0; i < argc; i++)
358 rendezvous(work, strdup(argv[i]));
359 rendezvous(work, nil);
360 postsharesrv(&usbdsrv, nil, "usb", "usbd", "b");