The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/devusb.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * USB device driver.
    3  *
    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).
    9  *
   10  * The interface provided is a violation of the standard:
   11  * you're welcome.
   12  *
   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
   21  * never be removed.
   22  *
   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.
   26  *
   27  * epN.M/data files permit I/O and are considered DMEXCL.
   28  * epN.M/ctl files provide status info and accept control requests.
   29  *
   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.
   33  *
   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.
   39  *
   40  */
   41 
   42 #include        "u.h"
   43 #include        "../port/lib.h"
   44 #include        "mem.h"
   45 #include        "dat.h"
   46 #include        "fns.h"
   47 #include        "io.h"
   48 #include        "../port/error.h"
   49 #include        "usb.h"
   50 
   51 typedef struct Hcitype Hcitype;
   52 
   53 enum
   54 {
   55         /* Qid numbers */
   56         Qdir = 0,               /* #u */
   57         Qusbdir,                        /* #u/usb */
   58         Qctl,                   /* #u/usb/ctl - control requests */
   59 
   60         Qep0dir,                        /* #u/usb/ep0.0 - endpoint 0 dir */
   61         Qep0io,                 /* #u/usb/ep0.0/data - endpoint 0 I/O */
   62         Qep0ctl,                /* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
   63         Qep0dummy,              /* give 4 qids to each endpoint */
   64 
   65         Qepdir = 0,             /* (qid-qep0dir)&3 is one of these */
   66         Qepio,                  /* to identify which file for the endpoint */
   67         Qepctl,
   68 
   69         /* ... */
   70 
   71         /* Usb ctls. */
   72         CMdebug = 0,            /* debug on|off */
   73         CMdump,                 /* dump (data structures for debug) */
   74         CMreset,                /* reset the bus; start over */
   75 
   76         /* Ep. ctls */
   77         CMnew = 0,              /* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
   78         CMnewdev,               /* newdev full|low|high portnb (allocate new devices) */
   79         CMhub,                  /* hub (set the device as a hub) */
   80         CMspeed,                /* speed full|low|high|no */
   81         CMmaxpkt,               /* maxpkt size */
   82         CMntds,                 /* ntds nb (max nb. of tds per µframe) */
   83         CMclrhalt,              /* clrhalt (halt was cleared on endpoint) */
   84         CMpollival,             /* pollival interval (interrupt/iso) */
   85         CMhz,                   /* hz n (samples/sec; iso) */
   86         CMsamplesz,             /* samplesz n (sample size; iso) */
   87         CMinfo,                 /* info infostr (ke.ep info for humans) */
   88         CMdetach,               /* detach (abort I/O forever on this ep). */
   89         CMaddress,              /* address (address is assigned) */
   90         CMdebugep,              /* debug n (set/clear debug for this ep) */
   91         CMname,                 /* name str (show up as #u/name as well) */
   92 
   93         /* Hub feature selectors */
   94         Rportenable     = 1,
   95         Rportreset      = 4,
   96 
   97 };
   98 
   99 struct Hcitype
  100 {
  101         char*   type;
  102         int     (*reset)(Hci*);
  103 };
  104 
  105 #define QID(q)  ((int)(q).path)
  106 
  107 static char Edetach[] = "device is detached";
  108 static char Enotconf[] = "endpoint not configured";
  109 char Estalled[] = "endpoint stalled";
  110 
  111 static Cmdtab usbctls[] =
  112 {
  113         {CMdebug,       "debug",        2},
  114         {CMdump,        "dump",         1},
  115         {CMreset,       "reset",        1},
  116 };
  117 
  118 static Cmdtab epctls[] =
  119 {
  120         {CMnew,         "new",          4},
  121         {CMnewdev,      "newdev",       3},
  122         {CMhub,         "hub",          1},
  123         {CMspeed,       "speed",        2},
  124         {CMmaxpkt,      "maxpkt",       2},
  125         {CMntds,        "ntds",         2},
  126         {CMpollival,    "pollival",     2},
  127         {CMsamplesz,    "samplesz",     2},
  128         {CMhz,          "hz",           2},
  129         {CMinfo,                "info",         0},
  130         {CMdetach,      "detach",       1},
  131         {CMaddress,     "address",      1},
  132         {CMdebugep,     "debug",        2},
  133         {CMclrhalt,     "clrhalt",      1},
  134         {CMname,        "name",         2},
  135 };
  136 
  137 static Dirtab usbdir[] =
  138 {
  139         "ctl",          {Qctl},         0,      0666,
  140 };
  141 
  142 char *usbmodename[] =
  143 {
  144         [OREAD] "r",
  145         [OWRITE]        "w",
  146         [ORDWR] "rw",
  147 };
  148 
  149 static char *ttname[] =
  150 {
  151         [Tnone] "none",
  152         [Tctl]  "control",
  153         [Tiso]  "iso",
  154         [Tintr] "interrupt",
  155         [Tbulk] "bulk",
  156 };
  157 
  158 static char *spname[] =
  159 {
  160         [Fullspeed]     "full",
  161         [Lowspeed]      "low",
  162         [Highspeed]     "high",
  163         [Nospeed]       "no",
  164 };
  165 
  166 static int      debug;
  167 static Hcitype  hcitypes[Nhcis];
  168 static Hci*     hcis[Nhcis];
  169 static QLock    epslck;         /* add, del, lookup endpoints */
  170 static Ep*      eps[Neps];      /* all endpoints known */
  171 static int      epmax;          /* 1 + last endpoint index used  */
  172 static int      usbidgen;       /* device address generator */
  173 
  174 /*
  175  * Is there something like this in a library? should it be?
  176  */
  177 char*
  178 seprintdata(char *s, char *se, uchar *d, int n)
  179 {
  180         int i;
  181         int l;
  182 
  183         s = seprint(s, se, " %#p[%d]: ", d, n);
  184         l = n;
  185         if(l > 10)
  186                 l = 10;
  187         for(i=0; i<l; i++)
  188                 s = seprint(s, se, " %2.2ux", d[i]);
  189         if(l < n)
  190                 s = seprint(s, se, "...");
  191         return s;
  192 }
  193 
  194 static int
  195 name2speed(char *name)
  196 {
  197         int i;
  198 
  199         for(i = 0; i < nelem(spname); i++)
  200                 if(strcmp(name, spname[i]) == 0)
  201                         return i;
  202         return Nospeed;
  203 }
  204 
  205 static int
  206 name2ttype(char *name)
  207 {
  208         int i;
  209 
  210         for(i = 0; i < nelem(ttname); i++)
  211                 if(strcmp(name, ttname[i]) == 0)
  212                         return i;
  213         /* may be a std. USB ep. type */
  214         i = strtol(name, nil, 0);
  215         switch(i+1){
  216         case Tctl:
  217         case Tiso:
  218         case Tbulk:
  219         case Tintr:
  220                 return i+1;
  221         default:
  222                 return Tnone;
  223         }
  224 }
  225 
  226 static int
  227 name2mode(char *mode)
  228 {
  229         int i;
  230 
  231         for(i = 0; i < nelem(usbmodename); i++)
  232                 if(strcmp(mode, usbmodename[i]) == 0)
  233                         return i;
  234         return -1;
  235 }
  236 
  237 static int
  238 qid2epidx(int q)
  239 {
  240         q = (q-Qep0dir)/4;
  241         if(q < 0 || q >= epmax || eps[q] == nil)
  242                 return -1;
  243         return q;
  244 }
  245 
  246 static int
  247 isqtype(int q, int type)
  248 {
  249         if(q < Qep0dir)
  250                 return 0;
  251         q -= Qep0dir;
  252         return (q & 3) == type;
  253 }
  254 
  255 void
  256 addhcitype(char* t, int (*r)(Hci*))
  257 {
  258         static int ntype;
  259 
  260         if(ntype == Nhcis)
  261                 panic("too many USB host interface types");
  262         hcitypes[ntype].type = t;
  263         hcitypes[ntype].reset = r;
  264         ntype++;
  265 }
  266 
  267 static char*
  268 seprintep(char *s, char *se, Ep *ep, int all)
  269 {
  270         static char* dsnames[] = { "config", "enabled", "detached" };
  271         Udev *d;
  272         int i;
  273         int di;
  274 
  275         d = ep->dev;
  276 
  277         qlock(ep);
  278         if(waserror()){
  279                 qunlock(ep);
  280                 nexterror();
  281         }
  282         di = ep->dev->nb;
  283         if(all)
  284                 s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
  285         s = seprint(s, se, "%s", dsnames[ep->dev->state]);
  286         s = seprint(s, se, " %s", ttname[ep->ttype]);
  287         assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
  288         s = seprint(s, se, " %s", usbmodename[ep->mode]);
  289         s = seprint(s, se, " speed %s", spname[d->speed]);
  290         s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
  291         s = seprint(s, se, " pollival %ld", ep->pollival);
  292         s = seprint(s, se, " samplesz %ld", ep->samplesz);
  293         s = seprint(s, se, " hz %ld", ep->hz);
  294         s = seprint(s, se, " hub %d", ep->dev->hub);
  295         s = seprint(s, se, " port %d", ep->dev->port);
  296         if(ep->inuse)
  297                 s = seprint(s, se, " busy");
  298         else
  299                 s = seprint(s, se, " idle");
  300         if(all){
  301                 s = seprint(s, se, " load %uld", ep->load);
  302                 s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
  303                 s = seprint(s, se, " idx %d", ep->idx);
  304                 if(ep->name != nil)
  305                         s = seprint(s, se, " name '%s'", ep->name);
  306                 if(ep == ep->ep0){
  307                         s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
  308                         s = seprint(s, se, " eps:");
  309                         for(i = 0; i < nelem(d->eps); i++)
  310                                 if(d->eps[i] != nil)
  311                                         s = seprint(s, se, " ep%d.%d", di, i);
  312                 }
  313         }
  314         if(ep->info != nil)
  315                 s = seprint(s, se, "\n%s\n", ep->info);
  316         else
  317                 s = seprint(s, se, "\n");
  318         qunlock(ep);
  319         poperror();
  320         return s;
  321 }
  322 
  323 static Ep*
  324 epalloc(Hci *hp)
  325 {
  326         Ep *ep;
  327         int i;
  328 
  329         ep = mallocz(sizeof(Ep), 1);
  330         ep->ref = 1;
  331         qlock(&epslck);
  332         for(i = 0; i < Neps; i++)
  333                 if(eps[i] == nil)
  334                         break;
  335         if(i == Neps){
  336                 qunlock(&epslck);
  337                 free(ep);
  338                 print("usb: bug: too few endpoints.\n");
  339                 return nil;     
  340         }
  341         ep->idx = i;
  342         if(epmax <= i)
  343                 epmax = i+1;
  344         eps[i] = ep;
  345         ep->hp = hp;
  346         ep->maxpkt = 8;
  347         ep->ntds = 1;
  348         ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
  349         qunlock(&epslck);
  350         return ep;
  351 }
  352 
  353 static Ep*
  354 getep(int i)
  355 {
  356         Ep *ep;
  357 
  358         if(i < 0 || i >= epmax || eps[i] == nil)
  359                 return nil;
  360         qlock(&epslck);
  361         ep = eps[i];
  362         if(ep != nil)
  363                 incref(ep);
  364         qunlock(&epslck);
  365         return ep;
  366 }
  367 
  368 static void
  369 putep(Ep *ep)
  370 {
  371         Udev *d;
  372 
  373         if(ep != nil && decref(ep) == 0){
  374                 d = ep->dev;
  375                 deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
  376                 qlock(&epslck);
  377                 eps[ep->idx] = nil;
  378                 if(ep->idx == epmax-1)
  379                         epmax--;
  380                 if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
  381                         usbidgen--;
  382                 qunlock(&epslck);
  383                 if(d != nil){
  384                         qlock(ep->ep0);
  385                         d->eps[ep->nb] = nil;
  386                         qunlock(ep->ep0);
  387                 }
  388                 if(ep->ep0 != ep){
  389                         putep(ep->ep0);
  390                         ep->ep0 = nil;
  391                 }
  392                 free(ep->info);
  393                 free(ep->name);
  394                 free(ep);
  395         }
  396 }
  397 
  398 static void
  399 dumpeps(void)
  400 {
  401         int i;
  402         static char buf[512];
  403         char *s;
  404         char *e;
  405         Ep *ep;
  406 
  407         print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
  408         for(i = 0; i < epmax; i++){
  409                 s = buf;
  410                 e = buf+sizeof(buf);
  411                 ep = getep(i);
  412                 if(ep != nil){
  413                         if(waserror()){
  414                                 putep(ep);
  415                                 nexterror();
  416                         }
  417                         s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
  418                         seprintep(s, e, ep, 1);
  419                         print("%s", buf);
  420                         ep->hp->seprintep(buf, e, ep);
  421                         print("%s", buf);
  422                         poperror();
  423                         putep(ep);
  424                 }
  425         }
  426         print("usb dump hcis:\n");
  427         for(i = 0; i < Nhcis; i++)
  428                 if(hcis[i] != nil)
  429                         hcis[i]->dump(hcis[i]);
  430 }
  431 
  432 static int
  433 newusbid(Hci *)
  434 {
  435         int id;
  436 
  437         qlock(&epslck);
  438         id = ++usbidgen;
  439         if(id >= 0x7F)
  440                 print("#u: too many device addresses; reuse them more\n");
  441         qunlock(&epslck);
  442         return id;
  443 }
  444 
  445 /*
  446  * Create endpoint 0 for a new device
  447  */
  448 static Ep*
  449 newdev(Hci *hp, int ishub, int isroot)
  450 {
  451         Ep *ep;
  452         Udev *d;
  453 
  454         ep = epalloc(hp);
  455         d = ep->dev = mallocz(sizeof(Udev), 1);
  456         d->nb = newusbid(hp);
  457         d->eps[0] = ep;
  458         ep->nb = 0;
  459         ep->toggle[0] = ep->toggle[1] = 0;
  460         d->ishub = ishub;
  461         d->isroot = isroot;
  462         if(hp->highspeed != 0)
  463                 d->speed = Highspeed;
  464         else
  465                 d->speed = Fullspeed;
  466         d->state = Dconfig;             /* address not yet set */
  467         ep->dev = d;
  468         ep->ep0 = ep;                   /* no ref counted here */
  469         ep->ttype = Tctl;
  470         ep->mode = ORDWR;
  471         dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
  472         return ep;
  473 }
  474 
  475 /*
  476  * Create a new endpoint for the device
  477  * accessed via the given endpoint 0.
  478  */
  479 static Ep*
  480 newdevep(Ep *ep, int i, int tt, int mode)
  481 {
  482         Ep *nep;
  483         Udev *d;
  484 
  485         d = ep->dev;
  486         if(d->eps[i] != nil)
  487                 error("endpoint already in use");
  488         nep = epalloc(ep->hp);
  489         incref(ep);
  490         d->eps[i] = nep;
  491         nep->nb = i;
  492         nep->toggle[0] = nep->toggle[1] = 0;
  493         nep->ep0 = ep;
  494         nep->dev = ep->dev;
  495         nep->mode = mode;
  496         nep->ttype = tt;
  497         nep->debug = ep->debug;
  498         if(tt == Tintr || tt == Tiso)   /* assign defaults */
  499                 nep->pollival = 10;
  500         if(tt == Tiso){
  501                 nep->samplesz = 4;
  502                 nep->hz = 44100;
  503         }
  504         deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
  505         return ep;
  506 }
  507 
  508 static int
  509 epdataperm(int mode)
  510 {
  511 
  512         switch(mode){
  513         case OREAD:
  514                 return 0440|DMEXCL;
  515                 break;
  516         case OWRITE:
  517                 return 0220|DMEXCL;
  518                 break;
  519         default:
  520                 return 0660|DMEXCL;
  521         }
  522 }
  523 
  524 static int
  525 usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
  526 {
  527         Qid q;
  528         Dirtab *dir;
  529         int perm;
  530         char *se;
  531         Ep *ep;
  532         int nb;
  533         int mode;
  534 
  535         if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
  536         if(s == DEVDOTDOT){
  537                 if(QID(c->qid) <= Qusbdir){
  538                         mkqid(&q, Qdir, 0, QTDIR);
  539                         devdir(c, q, "#u", 0, eve, 0555, dp);
  540                 }else{
  541                         mkqid(&q, Qusbdir, 0, QTDIR);
  542                         devdir(c, q, "usb", 0, eve, 0555, dp);
  543                 }
  544                 if(0)ddprint("ok\n");
  545                 return 1;
  546         }
  547 
  548         switch(QID(c->qid)){
  549         case Qdir:                              /* list #u */
  550                 if(s == 0){
  551                         mkqid(&q, Qusbdir, 0, QTDIR);
  552                         devdir(c, q, "usb", 0, eve, 0555, dp);
  553                         if(0)ddprint("ok\n");
  554                         return 1;
  555                 }
  556                 s--;
  557                 if(s < 0 || s >= epmax)
  558                         goto Fail;
  559                 ep = getep(s);
  560                 if(ep == nil || ep->name == nil){
  561                         if(ep != nil)
  562                                 putep(ep);
  563                         if(0)ddprint("skip\n");
  564                         return 0;
  565                 }
  566                 if(waserror()){
  567                         putep(ep);
  568                         nexterror();
  569                 }
  570                 mkqid(&q, Qep0io+s*4, 0, QTFILE);
  571                 devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
  572                 putep(ep);
  573                 poperror();
  574                 if(0)ddprint("ok\n");
  575                 return 1;
  576 
  577         case Qusbdir:                           /* list #u/usb */
  578         Usbdir:
  579                 if(s < nelem(usbdir)){
  580                         dir = &usbdir[s];
  581                         mkqid(&q, dir->qid.path, 0, QTFILE);
  582                         devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
  583                         if(0)ddprint("ok\n");
  584                         return 1;
  585                 }
  586                 s -= nelem(usbdir);
  587                 if(s < 0 || s >= epmax)
  588                         goto Fail;
  589                 ep = getep(s);
  590                 if(ep == nil){
  591                         if(0)ddprint("skip\n");
  592                         return 0;
  593                 }
  594                 if(waserror()){
  595                         putep(ep);
  596                         nexterror();
  597                 }
  598                 se = up->genbuf+sizeof(up->genbuf);
  599                 seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
  600                 mkqid(&q, Qep0dir+4*s, 0, QTDIR);
  601                 putep(ep);
  602                 poperror();
  603                 devdir(c, q, up->genbuf, 0, eve, 0755, dp);
  604                 if(0)ddprint("ok\n");
  605                 return 1;
  606 
  607         case Qctl:
  608                 s = 0;
  609                 goto Usbdir;
  610 
  611         default:                                /* list #u/usb/epN.M */
  612                 nb = qid2epidx(QID(c->qid));
  613                 ep = getep(nb);
  614                 if(ep == nil)
  615                         goto Fail;
  616                 mode = ep->mode;
  617                 putep(ep);
  618                 if(isqtype(QID(c->qid), Qepdir)){
  619                 Epdir:
  620                         switch(s){
  621                         case 0:
  622                                 mkqid(&q, Qep0io+nb*4, 0, QTFILE);
  623                                 perm = epdataperm(mode);
  624                                 devdir(c, q, "data", 0, eve, perm, dp);
  625                                 break;
  626                         case 1:
  627                                 mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
  628                                 devdir(c, q, "ctl", 0, eve, 0664, dp);
  629                                 break;
  630                         default:
  631                                 goto Fail;
  632                         }
  633                 }else if(isqtype(QID(c->qid), Qepctl)){
  634                         s = 1;
  635                         goto Epdir;
  636                 }else{
  637                         s = 0;
  638                         goto Epdir;
  639                 }
  640                 if(0)ddprint("ok\n");
  641                 return 1;
  642         }
  643 Fail:
  644         if(0)ddprint("fail\n");
  645         return -1;
  646         
  647 }
  648 
  649 static Hci*
  650 hciprobe(int cardno, int ctlrno)
  651 {
  652         Hci *hp;
  653         char buf[128];
  654         char *ebuf;
  655         char name[64];
  656         char *type;
  657         static int epnb = 1;    /* guess the endpoint nb. for the controller */
  658 
  659         ddprint("hciprobe %d %d\n", cardno, ctlrno);
  660         hp = mallocz(sizeof(Hci), 1);
  661         hp->ctlrno = ctlrno;
  662         hp->tbdf = BUSUNKNOWN;
  663 
  664         if(cardno < 0){
  665                 if(isaconfig("usb", ctlrno, hp) == 0){
  666                         free(hp);
  667                         return nil;
  668                 }
  669                 for(cardno = 0; cardno < Nhcis; cardno++){
  670                         if(hcitypes[cardno].type == nil)
  671                                 break;
  672                         type = hp->type;
  673                         if(type==nil || *type==0)
  674                                 type = "uhci";
  675                         if(cistrcmp(hcitypes[cardno].type, type) == 0)
  676                                 break;
  677                 }
  678         }
  679 
  680         if(cardno >= Nhcis || hcitypes[cardno].type == nil){
  681                 free(hp);
  682                 return nil;
  683         }
  684         if(hcitypes[cardno].reset(hp) < 0){
  685                 free(hp);
  686                 return nil;
  687         }
  688 
  689         /*
  690          * IRQ2 doesn't really exist, it's used to gang the interrupt
  691          * controllers together. A device set to IRQ2 will appear on
  692          * the second interrupt controller as IRQ9.
  693          */
  694         if(hp->irq == 2)
  695                 hp->irq = 9;
  696         snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
  697         intrenable(hp->irq, hp->interrupt, hp, hp->tbdf, name);
  698         ebuf = buf + sizeof buf;
  699         seprint(buf, ebuf, "#u/usb/ep%d.0: %s: port 0x%luX irq %d",
  700                 epnb++, hcitypes[cardno].type, hp->port, hp->irq);
  701         print("%s\n", buf);
  702 
  703         return hp;
  704 }
  705 
  706 static void
  707 usbreset(void)
  708 {
  709         int cardno, ctlrno;
  710         Hci *hp;
  711 
  712         if(getconf("*nousbprobe"))
  713                 return;
  714         dprint("usbreset\n");
  715 
  716         for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
  717                 if((hp = hciprobe(-1, ctlrno)) != nil)
  718                         hcis[ctlrno] = hp;
  719         cardno = ctlrno = 0;
  720         while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
  721                 if(hcis[ctlrno] != nil)
  722                         ctlrno++;
  723                 else{
  724                         hp = hciprobe(cardno, ctlrno);
  725                         if(hp == nil)
  726                                 cardno++;
  727                         hcis[ctlrno++] = hp;
  728                 }
  729         if(hcis[Nhcis-1] != nil)
  730                 print("usbreset: bug: Nhcis too small\n");
  731 }
  732 
  733 static void
  734 usbinit(void)
  735 {
  736         Hci *hp;
  737         int ctlrno;
  738         Ep *d;
  739         char info[40];
  740 
  741         dprint("usbinit\n");
  742         for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
  743                 hp = hcis[ctlrno];
  744                 if(hp != nil){
  745                         if(hp->init != nil)
  746                                 hp->init(hp);
  747                         d = newdev(hp, 1, 1);           /* new root hub */
  748                         d->dev->state = Denabled;       /* although addr == 0 */
  749                         d->maxpkt = 64;
  750                         snprint(info, sizeof(info), "ports %d", hp->nports);
  751                         kstrdup(&d->info, info);
  752                 }
  753         }
  754 }
  755 
  756 static Chan*
  757 usbattach(char *spec)
  758 {
  759         return devattach(L'u', spec);
  760 }
  761 
  762 static Walkqid*
  763 usbwalk(Chan *c, Chan *nc, char **name, int nname)
  764 {
  765         return devwalk(c, nc, name, nname, nil, 0, usbgen);
  766 }
  767 
  768 static int
  769 usbstat(Chan *c, uchar *db, int n)
  770 {
  771         return devstat(c, db, n, nil, 0, usbgen);
  772 }
  773 
  774 /*
  775  * µs for the given transfer, for bandwidth allocation.
  776  * This is a very rough worst case for what 5.11.3
  777  * of the usb 2.0 spec says.
  778  * Also, we are using maxpkt and not actual transfer sizes.
  779  * Only when we are sure we
  780  * are not exceeding b/w might we consider adjusting it.
  781  */
  782 static ulong
  783 usbload(int speed, int maxpkt)
  784 {
  785         enum{ Hostns = 1000, Hubns = 333 };
  786         ulong l;
  787         ulong bs;
  788 
  789         l = 0;
  790         bs = 10UL * maxpkt;
  791         switch(speed){
  792         case Highspeed:
  793                 l = 55*8*2 + 2 * (3 + bs) + Hostns;
  794                 break;
  795         case Fullspeed:
  796                 l = 9107 + 84 * (4 + bs) + Hostns;
  797                 break;
  798         case Lowspeed:
  799                 l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
  800                 break;
  801         default:
  802                 print("usbload: bad speed %d\n", speed);
  803                 /* let it run */
  804         }
  805         return l / 1000UL;      /* in µs */
  806 }
  807 
  808 static Chan*
  809 usbopen(Chan *c, int omode)
  810 {
  811         int q;
  812         Ep *ep;
  813         int mode;
  814 
  815         mode = openmode(omode);
  816         q = QID(c->qid);
  817 
  818         if(q >= Qep0dir && qid2epidx(q) < 0)
  819                 error(Eio);
  820         if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
  821                 return devopen(c, omode, nil, 0, usbgen);
  822 
  823         ep = getep(qid2epidx(q));
  824         if(ep == nil)
  825                 error(Eio);
  826         deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
  827         if(waserror()){
  828                 putep(ep);
  829                 nexterror();
  830         }
  831         qlock(ep);
  832         if(ep->inuse){
  833                 qunlock(ep);
  834                 error(Einuse);
  835         }
  836         ep->inuse = 1;
  837         qunlock(ep);
  838         if(waserror()){
  839                 ep->inuse = 0;
  840                 nexterror();
  841         }
  842         if(mode != OREAD && ep->mode == OREAD)
  843                 error(Eperm);
  844         if(mode != OWRITE && ep->mode == OWRITE)
  845                 error(Eperm);
  846         if(ep->ttype == Tnone)
  847                 error(Enotconf);
  848         ep->clrhalt = 0;
  849         ep->rhrepl = -1;
  850         if(ep->load == 0)
  851                 ep->load = usbload(ep->dev->speed, ep->maxpkt);
  852         ep->hp->epopen(ep);
  853 
  854         poperror();     /* ep->inuse */
  855         poperror();     /* don't putep(): ref kept for fid using the ep. */
  856 
  857         c->mode = mode;
  858         c->flag |= COPEN;
  859         c->offset = 0;
  860         c->aux = nil;   /* paranoia */
  861         return c;
  862 }
  863 
  864 static void
  865 epclose(Ep *ep)
  866 {
  867         qlock(ep);
  868         if(waserror()){
  869                 qunlock(ep);
  870                 nexterror();
  871         }
  872         if(ep->inuse){
  873                 ep->hp->epclose(ep);
  874                 ep->inuse = 0;
  875         }
  876         qunlock(ep);
  877         poperror();
  878 }
  879 
  880 static void
  881 usbclose(Chan *c)
  882 {
  883         int q;
  884         Ep *ep;
  885 
  886         q = QID(c->qid);
  887         if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
  888                 return;
  889 
  890         ep = getep(qid2epidx(q));
  891         if(ep == nil)
  892                 return;
  893         deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
  894         if(waserror()){
  895                 putep(ep);
  896                 nexterror();
  897         }
  898         if(c->flag & COPEN){
  899                 free(c->aux);
  900                 c->aux = nil;
  901                 epclose(ep);
  902                 putep(ep);      /* release ref kept since usbopen */
  903                 c->flag &= ~COPEN;
  904         }
  905         poperror();
  906         putep(ep);
  907 }
  908 
  909 static long
  910 ctlread(Chan *c, void *a, long n, vlong offset)
  911 {
  912         int q;
  913         char *s;
  914         char *us;
  915         char *se;
  916         Ep *ep;
  917         int i;
  918 
  919         q = QID(c->qid);
  920         us = s = smalloc(READSTR);
  921         se = s + READSTR;
  922         if(waserror()){
  923                 free(us);
  924                 nexterror();
  925         }
  926         if(q == Qctl)
  927                 for(i = 0; i < epmax; i++){
  928                         ep = getep(i);
  929                         if(ep != nil){
  930                                 if(waserror()){
  931                                         putep(ep);
  932                                         nexterror();
  933                                 }
  934                                 s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
  935                                 s = seprintep(s, se, ep, 0);
  936                                 poperror();
  937                         }
  938                         putep(ep);
  939                 }
  940         else{
  941                 ep = getep(qid2epidx(q));
  942                 if(ep == nil)
  943                         error(Eio);
  944                 if(waserror()){
  945                         putep(ep);
  946                         nexterror();
  947                 }
  948                 if(c->aux != nil){
  949                         /* After a new endpoint request we read
  950                          * the new endpoint name back.
  951                          */
  952                         strecpy(s, se, c->aux);
  953                         free(c->aux);
  954                         c->aux = nil;
  955                 }else
  956                         seprintep(s, se, ep, 0);
  957                 poperror();
  958                 putep(ep);
  959         }
  960         n = readstr(offset, a, n, us);
  961         poperror();
  962         free(us);
  963         return n;
  964 }
  965 
  966 /*
  967  * Fake root hub emulation.
  968  */
  969 static long
  970 rhubread(Ep *ep, void *a, long n)
  971 {
  972         char *b;
  973 
  974         if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
  975                 return -1;
  976         if(ep->rhrepl < 0)
  977                 return -1;
  978 
  979         b = a;
  980         memset(b, 0, n);
  981         PUT2(b, ep->rhrepl);
  982         ep->rhrepl = -1;
  983         return n;
  984 }
  985 
  986 static long
  987 rhubwrite(Ep *ep, void *a, long n)
  988 {
  989         uchar *s;
  990         int cmd;
  991         int feature;
  992         int port;
  993         Hci *hp;
  994 
  995         if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
  996                 return -1;
  997         if(n != Rsetuplen)
  998                 error("root hub is a toy hub");
  999         ep->rhrepl = -1;
 1000         s = a;
 1001         if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
 1002                 error("root hub is a toy hub");
 1003         hp = ep->hp;
 1004         cmd = s[Rreq];
 1005         feature = GET2(s+Rvalue);
 1006         port = GET2(s+Rindex);
 1007         if(port < 1 || port > hp->nports)
 1008                 error("bad hub port number");
 1009         switch(feature){
 1010         case Rportenable:
 1011                 ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
 1012                 break;
 1013         case Rportreset:
 1014                 ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
 1015                 break;
 1016         case Rgetstatus:
 1017                 ep->rhrepl = hp->portstatus(hp, port);
 1018                 break;
 1019         default:
 1020                 ep->rhrepl = 0;
 1021         }
 1022         return n;
 1023 }
 1024 
 1025 static long
 1026 usbread(Chan *c, void *a, long n, vlong offset)
 1027 {
 1028         int q;
 1029         Ep *ep;
 1030         int nr;
 1031 
 1032         q = QID(c->qid);
 1033 
 1034         if(c->qid.type == QTDIR)
 1035                 return devdirread(c, a, n, nil, 0, usbgen);
 1036 
 1037         if(q == Qctl || isqtype(q, Qepctl))
 1038                 return ctlread(c, a, n, offset);
 1039 
 1040         ep = getep(qid2epidx(q));
 1041         if(ep == nil)
 1042                 error(Eio);
 1043         if(waserror()){
 1044                 putep(ep);
 1045                 nexterror();
 1046         }
 1047         if(ep->dev->state == Ddetach)
 1048                 error(Edetach);
 1049         if(ep->mode == OWRITE || ep->inuse == 0)
 1050                 error(Ebadusefd);
 1051         switch(ep->ttype){
 1052         case Tnone:
 1053                 error("endpoint not configured");
 1054         case Tctl:
 1055                 nr = rhubread(ep, a, n);
 1056                 if(nr >= 0){
 1057                         n = nr;
 1058                         break;
 1059                 }
 1060                 /* else fall */
 1061         default:
 1062                 ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
 1063                 n = ep->hp->epread(ep, a, n);
 1064                 break;
 1065         }
 1066         poperror();
 1067         putep(ep);
 1068         return n;
 1069 }
 1070 
 1071 static long
 1072 pow2(int n)
 1073 {
 1074         long v;
 1075 
 1076         for(v = 1; n > 0; n--)
 1077                 v *= 2;
 1078         return v;
 1079 }
 1080 
 1081 static void
 1082 setmaxpkt(Ep *ep, char* s)
 1083 {
 1084         long spp;       /* samples per packet */
 1085 
 1086         if(ep->dev->speed == Highspeed)
 1087                 spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
 1088         else
 1089                 spp = (ep->hz * ep->pollival + 999) / 1000;
 1090         ep->maxpkt = spp * ep->samplesz;
 1091         deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
 1092                 " ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
 1093                 ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
 1094                 spp, ep->maxpkt);
 1095         if(ep->maxpkt > 1024){
 1096                 print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
 1097                 ep->maxpkt = 1024;
 1098         }
 1099 }
 1100 
 1101 /*
 1102  * Many endpoint ctls. simply update the portable representation
 1103  * of the endpoint. The actual controller driver will look
 1104  * at them to setup the endpoints as dictated.
 1105  */
 1106 static long
 1107 epctl(Ep *ep, Chan *c, void *a, long n)
 1108 {
 1109         static char *Info = "info ";
 1110         Ep *nep;
 1111         Udev *d;
 1112         int l;
 1113         char *s;
 1114         char *b;
 1115         int tt;
 1116         int i;
 1117         int mode;
 1118         int nb;
 1119         Cmdtab *ct;
 1120         Cmdbuf *cb;
 1121 
 1122         d = ep->dev;
 1123 
 1124         cb = parsecmd(a, n);
 1125         if(waserror()){
 1126                 free(cb);
 1127                 nexterror();
 1128         }
 1129         ct = lookupcmd(cb, epctls, nelem(epctls));
 1130         if(ct == nil)
 1131                 error(Ebadctl);
 1132         i = ct->index;
 1133         if(i == CMnew || i == CMspeed || i == CMhub)
 1134                 if(ep != ep->ep0)
 1135                         error("allowed only on a setup endpoint");
 1136         if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
 1137                 if(ep != ep->ep0 && ep->inuse != 0)
 1138                         error("must configure before using");
 1139         switch(i){
 1140         case CMnew:
 1141                 deprint("usb epctl %s\n", cb->f[0]);
 1142                 nb = strtol(cb->f[1], nil, 0);
 1143                 if(nb < 0 || nb >= Ndeveps)
 1144                         error("bad endpoint number");
 1145                 tt = name2ttype(cb->f[2]);
 1146                 if(tt == Tnone)
 1147                         error("unknown endpoint type");
 1148                 mode = name2mode(cb->f[3]);
 1149                 if(mode < 0)
 1150                         error("unknown i/o mode");
 1151                 newdevep(ep, nb, tt, mode);
 1152                 break;
 1153         case CMnewdev:
 1154                 deprint("usb epctl %s\n", cb->f[0]);
 1155                 if(ep != ep->ep0 || d->ishub == 0)
 1156                         error("not a hub setup endpoint");
 1157                 l = name2speed(cb->f[1]);
 1158                 if(l == Nospeed)
 1159                         error("speed must be full|low|high");
 1160                 nep = newdev(ep->hp, 0, 0);
 1161                 nep->dev->speed = l;
 1162                 if(nep->dev->speed  != Lowspeed)
 1163                         nep->maxpkt = 64;       /* assume full speed */
 1164                 nep->dev->hub = d->nb;
 1165                 nep->dev->port = atoi(cb->f[2]);
 1166                 /* next read request will read
 1167                  * the name for the new endpoint
 1168                  */
 1169                 l = sizeof(up->genbuf);
 1170                 snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
 1171                 kstrdup(&c->aux, up->genbuf);
 1172                 break;
 1173         case CMhub:
 1174                 deprint("usb epctl %s\n", cb->f[0]);
 1175                 d->ishub = 1;
 1176                 break;
 1177         case CMspeed:
 1178                 l = name2speed(cb->f[1]);
 1179                 deprint("usb epctl %s %d\n", cb->f[0], l);
 1180                 if(l == Nospeed)
 1181                         error("speed must be full|low|high");
 1182                 qlock(ep->ep0);
 1183                 d->speed = l;
 1184                 qunlock(ep->ep0);
 1185                 break;
 1186         case CMmaxpkt:
 1187                 l = strtoul(cb->f[1], nil, 0);
 1188                 deprint("usb epctl %s %d\n", cb->f[0], l);
 1189                 if(l < 1 || l > 1024)
 1190                         error("maxpkt not in [1:1024]");
 1191                 qlock(ep);
 1192                 ep->maxpkt = l;
 1193                 qunlock(ep);
 1194                 break;
 1195         case CMntds:
 1196                 l = strtoul(cb->f[1], nil, 0);
 1197                 deprint("usb epctl %s %d\n", cb->f[0], l);
 1198                 if(l < 1 || l > 3)
 1199                         error("ntds not in [1:3]");
 1200                 qlock(ep);
 1201                 ep->ntds = l;
 1202                 qunlock(ep);
 1203                 break;
 1204         case CMpollival:
 1205                 if(ep->ttype != Tintr && ep->ttype != Tiso)
 1206                         error("not an intr or iso endpoint");
 1207                 l = strtoul(cb->f[1], nil, 0);
 1208                 deprint("usb epctl %s %d\n", cb->f[0], l);
 1209                 if(ep->ttype == Tiso ||
 1210                    (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
 1211                         if(l < 1 || l > 16)
 1212                                 error("pollival power not in [1:16]");
 1213                         l = pow2(l-1);
 1214                 }else
 1215                         if(l < 1 || l > 255)
 1216                                 error("pollival not in [1:255]");
 1217                 qlock(ep);
 1218                 ep->pollival = l;
 1219                 if(ep->ttype == Tiso)
 1220                         setmaxpkt(ep, "pollival");
 1221                 qunlock(ep);
 1222                 break;
 1223         case CMsamplesz:
 1224                 if(ep->ttype != Tiso)
 1225                         error("not an iso endpoint");
 1226                 l = strtoul(cb->f[1], nil, 0);
 1227                 deprint("usb epctl %s %d\n", cb->f[0], l);
 1228                 if(l <= 0 || l > 8)
 1229                         error("samplesz not in [1:8]");
 1230                 qlock(ep);
 1231                 ep->samplesz = l;
 1232                 setmaxpkt(ep, "samplesz");
 1233                 qunlock(ep);
 1234                 break;
 1235         case CMhz:
 1236                 if(ep->ttype != Tiso)
 1237                         error("not an iso endpoint");
 1238                 l = strtoul(cb->f[1], nil, 0);
 1239                 deprint("usb epctl %s %d\n", cb->f[0], l);
 1240                 if(l <= 0 || l > 100000)
 1241                         error("hz not in [1:100000]");
 1242                 qlock(ep);
 1243                 ep->hz = l;
 1244                 setmaxpkt(ep, "hz");
 1245                 qunlock(ep);
 1246                 break;
 1247         case CMclrhalt:
 1248                 qlock(ep);
 1249                 deprint("usb epctl %s\n", cb->f[0]);
 1250                 ep->clrhalt = 1;
 1251                 qunlock(ep);
 1252                 break;
 1253         case CMinfo:
 1254                 deprint("usb epctl %s\n", cb->f[0]);
 1255                 l = strlen(Info);
 1256                 s = a;
 1257                 if(n < l+2 || strncmp(Info, s, l) != 0)
 1258                         error(Ebadctl);
 1259                 if(n > 1024)
 1260                         n = 1024;
 1261                 b = smalloc(n);
 1262                 memmove(b, s+l, n-l);
 1263                 b[n-l] = 0;
 1264                 if(b[n-l-1] == '\n')
 1265                         b[n-l-1] = 0;
 1266                 qlock(ep);
 1267                 free(ep->info);
 1268                 ep->info = b;
 1269                 qunlock(ep);
 1270                 break;
 1271         case CMaddress:
 1272                 deprint("usb epctl %s\n", cb->f[0]);
 1273                 ep->dev->state = Denabled;
 1274                 break;
 1275         case CMdetach:
 1276                 if(ep->dev->isroot != 0)
 1277                         error("can't detach a root hub");
 1278                 deprint("usb epctl %s ep%d.%d\n",
 1279                         cb->f[0], ep->dev->nb, ep->nb);
 1280                 ep->dev->state = Ddetach;
 1281                 /* Release file system ref. for its endpoints */
 1282                 for(i = 0; i < nelem(ep->dev->eps); i++)
 1283                         putep(ep->dev->eps[i]);
 1284                 break;
 1285         case CMdebugep:
 1286                 if(strcmp(cb->f[1], "on") == 0)
 1287                         ep->debug = 1;
 1288                 else if(strcmp(cb->f[1], "off") == 0)
 1289                         ep->debug = 0;
 1290                 else
 1291                         ep->debug = strtoul(cb->f[1], nil, 0);
 1292                 print("usb: ep%d.%d debug %d\n",
 1293                         ep->dev->nb, ep->nb, ep->debug);
 1294                 break;
 1295         case CMname:
 1296                 deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
 1297                 validname(cb->f[1], 0);
 1298                 kstrdup(&ep->name, cb->f[1]);
 1299                 break;
 1300         default:
 1301                 panic("usb: unknown epctl %d", ct->index);
 1302         }
 1303         free(cb);
 1304         poperror();
 1305         return n;
 1306 }
 1307 
 1308 static long
 1309 usbctl(void *a, long n)
 1310 {
 1311         Cmdtab *ct;
 1312         Cmdbuf *cb;
 1313         Ep *ep;
 1314         int i;
 1315 
 1316         cb = parsecmd(a, n);
 1317         if(waserror()){
 1318                 free(cb);
 1319                 nexterror();
 1320         }
 1321         ct = lookupcmd(cb, usbctls, nelem(usbctls));
 1322         dprint("usb ctl %s\n", cb->f[0]);
 1323         switch(ct->index){
 1324         case CMdebug:
 1325                 if(strcmp(cb->f[1], "on") == 0)
 1326                         debug = 1;
 1327                 else if(strcmp(cb->f[1], "off") == 0)
 1328                         debug = 0;
 1329                 else
 1330                         debug = strtol(cb->f[1], nil, 0);
 1331                 print("usb: debug %d\n", debug);
 1332                 for(i = 0; i < epmax; i++)
 1333                         if((ep = getep(i)) != nil){
 1334                                 ep->hp->debug(ep->hp, debug);
 1335                                 putep(ep);
 1336                         }
 1337                 break;
 1338         case CMreset:
 1339                 print("devusb: CMreset not implemented\n");
 1340                 error("not implemented");
 1341 #ifdef TODO
 1342                 XXX: I'm not sure this is a good idea.
 1343                 Usbd should not be restarted at all.
 1344                 for(all eps)
 1345                         closeep(ep);
 1346                 do a global reset once more
 1347                 recreate root hub devices in place.
 1348 #endif
 1349                 break;
 1350         case CMdump:
 1351                 dumpeps();
 1352                 break;
 1353         }
 1354         free(cb);
 1355         poperror();
 1356         return n;
 1357 }
 1358 
 1359 static long
 1360 ctlwrite(Chan *c, void *a, long n)
 1361 {
 1362         int q;
 1363         Ep *ep;
 1364 
 1365         q = QID(c->qid);
 1366         if(q == Qctl)
 1367                 return usbctl(a, n);
 1368 
 1369         ep = getep(qid2epidx(q));
 1370         if(ep == nil)
 1371                 error(Eio);
 1372         if(waserror()){
 1373                 putep(ep);
 1374                 nexterror();
 1375         }
 1376         if(ep->dev->state == Ddetach)
 1377                 error(Edetach);
 1378         if(isqtype(q, Qepctl) && c->aux != nil){
 1379                 /* Be sure we don't keep a cloned ep name */
 1380                 free(c->aux);
 1381                 c->aux = nil;
 1382                 error("read, not write, expected");
 1383         }
 1384         n = epctl(ep, c, a, n);
 1385         putep(ep);
 1386         poperror();
 1387         return n;
 1388 }
 1389 
 1390 static long
 1391 usbwrite(Chan *c, void *a, long n, vlong off)
 1392 {
 1393         int q;
 1394         Ep *ep;
 1395         int nr;
 1396 
 1397         if(c->qid.type == QTDIR)
 1398                 error(Eisdir);
 1399 
 1400         q = QID(c->qid);
 1401 
 1402         if(q == Qctl || isqtype(q, Qepctl))
 1403                 return ctlwrite(c, a, n);
 1404 
 1405         ep = getep(qid2epidx(q));
 1406         if(ep == nil)
 1407                 error(Eio);
 1408         if(waserror()){
 1409                 putep(ep);
 1410                 nexterror();
 1411         }
 1412         if(ep->dev->state == Ddetach)
 1413                 error(Edetach);
 1414         if(ep->mode == OREAD || ep->inuse == 0)
 1415                 error(Ebadusefd);
 1416 
 1417         switch(ep->ttype){
 1418         case Tnone:
 1419                 error("endpoint not configured");
 1420         case Tctl:
 1421                 nr = rhubwrite(ep, a, n);
 1422                 if(nr >= 0){
 1423                         n = nr;
 1424                         break;
 1425                 }
 1426                 /* else fall */
 1427         default:
 1428                 ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
 1429                 ep->hp->epwrite(ep, a, n);
 1430         }
 1431         putep(ep);
 1432         poperror();
 1433         return n;
 1434 }
 1435 
 1436 Dev usbdevtab = {
 1437         L'u',
 1438         "usb",
 1439 
 1440         usbreset,
 1441         usbinit,
 1442         devshutdown,
 1443         usbattach,
 1444         usbwalk,
 1445         usbstat,
 1446         usbopen,
 1447         devcreate,
 1448         usbclose,
 1449         usbread,
 1450         devbread,
 1451         usbwrite,
 1452         devbwrite,
 1453         devremove,
 1454         devwstat,
 1455 };

Cache object: c0ad0f868c7537ab49ca6fb2ab6cfc0e


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.