1 /*
2 * This part takes care of locking except for initialization and
3 * other threads created by the hw dep. drivers.
4 */
5
6 #include <u.h>
7 #include <libc.h>
8 #include <ctype.h>
9 #include <thread.h>
10 #include "usb.h"
11 #include "usbfs.h"
12 #include "serial.h"
13 #include "prolific.h"
14 #include "ucons.h"
15 #include "ftdi.h"
16 #include "silabs.h"
17
18 int serialdebug;
19
20 enum {
21 /* Qids. Maintain order (relative to dirtabs structs) */
22 Qroot = 0,
23 Qctl,
24 Qdata,
25 Qmax,
26 };
27
28 typedef struct Dirtab Dirtab;
29 struct Dirtab {
30 char *name;
31 int mode;
32 };
33
34 static Dirtab dirtab[] = {
35 [Qroot] "/", DMDIR|0555,
36 [Qdata] "%s", 0660,
37 [Qctl] "%sctl", 0664,
38 };
39
40 static int sdebug;
41
42 static void
serialfatal(Serial * ser)43 serialfatal(Serial *ser)
44 {
45 Serialport *p;
46 int i;
47
48 dsprint(2, "serial: fatal error, detaching\n");
49 devctl(ser->dev, "detach");
50
51 for(i = 0; i < ser->nifcs; i++){
52 p = &ser->p[i];
53 usbfsdel(&p->fs);
54 if(p->w4data != nil)
55 chanclose(p->w4data);
56 if(p->gotdata != nil)
57 chanclose(p->gotdata);
58 if(p->readc)
59 chanclose(p->readc);
60 }
61 }
62
63 /* I sleep with the lock... only way to drain in general */
64 static void
serialdrain(Serialport * p)65 serialdrain(Serialport *p)
66 {
67 Serial *ser;
68 uint baud, pipesize;
69
70 ser = p->s;
71 baud = p->baud;
72
73 if(p->baud == ~0)
74 return;
75 if(ser->maxwtrans < 256)
76 pipesize = 256;
77 else
78 pipesize = ser->maxwtrans;
79 /* wait for the at least 256-byte pipe to clear */
80 sleep(10 + pipesize/((1 + baud)*1000));
81 if(ser->clearpipes != nil)
82 ser->clearpipes(p);
83 }
84
85 int
serialreset(Serial * ser)86 serialreset(Serial *ser)
87 {
88 Serialport *p;
89 int i, res;
90
91 res = 0;
92 /* cmd for reset */
93 for(i = 0; i < ser->nifcs; i++){
94 p = &ser->p[i];
95 serialdrain(p);
96 }
97 if(ser->reset != nil)
98 res = ser->reset(ser, nil);
99 return res;
100 }
101
102 /* call this if something goes wrong, must be qlocked */
103 int
serialrecover(Serial * ser,Serialport * p,Dev * ep,char * err)104 serialrecover(Serial *ser, Serialport *p, Dev *ep, char *err)
105 {
106 if(p != nil)
107 dprint(2, "serial[%d], %s: %s, level %d\n", p->interfc,
108 p->name, err, ser->recover);
109 else
110 dprint(2, "serial[%s], global error, level %d\n",
111 ser->p[0].name, ser->recover);
112 ser->recover++;
113 if(strstr(err, "detached") != nil)
114 return -1;
115 if(ser->recover < 3){
116 if(p != nil){
117 if(ep != nil){
118 if(ep == p->epintr)
119 unstall(ser->dev, p->epintr, Ein);
120 if(ep == p->epin)
121 unstall(ser->dev, p->epin, Ein);
122 if(ep == p->epout)
123 unstall(ser->dev, p->epout, Eout);
124 return 0;
125 }
126
127 if(p->epintr != nil)
128 unstall(ser->dev, p->epintr, Ein);
129 if(p->epin != nil)
130 unstall(ser->dev, p->epin, Ein);
131 if(p->epout != nil)
132 unstall(ser->dev, p->epout, Eout);
133 }
134 return 0;
135 }
136 if(ser->recover > 4 && ser->recover < 8)
137 serialfatal(ser);
138 if(ser->recover > 8){
139 ser->reset(ser, p);
140 return 0;
141 }
142 if(serialreset(ser) < 0)
143 return -1;
144 return 0;
145 }
146
147 static int
serialctl(Serialport * p,char * cmd)148 serialctl(Serialport *p, char *cmd)
149 {
150 Serial *ser;
151 int c, i, n, nf, nop, nw, par, drain, set, lines;
152 char *f[16];
153 uchar x;
154
155 ser = p->s;
156 drain = set = lines = 0;
157 nf = tokenize(cmd, f, nelem(f));
158 for(i = 0; i < nf; i++){
159 if(strncmp(f[i], "break", 5) == 0){
160 if(ser->setbreak != nil)
161 ser->setbreak(p, 1);
162 continue;
163 }
164
165 nop = 0;
166 n = atoi(f[i]+1);
167 c = *f[i];
168 if (isascii(c) && isupper(c))
169 c = tolower(c);
170 switch(c){
171 case 'b':
172 drain++;
173 p->baud = n;
174 set++;
175 break;
176 case 'c':
177 p->dcd = n;
178 // lines++;
179 ++nop;
180 break;
181 case 'd':
182 p->dtr = n;
183 lines++;
184 break;
185 case 'e':
186 p->dsr = n;
187 // lines++;
188 ++nop;
189 break;
190 case 'f': /* flush the pipes */
191 drain++;
192 break;
193 case 'h': /* hangup?? */
194 p->rts = p->dtr = 0;
195 lines++;
196 fprint(2, "serial: %c, unsure ctl\n", c);
197 break;
198 case 'i':
199 ++nop;
200 break;
201 case 'k':
202 drain++;
203 ser->setbreak(p, 1);
204 sleep(n);
205 ser->setbreak(p, 0);
206 break;
207 case 'l':
208 drain++;
209 p->bits = n;
210 set++;
211 break;
212 case 'm':
213 drain++;
214 if(ser->modemctl != nil)
215 ser->modemctl(p, n);
216 if(n == 0)
217 p->cts = 0;
218 break;
219 case 'n':
220 p->blocked = n;
221 ++nop;
222 break;
223 case 'p': /* extended... */
224 if(strlen(f[i]) != 2)
225 return -1;
226 drain++;
227 par = f[i][1];
228 if(par == 'n')
229 p->parity = 0;
230 else if(par == 'o')
231 p->parity = 1;
232 else if(par == 'e')
233 p->parity = 2;
234 else if(par == 'm') /* mark parity */
235 p->parity = 3;
236 else if(par == 's') /* space parity */
237 p->parity = 4;
238 else
239 return -1;
240 set++;
241 break;
242 case 'q':
243 // drain++;
244 p->limit = n;
245 ++nop;
246 break;
247 case 'r':
248 drain++;
249 p->rts = n;
250 lines++;
251 break;
252 case 's':
253 drain++;
254 p->stop = n;
255 set++;
256 break;
257 case 'w':
258 /* ?? how do I put this */
259 p->timer = n * 100000LL;
260 ++nop;
261 break;
262 case 'x':
263 if(n == 0)
264 x = CTLS;
265 else
266 x = CTLQ;
267 if(ser->wait4write != nil)
268 nw = ser->wait4write(p, &x, 1);
269 else
270 nw = write(p->epout->dfd, &x, 1);
271 if(nw != 1){
272 serialrecover(ser, p, p->epout, "");
273 return -1;
274 }
275 break;
276 }
277 /*
278 * don't print. the condition is harmless and the print
279 * splatters all over the display.
280 */
281 USED(nop);
282 if (0 && nop)
283 fprint(2, "serial: %c, unsupported nop ctl\n", c);
284 }
285 if(drain)
286 serialdrain(p);
287 if(lines && !set){
288 if(ser->sendlines != nil && ser->sendlines(p) < 0)
289 return -1;
290 } else if(set){
291 if(ser->setparam != nil && ser->setparam(p) < 0)
292 return -1;
293 }
294 ser->recover = 0;
295 return 0;
296 }
297
298 char *pformat = "noems";
299
300 char *
serdumpst(Serialport * p,char * buf,int bufsz)301 serdumpst(Serialport *p, char *buf, int bufsz)
302 {
303 char *e, *s;
304 Serial *ser;
305
306 ser = p->s;
307
308 e = buf + bufsz;
309 s = seprint(buf, e, "b%d ", p->baud);
310 s = seprint(s, e, "c%d ", p->dcd); /* unimplemented */
311 s = seprint(s, e, "d%d ", p->dtr);
312 s = seprint(s, e, "e%d ", p->dsr); /* unimplemented */
313 s = seprint(s, e, "l%d ", p->bits);
314 s = seprint(s, e, "m%d ", p->mctl);
315 if(p->parity >= 0 || p->parity < strlen(pformat))
316 s = seprint(s, e, "p%c ", pformat[p->parity]);
317 else
318 s = seprint(s, e, "p%c ", '?');
319 s = seprint(s, e, "r%d ", p->rts);
320 s = seprint(s, e, "s%d ", p->stop);
321 s = seprint(s, e, "i%d ", p->fifo);
322 s = seprint(s, e, "\ndev(%d) ", 0);
323 s = seprint(s, e, "type(%d) ", ser->type);
324 s = seprint(s, e, "framing(%d) ", p->nframeerr);
325 s = seprint(s, e, "overruns(%d) ", p->novererr);
326 s = seprint(s, e, "berr(%d) ", p->nbreakerr);
327 s = seprint(s, e, " serr(%d)\n", p->nparityerr);
328 return s;
329 }
330
331 static int
serinit(Serialport * p)332 serinit(Serialport *p)
333 {
334 int res;
335 res = 0;
336 Serial *ser;
337
338 ser = p->s;
339
340 if(ser->init != nil)
341 res = ser->init(p);
342 if(ser->getparam != nil)
343 ser->getparam(p);
344 p->nframeerr = p->nparityerr = p->nbreakerr = p->novererr = 0;
345
346 return res;
347 }
348
349 static int
dwalk(Usbfs * fs,Fid * fid,char * name)350 dwalk(Usbfs *fs, Fid *fid, char *name)
351 {
352 int i;
353 char *dname;
354 Qid qid;
355 Serialport *p;
356
357 qid = fid->qid;
358 if((qid.type & QTDIR) == 0){
359 werrstr("walk in non-directory");
360 return -1;
361 }
362
363 if(strcmp(name, "..") == 0){
364 /* must be /eiaU%d; i.e. our root dir. */
365 fid->qid.path = Qroot | fs->qid;
366 fid->qid.vers = 0;
367 fid->qid.type = QTDIR;
368 return 0;
369 }
370
371 p = fs->aux;
372 for(i = 1; i < nelem(dirtab); i++){
373 dname = smprint(dirtab[i].name, p->name);
374 if(strcmp(name, dname) == 0){
375 qid.path = i | fs->qid;
376 qid.vers = 0;
377 qid.type = dirtab[i].mode >> 24;
378 fid->qid = qid;
379 free(dname);
380 return 0;
381 } else
382 free(dname);
383 }
384 werrstr(Enotfound);
385 return -1;
386 }
387
388 static void
dostat(Usbfs * fs,int path,Dir * d)389 dostat(Usbfs *fs, int path, Dir *d)
390 {
391 Dirtab *t;
392 Serialport *p;
393
394 t = &dirtab[path];
395 d->qid.path = path;
396 d->qid.type = t->mode >> 24;
397 d->mode = t->mode;
398 p = fs->aux;
399
400 if(strcmp(t->name, "/") == 0)
401 d->name = t->name;
402 else
403 snprint(d->name, Namesz, t->name, p->fs.name);
404 d->length = 0;
405 }
406
407 static int
dstat(Usbfs * fs,Qid qid,Dir * d)408 dstat(Usbfs *fs, Qid qid, Dir *d)
409 {
410 int path;
411
412 path = qid.path & ~fs->qid;
413 dostat(fs, path, d);
414 d->qid.path |= fs->qid;
415 return 0;
416 }
417
418 static int
dopen(Usbfs * fs,Fid * fid,int)419 dopen(Usbfs *fs, Fid *fid, int)
420 {
421 ulong path;
422 Serialport *p;
423
424 path = fid->qid.path & ~fs->qid;
425 p = fs->aux;
426 switch(path){ /* BUG: unneeded? */
427 case Qdata:
428 dsprint(2, "serial, opened data\n");
429 break;
430 case Qctl:
431 dsprint(2, "serial, opened ctl\n");
432 if(p->isjtag)
433 return 0;
434 serialctl(p, "l8 i1"); /* default line parameters */
435 break;
436 }
437 return 0;
438 }
439
440
441 static void
filldir(Usbfs * fs,Dir * d,Dirtab * tab,int i,void * v)442 filldir(Usbfs *fs, Dir *d, Dirtab *tab, int i, void *v)
443 {
444 Serialport *p;
445
446 p = v;
447 d->qid.path = i | fs->qid;
448 d->mode = tab->mode;
449 if((d->mode & DMDIR) != 0)
450 d->qid.type = QTDIR;
451 else
452 d->qid.type = QTFILE;
453 sprint(d->name, tab->name, p->name); /* hope it fits */
454 }
455
456 static int
dirgen(Usbfs * fs,Qid,int i,Dir * d,void * p)457 dirgen(Usbfs *fs, Qid, int i, Dir *d, void *p)
458 {
459 i++; /* skip root */
460 if(i >= nelem(dirtab))
461 return -1;
462 filldir(fs, d, &dirtab[i], i, p);
463 return 0;
464 }
465
466 enum {
467 Serbufsize = 256,
468 };
469
470 static long
dread(Usbfs * fs,Fid * fid,void * data,long count,vlong offset)471 dread(Usbfs *fs, Fid *fid, void *data, long count, vlong offset)
472 {
473 int dfd;
474 long rcount;
475 ulong path;
476 char *e, *buf, *err; /* change */
477 Qid q;
478 Serialport *p;
479 Serial *ser;
480 static int errrun, good;
481
482 q = fid->qid;
483 path = fid->qid.path & ~fs->qid;
484 p = fs->aux;
485 ser = p->s;
486
487 buf = emallocz(Serbufsize, 1);
488 err = emallocz(Serbufsize, 1);
489 qlock(ser);
490 switch(path){
491 case Qroot:
492 count = usbdirread(fs, q, data, count, offset, dirgen, p);
493 break;
494 case Qdata:
495 if(count > ser->maxread)
496 count = ser->maxread;
497
498 dsprint(2, "serial: reading from data\n");
499 do {
500 err[0] = 0;
501 dfd = p->epin->dfd;
502 if(usbdebug >= 3)
503 dsprint(2, "serial: reading: %ld\n", count);
504
505 assert(count > 0);
506 if(ser->wait4data != nil)
507 rcount = ser->wait4data(p, data, count);
508 else{
509 qunlock(ser);
510 rcount = read(dfd, data, count);
511 qlock(ser);
512 }
513 /*
514 * if we encounter a long run of continuous read
515 * errors, do something drastic so that our caller
516 * doesn't just spin its wheels forever.
517 */
518 if(rcount < 0) {
519 snprint(err, Serbufsize, "%r");
520 ++errrun;
521 sleep(20);
522 if (good > 0 && errrun > 10000) {
523 /* the line has been dropped; give up */
524 qunlock(ser);
525 fprint(2, "%s: line %s is gone: %r\n",
526 argv0, p->fs.name);
527 threadexitsall("serial line gone");
528 }
529 } else {
530 errrun = 0;
531 good++;
532 }
533 if(usbdebug >= 3)
534 dsprint(2, "serial: read: %s %ld\n", err, rcount);
535 } while(rcount < 0 && strstr(err, "timed out") != nil);
536
537 dsprint(2, "serial: read from bulk %ld, %10.10s\n", rcount, err);
538 if(rcount < 0){
539 dsprint(2, "serial: need to recover, data read %ld %r\n",
540 count);
541 serialrecover(ser, p, p->epin, err);
542 }
543 dsprint(2, "serial: read from bulk %ld\n", rcount);
544 count = rcount;
545 break;
546 case Qctl:
547 if(offset != 0 || p->isjtag)
548 count = 0;
549 else {
550 e = serdumpst(p, buf, Serbufsize);
551 count = usbreadbuf(data, count, 0, buf, e - buf);
552 }
553 break;
554 }
555 if(count >= 0)
556 ser->recover = 0;
557 qunlock(ser);
558 free(err);
559 free(buf);
560 return count;
561 }
562
563 static long
altwrite(Serialport * p,uchar * buf,long count)564 altwrite(Serialport *p, uchar *buf, long count)
565 {
566 int nw, dfd;
567 char err[128];
568 Serial *ser;
569
570 ser = p->s;
571 do{
572 dsprint(2, "serial: write to bulk %ld\n", count);
573
574 if(ser->wait4write != nil)
575 /* unlocked inside later */
576 nw = ser->wait4write(p, buf, count);
577 else{
578 dfd = p->epout->dfd;
579 qunlock(ser);
580 nw = write(dfd, buf, count);
581 qlock(ser);
582 }
583 rerrstr(err, sizeof err);
584 dsprint(2, "serial: written %s %d\n", err, nw);
585 } while(nw < 0 && strstr(err, "timed out") != nil);
586
587 if(nw != count){
588 dsprint(2, "serial: need to recover, status in write %d %r\n",
589 nw);
590 snprint(err, sizeof err, "%r");
591 serialrecover(p->s, p, p->epout, err);
592 }
593 return nw;
594 }
595
596 static long
dwrite(Usbfs * fs,Fid * fid,void * buf,long count,vlong)597 dwrite(Usbfs *fs, Fid *fid, void *buf, long count, vlong)
598 {
599 ulong path;
600 char *cmd;
601 Serialport *p;
602 Serial *ser;
603
604 p = fs->aux;
605 ser = p->s;
606 path = fid->qid.path & ~fs->qid;
607
608 qlock(ser);
609 switch(path){
610 case Qdata:
611 count = altwrite(p, (uchar *)buf, count);
612 break;
613 case Qctl:
614 if(p->isjtag)
615 break;
616 cmd = emallocz(count+1, 1);
617 memmove(cmd, buf, count);
618 cmd[count] = 0;
619 if(serialctl(p, cmd) < 0){
620 qunlock(ser);
621 werrstr(Ebadctl);
622 free(cmd);
623 return -1;
624 }
625 free(cmd);
626 break;
627 default:
628 qunlock(ser);
629 werrstr(Eperm);
630 return -1;
631 }
632 if(count >= 0)
633 ser->recover = 0;
634 else
635 serialrecover(ser, p, p->epout, "writing");
636 qunlock(ser);
637 return count;
638 }
639
640 static int
openeps(Serialport * p,int epin,int epout,int epintr)641 openeps(Serialport *p, int epin, int epout, int epintr)
642 {
643 Serial *ser;
644
645 ser = p->s;
646 p->epin = openep(ser->dev, epin);
647 if(p->epin == nil){
648 fprint(2, "serial: openep %d: %r\n", epin);
649 return -1;
650 }
651 if(epout == epin){
652 incref(p->epin);
653 p->epout = p->epin;
654 }else
655 p->epout = openep(ser->dev, epout);
656 if(p->epout == nil){
657 fprint(2, "serial: openep %d: %r\n", epout);
658 closedev(p->epin);
659 return -1;
660 }
661
662 if(!p->isjtag){
663 devctl(p->epin, "timeout 1000");
664 devctl(p->epout, "timeout 1000");
665 }
666
667 if(ser->hasepintr){
668 p->epintr = openep(ser->dev, epintr);
669 if(p->epintr == nil){
670 fprint(2, "serial: openep %d: %r\n", epintr);
671 closedev(p->epin);
672 closedev(p->epout);
673 return -1;
674 }
675 opendevdata(p->epintr, OREAD);
676 devctl(p->epintr, "timeout 1000");
677 }
678
679 if(ser->seteps!= nil)
680 ser->seteps(p);
681 if(p->epin == p->epout)
682 opendevdata(p->epin, ORDWR);
683 else{
684 opendevdata(p->epin, OREAD);
685 opendevdata(p->epout, OWRITE);
686 }
687 if(p->epin->dfd < 0 ||p->epout->dfd < 0 ||
688 (ser->hasepintr && p->epintr->dfd < 0)){
689 fprint(2, "serial: open i/o ep data: %r\n");
690 closedev(p->epin);
691 closedev(p->epout);
692 if(ser->hasepintr)
693 closedev(p->epintr);
694 return -1;
695 }
696 return 0;
697 }
698
699 static int
findendpoints(Serial * ser,int ifc)700 findendpoints(Serial *ser, int ifc)
701 {
702 int i, epin, epout, epintr;
703 Ep *ep, **eps;
704
705 epintr = epin = epout = -1;
706
707 /*
708 * interfc 0 means start from the start which is equiv to
709 * iterate through endpoints probably, could be done better
710 */
711 eps = ser->dev->usb->conf[0]->iface[ifc]->ep;
712
713 for(i = 0; i < Niface; i++){
714 if((ep = eps[i]) == nil)
715 continue;
716 if(ser->hasepintr && ep->type == Eintr &&
717 ep->dir == Ein && epintr == -1)
718 epintr = ep->id;
719 if(ep->type == Ebulk){
720 if((ep->dir == Ein || ep->dir == Eboth) && epin == -1)
721 epin = ep->id;
722 if((ep->dir == Eout || ep->dir == Eboth) && epout == -1)
723 epout = ep->id;
724 }
725 }
726 dprint(2, "serial[%d]: ep ids: in %d out %d intr %d\n", ifc, epin, epout, epintr);
727 if(epin == -1 || epout == -1 || (ser->hasepintr && epintr == -1))
728 return -1;
729
730 if(openeps(&ser->p[ifc], epin, epout, epintr) < 0)
731 return -1;
732
733 dprint(2, "serial: ep in %s out %s\n", ser->p[ifc].epin->dir, ser->p[ifc].epout->dir);
734 if(ser->hasepintr)
735 dprint(2, "serial: ep intr %s\n", ser->p[ifc].epintr->dir);
736
737 if(usbdebug > 1 || serialdebug > 2){
738 devctl(ser->p[ifc].epin, "debug 1");
739 devctl(ser->p[ifc].epout, "debug 1");
740 if(ser->hasepintr)
741 devctl(ser->p[ifc].epintr, "debug 1");
742 devctl(ser->dev, "debug 1");
743 }
744 return 0;
745 }
746
747 /* keep in sync with main.c */
748 static int
usage(void)749 usage(void)
750 {
751 werrstr("usage: usb/serial [-dD] [-m mtpt] [-s srv]");
752 return -1;
753 }
754
755 static void
serdevfree(void * a)756 serdevfree(void *a)
757 {
758 Serial *ser = a;
759 Serialport *p;
760 int i;
761
762 if(ser == nil)
763 return;
764
765 for(i = 0; i < ser->nifcs; i++){
766 p = &ser->p[i];
767
768 if(ser->hasepintr)
769 closedev(p->epintr);
770 closedev(p->epin);
771 closedev(p->epout);
772 p->epintr = p->epin = p->epout = nil;
773 if(p->w4data != nil)
774 chanfree(p->w4data);
775 if(p->gotdata != nil)
776 chanfree(p->gotdata);
777 if(p->readc)
778 chanfree(p->readc);
779
780 }
781 free(ser);
782 }
783
784 static Usbfs serialfs = {
785 .walk = dwalk,
786 .open = dopen,
787 .read = dread,
788 .write= dwrite,
789 .stat = dstat,
790 };
791
792 static void
serialfsend(Usbfs * fs)793 serialfsend(Usbfs *fs)
794 {
795 Serialport *p;
796
797 p = fs->aux;
798
799 if(p->w4data != nil)
800 chanclose(p->w4data);
801 if(p->gotdata != nil)
802 chanclose(p->gotdata);
803 if(p->readc)
804 chanclose(p->readc);
805 }
806
807 int
serialmain(Dev * dev,int argc,char * argv[])808 serialmain(Dev *dev, int argc, char* argv[])
809 {
810 Serial *ser;
811 Serialport *p;
812 char buf[50];
813 int i, devid;
814
815 devid = dev->id;
816 ARGBEGIN{
817 case 'd':
818 serialdebug++;
819 break;
820 case 'N':
821 devid = atoi(EARGF(usage()));
822 break;
823 default:
824 return usage();
825 }ARGEND
826 if(argc != 0)
827 return usage();
828
829 ser = dev->aux = emallocz(sizeof(Serial), 1);
830 ser->maxrtrans = ser->maxwtrans = sizeof ser->p[0].data;
831 ser->maxread = ser->maxwrite = sizeof ser->p[0].data;
832 ser->dev = dev;
833 dev->free = serdevfree;
834 ser->jtag = -1;
835 ser->nifcs = 1;
836
837 snprint(buf, sizeof buf, "vid %#06x did %#06x",
838 dev->usb->vid, dev->usb->did);
839 if(plmatch(buf) == 0){
840 ser->hasepintr = 1;
841 ser->Serialops = plops;
842 } else if(uconsmatch(buf) == 0)
843 ser->Serialops = uconsops;
844 else if(ftmatch(ser, buf) == 0)
845 ser->Serialops = ftops;
846 else if(slmatch(buf) == 0)
847 ser->Serialops = slops;
848 else {
849 werrstr("serial: no serial devices found");
850 return -1;
851 }
852 for(i = 0; i < ser->nifcs; i++){
853 p = &ser->p[i];
854 p->interfc = i;
855 p->s = ser;
856 p->fs = serialfs;
857 if(i == ser->jtag){
858 p->isjtag++;
859 }
860 if(findendpoints(ser, i) < 0){
861 werrstr("serial: no endpoints found for ifc %d", i);
862 return -1;
863 }
864 p->w4data = chancreate(sizeof(ulong), 0);
865 p->gotdata = chancreate(sizeof(ulong), 0);
866 }
867
868 qlock(ser);
869 serialreset(ser);
870 for(i = 0; i < ser->nifcs; i++){
871 p = &ser->p[i];
872 dprint(2, "serial: valid interface, calling serinit\n");
873 if(serinit(p) < 0){
874 dprint(2, "serial: serinit: %r\n");
875 return -1;
876 }
877
878 dsprint(2, "serial: adding interface %d, %p\n", p->interfc, p);
879 if(p->isjtag){
880 snprint(p->name, sizeof p->name, "jtag");
881 dsprint(2, "serial: JTAG interface %d %p\n", i, p);
882 snprint(p->fs.name, sizeof p->fs.name, "jtag%d.%d", devid, i);
883 } else {
884 snprint(p->name, sizeof p->name, "eiaU");
885 if(i == 0)
886 snprint(p->fs.name, sizeof p->fs.name, "eiaU%d", devid);
887 else
888 snprint(p->fs.name, sizeof p->fs.name, "eiaU%d.%d", devid, i);
889 }
890 fprint(2, "%s...", p->fs.name);
891 p->fs.dev = dev;
892 incref(dev);
893 p->fs.aux = p;
894 p->fs.end = serialfsend;
895 usbfsadd(&p->fs);
896 }
897
898 qunlock(ser);
899 return 0;
900 }
901