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>,
6 * Stefan Eilers <Eilers.Stefan@epost.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 * =====================================================================
17 #include <linux/crc-ccitt.h>
19 //#define GIG_M10x_STUFF_VOICE_DATA
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.
26 static inline int muststuff(unsigned char c)
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 */
37 /* == data input =========================================================== */
39 /* process a block of received bytes in command mode (modem response)
41 * number of processed bytes
43 static inline int cmd_loop(unsigned char c, unsigned char *src, int numbytes,
44 struct inbuf_t *inbuf)
46 struct cardstate *cs = inbuf->cs;
47 unsigned cbytes = cs->cbytes;
48 int inputstate = inbuf->inputstate;
49 int startbytes = numbytes;
52 cs->respdata[cbytes] = c;
53 if (c == 10 || c == 13) {
54 gig_dbg(DEBUG_TRANSCMD, "%s: End of Command (%d Bytes)",
57 gigaset_handle_modem_response(cs); /* can change
62 !(inputstate & INS_DLE_command)) {
63 inputstate &= ~INS_command;
67 /* advance in line buffer, checking for overflow */
68 if (cbytes < MAX_RESP_SIZE - 1)
71 dev_warn(cs->dev, "response too large\n");
79 (cs->dle || inputstate & INS_DLE_command)) {
80 inputstate |= INS_DLE_char;
86 inbuf->inputstate = inputstate;
88 return startbytes - numbytes;
91 /* process a block of received bytes in lock mode (tty i/f)
93 * number of processed bytes
95 static inline int lock_loop(unsigned char *src, int numbytes,
96 struct inbuf_t *inbuf)
98 struct cardstate *cs = inbuf->cs;
100 gigaset_dbg_buffer(DEBUG_LOCKCMD, "received response",
102 gigaset_if_receive(cs, src, numbytes);
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.
112 * number of processed bytes
113 * numbytes (all bytes processed) on error --FIXME
115 static inline int hdlc_loop(unsigned char c, unsigned char *src, int numbytes,
116 struct inbuf_t *inbuf)
118 struct cardstate *cs = inbuf->cs;
119 struct bc_state *bcs = inbuf->bcs;
120 int inputstate = bcs->inputstate;
121 __u16 fcs = bcs->fcs;
122 struct sk_buff *skb = bcs->skb;
124 struct sk_buff *compskb;
125 int startbytes = numbytes;
128 if (unlikely(inputstate & INS_byte_stuff)) {
129 inputstate &= ~INS_byte_stuff;
133 if (unlikely(c == PPP_ESCAPE)) {
134 if (unlikely(!numbytes)) {
135 inputstate |= INS_byte_stuff;
140 if (unlikely(c == DLE_FLAG &&
142 inbuf->inputstate & INS_DLE_command))) {
143 inbuf->inputstate |= INS_DLE_char;
144 inputstate |= INS_byte_stuff;
149 #ifdef CONFIG_GIGASET_DEBUG
150 if (unlikely(!muststuff(c)))
151 gig_dbg(DEBUG_HDLC, "byte stuffed: 0x%02x", c);
153 } else if (unlikely(c == PPP_FLAG)) {
154 if (unlikely(inputstate & INS_skip_frame)) {
155 if (!(inputstate & INS_have_data)) { /* 7E 7E */
156 #ifdef CONFIG_GIGASET_DEBUG
161 "7e----------------------------");
165 gigaset_rcv_error(NULL, cs, bcs);
166 } else if (!(inputstate & INS_have_data)) { /* 7E 7E */
167 #ifdef CONFIG_GIGASET_DEBUG
173 "7e----------------------------");
178 if (unlikely(fcs != PPP_GOODFCS)) {
180 "Packet checksum at %lu failed, "
181 "packet is corrupted (%u bytes)!\n",
182 bcs->rcvbytes, skb->len);
184 gigaset_rcv_error(compskb, cs, bcs);
187 if (likely((l = skb->len) > 2)) {
193 inputstate |= INS_skip_frame;
196 "invalid packet size (1)!\n");
198 gigaset_rcv_error(NULL,
202 if (likely(!(error ||
205 gigaset_rcv_skb(skb, cs, bcs);
215 inputstate &= ~(INS_have_data | INS_skip_frame);
216 if (unlikely(bcs->ignore)) {
217 inputstate |= INS_skip_frame;
219 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN)) != NULL)) {
220 skb_reserve(skb, HW_HDR_LEN);
223 "could not allocate new skb\n");
224 inputstate |= INS_skip_frame;
228 #ifdef CONFIG_GIGASET_DEBUG
229 } else if (unlikely(muststuff(c))) {
230 /* Should not happen. Possible after ZDLE=1<CR><LF>. */
231 gig_dbg(DEBUG_HDLC, "not byte stuffed: 0x%02x", c);
237 #ifdef CONFIG_GIGASET_DEBUG
238 if (unlikely(!(inputstate & INS_have_data))) {
239 gig_dbg(DEBUG_HDLC, "7e (%d x) ================",
245 inputstate |= INS_have_data;
247 if (likely(!(inputstate & INS_skip_frame))) {
248 if (unlikely(skb->len == SBUFSIZE)) {
249 dev_warn(cs->dev, "received packet too long\n");
250 dev_kfree_skb_any(skb);
252 inputstate |= INS_skip_frame;
255 *gigaset_skb_put_quick(skb, 1) = c;
256 /* *__skb_put (skb, 1) = c; */
257 fcs = crc_ccitt_byte(fcs, c);
260 if (unlikely(!numbytes))
264 if (unlikely(c == DLE_FLAG &&
266 inbuf->inputstate & INS_DLE_command))) {
267 inbuf->inputstate |= INS_DLE_char;
271 bcs->inputstate = inputstate;
274 return startbytes - numbytes;
277 /* process a block of received bytes in transparent data mode
278 * Invert bytes, undoing byte stuffing and watching for DLE escapes.
279 * If DLE is encountered, return immediately to let the caller handle it.
281 * number of processed bytes
282 * numbytes (all bytes processed) on error --FIXME
284 static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes,
285 struct inbuf_t *inbuf)
287 struct cardstate *cs = inbuf->cs;
288 struct bc_state *bcs = inbuf->bcs;
289 int inputstate = bcs->inputstate;
290 struct sk_buff *skb = bcs->skb;
291 int startbytes = numbytes;
295 inputstate |= INS_have_data;
297 if (likely(!(inputstate & INS_skip_frame))) {
298 if (unlikely(skb->len == SBUFSIZE)) {
299 //FIXME just pass skb up and allocate a new one
300 dev_warn(cs->dev, "received packet too long\n");
301 dev_kfree_skb_any(skb);
303 inputstate |= INS_skip_frame;
306 *gigaset_skb_put_quick(skb, 1) = gigaset_invtab[c];
309 if (unlikely(!numbytes))
313 if (unlikely(c == DLE_FLAG &&
315 inbuf->inputstate & INS_DLE_command))) {
316 inbuf->inputstate |= INS_DLE_char;
322 if (likely(inputstate & INS_have_data)) {
323 if (likely(!(inputstate & INS_skip_frame))) {
324 gigaset_rcv_skb(skb, cs, bcs);
326 inputstate &= ~(INS_have_data | INS_skip_frame);
327 if (unlikely(bcs->ignore)) {
328 inputstate |= INS_skip_frame;
330 } else if (likely((skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN))
332 skb_reserve(skb, HW_HDR_LEN);
334 dev_warn(cs->dev, "could not allocate new skb\n");
335 inputstate |= INS_skip_frame;
339 bcs->inputstate = inputstate;
341 return startbytes - numbytes;
344 /* process a block of data received from the device
346 void gigaset_m10x_input(struct inbuf_t *inbuf)
348 struct cardstate *cs;
349 unsigned tail, head, numbytes;
350 unsigned char *src, c;
353 head = atomic_read(&inbuf->head);
354 tail = atomic_read(&inbuf->tail);
355 gig_dbg(DEBUG_INTR, "buffer state: %u -> %u", head, tail);
359 src = inbuf->data + head;
360 numbytes = (head > tail ? RBUFSIZE : tail) - head;
361 gig_dbg(DEBUG_INTR, "processing %u bytes", numbytes);
364 if (atomic_read(&cs->mstate) == MS_LOCKED) {
365 procbytes = lock_loop(src, numbytes, inbuf);
367 numbytes -= procbytes;
371 if (c == DLE_FLAG && (cs->dle ||
372 inbuf->inputstate & INS_DLE_command)) {
373 if (!(inbuf->inputstate & INS_DLE_char)) {
374 inbuf->inputstate |= INS_DLE_char;
377 /* <DLE> <DLE> => <DLE> in data stream */
378 inbuf->inputstate &= ~INS_DLE_char;
381 if (!(inbuf->inputstate & INS_DLE_char)) {
383 /* FIXME use function pointers? */
384 if (inbuf->inputstate & INS_command)
385 procbytes = cmd_loop(c, src, numbytes, inbuf);
386 else if (inbuf->bcs->proto2 == ISDN_PROTO_L2_HDLC)
387 procbytes = hdlc_loop(c, src, numbytes, inbuf);
389 procbytes = iraw_loop(c, src, numbytes, inbuf);
392 numbytes -= procbytes;
393 } else { /* DLE char */
394 inbuf->inputstate &= ~INS_DLE_char;
396 case 'X': /*begin of command*/
397 #ifdef CONFIG_GIGASET_DEBUG
398 if (inbuf->inputstate & INS_command)
400 "received <DLE> 'X' in command mode\n");
403 INS_command | INS_DLE_command;
405 case '.': /*end of command*/
406 #ifdef CONFIG_GIGASET_DEBUG
407 if (!(inbuf->inputstate & INS_command))
409 "received <DLE> '.' in hdlc mode\n");
411 inbuf->inputstate &= cs->dle ?
412 ~(INS_DLE_command|INS_command)
415 //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
418 "received 0x10 0x%02x!\n",
420 /* FIXME: reset driver?? */
426 /* end of buffer, check for wrap */
438 gig_dbg(DEBUG_INTR, "setting head to %u", head);
439 atomic_set(&inbuf->head, head);
444 /* == data output ========================================================== */
446 /* Encoding of a PPP packet into an octet stuffed HDLC frame
447 * with FCS, opening and closing flags.
449 * skb skb containing original packet (freed upon return)
450 * head number of headroom bytes to allocate in result skb
451 * tail number of tailroom bytes to allocate in result skb
453 * pointer to newly allocated skb containing the result frame
455 static struct sk_buff *HDLC_Encode(struct sk_buff *skb, int head, int tail)
457 struct sk_buff *hdlc_skb;
462 unsigned int stuf_cnt;
471 fcs = crc_ccitt_byte(fcs, *cp++);
473 fcs ^= 0xffff; /* complement */
475 /* size of new buffer: original size + number of stuffing bytes
476 * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
478 hdlc_skb = dev_alloc_skb(skb->len + stuf_cnt + 6 + tail + head);
483 skb_reserve(hdlc_skb, head);
485 /* Copy acknowledge request into new skb */
486 memcpy(hdlc_skb->head, skb->head, 2);
488 /* Add flag sequence in front of everything.. */
489 *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
491 /* Perform byte stuffing while copying data. */
493 if (muststuff(*skb->data)) {
494 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
495 *(skb_put(hdlc_skb, 1)) = (*skb->data++) ^ PPP_TRANS;
497 *(skb_put(hdlc_skb, 1)) = *skb->data++;
500 /* Finally add FCS (byte stuffed) and flag sequence */
501 c = (fcs & 0x00ff); /* least significant byte first */
503 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
506 *(skb_put(hdlc_skb, 1)) = c;
508 c = ((fcs >> 8) & 0x00ff);
510 *(skb_put(hdlc_skb, 1)) = PPP_ESCAPE;
513 *(skb_put(hdlc_skb, 1)) = c;
515 *(skb_put(hdlc_skb, 1)) = PPP_FLAG;
521 /* Encoding of a raw packet into an octet stuffed bit inverted frame
523 * skb skb containing original packet (freed upon return)
524 * head number of headroom bytes to allocate in result skb
525 * tail number of tailroom bytes to allocate in result skb
527 * pointer to newly allocated skb containing the result frame
529 static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail)
531 struct sk_buff *iraw_skb;
536 /* worst case: every byte must be stuffed */
537 iraw_skb = dev_alloc_skb(2*skb->len + tail + head);
542 skb_reserve(iraw_skb, head);
547 c = gigaset_invtab[*cp++];
549 *(skb_put(iraw_skb, 1)) = c;
550 *(skb_put(iraw_skb, 1)) = c;
557 * called by common.c to queue an skb for sending
558 * and start transmission if necessary
560 * B Channel control structure
563 * number of bytes accepted for sending
564 * (skb->len if ok, 0 if out of buffer space)
565 * or error code (< 0, eg. -EINVAL)
567 int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb)
569 unsigned len = skb->len;
571 if (bcs->proto2 == ISDN_PROTO_L2_HDLC)
572 skb = HDLC_Encode(skb, HW_HDR_LEN, 0);
574 skb = iraw_encode(skb, HW_HDR_LEN, 0);
576 dev_err(bcs->cs->dev,
577 "unable to allocate memory for encoding!\n");
581 skb_queue_tail(&bcs->squeue, skb);
582 tasklet_schedule(&bcs->cs->write_tasklet);
584 return len; /* ok so far */