patch-2.2.15 linux/net/irda/iriap.c

Next file: linux/net/irda/iriap_event.c
Previous file: linux/net/irda/irda_device.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/net/irda/iriap.c linux/net/irda/iriap.c
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Thu Aug 21 00:02:07 1997
- * Modified at:   Sun May  9 15:59:05 1999
+ * Modified at:   Sat Dec 25 16:42:42 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * 
  *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>, 
@@ -28,7 +28,6 @@
 #include <linux/skbuff.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/irda.h>
 
 #include <asm/byteorder.h>
 #include <asm/unaligned.h>
@@ -61,8 +60,8 @@
 
 extern char *lmp_reasons[];
 
-static struct iriap_cb *iriap_open( __u8 slsap, int mode);
 static void __iriap_close(struct iriap_cb *self);
+static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
 static void iriap_disconnect_indication(void *instance, void *sap, 
 					LM_REASON reason, struct sk_buff *skb);
 static void iriap_connect_indication(void *instance, void *sap, 
@@ -82,22 +81,21 @@
  *    Initializes the IrIAP layer, called by the module initialization code
  *    in irmod.c 
  */
-__initfunc(int iriap_init(void))
+int __init iriap_init(void)
 {
-	__u16 hints;
 	struct ias_object *obj;
+	struct iriap_cb *server;
+	__u8 oct_seq[6];
+	__u16 hints;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
 	/* Allocate master array */
-	iriap = hashbin_new( HB_LOCAL);
-	if ( iriap == NULL)
+	iriap = hashbin_new(HB_LOCAL);
+	if (!iriap)
 		return -ENOMEM;
 
-	objects = hashbin_new( HB_LOCAL);
-	if ( objects == NULL) {
-		printk( KERN_WARNING 
-			"IrIAP: Can't allocate objects hashbin!\n");
+	objects = hashbin_new(HB_LOCAL);
+	if (!objects) {
+		WARNING(__FUNCTION__ "(), Can't allocate objects hashbin!\n");
 		return -ENOMEM;
 	}
 
@@ -105,22 +103,32 @@
 	 *  Register some default services for IrLMP 
 	 */
 	hints  = irlmp_service_to_hint(S_COMPUTER);
-	hints |= irlmp_service_to_hint(S_PNP);
 	service_handle = irlmp_register_service(hints);
 
-	/* 
-	 *  Register the Device object with LM-IAS
-	 */
-	obj = irias_new_object( "Device", IAS_DEVICE_ID);
-	irias_add_string_attrib( obj, "DeviceName", "Linux");
-	irias_insert_object( obj);
+	/* Register the Device object with LM-IAS */
+	obj = irias_new_object("Device", IAS_DEVICE_ID);
+	irias_add_string_attrib(obj, "DeviceName", "Linux");
+
+	oct_seq[0] = 0x01;  /* Version 1 */
+	oct_seq[1] = 0x00;  /* IAS support bits */
+	oct_seq[2] = 0x00;  /* LM-MUX support bits */
+#ifdef CONFIG_IRDA_ULTRA
+	oct_seq[2] |= 0x04; /* Connectionless Data support */
+#endif
+	irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3);
+	irias_insert_object(obj);
 
 	/*  
 	 *  Register server support with IrLMP so we can accept incoming 
 	 *  connections 
 	 */
-	iriap_open( LSAP_IAS, IAS_SERVER);
-	
+	server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
+	if (!server) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), unable to open server\n");
+		return -1;
+	}
+	iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
+
 	return 0;
 }
 
@@ -130,7 +138,7 @@
  *    Initializes the IrIAP layer, called by the module cleanup code in 
  *    irmod.c
  */
-void iriap_cleanup(void) 
+void iriap_cleanup(void)
 {
 	irlmp_unregister_service(service_handle);
 	
@@ -143,57 +151,41 @@
  *
  *    Opens an instance of the IrIAP layer, and registers with IrLMP
  */
-struct iriap_cb *iriap_open( __u8 slsap_sel, int mode)
+struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv, 
+			    CONFIRM_CALLBACK callback)
 {
 	struct iriap_cb *self;
-	struct notify_t notify;
-	struct lsap_cb *lsap;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	self = kmalloc( sizeof(struct iriap_cb), GFP_ATOMIC);
-	if ( self == NULL) {
-		DEBUG( 0, "iriap_open(), Unable to kmalloc!\n");
+	self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
+	if (!self) {
+		WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
 		return NULL;
 	}
 
 	/*
 	 *  Initialize instance
 	 */
-	memset( self, 0, sizeof(struct iriap_cb));
-
-	irda_notify_init( &notify);
-	notify.connect_confirm = iriap_connect_confirm;
-	notify.connect_indication = iriap_connect_indication;
-	notify.disconnect_indication = iriap_disconnect_indication;
-	notify.data_indication = iriap_data_indication;
-	notify.instance = self;
-	if ( mode == IAS_CLIENT)
-		strcpy( notify.name, "IrIAS cli");
-	else
-		strcpy( notify.name, "IrIAS srv");
-
-	lsap = irlmp_open_lsap( slsap_sel, &notify);
-	if ( lsap == NULL) {
-		DEBUG( 0, "iriap_open: Unable to allocated LSAP!\n");
-		return NULL;
-	}
-	slsap_sel = lsap->slsap_sel;
-	DEBUG( 4, __FUNCTION__ "(), source LSAP sel=%02x\n", slsap_sel);
+	memset(self, 0, sizeof(struct iriap_cb));
 	
 	self->magic = IAS_MAGIC;
-	self->lsap = lsap;
-	self->slsap_sel = slsap_sel;
 	self->mode = mode;
+	if (mode == IAS_CLIENT)
+		iriap_register_lsap(self, slsap_sel, mode);
+
+	self->confirm = callback;
+	self->priv = priv;
 
 	init_timer(&self->watchdog_timer);
 
-	hashbin_insert( iriap, (QUEUE*) self, slsap_sel, NULL);
+	hashbin_insert(iriap, (queue_t *) self, (int) self, NULL);
 	
-	iriap_next_client_state( self, S_DISCONNECT);
-	iriap_next_call_state( self, S_MAKE_CALL);
-	iriap_next_server_state( self, R_DISCONNECT);
-	iriap_next_r_connect_state( self, R_WAITING);
+	/* Initialize state machines */
+	iriap_next_client_state(self, S_DISCONNECT);
+	iriap_next_call_state(self, S_MAKE_CALL);
+	iriap_next_server_state(self, R_DISCONNECT);
+	iriap_next_r_connect_state(self, R_WAITING);
 	
 	return self;
 }
@@ -204,18 +196,21 @@
  *    Removes (deallocates) the IrIAP instance
  *
  */
-static void __iriap_close( struct iriap_cb *self)
+static void __iriap_close(struct iriap_cb *self)
 {
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	del_timer(&self->watchdog_timer);
 
+	if (self->skb)
+		dev_kfree_skb(self->skb);
+
 	self->magic = 0;
 
-	kfree( self);
+	kfree(self);
 }
 
 /*
@@ -223,25 +218,51 @@
  *
  *    Closes IrIAP and deregisters with IrLMP
  */
-void iriap_close( struct iriap_cb *self)
+void iriap_close(struct iriap_cb *self)
 {
 	struct iriap_cb *entry;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	if ( self->lsap) {
-		irlmp_close_lsap( self->lsap);
+	if (self->lsap) {
+		irlmp_close_lsap(self->lsap);
 		self->lsap = NULL;
 	}
 
-	entry = (struct iriap_cb *) hashbin_remove( iriap, self->slsap_sel, 
-						    NULL);
-	ASSERT( entry == self, return;);
+	entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL);
+	ASSERT(entry == self, return;);
+
+	__iriap_close(self);
+}
+
+static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
+{
+	notify_t notify;
+
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
+
+	irda_notify_init(&notify);
+	notify.connect_confirm       = iriap_connect_confirm;
+	notify.connect_indication    = iriap_connect_indication;
+	notify.disconnect_indication = iriap_disconnect_indication;
+	notify.data_indication       = iriap_data_indication;
+	notify.instance = self;
+	if (mode == IAS_CLIENT)
+		strcpy(notify.name, "IrIAS cli");
+	else
+		strcpy(notify.name, "IrIAS srv");
+
+	self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
+	if (self->lsap == NULL) {
+		ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
+		return -1;
+	}
+	self->slsap_sel = self->lsap->slsap_sel;
 
-	__iriap_close( self);
+	return 0;
 }
 
 /*
@@ -250,47 +271,45 @@
  *    Got disconnect, so clean up everything assosiated with this connection
  *
  */
-static void iriap_disconnect_indication( void *instance, void *sap, 
-					 LM_REASON reason, 
-					 struct sk_buff *userdata)
+static void iriap_disconnect_indication(void *instance, void *sap, 
+					LM_REASON reason, 
+					struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
 
-	DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
+	IRDA_DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
 
 	self = (struct iriap_cb *) instance;
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	ASSERT( iriap != NULL, return;);
+	ASSERT(iriap != NULL, return;);
 
 	del_timer(&self->watchdog_timer);
 
-	if ( self->mode == IAS_CLIENT) {
-		DEBUG( 4, __FUNCTION__ "(), disconnect as client\n");
+	if (self->mode == IAS_CLIENT) {
+		IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
 
+
+		iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION, 
+				      NULL);
 		/* 
 		 * Inform service user that the request failed by sending 
-		 * it a NULL value.
+		 * it a NULL value. Warning, the client might close us, so
+		 * remember no to use self anymore after calling confirm
 		 */
 		if (self->confirm)
  			self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
-		
-		
-		iriap_do_client_event( self, IAP_LM_DISCONNECT_INDICATION, 
-				       NULL);
-		/* Close instance only if client */
-		iriap_close( self);
-		
 	} else {
-		DEBUG( 4, __FUNCTION__ "(), disconnect as server\n");
-		iriap_do_server_event( self, IAP_LM_DISCONNECT_INDICATION, 
-				       NULL);
+		IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
+		iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION, 
+				      NULL);
+		iriap_close(self);
 	}
 
 	if (userdata)
-		dev_kfree_skb( userdata);
+		dev_kfree_skb(userdata);
 }
 
 /*
@@ -303,14 +322,14 @@
 {
 	struct sk_buff *skb;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb(64);
 	if (skb == NULL) {
-		DEBUG(0, __FUNCTION__
+		IRDA_DEBUG(0, __FUNCTION__
 		      "(), Could not allocate an sk_buff of length %d\n", 64);
 		return;
 	}
@@ -325,27 +344,27 @@
 
 void iriap_getinfobasedetails_request(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getinfobasedetails_confirm(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_request(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getobjects_confirm(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 void iriap_getvalue(void) 
 {
-	DEBUG( 0, __FUNCTION__ "(), Not implemented!\n");
+	IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
 }
 
 /*
@@ -354,26 +373,21 @@
  *    Retreive all values from attribute in all objects with given class
  *    name
  */
-void iriap_getvaluebyclass_request(char *name, char *attr, 
-				   __u32 saddr, __u32 daddr,
-				   CONFIRM_CALLBACK callback, void *priv)
+int iriap_getvaluebyclass_request(struct iriap_cb *self,
+				  __u32 saddr, __u32 daddr, 
+				  char *name, char *attr)
 {
 	struct sk_buff *skb;
-	struct iriap_cb *self;
-	__u8 *frame;
 	int name_len, attr_len;
-	__u8 slsap = LSAP_ANY;  /* Source LSAP to use */
-
-	DEBUG(4, __FUNCTION__ "()\n");
-	
-	self = iriap_open(slsap, IAS_CLIENT);
-	if (!self)
-		return;
+	__u8 *frame;
 
-	self->mode = IAS_CLIENT;
-	self->confirm = callback;
-	self->priv = priv;
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IAS_MAGIC, return -1;);
 
+	/* Client must supply the destination device address */
+	if (!daddr)
+		return -1;
+	
 	self->daddr = daddr;
 	self->saddr = saddr;
 
@@ -387,7 +401,7 @@
 	
 	skb = dev_alloc_skb(64);
 	if (!skb)
-		return;
+		return -ENOMEM;
 
 	name_len = strlen(name);
 	attr_len = strlen(attr);
@@ -405,6 +419,8 @@
 	memcpy(frame+3+name_len, attr, attr_len);  /* Insert attr */
 
 	iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
+
+	return 0;
 }
 
 /*
@@ -417,7 +433,6 @@
 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb) 
 {
 	struct ias_value *value;
-	int n;
 	int charset;
 	__u32 value_len;
 	__u32 tmp_cpu32;
@@ -425,6 +440,7 @@
 	__u16 len;
 	__u8  type;
 	__u8 *fp;
+	int n;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
@@ -437,29 +453,27 @@
 	/* Get length, MSB first */
 	len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
 
-	DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
+	IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
 
 	/* Get object ID, MSB first */
 	obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
-/* 	memcpy(&obj_id, fp+n, 2); n += 2; */
-/* 	be16_to_cpus(&obj_id); */
 
 	type = fp[n++];
-	DEBUG( 4, __FUNCTION__ "(), Value type = %d\n", type);
+	IRDA_DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
 
-	switch( type) {
+	switch (type) {
 	case IAS_INTEGER:
 		memcpy(&tmp_cpu32, fp+n, 4); n += 4;
 		be32_to_cpus(&tmp_cpu32);
 		value = irias_new_integer_value(tmp_cpu32);
 
 		/*  Legal values restricted to 0x01-0x6f, page 15 irttp */
-		DEBUG( 4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
+		IRDA_DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer); 
 		break;
 	case IAS_STRING:
 		charset = fp[n++];
 
-		switch(charset) {
+		switch (charset) {
 		case CS_ASCII:
 			break;
 /* 		case CS_ISO_8859_1: */
@@ -473,41 +487,52 @@
 /* 		case CS_ISO_8859_9: */
 /* 		case CS_UNICODE: */
 		default:
-			DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
-			      ias_charset_types[charset]);
+			IRDA_DEBUG(0, __FUNCTION__
+				   "(), charset %s, not supported\n",
+				   ias_charset_types[charset]);
+
+			/* Aborting, close connection! */
+			iriap_disconnect_request(self);
+			dev_kfree_skb(skb);
 			return;
 			/* break; */
 		}
 		value_len = fp[n++];
-		DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
-		ASSERT( value_len < 64, return;);
+		IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
+		ASSERT(value_len < 64, return;);
 		
 		/* Make sure the string is null-terminated */
 		fp[n+value_len] = 0x00;
 		
-		DEBUG(4, "Got string %s\n", fp+n);
+		IRDA_DEBUG(4, "Got string %s\n", fp+n);
 		value = irias_new_string_value(fp+n);
 		break;
 	case IAS_OCT_SEQ:
 		value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
 		n += 2;
 		
-		/* FIXME:should be 1024, but.... */
-		DEBUG(0, __FUNCTION__ "():octet sequence:len=%d\n", value_len);
 		ASSERT(value_len <= 55, return;);      
 		
 		value = irias_new_octseq_value(fp+n, value_len);
 		break;
 	default:
-		value = &missing;
+		value = irias_new_missing_value();
 		break;
 	}
 	
 	/* Finished, close connection! */
 	iriap_disconnect_request(self);
 
+	/* Warning, the client might close us, so remember no to use self
+	 * anymore after calling confirm 
+	 */
 	if (self->confirm)
 		self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
+	else {
+		IRDA_DEBUG(0, __FUNCTION__ "(), missing handler!\n");
+		irias_delete_value(value);
+	}
+	dev_kfree_skb(skb);
 }
 
 /*
@@ -524,22 +549,22 @@
 	__u32 tmp_be32, tmp_be16;
 	__u8 *fp;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( value != NULL, return;);
-	ASSERT( value->len <= 1024, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(value != NULL, return;);
+	ASSERT(value->len <= 1024, return;);
 
 	/* Initialize variables */
 	n = 0;
 
 	/* 
 	 *  We must adjust the size of the response after the length of the 
-	 *  value. We add 9 bytes because of the 6 bytes for the frame and
-	 *  max 3 bytes for the value coding.
+	 *  value. We add 32 bytes because of the 6 bytes for the frame and
+	 *  max 5 bytes for the value coding.
 	 */
-	skb = dev_alloc_skb(value->len + self->max_header_size + 9);
+	skb = dev_alloc_skb(value->len + self->max_header_size + 32);
 	if (!skb)
 		return;
 
@@ -561,7 +586,7 @@
 	tmp_be16 = cpu_to_be16(obj_id);
 	memcpy(fp+n, &tmp_be16, 2); n += 2;
 
-	switch(value->type) {
+	switch (value->type) {
 	case IAS_STRING:
 		skb_put(skb, 3 + value->len);
 		fp[n++] = value->type;
@@ -585,13 +610,12 @@
 		memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
 		break;
 	case IAS_MISSING:
-		DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
-		skb_put( skb, 1);
+		IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
+		skb_put(skb, 1);
 		fp[n++] = value->type;
 		break;
-
 	default:
-		DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
+		IRDA_DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
 		break;
 	}
 	iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
@@ -606,64 +630,58 @@
 void iriap_getvaluebyclass_indication(struct iriap_cb *self, 
 				      struct sk_buff *skb)
 {
-	__u8 *fp;
-	int n;
+ 	struct ias_object *obj;
+	struct ias_attrib *attrib;
 	int name_len;
 	int attr_len;
 	char name[64];
 	char attr[64];
- 	struct ias_object *obj;
-	struct ias_attrib *attrib;
+	__u8 *fp;
+	int n;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	fp = skb->data;
 	n = 1;
 
 	name_len = fp[n++];
-	memcpy( name, fp+n, name_len); n+=name_len;
+	memcpy(name, fp+n, name_len); n+=name_len;
 	name[name_len] = '\0';
 
 	attr_len = fp[n++]; 
-	memcpy( attr, fp+n, attr_len); n+=attr_len;
+	memcpy(attr, fp+n, attr_len); n+=attr_len;
 	attr[attr_len] = '\0';
 
-	dev_kfree_skb( skb);
+	/* We do not need the buffer anymore */
+	dev_kfree_skb(skb);
 
-	/* 
-	 *  Now, do some advanced parsing! :-) 
-	 */
-	DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
+	IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
 	obj = irias_find_object(name);
 	
-	if ( obj == NULL) {
-		DEBUG( 0, "LM-IAS: Object not found\n");
-		iriap_getvaluebyclass_response( self, 0x1235, 
-						IAS_CLASS_UNKNOWN, &missing);
+	if (obj == NULL) {
+		IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
+		iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
+					       &missing);
 		return;
 	}
-	DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
+	IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
 	
-	attrib = irias_find_attrib( obj, attr);
-	if ( attrib == NULL) {
-		DEBUG( 0, "LM-IAS: Attribute %s not found\n", attr);
+	attrib = irias_find_attrib(obj, attr);
+	if (attrib == NULL) {
+		IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
 		iriap_getvaluebyclass_response(self, obj->id,
 					       IAS_ATTRIB_UNKNOWN, &missing);
 		return;
 	}
 	
-	DEBUG(4, "LM-IAS: found %s\n", attrib->name);
+	/* We have a match; send the value.  */
+	iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS, 
+				       attrib->value);
 	
-	/*
-	 * We have a match; send the value.
-	 */
-	iriap_getvaluebyclass_response( self, obj->id, IAS_SUCCESS, 
-					attrib->value);
-
 	return;
 }
 
@@ -673,15 +691,15 @@
  *    Currently not used
  *
  */
-void iriap_send_ack( struct iriap_cb *self) 
+void iriap_send_ack(struct iriap_cb *self) 
 {
 	struct sk_buff *skb;
 	__u8 *frame;
 
-	DEBUG( 6, __FUNCTION__ "()\n");
+	IRDA_DEBUG(2, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
 
 	skb = dev_alloc_skb(64);
 	if (!skb)
@@ -693,7 +711,25 @@
 	frame = skb->data;
 
 	/* Build frame */
-	frame[0] = IAP_LST | self->operation;
+	frame[0] = IAP_LST | IAP_ACK | self->operation;
+
+	irlmp_data_request(self->lsap, skb);
+}
+
+void iriap_connect_request(struct iriap_cb *self)
+{
+	int ret;
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+
+	ret = irlmp_connect_request(self->lsap, LSAP_IAS, 
+				    self->saddr, self->daddr, 
+				    NULL, NULL);
+	if (ret < 0) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), connect failed!\n");
+		self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
+	}
 }
 
 /*
@@ -703,8 +739,8 @@
  *
  */
 static void iriap_connect_confirm(void *instance, void *sap, 
-				  struct qos_info *qos, 
-				  __u32 max_sdu_size, __u8 header_size, 
+				  struct qos_info *qos, __u32 max_seg_size, 
+				  __u8 max_header_size, 
 				  struct sk_buff *userdata)
 {
 	struct iriap_cb *self;
@@ -715,7 +751,8 @@
 	ASSERT(self->magic == IAS_MAGIC, return;);
 	ASSERT(userdata != NULL, return;);
 	
-	DEBUG(4, __FUNCTION__ "()\n");
+	self->max_data_size = max_seg_size;
+	self->max_header_size = max_header_size;
 	
 	del_timer(&self->watchdog_timer);
 
@@ -729,18 +766,43 @@
  *
  */
 static void iriap_connect_indication(void *instance, void *sap, 
-				     struct qos_info *qos, __u32 max_sdu_size,
-				     __u8 header_size, 
+				     struct qos_info *qos, __u32 max_seg_size,
+				     __u8 max_header_size, 
 				     struct sk_buff *userdata)
 {
-	struct iriap_cb *self;
+	struct iriap_cb *self, *new;
+
+	IRDA_DEBUG(0, __FUNCTION__ "()\n");
 
 	self = (struct iriap_cb *) instance;
 
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
+	
+	/* Start new server */
+	new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL); 
+	if (!new) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), open failed\n");
+		dev_kfree_skb(userdata);
+		return;
+	}
+	
+	/* Now attach up the new "socket" */
+	new->lsap = irlmp_dup(self->lsap, new);
+	if (!new->lsap) {
+		IRDA_DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+		return;
+	}
+		
+	new->max_data_size = max_seg_size;
+	new->max_header_size = max_header_size;
 
-	iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
+	/* Clean up the original one to keep it in listen state */
+	self->lsap->dlsap_sel = LSAP_ANY;
+	self->lsap->lsap_state = LSAP_DISCONNECTED;
+	/* FIXME: refcount in irlmp might get wrong */
+	
+	iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
 }
  
 /*
@@ -756,7 +818,7 @@
 	__u8  *frame;
 	__u8  opcode;
 	
-	DEBUG( 4, __FUNCTION__ "()\n"); 
+	IRDA_DEBUG(3, __FUNCTION__ "()\n"); 
 	
 	self = (struct iriap_cb *) instance;
 
@@ -769,65 +831,74 @@
 	
 	if (self->mode == IAS_SERVER) {
 		/* Call server */
-		DEBUG(4, __FUNCTION__ "(), Calling server!\n");
-		iriap_do_r_connect_event( self, IAP_RECV_F_LST, skb);
+		IRDA_DEBUG(4, __FUNCTION__ "(), Calling server!\n");
+		iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
 
 		return 0;
 	}
 	opcode = frame[0];
-	if ( ~opcode & 0x80) {
-		printk( KERN_ERR "IrIAS multiframe commands or results is "
-			"not implemented yet!\n");
+	if (~opcode & IAP_LST) {
+		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
+			"results is not implemented yet!\n");
+		dev_kfree_skb(skb);
 		return 0;
 	}
-
-	if (~opcode & IAP_ACK) {
-		DEBUG(2, __FUNCTION__ "() Got ack frame!\n");
-	/* 	return; */
+	
+	/* Check for ack frames since they don't contain any data */
+	if (opcode & IAP_ACK) {
+		IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
+		dev_kfree_skb(skb);
+	 	return 0;
 	}
 
 	opcode &= ~IAP_LST; /* Mask away LST bit */
-	
-	switch(opcode) {
+
+	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		dev_kfree_skb(skb);
 		break;
 	case GET_VALUE_BY_CLASS:
-		DEBUG( 4,"IrLMP GetValueByClass\n");
-		
-		switch(frame[1]) {
+		iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
+			
+		switch (frame[1]) {
 		case IAS_SUCCESS:
 			iriap_getvaluebyclass_confirm(self, skb);
 			break;
 		case IAS_CLASS_UNKNOWN:
-			printk(KERN_WARNING "IrIAP No such class!\n");
+			WARNING(__FUNCTION__ "(), No such class!\n");
 			/* Finished, close connection! */
 			iriap_disconnect_request(self);
 
+			/* 
+			 * Warning, the client might close us, so remember
+			 * no to use self anymore after calling confirm 
+			 */
 			if (self->confirm)
-				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
+				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
 					      self->priv);
+			dev_kfree_skb(skb);
 			break;
 		case IAS_ATTRIB_UNKNOWN:
-			printk(KERN_WARNING "IrIAP No such attribute!\n");
+			WARNING(__FUNCTION__ "(), No such attribute!\n");
 		       	/* Finished, close connection! */
 			iriap_disconnect_request(self);
 
+			/* 
+			 * Warning, the client might close us, so remember
+			 * no to use self anymore after calling confirm 
+			 */
 			if (self->confirm)
 				self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, 
 					      self->priv);
+			dev_kfree_skb(skb);
 			break;
-		}
-		iriap_do_call_event( self, IAP_RECV_F_LST, skb);
-
-		/*  
-		 *  We remove LSAPs used by IrIAS as a client since these
-		 *  are more difficult to reuse!  
-		 */
-		iriap_close( self);
+		}		
 		break;
 	default:
-		DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
+		IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", 
+			   opcode);
+		dev_kfree_skb(skb);
 		break;
 	}
 	return 0;
@@ -839,33 +910,34 @@
  *    Received call to server from peer LM-IAS
  *
  */
-void iriap_call_indication( struct iriap_cb *self, struct sk_buff *skb)
+void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
 {
 	__u8 *fp;
-	__u8  opcode;
+	__u8 opcode;
 
-	DEBUG( 4, __FUNCTION__ "()\n");
+	IRDA_DEBUG(4, __FUNCTION__ "()\n");
 
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IAS_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IAS_MAGIC, return;);
+	ASSERT(skb != NULL, return;);
 
 	fp = skb->data;
 
 	opcode = fp[0];
-	if ( ~opcode & 0x80) {
-		printk( KERN_ERR "IrIAS multiframe commands or results is "
-			"not implemented yet!\n");
+	if (~opcode & 0x80) {
+		WARNING(__FUNCTION__ "(), IrIAS multiframe commands or results"
+			"is not implemented yet!\n");
 		return;
 	}
 	opcode &= 0x7f; /* Mask away LST bit */
 	
 	switch (opcode) {
 	case GET_INFO_BASE:
-		DEBUG( 0, "IrLMP GetInfoBaseDetails not implemented!\n");
+		WARNING(__FUNCTION__ 
+			"(), GetInfoBaseDetails not implemented yet!\n");
 		break;
 	case GET_VALUE_BY_CLASS:
-		iriap_getvaluebyclass_indication( self, skb);
+		iriap_getvaluebyclass_indication(self, skb);
 		break;
 	}
 }
@@ -873,18 +945,17 @@
 /*
  * Function iriap_watchdog_timer_expired (data)
  *
- *    
+ *    Query has taken to long time, so abort
  *
  */
-void iriap_watchdog_timer_expired( unsigned long data)
+void iriap_watchdog_timer_expired(void *data)
 {
-	struct iriap_cb *self = ( struct iriap_cb *) data;
+	struct iriap_cb *self = (struct iriap_cb *) data;
 	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IAS_MAGIC, return;);
 
-	DEBUG(0, __FUNCTION__ "() Timeout! closing myself!\n");
-	iriap_close( self);
+	/* iriap_close(self); */
 }
 
 #ifdef CONFIG_PROC_FS
@@ -909,56 +980,56 @@
 
 	len = 0;
 
-	len += sprintf( buf+len, "LM-IAS Objects:\n");
+	len += sprintf(buf+len, "LM-IAS Objects:\n");
 
 	/* List all objects */
-	obj = (struct ias_object *) hashbin_get_first( objects);
+	obj = (struct ias_object *) hashbin_get_first(objects);
 	while ( obj != NULL) {
-		ASSERT( obj->magic == IAS_OBJECT_MAGIC, return 0;);
+		ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
 
-		len += sprintf( buf+len, "name: %s, ", obj->name);
-		len += sprintf( buf+len, "id=%d", obj->id);
-		len += sprintf( buf+len, "\n");
+		len += sprintf(buf+len, "name: %s, ", obj->name);
+		len += sprintf(buf+len, "id=%d", obj->id);
+		len += sprintf(buf+len, "\n");
 
 		/* List all attributes for this object */
 		attrib = (struct ias_attrib *) 
-			hashbin_get_first( obj->attribs);
-		while ( attrib != NULL) {
-			ASSERT( attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
-
-			len += sprintf( buf+len, " - Attribute name: \"%s\", ",
- 					attrib->name);
-			len += sprintf( buf+len, "value[%s]: ", 
-					ias_value_types[ attrib->value->type]);
+			hashbin_get_first(obj->attribs);
+		while (attrib != NULL) {
+			ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
+
+			len += sprintf(buf+len, " - Attribute name: \"%s\", ",
+				       attrib->name);
+			len += sprintf(buf+len, "value[%s]: ", 
+				       ias_value_types[attrib->value->type]);
 			
-			switch( attrib->value->type) {
+			switch (attrib->value->type) {
 			case IAS_INTEGER:
-				len += sprintf( buf+len, "%d\n", 
-						attrib->value->t.integer);
+				len += sprintf(buf+len, "%d\n", 
+					       attrib->value->t.integer);
 				break;
 			case IAS_STRING:
-				len += sprintf( buf+len, "\"%s\"\n", 
-						attrib->value->t.string);
+				len += sprintf(buf+len, "\"%s\"\n", 
+					       attrib->value->t.string);
 				break;
 			case IAS_OCT_SEQ:
-				len += sprintf( buf+len, "octet sequence\n");
+				len += sprintf(buf+len, "octet sequence\n");
 				break;
 			case IAS_MISSING:
-				len += sprintf( buf+len, "missing\n");
+				len += sprintf(buf+len, "missing\n");
 				break;
 			default:
-				DEBUG( 0, __FUNCTION__ 
-				       "(), Unknown value type!\n");
+				IRDA_DEBUG(0, __FUNCTION__ 
+				      "(), Unknown value type!\n");
 				return -1;
 			}
-			len += sprintf( buf+len, "\n");
+			len += sprintf(buf+len, "\n");
 			
 			attrib = (struct ias_attrib *) 
 				hashbin_get_next(obj->attribs);
 		}
-	        obj = ( struct ias_object *) hashbin_get_next( objects);
+	        obj = (struct ias_object *) hashbin_get_next(objects);
  	} 
-	restore_flags( flags);
+	restore_flags(flags);
 
 	return len;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)