2 * USB device driver framework.
4 * This is in charge of providing access to actual HCIs
5 * and providing I/O to the various endpoints of devices.
6 * A separate user program (usbd) is in charge of
7 * enumerating the bus, setting up endpoints and
8 * starting devices (also user programs).
10 * The interface provided is a violation of the standard:
13 * The interface consists of a root directory with several files
14 * plus a directory (epN.M) with two files per endpoint.
15 * A device is represented by its first endpoint, which
16 * is a control endpoint automatically allocated for each device.
17 * Device control endpoints may be used to create new endpoints.
18 * Devices corresponding to hubs may also allocate new devices,
19 * perhaps also hubs. Initially, a hub device is allocated for
20 * each controller present, to represent its root hub. Those can
23 * All endpoints refer to the first endpoint (epN.0) of the device,
24 * which keeps per-device information, and also to the HCI used
25 * to reach them. Although all endpoints cache that information.
27 * epN.M/data files permit I/O and are considered DMEXCL.
28 * epN.M/ctl files provide status info and accept control requests.
30 * Endpoints may be given file names to be listed also at #u,
31 * for those drivers that have nothing to do after configuring the
32 * device and its endpoints.
34 * Drivers for different controllers are kept at usb[oue]hci.c
35 * It's likely we could factor out much from controllers into
36 * a generic controller driver, the problem is that details
37 * regarding how to handle toggles, tokens, Tds, etc. will
38 * get in the way. Thus, code is probably easier the way it is.
42 #include "../port/lib.h"
47 #include "../port/error.h"
48 #include "../port/usb.h"
50 typedef struct Hcitype Hcitype;
57 Qctl, /* #u/usb/ctl - control requests */
59 Qep0dir, /* #u/usb/ep0.0 - endpoint 0 dir */
60 Qep0io, /* #u/usb/ep0.0/data - endpoint 0 I/O */
61 Qep0ctl, /* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
62 Qep0dummy, /* give 4 qids to each endpoint */
64 Qepdir = 0, /* (qid-qep0dir)&3 is one of these */
65 Qepio, /* to identify which file for the endpoint */
71 CMdebug = 0, /* debug on|off */
72 CMdump, /* dump (data structures for debug) */
75 CMnew = 0, /* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
76 CMnewdev, /* newdev full|low|high|super portnb (allocate new devices) */
77 CMhub, /* hub (set the device as a hub) */
78 CMspeed, /* speed full|low|high|no */
79 CMmaxpkt, /* maxpkt size */
80 CMntds, /* ntds nb (max nb. of tds per µframe) */
81 CMclrhalt, /* clrhalt (halt was cleared on endpoint) */
82 CMpollival, /* pollival interval (interrupt/iso) */
83 CMhz, /* hz n (samples/sec; iso) */
84 CMsamplesz, /* samplesz n (sample size; iso) */
85 CMinfo, /* info infostr (ke.ep info for humans) */
86 CMdetach, /* detach (abort I/O forever on this ep). */
87 CMaddress, /* address (address is assigned) */
88 CMdebugep, /* debug n (set/clear debug for this ep) */
89 CMname, /* name str (show up as #u/name as well) */
90 CMtmout, /* timeout n (activate timeouts for ep) */
91 CMsampledelay, /* maximum delay introduced by buffering (iso) */
92 CMpreset, /* reset the port */
93 CMuframes, /* set uframe mode (iso) */
95 /* Hub feature selectors */
107 #define QID(q) ((int)(q).path)
109 static char Edetach[] = "device is detached";
110 static char Enotconf[] = "endpoint not configured";
111 char Estalled[] = "endpoint stalled";
113 static Cmdtab usbctls[] =
115 {CMdebug, "debug", 2},
119 static Cmdtab epctls[] =
122 {CMnewdev, "newdev", 3},
124 {CMspeed, "speed", 2},
125 {CMmaxpkt, "maxpkt", 2},
127 {CMpollival, "pollival", 2},
128 {CMsamplesz, "samplesz", 2},
131 {CMdetach, "detach", 1},
132 {CMaddress, "address", 1},
133 {CMdebugep, "debug", 2},
134 {CMclrhalt, "clrhalt", 1},
136 {CMtmout, "timeout", 2},
137 {CMsampledelay, "sampledelay", 2},
138 {CMpreset, "reset", 1},
139 {CMuframes, "uframes", 2},
142 static Dirtab usbdir[] =
144 "ctl", {Qctl}, 0, 0666,
147 char *usbmodename[] =
154 static char *ttname[] =
163 static char *spname[] =
165 [Superspeed] "super",
173 static Hcitype hcitypes[Nhcis];
174 static Hci* hcis[Nhcis];
175 static QLock epslck; /* add, del, lookup endpoints */
176 static Ep* eps[Neps]; /* all endpoints known */
177 static int epmax; /* 1 + last endpoint index used */
178 static int usbidgen; /* device address generator */
181 * Is there something like this in a library? should it be?
184 seprintdata(char *s, char *se, uchar *d, int n)
188 s = seprint(s, se, " %#p[%d]: ", d, n);
193 s = seprint(s, se, " %2.2ux", d[i]);
195 s = seprint(s, se, "...");
200 name2speed(char *name)
204 for(i = 0; i < nelem(spname); i++)
205 if(strcmp(name, spname[i]) == 0)
211 name2ttype(char *name)
215 for(i = 0; i < nelem(ttname); i++)
216 if(strcmp(name, ttname[i]) == 0)
218 /* may be a std. USB ep. type */
219 i = strtol(name, nil, 0);
232 name2mode(char *mode)
236 for(i = 0; i < nelem(usbmodename); i++)
237 if(strcmp(mode, usbmodename[i]) == 0)
246 if(q < 0 || q >= epmax || eps[q] == nil)
252 isqtype(int q, int type)
257 return (q & 3) == type;
261 addhcitype(char* t, int (*r)(Hci*))
266 panic("too many USB host interface types");
267 hcitypes[ntype].type = t;
268 hcitypes[ntype].reset = r;
273 seprintep(char *s, char *se, Ep *ep, int all)
275 static char* dsnames[] = { "config", "enabled", "detached", "reset" };
289 s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
290 s = seprint(s, se, "%s", dsnames[ep->dev->state]);
291 s = seprint(s, se, " %s", ttname[ep->ttype]);
292 assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
293 s = seprint(s, se, " %s", usbmodename[ep->mode]);
294 s = seprint(s, se, " speed %s", spname[d->speed]);
295 s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
296 s = seprint(s, se, " ntds %ld", ep->ntds);
297 s = seprint(s, se, " pollival %ld", ep->pollival);
298 s = seprint(s, se, " samplesz %ld", ep->samplesz);
299 s = seprint(s, se, " hz %ld", ep->hz);
300 s = seprint(s, se, " uframes %ld", ep->uframes);
301 s = seprint(s, se, " hub %d", ep->dev->hub);
302 s = seprint(s, se, " port %d", ep->dev->port);
303 s = seprint(s, se, " rootport %d", ep->dev->rootport);
304 s = seprint(s, se, " addr %d", ep->dev->addr);
306 s = seprint(s, se, " busy");
308 s = seprint(s, se, " idle");
310 s = seprint(s, se, " load %uld", ep->load);
311 s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
312 s = seprint(s, se, " idx %d", ep->idx);
314 s = seprint(s, se, " name '%s'", ep->name);
316 s = seprint(s, se, " tmout");
318 s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
319 s = seprint(s, se, " eps:");
320 for(i = 0; i < nelem(d->eps); i++)
322 s = seprint(s, se, " ep%d.%d", di, i);
326 s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
328 s = seprint(s, se, "\n");
340 ep = smalloc(sizeof(Ep));
343 for(i = 0; i < Neps; i++)
349 print("usb: bug: too few endpoints.\n");
359 ep->uframes = ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
369 if(i < 0 || i >= epmax || eps[i] == nil)
384 if(ep == nil || decref(ep) > 0)
387 deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
390 if(ep->idx == epmax-1)
392 if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
397 d->eps[ep->nb] = nil;
417 static char buf[512];
422 print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
423 for(i = 0; i < epmax; i++){
432 s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
433 seprintep(s, e, ep, 1);
435 if(ep->hp->seprintep != nil){
436 ep->hp->seprintep(buf, e, ep);
443 print("usb dump hcis:\n");
444 for(i = 0; i < Nhcis; i++)
445 if(hcis[i] != nil && hcis[i]->dump != nil)
446 hcis[i]->dump(hcis[i]);
457 print("#u: too many device addresses; reuse them more\n");
463 * Create endpoint 0 for a new device
466 newdev(Hci *hp, int ishub, int isroot)
472 d = ep->dev = smalloc(sizeof(Udev));
473 d->nb = newusbid(hp);
477 ep->toggle[0] = ep->toggle[1] = 0;
483 d->speed = Fullspeed;
484 d->state = Dconfig; /* address not yet set */
486 ep->ep0 = ep; /* no ref counted here */
488 ep->tmout = Xfertmout;
490 dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
495 * Create a new endpoint for the device
496 * accessed via the given endpoint 0.
499 newdevep(Ep *ep, int i, int tt, int mode)
506 error("endpoint already in use");
507 nep = epalloc(ep->hp);
511 nep->toggle[0] = nep->toggle[1] = 0;
516 nep->debug = ep->debug;
520 nep->tmout = Xfertmout;
526 nep->tmout = Xfertmout;
533 deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
554 usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
564 if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
566 if(QID(c->qid) <= Qusbdir){
567 mkqid(&q, Qdir, 0, QTDIR);
568 devdir(c, q, "#u", 0, eve, 0555, dp);
570 mkqid(&q, Qusbdir, 0, QTDIR);
571 devdir(c, q, "usb", 0, eve, 0555, dp);
573 if(0)ddprint("ok\n");
578 case Qdir: /* list #u */
580 mkqid(&q, Qusbdir, 0, QTDIR);
581 devdir(c, q, "usb", 0, eve, 0555, dp);
582 if(0)ddprint("ok\n");
586 if(s < 0 || s >= epmax)
589 if(ep == nil || ep->name == nil){
592 if(0)ddprint("skip\n");
599 mkqid(&q, Qep0io+s*4, 0, QTFILE);
600 devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
603 if(0)ddprint("ok\n");
606 case Qusbdir: /* list #u/usb */
608 if(s < nelem(usbdir)){
610 mkqid(&q, dir->qid.path, 0, QTFILE);
611 devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
612 if(0)ddprint("ok\n");
616 if(s < 0 || s >= epmax)
620 if(0)ddprint("skip\n");
627 se = up->genbuf+sizeof(up->genbuf);
628 seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
629 mkqid(&q, Qep0dir+4*s, 0, QTDIR);
632 devdir(c, q, up->genbuf, 0, eve, 0755, dp);
633 if(0)ddprint("ok\n");
640 default: /* list #u/usb/epN.M */
641 nb = qid2epidx(QID(c->qid));
647 if(isqtype(QID(c->qid), Qepdir)){
651 mkqid(&q, Qep0io+nb*4, 0, QTFILE);
652 perm = epdataperm(mode);
653 devdir(c, q, "data", 0, eve, perm, dp);
656 mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
657 devdir(c, q, "ctl", 0, eve, 0664, dp);
662 }else if(isqtype(QID(c->qid), Qepctl)){
669 if(0)ddprint("ok\n");
673 if(0)ddprint("fail\n");
678 hciprobe(int cardno, int ctlrno)
682 static int epnb = 1; /* guess the endpoint nb. for the controller */
684 ddprint("hciprobe %d %d\n", cardno, ctlrno);
685 hp = smalloc(sizeof(Hci));
687 hp->tbdf = BUSUNKNOWN;
690 if(isaconfig("usb", ctlrno, hp) == 0){
694 for(cardno = 0; cardno < Nhcis; cardno++){
695 if(hcitypes[cardno].type == nil)
698 if(type==nil || *type==0)
700 if(cistrcmp(hcitypes[cardno].type, type) == 0)
705 if(cardno >= Nhcis || hcitypes[cardno].type == nil){
709 dprint("%s...", hcitypes[cardno].type);
710 if(hcitypes[cardno].reset(hp) < 0){
716 * modern machines have too many usb controllers to list on
719 dprint("#u/usb/ep%d.0: %s: port 0x%luX irq %d\n",
720 epnb, hcitypes[cardno].type, hp->port, hp->irq);
731 if(getconf("*nousbprobe"))
733 dprint("usbreset\n");
735 for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
736 if((hp = hciprobe(-1, ctlrno)) != nil)
739 while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
740 if(hcis[ctlrno] != nil)
743 hp = hciprobe(cardno, ctlrno);
748 if(hcis[Nhcis-1] != nil)
749 print("usbreset: bug: Nhcis (%d) too small\n", Nhcis);
772 for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
779 print("usbinit: %s: %s\n", hp->type, up->errstr);
786 hp->superspeed &= (1<<hp->nports)-1;
787 n = hp->nports - numbits(hp->superspeed);
789 d = newdev(hp, 1, 1); /* new LS/FS/HS root hub */
791 if(hp->highspeed != 0)
792 d->dev->speed = Highspeed;
793 d->dev->state = Denabled; /* although addr == 0 */
794 snprint(info, sizeof(info), "roothub ports %d", n);
795 kstrdup(&d->info, info);
797 n = numbits(hp->superspeed);
799 d = newdev(hp, 1, 1); /* new SS root hub */
801 d->dev->speed = Superspeed;
802 d->dev->state = Denabled; /* although addr == 0 */
803 snprint(info, sizeof(info), "roothub ports %d", n);
804 kstrdup(&d->info, info);
811 usbattach(char *spec)
813 return devattach(L'u', spec);
817 usbwalk(Chan *c, Chan *nc, char **name, int nname)
819 return devwalk(c, nc, name, nname, nil, 0, usbgen);
823 usbstat(Chan *c, uchar *db, int n)
825 return devstat(c, db, n, nil, 0, usbgen);
829 * µs for the given transfer, for bandwidth allocation.
830 * This is a very rough worst case for what 5.11.3
831 * of the usb 2.0 spec says.
832 * Also, we are using maxpkt and not actual transfer sizes.
833 * Only when we are sure we
834 * are not exceeding b/w might we consider adjusting it.
837 usbload(int speed, int maxpkt)
839 enum{ Hostns = 1000, Hubns = 333 };
847 l = 55*8*2 + 2 * (3 + bs) + Hostns;
850 l = 9107 + 84 * (4 + bs) + Hostns;
853 l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
856 print("usbload: bad speed %d\n", speed);
859 return l / 1000UL; /* in µs */
863 usbopen(Chan *c, int omode)
869 mode = openmode(omode);
872 if(q >= Qep0dir && qid2epidx(q) < 0)
874 if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
875 return devopen(c, omode, nil, 0, usbgen);
877 ep = getep(qid2epidx(q));
880 deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
896 if(mode != OREAD && ep->mode == OREAD)
898 if(mode != OWRITE && ep->mode == OWRITE)
900 if(ep->ttype == Tnone)
904 if(ep->load == 0 && ep->dev->speed != Superspeed)
905 ep->load = usbload(ep->dev->speed, ep->maxpkt);
908 poperror(); /* ep->inuse */
909 poperror(); /* don't putep(): ref kept for fid using the ep. */
914 c->aux = nil; /* paranoia */
941 if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
944 ep = getep(qid2epidx(q));
947 deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
956 putep(ep); /* release ref kept since usbopen */
964 ctlread(Chan *c, void *a, long n, vlong offset)
974 us = s = smalloc(READSTR);
981 for(i = 0; i < epmax; i++){
988 s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
989 s = seprintep(s, se, ep, 0);
995 ep = getep(qid2epidx(q));
1003 /* After a new endpoint request we read
1004 * the new endpoint name back.
1006 strecpy(s, se, c->aux);
1010 seprintep(s, se, ep, 0);
1014 n = readstr(offset, a, n, us);
1021 * Fake root hub emulation.
1024 rhubread(Ep *ep, void *a, long n)
1028 if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2 || ep->rhrepl == -1)
1032 b[1] = ep->rhrepl>>8;
1033 b[2] = ep->rhrepl>>16;
1034 b[3] = ep->rhrepl>>24;
1035 b[4] = ep->rhrepl>>32;
1036 b[5] = ep->rhrepl>>40;
1037 b[6] = ep->rhrepl>>48;
1038 b[7] = ep->rhrepl>>56;
1050 rootport(Ep *ep, int port)
1060 return hub->rootport;
1062 mask = hp->superspeed;
1063 if(hub->speed != Superspeed)
1064 mask = (1<<hp->nports)-1 & ~mask;
1066 for(rootport = 1; mask != 0; rootport++){
1078 rhubwrite(Ep *ep, void *a, long n)
1086 if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
1089 error("root hub is a toy hub");
1092 if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
1093 error("root hub is a toy hub");
1096 feature = GET2(s+Rvalue);
1097 port = rootport(ep, GET2(s+Rindex));
1099 error("bad hub port number");
1102 ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
1105 ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
1108 ep->rhrepl = hp->portstatus(hp, port);
1117 usbread(Chan *c, void *a, long n, vlong offset)
1125 if(c->qid.type == QTDIR)
1126 return devdirread(c, a, n, nil, 0, usbgen);
1128 if(q == Qctl || isqtype(q, Qepctl))
1129 return ctlread(c, a, n, offset);
1131 ep = getep(qid2epidx(q));
1138 if(ep->dev->state == Ddetach)
1140 if(ep->mode == OWRITE || ep->inuse == 0)
1144 error("endpoint not configured");
1146 nr = rhubread(ep, a, n);
1153 ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
1154 n = ep->hp->epread(ep, a, n);
1163 setmaxpkt(Ep *ep, char* s)
1165 long spp, max; /* samples per packet */
1167 if(ep->dev->speed == Fullspeed)
1168 spp = (ep->hz * ep->pollival + 999) / 1000;
1170 spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
1171 ep->maxpkt = spp * ep->samplesz;
1172 deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
1173 " ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
1174 ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
1176 switch(ep->dev->speed){
1189 if(ep->maxpkt*ep->ntds > max){
1190 print("usb: %s: maxpkt %ld > %ld for %s, truncating\n",
1191 s, ep->maxpkt*ep->ntds, max, spname[ep->dev->speed]);
1192 ep->maxpkt = max/ep->ntds;
1197 * Many endpoint ctls. simply update the portable representation
1198 * of the endpoint. The actual controller driver will look
1199 * at them to setup the endpoints as dictated.
1202 epctl(Ep *ep, Chan *c, void *a, long n)
1204 int i, l, mode, nb, tt;
1210 static char *Info = "info ";
1214 cb = parsecmd(a, n);
1219 ct = lookupcmd(cb, epctls, nelem(epctls));
1221 if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
1223 error("allowed only on a setup endpoint");
1224 if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
1225 if(ep != ep->ep0 && ep->inuse != 0)
1226 error("must configure before using");
1229 deprint("usb epctl %s\n", cb->f[0]);
1230 nb = strtol(cb->f[1], nil, 0);
1231 if(nb < 0 || nb >= Ndeveps)
1232 error("bad endpoint number");
1233 tt = name2ttype(cb->f[2]);
1235 error("unknown endpoint type");
1236 mode = name2mode(cb->f[3]);
1238 error("unknown i/o mode");
1239 newdevep(ep, nb, tt, mode);
1242 deprint("usb epctl %s\n", cb->f[0]);
1243 if(ep != ep->ep0 || d->ishub == 0)
1244 error("not a hub setup endpoint");
1245 l = name2speed(cb->f[1]);
1247 error("speed must be full|low|high|super");
1248 if(l != d->speed && (l == Superspeed || d->speed == Superspeed))
1249 error("wrong speed for superspeed hub/device");
1250 nep = newdev(ep->hp, 0, 0);
1251 nep->dev->speed = l;
1254 else if(l != Lowspeed)
1255 nep->maxpkt = 64; /* assume full speed */
1256 nep->dev->hub = d->addr;
1257 nep->dev->port = atoi(cb->f[2]);
1258 nep->dev->depth = d->depth+1;
1259 nep->dev->rootport = rootport(ep, nep->dev->port);
1260 nep->dev->routestr = d->routestr | (((nep->dev->port&15) << 4*nep->dev->depth) >> 4);
1261 /* next read request will read
1262 * the name for the new endpoint
1264 l = sizeof(up->genbuf);
1265 snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
1266 kstrdup(&c->aux, up->genbuf);
1269 deprint("usb epctl %s\n", cb->f[0]);
1273 l = name2speed(cb->f[1]);
1274 deprint("usb epctl %s %d\n", cb->f[0], l);
1276 error("speed must be full|low|high|super");
1277 if(l != d->speed && (l == Superspeed || d->speed == Superspeed))
1278 error("cannot change speed on superspeed device");
1284 l = strtoul(cb->f[1], nil, 0);
1285 deprint("usb epctl %s %d\n", cb->f[0], l);
1286 if(l < 1 || l > 1024)
1287 error("maxpkt not in [1:1024]");
1293 l = strtoul(cb->f[1], nil, 0);
1294 deprint("usb epctl %s %d\n", cb->f[0], l);
1296 error("ntds not in [1:3]");
1302 if(ep->ttype != Tintr && ep->ttype != Tiso)
1303 error("not an intr or iso endpoint");
1304 l = strtoul(cb->f[1], nil, 0);
1305 deprint("usb epctl %s %d\n", cb->f[0], l);
1306 if(ep->dev->speed == Fullspeed || ep->dev->speed == Lowspeed){
1307 if(l < 1 || l > 255)
1308 error("pollival not in [1:255]");
1311 error("pollival power not in [1:16]");
1316 if(ep->ttype == Tiso)
1317 setmaxpkt(ep, "pollival");
1321 if(ep->ttype != Tiso)
1322 error("not an iso endpoint");
1323 l = strtoul(cb->f[1], nil, 0);
1324 deprint("usb epctl %s %d\n", cb->f[0], l);
1326 error("samplesz not in [1:8]");
1329 setmaxpkt(ep, "samplesz");
1333 if(ep->ttype != Tiso)
1334 error("not an iso endpoint");
1335 l = strtoul(cb->f[1], nil, 0);
1336 deprint("usb epctl %s %d\n", cb->f[0], l);
1337 if(l <= 0 || l > 100000)
1338 error("hz not in [1:100000]");
1341 setmaxpkt(ep, "hz");
1345 if(ep->ttype != Tiso)
1346 error("not an iso endpoint");
1347 l = strtoul(cb->f[1], nil, 0);
1348 deprint("usb uframes %s %d\n", cb->f[0], l);
1349 if(l != 0 && l != 1)
1350 error("uframes not in [0:1]");
1357 deprint("usb epctl %s\n", cb->f[0]);
1362 deprint("usb epctl %s\n", cb->f[0]);
1365 if(n < l+2 || strncmp(Info, s, l) != 0)
1370 memmove(b, s+l, n-l);
1372 if(b[n-l-1] == '\n')
1380 deprint("usb epctl %s\n", cb->f[0]);
1381 if(ep->dev->addr == 0)
1382 ep->dev->addr = ep->dev->nb;
1383 ep->dev->state = Denabled;
1386 if(ep->dev->isroot != 0)
1387 error("can't detach a root hub");
1388 deprint("usb epctl %s ep%d.%d\n",
1389 cb->f[0], ep->dev->nb, ep->nb);
1390 ep->dev->state = Ddetach;
1391 /* Release file system ref. for its endpoints */
1392 for(i = 0; i < nelem(ep->dev->eps); i++)
1393 putep(ep->dev->eps[i]);
1396 if(strcmp(cb->f[1], "on") == 0)
1398 else if(strcmp(cb->f[1], "off") == 0)
1401 ep->debug = strtoul(cb->f[1], nil, 0);
1402 print("usb: ep%d.%d debug %d\n",
1403 ep->dev->nb, ep->nb, ep->debug);
1406 deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
1407 validname(cb->f[1], 0);
1408 kstrdup(&ep->name, cb->f[1]);
1411 deprint("usb epctl %s\n", cb->f[0]);
1412 if(ep->ttype == Tiso || ep->ttype == Tctl)
1413 error("ctl ignored for this endpoint type");
1414 ep->tmout = strtoul(cb->f[1], nil, 0);
1415 if(ep->tmout != 0 && ep->tmout < Xfertmout)
1416 ep->tmout = Xfertmout;
1419 if(ep->ttype != Tiso)
1420 error("ctl ignored for this endpoint type");
1421 ep->sampledelay = strtoul(cb->f[1], nil, 0);
1424 deprint("usb epctl %s\n", cb->f[0]);
1425 if(ep->ttype != Tctl)
1426 error("not a control endpoint");
1427 if(ep->dev->state != Denabled)
1428 error("forbidden on devices not enabled");
1429 ep->dev->state = Dreset;
1432 panic("usb: unknown epctl %d", ct->index);
1440 usbctl(void *a, long n)
1447 cb = parsecmd(a, n);
1452 ct = lookupcmd(cb, usbctls, nelem(usbctls));
1453 dprint("usb ctl %s\n", cb->f[0]);
1456 if(strcmp(cb->f[1], "on") == 0)
1458 else if(strcmp(cb->f[1], "off") == 0)
1461 debug = strtol(cb->f[1], nil, 0);
1462 print("usb: debug %d\n", debug);
1463 for(i = 0; i < epmax; i++)
1464 if((ep = getep(i)) != nil){
1465 if(ep->hp->debug != nil)
1466 ep->hp->debug(ep->hp, debug);
1480 ctlwrite(Chan *c, void *a, long n)
1487 return usbctl(a, n);
1489 ep = getep(qid2epidx(q));
1496 if(ep->dev->state == Ddetach)
1498 if(isqtype(q, Qepctl) && c->aux != nil){
1499 /* Be sure we don't keep a cloned ep name */
1502 error("read, not write, expected");
1504 n = epctl(ep, c, a, n);
1511 usbwrite(Chan *c, void *a, long n, vlong off)
1516 if(c->qid.type == QTDIR)
1521 if(q == Qctl || isqtype(q, Qepctl))
1522 return ctlwrite(c, a, n);
1524 ep = getep(qid2epidx(q));
1531 if(ep->dev->state == Ddetach)
1533 if(ep->mode == OREAD || ep->inuse == 0)
1538 error("endpoint not configured");
1540 nr = rhubwrite(ep, a, n);
1547 ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
1548 ep->hp->epwrite(ep, a, n);
1561 for(i = 0; i < Nhcis; i++){
1565 if(hp->shutdown == nil)
1566 print("#u: no shutdown function for %s\n", hp->type);