prolific.c 8.6 KB

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