2 * Common data handling layer for ser_gigaset and usb_gigaset
4 * Copyright (c) 2005 by Tilman Schmidt <tilman@imap.cc>,
5 * Hansjoerg Lipp <hjlipp@web.de>,
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 * =====================================================================
16 /* not set by Kbuild when building both ser_gigaset and usb_gigaset */
17 #ifndef KBUILD_MODNAME
18 #define KBUILD_MODNAME "asy_gigaset"
22 #include <linux/crc-ccitt.h>
23 #include <linux/bitrev.h>
25 //#define GIG_M10x_STUFF_VOICE_DATA
27 /* check if byte must be stuffed/escaped
28 * I'm not sure which data should be encoded.
29 * Therefore I will go the hard way and decode every value
30 * less than 0x20, the flag sequence and the control escape char.
32 static inline int muststuff(unsigned char c)
34 if (c < PPP_TRANS) return 1;
35 if (c == PPP_FLAG) return 1;
36 if (c == PPP_ESCAPE) return 1;
37 /* other possible candidates: */
38 /* 0x91: XON with parity set */
39 /* 0x93: XOFF with parity set */
43 /* == data input =========================================================== */
45 /* process a block of received bytes in command mode (modem response)
47 * number of processed bytes
49 static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
50 struct inbuf_t *inbuf)
52 struct cardstate *cs = inbuf->cs;
53 unsigned cbytes = cs->cbytes;
54 int inputstate = inbuf->inputstate;
55 int startbytes = numbytes;
58 cs->respdata[cbytes] = c;
59 if (c == 10 || c == 13) {
60 gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
63 gigaset_handle_modem_response(cs); /* can change
68 !(inputstate & INS_DLE_command)) {
69 inputstate &= ~INS_command;
73 /* advance in line buffer, checking for overflow */
74 if (cbytes < MAX_RESP_SIZE - 1)
77 dev_warn(cs->dev, "response too large\n");
85 (cs->dle || inputstate & INS_DLE_command)) {
86 inputstate |= INS_DLE_char;
92 inbuf->inputstate = inputstate;
94 return startbytes - numbytes;
97 /* process a block of received bytes in lock mode (tty i/f)
99 * number of processed bytes
101 static inline int lock_loop(unsigned char *src, int numbytes,
102 struct inbuf_t *inbuf)
104 struct cardstate *cs = inbuf->cs;
106 gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
108 gigaset_if_receive(cs, src, numbytes);
113 /* process a block of received bytes in HDLC data mode
114 * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
115 * When a frame is complete, check the FCS and pass valid frames to the LL.
116 * If DLE is encountered, return immediately to let the caller handle it.
118 * number of processed bytes
119 * numbytes (all bytes processed) on error --FIXME
121 static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
122 struct inbuf_t *inbuf)
124 struct cardstate *cs = inbuf->cs;
125 struct bc_state *bcs = inbuf->bcs;
126 int inputstate = bcs->inputstate;
127 __u16 fcs = bcs->fcs;
128 struct sk_buff *skb = bcs->skb;
130 struct sk_buff *compskb;
131 int startbytes = numbytes;
134 if (unlikely(inputstate & INS_byte_stuff)) {
135 inputstate &= ~INS_byte_stuff;
139 if (unlikely(c == PPP_ESCAPE)) {
140 if (unlikely(!numbytes)) {
141 inputstate |= INS_byte_stuff;
146 if (unlikely(c == DLE_FLAG &&
148 inbuf->inputstate & INS_DLE_command))) {
149 inbuf->inputstate |= INS_DLE_char;
150 inputstate |= INS_byte_stuff;
155 #ifdef CONFIG_GIGASET_DEBUG
156 if (unlikely(!muststuff(c)))
157 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
159 } else if (unlikely(c == PPP_FLAG)) {
160 if (unlikely(inputstate & INS_skip_frame)) {
161 if (!(inputstate & INS_have_data)) { /* 7E 7E */
162 #ifdef CONFIG_GIGASET_DEBUG
167 "7e----------------------------");
171 gigaset_rcv_error(NULL, cs, bcs);
172 } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
173 #ifdef CONFIG_GIGASET_DEBUG
179 "7e----------------------------");
184 if (unlikely(fcs != PPP_GOODFCS)) {
186 "Packet checksum at %lu failed, "
187 "packet is corrupted (%u bytes)!\n",
188 bcs->rcvbytes, skb->len);
190 gigaset_rcv_error(compskb, cs, bcs);
193 if (likely((l = skb->len) > 2)) {
199 inputstate |= INS_skip_frame;
202 "invalid packet size (1)!\n");
204 gigaset_rcv_error(NULL,
208 if (likely(!(error ||
211 gigaset_rcv_skb(skb, cs, bcs);
221 inputstate &= ~(INS_have_data | INS_skip_frame);
222 if (unlikely(bcs->ignore)) {
223 inputstate |= INS_skip_frame;
225 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
226 skb_reserve(skb, HW_HDR_LEN);
229 "could not allocate new skb\n");
230 inputstate |= INS_skip_frame;
234 #ifdef CONFIG_GIGASET_DEBUG
235 } else if (unlikely(muststuff(c))) {
236 /* Should not happen. Possible after ZDLE=1<CR><LF>. */
237 gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
243 #ifdef CONFIG_GIGASET_DEBUG
244 if (unlikely(!(inputstate & INS_have_data))) {
245 gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
251 inputstate |= INS_have_data;
253 if (likely(!(inputstate & INS_skip_frame))) {
254 if (unlikely(skb->len == SBUFSIZE)) {
255 dev_warn(cs->dev, "received packet too long\n");
256 dev_kfree_skb_any(skb);
258 inputstate |= INS_skip_frame;
261 *__skb_put(skb, 1) = c;
262 fcs = crc_ccitt_byte(fcs, c);
265 if (unlikely(!numbytes))
269 if (unlikely(c == DLE_FLAG &&
271 inbuf->inputstate & INS_DLE_command))) {
272 inbuf->inputstate |= INS_DLE_char;
276 bcs->inputstate = inputstate;
279 return startbytes - numbytes;
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.
286 * number of processed bytes
287 * numbytes (all bytes processed) on error --FIXME
289 static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
290 struct inbuf_t *inbuf)
292 struct cardstate *cs = inbuf->cs;
293 struct bc_state *bcs = inbuf->bcs;
294 int inputstate = bcs->inputstate;
295 struct sk_buff *skb = bcs->skb;
296 int startbytes = numbytes;
300 inputstate |= INS_have_data;
302 if (likely(!(inputstate & INS_skip_frame))) {
303 if (unlikely(skb->len == SBUFSIZE)) {
304 //FIXME just pass skb up and allocate a new one
305 dev_warn(cs->dev, "received packet too long\n");
306 dev_kfree_skb_any(skb);
308 inputstate |= INS_skip_frame;
311 *__skb_put(skb, 1) = bitrev8(c);
314 if (unlikely(!numbytes))
318 if (unlikely(c == DLE_FLAG &&
320 inbuf->inputstate & INS_DLE_command))) {
321 inbuf->inputstate |= INS_DLE_char;
327 if (likely(inputstate & INS_have_data)) {
328 if (likely(!(inputstate & INS_skip_frame))) {
329 gigaset_rcv_skb(skb, cs, bcs);
331 inputstate &= ~(INS_have_data | INS_skip_frame);
332 if (unlikely(bcs->ignore)) {
333 inputstate |= INS_skip_frame;
335 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
337 skb_reserve(skb, HW_HDR_LEN);
339 dev_warn(cs->dev, "could not allocate new skb\n");
340 inputstate |= INS_skip_frame;
344 bcs->inputstate = inputstate;
346 return startbytes - numbytes;
349 /* process a block of data received from the device
351 void gigaset_m10x_input(struct inbuf_t *inbuf)
353 struct cardstate *cs;
354 unsigned tail, head, numbytes;
355 unsigned char *src, c;
358 head = atomic_read(&inbuf->head);
359 tail = atomic_read(&inbuf->tail);
360 gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
364 src = inbuf->data + head;
365 numbytes = (head > tail ? RBUFSIZE : tail) - head;
366 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
369 if (atomic_read(&cs->mstate) == MS_LOCKED) {
370 procbytes = lock_loop(src, numbytes, inbuf);
372 numbytes -= procbytes;
376 if (c == DLE_FLAG && (cs->dle ||
377 inbuf->inputstate & INS_DLE_command)) {
378 if (!(inbuf->inputstate & INS_DLE_char)) {
379 inbuf->inputstate |= INS_DLE_char;
382 /* <DLE> <DLE> => <DLE> in data stream */
383 inbuf->inputstate &= ~INS_DLE_char;
386 if (!(inbuf->inputstate & INS_DLE_char)) {
388 /* FIXME use function pointers? */
389 if (inbuf->inputstate & INS_command)
390 procbytes = cmd_loop(c, src, numbytes, inbuf);
391 else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
392 procbytes = hdlc_loop(c, src, numbytes, inbuf);
394 procbytes = iraw_loop(c, src, numbytes, inbuf);
397 numbytes -= procbytes;
398 } else { /* DLE char */
399 inbuf->inputstate &= ~INS_DLE_char;
401 case 'X': /*begin of command*/
402 #ifdef CONFIG_GIGASET_DEBUG
403 if (inbuf->inputstate & INS_command)
405 "received <DLE> 'X' in command mode\n");
408 INS_command | INS_DLE_command;
410 case '.': /*end of command*/
411 #ifdef CONFIG_GIGASET_DEBUG
412 if (!(inbuf->inputstate & INS_command))
414 "received <DLE> '.' in hdlc mode\n");
416 inbuf->inputstate &= cs->dle ?
417 ~(INS_DLE_command|INS_command)
420 //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
423 "received 0x10 0x%02x!\n",
425 /* FIXME: reset driver?? */
431 /* end of buffer, check for wrap */
443 gig_dbg(DEBUG_INTR, "setting head to %u", head);
444 atomic_set(&inbuf->head, head);
449 /* == data output ========================================================== */
451 /* Encoding of a PPP packet into an octet stuffed HDLC frame
452 * with FCS, opening and closing flags.
454 * skb skb containing original packet (freed upon return)
455 * head number of headroom bytes to allocate in result skb
456 * tail number of tailroom bytes to allocate in result skb
458 * pointer to newly allocated skb containing the result frame
460 static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
462 struct sk_buff *hdlc_skb;
467 unsigned int stuf_cnt;
476 fcs = crc_ccitt_byte(fcs, *cp++);
478 fcs ^= 0xffff; /* complement */
480 /* size of new buffer: original size + number of stuffing bytes
481 * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
483 hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
488 skb_reserve(hdlc_skb, head);
490 /* Copy acknowledge request into new skb */
491 memcpy(hdlc_skb->head, skb->head, 2);
493 /* Add flag sequence in front of everything.. */
494 *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
496 /* Perform byte stuffing while copying data. */
498 if (muststuff(*skb->data)) {
499 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
500 *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
502 *(skb_put(hdlc_skb, 1)) = *skb->data++;
505 /* Finally add FCS (byte stuffed) and flag sequence */
506 c = (fcs & 0x00ff); /* least significant byte first */
508 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
511 *(skb_put(hdlc_skb, 1)) = c;
513 c = ((fcs >> 8) & 0x00ff);
515 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
518 *(skb_put(hdlc_skb, 1)) = c;
520 *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
526 /* Encoding of a raw packet into an octet stuffed bit inverted frame
528 * skb skb containing original packet (freed upon return)
529 * head number of headroom bytes to allocate in result skb
530 * tail number of tailroom bytes to allocate in result skb
532 * pointer to newly allocated skb containing the result frame
534 static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
536 struct sk_buff *iraw_skb;
541 /* worst case: every byte must be stuffed */
542 iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
547 skb_reserve(iraw_skb, head);
554 *(skb_put(iraw_skb, 1)) = c;
555 *(skb_put(iraw_skb, 1)) = c;
562 * called by common.c to queue an skb for sending
563 * and start transmission if necessary
565 * B Channel control structure
568 * number of bytes accepted for sending
569 * (skb->len if ok, 0 if out of buffer space)
570 * or error code (< 0, eg. -EINVAL)
572 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
574 unsigned len = skb->len;
577 if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
578 skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
580 skb = iraw_encode(skb, HW_HDR_LEN, 0);
582 err("unable to allocate memory for encoding!\n");
586 skb_queue_tail(&bcs->squeue, skb);
587 spin_lock_irqsave(&bcs->cs->lock, flags);
588 if (bcs->cs->connected)
589 tasklet_schedule(&bcs->cs->write_tasklet);
590 spin_unlock_irqrestore(&bcs->cs->lock, flags);
592 return len; /* ok so far */