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