12 typedef struct Tab Tab;
14 typedef struct Conn Conn;
15 typedef struct Stats Stats;
40 "etherU", DMDIR|0555, /* calling it *ether* makes snoopy(8) happy */
91 #define PATH(type, n) ((type)|((n)<<8))
92 #define TYPE(path) (((uint)(path) & 0x000000FF)>>0)
93 #define NUM(path) (((uint)(path) & 0xFFFFFF00)>>8)
94 #define NUMCONN(c) (((uintptr)(c)-(uintptr)&conn[0])/sizeof(conn[0]))
97 fillstat(Dir *d, uvlong path)
101 memset(d, 0, sizeof(*d));
102 d->uid = estrdup9p(uname);
103 d->gid = estrdup9p(uname);
105 d->atime = d->mtime = time0;
106 t = &tab[TYPE(path)];
107 d->name = smprint(t->name, NUM(path));
108 d->qid.type = t->mode>>24;
115 if(r->ifcall.aname && r->ifcall.aname[0]){
116 respond(r, "invalid attach specifier");
120 uname = estrdup9p(r->ifcall.uname);
121 r->fid->qid.path = PATH(Qroot, 0);
122 r->fid->qid.type = QTDIR;
123 r->fid->qid.vers = 0;
124 r->ofcall.qid = r->fid->qid;
131 fillstat(&r->d, r->fid->qid.path);
136 rootgen(int i, Dir *d, void*)
147 ifacegen(int i, Dir *d, void*)
156 fillstat(d, PATH(Qndir, i));
163 ndirgen(int i, Dir *d, void *aux)
167 fillstat(d, PATH(i, NUMCONN(aux)));
174 fswalk1(Fid *fid, char *name, Qid *qid)
180 path = fid->qid.path;
181 if(!(fid->qid.type&QTDIR))
182 return "walk in non-directory";
184 if(strcmp(name, "..") == 0){
189 qid->path = PATH(Qroot, 0);
190 qid->type = tab[Qroot].mode>>24;
193 qid->path = PATH(Qiface, 0);
194 qid->type = tab[Qiface].mode>>24;
197 return "bug in fswalk1";
201 for(i = TYPE(path)+1; i<nelem(tab); i++){
204 snprint(buf, sizeof buf, "%d", n);
205 if(n < nconn && strcmp(buf, name) == 0){
206 qid->path = PATH(i, n);
207 qid->type = tab[i].mode>>24;
212 if(strcmp(name, tab[i].name) == 0){
213 qid->path = PATH(i, NUM(path));
214 qid->type = tab[i].mode>>24;
217 if(tab[i].mode&DMDIR)
220 return "directory entry not found";
232 if((b = d->q) == nil)
236 if((d->q = b->next) == nil)
238 if((d->r = (Req*)r->aux) == nil)
244 memmove(r->ofcall.data, b->rp, n);
259 if(d->q==nil && d->nb){
267 d->rt = (Req**)&r->aux;
273 writeconndata(Req *r)
283 if((n == 11) && memcmp(p, "nonblocking", n)==0){
288 /* minimum frame length for rtl8150 */
292 /* slack space for header and trailers */
301 /* copy in the ethernet packet */
302 memmove(b->wp, p, r->ifcall.count);
303 b->wp += r->ifcall.count;
308 r->ofcall.count = r->ifcall.count;
316 char *t = "0123456789abcdef";
320 buf[i*2] = t[m[i]>>4];
321 buf[i*2+1] = t[m[i]&0xF];
333 path = r->fid->qid.path;
337 snprint(e, sizeof e, "bug in fsread path=%lux", path);
342 dirread9p(r, rootgen, nil);
347 dirread9p(r, ifacegen, nil);
352 snprint(buf, sizeof(buf),
357 stats.in, stats.out, 10, macaddr);
363 snprint(buf, sizeof(buf), "%E", macaddr);
369 dirread9p(r, ndirgen, &conn[NUM(path)]);
374 snprint(buf, sizeof(buf), "%11d ", NUM(path));
380 snprint(buf, sizeof(buf), "%11d ", conn[NUM(path)].type);
399 path = r->fid->qid.path;
403 p = (char*)r->ifcall.data;
404 if((n == 11) && memcmp(p, "promiscuous", 11)==0)
405 conn[NUM(path)].prom = 1;
406 if((n > 8) && memcmp(p, "connect ", 8)==0){
409 if(n - 8 >= sizeof(x)){
410 respond(r, "invalid control msg");
418 conn[NUM(path)].type = atoi(p);
427 snprint(e, sizeof e, "bug in fswrite path=%lux", path);
435 static int need[4] = { 4, 2, 6, 1 };
443 * lib9p already handles the blatantly obvious.
444 * we just have to enforce the permissions we have set.
446 path = r->fid->qid.path;
447 t = &tab[TYPE(path)];
448 n = need[r->ifcall.mode&3];
449 if((n&t->mode) != n){
450 respond(r, "permission denied");
459 for(i=0; i<nelem(conn); i++){
464 path = PATH(Qctl, i);
467 respond(r, "out of connections");
470 d = emalloc9p(sizeof(*d));
471 memset(d, 0, sizeof(*d));
479 c = &conn[NUM(path)];
493 r->fid->qid.path = path;
494 r->ofcall.qid.path = path;
507 if(TYPE(f->qid.path) == Qdata){
510 for(p=&d->r; *p; p=(Req**)&((*p)->aux)){
512 if((*p = (Req*)o->aux) == nil)
515 respond(o, "interrupted");
526 fsdestroyfid(Fid *fid)
532 if(TYPE(fid->qid.path) >= Qndir){
533 c = &conn[NUM(fid->qid.path)];
537 for(x=&c->dq; *x; x=&((*x)->next)){
549 if(TYPE(fid->qid.path) == Qctl)
557 setalt(Dev *d, int ifcid, int altid)
559 if(usbcmd(d, Rh2d|Rstd|Riface, Rsetiface, altid, ifcid, nil, 0) < 0)
560 dprint(2, "%s: setalt ifc %d alt %d: %r\n", argv0, ifcid, altid);
564 ifaceinit(Dev *d, Iface *ifc, int *ei, int *eo)
573 for(i = 0; (epin < 0 || epout < 0) && i < nelem(ifc->ep); i++)
574 if((ep = ifc->ep[i]) != nil && ep->type == Ebulk){
575 if(ep->dir == Eboth || ep->dir == Ein)
578 if(ep->dir == Eboth || ep->dir == Eout)
582 if(epin == -1 || epout == -1)
585 for(i = 0; i < nelem(ifc->altc); i++)
586 if(ifc->altc[i] != nil)
587 setalt(d, ifc->id, i);
595 findendpoints(Dev *d, int *ei, int *eo)
597 int i, j, ctlid, datid;
598 Iface *ctlif, *datif;
606 /* look for union descriptor with ethernet ctrl interface */
607 for(i = 0; i < nelem(ud->ddesc); i++){
608 if((desc = ud->ddesc[i]) == nil)
610 if(desc->data.bLength < 5 || desc->data.bbytes[0] != Cdcunion)
613 ctlid = desc->data.bbytes[1];
614 datid = desc->data.bbytes[2];
616 if((c = desc->conf) == nil)
620 for(j = 0; j < nelem(c->iface); j++){
621 if(c->iface[j] == nil)
623 if(c->iface[j]->id == ctlid)
625 if(c->iface[j]->id == datid)
628 if(datif != nil && ctlif != nil){
629 if(Subclass(ctlif->csp) == Scether)
630 if(ifaceinit(d, datif, ei, eo) != -1)
637 /* try any other one that seems to be ok */
638 for(i = 0; i < nelem(ud->conf); i++)
639 if((c = ud->conf[i]) != nil)
640 for(j = 0; j < nelem(c->iface); j++)
641 if(ifaceinit(d,c->iface[j],ei,eo) != -1)
648 inote(void *, char *msg)
650 if(strstr(msg, "interrupt"))
656 etheriq(Block *b, int wire)
664 if(BLEN(b) < Ehdrsz){
670 t = (h->type[0]<<8)|h->type[1];
672 for(i=0; i<nconn; i++){
680 if(!c->prom && !(h->d[0]&1))
681 if(memcmp(h->d, macaddr, sizeof(macaddr)))
683 for(d=c->dq; d; d=d->next){
687 q = copyblock(b, 64);
688 } else if(wire && b->ref == 1) {
692 q = copyblock(b, BLEN(b));
709 /* transmit frees buffer */
710 (*eptransmit)(epout, b);
723 threadsetname("usbreadproc");
727 /* receive allocates buffer and calls etheriq(b, 1); */
728 if((*epreceive)(epin) < 0){
729 rerrstr(err, sizeof(err));
730 if(strstr(err, "interrupted") || strstr(err, "timed out"))
732 fprint(2, "usbreadproc: %s\n", err);
744 .destroyfid= fsdestroyfid,
756 fprint(2, "usage: %s [-dD] [-t type] [-a addr] devid\n", argv0);
760 extern int aueinit(Dev *);
761 extern int a88178init(Dev *);
762 extern int a88772init(Dev *);
763 extern int smscinit(Dev *);
764 extern int cdcinit(Dev *);
765 extern int urlinit(Dev *);
766 extern int rndisinit(Dev *);
774 "a88178", a88178init,
775 "a88772", a88772init,
782 threadmain(int argc, char **argv)
788 fmtinstall('E', eipfmt);
800 parseether(macaddr, EARGF(usage()));
804 for(et=0; et<nelem(ethertype); et++)
805 if(strcmp(t, ethertype[et].name) == 0)
807 if(et == nelem(ethertype)){
808 fprint(2, "unsupported ethertype -t %s, supported types are: ", t);
809 for(et=0; et<nelem(ethertype); et++)
810 fprint(2, "%s ", ethertype[et].name);
822 if((d = getdev(atoi(*argv))) == nil)
823 sysfatal("getdev: %r");
824 if(findendpoints(d, &ei, &eo) < 0)
825 sysfatal("no endpoints found");
828 if((*ethertype[et].init)(d) < 0)
829 sysfatal("%s init failed: %r", ethertype[et].name);
830 if(epreceive == nil || eptransmit == nil)
831 sysfatal("bug in init");
833 if((epin = openep(d, ei)) == nil)
834 sysfatal("openep: %r");
838 opendevdata(epin, ORDWR);
840 if((epout = openep(d, eo)) == nil)
841 sysfatal("openep: %r");
842 opendevdata(epin, OREAD);
843 opendevdata(epout, OWRITE);
846 proccreate(usbreadproc, nil, 8*1024);
850 tab[Qiface].name = smprint("etherU%d", d->id);
851 snprint(s, sizeof(s), "%d.ether", d->id);
853 threadpostsharesrv(&fs, nil, "usbnet", s);
863 b = emalloc9p(sizeof(*b) + size);
864 b->lim = b->base + size;
880 copyblock(Block *b, int count)
887 memmove(nb->wp, b->rp, count);