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 { FTVid, AMONKEYDid }, 205 { 0, 0 }, 206 }; 207 208 enum { 209 Packsz = 64, /* default size */ 210 Maxpacksz = 512, 211 Bufsiz = 4 * 1024, 212 }; 213 214 static int 215 ftdiread(Serialport *p, int index, int req, uchar *buf, int len) 216 { 217 int res; 218 Serial *ser; 219 220 ser = p->s; 221 222 if(req != FTGETE2READ) 223 index |= p->interfc + 1; 224 dsprint(2, "serial: ftdiread %#p [%d] req: %#x val: %#x idx:%d buf:%p len:%d\n", 225 p, p->interfc, req, 0, index, buf, len); 226 res = usbcmd(ser->dev, Rd2h | Rftdireq | Rdev, req, 0, index, buf, len); 227 dsprint(2, "serial: ftdiread res:%d\n", res); 228 return res; 229 } 230 231 static int 232 ftdiwrite(Serialport *p, int val, int index, int req) 233 { 234 int res; 235 Serial *ser; 236 237 ser = p->s; 238 239 if(req != FTGETE2READ || req != FTSETE2ERASE || req != FTSETBAUDRATE) 240 index |= p->interfc + 1; 241 dsprint(2, "serial: ftdiwrite %#p [%d] req: %#x val: %#x idx:%d\n", 242 p, p->interfc, req, val, index); 243 res = usbcmd(ser->dev, Rh2d | Rftdireq | Rdev, req, val, index, nil, 0); 244 dsprint(2, "serial: ftdiwrite res:%d\n", res); 245 return res; 246 } 247 248 static int 249 ftmodemctl(Serialport *p, int set) 250 { 251 if(set == 0){ 252 p->mctl = 0; 253 ftdiwrite(p, 0, 0, FTSETMODEMCTRL); 254 return 0; 255 } 256 p->mctl = 1; 257 ftdiwrite(p, 0, FTRTSCTSHS, FTSETFLOWCTRL); 258 return 0; 259 } 260 261 static ushort 262 ft232ambaudbase2div(int baud, int base) 263 { 264 int divisor3; 265 ushort divisor; 266 267 divisor3 = (base / 2) / baud; 268 if((divisor3 & 7) == 7) 269 divisor3++; /* round x.7/8 up to x+1 */ 270 divisor = divisor3 >> 3; 271 divisor3 &= 7; 272 273 if(divisor3 == 1) 274 divisor |= 0xc000; /* 0.125 */ 275 else if(divisor3 >= 4) 276 divisor |= 0x4000; /* 0.5 */ 277 else if(divisor3 != 0) 278 divisor |= 0x8000; /* 0.25 */ 279 if( divisor == 1) 280 divisor = 0; /* special case for maximum baud rate */ 281 return divisor; 282 } 283 284 enum{ 285 ClockNew = 48000000, 286 ClockOld = 12000000 / 16, 287 HetiraDiv = 240, 288 UirtDiv = 77, 289 }; 290 291 static ushort 292 ft232ambaud2div(int baud) 293 { 294 return ft232ambaudbase2div(baud, ClockNew); 295 } 296 297 static ulong divfrac[8] = { 0, 3, 2, 4, 1, 5, 6, 7}; 298 299 static ulong 300 ft232bmbaudbase2div(int baud, int base) 301 { 302 int divisor3; 303 u32int divisor; 304 305 divisor3 = (base / 2) / baud; 306 divisor = divisor3 >> 3 | divfrac[divisor3 & 7] << 14; 307 308 /* Deal with special cases for highest baud rates. */ 309 if( divisor == 1) 310 divisor = 0; /* 1.0 */ 311 else if( divisor == 0x4001) 312 divisor = 1; /* 1.5 */ 313 return divisor; 314 } 315 316 static ulong 317 ft232bmbaud2div (int baud) 318 { 319 return ft232bmbaudbase2div (baud, ClockNew); 320 } 321 322 static int 323 customdiv(Serial *ser) 324 { 325 if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTHETIRA1Did) 326 return HetiraDiv; 327 else if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTUSBUIRTDid) 328 return UirtDiv; 329 330 fprint(2, "serial: weird custom divisor\n"); 331 return 0; /* shouldn't happen, break as much as I can */ 332 } 333 334 static ulong 335 ftbaudcalcdiv(Serial *ser, int baud) 336 { 337 int cusdiv; 338 ulong divval; 339 340 if(baud == 38400 && (cusdiv = customdiv(ser)) != 0) 341 baud = ser->baudbase / cusdiv; 342 343 if(baud == 0) 344 baud = 9600; 345 346 switch(ser->type) { 347 case SIO: 348 switch(baud) { 349 case 300: 350 divval = FTb300; 351 break; 352 case 600: 353 divval = FTb600; 354 break; 355 case 1200: 356 divval = FTb1200; 357 break; 358 case 2400: 359 divval = FTb2400; 360 break; 361 case 4800: 362 divval = FTb4800; 363 break; 364 case 9600: 365 divval = FTb9600; 366 break; 367 case 19200: 368 divval = FTb19200; 369 break; 370 case 38400: 371 divval = FTb38400; 372 break; 373 case 57600: 374 divval = FTb57600; 375 break; 376 case 115200: 377 divval = FTb115200; 378 break; 379 default: 380 divval = FTb9600; 381 break; 382 } 383 break; 384 case FT8U232AM: 385 if(baud <= 3000000) 386 divval = ft232ambaud2div(baud); 387 else 388 divval = ft232ambaud2div(9600); 389 break; 390 case FT232BM: 391 case FT2232C: 392 case FTKINDR: 393 case FT2232H: 394 case FT4232H: 395 if(baud <= 3000000) 396 divval = ft232bmbaud2div(baud); 397 else 398 divval = ft232bmbaud2div(9600); 399 break; 400 default: 401 divval = ft232bmbaud2div(9600); 402 break; 403 } 404 return divval; 405 } 406 407 static int 408 ftsetparam(Serialport *p) 409 { 410 int res; 411 ushort val; 412 ulong bauddiv; 413 414 val = 0; 415 if(p->stop == 1) 416 val |= FTSETDATASTOPBITS1; 417 else if(p->stop == 2) 418 val |= FTSETDATASTOPBITS2; 419 else if(p->stop == 15) 420 val |= FTSETDATASTOPBITS15; 421 switch(p->parity){ 422 case 0: 423 val |= FTSETDATAParNONE; 424 break; 425 case 1: 426 val |= FTSETDATAParODD; 427 break; 428 case 2: 429 val |= FTSETDATAParEVEN; 430 break; 431 case 3: 432 val |= FTSETDATAParMARK; 433 break; 434 case 4: 435 val |= FTSETDATAParSPACE; 436 break; 437 }; 438 439 dsprint(2, "serial: setparam\n"); 440 441 res = ftdiwrite(p, val, 0, FTSETDATA); 442 if(res < 0) 443 return res; 444 445 res = ftmodemctl(p, p->mctl); 446 if(res < 0) 447 return res; 448 449 bauddiv = ftbaudcalcdiv(p->s, p->baud); 450 res = ftdiwrite(p, bauddiv, (bauddiv>>16) & 1, FTSETBAUDRATE); 451 452 dsprint(2, "serial: setparam res: %d\n", res); 453 return res; 454 } 455 456 static int 457 hasjtag(Usbdev *udev) 458 { 459 /* no string, for now, by default we detect no jtag */ 460 if(udev->product != nil && cistrstr(udev->product, "jtag") != nil) 461 return 1; 462 return 0; 463 } 464 465 /* ser locked */ 466 static void 467 ftgettype(Serial *ser) 468 { 469 int i, outhdrsz, dno, pksz; 470 ulong baudbase; 471 Conf *cnf; 472 473 pksz = Packsz; 474 /* Assume it is not the original SIO device for now. */ 475 baudbase = ClockNew / 2; 476 outhdrsz = 0; 477 dno = ser->dev->usb->dno; 478 cnf = ser->dev->usb->conf[0]; 479 ser->nifcs = 0; 480 for(i = 0; i < Niface; i++) 481 if(cnf->iface[i] != nil) 482 ser->nifcs++; 483 if(ser->nifcs > 1) { 484 /* 485 * Multiple interfaces. default assume FT2232C, 486 */ 487 if(dno == 0x500) 488 ser->type = FT2232C; 489 else if(dno == 0x600) 490 ser->type = FTKINDR; 491 else if(dno == 0x700){ 492 ser->type = FT2232H; 493 pksz = Maxpacksz; 494 } else if(dno == 0x800){ 495 ser->type = FT4232H; 496 pksz = Maxpacksz; 497 } else 498 ser->type = FT2232C; 499 500 if(hasjtag(ser->dev->usb)) 501 ser->jtag = 0; 502 503 /* 504 * BM-type devices have a bug where dno gets set 505 * to 0x200 when serial is 0. 506 */ 507 if(dno < 0x500) 508 fprint(2, "serial: warning: dno %d too low for " 509 "multi-interface device\n", dno); 510 } else if(dno < 0x200) { 511 /* Old device. Assume it is the original SIO. */ 512 ser->type = SIO; 513 baudbase = ClockOld/16; 514 outhdrsz = 1; 515 } else if(dno < 0x400) 516 /* 517 * Assume its an FT8U232AM (or FT8U245AM) 518 * (It might be a BM because of the iSerialNumber bug, 519 * but it will still work as an AM device.) 520 */ 521 ser->type = FT8U232AM; 522 else /* Assume it is an FT232BM (or FT245BM) */ 523 ser->type = FT232BM; 524 525 ser->maxrtrans = ser->maxwtrans = pksz; 526 ser->baudbase = baudbase; 527 ser->outhdrsz = outhdrsz; 528 ser->inhdrsz = 2; 529 530 dsprint (2, "serial: detected type: %#x\n", ser->type); 531 } 532 533 int 534 ftmatch(Serial *ser, char *info) 535 { 536 Cinfo *ip; 537 char buf[50]; 538 539 for(ip = ftinfo; ip->vid != 0; ip++){ 540 snprint(buf, sizeof buf, "vid %#06x did %#06x", ip->vid, ip->did); 541 dsprint(2, "serial: %s %s\n", buf, info); 542 if(strstr(info, buf) != nil){ 543 if(ser != nil){ 544 qlock(ser); 545 ftgettype(ser); 546 qunlock(ser); 547 } 548 return 0; 549 } 550 } 551 return -1; 552 } 553 554 static int 555 ftuseinhdr(Serialport *p, uchar *b) 556 { 557 if(b[0] & FTICTS) 558 p->cts = 1; 559 else 560 p->cts = 0; 561 if(b[0] & FTIDSR) 562 p->dsr = 1; 563 else 564 p->dsr = 0; 565 if(b[0] & FTIRI) 566 p->ring = 1; 567 else 568 p->ring = 0; 569 if(b[0] & FTIRLSD) 570 p->rlsd = 1; 571 else 572 p->rlsd = 0; 573 574 if(b[1] & FTIOE) 575 p->novererr++; 576 if(b[1] & FTIPE) 577 p->nparityerr++; 578 if(b[1] & FTIFE) 579 p->nframeerr++; 580 if(b[1] & FTIBI) 581 p->nbreakerr++; 582 return 0; 583 } 584 585 static int 586 ftsetouthdr(Serialport *p, uchar *b, int len) 587 { 588 if(p->s->outhdrsz != 0) 589 b[0] = FTOPORT | (FTOLENMSK & len); 590 return p->s->outhdrsz; 591 } 592 593 static int 594 wait4data(Serialport *p, uchar *data, int count) 595 { 596 int d; 597 Serial *ser; 598 599 ser = p->s; 600 601 qunlock(ser); 602 d = sendul(p->w4data, 1); 603 qlock(ser); 604 if(d <= 0) 605 return -1; 606 if(p->ndata >= count) 607 p->ndata -= count; 608 else{ 609 count = p->ndata; 610 p->ndata = 0; 611 } 612 assert(count >= 0); 613 assert(p->ndata >= 0); 614 memmove(data, p->data, count); 615 if(p->ndata != 0) 616 memmove(p->data, p->data+count, p->ndata); 617 618 recvul(p->gotdata); 619 return count; 620 } 621 622 static int 623 wait4write(Serialport *p, uchar *data, int count) 624 { 625 int off, fd; 626 uchar *b; 627 Serial *ser; 628 629 ser = p->s; 630 631 b = emallocz(count+ser->outhdrsz, 1); 632 off = ftsetouthdr(p, b, count); 633 memmove(b+off, data, count); 634 635 fd = p->epout->dfd; 636 qunlock(ser); 637 count = write(fd, b, count+off); 638 qlock(ser); 639 free(b); 640 return count; 641 } 642 643 typedef struct Packser Packser; 644 struct Packser{ 645 int nb; 646 uchar b[Bufsiz]; 647 }; 648 649 typedef struct Areader Areader; 650 struct Areader{ 651 Serialport *p; 652 Channel *c; 653 }; 654 655 static void 656 shutdownchan(Channel *c) 657 { 658 Packser *bp; 659 660 while((bp=nbrecvp(c)) != nil) 661 free(bp); 662 chanfree(c); 663 } 664 665 int 666 cpdata(Serial *ser, Serialport *port, uchar *out, uchar *in, int sz) 667 { 668 int i, ncp, ntotcp, pksz; 669 670 pksz = ser->maxrtrans; 671 ntotcp = 0; 672 673 for(i = 0; i < sz; i+= pksz){ 674 ftuseinhdr(port, in + i); 675 if(sz - i > pksz) 676 ncp = pksz - ser->inhdrsz; 677 else 678 ncp = sz - i - ser->inhdrsz; 679 memmove(out, in + i + ser->inhdrsz, ncp); 680 out += ncp; 681 ntotcp += ncp; 682 } 683 return ntotcp; 684 } 685 686 static void 687 epreader(void *u) 688 { 689 int dfd, rcount, cl, ntries, recov; 690 char err[40]; 691 Areader *a; 692 Channel *c; 693 Packser *pk; 694 Serial *ser; 695 Serialport *p; 696 697 threadsetname("epreader proc"); 698 a = u; 699 p = a->p; 700 ser = p->s; 701 c = a->c; 702 free(a); 703 704 qlock(ser); /* this makes the reader wait end of initialization too */ 705 dfd = p->epin->dfd; 706 qunlock(ser); 707 708 ntries = 0; 709 pk = nil; 710 do { 711 if (pk == nil) 712 pk = emallocz(sizeof(Packser), 1); 713 Eagain: 714 rcount = read(dfd, pk->b, sizeof pk->b); 715 if(serialdebug > 5) 716 dsprint(2, "%d %#ux%#ux ", rcount, p->data[0], 717 p->data[1]); 718 719 if(rcount < 0){ 720 if(ntries++ > 100) 721 break; 722 qlock(ser); 723 recov = serialrecover(ser, p, nil, "epreader: bulkin error"); 724 qunlock(ser); 725 if(recov >= 0) 726 goto Eagain; 727 } 728 if(rcount == 0) 729 continue; 730 if(rcount >= ser->inhdrsz){ 731 rcount = cpdata(ser, p, pk->b, pk->b, rcount); 732 if(rcount != 0){ 733 pk->nb = rcount; 734 cl = sendp(c, pk); 735 if(cl < 0){ 736 /* 737 * if it was a time-out, I don't want 738 * to give back an error. 739 */ 740 rcount = 0; 741 break; 742 } 743 }else 744 free(pk); 745 qlock(ser); 746 ser->recover = 0; 747 qunlock(ser); 748 ntries = 0; 749 pk = nil; 750 } 751 } while(rcount >= 0 || (rcount < 0 && strstr(err, "timed out") != nil)); 752 753 if(rcount < 0) 754 fprint(2, "%s: error reading %s: %r\n", argv0, p->fs.name); 755 free(pk); 756 nbsendp(c, nil); 757 if(p->w4data != nil) 758 chanclose(p->w4data); 759 if(p->gotdata != nil) 760 chanclose(p->gotdata); 761 devctl(ser->dev, "detach"); 762 closedev(ser->dev); 763 usbfsdel(&p->fs); 764 } 765 766 static void 767 statusreader(void *u) 768 { 769 Areader *a; 770 Channel *c; 771 Packser *pk; 772 Serialport *p; 773 Serial *ser; 774 int cl; 775 776 p = u; 777 ser = p->s; 778 threadsetname("statusreader thread"); 779 /* big buffering, fewer bytes lost */ 780 c = chancreate(sizeof(Packser *), 128); 781 a = emallocz(sizeof(Areader), 1); 782 a->p = p; 783 a->c = c; 784 incref(ser->dev); 785 proccreate(epreader, a, 16*1024); 786 787 while((pk = recvp(c)) != nil){ 788 memmove(p->data, pk->b, pk->nb); 789 p->ndata = pk->nb; 790 free(pk); 791 dsprint(2, "serial %p: status reader %d \n", p, p->ndata); 792 /* consume it all */ 793 while(p->ndata != 0){ 794 dsprint(2, "serial %p: status reader to consume: %d\n", 795 p, p->ndata); 796 cl = recvul(p->w4data); 797 if(cl < 0) 798 break; 799 cl = sendul(p->gotdata, 1); 800 if(cl < 0) 801 break; 802 } 803 } 804 805 shutdownchan(c); 806 devctl(ser->dev, "detach"); 807 closedev(ser->dev); 808 usbfsdel(&p->fs); 809 } 810 811 static int 812 ftreset(Serial *ser, Serialport *p) 813 { 814 int i; 815 816 if(p != nil){ 817 ftdiwrite(p, FTRESETCTLVAL, 0, FTRESET); 818 return 0; 819 } 820 p = ser->p; 821 for(i = 0; i < Maxifc; i++) 822 if(p[i].s != nil) 823 ftdiwrite(&p[i], FTRESETCTLVAL, 0, FTRESET); 824 return 0; 825 } 826 827 static int 828 ftinit(Serialport *p) 829 { 830 Serial *ser; 831 uint timerval; 832 int res; 833 834 ser = p->s; 835 if(p->isjtag){ 836 res = ftdiwrite(p, FTSETFLOWCTRL, 0, FTDISABLEFLOWCTRL); 837 if(res < 0) 838 return -1; 839 res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval, 840 FTLATENCYTIMERSZ); 841 if(res < 0) 842 return -1; 843 dsprint(2, "serial: jtag latency timer is %d\n", timerval); 844 timerval = 2; 845 ftdiwrite(p, FTLATENCYDEFAULT, 0, FTSETLATENCYTIMER); 846 res = ftdiread(p, FTSETLATENCYTIMER, 0, (uchar *)&timerval, 847 FTLATENCYTIMERSZ); 848 if(res < 0) 849 return -1; 850 851 dsprint(2, "serial: jtag latency timer set to %d\n", timerval); 852 /* may be unnecessary */ 853 devctl(p->epin, "timeout 5000"); 854 devctl(p->epout, "timeout 5000"); 855 /* 0xb is the mask for lines. plug dependant? */ 856 ftdiwrite(p, BMMPSSE|0x0b, 0, FTSETBITMODE); 857 } 858 incref(ser->dev); 859 threadcreate(statusreader, p, 8*1024); 860 return 0; 861 } 862 863 static int 864 ftsetbreak(Serialport *p, int val) 865 { 866 return ftdiwrite(p, (val != 0? FTSETBREAK: 0), 0, FTSETDATA); 867 } 868 869 static int 870 ftclearpipes(Serialport *p) 871 { 872 /* maybe can be done in one... */ 873 ftdiwrite(p, FTRESETCTLVALPURGETX, 0, FTRESET); 874 ftdiwrite(p, FTRESETCTLVALPURGERX, 0, FTRESET); 875 return 0; 876 } 877 878 static int 879 setctlline(Serialport *p, uchar val) 880 { 881 return ftdiwrite(p, val | (val << 8), 0, FTSETMODEMCTRL); 882 } 883 884 static void 885 updatectlst(Serialport *p, int val) 886 { 887 if(p->rts) 888 p->ctlstate |= val; 889 else 890 p->ctlstate &= ~val; 891 } 892 893 static int 894 setctl(Serialport *p) 895 { 896 int res; 897 Serial *ser; 898 899 ser = p->s; 900 901 if(ser->dev->usb->vid == FTVid && ser->dev->usb->did == FTHETIRA1Did){ 902 fprint(2, "serial: cannot set lines for this device\n"); 903 updatectlst(p, CtlRTS|CtlDTR); 904 p->rts = p->dtr = 1; 905 return -1; 906 } 907 908 /* NB: you can not set DTR and RTS with one control message */ 909 updatectlst(p, CtlRTS); 910 res = setctlline(p, (CtlRTS<<8)|p->ctlstate); 911 if(res < 0) 912 return res; 913 914 updatectlst(p, CtlDTR); 915 res = setctlline(p, (CtlDTR<<8)|p->ctlstate); 916 if(res < 0) 917 return res; 918 919 return 0; 920 } 921 922 static int 923 ftsendlines(Serialport *p) 924 { 925 int res; 926 927 dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate); 928 res = setctl(p); 929 dsprint(2, "serial: sendlines res: %d\n", res); 930 return 0; 931 } 932 933 static int 934 ftseteps(Serialport *p) 935 { 936 char *s; 937 Serial *ser; 938 939 ser = p->s; 940 941 s = smprint("maxpkt %d", ser->maxrtrans); 942 devctl(p->epin, s); 943 free(s); 944 945 s = smprint("maxpkt %d", ser->maxwtrans); 946 devctl(p->epout, s); 947 free(s); 948 return 0; 949 } 950 951 Serialops ftops = { 952 .init = ftinit, 953 .seteps = ftseteps, 954 .setparam = ftsetparam, 955 .clearpipes = ftclearpipes, 956 .reset = ftreset, 957 .sendlines = ftsendlines, 958 .modemctl = ftmodemctl, 959 .setbreak = ftsetbreak, 960 .wait4data = wait4data, 961 .wait4write = wait4write, 962 }; 963