import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / net / irda / wrapper.c
1 /*********************************************************************
2  *                
3  * Filename:      wrapper.c
4  * Version:       1.2
5  * Description:   IrDA SIR async wrapper layer
6  * Status:        Stable
7  * Author:        Dag Brattli <dagb@cs.uit.no>
8  * Created at:    Mon Aug  4 20:40:53 1997
9  * Modified at:   Fri Jan 28 13:21:09 2000
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>
13  * 
14  *     Copyright (c) 1998-2000 Dag Brattli <dagb@cs.uit.no>, 
15  *     All Rights Reserved.
16  *     
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.
21  *
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.
25  *
26  ********************************************************************/
27
28 #include <linux/skbuff.h>
29 #include <linux/string.h>
30 #include <asm/byteorder.h>
31
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>
39
40 static inline int stuff_byte(__u8 byte, __u8 *buf);
41
42 static void state_outside_frame(struct net_device *dev, 
43                                 struct net_device_stats *stats, 
44                                 iobuff_t *rx_buff, __u8 byte);
45 static void state_begin_frame(struct net_device *dev, 
46                               struct net_device_stats *stats, 
47                               iobuff_t *rx_buff, __u8 byte);
48 static void state_link_escape(struct net_device *dev, 
49                               struct net_device_stats *stats, 
50                               iobuff_t *rx_buff, __u8 byte);
51 static void state_inside_frame(struct net_device *dev, 
52                                struct net_device_stats *stats, 
53                                iobuff_t *rx_buff, __u8 byte);
54
55 static void (*state[])(struct net_device *dev, struct net_device_stats *stats, 
56                        iobuff_t *rx_buff, __u8 byte) = 
57
58         state_outside_frame,
59         state_begin_frame,
60         state_link_escape,
61         state_inside_frame,
62 };
63
64 /*
65  * Function async_wrap (skb, *tx_buff, buffsize)
66  *
67  *    Makes a new buffer with wrapping and stuffing, should check that 
68  *    we don't get tx buffer overflow.
69  */
70 int async_wrap_skb(struct sk_buff *skb, __u8 *tx_buff, int buffsize)
71 {
72         struct irda_skb_cb *cb = (struct irda_skb_cb *) skb->cb;
73         int xbofs;
74         int i;
75         int n;
76         union {
77                 __u16 value;
78                 __u8 bytes[2];
79         } fcs;
80
81         /* Initialize variables */
82         fcs.value = INIT_FCS;
83         n = 0;
84
85         /*
86          *  Send  XBOF's for required min. turn time and for the negotiated
87          *  additional XBOFS
88          */
89         
90         if (cb->magic != LAP_MAGIC) {
91                 /* 
92                  * This will happen for all frames sent from user-space.
93                  * Nothing to worry about, but we set the default number of 
94                  * BOF's
95                  */
96                 IRDA_DEBUG(1, __FUNCTION__ "(), wrong magic in skb!\n");
97                 xbofs = 10;
98         } else
99                 xbofs = cb->xbofs + cb->xbofs_delay;
100
101         IRDA_DEBUG(4, __FUNCTION__ "(), xbofs=%d\n", xbofs);
102
103         /* Check that we never use more than 115 + 48 xbofs */
104         if (xbofs > 163) {
105                 IRDA_DEBUG(0, __FUNCTION__ "(), too many xbofs (%d)\n", xbofs);
106                 xbofs = 163;
107         }
108
109         memset(tx_buff+n, XBOF, xbofs);
110         n += xbofs;
111
112         /* Start of packet character BOF */
113         tx_buff[n++] = BOF;
114
115         /* Insert frame and calc CRC */
116         for (i=0; i < skb->len; i++) {
117                 /*
118                  *  Check for the possibility of tx buffer overflow. We use
119                  *  bufsize-5 since the maximum number of bytes that can be 
120                  *  transmitted after this point is 5.
121                  */
122                 ASSERT(n < (buffsize-5), return n;);
123
124                 n += stuff_byte(skb->data[i], tx_buff+n);
125                 fcs.value = irda_fcs(fcs.value, skb->data[i]);
126         }
127         
128         /* Insert CRC in little endian format (LSB first) */
129         fcs.value = ~fcs.value;
130 #ifdef __LITTLE_ENDIAN
131         n += stuff_byte(fcs.bytes[0], tx_buff+n);
132         n += stuff_byte(fcs.bytes[1], tx_buff+n);
133 #else /* ifdef __BIG_ENDIAN */
134         n += stuff_byte(fcs.bytes[1], tx_buff+n);
135         n += stuff_byte(fcs.bytes[0], tx_buff+n);
136 #endif
137         tx_buff[n++] = EOF;
138
139         return n;
140 }
141
142 /*
143  * Function stuff_byte (byte, buf)
144  *
145  *    Byte stuff one single byte and put the result in buffer pointed to by
146  *    buf. The buffer must at all times be able to have two bytes inserted.
147  * 
148  */
149 static inline int stuff_byte(__u8 byte, __u8 *buf) 
150 {
151         switch (byte) {
152         case BOF: /* FALLTHROUGH */
153         case EOF: /* FALLTHROUGH */
154         case CE:
155                 /* Insert transparently coded */
156                 buf[0] = CE;               /* Send link escape */
157                 buf[1] = byte^IRDA_TRANS;    /* Complement bit 5 */
158                 return 2;
159                 /* break; */
160         default:
161                  /* Non-special value, no transparency required */
162                 buf[0] = byte;
163                 return 1;
164                 /* break; */
165         }
166 }
167
168 /*
169  * Function async_bump (buf, len, stats)
170  *
171  *    Got a frame, make a copy of it, and pass it up the stack! We can try
172  *    to inline it since it's only called from state_inside_frame
173  */
174 inline void async_bump(struct net_device *dev, struct net_device_stats *stats,
175                        __u8 *buf, int len)
176 {
177         struct sk_buff *skb;
178
179         skb = dev_alloc_skb(len+1);
180         if (!skb)  {
181                 stats->rx_dropped++;
182                 return;
183         }
184
185         /* Align IP header to 20 bytes */
186         skb_reserve(skb, 1);
187         
188         /* Copy data without CRC */
189         memcpy(skb_put(skb, len-2), buf, len-2); 
190         
191         /* Feed it to IrLAP layer */
192         skb->dev = dev;
193         skb->mac.raw  = skb->data;
194         skb->protocol = htons(ETH_P_IRDA);
195
196         netif_rx(skb);
197
198         stats->rx_packets++;
199         stats->rx_bytes += len; 
200 }
201
202 /*
203  * Function async_unwrap_char (dev, rx_buff, byte)
204  *
205  *    Parse and de-stuff frame received from the IrDA-port
206  *
207  */
208 inline void async_unwrap_char(struct net_device *dev, 
209                               struct net_device_stats *stats, 
210                               iobuff_t *rx_buff, __u8 byte)
211 {
212         (*state[rx_buff->state])(dev, stats, rx_buff, byte);
213 }
214          
215 /*
216  * Function state_outside_frame (dev, rx_buff, byte)
217  *
218  *    Not receiving any frame (or just bogus data)
219  *
220  */
221 static void state_outside_frame(struct net_device *dev, 
222                                 struct net_device_stats *stats, 
223                                 iobuff_t *rx_buff, __u8 byte)
224 {
225         switch (byte) {
226         case BOF:
227                 rx_buff->state = BEGIN_FRAME;
228                 rx_buff->in_frame = TRUE;
229                 break;
230         case XBOF:
231                 /* idev->xbofs++; */
232                 break;
233         case EOF:
234                 irda_device_set_media_busy(dev, TRUE);
235                 break;
236         default:
237                 irda_device_set_media_busy(dev, TRUE);
238                 break;
239         }
240 }
241
242 /*
243  * Function state_begin_frame (idev, byte)
244  *
245  *    Begin of frame detected
246  *
247  */
248 static void state_begin_frame(struct net_device *dev, 
249                               struct net_device_stats *stats, 
250                               iobuff_t *rx_buff, __u8 byte)
251 {
252         /* Time to initialize receive buffer */
253         rx_buff->data = rx_buff->head;
254         rx_buff->len = 0;
255         rx_buff->fcs = INIT_FCS;
256
257         switch (byte) {
258         case BOF:
259                 /* Continue */
260                 break;
261         case CE:
262                 /* Stuffed byte */
263                 rx_buff->state = LINK_ESCAPE;
264                 break;
265         case EOF:
266                 /* Abort frame */
267                 rx_buff->state = OUTSIDE_FRAME;
268                 IRDA_DEBUG(1, __FUNCTION__ "(), abort frame\n");
269                 stats->rx_errors++;
270                 stats->rx_frame_errors++;
271                 break;
272         default:
273                 rx_buff->data[rx_buff->len++] = byte;
274                 rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
275                 rx_buff->state = INSIDE_FRAME;
276                 break;
277         }
278 }
279
280 /*
281  * Function state_link_escape (dev, byte)
282  *
283  *    Found link escape character
284  *
285  */
286 static void state_link_escape(struct net_device *dev, 
287                               struct net_device_stats *stats, 
288                               iobuff_t *rx_buff, __u8 byte)
289 {
290         switch (byte) {
291         case BOF: /* New frame? */
292                 IRDA_DEBUG(1, __FUNCTION__ 
293                            "(), Discarding incomplete frame\n");
294                 rx_buff->state = BEGIN_FRAME;
295                 irda_device_set_media_busy(dev, TRUE);
296                 break;
297         case CE:
298                 WARNING(__FUNCTION__ "(), state not defined\n");
299                 break;
300         case EOF: /* Abort frame */
301                 rx_buff->state = OUTSIDE_FRAME;
302                 break;
303         default:
304                 /* 
305                  *  Stuffed char, complement bit 5 of byte 
306                  *  following CE, IrLAP p.114 
307                  */
308                 byte ^= IRDA_TRANS;
309                 if (rx_buff->len < rx_buff->truesize)  {
310                         rx_buff->data[rx_buff->len++] = byte;
311                         rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
312                         rx_buff->state = INSIDE_FRAME;
313                 } else {
314                         IRDA_DEBUG(1, __FUNCTION__ "(), rx buffer overflow\n");
315                         rx_buff->state = OUTSIDE_FRAME;
316                 }
317                 break;
318         }
319 }
320
321 /*
322  * Function state_inside_frame (dev, byte)
323  *
324  *    Handle bytes received within a frame
325  *
326  */
327 static void state_inside_frame(struct net_device *dev, 
328                                struct net_device_stats *stats,
329                                iobuff_t *rx_buff, __u8 byte)
330 {
331         int ret = 0; 
332
333         switch (byte) {
334         case BOF: /* New frame? */
335                 IRDA_DEBUG(1, __FUNCTION__ 
336                            "(), Discarding incomplete frame\n");
337                 rx_buff->state = BEGIN_FRAME;
338                 irda_device_set_media_busy(dev, TRUE);
339                 break;
340         case CE: /* Stuffed char */
341                 rx_buff->state = LINK_ESCAPE;
342                 break;
343         case EOF: /* End of frame */
344                 rx_buff->state = OUTSIDE_FRAME;
345                 rx_buff->in_frame = FALSE;
346                 
347                 /* Test FCS and signal success if the frame is good */
348                 if (rx_buff->fcs == GOOD_FCS) {
349                         /* Deliver frame */
350                         async_bump(dev, stats, rx_buff->data, rx_buff->len);
351                         ret = TRUE;
352                         break;
353                 } else {
354                         /* Wrong CRC, discard frame!  */
355                         irda_device_set_media_busy(dev, TRUE); 
356
357                         IRDA_DEBUG(1, __FUNCTION__ "(), crc error\n");
358                         stats->rx_errors++;
359                         stats->rx_crc_errors++;
360                 }                       
361                 break;
362         default: /* Must be the next byte of the frame */
363                 if (rx_buff->len < rx_buff->truesize)  {
364                         rx_buff->data[rx_buff->len++] = byte;
365                         rx_buff->fcs = irda_fcs(rx_buff->fcs, byte);
366                 } else {
367                         IRDA_DEBUG(1, __FUNCTION__ 
368                               "(), Rx buffer overflow, aborting\n");
369                         rx_buff->state = OUTSIDE_FRAME;
370                 }
371                 break;
372         }
373 }
374
375