1 /*********************************************************************
5 * Description: SIR 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: Wed Apr 21 12:45:55 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1998 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 inline static int stuff_byte(__u8 byte
, __u8
*buf
);
40 * Function async_wrap (skb, *tx_buff)
42 * Makes a new buffer with wrapping and stuffing, should check that
43 * we don't get tx buffer overflow.
45 int async_wrap_skb(struct sk_buff
*skb
, __u8
*tx_buff
, int buffsize
)
55 ASSERT(skb
!= NULL
, return 0;);
57 /* Initialize variables */
61 if (skb
->len
> 2048) {
62 DEBUG(0, __FUNCTION__
"Warning size=%d of sk_buff to big!\n",
68 * Send XBOF's for required min. turn time and for the negotiated
71 if (((struct irlap_skb_cb
*)(skb
->cb
))->magic
!= LAP_MAGIC
) {
72 DEBUG(1, __FUNCTION__
"(), wrong magic in skb!\n");
75 xbofs
= ((struct irlap_skb_cb
*)(skb
->cb
))->xbofs
;
78 for (i
=0; i
<xbofs
; i
++)
81 memset(tx_buff
+n
, XBOF
, xbofs
);
84 /* Start of packet character BOF */
87 /* Insert frame and calc CRC */
88 for (i
=0; i
< skb
->len
; i
++) {
90 * Check for the possibility of tx buffer overflow. We use
91 * bufsize-5 since the maximum number of bytes that can be
92 * transmitted after this point is 5.
94 ASSERT(n
< (buffsize
-5), return n
;);
96 n
+= stuff_byte(skb
->data
[i
], tx_buff
+n
);
97 fcs
.value
= IR_FCS(fcs
.value
, skb
->data
[i
]);
100 /* Insert CRC in little endian format (LSB first) */
101 fcs
.value
= ~fcs
.value
;
102 #ifdef __LITTLE_ENDIAN
103 n
+= stuff_byte(fcs
.bytes
[0], tx_buff
+n
);
104 n
+= stuff_byte(fcs
.bytes
[1], tx_buff
+n
);
105 #else ifdef __BIG_ENDIAN
106 n
+= stuff_byte(fcs
.bytes
[1], tx_buff
+n
);
107 n
+= stuff_byte(fcs
.bytes
[0], tx_buff
+n
);
116 printk("%02x", tx_buff
[i
]);
124 * Function async_bump (idev)
126 * Got a frame, make a copy of it, and pass it up the stack!
129 static inline void async_bump(struct irda_device
*idev
, __u8
*buf
, int len
)
133 skb
= dev_alloc_skb(len
+1);
135 idev
->stats
.rx_dropped
++;
139 /* Align IP header to 20 bytes */
142 /* Copy data without CRC */
143 memcpy(skb_put(skb
, len
-2), buf
, len
-2);
146 * Feed it to IrLAP layer
148 skb
->dev
= &idev
->netdev
;
149 skb
->mac
.raw
= skb
->data
;
150 skb
->protocol
= htons(ETH_P_IRDA
);
153 idev
->stats
.rx_packets
++;
154 idev
->stats
.rx_bytes
+= skb
->len
;
158 * Function async_unwrap (skb)
160 * Parse and de-stuff frame received from the IR-port
163 void async_unwrap_char(struct irda_device
*idev
, __u8 byte
)
165 /* State machine for receiving frames */
166 switch (idev
->rx_buff
.state
) {
170 idev
->rx_buff
.state
= BEGIN_FRAME
;
171 idev
->rx_buff
.in_frame
= TRUE
;
177 irda_device_set_media_busy( idev
, TRUE
);
190 idev
->rx_buff
.state
= LINK_ESCAPE
;
194 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
196 idev
->stats
.rx_errors
++;
197 idev
->stats
.rx_frame_errors
++;
200 /* Got first byte of frame */
201 idev
->rx_buff
.data
= idev
->rx_buff
.head
;
202 idev
->rx_buff
.len
= 0;
204 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
206 idev
->rx_buff
.fcs
= IR_FCS(INIT_FCS
, byte
);
207 idev
->rx_buff
.state
= INSIDE_FRAME
;
215 idev
->rx_buff
.state
= BEGIN_FRAME
;
216 irda_device_set_media_busy(idev
, TRUE
);
219 DEBUG(4, "WARNING: State not defined\n");
223 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
227 * Stuffed char, complement bit 5 of byte
228 * following CE, IrLAP p.114
231 if (idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
232 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
233 idev
->rx_buff
.fcs
= IR_FCS(idev
->rx_buff
.fcs
,
235 idev
->rx_buff
.state
= INSIDE_FRAME
;
237 DEBUG(1, __FUNCTION__
238 "(), Rx buffer overflow, aborting\n");
239 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
248 idev
->rx_buff
.state
= BEGIN_FRAME
;
249 irda_device_set_media_busy(idev
, TRUE
);
253 idev
->rx_buff
.state
= LINK_ESCAPE
;
257 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
258 idev
->rx_buff
.in_frame
= FALSE
;
261 * Test FCS and deliver frame if it's good
263 if (idev
->rx_buff
.fcs
== GOOD_FCS
) {
264 async_bump(idev
, idev
->rx_buff
.data
,
267 /* Wrong CRC, discard frame! */
268 irda_device_set_media_busy(idev
, TRUE
);
270 idev
->stats
.rx_errors
++;
271 idev
->stats
.rx_crc_errors
++;
275 /* Next byte of frame */
276 if (idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
277 idev
->rx_buff
.data
[idev
->rx_buff
.len
++] = byte
;
278 idev
->rx_buff
.fcs
= IR_FCS(idev
->rx_buff
.fcs
,
281 DEBUG(1, __FUNCTION__
282 "(), Rx buffer overflow, aborting\n");
283 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
292 * Function stuff_byte (byte, buf)
294 * Byte stuff one single byte and put the result in buffer pointed to by
295 * buf. The buffer must at all times be able to have two bytes inserted.
298 inline static int stuff_byte(__u8 byte
, __u8
*buf
)
301 case BOF
: /* FALLTHROUGH */
302 case EOF
: /* FALLTHROUGH */
304 /* Insert transparently coded */
305 buf
[0] = CE
; /* Send link escape */
306 buf
[1] = byte
^IR_TRANS
; /* Complement bit 5 */
310 /* Non-special value, no transparency required */