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);
95 req->fid->aux = e->link;
104 pushevent(char *data)
111 ee = emallocz(sizeof(Event), 1);
114 e->len = strlen(data);
117 for(r = reqfirst; r != nil; r = rr){
133 dirgen(int n, Dir *d, void *)
143 d->uid = strdup(getuser());
144 d->gid = strdup(d->uid);
145 d->muid = strdup(d->uid);
146 d->name = strdup(names[n+1]);
147 d->mode = 0555 | (d->qid.type << 24);
148 d->atime = d->mtime = time(0);
156 req->fid->qid = (Qid) {Qroot, 0, QTDIR};
157 req->ofcall.qid = req->fid->qid;
162 usbdwalk(Fid *fid, char *name, Qid *qid)
166 if(strcmp(name, "..") == 0){
167 fid->qid = (Qid) {Qroot, 0, QTDIR};
171 if(fid->qid.path != Qroot)
172 return "not a directory";
173 for(i = 0; i < Qmax; i++)
174 if(strcmp(name, names[i]) == 0){
175 fid->qid = (Qid) {i, 0, 0};
179 return "does not exist";
185 switch((long)req->fid->qid.path){
187 dirread9p(req, dirgen, nil);
191 if(req->fid->aux == nil){
192 respond(req, "the front fell off");
198 respond(req, Enonexist);
206 if(dirgen(req->fid->qid.path - 1, &req->d, nil) < 0)
207 respond(req, "the front fell off");
213 formatdev(Dev *d, int type)
218 return smprint("%s %d %.4x %.4x %.8lx\n", type ? "detach" : "attach", d->id, u->vid, u->did, u->csp);
231 for(h = hubs; h != nil; h = h->next){
232 for(i = 1; i <= h->nport; i++){
235 if(p->dev == nil || p->dev->usb == nil || p->hub != nil)
237 e = emallocz(sizeof(Event), 1);
238 e->data = formatdev(p->dev, 0);
239 e->len = strlen(e->data);
253 extern QLock hublock;
255 if(req->fid->qid.path == Qusbevent){
261 enumerate(&req->fid->aux);
273 usbddestroyfid(Fid *fid)
277 if(fid->qid.path == Qusbevent && fid->aux != nil){
280 if(--e->ref == 0 && e->prev == 0)
281 while(e->ref == 0 && e->prev == 0 && e != evlast)
294 if(r == req->oldreq){
301 respond(req->oldreq, "interrupted");
306 .attach = usbdattach,
312 .destroyfid = usbddestroyfid,
320 if(d->usb->class == Clhub){
322 * Hubs are handled directly by this process avoiding
323 * concurrent operation so that at most one device
324 * has the config address in use.
325 * We cancel kernel debug for these eps. too chatty.
327 if((p->hub = newhub(d->dir, d)) == nil)
334 pushevent(formatdev(d, 0));
341 if(p->dev->usb->class == Clhub)
343 pushevent(formatdev(p->dev, 1));
347 main(int argc, char **argv)
364 switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
365 case -1: sysfatal("rfork: %r");
366 case 0: work(); exits(nil);
369 if((fd = open("/dev/usb", OREAD)) < 0){
370 rendezvous(work, nil);
371 sysfatal("/dev/usb: %r");
373 nd = dirreadall(fd, &d);
376 rendezvous(work, nil);
377 sysfatal("/dev/usb: no hubs");
379 for(i = 0; i < nd; i++)
380 if(strcmp(d[i].name, "ctl") != 0)
381 rendezvous(work, smprint("/dev/usb/%s", d[i].name));
384 for(i = 0; i < argc; i++)
385 rendezvous(work, strdup(argv[i]));
386 rendezvous(work, nil);
387 postsharesrv(&usbdsrv, nil, "usb", "usbd");