Import 2.2.8pre3
[davej-history.git] / net / irda / wrapper.c
blobc4822e2c6e8655bb9531ff4066678bcc4130b921
1 /*********************************************************************
2 *
3 * Filename: wrapper.c
4 * Version: 1.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)
47 int i;
48 int n;
49 int xbofs;
50 union {
51 __u16 value;
52 __u8 bytes[2];
53 } fcs;
55 ASSERT(skb != NULL, return 0;);
57 /* Initialize variables */
58 fcs.value = INIT_FCS;
59 n = 0;
61 if (skb->len > 2048) {
62 DEBUG(0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n",
63 (int) skb->len);
64 return 0;
68 * Send XBOF's for required min. turn time and for the negotiated
69 * additional XBOFS
71 if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
72 DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
73 xbofs = 10;
74 } else
75 xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
77 #if 0
78 for (i=0; i<xbofs; i++)
79 tx_buff[n++] = XBOF;
80 #else
81 memset(tx_buff+n, XBOF, xbofs);
82 n += xbofs;
83 #endif
84 /* Start of packet character BOF */
85 tx_buff[n++] = 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);
108 #endif
109 tx_buff[n++] = EOF;
111 #if 0
113 int i;
115 for (i=0;i<n;i++)
116 printk("%02x", tx_buff[i]);
117 printk("\n");
119 #endif
120 return n;
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)
131 struct sk_buff *skb;
133 skb = dev_alloc_skb(len+1);
134 if (!skb) {
135 idev->stats.rx_dropped++;
136 return;
139 /* Align IP header to 20 bytes */
140 skb_reserve(skb, 1);
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);
152 netif_rx(skb);
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) {
167 case OUTSIDE_FRAME:
168 switch(byte) {
169 case BOF:
170 idev->rx_buff.state = BEGIN_FRAME;
171 idev->rx_buff.in_frame = TRUE;
172 break;
173 case XBOF:
174 /* idev->xbofs++; */
175 break;
176 case EOF:
177 irda_device_set_media_busy( idev, TRUE);
178 break;
179 default:
180 break;
182 break;
183 case BEGIN_FRAME:
184 switch (byte) {
185 case BOF:
186 /* Continue */
187 break;
188 case CE:
189 /* Stuffed byte */
190 idev->rx_buff.state = LINK_ESCAPE;
191 break;
192 case EOF:
193 /* Abort frame */
194 idev->rx_buff.state = OUTSIDE_FRAME;
196 idev->stats.rx_errors++;
197 idev->stats.rx_frame_errors++;
198 break;
199 default:
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;
208 break;
210 break;
211 case LINK_ESCAPE:
212 switch (byte) {
213 case BOF:
214 /* New frame? */
215 idev->rx_buff.state = BEGIN_FRAME;
216 irda_device_set_media_busy(idev, TRUE);
217 break;
218 case CE:
219 DEBUG(4, "WARNING: State not defined\n");
220 break;
221 case EOF:
222 /* Abort frame */
223 idev->rx_buff.state = OUTSIDE_FRAME;
224 break;
225 default:
227 * Stuffed char, complement bit 5 of byte
228 * following CE, IrLAP p.114
230 byte ^= IR_TRANS;
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,
234 byte);
235 idev->rx_buff.state = INSIDE_FRAME;
236 } else {
237 DEBUG(1, __FUNCTION__
238 "(), Rx buffer overflow, aborting\n");
239 idev->rx_buff.state = OUTSIDE_FRAME;
241 break;
243 break;
244 case INSIDE_FRAME:
245 switch (byte) {
246 case BOF:
247 /* New frame? */
248 idev->rx_buff.state = BEGIN_FRAME;
249 irda_device_set_media_busy(idev, TRUE);
250 break;
251 case CE:
252 /* Stuffed char */
253 idev->rx_buff.state = LINK_ESCAPE;
254 break;
255 case EOF:
256 /* End of frame */
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,
265 idev->rx_buff.len);
266 } else {
267 /* Wrong CRC, discard frame! */
268 irda_device_set_media_busy(idev, TRUE);
270 idev->stats.rx_errors++;
271 idev->stats.rx_crc_errors++;
273 break;
274 default:
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,
279 byte);
280 } else {
281 DEBUG(1, __FUNCTION__
282 "(), Rx buffer overflow, aborting\n");
283 idev->rx_buff.state = OUTSIDE_FRAME;
285 break;
287 break;
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)
300 switch (byte) {
301 case BOF: /* FALLTHROUGH */
302 case EOF: /* FALLTHROUGH */
303 case CE:
304 /* Insert transparently coded */
305 buf[0] = CE; /* Send link escape */
306 buf[1] = byte^IR_TRANS; /* Complement bit 5 */
307 return 2;
308 /* break; */
309 default:
310 /* Non-special value, no transparency required */
311 buf[0] = byte;
312 return 1;
313 /* break; */