1 #include <u.h> 2 #include <libc.h> 3 #include <thread.h> 4 #include "usb.h" 5 #include "usbfs.h" 6 #include "serial.h" 7 #include "prolific.h" 8 9 Cinfo plinfo[] = { 10 { PL2303Vid, PL2303Did }, 11 { PL2303Vid, PL2303DidRSAQ2 }, 12 { PL2303Vid, PL2303DidDCU11 }, 13 { PL2303Vid, PL2303DidRSAQ3 }, 14 { PL2303Vid, PL2303DidPHAROS }, 15 { PL2303Vid, PL2303DidALDIGA }, 16 { PL2303Vid, PL2303DidMMX }, 17 { PL2303Vid, PL2303DidGPRS }, 18 { IODATAVid, IODATADid }, 19 { IODATAVid, IODATADidRSAQ5 }, 20 { ATENVid, ATENDid }, 21 { ATENVid2, ATENDid }, 22 { ELCOMVid, ELCOMDid }, 23 { ELCOMVid, ELCOMDidUCSGT }, 24 { ITEGNOVid, ITEGNODid }, 25 { ITEGNOVid, ITEGNODid2080 }, 26 { MA620Vid, MA620Did }, 27 { RATOCVid, RATOCDid }, 28 { TRIPPVid, TRIPPDid }, 29 { RADIOSHACKVid,RADIOSHACKDid }, 30 { DCU10Vid, DCU10Did }, 31 { SITECOMVid, SITECOMDid }, 32 { ALCATELVid, ALCATELDid }, 33 { SAMSUNGVid, SAMSUNGDid }, 34 { SIEMENSVid, SIEMENSDidSX1 }, 35 { SIEMENSVid, SIEMENSDidX65 }, 36 { SIEMENSVid, SIEMENSDidX75 }, 37 { SIEMENSVid, SIEMENSDidEF81 }, 38 { SYNTECHVid, SYNTECHDid }, 39 { NOKIACA42Vid, NOKIACA42Did }, 40 { CA42CA42Vid, CA42CA42Did }, 41 { SAGEMVid, SAGEMDid }, 42 { LEADTEKVid, LEADTEK9531Did }, 43 { SPEEDDRAGONVid,SPEEDDRAGONDid }, 44 { DATAPILOTU2Vid,DATAPILOTU2Did }, 45 { BELKINVid, BELKINDid }, 46 { ALCORVid, ALCORDid }, 47 { WS002INVid, WS002INDid }, 48 { COREGAVid, COREGADid }, 49 { YCCABLEVid, YCCABLEDid }, 50 { SUPERIALVid, SUPERIALDid }, 51 { HPVid, HPLD220Did }, 52 { 0, 0 }, 53 }; 54 55 int 56 plmatch(char *info) 57 { 58 Cinfo *ip; 59 char buf[50]; 60 61 for(ip = plinfo; ip->vid != 0; ip++){ 62 snprint(buf, sizeof buf, "vid %#06x did %#06x", 63 ip->vid, ip->did); 64 dsprint(2, "serial: %s %s\n", buf, info); 65 if(strstr(info, buf) != nil) 66 return 0; 67 } 68 return -1; 69 } 70 71 static void statusreader(void *u); 72 73 static void 74 dumpbuf(uchar *buf, int bufsz) 75 { 76 int i; 77 78 for(i=0; i<bufsz; i++) 79 print("buf[%d]=%#ux ", i, buf[i]); 80 print("\n"); 81 } 82 83 static int 84 vendorread(Serialport *p, int val, int index, uchar *buf) 85 { 86 int res; 87 Serial *ser; 88 89 ser = p->s; 90 91 dsprint(2, "serial: vendorread val: 0x%x idx:%d buf:%p\n", 92 val, index, buf); 93 res = usbcmd(ser->dev, Rd2h | Rvendor | Rdev, VendorReadReq, 94 val, index, buf, 1); 95 dsprint(2, "serial: vendorread res:%d\n", res); 96 return res; 97 } 98 99 static int 100 vendorwrite(Serialport *p, int val, int index) 101 { 102 int res; 103 Serial *ser; 104 105 ser = p->s; 106 107 dsprint(2, "serial: vendorwrite val: 0x%x idx:%d\n", val, index); 108 res = usbcmd(ser->dev, Rh2d | Rvendor | Rdev, VendorWriteReq, 109 val, index, nil, 0); 110 dsprint(2, "serial: vendorwrite res:%d\n", res); 111 return res; 112 } 113 114 /* BUG: I could probably read Dcr0 and set only the bits */ 115 static int 116 plmodemctl(Serialport *p, int set) 117 { 118 Serial *ser; 119 120 ser = p->s; 121 122 if(set == 0){ 123 p->mctl = 0; 124 vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init); 125 return 0; 126 } 127 128 p->mctl = 1; 129 if(ser->type == TypeHX) 130 vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init|Dcr0HwFcX); 131 else 132 vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init|Dcr0HwFcH); 133 return 0; 134 } 135 136 static int 137 plgetparam(Serialport *p) 138 { 139 uchar buf[ParamReqSz]; 140 int res; 141 Serial *ser; 142 143 ser = p->s; 144 145 146 res = usbcmd(ser->dev, Rd2h | Rclass | Riface, GetLineReq, 147 0, 0, buf, sizeof buf); 148 p->baud = GET4(buf); 149 150 /* 151 * with the Pl9 interface it is not possible to set `1.5' as stop bits 152 * for the prologic: 153 * 0 is 1 stop bit 154 * 1 is 1.5 stop bits 155 * 2 is 2 stop bits 156 */ 157 if(buf[4] == 1) 158 fprint(2, "warning, stop bit set to 1.5 unsupported"); 159 else if(buf[4] == 0) 160 p->stop = 1; 161 else if(buf[4] == 2) 162 p->stop = 2; 163 p->parity = buf[5]; 164 p->bits = buf[6]; 165 166 dsprint(2, "serial: getparam: "); 167 if(serialdebug) 168 dumpbuf(buf, sizeof buf); 169 dsprint(2, "serial: getparam res: %d\n", res); 170 return res; 171 } 172 173 static int 174 plsetparam(Serialport *p) 175 { 176 uchar buf[ParamReqSz]; 177 int res; 178 Serial *ser; 179 180 ser = p->s; 181 182 PUT4(buf, p->baud); 183 184 if(p->stop == 1) 185 buf[4] = 0; 186 else if(p->stop == 2) 187 buf[4] = 2; /* see comment in getparam */ 188 buf[5] = p->parity; 189 buf[6] = p->bits; 190 191 dsprint(2, "serial: setparam: "); 192 if(serialdebug) 193 dumpbuf(buf, sizeof buf); 194 res = usbcmd(ser->dev, Rh2d | Rclass | Riface, SetLineReq, 195 0, 0, buf, sizeof buf); 196 plmodemctl(p, p->mctl); 197 plgetparam(p); /* make sure our state corresponds */ 198 199 dsprint(2, "serial: setparam res: %d\n", res); 200 return res; 201 } 202 203 static int 204 revid(ulong devno) 205 { 206 switch(devno){ 207 case RevH: 208 return TypeH; 209 case RevX: 210 case RevHX: 211 case Rev1: 212 return TypeHX; 213 default: 214 return TypeUnk; 215 } 216 } 217 218 /* linux driver says the release id is not always right */ 219 static int 220 heuristicid(ulong csp, ulong maxpkt) 221 { 222 if(Class(csp) == 0x02) 223 return TypeH; 224 else if(maxpkt == 0x40) 225 return TypeHX; 226 else if(Class(csp) == 0x00 || Class(csp) == 0xFF) 227 return TypeH; 228 else{ 229 fprint(2, "serial: chip unknown, setting to HX version\n"); 230 return TypeHX; 231 } 232 } 233 234 static int 235 plinit(Serialport *p) 236 { 237 char *st; 238 uchar *buf; 239 ulong csp, maxpkt, dno; 240 Serial *ser; 241 242 ser = p->s; 243 buf = emallocz(VendorReqSz, 1); 244 dsprint(2, "plinit\n"); 245 246 csp = ser->dev->usb->csp; 247 maxpkt = ser->dev->maxpkt; 248 dno = ser->dev->usb->dno; 249 250 if((ser->type = revid(dno)) == TypeUnk) 251 ser->type = heuristicid(csp, maxpkt); 252 253 dsprint(2, "serial: type %d\n", ser->type); 254 255 vendorread(p, 0x8484, 0, buf); 256 vendorwrite(p, 0x0404, 0); 257 vendorread(p, 0x8484, 0, buf); 258 vendorread(p, 0x8383, 0, buf); 259 vendorread(p, 0x8484, 0, buf); 260 vendorwrite(p, 0x0404, 1); 261 vendorread(p, 0x8484, 0, buf); 262 vendorread(p, 0x8383, 0, buf); 263 264 vendorwrite(p, Dcr0Idx|DcrSet, Dcr0Init); 265 vendorwrite(p, Dcr1Idx|DcrSet, Dcr1Init); 266 267 if(ser->type == TypeHX) 268 vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitX); 269 else 270 vendorwrite(p, Dcr2Idx|DcrSet, Dcr2InitH); 271 272 plgetparam(p); 273 qunlock(ser); 274 free(buf); 275 st = emallocz(255, 1); 276 qlock(ser); 277 if(serialdebug) 278 serdumpst(p, st, 255); 279 dsprint(2, st); 280 free(st); 281 /* p gets freed by closedev, the process has a reference */ 282 incref(ser->dev); 283 proccreate(statusreader, p, 8*1024); 284 return 0; 285 } 286 287 static int 288 plsetbreak(Serialport *p, int val) 289 { 290 Serial *ser; 291 292 ser = p->s; 293 return usbcmd(ser->dev, Rh2d | Rclass | Riface, 294 (val != 0? BreakOn: BreakOff), val, 0, nil, 0); 295 } 296 297 static int 298 plclearpipes(Serialport *p) 299 { 300 Serial *ser; 301 302 ser = p->s; 303 304 if(ser->type == TypeHX){ 305 vendorwrite(p, PipeDSRst, 0); 306 vendorwrite(p, PipeUSRst, 0); 307 }else{ 308 if(unstall(ser->dev, p->epout, Eout) < 0) 309 dprint(2, "disk: unstall epout: %r\n"); 310 if(unstall(ser->dev, p->epin, Ein) < 0) 311 dprint(2, "disk: unstall epin: %r\n"); 312 if(unstall(ser->dev, p->epintr, Ein) < 0) 313 dprint(2, "disk: unstall epintr: %r\n"); 314 } 315 return 0; 316 } 317 318 static int 319 setctlline(Serialport *p, uchar val) 320 { 321 Serial *ser; 322 323 ser = p->s; 324 return usbcmd(ser->dev, Rh2d | Rclass | Riface, SetCtlReq, 325 val, 0, nil, 0); 326 } 327 328 static void 329 composectl(Serialport *p) 330 { 331 if(p->rts) 332 p->ctlstate |= CtlRTS; 333 else 334 p->ctlstate &= ~CtlRTS; 335 if(p->dtr) 336 p->ctlstate |= CtlDTR; 337 else 338 p->ctlstate &= ~CtlDTR; 339 } 340 341 static int 342 plsendlines(Serialport *p) 343 { 344 int res; 345 346 dsprint(2, "serial: sendlines: %#2.2x\n", p->ctlstate); 347 composectl(p); 348 res = setctlline(p, p->ctlstate); 349 dsprint(2, "serial: sendlines res: %d\n", res); 350 return 0; 351 } 352 353 static int 354 plreadstatus(Serialport *p) 355 { 356 int nr, dfd; 357 char err[40]; 358 uchar buf[VendorReqSz]; 359 Serial *ser; 360 361 ser = p->s; 362 363 qlock(ser); 364 dsprint(2, "serial: reading from interrupt\n"); 365 dfd = p->epintr->dfd; 366 367 qunlock(ser); 368 nr = read(dfd, buf, sizeof buf); 369 qlock(ser); 370 snprint(err, sizeof err, "%r"); 371 dsprint(2, "serial: interrupt read %d %r\n", nr); 372 373 if(nr < 0 && strstr(err, "timed out") == nil){ 374 dsprint(2, "serial: need to recover, status read %d %r\n", nr); 375 if(serialrecover(ser, err) < 0){ 376 qunlock(ser); 377 return -1; 378 } 379 } 380 if(nr < 0) 381 dsprint(2, "serial: reading status: %r"); 382 else if(nr >= sizeof buf - 1){ 383 p->dcd = buf[8] & DcdStatus; 384 p->dsr = buf[8] & DsrStatus; 385 p->cts = buf[8] & BreakerrStatus; 386 p->ring = buf[8] & RingStatus; 387 p->cts = buf[8] & CtsStatus; 388 if(buf[8] & FrerrStatus) 389 p->nframeerr++; 390 if(buf[8] & ParerrStatus) 391 p->nparityerr++; 392 if(buf[8] & OvererrStatus) 393 p->novererr++; 394 } else 395 dsprint(2, "serial: bad status read %d\n", nr); 396 dsprint(2, "serial: finished read from interrupt %d\n", nr); 397 qunlock(ser); 398 return 0; 399 } 400 401 static void 402 statusreader(void *u) 403 { 404 Serialport *p; 405 Serial *ser; 406 407 p = u; 408 ser = p->s; 409 threadsetname("statusreaderproc"); 410 while(plreadstatus(p) >= 0) 411 ; 412 fprint(2, "serial: statusreader exiting\n"); 413 closedev(ser->dev); 414 } 415 416 /* 417 * Maximum number of bytes transferred per frame 418 * The output buffer size cannot be increased due to the size encoding 419 */ 420 421 static int 422 plseteps(Serialport *p) 423 { 424 devctl(p->epin, "maxpkt 256"); 425 devctl(p->epout, "maxpkt 256"); 426 return 0; 427 } 428 429 Serialops plops = { 430 .init = plinit, 431 .getparam = plgetparam, 432 .setparam = plsetparam, 433 .clearpipes = plclearpipes, 434 .sendlines = plsendlines, 435 .modemctl = plmodemctl, 436 .setbreak = plsetbreak, 437 .seteps = plseteps, 438 }; 439