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: Mon Sep 20 11:18:44 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
11 * Modified at: Fri May 28 3:11 CST 1999
12 * Modified by: Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
14 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
15 * All Rights Reserved.
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
22 * Neither Dag Brattli nor University of Tromsø admit liability nor
23 * provide warranty for any of this software. This material is
24 * provided "AS-IS" and at no charge.
26 ********************************************************************/
28 #include <linux/skbuff.h>
29 #include <linux/string.h>
30 #include <asm/byteorder.h>
32 #include <net/irda/irda.h>
33 #include <net/irda/wrapper.h>
34 #include <net/irda/irtty.h>
35 #include <net/irda/crc.h>
36 #include <net/irda/irlap.h>
37 #include <net/irda/irlap_frame.h>
38 #include <net/irda/irda_device.h>
40 static inline int stuff_byte(__u8 byte
, __u8
*buf
);
42 static void state_outside_frame(struct irda_device
*idev
, __u8 byte
);
43 static void state_begin_frame(struct irda_device
*idev
, __u8 byte
);
44 static void state_link_escape(struct irda_device
*idev
, __u8 byte
);
45 static void state_inside_frame(struct irda_device
*idev
, __u8 byte
);
47 static void (*state
[])(struct irda_device
*idev
, __u8 byte
) =
56 * Function async_wrap (skb, *tx_buff, buffsize)
58 * Makes a new buffer with wrapping and stuffing, should check that
59 * we don't get tx buffer overflow.
61 int async_wrap_skb(struct sk_buff
*skb
, __u8
*tx_buff
, int buffsize
)
71 /* Initialize variables */
76 * Send XBOF's for required min. turn time and for the negotiated
79 if (((struct irda_skb_cb
*)(skb
->cb
))->magic
!= LAP_MAGIC
) {
80 DEBUG(1, __FUNCTION__
"(), wrong magic in skb!\n");
83 xbofs
= ((struct irda_skb_cb
*)(skb
->cb
))->xbofs
;
85 memset(tx_buff
+n
, XBOF
, xbofs
);
88 /* Start of packet character BOF */
91 /* Insert frame and calc CRC */
92 for (i
=0; i
< skb
->len
; i
++) {
94 * Check for the possibility of tx buffer overflow. We use
95 * bufsize-5 since the maximum number of bytes that can be
96 * transmitted after this point is 5.
98 ASSERT(n
< (buffsize
-5), return n
;);
100 n
+= stuff_byte(skb
->data
[i
], tx_buff
+n
);
101 fcs
.value
= irda_fcs(fcs
.value
, skb
->data
[i
]);
104 /* Insert CRC in little endian format (LSB first) */
105 fcs
.value
= ~fcs
.value
;
106 #ifdef __LITTLE_ENDIAN
107 n
+= stuff_byte(fcs
.bytes
[0], tx_buff
+n
);
108 n
+= stuff_byte(fcs
.bytes
[1], tx_buff
+n
);
109 #else ifdef __BIG_ENDIAN
110 n
+= stuff_byte(fcs
.bytes
[1], tx_buff
+n
);
111 n
+= stuff_byte(fcs
.bytes
[0], tx_buff
+n
);
119 * Function async_bump (idev, buf, len)
121 * Got a frame, make a copy of it, and pass it up the stack!
124 static inline void async_bump(struct irda_device
*idev
, __u8
*buf
, int len
)
128 skb
= dev_alloc_skb(len
+1);
130 idev
->stats
.rx_dropped
++;
134 /* Align IP header to 20 bytes */
137 /* Copy data without CRC */
138 memcpy(skb_put(skb
, len
-2), buf
, len
-2);
141 * Feed it to IrLAP layer
143 skb
->dev
= &idev
->netdev
;
144 skb
->mac
.raw
= skb
->data
;
145 skb
->protocol
= htons(ETH_P_IRDA
);
148 idev
->stats
.rx_packets
++;
149 idev
->stats
.rx_bytes
+= skb
->len
;
153 * Function stuff_byte (byte, buf)
155 * Byte stuff one single byte and put the result in buffer pointed to by
156 * buf. The buffer must at all times be able to have two bytes inserted.
159 static inline int stuff_byte(__u8 byte
, __u8
*buf
)
162 case BOF
: /* FALLTHROUGH */
163 case EOF
: /* FALLTHROUGH */
165 /* Insert transparently coded */
166 buf
[0] = CE
; /* Send link escape */
167 buf
[1] = byte
^IRDA_TRANS
; /* Complement bit 5 */
171 /* Non-special value, no transparency required */
179 * Function async_unwrap_char (idev, byte)
181 * Parse and de-stuff frame received from the IrDA-port
184 inline void async_unwrap_char(struct irda_device
*idev
, __u8 byte
)
186 (*state
[idev
->rx_buff
.state
]) (idev
, byte
);
190 * Function state_outside_frame (idev, byte)
195 static void state_outside_frame(struct irda_device
*idev
, __u8 byte
)
199 idev
->rx_buff
.state
= BEGIN_FRAME
;
200 idev
->rx_buff
.in_frame
= TRUE
;
206 irda_device_set_media_busy(&idev
->netdev
, TRUE
);
214 * Function state_begin_frame (idev, byte)
216 * Begin of frame detected
219 static void state_begin_frame(struct irda_device
*idev
, __u8 byte
)
227 idev
->rx_buff
.state
= LINK_ESCAPE
;
229 /* Time to initialize receive buffer */
230 idev
->rx_buff
.data
= idev
->rx_buff
.head
;
231 idev
->rx_buff
.len
= 0;
235 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
237 idev
->stats
.rx_errors
++;
238 idev
->stats
.rx_frame_errors
++;
241 /* Time to initialize receive buffer */
242 idev
->rx_buff
.data
= idev
->rx_buff
.head
;
243 idev
->rx_buff
.len
= 0;
245 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
247 idev
->rx_buff
.fcs
= irda_fcs(INIT_FCS
, byte
);
248 idev
->rx_buff
.state
= INSIDE_FRAME
;
254 * Function state_link_escape (idev, byte)
259 static void state_link_escape(struct irda_device
*idev
, __u8 byte
)
262 case BOF
: /* New frame? */
263 idev
->rx_buff
.state
= BEGIN_FRAME
;
264 irda_device_set_media_busy(&idev
->netdev
, TRUE
);
267 DEBUG(4, "WARNING: State not defined\n");
269 case EOF
: /* Abort frame */
270 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
274 * Stuffed char, complement bit 5 of byte
275 * following CE, IrLAP p.114
278 if (idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
279 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
280 idev
->rx_buff
.fcs
= irda_fcs(idev
->rx_buff
.fcs
, byte
);
281 idev
->rx_buff
.state
= INSIDE_FRAME
;
283 DEBUG(1, __FUNCTION__
284 "(), Rx buffer overflow, aborting\n");
285 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
292 * Function state_inside_frame (idev, byte)
294 * Handle bytes received within a frame
297 static void state_inside_frame(struct irda_device
*idev
, __u8 byte
)
300 case BOF
: /* New frame? */
301 idev
->rx_buff
.state
= BEGIN_FRAME
;
302 irda_device_set_media_busy(&idev
->netdev
, TRUE
);
304 case CE
: /* Stuffed char */
305 idev
->rx_buff
.state
= LINK_ESCAPE
;
307 case EOF
: /* End of frame */
308 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
309 idev
->rx_buff
.in_frame
= FALSE
;
311 /* Test FCS and deliver frame if it's good */
312 if (idev
->rx_buff
.fcs
== GOOD_FCS
) {
313 async_bump(idev
, idev
->rx_buff
.data
,
316 /* Wrong CRC, discard frame! */
317 irda_device_set_media_busy(&idev
->netdev
, TRUE
);
319 idev
->stats
.rx_errors
++;
320 idev
->stats
.rx_crc_errors
++;
323 default: /* Must be the next byte of the frame */
324 if (idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
325 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
326 idev
->rx_buff
.fcs
= irda_fcs(idev
->rx_buff
.fcs
, byte
);
328 DEBUG(1, __FUNCTION__
329 "(), Rx buffer overflow, aborting\n");
330 idev
->rx_buff
.state
= OUTSIDE_FRAME
;