asyncdata.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587
  1. /*
  2. * Common data handling layer for ser_gigaset and usb_gigaset
  3. *
  4. * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
  5. * Hansjoerg Lipp <hjlipp@web.de>,
  6. * Stefan Eilers.
  7. *
  8. * =====================================================================
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License as
  11. * published by the Free Software Foundation; either version 2 of
  12. * the License, or (at your option) any later version.
  13. * =====================================================================
  14. */
  15. #include "gigaset.h"
  16. #include <linux/crc-ccitt.h>
  17. //#define GIG_M10x_STUFF_VOICE_DATA
  18. /* check if byte must be stuffed/escaped
  19. * I'm not sure which data should be encoded.
  20. * Therefore I will go the hard way and decode every value
  21. * less than 0x20, the flag sequence and the control escape char.
  22. */
  23. static inline int muststuff(unsigned char c)
  24. {
  25. if (c < PPP_TRANS) return 1;
  26. if (c == PPP_FLAG) return 1;
  27. if (c == PPP_ESCAPE) return 1;
  28. /* other possible candidates: */
  29. /* 0x91: XON with parity set */
  30. /* 0x93: XOFF with parity set */
  31. return 0;
  32. }
  33. /* == data input =========================================================== */
  34. /* process a block of received bytes in command mode (modem response)
  35. * Return value:
  36. * number of processed bytes
  37. */
  38. static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
  39. struct inbuf_t *inbuf)
  40. {
  41. struct cardstate *cs = inbuf->cs;
  42. unsigned cbytes = cs->cbytes;
  43. int inputstate = inbuf->inputstate;
  44. int startbytes = numbytes;
  45. for (;;) {
  46. cs->respdata[cbytes] = c;
  47. if (c == 10 || c == 13) {
  48. gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
  49. __func__, cbytes);
  50. cs->cbytes = cbytes;
  51. gigaset_handle_modem_response(cs); /* can change
  52. cs->dle */
  53. cbytes = 0;
  54. if (cs->dle &&
  55. !(inputstate & INS_DLE_command)) {
  56. inputstate &= ~INS_command;
  57. break;
  58. }
  59. } else {
  60. /* advance in line buffer, checking for overflow */
  61. if (cbytes < MAX_RESP_SIZE - 1)
  62. cbytes++;
  63. else
  64. dev_warn(cs->dev, "response too large\n");
  65. }
  66. if (!numbytes)
  67. break;
  68. c = *src++;
  69. --numbytes;
  70. if (c == DLE_FLAG &&
  71. (cs->dle || inputstate & INS_DLE_command)) {
  72. inputstate |= INS_DLE_char;
  73. break;
  74. }
  75. }
  76. cs->cbytes = cbytes;
  77. inbuf->inputstate = inputstate;
  78. return startbytes - numbytes;
  79. }
  80. /* process a block of received bytes in lock mode (tty i/f)
  81. * Return value:
  82. * number of processed bytes
  83. */
  84. static inline int lock_loop(unsigned char *src, int numbytes,
  85. struct inbuf_t *inbuf)
  86. {
  87. struct cardstate *cs = inbuf->cs;
  88. gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
  89. numbytes, src);
  90. gigaset_if_receive(cs, src, numbytes);
  91. return numbytes;
  92. }
  93. /* process a block of received bytes in HDLC data mode
  94. * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
  95. * When a frame is complete, check the FCS and pass valid frames to the LL.
  96. * If DLE is encountered, return immediately to let the caller handle it.
  97. * Return value:
  98. * number of processed bytes
  99. * numbytes (all bytes processed) on error --FIXME
  100. */
  101. static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
  102. struct inbuf_t *inbuf)
  103. {
  104. struct cardstate *cs = inbuf->cs;
  105. struct bc_state *bcs = inbuf->bcs;
  106. int inputstate = bcs->inputstate;
  107. __u16 fcs = bcs->fcs;
  108. struct sk_buff *skb = bcs->skb;
  109. unsigned char error;
  110. struct sk_buff *compskb;
  111. int startbytes = numbytes;
  112. int l;
  113. if (unlikely(inputstate & INS_byte_stuff)) {
  114. inputstate &= ~INS_byte_stuff;
  115. goto byte_stuff;
  116. }
  117. for (;;) {
  118. if (unlikely(c == PPP_ESCAPE)) {
  119. if (unlikely(!numbytes)) {
  120. inputstate |= INS_byte_stuff;
  121. break;
  122. }
  123. c = *src++;
  124. --numbytes;
  125. if (unlikely(c == DLE_FLAG &&
  126. (cs->dle ||
  127. inbuf->inputstate & INS_DLE_command))) {
  128. inbuf->inputstate |= INS_DLE_char;
  129. inputstate |= INS_byte_stuff;
  130. break;
  131. }
  132. byte_stuff:
  133. c ^= PPP_TRANS;
  134. #ifdef CONFIG_GIGASET_DEBUG
  135. if (unlikely(!muststuff(c)))
  136. gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
  137. #endif
  138. } else if (unlikely(c == PPP_FLAG)) {
  139. if (unlikely(inputstate & INS_skip_frame)) {
  140. if (!(inputstate & INS_have_data)) { /* 7E 7E */
  141. #ifdef CONFIG_GIGASET_DEBUG
  142. ++bcs->emptycount;
  143. #endif
  144. } else
  145. gig_dbg(DEBUG_HDLC,
  146. "7e----------------------------");
  147. /* end of frame */
  148. error = 1;
  149. gigaset_rcv_error(NULL, cs, bcs);
  150. } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
  151. #ifdef CONFIG_GIGASET_DEBUG
  152. ++bcs->emptycount;
  153. #endif
  154. break;
  155. } else {
  156. gig_dbg(DEBUG_HDLC,
  157. "7e----------------------------");
  158. /* end of frame */
  159. error = 0;
  160. if (unlikely(fcs != PPP_GOODFCS)) {
  161. dev_err(cs->dev,
  162. "Packet checksum at %lu failed, "
  163. "packet is corrupted (%u bytes)!\n",
  164. bcs->rcvbytes, skb->len);
  165. compskb = NULL;
  166. gigaset_rcv_error(compskb, cs, bcs);
  167. error = 1;
  168. } else {
  169. if (likely((l = skb->len) > 2)) {
  170. skb->tail -= 2;
  171. skb->len -= 2;
  172. } else {
  173. dev_kfree_skb(skb);
  174. skb = NULL;
  175. inputstate |= INS_skip_frame;
  176. if (l == 1) {
  177. dev_err(cs->dev,
  178. "invalid packet size (1)!\n");
  179. error = 1;
  180. gigaset_rcv_error(NULL,
  181. cs, bcs);
  182. }
  183. }
  184. if (likely(!(error ||
  185. (inputstate &
  186. INS_skip_frame)))) {
  187. gigaset_rcv_skb(skb, cs, bcs);
  188. }
  189. }
  190. }
  191. if (unlikely(error))
  192. if (skb)
  193. dev_kfree_skb(skb);
  194. fcs = PPP_INITFCS;
  195. inputstate &= ~(INS_have_data | INS_skip_frame);
  196. if (unlikely(bcs->ignore)) {
  197. inputstate |= INS_skip_frame;
  198. skb = NULL;
  199. } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
  200. skb_reserve(skb, HW_HDR_LEN);
  201. } else {
  202. dev_warn(cs->dev,
  203. "could not allocate new skb\n");
  204. inputstate |= INS_skip_frame;
  205. }
  206. break;
  207. #ifdef CONFIG_GIGASET_DEBUG
  208. } else if (unlikely(muststuff(c))) {
  209. /* Should not happen. Possible after ZDLE=1<CR><LF>. */
  210. gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
  211. #endif
  212. }
  213. /* add character */
  214. #ifdef CONFIG_GIGASET_DEBUG
  215. if (unlikely(!(inputstate & INS_have_data))) {
  216. gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
  217. bcs->emptycount);
  218. bcs->emptycount = 0;
  219. }
  220. #endif
  221. inputstate |= INS_have_data;
  222. if (likely(!(inputstate & INS_skip_frame))) {
  223. if (unlikely(skb->len == SBUFSIZE)) {
  224. dev_warn(cs->dev, "received packet too long\n");
  225. dev_kfree_skb_any(skb);
  226. skb = NULL;
  227. inputstate |= INS_skip_frame;
  228. break;
  229. }
  230. *__skb_put(skb, 1) = c;
  231. fcs = crc_ccitt_byte(fcs, c);
  232. }
  233. if (unlikely(!numbytes))
  234. break;
  235. c = *src++;
  236. --numbytes;
  237. if (unlikely(c == DLE_FLAG &&
  238. (cs->dle ||
  239. inbuf->inputstate & INS_DLE_command))) {
  240. inbuf->inputstate |= INS_DLE_char;
  241. break;
  242. }
  243. }
  244. bcs->inputstate = inputstate;
  245. bcs->fcs = fcs;
  246. bcs->skb = skb;
  247. return startbytes - numbytes;
  248. }
  249. /* process a block of received bytes in transparent data mode
  250. * Invert bytes, undoing byte stuffing and watching for DLE escapes.
  251. * If DLE is encountered, return immediately to let the caller handle it.
  252. * Return value:
  253. * number of processed bytes
  254. * numbytes (all bytes processed) on error --FIXME
  255. */
  256. static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
  257. struct inbuf_t *inbuf)
  258. {
  259. struct cardstate *cs = inbuf->cs;
  260. struct bc_state *bcs = inbuf->bcs;
  261. int inputstate = bcs->inputstate;
  262. struct sk_buff *skb = bcs->skb;
  263. int startbytes = numbytes;
  264. for (;;) {
  265. /* add character */
  266. inputstate |= INS_have_data;
  267. if (likely(!(inputstate & INS_skip_frame))) {
  268. if (unlikely(skb->len == SBUFSIZE)) {
  269. //FIXME just pass skb up and allocate a new one
  270. dev_warn(cs->dev, "received packet too long\n");
  271. dev_kfree_skb_any(skb);
  272. skb = NULL;
  273. inputstate |= INS_skip_frame;
  274. break;
  275. }
  276. *__skb_put(skb, 1) = gigaset_invtab[c];
  277. }
  278. if (unlikely(!numbytes))
  279. break;
  280. c = *src++;
  281. --numbytes;
  282. if (unlikely(c == DLE_FLAG &&
  283. (cs->dle ||
  284. inbuf->inputstate & INS_DLE_command))) {
  285. inbuf->inputstate |= INS_DLE_char;
  286. break;
  287. }
  288. }
  289. /* pass data up */
  290. if (likely(inputstate & INS_have_data)) {
  291. if (likely(!(inputstate & INS_skip_frame))) {
  292. gigaset_rcv_skb(skb, cs, bcs);
  293. }
  294. inputstate &= ~(INS_have_data | INS_skip_frame);
  295. if (unlikely(bcs->ignore)) {
  296. inputstate |= INS_skip_frame;
  297. skb = NULL;
  298. } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
  299. != NULL)) {
  300. skb_reserve(skb, HW_HDR_LEN);
  301. } else {
  302. dev_warn(cs->dev, "could not allocate new skb\n");
  303. inputstate |= INS_skip_frame;
  304. }
  305. }
  306. bcs->inputstate = inputstate;
  307. bcs->skb = skb;
  308. return startbytes - numbytes;
  309. }
  310. /* process a block of data received from the device
  311. */
  312. void gigaset_m10x_input(struct inbuf_t *inbuf)
  313. {
  314. struct cardstate *cs;
  315. unsigned tail, head, numbytes;
  316. unsigned char *src, c;
  317. int procbytes;
  318. head = atomic_read(&inbuf->head);
  319. tail = atomic_read(&inbuf->tail);
  320. gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
  321. if (head != tail) {
  322. cs = inbuf->cs;
  323. src = inbuf->data + head;
  324. numbytes = (head > tail ? RBUFSIZE : tail) - head;
  325. gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
  326. while (numbytes) {
  327. if (atomic_read(&cs->mstate) == MS_LOCKED) {
  328. procbytes = lock_loop(src, numbytes, inbuf);
  329. src += procbytes;
  330. numbytes -= procbytes;
  331. } else {
  332. c = *src++;
  333. --numbytes;
  334. if (c == DLE_FLAG && (cs->dle ||
  335. inbuf->inputstate & INS_DLE_command)) {
  336. if (!(inbuf->inputstate & INS_DLE_char)) {
  337. inbuf->inputstate |= INS_DLE_char;
  338. goto nextbyte;
  339. }
  340. /* <DLE> <DLE> => <DLE> in data stream */
  341. inbuf->inputstate &= ~INS_DLE_char;
  342. }
  343. if (!(inbuf->inputstate & INS_DLE_char)) {
  344. /* FIXME use function pointers? */
  345. if (inbuf->inputstate & INS_command)
  346. procbytes = cmd_loop(c, src, numbytes, inbuf);
  347. else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
  348. procbytes = hdlc_loop(c, src, numbytes, inbuf);
  349. else
  350. procbytes = iraw_loop(c, src, numbytes, inbuf);
  351. src += procbytes;
  352. numbytes -= procbytes;
  353. } else { /* DLE char */
  354. inbuf->inputstate &= ~INS_DLE_char;
  355. switch (c) {
  356. case 'X': /*begin of command*/
  357. #ifdef CONFIG_GIGASET_DEBUG
  358. if (inbuf->inputstate & INS_command)
  359. dev_err(cs->dev,
  360. "received <DLE> 'X' in command mode\n");
  361. #endif
  362. inbuf->inputstate |=
  363. INS_command | INS_DLE_command;
  364. break;
  365. case '.': /*end of command*/
  366. #ifdef CONFIG_GIGASET_DEBUG
  367. if (!(inbuf->inputstate & INS_command))
  368. dev_err(cs->dev,
  369. "received <DLE> '.' in hdlc mode\n");
  370. #endif
  371. inbuf->inputstate &= cs->dle ?
  372. ~(INS_DLE_command|INS_command)
  373. : ~INS_DLE_command;
  374. break;
  375. //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
  376. default:
  377. dev_err(cs->dev,
  378. "received 0x10 0x%02x!\n",
  379. (int) c);
  380. /* FIXME: reset driver?? */
  381. }
  382. }
  383. }
  384. nextbyte:
  385. if (!numbytes) {
  386. /* end of buffer, check for wrap */
  387. if (head > tail) {
  388. head = 0;
  389. src = inbuf->data;
  390. numbytes = tail;
  391. } else {
  392. head = tail;
  393. break;
  394. }
  395. }
  396. }
  397. gig_dbg(DEBUG_INTR, "setting head to %u", head);
  398. atomic_set(&inbuf->head, head);
  399. }
  400. }
  401. /* == data output ========================================================== */
  402. /* Encoding of a PPP packet into an octet stuffed HDLC frame
  403. * with FCS, opening and closing flags.
  404. * parameters:
  405. * skb skb containing original packet (freed upon return)
  406. * head number of headroom bytes to allocate in result skb
  407. * tail number of tailroom bytes to allocate in result skb
  408. * Return value:
  409. * pointer to newly allocated skb containing the result frame
  410. */
  411. static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
  412. {
  413. struct sk_buff *hdlc_skb;
  414. __u16 fcs;
  415. unsigned char c;
  416. unsigned char *cp;
  417. int len;
  418. unsigned int stuf_cnt;
  419. stuf_cnt = 0;
  420. fcs = PPP_INITFCS;
  421. cp = skb->data;
  422. len = skb->len;
  423. while (len--) {
  424. if (muststuff(*cp))
  425. stuf_cnt++;
  426. fcs = crc_ccitt_byte(fcs, *cp++);
  427. }
  428. fcs ^= 0xffff; /* complement */
  429. /* size of new buffer: original size + number of stuffing bytes
  430. * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
  431. */
  432. hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
  433. if (!hdlc_skb) {
  434. dev_kfree_skb(skb);
  435. return NULL;
  436. }
  437. skb_reserve(hdlc_skb, head);
  438. /* Copy acknowledge request into new skb */
  439. memcpy(hdlc_skb->head, skb->head, 2);
  440. /* Add flag sequence in front of everything.. */
  441. *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
  442. /* Perform byte stuffing while copying data. */
  443. while (skb->len--) {
  444. if (muststuff(*skb->data)) {
  445. *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
  446. *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
  447. } else
  448. *(skb_put(hdlc_skb, 1)) = *skb->data++;
  449. }
  450. /* Finally add FCS (byte stuffed) and flag sequence */
  451. c = (fcs & 0x00ff); /* least significant byte first */
  452. if (muststuff(c)) {
  453. *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
  454. c ^= PPP_TRANS;
  455. }
  456. *(skb_put(hdlc_skb, 1)) = c;
  457. c = ((fcs >> 8) & 0x00ff);
  458. if (muststuff(c)) {
  459. *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
  460. c ^= PPP_TRANS;
  461. }
  462. *(skb_put(hdlc_skb, 1)) = c;
  463. *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
  464. dev_kfree_skb(skb);
  465. return hdlc_skb;
  466. }
  467. /* Encoding of a raw packet into an octet stuffed bit inverted frame
  468. * parameters:
  469. * skb skb containing original packet (freed upon return)
  470. * head number of headroom bytes to allocate in result skb
  471. * tail number of tailroom bytes to allocate in result skb
  472. * Return value:
  473. * pointer to newly allocated skb containing the result frame
  474. */
  475. static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
  476. {
  477. struct sk_buff *iraw_skb;
  478. unsigned char c;
  479. unsigned char *cp;
  480. int len;
  481. /* worst case: every byte must be stuffed */
  482. iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
  483. if (!iraw_skb) {
  484. dev_kfree_skb(skb);
  485. return NULL;
  486. }
  487. skb_reserve(iraw_skb, head);
  488. cp = skb->data;
  489. len = skb->len;
  490. while (len--) {
  491. c = gigaset_invtab[*cp++];
  492. if (c == DLE_FLAG)
  493. *(skb_put(iraw_skb, 1)) = c;
  494. *(skb_put(iraw_skb, 1)) = c;
  495. }
  496. dev_kfree_skb(skb);
  497. return iraw_skb;
  498. }
  499. /* gigaset_send_skb
  500. * called by common.c to queue an skb for sending
  501. * and start transmission if necessary
  502. * parameters:
  503. * B Channel control structure
  504. * skb
  505. * Return value:
  506. * number of bytes accepted for sending
  507. * (skb->len if ok, 0 if out of buffer space)
  508. * or error code (< 0, eg. -EINVAL)
  509. */
  510. int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
  511. {
  512. unsigned len = skb->len;
  513. unsigned long flags;
  514. if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
  515. skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
  516. else
  517. skb = iraw_encode(skb, HW_HDR_LEN, 0);
  518. if (!skb) {
  519. err("unable to allocate memory for encoding!\n");
  520. return -ENOMEM;
  521. }
  522. skb_queue_tail(&bcs->squeue, skb);
  523. spin_lock_irqsave(&bcs->cs->lock, flags);
  524. if (bcs->cs->connected)
  525. tasklet_schedule(&bcs->cs->write_tasklet);
  526. spin_unlock_irqrestore(&bcs->cs->lock, flags);
  527. return len; /* ok so far */
  528. }