1 /*********************************************************************
5 * Description: IrDA SIR async wrapper layer
6 * Status: Experimental.
7 * Author: Dag Brattli <dagb@cs.uit.no>
8 * Created at: Mon Aug 4 20:40:53 1997
9 * Modified at: Sun May 2 21:58:00 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
13 * All Rights Reserved.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * Neither Dag Brattli nor University of Tromsø admit liability nor
21 * provide warranty for any of this software. This material is
22 * provided "AS-IS" and at no charge.
24 ********************************************************************/
26 #include <linux/skbuff.h>
27 #include <asm/byteorder.h>
29 #include <net/irda/irda.h>
30 #include <net/irda/wrapper.h>
31 #include <net/irda/irtty.h>
32 #include <net/irda/crc.h>
33 #include <net/irda/irlap.h>
34 #include <net/irda/irlap_frame.h>
35 #include <net/irda/irda_device.h>
37 static inline int stuff_byte(__u8 byte
, __u8
*buf
);
39 static void state_outside_frame(struct irda_device
*idev
, __u8 byte
);
40 static void state_begin_frame(struct irda_device
*idev
, __u8 byte
);
41 static void state_link_escape(struct irda_device
*idev
, __u8 byte
);
42 static void state_inside_frame(struct irda_device
*idev
, __u8 byte
);
44 static void (*state
[])(struct irda_device
*idev
, __u8 byte
) =
53 * Function async_wrap (skb, *tx_buff)
55 * Makes a new buffer with wrapping and stuffing, should check that
56 * we don't get tx buffer overflow.
58 int async_wrap_skb(struct sk_buff
*skb
, __u8
*tx_buff
, int buffsize
)
68 /* Initialize variables */
72 if (skb
->len
> 2048) {
73 DEBUG(0, __FUNCTION__
"Warning size=%d of sk_buff to big!\n",
79 * Send XBOF's for required min. turn time and for the negotiated
82 if (((struct irlap_skb_cb
*)(skb
->cb
))->magic
!= LAP_MAGIC
) {
83 DEBUG(1, __FUNCTION__
"(), wrong magic in skb!\n");
86 xbofs
= ((struct irlap_skb_cb
*)(skb
->cb
))->xbofs
;
88 memset(tx_buff
+n
, XBOF
, xbofs
);
91 /* Start of packet character BOF */
94 /* Insert frame and calc CRC */
95 for (i
=0; i
< skb
->len
; i
++) {
97 * Check for the possibility of tx buffer overflow. We use
98 * bufsize-5 since the maximum number of bytes that can be
99 * transmitted after this point is 5.
101 ASSERT(n
< (buffsize
-5), return n
;);
103 n
+= stuff_byte(skb
->data
[i
], tx_buff
+n
);
104 fcs
.value
= irda_fcs(fcs
.value
, skb
->data
[i
]);
107 /* Insert CRC in little endian format (LSB first) */
108 fcs
.value
= ~fcs
.value
;
109 #ifdef __LITTLE_ENDIAN
110 n
+= stuff_byte(fcs
.bytes
[0], tx_buff
+n
);
111 n
+= stuff_byte(fcs
.bytes
[1], tx_buff
+n
);
112 #else ifdef __BIG_ENDIAN
113 n
+= stuff_byte(fcs
.bytes
[1], tx_buff
+n
);
114 n
+= stuff_byte(fcs
.bytes
[0], tx_buff
+n
);
122 * Function async_bump (idev)
124 * Got a frame, make a copy of it, and pass it up the stack!
127 static inline void async_bump(struct irda_device
*idev
, __u8
*buf
, int len
)
131 skb
= dev_alloc_skb(len
+1);
133 idev
->stats
.rx_dropped
++;
137 /* Align IP header to 20 bytes */
140 /* Copy data without CRC */
141 memcpy(skb_put(skb
, len
-2), buf
, len
-2);
144 * Feed it to IrLAP layer
146 skb
->dev
= &idev
->netdev
;
147 skb
->mac
.raw
= skb
->data
;
148 skb
->protocol
= htons(ETH_P_IRDA
);
151 idev
->stats
.rx_packets
++;
152 idev
->stats
.rx_bytes
+= skb
->len
;
156 * Function stuff_byte (byte, buf)
158 * Byte stuff one single byte and put the result in buffer pointed to by
159 * buf. The buffer must at all times be able to have two bytes inserted.
162 static inline int stuff_byte(__u8 byte
, __u8
*buf
)
165 case BOF
: /* FALLTHROUGH */
166 case EOF
: /* FALLTHROUGH */
168 /* Insert transparently coded */
169 buf
[0] = CE
; /* Send link escape */
170 buf
[1] = byte
^IRDA_TRANS
; /* Complement bit 5 */
174 /* Non-special value, no transparency required */
182 * Function async_unwrap (skb)
184 * Parse and de-stuff frame received from the IrDA-port
187 inline void async_unwrap_char(struct irda_device
*idev
, __u8 byte
)
189 (*state
[idev
->rx_buff
.state
]) (idev
, byte
);
193 * Function state_outside_frame (idev, byte)
198 static void state_outside_frame(struct irda_device
*idev
, __u8 byte
)
202 idev
->rx_buff
.state
= BEGIN_FRAME
;
203 idev
->rx_buff
.in_frame
= TRUE
;
209 irda_device_set_media_busy( idev
, TRUE
);
217 * Function state_begin_frame (idev, byte)
222 static void state_begin_frame(struct irda_device
*idev
, __u8 byte
)
230 idev
->rx_buff
.state
= LINK_ESCAPE
;
234 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
236 idev
->stats
.rx_errors
++;
237 idev
->stats
.rx_frame_errors
++;
240 /* Got first byte of frame */
241 idev
->rx_buff
.data
= idev
->rx_buff
.head
;
242 idev
->rx_buff
.len
= 0;
244 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
246 idev
->rx_buff
.fcs
= irda_fcs(INIT_FCS
, byte
);
247 idev
->rx_buff
.state
= INSIDE_FRAME
;
253 * Function state_link_escape (idev, byte)
258 static void state_link_escape(struct irda_device
*idev
, __u8 byte
)
261 case BOF
: /* New frame? */
262 idev
->rx_buff
.state
= BEGIN_FRAME
;
263 irda_device_set_media_busy(idev
, TRUE
);
266 DEBUG(4, "WARNING: State not defined\n");
268 case EOF
: /* Abort frame */
269 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
273 * Stuffed char, complement bit 5 of byte
274 * following CE, IrLAP p.114
277 if (idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
278 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
279 idev
->rx_buff
.fcs
= irda_fcs(idev
->rx_buff
.fcs
, byte
);
280 idev
->rx_buff
.state
= INSIDE_FRAME
;
282 DEBUG(1, __FUNCTION__
283 "(), Rx buffer overflow, aborting\n");
284 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
291 * Function state_inside_frame (idev, byte)
296 static void state_inside_frame(struct irda_device
*idev
, __u8 byte
)
299 case BOF
: /* New frame? */
300 idev
->rx_buff
.state
= BEGIN_FRAME
;
301 irda_device_set_media_busy(idev
, TRUE
);
303 case CE
: /* Stuffed char */
304 idev
->rx_buff
.state
= LINK_ESCAPE
;
306 case EOF
: /* End of frame */
307 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
308 idev
->rx_buff
.in_frame
= FALSE
;
310 /* Test FCS and deliver frame if it's good */
311 if (idev
->rx_buff
.fcs
== GOOD_FCS
) {
312 async_bump(idev
, idev
->rx_buff
.data
,
315 /* Wrong CRC, discard frame! */
316 irda_device_set_media_busy(idev
, TRUE
);
318 idev
->stats
.rx_errors
++;
319 idev
->stats
.rx_crc_errors
++;
322 default: /* Must be the next byte of the frame */
323 if (idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
324 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
325 idev
->rx_buff
.fcs
= irda_fcs(idev
->rx_buff
.fcs
, byte
);
327 DEBUG(1, __FUNCTION__
328 "(), Rx buffer overflow, aborting\n");
329 idev
->rx_buff
.state
= OUTSIDE_FRAME
;