Import 2.3.4pre3
[davej-history.git] / net / irda / wrapper.c
blobb78368bc0e69c17d7da206ce9576c063fa75467f
1 /*********************************************************************
2 *
3 * Filename: wrapper.c
4 * Version: 1.2
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: Sun May 2 21:58:00 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1998-1999 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 static inline int stuff_byte(__u8 byte, __u8 *buf);
39 static void state_outside_frame(struct irda_device *idev, __u8 byte);
40 static void state_begin_frame(struct irda_device *idev, __u8 byte);
41 static void state_link_escape(struct irda_device *idev, __u8 byte);
42 static void state_inside_frame(struct irda_device *idev, __u8 byte);
44 static void (*state[])(struct irda_device *idev, __u8 byte) =
46 state_outside_frame,
47 state_begin_frame,
48 state_link_escape,
49 state_inside_frame,
53 * Function async_wrap (skb, *tx_buff)
55 * Makes a new buffer with wrapping and stuffing, should check that
56 * we don't get tx buffer overflow.
58 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
60 int i;
61 int n;
62 int xbofs;
63 union {
64 __u16 value;
65 __u8 bytes[2];
66 } fcs;
68 /* Initialize variables */
69 fcs.value = INIT_FCS;
70 n = 0;
72 if (skb->len > 2048) {
73 DEBUG(0, __FUNCTION__ "Warning size=%d of sk_buff to big!\n",
74 (int) skb->len);
75 return 0;
79 * Send XBOF's for required min. turn time and for the negotiated
80 * additional XBOFS
82 if (((struct irlap_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
83 DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
84 xbofs = 10;
85 } else
86 xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
88 memset(tx_buff+n, XBOF, xbofs);
89 n += xbofs;
91 /* Start of packet character BOF */
92 tx_buff[n++] = BOF;
94 /* Insert frame and calc CRC */
95 for (i=0; i < skb->len; i++) {
97 * Check for the possibility of tx buffer overflow. We use
98 * bufsize-5 since the maximum number of bytes that can be
99 * transmitted after this point is 5.
101 ASSERT(n < (buffsize-5), return n;);
103 n += stuff_byte(skb->data[i], tx_buff+n);
104 fcs.value = irda_fcs(fcs.value, skb->data[i]);
107 /* Insert CRC in little endian format (LSB first) */
108 fcs.value = ~fcs.value;
109 #ifdef __LITTLE_ENDIAN
110 n += stuff_byte(fcs.bytes[0], tx_buff+n);
111 n += stuff_byte(fcs.bytes[1], tx_buff+n);
112 #else ifdef __BIG_ENDIAN
113 n += stuff_byte(fcs.bytes[1], tx_buff+n);
114 n += stuff_byte(fcs.bytes[0], tx_buff+n);
115 #endif
116 tx_buff[n++] = EOF;
118 return n;
122 * Function async_bump (idev)
124 * Got a frame, make a copy of it, and pass it up the stack!
127 static inline void async_bump(struct irda_device *idev, __u8 *buf, int len)
129 struct sk_buff *skb;
131 skb = dev_alloc_skb(len+1);
132 if (!skb) {
133 idev->stats.rx_dropped++;
134 return;
137 /* Align IP header to 20 bytes */
138 skb_reserve(skb, 1);
140 /* Copy data without CRC */
141 memcpy(skb_put(skb, len-2), buf, len-2);
144 * Feed it to IrLAP layer
146 skb->dev = &idev->netdev;
147 skb->mac.raw = skb->data;
148 skb->protocol = htons(ETH_P_IRDA);
150 netif_rx(skb);
151 idev->stats.rx_packets++;
152 idev->stats.rx_bytes += skb->len;
156 * Function stuff_byte (byte, buf)
158 * Byte stuff one single byte and put the result in buffer pointed to by
159 * buf. The buffer must at all times be able to have two bytes inserted.
162 static inline int stuff_byte(__u8 byte, __u8 *buf)
164 switch (byte) {
165 case BOF: /* FALLTHROUGH */
166 case EOF: /* FALLTHROUGH */
167 case CE:
168 /* Insert transparently coded */
169 buf[0] = CE; /* Send link escape */
170 buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */
171 return 2;
172 /* break; */
173 default:
174 /* Non-special value, no transparency required */
175 buf[0] = byte;
176 return 1;
177 /* break; */
182 * Function async_unwrap (skb)
184 * Parse and de-stuff frame received from the IrDA-port
187 inline void async_unwrap_char(struct irda_device *idev, __u8 byte)
189 (*state[idev->rx_buff.state]) (idev, byte);
193 * Function state_outside_frame (idev, byte)
198 static void state_outside_frame(struct irda_device *idev, __u8 byte)
200 switch (byte) {
201 case BOF:
202 idev->rx_buff.state = BEGIN_FRAME;
203 idev->rx_buff.in_frame = TRUE;
204 break;
205 case XBOF:
206 /* idev->xbofs++; */
207 break;
208 case EOF:
209 irda_device_set_media_busy( idev, TRUE);
210 break;
211 default:
212 break;
217 * Function state_begin_frame (idev, byte)
222 static void state_begin_frame(struct irda_device *idev, __u8 byte)
224 switch (byte) {
225 case BOF:
226 /* Continue */
227 break;
228 case CE:
229 /* Stuffed byte */
230 idev->rx_buff.state = LINK_ESCAPE;
231 break;
232 case EOF:
233 /* Abort frame */
234 idev->rx_buff.state = OUTSIDE_FRAME;
236 idev->stats.rx_errors++;
237 idev->stats.rx_frame_errors++;
238 break;
239 default:
240 /* Got first byte of frame */
241 idev->rx_buff.data = idev->rx_buff.head;
242 idev->rx_buff.len = 0;
244 idev->rx_buff.data[idev->rx_buff.len++] = byte;
246 idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
247 idev->rx_buff.state = INSIDE_FRAME;
248 break;
253 * Function state_link_escape (idev, byte)
258 static void state_link_escape(struct irda_device *idev, __u8 byte)
260 switch (byte) {
261 case BOF: /* New frame? */
262 idev->rx_buff.state = BEGIN_FRAME;
263 irda_device_set_media_busy(idev, TRUE);
264 break;
265 case CE:
266 DEBUG(4, "WARNING: State not defined\n");
267 break;
268 case EOF: /* Abort frame */
269 idev->rx_buff.state = OUTSIDE_FRAME;
270 break;
271 default:
273 * Stuffed char, complement bit 5 of byte
274 * following CE, IrLAP p.114
276 byte ^= IRDA_TRANS;
277 if (idev->rx_buff.len < idev->rx_buff.truesize) {
278 idev->rx_buff.data[idev->rx_buff.len++] = byte;
279 idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
280 idev->rx_buff.state = INSIDE_FRAME;
281 } else {
282 DEBUG(1, __FUNCTION__
283 "(), Rx buffer overflow, aborting\n");
284 idev->rx_buff.state = OUTSIDE_FRAME;
286 break;
291 * Function state_inside_frame (idev, byte)
296 static void state_inside_frame(struct irda_device *idev, __u8 byte)
298 switch (byte) {
299 case BOF: /* New frame? */
300 idev->rx_buff.state = BEGIN_FRAME;
301 irda_device_set_media_busy(idev, TRUE);
302 break;
303 case CE: /* Stuffed char */
304 idev->rx_buff.state = LINK_ESCAPE;
305 break;
306 case EOF: /* End of frame */
307 idev->rx_buff.state = OUTSIDE_FRAME;
308 idev->rx_buff.in_frame = FALSE;
310 /* Test FCS and deliver frame if it's good */
311 if (idev->rx_buff.fcs == GOOD_FCS) {
312 async_bump(idev, idev->rx_buff.data,
313 idev->rx_buff.len);
314 } else {
315 /* Wrong CRC, discard frame! */
316 irda_device_set_media_busy(idev, TRUE);
318 idev->stats.rx_errors++;
319 idev->stats.rx_crc_errors++;
321 break;
322 default: /* Must be the next byte of the frame */
323 if (idev->rx_buff.len < idev->rx_buff.truesize) {
324 idev->rx_buff.data[idev->rx_buff.len++] = byte;
325 idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
326 } else {
327 DEBUG(1, __FUNCTION__
328 "(), Rx buffer overflow, aborting\n");
329 idev->rx_buff.state = OUTSIDE_FRAME;
331 break;