Import 2.3.25pre1
[davej-history.git] / net / irda / wrapper.c
blobf884290f744a5d134c952a2488578c49fc5678b4
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 Oct 18 15:51:58 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 int state_outside_frame(struct net_device *dev,
43 struct iobuff_t *rx_buff, __u8 byte);
44 static int state_begin_frame(struct net_device *dev,
45 struct iobuff_t *rx_buff, __u8 byte);
46 static int state_link_escape(struct net_device *dev,
47 struct iobuff_t *rx_buff, __u8 byte);
48 static int state_inside_frame(struct net_device *dev,
49 struct iobuff_t *rx_buff, __u8 byte);
51 static int (*state[])(struct net_device *dev, struct iobuff_t *rx_buff,
52 __u8 byte) =
54 state_outside_frame,
55 state_begin_frame,
56 state_link_escape,
57 state_inside_frame,
61 * Function async_wrap (skb, *tx_buff, buffsize)
63 * Makes a new buffer with wrapping and stuffing, should check that
64 * we don't get tx buffer overflow.
66 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
68 int xbofs;
69 int i;
70 int n;
71 union {
72 __u16 value;
73 __u8 bytes[2];
74 } fcs;
76 /* Initialize variables */
77 fcs.value = INIT_FCS;
78 n = 0;
81 * Send XBOF's for required min. turn time and for the negotiated
82 * additional XBOFS
84 if (((struct irda_skb_cb *)(skb->cb))->magic != LAP_MAGIC) {
85 IRDA_DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
86 xbofs = 10;
87 } else
88 xbofs = ((struct irda_skb_cb *)(skb->cb))->xbofs;
90 memset(tx_buff+n, XBOF, xbofs);
91 n += xbofs;
93 /* Start of packet character BOF */
94 tx_buff[n++] = BOF;
96 /* Insert frame and calc CRC */
97 for (i=0; i < skb->len; i++) {
99 * Check for the possibility of tx buffer overflow. We use
100 * bufsize-5 since the maximum number of bytes that can be
101 * transmitted after this point is 5.
103 ASSERT(n < (buffsize-5), return n;);
105 n += stuff_byte(skb->data[i], tx_buff+n);
106 fcs.value = irda_fcs(fcs.value, skb->data[i]);
109 /* Insert CRC in little endian format (LSB first) */
110 fcs.value = ~fcs.value;
111 #ifdef __LITTLE_ENDIAN
112 n += stuff_byte(fcs.bytes[0], tx_buff+n);
113 n += stuff_byte(fcs.bytes[1], tx_buff+n);
114 #else ifdef __BIG_ENDIAN
115 n += stuff_byte(fcs.bytes[1], tx_buff+n);
116 n += stuff_byte(fcs.bytes[0], tx_buff+n);
117 #endif
118 tx_buff[n++] = EOF;
120 return n;
124 * Function stuff_byte (byte, buf)
126 * Byte stuff one single byte and put the result in buffer pointed to by
127 * buf. The buffer must at all times be able to have two bytes inserted.
130 static inline int stuff_byte(__u8 byte, __u8 *buf)
132 switch (byte) {
133 case BOF: /* FALLTHROUGH */
134 case EOF: /* FALLTHROUGH */
135 case CE:
136 /* Insert transparently coded */
137 buf[0] = CE; /* Send link escape */
138 buf[1] = byte^IRDA_TRANS; /* Complement bit 5 */
139 return 2;
140 /* break; */
141 default:
142 /* Non-special value, no transparency required */
143 buf[0] = byte;
144 return 1;
145 /* break; */
150 * Function async_bump (buf, len, stats)
152 * Got a frame, make a copy of it, and pass it up the stack!
155 int async_bump(struct net_device *dev, __u8 *buf, int len)
157 struct net_device_stats *stats = dev->get_stats(dev);
158 struct sk_buff *skb;
160 skb = dev_alloc_skb(len+1);
161 if (!skb) {
162 stats->rx_dropped++;
163 return -ENOMEM;
166 /* Align IP header to 20 bytes */
167 skb_reserve(skb, 1);
169 /* Copy data without CRC */
170 memcpy(skb_put(skb, len-2), buf, len-2);
172 /* Feed it to IrLAP layer */
173 skb->dev = dev;
174 skb->mac.raw = skb->data;
175 skb->protocol = htons(ETH_P_IRDA);
177 netif_rx(skb);
179 stats->rx_packets++;
180 stats->rx_bytes += len;
182 return skb->len;
186 * Function async_unwrap_char (dev, rx_buff, byte)
188 * Parse and de-stuff frame received from the IrDA-port
191 inline int async_unwrap_char(struct net_device *dev, struct iobuff_t *rx_buff,
192 __u8 byte)
194 return (*state[rx_buff->state])(dev, rx_buff, byte);
198 * Function state_outside_frame (dev, rx_buff, byte)
203 static int state_outside_frame(struct net_device *dev,
204 struct iobuff_t *rx_buff, __u8 byte)
206 switch (byte) {
207 case BOF:
208 rx_buff->state = BEGIN_FRAME;
209 rx_buff->in_frame = TRUE;
210 break;
211 case XBOF:
212 /* idev->xbofs++; */
213 break;
214 case EOF:
215 irda_device_set_media_busy(dev, TRUE);
216 break;
217 default:
218 break;
220 return 0;
224 * Function state_begin_frame (idev, byte)
226 * Begin of frame detected
229 static int state_begin_frame(struct net_device *dev,
230 struct iobuff_t *rx_buff, __u8 byte)
232 struct net_device_stats *stats = dev->get_stats(dev);
234 /* Time to initialize receive buffer */
235 rx_buff->data = rx_buff->head;
236 rx_buff->len = 0;
237 rx_buff->fcs = INIT_FCS;
239 switch (byte) {
240 case BOF:
241 /* Continue */
242 break;
243 case CE:
244 /* Stuffed byte */
245 rx_buff->state = LINK_ESCAPE;
246 break;
247 case EOF:
248 /* Abort frame */
249 rx_buff->state = OUTSIDE_FRAME;
251 stats->rx_errors++;
252 stats->rx_frame_errors++;
253 break;
254 default:
255 rx_buff->data[rx_buff->len++] = byte;
257 rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
258 rx_buff->state = INSIDE_FRAME;
259 break;
261 return 0;
265 * Function state_link_escape (idev, byte)
270 static int state_link_escape(struct net_device *dev,
271 struct iobuff_t *rx_buff, __u8 byte)
273 switch (byte) {
274 case BOF: /* New frame? */
275 rx_buff->state = BEGIN_FRAME;
276 irda_device_set_media_busy(dev, TRUE);
277 break;
278 case CE:
279 IRDA_DEBUG(4, "WARNING: State not defined\n");
280 break;
281 case EOF: /* Abort frame */
282 rx_buff->state = OUTSIDE_FRAME;
283 break;
284 default:
286 * Stuffed char, complement bit 5 of byte
287 * following CE, IrLAP p.114
289 byte ^= IRDA_TRANS;
290 if (rx_buff->len < rx_buff->truesize) {
291 rx_buff->data[rx_buff->len++] = byte;
292 rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
293 rx_buff->state = INSIDE_FRAME;
294 } else {
295 IRDA_DEBUG(1, __FUNCTION__
296 "(), Rx buffer overflow, aborting\n");
297 rx_buff->state = OUTSIDE_FRAME;
299 break;
301 return 0;
305 * Function state_inside_frame (idev, byte)
307 * Handle bytes received within a frame
310 static int state_inside_frame(struct net_device *dev,
311 struct iobuff_t *rx_buff, __u8 byte)
313 struct net_device_stats *stats = dev->get_stats(dev);
314 int ret = 0;
316 switch (byte) {
317 case BOF: /* New frame? */
318 rx_buff->state = BEGIN_FRAME;
319 irda_device_set_media_busy(dev, TRUE);
320 break;
321 case CE: /* Stuffed char */
322 rx_buff->state = LINK_ESCAPE;
323 break;
324 case EOF: /* End of frame */
325 rx_buff->state = OUTSIDE_FRAME;
326 rx_buff->in_frame = FALSE;
328 /* Test FCS and signal success if the frame is good */
329 if (rx_buff->fcs == GOOD_FCS) {
330 /* Deliver frame */
331 async_bump(dev, rx_buff->data, rx_buff->len);
332 ret = TRUE;
333 break;
334 } else {
335 /* Wrong CRC, discard frame! */
336 irda_device_set_media_busy(dev, TRUE);
338 stats->rx_errors++;
339 stats->rx_crc_errors++;
341 break;
342 default: /* Must be the next byte of the frame */
343 if (rx_buff->len < rx_buff->truesize) {
344 rx_buff->data[rx_buff->len++] = byte;
345 rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
346 } else {
347 IRDA_DEBUG(1, __FUNCTION__
348 "(), Rx buffer overflow, aborting\n");
349 rx_buff->state = OUTSIDE_FRAME;
351 break;
353 return 0;