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