patch-2.1.132 linux/net/irda/irlan/irlan_common.c
Next file: linux/net/irda/irlan/irlan_eth.c
Previous file: linux/net/irda/irlan/irlan_cli_event.c
Back to the patch index
Back to the overall index
- Lines: 897
- Date:
Thu Dec 17 09:01:03 1998
- Orig file:
v2.1.131/linux/net/irda/irlan/irlan_common.c
- Orig date:
Wed Dec 31 16:00:00 1969
diff -u --recursive --new-file v2.1.131/linux/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c
@@ -0,0 +1,896 @@
+/*********************************************************************
+ *
+ * Filename: irlan_common.c
+ * Version: 0.1
+ * Description: IrDA LAN Access Protocol Implementation
+ * Status: Experimental.
+ * Author: Dag Brattli <dagb@cs.uit.no>
+ * Created at: Sun Aug 31 20:14:37 1997
+ * Modified at: Mon Dec 14 10:43:05 1998
+ * Modified by: Dag Brattli <dagb@cs.uit.no>
+ *
+ * Copyright (c) 1997 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/config.h>
+#include <linux/module.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+
+#include <net/irda/irda.h>
+#include <net/irda/irttp.h>
+#include <net/irda/irlmp.h>
+#include <net/irda/iriap.h>
+#include <net/irda/timer.h>
+
+#include <net/irda/irlan_common.h>
+
+static void __irlan_close( struct irlan_cb *self);
+
+/*
+ * Master structure
+ */
+hashbin_t *irlan = NULL;
+
+#ifdef CONFIG_PROC_FS
+static int irlan_proc_read( char *buf, char **start, off_t offset,
+ int len, int unused);
+
+extern struct proc_dir_entry proc_irda;
+
+struct proc_dir_entry proc_irlan = {
+ 0, 5, "irlan",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, NULL,
+ &irlan_proc_read,
+};
+#endif
+
+/*
+ * Function irlan_init (void)
+ *
+ * Initialize IrLAN layer
+ *
+ */
+__initfunc(int irlan_init( void))
+{
+ /* Allocate master array */
+ irlan = hashbin_new( HB_LOCAL);
+ if ( irlan == NULL) {
+ printk( KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
+ return -ENOMEM;
+ }
+#ifdef CONFIG_PROC_FS
+ proc_register( &proc_irda, &proc_irlan);
+#endif /* CONFIG_PROC_FS */
+
+ return 0;
+}
+
+void irlan_cleanup(void)
+{
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+#ifdef CONFIG_PROC_FS
+ proc_unregister( &proc_irda, proc_irlan.low_ino);
+#endif
+ /*
+ * Delete hashbin and close all irlan client instances in it
+ */
+ hashbin_delete( irlan, (FREE_FUNC) __irlan_close);
+}
+
+
+/*
+ * Function irlan_open (void)
+ *
+ *
+ *
+ */
+struct irlan_cb *irlan_open(void)
+{
+ struct irlan_cb *self;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ /*
+ * Initialize the irlan structure.
+ */
+ self = kmalloc( sizeof(struct irlan_cb), GFP_ATOMIC);
+ if ( self == NULL)
+ return NULL;
+
+ memset( self, 0, sizeof( struct irlan_cb));
+
+ /*
+ * Initialize local device structure
+ */
+ self->magic = IRLAN_MAGIC;
+
+ return self;
+}
+/*
+ * Function irlan_close (self)
+ *
+ * This function closes and deallocates the IrLAN client instances. Be
+ * aware that other functions which calles client_close() must call
+ * hashbin_remove() first!!!
+ *
+ */
+void __irlan_close( struct irlan_cb *self)
+{
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ /*
+ * Disconnect open TSAP connections
+ */
+ if ( self->tsap_data) {
+ irttp_disconnect_request( self->tsap_data, NULL, P_HIGH);
+
+ /* FIXME: this will close the tsap before the disconenct
+ * frame has been sent
+ */
+ /* irttp_close_tsap( self->tsap_data); */
+ }
+ if ( self->tsap_ctrl) {
+ irttp_disconnect_request( self->tsap_ctrl, NULL, P_HIGH);
+
+ /* irttp_close_tsap( self->tsap_control); */
+ }
+
+ unregister_netdev( &self->dev);
+
+ /*
+ * Make sure that nobody uses this instance anymore!
+ */
+ self->magic = 0;
+
+ /*
+ * Dealloacte structure
+ */
+ kfree( self);
+}
+
+/*
+ * Function irlan_close (self)
+ *
+ *
+ *
+ */
+void irlan_close( struct irlan_cb *self)
+{
+ struct irlan_cb *entry;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ entry = hashbin_remove( irlan, self->daddr, NULL);
+
+ ASSERT( entry == self, return;);
+
+ __irlan_close( self);
+}
+
+/*
+ * Function irlan_get_provider_info (self)
+ *
+ * Send Get Provider Information command to peer IrLAN layer
+ *
+ */
+void irlan_get_provider_info( struct irlan_cb *self)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ skb = dev_alloc_skb( 64);
+ if (skb == NULL) {
+ DEBUG( 0, __FUNCTION__
+ "(), Could not allocate an skb of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ frame[0] = CMD_GET_PROVIDER_INFO;
+ frame[1] = 0x00; /* Zero parameters */
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_open_data_channel (self)
+ *
+ * Send an Open Data Command to provider
+ *
+ */
+void irlan_open_data_channel( struct irlan_cb *self)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ skb = dev_alloc_skb( 64);
+ if (skb == NULL) {
+ DEBUG( 0, __FUNCTION__
+ "(), Could not allocate an skb of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ /* Build frame */
+ frame[0] = CMD_OPEN_DATA_CHANNEL;
+ frame[1] = 0x02; /* Two parameters */
+
+ insert_string_param( skb, "MEDIA", "802.3");
+ insert_string_param( skb, "ACCESS_TYPE", "DIRECT");
+ /* insert_string_param( skb, "MODE", "UNRELIABLE"); */
+
+/* self->use_udata = TRUE; */
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_open_unicast_addr (self)
+ *
+ * Make IrLAN provider accept ethernet frames addressed to the unicast
+ * address.
+ *
+ */
+void irlan_open_unicast_addr( struct irlan_cb *self)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ skb = dev_alloc_skb( 128);
+ if (skb == NULL) {
+ DEBUG( 0, __FUNCTION__
+ "(), Could not allocate an skb of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ frame[0] = CMD_FILTER_OPERATION;
+ frame[1] = 0x03; /* Three parameters */
+ insert_byte_param( skb, "DATA_CHAN" , self->dtsap_sel_data);
+ insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
+ insert_string_param( skb, "FILTER_MODE", "FILTER");
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_set_broadcast_filter (self, status)
+ *
+ * Make IrLAN provider accept ethernet frames addressed to the broadcast
+ * address. Be careful with the use of this one, sice there may be a lot
+ * of broadcast traffic out there. We can still function without this
+ * one but then _we_ have to initiate all communication with other
+ * hosts, sice ARP request for this host will not be answered.
+ */
+void irlan_set_broadcast_filter( struct irlan_cb *self, int status)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ /* Should only be used by client */
+ if (!self->client)
+ return;
+
+ skb = dev_alloc_skb( 128);
+ if (skb == NULL) {
+ DEBUG( 0, __FUNCTION__
+ "(), Could not allocate an skb of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ frame[0] = CMD_FILTER_OPERATION;
+ frame[1] = 0x03; /* Three parameters */
+ insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
+ insert_string_param( skb, "FILTER_TYPE", "BROADCAST");
+ if ( status)
+ insert_string_param( skb, "FILTER_MODE", "FILTER");
+ else
+ insert_string_param( skb, "FILTER_MODE", "NONE");
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_set_multicast_filter (self, status)
+ *
+ * Make IrLAN provider accept ethernet frames addressed to the multicast
+ * address.
+ *
+ */
+void irlan_set_multicast_filter( struct irlan_cb *self, int status)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ /* Should only be used by client */
+ if (!self->client)
+ return;
+
+ skb = dev_alloc_skb( 128);
+ if (skb == NULL) {
+ DEBUG( 0, __FUNCTION__
+ "(), Could not allocate an skb of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ frame[0] = CMD_FILTER_OPERATION;
+ frame[1] = 0x03; /* Three parameters */
+ insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
+ insert_string_param( skb, "FILTER_TYPE", "MULTICAST");
+ if ( status)
+ insert_string_param( skb, "FILTER_MODE", "ALL");
+ else
+ insert_string_param( skb, "FILTER_MODE", "NONE");
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_get_unicast_addr (self)
+ *
+ * Retrives the unicast address from the IrLAN provider. This address
+ * will be inserted into the devices structure, so the ethernet layer
+ * can construct its packets.
+ *
+ */
+void irlan_get_unicast_addr( struct irlan_cb *self)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ skb = dev_alloc_skb( 128);
+ if (skb == NULL) {
+ DEBUG( 0, "irlan_client_get_unicast_addr: "
+ "Could not allocate an sk_buff of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ frame[0] = CMD_FILTER_OPERATION;
+ frame[1] = 0x03; /* Three parameters */
+ insert_byte_param( skb, "DATA_CHAN", self->dtsap_sel_data);
+ insert_string_param( skb, "FILTER_TYPE", "DIRECTED");
+ insert_string_param( skb, "FILTER_OPERATION", "DYNAMIC");
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function irlan_get_media_char (self)
+ *
+ *
+ *
+ */
+void irlan_get_media_char( struct irlan_cb *self)
+{
+ struct sk_buff *skb;
+ __u8 *frame;
+
+ DEBUG( 4, __FUNCTION__ "()\n");
+
+ ASSERT( self != NULL, return;);
+ ASSERT( self->magic == IRLAN_MAGIC, return;);
+
+ skb = dev_alloc_skb( 64);
+ if (skb == NULL) {
+ DEBUG( 0,"irlan_server_get_media_char: "
+ "Could not allocate an sk_buff of length %d\n", 64);
+ return;
+ }
+
+ /* Reserve space for TTP, LMP, and LAP header */
+ skb_reserve( skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_put( skb, 2);
+
+ frame = skb->data;
+
+ /* Build frame */
+ frame[0] = CMD_GET_MEDIA_CHAR;
+ frame[1] = 0x01; /* One parameter */
+
+ insert_string_param( skb, "MEDIA", "802.3");
+
+ irttp_data_request( self->tsap_ctrl, skb);
+}
+
+/*
+ * Function insert_byte_param (skb, param, value)
+ *
+ * Insert byte parameter into frame
+ *
+ */
+int insert_byte_param( struct sk_buff *skb, char *param, __u8 value)
+{
+ __u8 *frame;
+ __u8 len_param;
+ __u16 len_value;
+ int n=0;
+
+ if ( skb == NULL) {
+ DEBUG( 0, "insert_param: Got NULL skb\n");
+ return 0;
+ }
+
+ len_param = strlen( param);
+ len_value = 1;
+
+ /*
+ * Insert at end of sk-buffer
+ */
+ frame = skb->tail;
+
+ /* Make space for data */
+ if ( skb_tailroom(skb) < (len_param+len_value+3)) {
+ DEBUG( 0, "insert_param: No more space at end of skb\n");
+ return 0;
+ }
+ skb_put( skb, len_param+len_value+3);
+
+ /* Insert parameter length */
+ frame[n++] = len_param;
+
+ /* Insert parameter */
+ memcpy( frame+n, param, len_param);
+ n += len_param;
+
+ /* Insert value length ( 2 byte little endian format, LSB first) */
+ frame[n++] = len_value & 0xff;
+ frame[n++] = len_value >> 8;
+
+ frame[n++] = value;
+
+ return len_param+len_value+3;
+}
+
+/*
+ * Function insert_string (skb, param, value)
+ *
+ * Insert string parameter into frame
+ *
+ */
+int insert_string_param( struct sk_buff *skb, char *param, char *value)
+{
+ __u8 *frame;
+ __u8 len_param;
+ __u16 len_value;
+ int n=0;
+
+ if ( skb == NULL) {
+ DEBUG( 0, "insert_param: Got NULL skb\n");
+ return 0;
+ }
+ len_param = strlen( param);
+ len_value = strlen( value);
+
+ /*
+ * Insert at end of sk-buffer
+ */
+ frame = skb->tail;
+
+ /* Make space for data */
+ if ( skb_tailroom(skb) < (len_param+len_value+3)) {
+ DEBUG( 0, "insert_param: No more space at end of skb\n");
+ return 0;
+ }
+ skb_put( skb, len_param+len_value+3);
+
+ /* Insert parameter length */
+ frame[n++] = len_param;
+
+ /* Insert parameter */
+ memcpy( frame+n, param, len_param);
+ n += len_param;
+
+ /* Insert value length ( 2 byte little endian format, LSB first) */
+ frame[n++] = len_value & 0xff;
+ frame[n++] = len_value >> 8;
+
+ memcpy( frame+n, value, len_value);
+ n+=len_value;
+
+ return len_param+len_value+3;
+}
+
+/*
+ * Function insert_array_param( skb, param, value, len_value)
+ *
+ * Insert array parameter into frame
+ *
+ */
+int insert_array_param( struct sk_buff *skb, char *name, __u8 *value,
+ __u16 value_len)
+{
+ __u8 *frame;
+ __u8 name_len;
+ int n=0;
+
+ if ( skb == NULL) {
+ DEBUG( 0, __FUNCTION__ "(), Got NULL skb\n");
+ return 0;
+ }
+ name_len = strlen( name);
+
+ /*
+ * Insert at end of sk-buffer
+ */
+ frame = skb->tail;
+
+ /* Make space for data */
+ if ( skb_tailroom(skb) < (name_len+value_len+3)) {
+ DEBUG( 0, __FUNCTION__ "(), No more space at end of skb\n");
+ return 0;
+ }
+ skb_put( skb, name_len+value_len+3);
+
+ /* Insert parameter length */
+ frame[n++] = name_len;
+
+ /* Insert parameter */
+ memcpy( frame+n, name, name_len);
+ n += name_len;
+
+ /* Insert value length ( 2 byte little endian format, LSB first) */
+ /* FIXME: should we use htons() here? */
+ frame[n++] = value_len & 0xff;
+ frame[n++] = value_len >> 8;
+
+ memcpy( frame+n, value, value_len);
+ n+=value_len;
+
+ return name_len+value_len+3;
+}
+
+/*
+ * Function insert_param (skb, param, value, byte)
+ *
+ * Insert parameter at end of buffer, structure of a parameter is:
+ *
+ * -----------------------------------------------------------------------
+ * | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
+ * -----------------------------------------------------------------------
+ */
+int insert_param( struct sk_buff *skb, char *param, int type, char *value_char,
+ __u8 value_byte, __u16 value_short)
+{
+ __u8 *frame;
+ __u8 len_param;
+ __u16 len_value;
+ int n;
+
+ if ( skb == NULL) {
+ DEBUG( 0, "insert_param: Got NULL skb\n");
+ return 0;
+ }
+
+ n = 0;
+
+ len_param = strlen( param);
+ switch ( type) {
+ case 1:
+ ASSERT( value_char != NULL, return 0;);
+ len_value = strlen( value_char);
+ break;
+ case 2:
+ len_value = 1;
+ break;
+ case 3:
+ len_value = 2;
+ break;
+ default:
+ DEBUG( 0, "Error in insert_param!\n");
+ return 0;
+ break;
+ }
+
+ /*
+ * Insert at end of sk-buffer
+ */
+ frame = skb->tail;
+
+ /* Make space for data */
+ if ( skb_tailroom(skb) < (len_param+len_value+3)) {
+ DEBUG( 0, "insert_param: No more space at end of skb\n");
+ return 0;
+ }
+ skb_put( skb, len_param+len_value+3);
+
+ /* Insert parameter length */
+ frame[n++] = len_param;
+
+ /* Insert parameter */
+ memcpy( frame+n, param, len_param); n += len_param;
+
+ /* Insert value length ( 2 byte little endian format, LSB first) */
+ frame[n++] = len_value & 0xff;
+ frame[n++] = len_value >> 8;
+
+ /* Insert value */
+ switch (type) {
+ case 1:
+ memcpy( frame+n, value_char, len_value); n+=len_value;
+ break;
+ case 2:
+ frame[n++] = value_byte;
+ break;
+ case 3:
+ frame[n++] = value_short & 0xff;
+ frame[n++] = (value_short >> 8) & 0xff;
+ break;
+ default:
+ break;
+ }
+ ASSERT( n == (len_param+len_value+3), return 0;);
+
+ return len_param+len_value+3;
+}
+
+/*
+ * Function irlan_get_response_param (buf, param, value)
+ *
+ * Extracts a single parameter name/value pair from buffer and updates
+ * the buffer pointer to point to the next name/value pair.
+ *
+ */
+int irlan_get_response_param( __u8 *buf, char *name, char *value, int *len)
+{
+ __u8 name_len;
+ __u16 val_len;
+ int n=0;
+
+ DEBUG( 4, "irlan_get_response_param()\n");
+
+ /* get length of parameter name ( 1 byte) */
+ name_len = buf[n++];
+
+ if (name_len > 254) {
+ DEBUG( 0, __FUNCTION__ "(), name_len > 254\n");
+ return -1;
+ }
+
+ /* get parameter name */
+ memcpy( name, buf+n, name_len);
+ name[ name_len] = '\0';
+ n+=name_len;
+
+ /*
+ * Get length of parameter value ( 2 bytes in little endian
+ * format)
+ */
+ val_len = buf[n++] & 0xff;
+ val_len |= buf[n++] << 8;
+
+ if (val_len > 1016) {
+ DEBUG( 0, __FUNCTION__ "(), parameter length to long\n");
+ return -1;
+ }
+
+ *len = val_len;
+
+ /* get parameter value */
+ memcpy( value, buf+n, val_len);
+ value[ val_len] = '\0';
+ n+=val_len;
+
+ DEBUG( 4, "Parameter: %s ", name);
+ DEBUG( 4, "Value: %s\n", value);
+
+ return n;
+}
+
+#ifdef CONFIG_PROC_FS
+/*
+ * Function irlan_client_proc_read (buf, start, offset, len, unused)
+ *
+ * Give some info to the /proc file system
+ */
+static int irlan_proc_read( char *buf, char **start, off_t offset,
+ int len, int unused)
+{
+ struct irlan_cb *self;
+
+ ASSERT( irlan != NULL, return 0;);
+
+ len = 0;
+
+ len += sprintf( buf+len, "IrLAN\n");
+
+ self = ( struct irlan_cb *) hashbin_get_first( irlan);
+ while ( self != NULL) {
+ ASSERT( self->magic == IRLAN_MAGIC, return len;);
+
+ len += sprintf( buf+len, "ifname: %s, ",
+ self->ifname);
+ /* len += sprintf( buf+len, "state: %s, ", */
+/* irlan_client_state[ self->state]); */
+ len += sprintf( buf+len, "saddr: %#08x\n",
+ self->saddr);
+ len += sprintf( buf+len, "daddr: %#08x\n",
+ self->daddr);
+ len += sprintf( buf+len, "tbusy: %s\n", self->dev.tbusy ?
+ "TRUE" : "FALSE");
+
+ len += sprintf( buf+len, "\n");
+
+ self = ( struct irlan_cb *) hashbin_get_next( irlan);
+ DEBUG( 4, "self=%p\n", self);
+ }
+ return len;
+}
+#endif
+
+/*
+ * Function print_ret_code (code)
+ *
+ * Print return code of request to peer IrLAN layer.
+ *
+ */
+void print_ret_code( __u8 code)
+{
+ switch( code) {
+ case 0:
+ printk( KERN_INFO "Success\n");
+ break;
+ case 1:
+ printk( KERN_WARNING "Insufficient resources\n");
+ break;
+ case 2:
+ printk( KERN_WARNING "Invalid command format\n");
+ break;
+ case 3:
+ printk( KERN_WARNING "Command not supported\n");
+ break;
+ case 4:
+ printk( KERN_WARNING "Parameter not supported\n");
+ break;
+ case 5:
+ printk( KERN_WARNING "Value not supported\n");
+ break;
+ case 6:
+ printk( KERN_WARNING "Not open\n");
+ break;
+ case 7:
+ printk( KERN_WARNING "Authentication required\n");
+ break;
+ case 8:
+ printk( KERN_WARNING "Invalid password\n");
+ break;
+ case 9:
+ printk( KERN_WARNING "Protocol error\n");
+ break;
+ case 255:
+ printk( KERN_WARNING "Asynchronous status\n");
+ break;
+ }
+}
+
+#ifdef MODULE
+
+MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
+MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
+
+/*
+ * Function init_module (void)
+ *
+ * Initialize the IrLAN module, this function is called by the
+ * modprobe(1) program.
+ */
+int init_module(void)
+{
+ DEBUG( 4, __FUNCTION__ "(), irlan.c\n");
+
+ irlan_init();
+
+ return 0;
+}
+
+/*
+ * Function cleanup_module (void)
+ *
+ * Remove the IrLAN module, this function is called by the rmmod(1)
+ * program
+ */
+void cleanup_module(void)
+{
+ DEBUG( 4, "--> irlan, cleanup_module\n");
+ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
+
+ /* Free some memory */
+ irlan_cleanup();
+
+ DEBUG( 4, "irlan, cleanup_module -->\n");
+}
+
+#endif /* MODULE */
+
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov