serial.c 17 KB

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