13 typedef struct Tab Tab;
14 typedef struct Qbuf Qbuf;
16 typedef struct Conn Conn;
17 typedef struct Ehdr Ehdr;
18 typedef struct Stats Stats;
43 "etherU", DMDIR|0555, /* calling it *ether* makes snoopy(8) happy */
104 #define PATH(type, n) ((type)|((n)<<8))
105 #define TYPE(path) (((uint)(path) & 0x000000FF)>>0)
106 #define NUM(path) (((uint)(path) & 0xFFFFFF00)>>8)
107 #define NUMCONN(c) (((long)(c)-(long)&conn[0])/sizeof(conn[0]))
110 receivepacket(void *buf, int len);
113 fillstat(Dir *d, uvlong path)
117 memset(d, 0, sizeof(*d));
118 d->uid = estrdup9p(uname);
119 d->gid = estrdup9p(uname);
121 d->atime = d->mtime = time0;
122 t = &tab[TYPE(path)];
123 d->name = smprint(t->name, NUM(path));
124 d->qid.type = t->mode>>24;
131 if(r->ifcall.aname && r->ifcall.aname[0]){
132 respond(r, "invalid attach specifier");
136 uname = estrdup9p(r->ifcall.uname);
137 r->fid->qid.path = PATH(Qroot, 0);
138 r->fid->qid.type = QTDIR;
139 r->fid->qid.vers = 0;
140 r->ofcall.qid = r->fid->qid;
147 fillstat(&r->d, r->fid->qid.path);
152 rootgen(int i, Dir *d, void*)
163 ifacegen(int i, Dir *d, void*)
172 fillstat(d, PATH(Qndir, i));
179 ndirgen(int i, Dir *d, void *aux)
183 fillstat(d, PATH(i, NUMCONN(aux)));
190 fswalk1(Fid *fid, char *name, Qid *qid)
196 path = fid->qid.path;
197 if(!(fid->qid.type&QTDIR))
198 return "walk in non-directory";
200 if(strcmp(name, "..") == 0){
205 qid->path = PATH(Qroot, 0);
206 qid->type = tab[Qroot].mode>>24;
209 qid->path = PATH(Qiface, 0);
210 qid->type = tab[Qiface].mode>>24;
213 return "bug in fswalk1";
217 for(i = TYPE(path)+1; i<nelem(tab); i++){
220 snprint(buf, sizeof buf, "%d", n);
221 if(n < nconn && strcmp(buf, name) == 0){
222 qid->path = PATH(i, n);
223 qid->type = tab[i].mode>>24;
228 if(strcmp(name, tab[i].name) == 0){
229 qid->path = PATH(i, NUM(path));
230 qid->type = tab[i].mode>>24;
233 if(tab[i].mode&DMDIR)
236 return "directory entry not found";
248 if((b = d->q) == nil)
250 if((d->q = b->next) == nil)
252 if((d->r = (Req*)r->aux) == nil)
258 memmove(r->ofcall.data, b->data, n);
272 if(d->q==nil && d->nb){
281 d->rt = (Req**)&r->aux;
287 writeconndata(Req *r)
296 if((n == 11) && memcmp(p, "nonblocking", n)==0){
300 epwrite(epout, p, n);
301 if(receivepacket(p, n) == 0)
312 char *t = "0123456789abcdef";
316 buf[i*2] = t[m[i]>>4];
317 buf[i*2+1] = t[m[i]&0xF];
329 path = r->fid->qid.path;
333 snprint(e, sizeof e, "bug in fsread path=%lux", path);
338 dirread9p(r, rootgen, nil);
343 dirread9p(r, ifacegen, nil);
348 snprint(buf, sizeof(buf),
353 stats.in, stats.out, 10, macaddr);
359 snprint(buf, sizeof(buf), "%E", macaddr);
365 dirread9p(r, ndirgen, &conn[NUM(path)]);
370 snprint(buf, sizeof(buf), "%11d ", NUM(path));
376 snprint(buf, sizeof(buf), "%11d ", conn[NUM(path)].type);
395 path = r->fid->qid.path;
399 p = (char*)r->ifcall.data;
400 if((n == 11) && memcmp(p, "promiscuous", 11)==0)
401 conn[NUM(path)].prom = 1;
402 if((n > 8) && memcmp(p, "connect ", 8)==0){
405 if(n - 8 >= sizeof(x)){
406 respond(r, "invalid control msg");
414 conn[NUM(path)].type = atoi(p);
423 snprint(e, sizeof e, "bug in fswrite path=%lux", path);
431 static int need[4] = { 4, 2, 6, 1 };
440 * lib9p already handles the blatantly obvious.
441 * we just have to enforce the permissions we have set.
443 path = r->fid->qid.path;
444 t = &tab[TYPE(path)];
445 n = need[r->ifcall.mode&3];
446 if((n&t->mode) != n){
447 respond(r, "permission denied");
456 for(i=0; i<nelem(conn); i++){
461 path = PATH(Qctl, i);
464 respond(r, "out of connections");
467 d = emalloc9p(sizeof(*d));
468 memset(d, 0, sizeof(*d));
476 c = &conn[NUM(path)];
490 r->fid->qid.path = path;
491 r->ofcall.qid.path = path;
504 if(TYPE(f->qid.path) == Qdata){
507 for(p=&d->r; *p; p=(Req**)&((*p)->aux)){
509 if((*p = (Req*)o->aux) == nil)
512 respond(o, "interrupted");
523 fsdestroyfid(Fid *fid)
529 if(TYPE(fid->qid.path) >= Qndir){
530 c = &conn[NUM(fid->qid.path)];
534 for(x=&c->dq; *x; x=&((*x)->next)){
547 if(TYPE(fid->qid.path) == Qctl)
555 setalt(Dev *d, int ifcid, int altid)
557 if(usbcmd(d, Rh2d|Rstd|Riface, Rsetiface, altid, ifcid, nil, 0) < 0)
558 dprint(2, "%s: setalt ifc %d alt %d: %r\n", argv0, ifcid, altid);
562 ifaceinit(Dev *d, Iface *ifc, int *ei, int *eo)
571 for(i = 0; (epin < 0 || epout < 0) && i < nelem(ifc->ep); i++)
572 if((ep = ifc->ep[i]) != nil && ep->type == Ebulk){
573 if(ep->dir == Eboth || ep->dir == Ein)
576 if(ep->dir == Eboth || ep->dir == Eout)
580 if(epin == -1 || epout == -1)
583 for(i = 0; i < nelem(ifc->altc); i++)
584 if(ifc->altc[i] != nil)
585 setalt(d, ifc->id, i);
593 findendpoints(Dev *d, int *ei, int *eo)
595 int i, j, ctlid, datid;
596 Iface *ctlif, *datif;
604 /* look for union descriptor with ethernet ctrl interface */
605 for(i = 0; i < nelem(ud->ddesc); i++){
606 if((desc = ud->ddesc[i]) == nil)
608 if(desc->data.bLength < 5 || desc->data.bbytes[0] != Cdcunion)
611 ctlid = desc->data.bbytes[1];
612 datid = desc->data.bbytes[2];
614 if((c = desc->conf) == nil)
618 for(j = 0; j < nelem(c->iface); j++){
619 if(c->iface[j] == nil)
621 if(c->iface[j]->id == ctlid)
623 if(c->iface[j]->id == datid)
626 if(datif != nil && ctlif != nil){
627 if(Subclass(ctlif->csp) == Scether)
628 if(ifaceinit(d, datif, ei, eo) != -1)
635 /* try any other one that seems to be ok */
636 for(i = 0; i < nelem(ud->conf); i++)
637 if((c = ud->conf[i]) != nil)
638 for(j = 0; j < nelem(c->iface); j++)
639 if(ifaceinit(d,c->iface[j],ei,eo) != -1)
646 inote(void *, char *msg)
648 if(strstr(msg, "interrupt"))
654 receivepacket(void *buf, int len)
664 t = (h->type[0]<<8)|h->type[1];
666 for(i=0; i<nconn; i++){
678 if(!c->prom && !(h->d[0]&1))
679 if(memcmp(h->d, macaddr, sizeof(macaddr)))
681 for(d=c->dq; d; d=d->next){
685 if(c->type == -2 && n > 64)
688 b = emalloc9p(sizeof(*b) + n);
690 memcpy(b->data, buf, n);
715 threadsetname("usbreadproc");
719 n = epread(epin, buf, sizeof(buf));
721 rerrstr(err, sizeof(err));
722 if(strstr(err, "interrupted") || strstr(err, "timed out"))
724 fprint(2, "usbreadproc: %s\n", err);
732 if(receivepacket(buf, n) == 0)
740 .destroyfid= fsdestroyfid,
752 fprint(2, "usage: %s [-dD] [-t type] [-a addr] devid\n", argv0);
757 extern int a88178init(Dev *);
758 extern int a88772init(Dev *);
759 extern int smscinit(Dev *);
760 extern int cdcinit(Dev *);
768 "a88178", a88178init,
769 "a88772", a88772init,
773 threadmain(int argc, char **argv)
779 fmtinstall('E', eipfmt);
791 parseether(macaddr, EARGF(usage()));
795 for(et=0; et<nelem(ethertype); et++)
796 if(strcmp(t, ethertype[et].name) == 0)
798 if(et == nelem(ethertype)){
799 fprint(2, "unsupported ethertype -t %s, supported types are: ", t);
800 for(et=0; et<nelem(ethertype); et++)
801 fprint(2, "%s ", ethertype[et].name);
813 if((d = getdev(atoi(*argv))) == nil)
814 sysfatal("getdev: %r");
815 if(findendpoints(d, &ei, &eo) < 0)
816 sysfatal("no endpoints found");
819 if((*ethertype[et].init)(d) < 0)
820 sysfatal("%s init failed: %r", ethertype[et].name);
821 if(epread == nil || epwrite == nil)
822 sysfatal("bug in init");
824 if((epin = openep(d, ei)) == nil)
825 sysfatal("openep: %r");
829 opendevdata(epin, ORDWR);
831 if((epout = openep(d, eo)) == nil)
832 sysfatal("openep: %r");
833 opendevdata(epin, OREAD);
834 opendevdata(epout, OWRITE);
837 proccreate(usbreadproc, nil, 8*1024);
841 tab[Qiface].name = smprint("etherU%d", d->id);
842 snprint(s, sizeof(s), "%d.ether", d->id);
844 threadpostsharesrv(&fs, nil, "usbnet", s);