patch-2.1.132 linux/net/irda/wrapper.c
Next file: linux/net/protocols.c
Previous file: linux/net/irda/timer.c
Back to the patch index
Back to the overall index
- Lines: 319
- Date:
Thu Dec 17 09:01:03 1998
- Orig file:
v2.1.131/linux/net/irda/wrapper.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.131/linux/net/irda/wrapper.c linux/net/irda/wrapper.c
@@ -0,0 +1,318 @@
+/*********************************************************************
+ *
+ * Filename: wrapper.c
+ * Version:
+ * Description: IrDA Wrapper layer
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Mon Aug 4 20:40:53 1997
+ * Modified at: Wed Dec 9 01:35:53 1998
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>,
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * Neither Dag Brattli nor University of Tromsų admit liability nor
+ * provide warranty for any of this software. This material is
+ * provided "AS-IS" and at no charge.
+ *
+ ********************************************************************/
+
+#include <linux/skbuff.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/wrapper.h>
+#include <net/irda/irtty.h>
+#include <net/irda/crc.h>
+#include <net/irda/irlap.h>
+#include <net/irda/irlap_frame.h>
+#include <net/irda/irda_device.h>
+
+#define MIN_LENGTH 14
+
+__inline__ static int stuff_byte( __u8 byte, __u8 *buf);
+
+/*
+ * Function async_wrap (skb, *tx_buff)
+ *
+ * Makes a new buffer with wrapping and stuffing, should check that
+ * we don't get tx buffer overflow.
+ */
+int async_wrap_skb( struct sk_buff *skb, __u8 *tx_buff, int buffsize)
+{
+ __u8 byte;
+ int i, n;
+ int xbofs;
+ union {
+ __u16 value;
+ __u8 bytes[2];
+ } fcs;
+
+
+ DEBUG( 6, __FUNCTION__ "()\n");
+ ASSERT( skb != NULL, return 0;);
+
+ /* Initialize variables */
+ fcs.value = INIT_FCS;
+ n = 0;
+
+ if ( skb->len > 2048) {
+ DEBUG( 0,"async_xmit: Warning size=%d of sk_buff to big!\n",
+ (int) skb->len);
+
+ return 0;
+ }
+
+ /*
+ * Send XBOF's for required min. turn time and for the negotiated
+ * additional XBOFS
+ */
+ xbofs = ((struct irlap_skb_cb *)(skb->cb))->xbofs;
+ for ( i=0; i<xbofs; i++) {
+ tx_buff[n++] = XBOF;
+ }
+
+ /* Start of packet character BOF */
+ tx_buff[n++] = BOF;
+
+ /* Insert frame and calc CRC */
+ for( i=0; i < skb->len; i++) {
+ byte = skb->data[i];
+
+ /*
+ * Check for the possibility of tx buffer overflow. We use
+ * bufsize-5 since the maximum number of bytes that can be
+ * transmitted after this point is 5.
+ */
+ if ( n > buffsize-5) {
+ printk( KERN_WARNING
+ "IrDA Wrapper: TX-buffer overflow!\n");
+ return n;
+ }
+ n+=stuff_byte( byte, tx_buff+n);
+ fcs.value = IR_FCS( fcs.value, byte);
+ }
+
+ /* Insert CRC in little endian format (LSB first) */
+ fcs.value = ~fcs.value;
+#ifdef __LITTLE_ENDIAN
+ n += stuff_byte( fcs.bytes[0], tx_buff+n);
+ n += stuff_byte( fcs.bytes[1], tx_buff+n);
+#else ifdef __BIG_ENDIAN
+ n += stuff_byte( fcs.bytes[1], tx_buff+n);
+ n += stuff_byte( fcs.bytes[0], tx_buff+n);
+#endif
+ tx_buff[n++] = EOF;
+
+ DEBUG( 6, "async_wrap() -->\n");
+
+ return n;
+}
+
+/*
+ * Function async_bump (irdev)
+ *
+ * Got a frame, make a copy of it, and pass it up the stack!
+ *
+ */
+static __inline__ void async_bump( struct irda_device *irdev, __u8 *buf,
+ int len)
+{
+ struct sk_buff *skb;
+
+ skb = dev_alloc_skb( len+1);
+ if (skb == NULL) {
+ printk( KERN_INFO __FUNCTION__ "() memory squeeze, "
+ "dropping frame.\n");
+ irdev->stats.rx_dropped++;
+ return;
+ }
+
+ /* Align to 20 bytes */
+ skb_reserve( skb, 1);
+
+ /* For finding out how much time we use to
+ send a frame */
+ do_gettimeofday( &skb->stamp);
+
+ ASSERT( len-2 > 0, return;);
+
+ /* Copy data without CRC */
+ skb_put( skb, len-2);
+ memcpy( skb->data, buf, len-2);
+
+ irdev->rx_buff.len = 0;
+ /*
+ * Feed it to IrLAP layer
+ */
+ /* memcpy(skb_put(skb,count), ax->rbuff, count); */
+ skb->dev = &irdev->netdev;
+ skb->mac.raw = skb->data;
+ skb->protocol = htons(ETH_P_IRDA);
+
+ netif_rx( skb);
+ irdev->stats.rx_packets++;
+
+ /* irlap_input( skb, skb->dev, NULL); */
+}
+
+/*
+ * Function async_unwrap (skb)
+ *
+ * Parse and de-stuff frame received from the IR-port
+ *
+ */
+void async_unwrap_char( struct irda_device *irdev, __u8 byte)
+{
+ DEBUG( 6, "async_unwrap()\n");
+
+ /* State machine for receiving frames */
+ switch( irdev->rx_buff.state) {
+ case OUTSIDE_FRAME:
+ if ( byte == BOF) {
+ irdev->rx_buff.state = BEGIN_FRAME;
+ irdev->rx_buff.in_frame = TRUE;
+ } else if ( byte == EOF) {
+ irda_device_set_media_busy( irdev, TRUE);
+ }
+ break;
+ case BEGIN_FRAME:
+ switch ( byte) {
+ case BOF:
+ /* Continue */
+ break;
+ case CE:
+ /* Stuffed byte */
+ irdev->rx_buff.state = LINK_ESCAPE;
+ break;
+ case EOF:
+ /* Abort frame */
+ DEBUG( 0, "Frame abort (1)\n");
+ irdev->rx_buff.state = OUTSIDE_FRAME;
+ break;
+ default:
+ /* Got first byte of frame */
+ if ( irdev->rx_buff.len < irdev->rx_buff.truesize) {
+ irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+
+ irdev->rx_buff.fcs = IR_FCS ( INIT_FCS, byte);
+ irdev->rx_buff.state = INSIDE_FRAME;
+ } else
+ printk( "Rx buffer overflow\n");
+ break;
+ }
+ break;
+ case LINK_ESCAPE:
+ switch ( byte) {
+ case BOF:
+ /* New frame? */
+ DEBUG( 4, "New frame?\n");
+ irdev->rx_buff.state = BEGIN_FRAME;
+ irdev->rx_buff.len = 0;
+ irda_device_set_media_busy( irdev, TRUE);
+ break;
+ case CE:
+ DEBUG( 4, "WARNING: State not defined\n");
+ break;
+ case EOF:
+ /* Abort frame */
+ DEBUG( 0, "Abort frame (2)\n");
+ irdev->rx_buff.state = OUTSIDE_FRAME;
+ irdev->rx_buff.len = 0;
+ break;
+ default:
+ /*
+ * Stuffed char, complement bit 5 of byte
+ * following CE, IrLAP p.114
+ */
+ byte ^= IR_TRANS;
+ if ( irdev->rx_buff.len < irdev->rx_buff.truesize) {
+ irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+
+ irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte);
+ irdev->rx_buff.state = INSIDE_FRAME;
+ } else
+ printk( "Rx buffer overflow\n");
+ break;
+ }
+ break;
+ case INSIDE_FRAME:
+ switch ( byte) {
+ case BOF:
+ /* New frame? */
+ DEBUG( 4, "New frame?\n");
+ irdev->rx_buff.state = BEGIN_FRAME;
+ irdev->rx_buff.len = 0;
+ irda_device_set_media_busy( irdev, TRUE);
+ break;
+ case CE:
+ /* Stuffed char */
+ irdev->rx_buff.state = LINK_ESCAPE;
+ break;
+ case EOF:
+ /* End of frame */
+ irdev->rx_buff.state = OUTSIDE_FRAME;
+ irdev->rx_buff.in_frame = FALSE;
+
+ /*
+ * Test FCS and deliver frame if it's good
+ */
+ if ( irdev->rx_buff.fcs == GOOD_FCS) {
+ async_bump( irdev, irdev->rx_buff.data,
+ irdev->rx_buff.len);
+ } else {
+ /*
+ * Wrong CRC, discard frame!
+ */
+ DEBUG( 0, "Received frame has wrong CRC\n");
+ irda_device_set_media_busy( irdev, TRUE);
+ irdev->rx_buff.len = 0;
+ }
+ break;
+ default:
+ /* Next byte of frame */
+ if ( irdev->rx_buff.len < irdev->rx_buff.truesize) {
+ irdev->rx_buff.data[ irdev->rx_buff.len++] = byte;
+
+ irdev->rx_buff.fcs = IR_FCS( irdev->rx_buff.fcs, byte);
+ } else
+ printk( "Rx buffer overflow\n");
+ break;
+ }
+ break;
+ }
+}
+
+/*
+ * Function stuff_byte (byte, buf)
+ *
+ * Byte stuff one single byte and put the result in buffer pointed to by
+ * buf. The buffer must at all times be able to have two bytes inserted.
+ *
+ */
+__inline__ static int stuff_byte( __u8 byte, __u8 *buf)
+{
+ switch ( byte) {
+ case BOF:
+ case EOF:
+ case CE:
+ /* Insert transparently coded */
+ buf[0] = CE; /* Send link escape */
+ buf[1] = byte^IR_TRANS; /* Complement bit 5 */
+ return 2;
+ /* break; */
+ default:
+ /* Non-special value, no transparency required */
+ buf[0] = byte;
+ return 1;
+ /* break; */
+ }
+}
+
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov