ttyPos.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. #include "ttyPos.h"
  2. #define DRV_VERSION "303"
  3. #define VERSION_DATE "2014.10.13_01"
  4. #define MAX_RETRY_S 5
  5. #define DRV_NAME "ttyPos"
  6. static struct tty_pos *pdx_table[POS_TTY_MINORS];
  7. #ifdef LINUX_VERSION_CODE
  8. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  9. static struct tty_port pos_port[POS_TTY_MINORS];
  10. #endif
  11. #endif
  12. static unsigned char ResetPipePort(struct tty_pos *dev)
  13. {
  14. struct tty_pos *pdx = dev;
  15. int retval;
  16. retval = usb_clear_halt(pdx->udev, usb_sndbulkpipe(pdx->udev,
  17. pdx->bulk_out_epAddr));
  18. if (retval) {
  19. ERR("%s - ERROR CLEAR %X HALT = %d",
  20. __func__, pdx->bulk_out_epAddr, retval);
  21. goto reset_port;
  22. }
  23. retval = usb_clear_halt(pdx->udev, usb_rcvbulkpipe(pdx->udev,
  24. pdx->bulk_in_epAddr));
  25. if (retval) {
  26. ERR("%s - ERROR CLEAR %X HALT = %d",
  27. __func__, pdx->bulk_in_epAddr, retval);
  28. goto reset_port;
  29. }
  30. return 0;
  31. reset_port:
  32. retval = usb_reset_device(pdx->udev);
  33. if (retval) {
  34. ERR("%s - ERROR RESETTING DEVICE: %d", __func__, retval);
  35. }
  36. return retval;
  37. }
  38. static int VerifyChecksum(ST_BULK_IO *p_bio)
  39. {
  40. unsigned char a, b;
  41. int i, dn;
  42. dn = p_bio->Len + 4;
  43. a = 0;
  44. for (i = 2; i < dn; i++) {
  45. a ^= ((unsigned char *)p_bio)[i];
  46. }
  47. a ^= p_bio->SeqNo & 0x0f;
  48. a ^= p_bio->ReqType & 0x0f;
  49. b = (p_bio->SeqNo & 0xf0) + (p_bio->ReqType >> 4);
  50. if (a != b)
  51. return 1;
  52. /* clear checksum field */
  53. p_bio->SeqNo &= 0x0f;
  54. p_bio->ReqType &= 0x0f;
  55. return 0;
  56. }
  57. static void SetChecksum(ST_BULK_IO *p_bio)
  58. {
  59. unsigned char a;
  60. int i, dn;
  61. dn = p_bio->Len + 4;
  62. a = 0;
  63. for (i = 2; i < dn; i++) {
  64. a ^= ((unsigned char *)p_bio)[i];
  65. }
  66. a ^= p_bio->SeqNo & 0x0f;
  67. a ^= p_bio->ReqType & 0x0f;
  68. /* fill high 4 bits of checksum into high 4 bits of ID field */
  69. p_bio->SeqNo = (p_bio->SeqNo & 0x0f) | (a & 0xf0);
  70. /* fill low 4 bits of checksum into high 4 bits of REQ_TYPE field */
  71. p_bio->ReqType |= (a << 4);
  72. }
  73. static void UrbCallBack(struct urb *urb)
  74. {
  75. struct tty_pos *pdx;
  76. pdx = (struct tty_pos *)urb->context;
  77. atomic_set(&pdx->urb_done, 1);
  78. wake_up(&pdx->urb_wait);
  79. }
  80. static int SendAndWaitUrb(struct tty_pos *dev)
  81. {
  82. struct tty_pos *pdx = dev;
  83. int retval;
  84. atomic_set(&pdx->urb_done, 0);
  85. /* send the data out the bulk port */
  86. retval = usb_submit_urb(pdx->urb, /* GFP_KERNEL */ GFP_ATOMIC);
  87. if (retval) {
  88. ERR("%s - FAILED SUBMITTING WRITE URB: %d", __func__, retval);
  89. retval = 1;
  90. goto exit;
  91. }
  92. retval = wait_event_timeout(pdx->urb_wait,
  93. (atomic_read(&pdx->urb_done) == 1), pdx->timeout_jiffies);
  94. if (retval == 0) {
  95. /* INFO("URB TIMEOUT\n"); */
  96. if (atomic_read(&pdx->urb_done) == 0) { /* urb is not done */
  97. #if 0
  98. usb_unlink_urb(pdx->urb);
  99. printk(KERN_ALERT "usb_done: %d; %d\n",
  100. (atomic_read(&pdx->urb_done) == 1),
  101. /* pdx->urb_done, */ usb_unlink_urb(pdx->urb));
  102. #endif
  103. usb_kill_urb(pdx->urb);
  104. #if 0
  105. wait_event(pdx->urb_wait,
  106. (atomic_read(&pdx->urb_done) == 1));
  107. #endif
  108. }
  109. #if 0
  110. INFO("urb->status: %d, %d\n", pdx->urb->status,
  111. pdx->urb->actual_length);
  112. #endif
  113. retval = 2;
  114. goto exit;
  115. }
  116. else if (retval < 0) {
  117. ERR("%s - WAIT FAILED: %d", __func__, retval);
  118. retval = 3;
  119. goto exit;
  120. }
  121. else {
  122. retval = 0;
  123. #if 0
  124. printk(KERN_INFO "Use jiffies: %d", pdx->timeout_jiffies -
  125. retval);
  126. #endif
  127. }
  128. if (pdx->urb->status) {
  129. /* if (pdx->urb->status != -EREMOTEIO) */
  130. {
  131. ERR("%s - nonzero status received: %d", __func__,
  132. pdx->urb->status);
  133. ERR("urb status:%d\n",pdx->urb->status);
  134. retval = 4;
  135. goto exit;
  136. }
  137. }
  138. exit:
  139. return retval;
  140. }
  141. /* error codes: 11~29 */
  142. static int ProcessCommand(struct tty_pos *dev)
  143. {
  144. struct tty_pos *pdx = dev;
  145. int retval;
  146. /* stage 1: send command pack */
  147. SetChecksum((ST_BULK_IO *)pdx->BioPack);
  148. if (pdx->urb == NULL)
  149. return 18;
  150. if (pdx->urb->status == -EINPROGRESS) {
  151. #if 0
  152. ERR("URB IN PROGRESS\n");
  153. #endif
  154. return 19;
  155. }
  156. usb_fill_bulk_urb(pdx->urb, pdx->udev,
  157. usb_sndbulkpipe(pdx->udev, pdx->bulk_out_epAddr),
  158. pdx->BioPack, pdx->BioPack->Len + 4, UrbCallBack, pdx);
  159. retval = SendAndWaitUrb((struct tty_pos *)pdx);
  160. if (retval != 0)
  161. return retval + 10;
  162. /* stage 2: receive answer pack */
  163. /* clear pack flags */
  164. pdx->BioPack->SeqNo = 0;
  165. pdx->BioPack->ReqType = 0;
  166. pdx->BioPack->Len = 0;
  167. if (pdx->urb == NULL)
  168. return 28;
  169. usb_fill_bulk_urb(pdx->urb, pdx->udev,
  170. usb_rcvbulkpipe(pdx->udev, pdx->bulk_in_epAddr),
  171. pdx->BioPack, sizeof(*pdx->BioPack), UrbCallBack, pdx);
  172. retval = SendAndWaitUrb((struct tty_pos *)pdx);
  173. if (retval != 0)
  174. return retval + 20;
  175. if (VerifyChecksum((ST_BULK_IO *)pdx->BioPack)) {
  176. unsigned int i;
  177. /* unsigned char x; */
  178. ERR("VERIFY CHECKSUM FAILED: %d\n", retval);
  179. ERR("%X; %X; %X\n", pdx->BioPack->SeqNo,
  180. pdx->BioPack->ReqType, pdx->BioPack->Len);
  181. for (i = 0; i < 508; i++) {
  182. INFO("%X\n", pdx->BioPack->Data[i]);
  183. }
  184. #if 0
  185. for (i = 0, x = pdx->BioPack.Data[0];
  186. i < pdx->BioPack.Len; i++, x++) {
  187. if (pdx->BioPack.Data[i] != x) {
  188. printk(KERN_ALERT "%d: %X; %X\n", i - 1,
  189. pdx->BioPack.Data[i - 1], x - 1);
  190. printk(KERN_ALERT "%d: %X; %X\n", i,
  191. pdx->BioPack.Data[i], x);
  192. printk(KERN_ALERT "%d: %X; %X\n", i + 1,
  193. pdx->BioPack.Data[i + 1], x + 1);
  194. printk(KERN_ALERT "%d: %X; %X\n", i + 2,
  195. pdx->BioPack.Data[i + 2], x + 2);
  196. printk(KERN_ALERT "%d: %X; %X\n", i + 3,
  197. pdx->BioPack.Data[i + 3], x + 3);
  198. break;
  199. }
  200. }
  201. #endif
  202. return 29;
  203. }
  204. return 0;
  205. }
  206. static void SleepMs(unsigned int nMs, struct tty_pos *dev)
  207. {
  208. #if 0
  209. set_current_state(TASK_UNINTERRUPTIBLE);
  210. schedule_timeout(nMs * HZ / 1000);
  211. #endif
  212. struct tty_pos *pdx = dev;
  213. unsigned int timeout = (nMs * HZ / 1000);
  214. if (timeout < 1) {
  215. timeout = 1;
  216. }
  217. wait_event_timeout(pdx->write_wait,
  218. (atomic_read(&pdx->write_flag) == 1), timeout);
  219. }
  220. static int ThreadCallBack(void *data)
  221. {
  222. struct tty_pos *pdx = data;
  223. unsigned char loops;
  224. int retval;
  225. unsigned int i, rlen, wlen;
  226. struct tty_struct *tty;
  227. retval = ResetPipePort(pdx);
  228. if (retval != 0) {
  229. retval = 1;
  230. goto exit;
  231. }
  232. tty = pdx->tty;
  233. while (pdx->ThreadState == THREAD_CREATED) {
  234. /* get device buffer status */
  235. for (loops = 0; (loops < MAX_RETRY_S) &&
  236. (pdx->ThreadState == THREAD_CREATED); loops++) {
  237. /* building command pack */
  238. pdx->SeqCount = (pdx->SeqCount + 1) & 0x0f;
  239. pdx->BioPack->SeqNo = pdx->SeqCount;
  240. pdx->BioPack->ReqType = STATUS_COMMAND;
  241. pdx->BioPack->Len = 0;
  242. retval = ProcessCommand((struct tty_pos *)pdx);
  243. if (retval != 0) {
  244. retval += 100;
  245. goto loop_s_tail;
  246. }
  247. if (pdx->urb->actual_length != 20) {
  248. retval = 130;
  249. goto loop_s_tail;
  250. }
  251. if (pdx->BioPack->SeqNo != pdx->SeqCount) {
  252. retval = 131;
  253. goto loop_s_tail;
  254. }
  255. if (pdx->BioPack->ReqType != STATUS_COMMAND) {
  256. retval = 132;
  257. goto loop_s_tail;
  258. }
  259. memcpy(&pdx->BioDevState, pdx->BioPack->Data,
  260. sizeof(pdx->BioDevState));
  261. if ((!pdx->BioDevState.TxLeft) &&
  262. IS_POOL_EMPTY(pdx->TxPool)) {
  263. SleepMs(10, (struct tty_pos *)pdx);
  264. }
  265. loop_s_tail:
  266. if (retval == 0)
  267. break;
  268. ERR("STATUS RETRY, loop: %d, err: %d, seq: %02X\n",
  269. loops, retval, pdx->SeqCount);
  270. ResetPipePort(pdx);
  271. }
  272. if (retval != 0)
  273. goto exit;
  274. r_process: /* read from usb device */
  275. for (loops = 0; (loops < MAX_RETRY_S) &&
  276. (pdx->ThreadState == THREAD_CREATED); loops++) {
  277. if (!pdx->BioDevState.TxLeft)
  278. goto w_process;
  279. rlen = pdx->BioDevState.TxLeft;
  280. if (rlen > sizeof(pdx->BioPack->Data)) {
  281. rlen = sizeof(pdx->BioPack->Data);
  282. }
  283. #ifdef LINUX_VERSION_CODE
  284. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  285. rlen = tty_buffer_request_room(&pos_port[pdx->devIndex],rlen);
  286. #else
  287. rlen = tty_buffer_request_room(tty, rlen);
  288. #endif
  289. #endif
  290. if (!loops) {
  291. pdx->SeqCount = (pdx->SeqCount + 1) & 0x0f;
  292. }
  293. pdx->BioPack->SeqNo = pdx->SeqCount;
  294. pdx->BioPack->ReqType = READ_COMMAND;
  295. pdx->BioPack->Len = 2;
  296. /* in dlen required */
  297. pdx->BioPack->Data[0] = (unsigned short)rlen & 0xff;
  298. pdx->BioPack->Data[1] = (unsigned short)rlen >> 8;
  299. retval = ProcessCommand((struct tty_pos *)pdx);
  300. if (retval != 0) {
  301. retval += 200;
  302. goto loop_r_tail;
  303. }
  304. if (pdx->BioPack->SeqNo != pdx->SeqCount) {
  305. retval = 231;
  306. goto loop_r_tail;
  307. }
  308. if (pdx->BioPack->ReqType != READ_COMMAND) {
  309. if ((pdx->BioPack->ReqType == STATUS_COMMAND) &&
  310. (pdx->BioPack->Len >=
  311. sizeof(pdx->BioDevState))) {
  312. memcpy(&pdx->BioDevState,
  313. pdx->BioPack->Data,
  314. sizeof(pdx->BioDevState));
  315. goto w_process; /* no data to fetch */
  316. }
  317. retval = 232;
  318. ERR(" %02X, ERROR req_type: %02X.\n",
  319. pdx->SeqCount, pdx->BioPack->ReqType);
  320. goto loop_r_tail;
  321. }
  322. if (pdx->urb->actual_length <
  323. (int)pdx->BioPack->Len + 4) {
  324. retval = 233;
  325. goto loop_r_tail;
  326. }
  327. if (pdx->BioPack->Len > rlen) {
  328. ERR("MORE DATA FETCHED THAN DECLARED, NEED: "
  329. "%d, RN: %d\n", rlen, pdx->BioPack->Len);
  330. retval = 234;
  331. goto exit;
  332. }
  333. rlen = pdx->BioPack->Len;
  334. #if 0
  335. for (j = 0; j < rlen - 1; j++) {
  336. if ((pdx->BioPack.Data[j] + 1 !=
  337. pdx->BioPack.Data[j + 1])
  338. && (pdx->BioPack.Data[j + 1] != 0)) {
  339. inerr = 235;
  340. goto exit;
  341. }
  342. }
  343. #endif
  344. #ifdef LINUX_VERSION_CODE
  345. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  346. tty_insert_flip_string(&pos_port[pdx->devIndex], pdx->BioPack->Data, rlen);
  347. tty_flip_buffer_push(&pos_port[pdx->devIndex]);
  348. #else
  349. tty_insert_flip_string(tty, pdx->BioPack->Data, rlen);
  350. tty_flip_buffer_push(tty);
  351. #endif
  352. #endif
  353. pdx->BioDevState.TxLeft -= rlen;
  354. #if 0
  355. printk(KERN_ALERT "%02X, RN: %d\n", pdx->SeqCount,
  356. rlen);
  357. #endif
  358. if (pdx->BioDevState.TxLeft)
  359. goto r_process;
  360. loop_r_tail:
  361. if (retval == 0)
  362. break;
  363. ERR("RX RETRY, loop: %d, err: %d, SEQ: %02X\n",
  364. loops, retval, pdx->SeqCount);
  365. ResetPipePort(pdx);
  366. }
  367. if (retval)
  368. goto exit;
  369. w_process: /* write to usb device */
  370. wlen = GET_USING_POOL(pdx->TxPool);
  371. if (wlen > sizeof(pdx->BioPack->Data)) {
  372. wlen = sizeof(pdx->BioPack->Data);
  373. }
  374. if (wlen > pdx->BioDevState.RxLeft) {
  375. wlen = pdx->BioDevState.RxLeft;
  376. }
  377. for (loops = 0; (loops < MAX_RETRY_S) &&
  378. (pdx->ThreadState == THREAD_CREATED); loops++) {
  379. if (wlen == 0)
  380. break;
  381. if (!loops) {
  382. pdx->SeqCount = (pdx->SeqCount + 1) & 0x0f;
  383. }
  384. pdx->BioPack->SeqNo = pdx->SeqCount;
  385. pdx->BioPack->ReqType = WRITE_COMMAND;
  386. pdx->BioPack->Len = (unsigned short)wlen;
  387. for (i = 0; i < wlen; i++) {
  388. pdx->BioPack->Data[i] =
  389. pdx->TxPool.Buffer[(pdx->TxPool.ReadPos +
  390. i) % POOL_SIZE];
  391. }
  392. retval = ProcessCommand((struct tty_pos *)pdx);
  393. if (retval != 0) {
  394. retval += 300;
  395. goto loop_w_tail;
  396. }
  397. if (pdx->urb->actual_length != 20) {
  398. retval = 330;
  399. goto loop_w_tail;
  400. }
  401. if (pdx->BioPack->SeqNo != pdx->SeqCount) {
  402. retval = 331;
  403. ERR("***** Mismatched with SEQ: %02X, "
  404. "wlen: %d, loop: %d\n", pdx->SeqCount,
  405. wlen, loops);
  406. ERR(" SEQ: %02X, type: %02X, dn: %d\n",
  407. pdx->BioPack->SeqNo, pdx->BioPack->ReqType,
  408. pdx->BioPack->Len);
  409. for (i = 0; i < pdx->BioPack->Len; i++) {
  410. INFO("%02X ", pdx->BioPack->Data[i]);
  411. }
  412. if (((pdx->BioPack->SeqNo + 1) % 16) ==
  413. pdx->SeqCount)
  414. goto loop_w_tail;
  415. goto exit;
  416. } /* mismatched seq_no */
  417. if (pdx->BioPack->ReqType != STATUS_COMMAND) {
  418. retval = 332;
  419. ERR(" SEQ: %02X, type: %02X, dn: %d\n",
  420. pdx->BioPack->SeqNo, pdx->BioPack->ReqType,
  421. pdx->BioPack->Len);
  422. for (i = 0; i < sizeof(pdx->BioPack->Data);
  423. i++) {
  424. INFO("%02X ", pdx->BioPack->Data[i]);
  425. }
  426. INFO("\n");
  427. goto exit;
  428. } /* mismatched req_type */
  429. #if 0
  430. printk(KERN_ALERT "%02X, WN: %d\n", pdx->SeqCount,
  431. wlen);
  432. #endif
  433. pdx->TxPool.ReadPos = (pdx->TxPool.ReadPos + wlen) %
  434. POOL_SIZE;
  435. memcpy(&pdx->BioDevState, pdx->BioPack->Data,
  436. sizeof(pdx->BioDevState));
  437. if (!IS_POOL_EMPTY(pdx->TxPool))
  438. goto w_process;
  439. atomic_set(&pdx->write_flag, 0);
  440. loop_w_tail:
  441. if (retval == 0)
  442. break;
  443. ERR("TX RETRY, loop: %d, err: %d, SEQ: %02X\n",
  444. loops, retval, pdx->SeqCount);
  445. ResetPipePort(pdx);
  446. }
  447. if (retval)
  448. goto exit;
  449. }
  450. exit:
  451. #if 0
  452. INFO("ThreadCallBack Exit\n");
  453. #endif
  454. if (retval != 0) {
  455. ERR("%02X, ERR: %d\n", pdx->SeqCount, retval);
  456. ResetPipePort(pdx);
  457. }
  458. pdx->ThreadState = THREAD_STOPPED;
  459. complete(&pdx->ThreadExit_completion);
  460. do_exit(0);
  461. }
  462. static void pos_delete(struct kref *kref)
  463. {
  464. struct tty_pos *pdx = to_pos_dev(kref);
  465. if (pdx == NULL)
  466. return;
  467. if(pdx->devIndex >= POS_TTY_MINORS)
  468. return;
  469. if (pdx->tty) {
  470. pdx->tty->driver_data = NULL;
  471. }
  472. pdx_table[pdx->devIndex] = NULL;
  473. usb_free_urb(pdx->urb);
  474. usb_put_dev(pdx->udev);
  475. kfree(pdx->BioPack);
  476. kfree(pdx);
  477. }
  478. static int pos_open(struct tty_struct *tty, struct file *filp)
  479. {
  480. struct tty_pos *pdx;
  481. if(tty==NULL)return USB_ERR_MEM_SYSTEM;
  482. if(tty->index >= POS_TTY_MINORS || tty->index<0)return USB_ERR_MEM_SYSTEM;
  483. // INFO("%s index:%d\n",__func__,tty->index);
  484. pdx = pdx_table[tty->index];
  485. if (pdx == NULL)
  486. return USB_ERR_DEV_ABSENT;
  487. if (THREAD_IS_RUNNING(pdx->ThreadState)) {
  488. return USB_ERR_BUSY;
  489. }
  490. tty->driver_data = pdx;
  491. pdx->tty = tty;
  492. #ifdef LINUX_VERSION_CODE
  493. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  494. tty_port_tty_set(&pos_port[pdx->devIndex], tty);
  495. #endif
  496. #endif
  497. kref_get(&pdx->kref);
  498. #ifdef LINUX_VERSION_CODE
  499. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  500. reinit_completion(&pdx->ThreadExit_completion);
  501. #else
  502. INIT_COMPLETION(pdx->ThreadExit_completion);
  503. #endif
  504. #endif
  505. pdx->ThreadState = THREAD_CREATED;
  506. #ifdef LINUX_VERSION_CODE
  507. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  508. {
  509. struct task_struct *thread;
  510. thread = kthread_run(ThreadCallBack,(struct tty_pos *)pdx,"ThreadCallBack");
  511. if (IS_ERR(thread))
  512. {
  513. ERR("FAILED TO CREATE KERNEL THREAD!\n");
  514. pdx->ThreadState = THREAD_INIT;
  515. kref_put(&pdx->kref, pos_delete);
  516. return USB_ERR_RC_SYSTEM;
  517. }
  518. }
  519. #else
  520. {
  521. pid_t pid;
  522. pid = kernel_thread(ThreadCallBack, (struct tty_pos *)pdx,
  523. CLONE_FS | CLONE_FILES);
  524. if (pid < 0) {
  525. ERR("FAILED TO CREATE KERNEL THREAD!\n");
  526. pdx->ThreadState = THREAD_INIT;
  527. kref_put(&pdx->kref, pos_delete);
  528. return USB_ERR_RC_SYSTEM;
  529. }
  530. }
  531. #endif
  532. #endif
  533. pdx->filp = filp;
  534. return 0;
  535. }
  536. static void pos_close(struct tty_struct *tty, struct file *filp)
  537. {
  538. struct tty_pos *pdx = tty->driver_data;
  539. if (pdx == NULL)
  540. return;
  541. if(pdx_table[pdx->devIndex]==NULL)
  542. return;
  543. if (pdx->ThreadState == THREAD_CREATED) {
  544. pdx->ThreadState = THREAD_CLOSE;
  545. wait_for_completion(&pdx->ThreadExit_completion);
  546. }
  547. pdx->ThreadState = THREAD_INIT;
  548. kref_put(&pdx->kref, pos_delete);
  549. //tty_ldisc_flush(tty);
  550. }
  551. static int pos_write(struct tty_struct *tty, const unsigned char *buf,
  552. int count)
  553. {
  554. struct tty_pos *pdx = tty->driver_data;
  555. unsigned int wn, i;
  556. int retval;
  557. if (!pdx)
  558. return USB_ERR_NOT_OPEN;
  559. if (!THREAD_IS_RUNNING(pdx->ThreadState)) {
  560. retval = USB_ERR_INVALID;
  561. goto exit;
  562. }
  563. if (count == 0) {
  564. retval = 0;
  565. goto exit;
  566. }
  567. wn = GET_SPACE_POOL(pdx->TxPool);
  568. if (wn >= count) {
  569. wn = count;
  570. }
  571. else
  572. return USB_ERR_BUF;
  573. for (i = 0; i < wn; i++) {
  574. pdx->TxPool.Buffer[(pdx->TxPool.WritePos + i) % POOL_SIZE] =
  575. buf[i];
  576. }
  577. pdx->TxPool.WritePos = (pdx->TxPool.WritePos + wn) % POOL_SIZE;
  578. retval = wn;
  579. atomic_set(&pdx->write_flag, 1);
  580. wake_up(&pdx->write_wait);
  581. exit:
  582. return retval;
  583. }
  584. static int pos_write_room(struct tty_struct *tty)
  585. {
  586. struct tty_pos *pdx = tty->driver_data;
  587. int room = -EINVAL;
  588. if (!pdx)
  589. return -ENODEV;
  590. room = GET_SPACE_POOL(pdx->TxPool);
  591. return room;
  592. }
  593. #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
  594. static int pos_ioctl(struct tty_struct *tty, struct file *filp,
  595. unsigned int cmd, unsigned long arg)
  596. #else
  597. static int pos_ioctl(struct tty_struct *tty, unsigned int cmd,
  598. unsigned long arg)
  599. #endif
  600. {
  601. struct tty_pos *pdx = tty->driver_data;
  602. #if 0
  603. INFO("pos_ioctl\n");
  604. #endif
  605. if (!pdx)
  606. return -ENODEV;
  607. switch (cmd) {
  608. case TIOCGSERIAL:
  609. case TIOCMIWAIT:
  610. case TIOCGICOUNT:
  611. default:
  612. break;
  613. }
  614. #if 0
  615. INFO("%s-cmd: 0x%X\n", __func__, cmd);
  616. #endif
  617. return -ENOIOCTLCMD;
  618. }
  619. #define RELEVANT_IFLAG(iflag) \
  620. ((iflag) & (IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK))
  621. static void pos_set_termios(struct tty_struct *tty,
  622. struct ktermios *old_termios)
  623. {
  624. unsigned int cflag;
  625. #ifdef LINUX_VERSION_CODE
  626. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  627. cflag = tty->termios.c_cflag;
  628. #else
  629. cflag = tty->termios->c_cflag;
  630. #endif
  631. #endif
  632. /* check that they really want us to change something */
  633. if (old_termios) {
  634. if ((cflag == old_termios->c_cflag) &&
  635. #ifdef LINUX_VERSION_CODE
  636. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  637. (RELEVANT_IFLAG(tty->termios.c_iflag) ==
  638. #else
  639. (RELEVANT_IFLAG(tty->termios->c_iflag) ==
  640. #endif
  641. #endif
  642. RELEVANT_IFLAG(old_termios->c_iflag))) {
  643. #if 0
  644. INFO(" - nothing to change...\n");
  645. #endif
  646. return;
  647. }
  648. }
  649. #if 0
  650. /* get the byte size */
  651. switch (cflag & CSIZE) {
  652. case CS5:
  653. INFO(" - data bits = 5\n");
  654. break;
  655. case CS6:
  656. INFO(" - data bits = 6\n");
  657. break;
  658. case CS7:
  659. INFO(" - data bits = 7\n");
  660. break;
  661. default:
  662. case CS8:
  663. INFO(" - data bits = 8\n");
  664. break;
  665. }
  666. /* determine the parity */
  667. if (cflag & PARENB) {
  668. if (cflag & PARODD) {
  669. INFO(" - parity = odd\n");
  670. }
  671. else {
  672. INFO(" - parity = even\n");
  673. }
  674. }
  675. else {
  676. INFO(" - parity = none\n");
  677. }
  678. /* figure out the stop bits requested */
  679. if (cflag & CSTOPB) {
  680. INFO(" - stop bits = 2\n");
  681. }
  682. else {
  683. INFO(" - stop bits = 1\n");
  684. }
  685. /* figure out the hardware flow control settings */
  686. if (cflag & CRTSCTS) {
  687. INFO(" - RTS/CTS is enabled\n");
  688. }
  689. else {
  690. INFO(" - RTS/CTS is disabled\n");
  691. }
  692. /* determine software flow control.
  693. * if we are implementing XON/XOFF, set the start and
  694. * stop character in the device */
  695. if (I_IXOFF(tty) || I_IXON(tty)) {
  696. unsigned char stop_char = STOP_CHAR(tty);
  697. unsigned char start_char = START_CHAR(tty);
  698. /* if we are implementing INBOUND XON/XOFF */
  699. if (I_IXOFF(tty)) {
  700. INFO(" - INBOUND XON/XOFF is enabled, "
  701. "XON = %2x, XOFF = %2x", start_char, stop_char);
  702. }
  703. else {
  704. INFO(" - INBOUND XON/XOFF is disabled");
  705. }
  706. /* if we are implementing OUTBOUND XON/XOFF */
  707. if (I_IXON(tty)) {
  708. INFO(" - OUTBOUND XON/XOFF is enabled, "
  709. "XON = %2x, XOFF = %2x", start_char, stop_char);
  710. }
  711. else {
  712. INFO(" - OUTBOUND XON/XOFF is disabled");
  713. }
  714. }
  715. /* get the baud rate wanted */
  716. INFO(" - baud rate = %d\n", tty_get_baud_rate(tty));
  717. #endif
  718. }
  719. static void pos_throttle(struct tty_struct *tty)
  720. {
  721. /* INFO("pos_throttle\n"); */
  722. }
  723. static void pos_unthrottle(struct tty_struct *tty)
  724. {
  725. /* INFO("pos_unthrottle\n"); */
  726. }
  727. static void pos_flush_buffer(struct tty_struct *tty)
  728. {
  729. struct tty_pos *pdx = tty->driver_data;
  730. #if 0
  731. INFO("pos_flush_buffer\n");
  732. #endif
  733. if (!pdx)
  734. return;
  735. INIT_POOL_BUFFER(pdx->TxPool);
  736. }
  737. static int pos_chars_in_buffer(struct tty_struct *tty)
  738. {
  739. int in_buf_len;
  740. struct tty_pos *pdx = tty->driver_data;
  741. if (!pdx)
  742. return -ENODEV;
  743. in_buf_len = GET_USING_POOL(pdx->TxPool);
  744. #if 0
  745. printk(KERN_ALERT "pos_chars_in_buffer: %d\n", in_buf_len);
  746. #endif
  747. return in_buf_len;
  748. }
  749. /* Our fake UART values */
  750. #define MCR_DTR 0x01
  751. #define MCR_RTS 0x02
  752. #define MCR_LOOP 0x04
  753. #define MSR_CTS 0x08
  754. #define MSR_CD 0x10
  755. #define MSR_RI 0x20
  756. #define MSR_DSR 0x40
  757. #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
  758. static int pos_tiocmget(struct tty_struct *tty, struct file *filp)
  759. #else
  760. static int pos_tiocmget(struct tty_struct *tty)
  761. #endif
  762. {
  763. struct tty_pos *pdx = tty->driver_data;
  764. unsigned int msr, mcr, result;
  765. #if 0
  766. INFO("pos_tiocmget\n");
  767. #endif
  768. if (!pdx)
  769. return -ENODEV;
  770. msr = pdx->msr;
  771. mcr = pdx->mcr;
  772. result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | /* DTR is set */
  773. ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | /* RTS is set */
  774. ((mcr & MCR_LOOP) ? TIOCM_LOOP : 0) | /* LOOP is set */
  775. ((msr & MSR_CTS) ? TIOCM_CTS : 0) | /* CTS is set */
  776. ((msr & MSR_CD) ? TIOCM_CAR : 0) | /* Carrier detect is set */
  777. ((msr & MSR_RI) ? TIOCM_RI : 0) | /* Ring Indicator is set */
  778. ((msr & MSR_DSR) ? TIOCM_DSR : 0); /* DSR is set */
  779. return result;
  780. }
  781. #if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0)
  782. static int pos_tiocmset(struct tty_struct *tty, struct file *filp,
  783. unsigned int set, unsigned int clear)
  784. #else
  785. static int pos_tiocmset(struct tty_struct *tty, unsigned int set,
  786. unsigned int clear)
  787. #endif
  788. {
  789. struct tty_pos *pdx = tty->driver_data;
  790. unsigned int mcr;
  791. if (!pdx)
  792. return -ENODEV;
  793. mcr = pdx->mcr;
  794. if (set & TIOCM_RTS) {
  795. mcr |= MCR_RTS;
  796. }
  797. if (set & TIOCM_DTR) {
  798. mcr |= MCR_DTR; /* mcr |= MCR_RTS; */
  799. }
  800. if (clear & TIOCM_RTS) {
  801. mcr &= ~MCR_RTS;
  802. }
  803. if (clear & TIOCM_DTR) {
  804. mcr &= ~MCR_DTR; /* mcr &= ~MCR_RTS; */
  805. }
  806. /* set the new MCR value in the device */
  807. pdx->mcr = mcr;
  808. return 0;
  809. }
  810. static const struct tty_operations pos_ops = {
  811. .open = pos_open,
  812. .close = pos_close,
  813. .write = pos_write,
  814. .write_room = pos_write_room,
  815. .ioctl = pos_ioctl,
  816. .set_termios = pos_set_termios,
  817. .throttle = pos_throttle,
  818. .unthrottle = pos_unthrottle,
  819. .flush_buffer = pos_flush_buffer,
  820. .chars_in_buffer = pos_chars_in_buffer,
  821. .tiocmget = pos_tiocmget,
  822. .tiocmset = pos_tiocmset,
  823. };
  824. struct tty_driver *pos_tty_driver;
  825. static int pos_usb_probe(struct usb_interface *interface,
  826. const struct usb_device_id *id)
  827. {
  828. struct tty_pos *pdx;
  829. struct usb_host_interface *iface_desc;
  830. struct usb_endpoint_descriptor *endpoint;
  831. int i, retval = -ENOMEM;
  832. for(i=0;i<POS_TTY_MINORS;i++)
  833. {
  834. if (pdx_table[i] == NULL)
  835. break;
  836. }
  837. if(i==POS_TTY_MINORS)
  838. return -ENOMEM;
  839. pdx = kzalloc(sizeof(*pdx), /* GFP_KERNEL */ GFP_ATOMIC);
  840. if (!pdx) {
  841. ERR("OUT OF MEMORY pdx\n");
  842. return -ENOMEM;
  843. }
  844. pdx->BioPack = kzalloc(sizeof(*pdx->BioPack), GFP_ATOMIC);
  845. if (!pdx) {
  846. ERR("OUT OF MEMORY BioPack\n");
  847. return -ENOMEM;
  848. }
  849. printk(KERN_ALERT "ttyPos probe:%s %s,index:%d\n",DRV_VERSION,VERSION_DATE,i);
  850. pdx->devIndex = i;
  851. pdx_table[pdx->devIndex] = pdx;
  852. INIT_POOL_BUFFER(pdx->TxPool);
  853. pdx->timeout_jiffies = 400 * HZ / 1000; /* 400ms */
  854. kref_init(&pdx->kref);
  855. init_waitqueue_head(&pdx->urb_wait);
  856. atomic_set(&pdx->urb_done, 0);
  857. init_waitqueue_head(&pdx->write_wait);
  858. atomic_set(&pdx->write_flag, 0);
  859. init_completion(&pdx->ThreadExit_completion);
  860. pdx->udev = usb_get_dev(interface_to_usbdev(interface));
  861. pdx->interface = interface;
  862. pdx->urb = usb_alloc_urb(0, /* GFP_KERNEL */ GFP_ATOMIC);
  863. if (!pdx->urb) {
  864. retval = -ENOMEM;
  865. ERR("FAILED ALLOC URB!\n");
  866. goto error;
  867. }
  868. iface_desc = interface->cur_altsetting;
  869. for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
  870. endpoint = &iface_desc->endpoint[i].desc;
  871. if (endpoint->bEndpointAddress & 0x80) {
  872. pdx->bulk_in_epAddr = endpoint->bEndpointAddress;
  873. }
  874. else {
  875. pdx->bulk_out_epAddr = endpoint->bEndpointAddress;
  876. }
  877. }
  878. if (!(pdx->bulk_in_epAddr && pdx->bulk_out_epAddr)) {
  879. ERR("COULD NOT FIND BOTH BULK-IN AND BULK-OUT ENDPOINT\n");
  880. }
  881. usb_set_intfdata(interface, pdx);
  882. #ifdef LINUX_VERSION_CODE
  883. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  884. tty_port_register_device(&pos_port[pdx->devIndex], pos_tty_driver,
  885. pdx->devIndex, NULL);
  886. #else
  887. tty_register_device(pos_tty_driver, pdx->devIndex, NULL);
  888. #endif
  889. #endif
  890. dev_info(&interface->dev,
  891. "USB POS device now attached to PosUsb-%d",
  892. interface->minor);
  893. return 0;
  894. error:
  895. if (pdx) {
  896. kref_put(&pdx->kref, pos_delete);
  897. }
  898. ERR("--pos_probe error\n");
  899. return retval;
  900. }
  901. static void pos_usb_disconnect(struct usb_interface *interface)
  902. {
  903. struct tty_pos *pdx;
  904. #if 0
  905. INFO("++pos_disconnect\n");
  906. #endif
  907. pdx = usb_get_intfdata(interface);
  908. if (pdx == NULL)
  909. return;
  910. tty_unregister_device(pos_tty_driver, pdx->devIndex);
  911. if (pdx->ThreadState == THREAD_CREATED) {
  912. pdx->ThreadState = THREAD_CLOSE;
  913. #if 0
  914. INFO("Wait thread exit\n");
  915. #endif
  916. wait_for_completion(&pdx->ThreadExit_completion);
  917. #if 0
  918. INFO("Wait thread exit success!\n");
  919. #endif
  920. }
  921. pdx->ThreadState = THREAD_INIT;
  922. usb_set_intfdata(interface, NULL);
  923. #if 0
  924. usb_deregister_dev(interface, &pos_class);
  925. #endif
  926. pdx->interface = NULL;
  927. kref_put(&pdx->kref, pos_delete);
  928. #if 0
  929. INFO("--pos_disconnect\n");
  930. #endif
  931. }
  932. #if 1
  933. static int pos_usb_suspend(struct usb_interface *intf, pm_message_t message)
  934. {
  935. // printk(KERN_ALERT "pos_suspend\n");
  936. return 0;
  937. }
  938. static int pos_usb_resume(struct usb_interface *intf)
  939. {
  940. // printk(KERN_ALERT "pos_resume\n");
  941. return 0;
  942. }
  943. #endif
  944. #ifdef OLD_USB_DRIVER
  945. static void pos_usb_pre_reset(struct usb_interface *intf)
  946. {
  947. /* struct tty_pos *pdx = usb_get_intfdata(intf); */
  948. #if 0
  949. INFO("pos_pre_reset\n");
  950. #endif
  951. }
  952. #else
  953. static int pos_usb_pre_reset(struct usb_interface *intf)
  954. {
  955. /* struct tty_pos *pdx = usb_get_intfdata(intf); */
  956. #if 0
  957. INFO("pos_pre_reset\n");
  958. #endif
  959. return 0;
  960. }
  961. #endif
  962. #ifdef OLD_USB_DRIVER
  963. static void pos_usb_post_reset(struct usb_interface *intf)
  964. {
  965. #if 0
  966. INFO("pos_post_reset\n");
  967. #endif
  968. }
  969. #else
  970. static int pos_usb_post_reset(struct usb_interface *intf)
  971. {
  972. #if 0
  973. INFO("pos_post_reset\n");
  974. #endif
  975. return 0;
  976. }
  977. #endif
  978. static struct usb_driver pos_usb_driver = {
  979. .name = "PosUsb",
  980. .probe = pos_usb_probe,
  981. .disconnect = pos_usb_disconnect,
  982. #if 1
  983. .suspend = pos_usb_suspend,
  984. .resume = pos_usb_resume,
  985. .supports_autosuspend = 1,
  986. #endif
  987. .pre_reset = pos_usb_pre_reset,
  988. .post_reset = pos_usb_post_reset,
  989. .id_table = pos_usb_table,
  990. };
  991. /* Compatible with TTY_DRIVER_DYNAMIC_DEV and TTY_DRIVER_NO_DEVFS */
  992. #define TTY_USB_DEV 0x0008
  993. #ifdef LINUX_VERSION_CODE
  994. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  995. static int pos_port_activate(struct tty_port *port, struct tty_struct *tty)
  996. {
  997. return 0;
  998. }
  999. static void pos_port_shutdown(struct tty_port *port)
  1000. {
  1001. }
  1002. static int pos_carrier_raised(struct tty_port *port)
  1003. {
  1004. return 0;
  1005. }
  1006. static void pos_dtr_rts(struct tty_port *port, int onoff)
  1007. {
  1008. }
  1009. static const struct tty_port_operations pos_port_ops = {
  1010. .activate = pos_port_activate,
  1011. .shutdown = pos_port_shutdown,
  1012. .carrier_raised = pos_carrier_raised,
  1013. .dtr_rts = pos_dtr_rts,
  1014. };
  1015. #endif
  1016. #endif
  1017. static int __init pos_tty_init(void)
  1018. {
  1019. int result,i;
  1020. printk(KERN_ALERT "ttyPos:%s %s\n",DRV_VERSION,VERSION_DATE);
  1021. for(i=0;i<POS_TTY_MINORS;i++)
  1022. pdx_table[i] = NULL;
  1023. pos_tty_driver = alloc_tty_driver(POS_TTY_MINORS);
  1024. if (!pos_tty_driver)
  1025. return -ENOMEM;
  1026. pos_tty_driver->owner = THIS_MODULE;
  1027. pos_tty_driver->driver_name = "usbpos";
  1028. pos_tty_driver->name = "ttyPos";
  1029. pos_tty_driver->major = 0;//POS_TTY_MAJOR;//The major number will be chosen dynamically
  1030. pos_tty_driver->minor_start = 0;
  1031. pos_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
  1032. pos_tty_driver->subtype = SERIAL_TYPE_NORMAL;
  1033. pos_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_USB_DEV;
  1034. pos_tty_driver->init_termios = tty_std_termios;
  1035. pos_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD
  1036. | HUPCL | CLOCAL;
  1037. tty_set_operations(pos_tty_driver, &pos_ops);
  1038. #ifdef LINUX_VERSION_CODE
  1039. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  1040. for (i = 0; i < POS_TTY_MINORS; i++)
  1041. {
  1042. tty_port_init(&pos_port[i]);
  1043. pos_port[i].ops = &pos_port_ops;
  1044. pos_port[i].close_delay = HZ / 2; /* .5 seconds */
  1045. pos_port[i].closing_wait = 30 * HZ;/* 30 seconds */
  1046. }
  1047. #endif
  1048. #endif
  1049. result = tty_register_driver(pos_tty_driver);
  1050. if (result) {
  1051. ERR("%s - tty_register_driver failed\n", __func__);
  1052. goto byebye1;
  1053. }
  1054. #ifdef LINUX_VERSION_CODE
  1055. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  1056. for (i = 0; i < POS_TTY_MINORS; i++)
  1057. tty_port_destroy(&pos_port[i]);
  1058. #endif
  1059. #endif
  1060. result = usb_register(&pos_usb_driver);
  1061. if (result) {
  1062. ERR("%s - usb_register failed; err: %d\n",__func__, result);
  1063. goto byebye2;
  1064. }
  1065. return 0;
  1066. byebye2:
  1067. tty_unregister_driver(pos_tty_driver);
  1068. byebye1:
  1069. put_tty_driver(pos_tty_driver);
  1070. return result;
  1071. }
  1072. static void __exit pos_tty_exit(void)
  1073. {
  1074. unsigned int i;
  1075. usb_deregister(&pos_usb_driver);
  1076. tty_unregister_driver(pos_tty_driver);
  1077. put_tty_driver(pos_tty_driver);
  1078. #ifdef LINUX_VERSION_CODE
  1079. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0))
  1080. for (i = 0; i < POS_TTY_MINORS; i++)
  1081. tty_port_destroy(&pos_port[i]);
  1082. #endif
  1083. #endif
  1084. INFO("pos_tty_exit\n");
  1085. }
  1086. module_init(pos_tty_init);
  1087. module_exit(pos_tty_exit);
  1088. MODULE_LICENSE("GPL");
  1089. MODULE_ALIAS_LDISC(N_SLIP);