* better
[mascara-docs.git] / i386 / linux-2.3.21 / net / irda / wrapper.c
blob5f5ed14f3b025be529f3d67feb9502c3313c66ac
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: Mon Sep 20 11:18:44 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
11 * Modified at: Fri May 28 3:11 CST 1999
12 * Modified by: Horst von Brand <vonbrand@sleipnir.valparaiso.cl>
14 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
15 * All Rights Reserved.
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License as
19 * published by the Free Software Foundation; either version 2 of
20 * the License, or (at your option) any later version.
22 * Neither Dag Brattli nor University of Tromsø admit liability nor
23 * provide warranty for any of this software. This material is
24 * provided "AS-IS" and at no charge.
26 ********************************************************************/
28 #include <linux/skbuff.h>
29 #include <linux/string.h>
30 #include <asm/byteorder.h>
32 #include <net/irda/irda.h>
33 #include <net/irda/wrapper.h>
34 #include <net/irda/irtty.h>
35 #include <net/irda/crc.h>
36 #include <net/irda/irlap.h>
37 #include <net/irda/irlap_frame.h>
38 #include <net/irda/irda_device.h>
40 static inline int stuff_byte(__u8 byte, __u8 *buf);
42 static void state_outside_frame(struct irda_device *idev, __u8 byte);
43 static void state_begin_frame(struct irda_device *idev, __u8 byte);
44 static void state_link_escape(struct irda_device *idev, __u8 byte);
45 static void state_inside_frame(struct irda_device *idev, __u8 byte);
47 static void (*state[])(struct irda_device *idev, __u8 byte) =
49 state_outside_frame,
50 state_begin_frame,
51 state_link_escape,
52 state_inside_frame,
56 * Function async_wrap (skb, *tx_buff, buffsize)
58 * Makes a new buffer with wrapping and stuffing, should check that
59 * we don't get tx buffer overflow.
61 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
63 int i;
64 int n;
65 int xbofs;
66 union {
67 __u16 value;
68 __u8 bytes[2];
69 } fcs;
71 /* Initialize variables */
72 fcs.value = INIT_FCS;
73 n = 0;
76 * Send XBOF's for required min. turn time and for the negotiated
77 * additional XBOFS
79 if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
80 DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
81 xbofs = 10;
82 } else
83 xbofs = ((struct irda_skb_cb *)(skb->cb))->xbofs;
85 memset(tx_buff+n, XBOF, xbofs);
86 n += xbofs;
88 /* Start of packet character BOF */
89 tx_buff[n++] = BOF;
91 /* Insert frame and calc CRC */
92 for (i=0; i < skb->len; i++) {
94 * Check for the possibility of tx buffer overflow. We use
95 * bufsize-5 since the maximum number of bytes that can be
96 * transmitted after this point is 5.
98 ASSERT(n < (buffsize-5), return n;);
100 n += stuff_byte(skb->data[i], tx_buff+n);
101 fcs.value = irda_fcs(fcs.value, skb->data[i]);
104 /* Insert CRC in little endian format (LSB first) */
105 fcs.value = ~fcs.value;
106 #ifdef __LITTLE_ENDIAN
107 n += stuff_byte(fcs.bytes[0], tx_buff+n);
108 n += stuff_byte(fcs.bytes[1], tx_buff+n);
109 #else ifdef __BIG_ENDIAN
110 n += stuff_byte(fcs.bytes[1], tx_buff+n);
111 n += stuff_byte(fcs.bytes[0], tx_buff+n);
112 #endif
113 tx_buff[n++] = EOF;
115 return n;
119 * Function async_bump (idev, buf, len)
121 * Got a frame, make a copy of it, and pass it up the stack!
124 static inline void async_bump(struct irda_device *idev, __u8 *buf, int len)
126 struct sk_buff *skb;
128 skb = dev_alloc_skb(len+1);
129 if (!skb) {
130 idev->stats.rx_dropped++;
131 return;
134 /* Align IP header to 20 bytes */
135 skb_reserve(skb, 1);
137 /* Copy data without CRC */
138 memcpy(skb_put(skb, len-2), buf, len-2);
141 * Feed it to IrLAP layer
143 skb->dev = &idev->netdev;
144 skb->mac.raw = skb->data;
145 skb->protocol = htons(ETH_P_IRDA);
147 netif_rx(skb);
148 idev->stats.rx_packets++;
149 idev->stats.rx_bytes += skb->len;
153 * Function stuff_byte (byte, buf)
155 * Byte stuff one single byte and put the result in buffer pointed to by
156 * buf. The buffer must at all times be able to have two bytes inserted.
159 static inline int stuff_byte(__u8 byte, __u8 *buf)
161 switch (byte) {
162 case BOF: /* FALLTHROUGH */
163 case EOF: /* FALLTHROUGH */
164 case CE:
165 /* Insert transparently coded */
166 buf[0] = CE; /* Send link escape */
167 buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */
168 return 2;
169 /* break; */
170 default:
171 /* Non-special value, no transparency required */
172 buf[0] = byte;
173 return 1;
174 /* break; */
179 * Function async_unwrap_char (idev, byte)
181 * Parse and de-stuff frame received from the IrDA-port
184 inline void async_unwrap_char(struct irda_device *idev, __u8 byte)
186 (*state[idev->rx_buff.state]) (idev, byte);
190 * Function state_outside_frame (idev, byte)
195 static void state_outside_frame(struct irda_device *idev, __u8 byte)
197 switch (byte) {
198 case BOF:
199 idev->rx_buff.state = BEGIN_FRAME;
200 idev->rx_buff.in_frame = TRUE;
201 break;
202 case XBOF:
203 /* idev->xbofs++; */
204 break;
205 case EOF:
206 irda_device_set_media_busy(&idev->netdev, TRUE);
207 break;
208 default:
209 break;
214 * Function state_begin_frame (idev, byte)
216 * Begin of frame detected
219 static void state_begin_frame(struct irda_device *idev, __u8 byte)
221 switch (byte) {
222 case BOF:
223 /* Continue */
224 break;
225 case CE:
226 /* Stuffed byte */
227 idev->rx_buff.state = LINK_ESCAPE;
229 /* Time to initialize receive buffer */
230 idev->rx_buff.data = idev->rx_buff.head;
231 idev->rx_buff.len = 0;
232 break;
233 case EOF:
234 /* Abort frame */
235 idev->rx_buff.state = OUTSIDE_FRAME;
237 idev->stats.rx_errors++;
238 idev->stats.rx_frame_errors++;
239 break;
240 default:
241 /* Time to initialize receive buffer */
242 idev->rx_buff.data = idev->rx_buff.head;
243 idev->rx_buff.len = 0;
245 idev->rx_buff.data[idev->rx_buff.len++] = byte;
247 idev->rx_buff.fcs = irda_fcs(INIT_FCS, byte);
248 idev->rx_buff.state = INSIDE_FRAME;
249 break;
254 * Function state_link_escape (idev, byte)
259 static void state_link_escape(struct irda_device *idev, __u8 byte)
261 switch (byte) {
262 case BOF: /* New frame? */
263 idev->rx_buff.state = BEGIN_FRAME;
264 irda_device_set_media_busy(&idev->netdev, TRUE);
265 break;
266 case CE:
267 DEBUG(4, "WARNING: State not defined\n");
268 break;
269 case EOF: /* Abort frame */
270 idev->rx_buff.state = OUTSIDE_FRAME;
271 break;
272 default:
274 * Stuffed char, complement bit 5 of byte
275 * following CE, IrLAP p.114
277 byte ^= IRDA_TRANS;
278 if (idev->rx_buff.len < idev->rx_buff.truesize) {
279 idev->rx_buff.data[idev->rx_buff.len++] = byte;
280 idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
281 idev->rx_buff.state = INSIDE_FRAME;
282 } else {
283 DEBUG(1, __FUNCTION__
284 "(), Rx buffer overflow, aborting\n");
285 idev->rx_buff.state = OUTSIDE_FRAME;
287 break;
292 * Function state_inside_frame (idev, byte)
294 * Handle bytes received within a frame
297 static void state_inside_frame(struct irda_device *idev, __u8 byte)
299 switch (byte) {
300 case BOF: /* New frame? */
301 idev->rx_buff.state = BEGIN_FRAME;
302 irda_device_set_media_busy(&idev->netdev, TRUE);
303 break;
304 case CE: /* Stuffed char */
305 idev->rx_buff.state = LINK_ESCAPE;
306 break;
307 case EOF: /* End of frame */
308 idev->rx_buff.state = OUTSIDE_FRAME;
309 idev->rx_buff.in_frame = FALSE;
311 /* Test FCS and deliver frame if it's good */
312 if (idev->rx_buff.fcs == GOOD_FCS) {
313 async_bump(idev, idev->rx_buff.data,
314 idev->rx_buff.len);
315 } else {
316 /* Wrong CRC, discard frame! */
317 irda_device_set_media_busy(&idev->netdev, TRUE);
319 idev->stats.rx_errors++;
320 idev->stats.rx_crc_errors++;
322 break;
323 default: /* Must be the next byte of the frame */
324 if (idev->rx_buff.len < idev->rx_buff.truesize) {
325 idev->rx_buff.data[idev->rx_buff.len++] = byte;
326 idev->rx_buff.fcs = irda_fcs(idev->rx_buff.fcs, byte);
327 } else {
328 DEBUG(1, __FUNCTION__
329 "(), Rx buffer overflow, aborting\n");
330 idev->rx_buff.state = OUTSIDE_FRAME;
332 break;