256fc4809c812c4a87d389d97b862b75fbbe5a58
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 * =====================================================================
17 #include <linux/crc-ccitt.h>
18 #include <linux/bitrev.h>
20 /* check if byte must be stuffed/escaped
21 * I'm not sure which data should be encoded.
22 * Therefore I will go the hard way and decode every value
23 * less than 0x20, the flag sequence and the control escape char.
25 static inline int muststuff(unsigned char c
)
27 if (c
< PPP_TRANS
) return 1;
28 if (c
== PPP_FLAG
) return 1;
29 if (c
== PPP_ESCAPE
) return 1;
30 /* other possible candidates: */
31 /* 0x91: XON with parity set */
32 /* 0x93: XOFF with parity set */
36 /* == data input =========================================================== */
38 /* process a block of received bytes in command mode (modem response)
40 * number of processed bytes
42 static inline int cmd_loop(unsigned char c
, unsigned char *src
, int numbytes
,
43 struct inbuf_t
*inbuf
)
45 struct cardstate
*cs
= inbuf
->cs
;
46 unsigned cbytes
= cs
->cbytes
;
47 int inputstate
= inbuf
->inputstate
;
48 int startbytes
= numbytes
;
51 cs
->respdata
[cbytes
] = c
;
52 if (c
== 10 || c
== 13) {
53 gig_dbg(DEBUG_TRANSCMD
, "%s: End of Command (%d Bytes)",
56 gigaset_handle_modem_response(cs
); /* can change
61 !(inputstate
& INS_DLE_command
)) {
62 inputstate
&= ~INS_command
;
66 /* advance in line buffer, checking for overflow */
67 if (cbytes
< MAX_RESP_SIZE
- 1)
70 dev_warn(cs
->dev
, "response too large\n");
78 (cs
->dle
|| inputstate
& INS_DLE_command
)) {
79 inputstate
|= INS_DLE_char
;
85 inbuf
->inputstate
= inputstate
;
87 return startbytes
- numbytes
;
90 /* process a block of received bytes in lock mode (tty i/f)
92 * number of processed bytes
94 static inline int lock_loop(unsigned char *src
, int numbytes
,
95 struct inbuf_t
*inbuf
)
97 struct cardstate
*cs
= inbuf
->cs
;
99 gigaset_dbg_buffer(DEBUG_LOCKCMD
, "received response",
101 gigaset_if_receive(cs
, src
, numbytes
);
106 /* process a block of received bytes in HDLC data mode
107 * Collect HDLC frames, undoing byte stuffing and watching for DLE escapes.
108 * When a frame is complete, check the FCS and pass valid frames to the LL.
109 * If DLE is encountered, return immediately to let the caller handle it.
111 * number of processed bytes
112 * numbytes (all bytes processed) on error --FIXME
114 static inline int hdlc_loop(unsigned char c
, unsigned char *src
, int numbytes
,
115 struct inbuf_t
*inbuf
)
117 struct cardstate
*cs
= inbuf
->cs
;
118 struct bc_state
*bcs
= inbuf
->bcs
;
119 int inputstate
= bcs
->inputstate
;
120 __u16 fcs
= bcs
->fcs
;
121 struct sk_buff
*skb
= bcs
->skb
;
122 int startbytes
= numbytes
;
124 if (unlikely(inputstate
& INS_byte_stuff
)) {
125 inputstate
&= ~INS_byte_stuff
;
129 if (unlikely(c
== PPP_ESCAPE
)) {
130 if (unlikely(!numbytes
)) {
131 inputstate
|= INS_byte_stuff
;
136 if (unlikely(c
== DLE_FLAG
&&
138 inbuf
->inputstate
& INS_DLE_command
))) {
139 inbuf
->inputstate
|= INS_DLE_char
;
140 inputstate
|= INS_byte_stuff
;
145 if (unlikely(!muststuff(c
)))
146 gig_dbg(DEBUG_HDLC
, "byte stuffed: 0x%02x", c
);
147 } else if (unlikely(c
== PPP_FLAG
)) {
148 if (unlikely(inputstate
& INS_skip_frame
)) {
149 #ifdef CONFIG_GIGASET_DEBUG
150 if (!(inputstate
& INS_have_data
)) { /* 7E 7E */
154 "7e----------------------------");
158 gigaset_isdn_rcv_err(bcs
);
159 dev_kfree_skb_any(skb
);
160 } else if (!(inputstate
& INS_have_data
)) { /* 7E 7E */
161 #ifdef CONFIG_GIGASET_DEBUG
167 "7e----------------------------");
170 if (unlikely(fcs
!= PPP_GOODFCS
)) {
172 "Checksum failed, %u bytes corrupted!\n",
174 gigaset_isdn_rcv_err(bcs
);
175 dev_kfree_skb_any(skb
);
176 } else if (likely(skb
->len
> 2)) {
177 __skb_trim(skb
, skb
->len
- 2);
178 gigaset_skb_rcvd(bcs
, skb
);
182 "invalid packet size (%d)\n", skb
->len
);
183 gigaset_isdn_rcv_err(bcs
);
185 dev_kfree_skb_any(skb
);
190 inputstate
&= ~(INS_have_data
| INS_skip_frame
);
191 if (unlikely(bcs
->ignore
)) {
192 inputstate
|= INS_skip_frame
;
195 skb
= dev_alloc_skb(SBUFSIZE
+ cs
->hw_hdr_len
);
197 skb_reserve(skb
, cs
->hw_hdr_len
);
200 "could not allocate new skb\n");
201 inputstate
|= INS_skip_frame
;
206 } else if (unlikely(muststuff(c
))) {
207 /* Should not happen. Possible after ZDLE=1<CR><LF>. */
208 gig_dbg(DEBUG_HDLC
, "not byte stuffed: 0x%02x", c
);
213 #ifdef CONFIG_GIGASET_DEBUG
214 if (unlikely(!(inputstate
& INS_have_data
))) {
215 gig_dbg(DEBUG_HDLC
, "7e (%d x) ================",
221 inputstate
|= INS_have_data
;
223 if (likely(!(inputstate
& INS_skip_frame
))) {
224 if (unlikely(skb
->len
== SBUFSIZE
)) {
225 dev_warn(cs
->dev
, "received packet too long\n");
226 dev_kfree_skb_any(skb
);
228 inputstate
|= INS_skip_frame
;
231 *__skb_put(skb
, 1) = c
;
232 fcs
= crc_ccitt_byte(fcs
, c
);
235 if (unlikely(!numbytes
))
239 if (unlikely(c
== DLE_FLAG
&&
241 inbuf
->inputstate
& INS_DLE_command
))) {
242 inbuf
->inputstate
|= INS_DLE_char
;
246 bcs
->inputstate
= inputstate
;
249 return startbytes
- numbytes
;
252 /* process a block of received bytes in transparent data mode
253 * Invert bytes, undoing byte stuffing and watching for DLE escapes.
254 * If DLE is encountered, return immediately to let the caller handle it.
256 * number of processed bytes
257 * numbytes (all bytes processed) on error --FIXME
259 static inline int iraw_loop(unsigned char c
, unsigned char *src
, int numbytes
,
260 struct inbuf_t
*inbuf
)
262 struct cardstate
*cs
= inbuf
->cs
;
263 struct bc_state
*bcs
= inbuf
->bcs
;
264 int inputstate
= bcs
->inputstate
;
265 struct sk_buff
*skb
= bcs
->skb
;
266 int startbytes
= numbytes
;
270 inputstate
|= INS_have_data
;
272 if (likely(!(inputstate
& INS_skip_frame
))) {
273 if (unlikely(skb
->len
== SBUFSIZE
)) {
274 //FIXME just pass skb up and allocate a new one
275 dev_warn(cs
->dev
, "received packet too long\n");
276 dev_kfree_skb_any(skb
);
278 inputstate
|= INS_skip_frame
;
281 *__skb_put(skb
, 1) = bitrev8(c
);
284 if (unlikely(!numbytes
))
288 if (unlikely(c
== DLE_FLAG
&&
290 inbuf
->inputstate
& INS_DLE_command
))) {
291 inbuf
->inputstate
|= INS_DLE_char
;
297 if (likely(inputstate
& INS_have_data
)) {
298 if (likely(!(inputstate
& INS_skip_frame
))) {
299 gigaset_skb_rcvd(bcs
, skb
);
301 inputstate
&= ~(INS_have_data
| INS_skip_frame
);
302 if (unlikely(bcs
->ignore
)) {
303 inputstate
|= INS_skip_frame
;
306 skb
= dev_alloc_skb(SBUFSIZE
+ cs
->hw_hdr_len
);
308 skb_reserve(skb
, cs
->hw_hdr_len
);
311 "could not allocate new skb\n");
312 inputstate
|= INS_skip_frame
;
317 bcs
->inputstate
= inputstate
;
319 return startbytes
- numbytes
;
323 * gigaset_m10x_input() - process a block of data received from the device
324 * @inbuf: received data and device descriptor structure.
326 * Called by hardware module {ser,usb}_gigaset with a block of received
327 * bytes. Separates the bytes received over the serial data channel into
328 * user data and command replies (locked/unlocked) according to the
329 * current state of the interface.
331 void gigaset_m10x_input(struct inbuf_t
*inbuf
)
333 struct cardstate
*cs
;
334 unsigned tail
, head
, numbytes
;
335 unsigned char *src
, c
;
340 gig_dbg(DEBUG_INTR
, "buffer state: %u -> %u", head
, tail
);
344 src
= inbuf
->data
+ head
;
345 numbytes
= (head
> tail
? RBUFSIZE
: tail
) - head
;
346 gig_dbg(DEBUG_INTR
, "processing %u bytes", numbytes
);
349 if (cs
->mstate
== MS_LOCKED
) {
350 procbytes
= lock_loop(src
, numbytes
, inbuf
);
352 numbytes
-= procbytes
;
356 if (c
== DLE_FLAG
&& (cs
->dle
||
357 inbuf
->inputstate
& INS_DLE_command
)) {
358 if (!(inbuf
->inputstate
& INS_DLE_char
)) {
359 inbuf
->inputstate
|= INS_DLE_char
;
362 /* <DLE> <DLE> => <DLE> in data stream */
363 inbuf
->inputstate
&= ~INS_DLE_char
;
366 if (!(inbuf
->inputstate
& INS_DLE_char
)) {
368 /* FIXME use function pointers? */
369 if (inbuf
->inputstate
& INS_command
)
370 procbytes
= cmd_loop(c
, src
, numbytes
, inbuf
);
371 else if (inbuf
->bcs
->proto2
== L2_HDLC
)
372 procbytes
= hdlc_loop(c
, src
, numbytes
, inbuf
);
374 procbytes
= iraw_loop(c
, src
, numbytes
, inbuf
);
377 numbytes
-= procbytes
;
378 } else { /* DLE char */
379 inbuf
->inputstate
&= ~INS_DLE_char
;
381 case 'X': /*begin of command*/
382 if (inbuf
->inputstate
& INS_command
)
384 "received <DLE> 'X' in command mode\n");
386 INS_command
| INS_DLE_command
;
388 case '.': /*end of command*/
389 if (!(inbuf
->inputstate
& INS_command
))
391 "received <DLE> '.' in hdlc mode\n");
392 inbuf
->inputstate
&= cs
->dle
?
393 ~(INS_DLE_command
|INS_command
)
396 //case DLE_FLAG: /*DLE_FLAG in data stream*/ /* schon oben behandelt! */
399 "received 0x10 0x%02x!\n",
401 /* FIXME: reset driver?? */
407 /* end of buffer, check for wrap */
419 gig_dbg(DEBUG_INTR
, "setting head to %u", head
);
423 EXPORT_SYMBOL_GPL(gigaset_m10x_input
);
426 /* == data output ========================================================== */
429 * Encode a data packet into an octet stuffed HDLC frame with FCS,
430 * opening and closing flags, preserving headroom data.
432 * skb skb containing original packet (freed upon return)
434 * pointer to newly allocated skb containing the result frame
435 * and the original link layer header, NULL on error
437 static struct sk_buff
*HDLC_Encode(struct sk_buff
*skb
)
439 struct sk_buff
*hdlc_skb
;
444 unsigned int stuf_cnt
;
453 fcs
= crc_ccitt_byte(fcs
, *cp
++);
455 fcs
^= 0xffff; /* complement */
457 /* size of new buffer: original size + number of stuffing bytes
458 * + 2 bytes FCS + 2 stuffing bytes for FCS (if needed) + 2 flag bytes
459 * + room for link layer header
461 hdlc_skb
= dev_alloc_skb(skb
->len
+ stuf_cnt
+ 6 + skb
->mac_len
);
463 dev_kfree_skb_any(skb
);
467 /* Copy link layer header into new skb */
468 skb_reset_mac_header(hdlc_skb
);
469 skb_reserve(hdlc_skb
, skb
->mac_len
);
470 memcpy(skb_mac_header(hdlc_skb
), skb_mac_header(skb
), skb
->mac_len
);
471 hdlc_skb
->mac_len
= skb
->mac_len
;
473 /* Add flag sequence in front of everything.. */
474 *(skb_put(hdlc_skb
, 1)) = PPP_FLAG
;
476 /* Perform byte stuffing while copying data. */
478 if (muststuff(*skb
->data
)) {
479 *(skb_put(hdlc_skb
, 1)) = PPP_ESCAPE
;
480 *(skb_put(hdlc_skb
, 1)) = (*skb
->data
++) ^ PPP_TRANS
;
482 *(skb_put(hdlc_skb
, 1)) = *skb
->data
++;
485 /* Finally add FCS (byte stuffed) and flag sequence */
486 c
= (fcs
& 0x00ff); /* least significant byte first */
488 *(skb_put(hdlc_skb
, 1)) = PPP_ESCAPE
;
491 *(skb_put(hdlc_skb
, 1)) = c
;
493 c
= ((fcs
>> 8) & 0x00ff);
495 *(skb_put(hdlc_skb
, 1)) = PPP_ESCAPE
;
498 *(skb_put(hdlc_skb
, 1)) = c
;
500 *(skb_put(hdlc_skb
, 1)) = PPP_FLAG
;
502 dev_kfree_skb_any(skb
);
507 * Encode a data packet into an octet stuffed raw bit inverted frame,
508 * preserving headroom data.
510 * skb skb containing original packet (freed upon return)
512 * pointer to newly allocated skb containing the result frame
513 * and the original link layer header, NULL on error
515 static struct sk_buff
*iraw_encode(struct sk_buff
*skb
)
517 struct sk_buff
*iraw_skb
;
522 /* size of new buffer (worst case = every byte must be stuffed):
523 * 2 * original size + room for link layer header
525 iraw_skb
= dev_alloc_skb(2*skb
->len
+ skb
->mac_len
);
527 dev_kfree_skb_any(skb
);
531 /* copy link layer header into new skb */
532 skb_reset_mac_header(iraw_skb
);
533 skb_reserve(iraw_skb
, skb
->mac_len
);
534 memcpy(skb_mac_header(iraw_skb
), skb_mac_header(skb
), skb
->mac_len
);
535 iraw_skb
->mac_len
= skb
->mac_len
;
537 /* copy and stuff data */
543 *(skb_put(iraw_skb
, 1)) = c
;
544 *(skb_put(iraw_skb
, 1)) = c
;
546 dev_kfree_skb_any(skb
);
551 * gigaset_m10x_send_skb() - queue an skb for sending
552 * @bcs: B channel descriptor structure.
553 * @skb: data to send.
555 * Called by LL to encode and queue an skb for sending, and start
556 * transmission if necessary.
557 * Once the payload data has been transmitted completely, gigaset_skb_sent()
558 * will be called with the skb's link layer header preserved.
561 * number of bytes accepted for sending (skb->len) if ok,
562 * error code < 0 (eg. -ENOMEM) on error
564 int gigaset_m10x_send_skb(struct bc_state
*bcs
, struct sk_buff
*skb
)
566 unsigned len
= skb
->len
;
569 if (bcs
->proto2
== L2_HDLC
)
570 skb
= HDLC_Encode(skb
);
572 skb
= iraw_encode(skb
);
574 dev_err(bcs
->cs
->dev
,
575 "unable to allocate memory for encoding!\n");
579 skb_queue_tail(&bcs
->squeue
, skb
);
580 spin_lock_irqsave(&bcs
->cs
->lock
, flags
);
581 if (bcs
->cs
->connected
)
582 tasklet_schedule(&bcs
->cs
->write_tasklet
);
583 spin_unlock_irqrestore(&bcs
->cs
->lock
, flags
);
585 return len
; /* ok so far */
587 EXPORT_SYMBOL_GPL(gigaset_m10x_send_skb
);
This page took 0.041683 seconds and 4 git commands to generate.