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