ftdi.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961
  1. /* Future Technology Devices International serial ports */
  2. #include <u.h>
  3. #include <libc.h>
  4. #include <thread.h>
  5. #include "usb.h"
  6. #include "usbfs.h"
  7. #include "serial.h"
  8. #include "ftdi.h"
  9. /*
  10. * BUG: This keeps growing, there has to be a better way, but without
  11. * devices to try it... We can probably simply look for FTDI in the
  12. * string, or use regular expressions somehow.
  13. */
  14. Cinfo ftinfo[] = {
  15. { FTVid, FTACTZWAVEDid },
  16. { FTSheevaVid, FTSheevaDid },
  17. { FTVid, FTOpenRDUltDid},
  18. { FTVid, FTIRTRANSDid },
  19. { FTVid, FTIPLUSDid },
  20. { FTVid, FTSIODid },
  21. { FTVid, FT8U232AMDid },
  22. { FTVid, FT8U232AMALTDid },
  23. { FTVid, FT8U2232CDid },
  24. { FTVid, FTRELAISDid },
  25. { INTERBIOMVid, INTERBIOMIOBRDDid },
  26. { INTERBIOMVid, INTERBIOMMINIIOBRDDid },
  27. { FTVid, FTXF632Did },
  28. { FTVid, FTXF634Did },
  29. { FTVid, FTXF547Did },
  30. { FTVid, FTXF633Did },
  31. { FTVid, FTXF631Did },
  32. { FTVid, FTXF635Did },
  33. { FTVid, FTXF640Did },
  34. { FTVid, FTXF642Did },
  35. { FTVid, FTDSS20Did },
  36. { FTNFRICVid, FTNFRICDid },
  37. { FTVid, FTVNHCPCUSBDDid },
  38. { FTVid, FTMTXORB0Did },
  39. { FTVid, FTMTXORB1Did },
  40. { FTVid, FTMTXORB2Did },
  41. { FTVid, FTMTXORB3Did },
  42. { FTVid, FTMTXORB4Did },
  43. { FTVid, FTMTXORB5Did },
  44. { FTVid, FTMTXORB6Did },
  45. { FTVid, FTPERLEULTRAPORTDid },
  46. { FTVid, FTPIEGROUPDid },
  47. { SEALEVELVid, SEALEVEL2101Did },
  48. { SEALEVELVid, SEALEVEL2102Did },
  49. { SEALEVELVid, SEALEVEL2103Did },
  50. { SEALEVELVid, SEALEVEL2104Did },
  51. { SEALEVELVid, SEALEVEL22011Did },
  52. { SEALEVELVid, SEALEVEL22012Did },
  53. { SEALEVELVid, SEALEVEL22021Did },
  54. { SEALEVELVid, SEALEVEL22022Did },
  55. { SEALEVELVid, SEALEVEL22031Did },
  56. { SEALEVELVid, SEALEVEL22032Did },
  57. { SEALEVELVid, SEALEVEL24011Did },
  58. { SEALEVELVid, SEALEVEL24012Did },
  59. { SEALEVELVid, SEALEVEL24013Did },
  60. { SEALEVELVid, SEALEVEL24014Did },
  61. { SEALEVELVid, SEALEVEL24021Did },
  62. { SEALEVELVid, SEALEVEL24022Did },
  63. { SEALEVELVid, SEALEVEL24023Did },
  64. { SEALEVELVid, SEALEVEL24024Did },
  65. { SEALEVELVid, SEALEVEL24031Did },
  66. { SEALEVELVid, SEALEVEL24032Did },
  67. { SEALEVELVid, SEALEVEL24033Did },
  68. { SEALEVELVid, SEALEVEL24034Did },
  69. { SEALEVELVid, SEALEVEL28011Did },
  70. { SEALEVELVid, SEALEVEL28012Did },
  71. { SEALEVELVid, SEALEVEL28013Did },
  72. { SEALEVELVid, SEALEVEL28014Did },
  73. { SEALEVELVid, SEALEVEL28015Did },
  74. { SEALEVELVid, SEALEVEL28016Did },
  75. { SEALEVELVid, SEALEVEL28017Did },
  76. { SEALEVELVid, SEALEVEL28018Did },
  77. { SEALEVELVid, SEALEVEL28021Did },
  78. { SEALEVELVid, SEALEVEL28022Did },
  79. { SEALEVELVid, SEALEVEL28023Did },
  80. { SEALEVELVid, SEALEVEL28024Did },
  81. { SEALEVELVid, SEALEVEL28025Did },
  82. { SEALEVELVid, SEALEVEL28026Did },
  83. { SEALEVELVid, SEALEVEL28027Did },
  84. { SEALEVELVid, SEALEVEL28028Did },
  85. { SEALEVELVid, SEALEVEL28031Did },
  86. { SEALEVELVid, SEALEVEL28032Did },
  87. { SEALEVELVid, SEALEVEL28033Did },
  88. { SEALEVELVid, SEALEVEL28034Did },
  89. { SEALEVELVid, SEALEVEL28035Did },
  90. { SEALEVELVid, SEALEVEL28036Did },
  91. { SEALEVELVid, SEALEVEL28037Did },
  92. { SEALEVELVid, SEALEVEL28038Did },
  93. { IDTECHVid, IDTECHIDT1221UDid },
  94. { OCTVid, OCTUS101Did },
  95. { FTVid, FTHETIRA1Did }, /* special quirk div = 240 baud = B38400 rtscts = 1 */
  96. { FTVid, FTUSBUIRTDid }, /* special quirk div = 77, baud = B38400 */
  97. { FTVid, PROTEGOSPECIAL1 },
  98. { FTVid, PROTEGOR2X0 },
  99. { FTVid, PROTEGOSPECIAL3 },
  100. { FTVid, PROTEGOSPECIAL4 },
  101. { FTVid, FTGUDEADSE808Did },
  102. { FTVid, FTGUDEADSE809Did },
  103. { FTVid, FTGUDEADSE80ADid },
  104. { FTVid, FTGUDEADSE80BDid },
  105. { FTVid, FTGUDEADSE80CDid },
  106. { FTVid, FTGUDEADSE80DDid },
  107. { FTVid, FTGUDEADSE80EDid },
  108. { FTVid, FTGUDEADSE80FDid },
  109. { FTVid, FTGUDEADSE888Did },
  110. { FTVid, FTGUDEADSE889Did },
  111. { FTVid, FTGUDEADSE88ADid },
  112. { FTVid, FTGUDEADSE88BDid },
  113. { FTVid, FTGUDEADSE88CDid },
  114. { FTVid, FTGUDEADSE88DDid },
  115. { FTVid, FTGUDEADSE88EDid },
  116. { FTVid, FTGUDEADSE88FDid },
  117. { FTVid, FTELVUO100Did },
  118. { FTVid, FTELVUM100Did },
  119. { FTVid, FTELVUR100Did },
  120. { FTVid, FTELVALC8500Did },
  121. { FTVid, FTPYRAMIDDid },
  122. { FTVid, FTELVFHZ1000PCDid },
  123. { FTVid, FTELVCLI7000Did },
  124. { FTVid, FTELVPPS7330Did },
  125. { FTVid, FTELVTFM100Did },
  126. { FTVid, FTELVUDF77Did },
  127. { FTVid, FTELVUIO88Did },
  128. { FTVid, FTELVUAD8Did },
  129. { FTVid, FTELVUDA7Did },
  130. { FTVid, FTELVUSI2Did },
  131. { FTVid, FTELVT1100Did },
  132. { FTVid, FTELVPCD200Did },
  133. { FTVid, FTELVULA200Did },
  134. { FTVid, FTELVCSI8Did },
  135. { FTVid, FTELVEM1000DLDid },
  136. { FTVid, FTELVPCK100Did },
  137. { FTVid, FTELVRFP500Did },
  138. { FTVid, FTELVFS20SIGDid },
  139. { FTVid, FTELVWS300PCDid },
  140. { FTVid, FTELVFHZ1300PCDid },
  141. { FTVid, FTELVWS500Did },
  142. { FTVid, LINXSDMUSBQSSDid },
  143. { FTVid, LINXMASTERDEVEL2Did },
  144. { FTVid, LINXFUTURE0Did },
  145. { FTVid, LINXFUTURE1Did },
  146. { FTVid, LINXFUTURE2Did },
  147. { FTVid, FTCCSICDU200Did },
  148. { FTVid, FTCCSICDU401Did },
  149. { FTVid, INSIDEACCESSO },
  150. { INTREDidVid, INTREDidVALUECANDid },
  151. { INTREDidVid, INTREDidNEOVIDid },
  152. { FALCOMVid, FALCOMTWISTDid },
  153. { FALCOMVid, FALCOMSAMBADid },
  154. { FTVid, FTSUUNTOSPORTSDid },
  155. { FTVid, FTRMCANVIEWDid },
  156. { BANDBVid, BANDBUSOTL4Did },
  157. { BANDBVid, BANDBUSTL4Did },
  158. { BANDBVid, BANDBUSO9ML2Did },
  159. { FTVid, EVERECOPROCDSDid },
  160. { FTVid, FT4NGALAXYDE0Did },
  161. { FTVid, FT4NGALAXYDE1Did },
  162. { FTVid, FT4NGALAXYDE2Did },
  163. { FTVid, XSENSCONVERTER0Did },
  164. { FTVid, XSENSCONVERTER1Did },
  165. { FTVid, XSENSCONVERTER2Did },
  166. { FTVid, XSENSCONVERTER3Did },
  167. { FTVid, XSENSCONVERTER4Did },
  168. { FTVid, XSENSCONVERTER5Did },
  169. { FTVid, XSENSCONVERTER6Did },
  170. { FTVid, XSENSCONVERTER7Did },
  171. { MOBILITYVid, MOBILITYUSBSERIALDid },
  172. { FTVid, FTACTIVEROBOTSDid },
  173. { FTVid, FTMHAMKWDid },
  174. { FTVid, FTMHAMYSDid },
  175. { FTVid, FTMHAMY6Did },
  176. { FTVid, FTMHAMY8Did },
  177. { FTVid, FTMHAMICDid },
  178. { FTVid, FTMHAMDB9Did },
  179. { FTVid, FTMHAMRS232Did },
  180. { FTVid, FTMHAMY9Did },
  181. { FTVid, FTTERATRONIKVCPDid },
  182. { FTVid, FTTERATRONIKD2XXDid },
  183. { EVOLUTIONVid, EVOLUTIONER1Did },
  184. { FTVid, FTARTEMISDid },
  185. { FTVid, FTATIKATK16Did },
  186. { FTVid, FTATIKATK16CDid },
  187. { FTVid, FTATIKATK16HRDid },
  188. { FTVid, FTATIKATK16HRCDid },
  189. { KOBILVid, KOBILCONVB1Did },
  190. { KOBILVid, KOBILCONVKAANDid },
  191. { POSIFLEXVid, POSIFLEXPP7000Did },
  192. { FTVid, FTTTUSBDid },
  193. { FTVid, FTECLOCOM1WIREDid },
  194. { FTVid, FTWESTREXMODEL777Did },
  195. { FTVid, FTWESTREXMODEL8900FDid },
  196. { FTVid, FTPCDJDAC2Did },
  197. { FTVid, FTRRCIRKITSLOCOBUFFERDid },
  198. { FTVid, FTASKRDR400Did },
  199. { ICOMID1Vid, ICOMID1Did },
  200. { PAPOUCHVid, PAPOUCHTMUDid },
  201. { FTVid, FTACGHFDUALDid },
  202. { FT8U232AMDid, FT4232HDid },
  203. { 0, 0 },
  204. };
  205. enum {
  206. Packsz = 64, /* default size */
  207. Maxpacksz = 512,
  208. Bufsiz = 4 * 1024,
  209. };
  210. static int
  211. ftdiread(Serialport *p, int index, int req, uchar *buf, int len)
  212. {
  213. int res;
  214. Serial *ser;
  215. ser = p->s;
  216. if(req != FTGETE2READ)
  217. index |= p->interfc + 1;
  218. dsprint(2, "serial: ftdiread %#p [%d] req: %#x val: %#x idx:%d buf:%p len:%d\n",
  219. p, p->interfc, req, 0, index, buf, len);
  220. res = usbcmd(ser->dev, Rd2h | Rftdireq | Rdev, req, 0, index, buf, len);
  221. dsprint(2, "serial: ftdiread res:%d\n", res);
  222. return res;
  223. }
  224. static int
  225. ftdiwrite(Serialport *p, int val, int index, int req)
  226. {
  227. int res;
  228. Serial *ser;
  229. ser = p->s;
  230. if(req != FTGETE2READ || req != FTSETE2ERASE || req != FTSETBAUDRATE)
  231. index |= p->interfc + 1;
  232. dsprint(2, "serial: ftdiwrite %#p [%d] req: %#x val: %#x idx:%d\n",
  233. p, p->interfc, req, val, index);
  234. res = usbcmd(ser->dev, Rh2d | Rftdireq | Rdev, req, val, index, nil, 0);
  235. dsprint(2, "serial: ftdiwrite res:%d\n", res);
  236. return res;
  237. }
  238. static int
  239. ftmodemctl(Serialport *p, int set)
  240. {
  241. if(set == 0){
  242. p->mctl = 0;
  243. ftdiwrite(p, 0, 0, FTSETMODEMCTRL);
  244. return 0;
  245. }
  246. p->mctl = 1;
  247. ftdiwrite(p, 0, FTRTSCTSHS, FTSETFLOWCTRL);
  248. return 0;
  249. }
  250. static ushort
  251. ft232ambaudbase2div(int baud, int base)
  252. {
  253. int divisor3;
  254. ushort divisor;
  255. divisor3 = (base / 2) / baud;
  256. if((divisor3 & 7) == 7)
  257. divisor3++; /* round x.7/8 up to x+1 */
  258. divisor = divisor3 >> 3;
  259. divisor3 &= 7;
  260. if(divisor3 == 1)
  261. divisor |= 0xc000; /* 0.125 */
  262. else if(divisor3 >= 4)
  263. divisor |= 0x4000; /* 0.5 */
  264. else if(divisor3 != 0)
  265. divisor |= 0x8000; /* 0.25 */
  266. if( divisor == 1)
  267. divisor = 0; /* special case for maximum baud rate */
  268. return divisor;
  269. }
  270. enum{
  271. ClockNew = 48000000,
  272. ClockOld = 12000000 / 16,
  273. HetiraDiv = 240,
  274. UirtDiv = 77,
  275. };
  276. static ushort
  277. ft232ambaud2div(int baud)
  278. {
  279. return ft232ambaudbase2div(baud, ClockNew);
  280. }
  281. static ulong divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7};
  282. static ulong
  283. ft232bmbaudbase2div(int baud, int base)
  284. {
  285. int divisor3;
  286. u32int divisor;
  287. divisor3 = (base / 2) / baud;
  288. divisor = divisor3 >> 3 | divfrac[divisor3 & 7] << 14;
  289. /* Deal with special cases for highest baud rates. */
  290. if( divisor == 1)
  291. divisor = 0; /* 1.0 */
  292. else if( divisor == 0x4001)
  293. divisor = 1; /* 1.5 */
  294. return divisor;
  295. }
  296. static ulong
  297. ft232bmbaud2div (int baud)
  298. {
  299. return ft232bmbaudbase2div (baud, ClockNew);
  300. }
  301. static int
  302. customdiv(Serial *ser)
  303. {
  304. if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTHETIRA1Did)
  305. return HetiraDiv;
  306. else if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTUSBUIRTDid)
  307. return UirtDiv;
  308. fprint(2, "serial: weird custom divisor\n");
  309. return 0; /* shouldn't happen, break as much as I can */
  310. }
  311. static ulong
  312. ftbaudcalcdiv(Serial *ser, int baud)
  313. {
  314. int cusdiv;
  315. ulong divval;
  316. if(baud == 38400 && (cusdiv = customdiv(ser)) != 0)
  317. baud = ser->baudbase / cusdiv;
  318. if(baud == 0)
  319. baud = 9600;
  320. switch(ser->type) {
  321. case SIO:
  322. switch(baud) {
  323. case 300:
  324. divval = FTb300;
  325. break;
  326. case 600:
  327. divval = FTb600;
  328. break;
  329. case 1200:
  330. divval = FTb1200;
  331. break;
  332. case 2400:
  333. divval = FTb2400;
  334. break;
  335. case 4800:
  336. divval = FTb4800;
  337. break;
  338. case 9600:
  339. divval = FTb9600;
  340. break;
  341. case 19200:
  342. divval = FTb19200;
  343. break;
  344. case 38400:
  345. divval = FTb38400;
  346. break;
  347. case 57600:
  348. divval = FTb57600;
  349. break;
  350. case 115200:
  351. divval = FTb115200;
  352. break;
  353. default:
  354. divval = FTb9600;
  355. break;
  356. }
  357. break;
  358. case FT8U232AM:
  359. if(baud <= 3000000)
  360. divval = ft232ambaud2div(baud);
  361. else
  362. divval = ft232ambaud2div(9600);
  363. break;
  364. case FT232BM:
  365. case FT2232C:
  366. case FTKINDR:
  367. case FT2232H:
  368. case FT4232H:
  369. if(baud <= 3000000)
  370. divval = ft232bmbaud2div(baud);
  371. else
  372. divval = ft232bmbaud2div(9600);
  373. break;
  374. default:
  375. divval = ft232bmbaud2div(9600);
  376. break;
  377. }
  378. return divval;
  379. }
  380. static int
  381. ftsetparam(Serialport *p)
  382. {
  383. int res;
  384. ushort val;
  385. ulong bauddiv;
  386. val = 0;
  387. if(p->stop == 1)
  388. val |= FTSETDATASTOPBITS1;
  389. else if(p->stop == 2)
  390. val |= FTSETDATASTOPBITS2;
  391. else if(p->stop == 15)
  392. val |= FTSETDATASTOPBITS15;
  393. switch(p->parity){
  394. case 0:
  395. val |= FTSETDATAParNONE;
  396. break;
  397. case 1:
  398. val |= FTSETDATAParODD;
  399. break;
  400. case 2:
  401. val |= FTSETDATAParEVEN;
  402. break;
  403. case 3:
  404. val |= FTSETDATAParMARK;
  405. break;
  406. case 4:
  407. val |= FTSETDATAParSPACE;
  408. break;
  409. };
  410. dsprint(2, "serial: setparam\n");
  411. res = ftdiwrite(p, val, 0, FTSETDATA);
  412. if(res < 0)
  413. return res;
  414. res = ftmodemctl(p, p->mctl);
  415. if(res < 0)
  416. return res;
  417. bauddiv = ftbaudcalcdiv(p->s, p->baud);
  418. res = ftdiwrite(p, bauddiv, (bauddiv>>16) & 1, FTSETBAUDRATE);
  419. dsprint(2, "serial: setparam res: %d\n", res);
  420. return res;
  421. }
  422. static int
  423. hasjtag(Usbdev *udev)
  424. {
  425. /* no string, for now, by default we detect no jtag */
  426. if(udev->product != nil && cistrstr(udev->product, "jtag") != nil)
  427. return 1;
  428. return 0;
  429. }
  430. /* ser locked */
  431. static void
  432. ftgettype(Serial *ser)
  433. {
  434. int i, outhdrsz, dno, pksz;
  435. ulong baudbase;
  436. Conf *cnf;
  437. pksz = Packsz;
  438. /* Assume it is not the original SIO device for now. */
  439. baudbase = ClockNew / 2;
  440. outhdrsz = 0;
  441. dno = ser->dev->usb->dno;
  442. cnf = ser->dev->usb->conf[0];
  443. ser->nifcs = 0;
  444. for(i = 0; i < Niface; i++)
  445. if(cnf->iface[i] != nil)
  446. ser->nifcs++;
  447. if(ser->nifcs > 1) {
  448. /*
  449. * Multiple interfaces. default assume FT2232C,
  450. */
  451. if(dno == 0x500)
  452. ser->type = FT2232C;
  453. else if(dno == 0x600)
  454. ser->type = FTKINDR;
  455. else if(dno == 0x700){
  456. ser->type = FT2232H;
  457. pksz = Maxpacksz;
  458. } else if(dno == 0x800){
  459. ser->type = FT4232H;
  460. pksz = Maxpacksz;
  461. } else
  462. ser->type = FT2232C;
  463. if(hasjtag(ser->dev->usb))
  464. ser->jtag = 0;
  465. /*
  466. * BM-type devices have a bug where dno gets set
  467. * to 0x200 when serial is 0.
  468. */
  469. if(dno < 0x500)
  470. fprint(2, "serial: warning: dno %d too low for "
  471. "multi-interface device\n", dno);
  472. } else if(dno < 0x200) {
  473. /* Old device. Assume it is the original SIO. */
  474. ser->type = SIO;
  475. baudbase = ClockOld/16;
  476. outhdrsz = 1;
  477. } else if(dno < 0x400)
  478. /*
  479. * Assume its an FT8U232AM (or FT8U245AM)
  480. * (It might be a BM because of the iSerialNumber bug,
  481. * but it will still work as an AM device.)
  482. */
  483. ser->type = FT8U232AM;
  484. else /* Assume it is an FT232BM (or FT245BM) */
  485. ser->type = FT232BM;
  486. ser->maxrtrans = ser->maxwtrans = pksz;
  487. ser->baudbase = baudbase;
  488. ser->outhdrsz = outhdrsz;
  489. ser->inhdrsz = 2;
  490. dsprint (2, "serial: detected type: %#x\n", ser->type);
  491. }
  492. int
  493. ftmatch(Serial *ser, char *info)
  494. {
  495. Cinfo *ip;
  496. char buf[50];
  497. for(ip = ftinfo; ip->vid != 0; ip++){
  498. snprint(buf, sizeof buf, "vid %#06x did %#06x", ip->vid, ip->did);
  499. dsprint(2, "serial: %s %s\n", buf, info);
  500. if(strstr(info, buf) != nil){
  501. if(ser != nil){
  502. qlock(ser);
  503. ftgettype(ser);
  504. qunlock(ser);
  505. }
  506. return 0;
  507. }
  508. }
  509. return -1;
  510. }
  511. static int
  512. ftuseinhdr(Serialport *p, uchar *b)
  513. {
  514. if(b[0] & FTICTS)
  515. p->cts = 1;
  516. else
  517. p->cts = 0;
  518. if(b[0] & FTIDSR)
  519. p->dsr = 1;
  520. else
  521. p->dsr = 0;
  522. if(b[0] & FTIRI)
  523. p->ring = 1;
  524. else
  525. p->ring = 0;
  526. if(b[0] & FTIRLSD)
  527. p->rlsd = 1;
  528. else
  529. p->rlsd = 0;
  530. if(b[1] & FTIOE)
  531. p->novererr++;
  532. if(b[1] & FTIPE)
  533. p->nparityerr++;
  534. if(b[1] & FTIFE)
  535. p->nframeerr++;
  536. if(b[1] & FTIBI)
  537. p->nbreakerr++;
  538. return 0;
  539. }
  540. static int
  541. ftsetouthdr(Serialport *p, uchar *b, int len)
  542. {
  543. if(p->s->outhdrsz != 0)
  544. b[0] = FTOPORT | (FTOLENMSK & len);
  545. return p->s->outhdrsz;
  546. }
  547. static int
  548. wait4data(Serialport *p, uchar *data, int count)
  549. {
  550. int d;
  551. Serial *ser;
  552. ser = p->s;
  553. qunlock(ser);
  554. d = sendul(p->w4data, 1);
  555. qlock(ser);
  556. if(d <= 0)
  557. return -1;
  558. if(p->ndata >= count)
  559. p->ndata -= count;
  560. else{
  561. count = p->ndata;
  562. p->ndata = 0;
  563. }
  564. assert(count >= 0);
  565. assert(p->ndata >= 0);
  566. memmove(data, p->data, count);
  567. if(p->ndata != 0)
  568. memmove(p->data, p->data+count, p->ndata);
  569. recvul(p->gotdata);
  570. return count;
  571. }
  572. static int
  573. wait4write(Serialport *p, uchar *data, int count)
  574. {
  575. int off, fd;
  576. uchar *b;
  577. Serial *ser;
  578. ser = p->s;
  579. b = emallocz(count+ser->outhdrsz, 1);
  580. off = ftsetouthdr(p, b, count);
  581. memmove(b+off, data, count);
  582. fd = p->epout->dfd;
  583. qunlock(ser);
  584. count = write(fd, b, count+off);
  585. qlock(ser);
  586. free(b);
  587. return count;
  588. }
  589. typedef struct Packser Packser;
  590. struct Packser{
  591. int nb;
  592. uchar b[Bufsiz];
  593. };
  594. typedef struct Areader Areader;
  595. struct Areader{
  596. Serialport *p;
  597. Channel *c;
  598. };
  599. static void
  600. shutdownchan(Channel *c)
  601. {
  602. Packser *bp;
  603. while((bp=nbrecvp(c)) != nil)
  604. free(bp);
  605. chanfree(c);
  606. }
  607. int
  608. cpdata(Serial *ser, Serialport *port, uchar *out, uchar *in, int sz)
  609. {
  610. int i, ncp, ntotcp, pksz;
  611. pksz = ser->maxrtrans;
  612. ntotcp = 0;
  613. for(i = 0; i < sz; i+= pksz){
  614. ftuseinhdr(port, in + i);
  615. if(sz - i > pksz)
  616. ncp = pksz - ser->inhdrsz;
  617. else
  618. ncp = sz - i - ser->inhdrsz;
  619. memmove(out, in + i + ser->inhdrsz, ncp);
  620. out += ncp;
  621. ntotcp += ncp;
  622. }
  623. return ntotcp;
  624. }
  625. static void
  626. epreader(void *u)
  627. {
  628. int dfd, rcount, cl, ntries, recov;
  629. char err[40];
  630. Areader *a;
  631. Channel *c;
  632. Packser *pk;
  633. Serial *ser;
  634. Serialport *p;
  635. threadsetname("epreader proc");
  636. a = u;
  637. p = a->p;
  638. ser = p->s;
  639. c = a->c;
  640. free(a);
  641. qlock(ser); /* this makes the reader wait end of initialization too */
  642. dfd = p->epin->dfd;
  643. qunlock(ser);
  644. ntries = 0;
  645. pk = nil;
  646. do {
  647. if (pk == nil)
  648. pk = emallocz(sizeof(Packser), 1);
  649. Eagain:
  650. rcount = read(dfd, pk->b, sizeof pk->b);
  651. if(serialdebug > 5)
  652. dsprint(2, "%d %#ux%#ux ", rcount, p->data[0],
  653. p->data[1]);
  654. if(rcount < 0){
  655. if(ntries++ > 100)
  656. break;
  657. qlock(ser);
  658. recov = serialrecover(ser, p, nil, "epreader: bulkin error");
  659. qunlock(ser);
  660. if(recov >= 0)
  661. goto Eagain;
  662. }
  663. if(rcount == 0)
  664. continue;
  665. if(rcount >= ser->inhdrsz){
  666. rcount = cpdata(ser, p, pk->b, pk->b, rcount);
  667. if(rcount != 0){
  668. pk->nb = rcount;
  669. cl = sendp(c, pk);
  670. if(cl < 0){
  671. /*
  672. * if it was a time-out, I don't want
  673. * to give back an error.
  674. */
  675. rcount = 0;
  676. break;
  677. }
  678. }else
  679. free(pk);
  680. qlock(ser);
  681. ser->recover = 0;
  682. qunlock(ser);
  683. ntries = 0;
  684. pk = nil;
  685. }
  686. } while(rcount >= 0 || (rcount < 0 && strstr(err, "timed out") != nil));
  687. if(rcount < 0)
  688. fprint(2, "%s: error reading %s: %r\n", argv0, p->fs.name);
  689. free(pk);
  690. nbsendp(c, nil);
  691. if(p->w4data != nil)
  692. chanclose(p->w4data);
  693. if(p->gotdata != nil)
  694. chanclose(p->gotdata);
  695. devctl(ser->dev, "detach");
  696. closedev(ser->dev);
  697. usbfsdel(&p->fs);
  698. }
  699. static void
  700. statusreader(void *u)
  701. {
  702. Areader *a;
  703. Channel *c;
  704. Packser *pk;
  705. Serialport *p;
  706. Serial *ser;
  707. int cl;
  708. p = u;
  709. ser = p->s;
  710. threadsetname("statusreader thread");
  711. /* big buffering, fewer bytes lost */
  712. c = chancreate(sizeof(Packser *), 128);
  713. a = emallocz(sizeof(Areader), 1);
  714. a->p = p;
  715. a->c = c;
  716. incref(ser->dev);
  717. proccreate(epreader, a, 16*1024);
  718. while((pk = recvp(c)) != nil){
  719. memmove(p->data, pk->b, pk->nb);
  720. p->ndata = pk->nb;
  721. free(pk);
  722. dsprint(2, "serial %p: status reader %d \n", p, p->ndata);
  723. /* consume it all */
  724. while(p->ndata != 0){
  725. dsprint(2, "serial %p: status reader to consume: %d\n",
  726. p, p->ndata);
  727. cl = recvul(p->w4data);
  728. if(cl < 0)
  729. break;
  730. cl = sendul(p->gotdata, 1);
  731. if(cl < 0)
  732. break;
  733. }
  734. }
  735. shutdownchan(c);
  736. devctl(ser->dev, "detach");
  737. closedev(ser->dev);
  738. usbfsdel(&p->fs);
  739. }
  740. static int
  741. ftreset(Serial *ser, Serialport *p)
  742. {
  743. int i;
  744. if(p != nil){
  745. ftdiwrite(p, FTRESETCTLVAL, 0, FTRESET);
  746. return 0;
  747. }
  748. p = ser->p;
  749. for(i = 0; i < Maxifc; i++)
  750. if(p[i].s != nil)
  751. ftdiwrite(&p[i], FTRESETCTLVAL, 0, FTRESET);
  752. return 0;
  753. }
  754. static int
  755. ftinit(Serialport *p)
  756. {
  757. Serial *ser;
  758. uint timerval;
  759. int res;
  760. ser = p->s;
  761. if(p->isjtag){
  762. res = ftdiwrite(p, FTSETFLOWCTRL, 0, FTDISABLEFLOWCTRL);
  763. if(res < 0)
  764. return -1;
  765. res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
  766. FTLATENCYTIMERSZ);
  767. if(res < 0)
  768. return -1;
  769. dsprint(2, "serial: jtag latency timer is %d\n", timerval);
  770. timerval = 2;
  771. ftdiwrite(p, FTLATENCYDEFAULT, 0, FTSETLATENCYTIMER);
  772. res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval,
  773. FTLATENCYTIMERSZ);
  774. if(res < 0)
  775. return -1;
  776. dsprint(2, "serial: jtag latency timer set to %d\n", timerval);
  777. /* may be unnecessary */
  778. devctl(p->epin, "timeout 5000");
  779. devctl(p->epout, "timeout 5000");
  780. /* 0xb is the mask for lines. plug dependant? */
  781. ftdiwrite(p, BMMPSSE|0x0b, 0, FTSETBITMODE);
  782. }
  783. incref(ser->dev);
  784. threadcreate(statusreader, p, 8*1024);
  785. return 0;
  786. }
  787. static int
  788. ftsetbreak(Serialport *p, int val)
  789. {
  790. return ftdiwrite(p, (val != 0? FTSETBREAK: 0), 0, FTSETDATA);
  791. }
  792. static int
  793. ftclearpipes(Serialport *p)
  794. {
  795. /* maybe can be done in one... */
  796. ftdiwrite(p, FTRESETCTLVALPURGETX, 0, FTRESET);
  797. ftdiwrite(p, FTRESETCTLVALPURGERX, 0, FTRESET);
  798. return 0;
  799. }
  800. static int
  801. setctlline(Serialport *p, uchar val)
  802. {
  803. return ftdiwrite(p, val | (val << 8), 0, FTSETMODEMCTRL);
  804. }
  805. static void
  806. updatectlst(Serialport *p, int val)
  807. {
  808. if(p->rts)
  809. p->ctlstate |= val;
  810. else
  811. p->ctlstate &= ~val;
  812. }
  813. static int
  814. setctl(Serialport *p)
  815. {
  816. int res;
  817. Serial *ser;
  818. ser = p->s;
  819. if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTHETIRA1Did){
  820. fprint(2, "serial: cannot set lines for this device\n");
  821. updatectlst(p, CtlRTS|CtlDTR);
  822. p->rts = p->dtr = 1;
  823. return -1;
  824. }
  825. /* NB: you can not set DTR and RTS with one control message */
  826. updatectlst(p, CtlRTS);
  827. res = setctlline(p, (CtlRTS<<8)|p->ctlstate);
  828. if(res < 0)
  829. return res;
  830. updatectlst(p, CtlDTR);
  831. res = setctlline(p, (CtlDTR<<8)|p->ctlstate);
  832. if(res < 0)
  833. return res;
  834. return 0;
  835. }
  836. static int
  837. ftsendlines(Serialport *p)
  838. {
  839. int res;
  840. dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate);
  841. res = setctl(p);
  842. dsprint(2, "serial: sendlines res: %d\n", res);
  843. return 0;
  844. }
  845. static int
  846. ftseteps(Serialport *p)
  847. {
  848. char *s;
  849. Serial *ser;
  850. ser = p->s;
  851. s = smprint("maxpkt %d", ser->maxrtrans);
  852. devctl(p->epin, s);
  853. free(s);
  854. s = smprint("maxpkt %d", ser->maxwtrans);
  855. devctl(p->epout, s);
  856. free(s);
  857. return 0;
  858. }
  859. Serialops ftops = {
  860. .init = ftinit,
  861. .seteps = ftseteps,
  862. .setparam = ftsetparam,
  863. .clearpipes = ftclearpipes,
  864. .reset = ftreset,
  865. .sendlines = ftsendlines,
  866. .modemctl = ftmodemctl,
  867. .setbreak = ftsetbreak,
  868. .wait4data = wait4data,
  869. .wait4write = wait4write,
  870. };