2.2.0-final
[davej-history.git] / net / irda / wrapper.c
blobfdebb5788e70dcda6ef5461d8a7cca26d1fc2682
1 /*********************************************************************
2 *
3 * Filename: wrapper.c
4 * Version:
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>
37 #define MIN_LENGTH 14
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)
49 __u8 byte;
50 int i, n;
51 int xbofs;
52 union {
53 __u16 value;
54 __u8 bytes[2];
55 } fcs;
58 DEBUG( 6, __FUNCTION__ "()\n");
59 ASSERT( skb != NULL, return 0;);
61 /* Initialize variables */
62 fcs.value = INIT_FCS;
63 n = 0;
65 if ( skb->len > 2048) {
66 DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n",
67 (int) skb->len);
69 return 0;
73 * Send XBOF's for required min. turn time and for the negotiated
74 * additional XBOFS
76 xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
77 for ( i=0; i<xbofs; i++) {
78 tx_buff[n++] = XBOF;
81 /* Start of packet character BOF */
82 tx_buff[n++] = BOF;
84 /* Insert frame and calc CRC */
85 for( i=0; i < skb->len; i++) {
86 byte = skb->data[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) {
94 printk( KERN_WARNING
95 "IrDA Wrapper: TX-buffer overflow!\n");
96 return 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);
110 #endif
111 tx_buff[n++] = EOF;
113 return 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,
123 int len)
125 struct sk_buff *skb;
127 skb = dev_alloc_skb( len+1);
128 if (skb == NULL) {
129 printk( KERN_INFO __FUNCTION__ "() memory squeeze, "
130 "dropping frame.\n");
131 idev->stats.rx_dropped++;
132 return;
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);
153 netif_rx( skb);
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) {
168 case OUTSIDE_FRAME:
169 if ( byte == BOF) {
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);
175 break;
176 case BEGIN_FRAME:
177 switch ( byte) {
178 case BOF:
179 /* Continue */
180 break;
181 case CE:
182 /* Stuffed byte */
183 idev->rx_buff.state = LINK_ESCAPE;
184 break;
185 case EOF:
186 /* Abort frame */
187 idev->rx_buff.state = OUTSIDE_FRAME;
189 idev->stats.rx_errors++;
190 idev->stats.rx_frame_errors++;
191 break;
192 default:
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;
199 } else
200 printk( "Rx buffer overflow\n");
201 break;
203 break;
204 case LINK_ESCAPE:
205 switch ( byte) {
206 case BOF:
207 /* New frame? */
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);
212 break;
213 case CE:
214 DEBUG( 4, "WARNING: State not defined\n");
215 break;
216 case EOF:
217 /* Abort frame */
218 DEBUG( 0, "Abort frame (2)\n");
219 idev->rx_buff.state = OUTSIDE_FRAME;
220 idev->rx_buff.len = 0;
221 break;
222 default:
224 * Stuffed char, complement bit 5 of byte
225 * following CE, IrLAP p.114
227 byte ^= IR_TRANS;
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;
233 } else
234 printk( "Rx buffer overflow\n");
235 break;
237 break;
238 case INSIDE_FRAME:
239 switch ( byte) {
240 case BOF:
241 /* New frame? */
242 idev->rx_buff.state = BEGIN_FRAME;
243 idev->rx_buff.len = 0;
244 irda_device_set_media_busy( idev, TRUE);
245 break;
246 case CE:
247 /* Stuffed char */
248 idev->rx_buff.state = LINK_ESCAPE;
249 break;
250 case EOF:
251 /* End of frame */
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,
260 idev->rx_buff.len);
261 } else {
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++;
269 break;
270 default:
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);
276 } else
277 printk( "Rx buffer overflow\n");
278 break;
280 break;
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)
293 switch ( byte) {
294 case BOF:
295 case EOF:
296 case CE:
297 /* Insert transparently coded */
298 buf[0] = CE; /* Send link escape */
299 buf[1] = byte^IR_TRANS; /* Complement bit 5 */
300 return 2;
301 /* break; */
302 default:
303 /* Non-special value, no transparency required */
304 buf[0] = byte;
305 return 1;
306 /* break; */