1 /*********************************************************************
5 * Description: IrDA 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: Sat Jan 16 22:05:45 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>
39 __inline__
static int stuff_byte( __u8 byte
, __u8
*buf
);
42 * Function async_wrap (skb, *tx_buff)
44 * Makes a new buffer with wrapping and stuffing, should check that
45 * we don't get tx buffer overflow.
47 int async_wrap_skb( struct sk_buff
*skb
, __u8
*tx_buff
, int buffsize
)
58 DEBUG( 6, __FUNCTION__
"()\n");
59 ASSERT( skb
!= NULL
, return 0;);
61 /* Initialize variables */
65 if ( skb
->len
> 2048) {
66 DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n",
73 * Send XBOF's for required min. turn time and for the negotiated
76 xbofs
= ((struct irlap_skb_cb
*)(skb
->cb
))->xbofs
;
77 for ( i
=0; i
<xbofs
; i
++) {
81 /* Start of packet character BOF */
84 /* Insert frame and calc CRC */
85 for( i
=0; i
< skb
->len
; i
++) {
89 * Check for the possibility of tx buffer overflow. We use
90 * bufsize-5 since the maximum number of bytes that can be
91 * transmitted after this point is 5.
93 if ( n
> buffsize
-5) {
95 "IrDA Wrapper: TX-buffer overflow!\n");
98 n
+=stuff_byte( byte
, tx_buff
+n
);
99 fcs
.value
= IR_FCS( fcs
.value
, byte
);
102 /* Insert CRC in little endian format (LSB first) */
103 fcs
.value
= ~fcs
.value
;
104 #ifdef __LITTLE_ENDIAN
105 n
+= stuff_byte( fcs
.bytes
[0], tx_buff
+n
);
106 n
+= stuff_byte( fcs
.bytes
[1], tx_buff
+n
);
107 #else ifdef __BIG_ENDIAN
108 n
+= stuff_byte( fcs
.bytes
[1], tx_buff
+n
);
109 n
+= stuff_byte( fcs
.bytes
[0], tx_buff
+n
);
117 * Function async_bump (idev)
119 * Got a frame, make a copy of it, and pass it up the stack!
122 static __inline__
void async_bump( struct irda_device
*idev
, __u8
*buf
,
127 skb
= dev_alloc_skb( len
+1);
129 printk( KERN_INFO __FUNCTION__
"() memory squeeze, "
130 "dropping frame.\n");
131 idev
->stats
.rx_dropped
++;
135 /* Align to 20 bytes */
136 skb_reserve( skb
, 1);
138 ASSERT( len
-2 > 0, return;);
140 /* Copy data without CRC */
141 skb_put( skb
, len
-2);
142 memcpy( skb
->data
, buf
, len
-2);
144 idev
->rx_buff
.len
= 0;
146 * Feed it to IrLAP layer
148 /* memcpy(skb_put(skb,count), ax->rbuff, count); */
149 skb
->dev
= &idev
->netdev
;
150 skb
->mac
.raw
= skb
->data
;
151 skb
->protocol
= htons(ETH_P_IRDA
);
154 idev
->stats
.rx_packets
++;
155 idev
->stats
.rx_bytes
+= skb
->len
;
159 * Function async_unwrap (skb)
161 * Parse and de-stuff frame received from the IR-port
164 void async_unwrap_char( struct irda_device
*idev
, __u8 byte
)
166 /* State machine for receiving frames */
167 switch( idev
->rx_buff
.state
) {
170 idev
->rx_buff
.state
= BEGIN_FRAME
;
171 idev
->rx_buff
.in_frame
= TRUE
;
172 } else if ( byte
== EOF
) {
173 irda_device_set_media_busy( idev
, TRUE
);
183 idev
->rx_buff
.state
= LINK_ESCAPE
;
187 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
189 idev
->stats
.rx_errors
++;
190 idev
->stats
.rx_frame_errors
++;
193 /* Got first byte of frame */
194 if ( idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
195 idev
->rx_buff
.data
[ idev
->rx_buff
.len
++] = byte
;
197 idev
->rx_buff
.fcs
= IR_FCS( INIT_FCS
, byte
);
198 idev
->rx_buff
.state
= INSIDE_FRAME
;
200 printk( "Rx buffer overflow\n");
208 DEBUG( 4, "New frame?\n");
209 idev
->rx_buff
.state
= BEGIN_FRAME
;
210 idev
->rx_buff
.len
= 0;
211 irda_device_set_media_busy( idev
, TRUE
);
214 DEBUG( 4, "WARNING: State not defined\n");
218 DEBUG( 0, "Abort frame (2)\n");
219 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
220 idev
->rx_buff
.len
= 0;
224 * Stuffed char, complement bit 5 of byte
225 * following CE, IrLAP p.114
228 if ( idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
229 idev
->rx_buff
.data
[ idev
->rx_buff
.len
++] = byte
;
231 idev
->rx_buff
.fcs
= IR_FCS( idev
->rx_buff
.fcs
, byte
);
232 idev
->rx_buff
.state
= INSIDE_FRAME
;
234 printk( "Rx buffer overflow\n");
242 idev
->rx_buff
.state
= BEGIN_FRAME
;
243 idev
->rx_buff
.len
= 0;
244 irda_device_set_media_busy( idev
, TRUE
);
248 idev
->rx_buff
.state
= LINK_ESCAPE
;
252 idev
->rx_buff
.state
= OUTSIDE_FRAME
;
253 idev
->rx_buff
.in_frame
= FALSE
;
256 * Test FCS and deliver frame if it's good
258 if ( idev
->rx_buff
.fcs
== GOOD_FCS
) {
259 async_bump( idev
, idev
->rx_buff
.data
,
262 /* Wrong CRC, discard frame! */
263 irda_device_set_media_busy( idev
, TRUE
);
264 idev
->rx_buff
.len
= 0;
266 idev
->stats
.rx_errors
++;
267 idev
->stats
.rx_crc_errors
++;
271 /* Next byte of frame */
272 if ( idev
->rx_buff
.len
< idev
->rx_buff
.truesize
) {
273 idev
->rx_buff
.data
[ idev
->rx_buff
.len
++] = byte
;
275 idev
->rx_buff
.fcs
= IR_FCS( idev
->rx_buff
.fcs
, byte
);
277 printk( "Rx buffer overflow\n");
285 * Function stuff_byte (byte, buf)
287 * Byte stuff one single byte and put the result in buffer pointed to by
288 * buf. The buffer must at all times be able to have two bytes inserted.
291 __inline__
static int stuff_byte( __u8 byte
, __u8
*buf
)
297 /* Insert transparently coded */
298 buf
[0] = CE
; /* Send link escape */
299 buf
[1] = byte
^IR_TRANS
; /* Complement bit 5 */
303 /* Non-special value, no transparency required */