patch-2.2.3 linux/net/irda/irlpt/irlpt_common.c

Next file: linux/net/irda/irlpt/irlpt_srvr.c
Previous file: linux/net/irda/irlpt/irlpt_cli_fsm.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.2/linux/net/irda/irlpt/irlpt_common.c linux/net/irda/irlpt/irlpt_common.c
@@ -68,7 +68,7 @@
 
 char *irlpt_reasons[] = {
 	"SERVICE_CLOSE",     /* Service has closed the connection */
-	"DISC_INDICATION",   /* Received a disconnect request from peer entity*/
+	"DISC_INDICATION",   /* Received disconnect request from peer entity*/
 	"NO_RESPONSE",       /* To many retransmits without response */
 	"DEADLOCK_DETECTED", /* To many retransmits _with_ response */
 	"FOUND_NONE",        /* No devices were discovered */
@@ -81,7 +81,6 @@
 	"IRLPT_CLIENT_QUERY",
 	"IRLPT_CLIENT_READY",
 	"IRLPT_CLIENT_WAITI",
-	"IRLPT_CLIENT_WAITR",
 	"IRLPT_CLIENT_CONN"
 };
 
@@ -108,9 +107,8 @@
 hashbin_t *irlpt_clients = NULL;
 struct irlpt_cb *irlpt_server = NULL;
 int irlpt_common_debug = 4;  /* want to change this? please don't! 
-				use irlpt_common_debug=3 on the command line! */
-
-static struct wait_queue *irlpt_wait;
+				use irlpt_common_debug=3 on the 
+				command line! */
 
 #if 0
 static char *rcsid = "$Id: irlpt_common.c,v 1.6 1998/11/10 22:50:58 dagb Exp $";
@@ -152,7 +150,6 @@
 	char *ptr = buffer;
 	struct irlpt_cb *self;
 	struct sk_buff *skb = NULL;
-	struct wait_queue wait = { current, NULL };
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -170,11 +167,12 @@
 		switch (self->eof) {
 		case LM_USER_REQUEST:
 			self->eof = FALSE;
-			DEBUG(3, "irlpt_read: returning 0\n");
+			DEBUG(irlpt_common_debug, 
+			      __FUNCTION__ ": returning 0\n");
 			return 0;
 		case LM_LAP_DISCONNECT:
 			self->eof = FALSE;
-			return -EIO;
+			return 0;
 		case LM_LAP_RESET:
 			self->eof = FALSE;
 			return -ECONNRESET;
@@ -208,11 +206,7 @@
 			       len, count, self->eof);
 
 			if (!signal_pending(current) && !self->eof) {
-			        add_wait_queue(&irlpt_wait, &wait);
-				current->state = TASK_INTERRUPTIBLE;
-				schedule();
-				current->state = TASK_RUNNING;
-				remove_wait_queue(&irlpt_wait, &wait);
+				interruptible_sleep_on(&self->read_wait);
 			} else
 				break;
 		}
@@ -228,7 +222,6 @@
 {
 	struct irlpt_cb *self;
 	struct sk_buff *skb;
-	struct wait_queue wait = { current, NULL };
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -240,26 +233,25 @@
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
 	       ": count = %d\n", count);
 
-	if (self->state != IRLPT_CLIENT_CONN) {
+	DEBUG( irlpt_common_debug, __FUNCTION__ 
+	       ": pkt_count = %d\n", self->pkt_count);
+	if (self->pkt_count > 8) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state != IRLPT_CONN (possible link problems?)\n");
-		return -ENOLINK;
+		       ": too many outstanding buffers, going to sleep\n");
+		interruptible_sleep_on(&self->write_wait);
 	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
 	       ": pkt_count = %d\n", self->pkt_count);
-	if (self->pkt_count > 8) {
+
+	if (self->state != IRLPT_CLIENT_CONN) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": too many outstanding buffers, going to sleep\n");
-		add_wait_queue(&self->write_wait, &wait);
-		current->state = TASK_INTERRUPTIBLE;
-		schedule();
-		current->state = TASK_RUNNING;
-		remove_wait_queue(&self->write_wait, &wait);
+		       ": state != IRLPT_CONN (possible link problems?)\n");
+		return -ENOLINK;
 	}
 
 	DEBUG( irlpt_common_debug, __FUNCTION__ 
-	       ":count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
+	       ": count = %d, irlap_data_size = %d, IRLPT_MAX_HEADER = %d\n",
 		count, self->irlap_data_size, IRLPT_MAX_HEADER);
 
  	if (count > (self->irlap_data_size - IRLPT_MAX_HEADER)) {
@@ -272,7 +264,8 @@
 
 	skb = dev_alloc_skb(count + IRLPT_MAX_HEADER);
 	if ( skb == NULL) {
-		printk( KERN_INFO __FUNCTION__ ": couldn't allocate skbuff!\n");
+		printk( KERN_INFO 
+			__FUNCTION__ ": couldn't allocate skbuff!\n");
 		return 0;
 	}
 
@@ -292,6 +285,9 @@
 
 	irlmp_data_request(self->lsap, skb);
 
+	irda_start_timer( &self->lpt_timer, 5000, (unsigned long) self, 
+			  self->timeout);
+
 	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 
 	return(count);
@@ -305,60 +301,13 @@
 	return -ESPIPE;
 }
 
-#if 0
-
-/*
- * Function irlpt_select (inode, filp, mode, table)
- *
- *    Implementation for the select() call
- *
- */
-int irlpt_select( struct inode *inode, struct file *filp, int mode, 
-			 select_table *table)
-{
-	struct irlpt_cb *self;
-
-	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
-	
-	self = irlpt_find_handle(MINOR( inode->i_rdev));
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
-
-	switch (mode) {
-	case SEL_IN:
-		if ( skb_queue_len( &self->rx_queue))
-			return 1; /* Readable */
-		select_wait( &self->read_wait, table);
-		break;
-	case SEL_OUT:
-		if ( self->connected)
-			return 1;
-		select_wait( &self->write_wait, table);
-		break;
-	case SEL_EX:
-		if ( self->connected)
-			return 1;
-		select_wait( &self->ex_wait, table);
-		break;
-	default:
-		break;
-	}
-
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
-
-	return 0;
-}
-
-#else
-
 /*
- * Function irobex_poll (file, wait)
+ * Function irlpt_poll (file, wait)
  *
  *    
  *
  */
-static u_int irlpt_poll(struct file *file, poll_table *wait)
+u_int irlpt_poll(struct file *file, poll_table *wait)
 {
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -367,8 +316,6 @@
 	return 0;
 }
 
-#endif
-
 /*
  * Function open_irlpt (inode, file)
  *
@@ -378,6 +325,7 @@
 int irlpt_open(struct inode *inode, struct file *file)
 {
 	struct irlpt_cb *self;
+	struct irlpt_info info;
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -386,22 +334,6 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-#if 0
-	if (self->state == IRLPT_IDLE) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ 
-		       ": state == IRLPT_IDLE! (no device found yet)\n");
-		return -ENODEV;
-	}
-
-	if (self->state == IRLPT_QUERY ||
-	    self->state == IRLPT_READY ||
-	    self->state == IRLPT_WAITI) {
-		DEBUG( irlpt_common_debug, __FUNCTION__ ": state == IRLPT_QUERY, " 
-		       "IRLPT_READY or IRLPT_WAITI (link problems)!\n");
-		return -EBUSY;
-	}
-#endif
-
 	if (self->count++) {
 		DEBUG( irlpt_common_debug, __FUNCTION__ 
 		       ": count not zero; actual = %d\n", self->count);
@@ -409,6 +341,35 @@
 		return -EBUSY;
 	}
 
+	self->eof = FALSE;
+
+	/* ok, now, if it's idle, try to get some information
+	   about the remote end, and sleep till we get totally connected.. */
+
+	if ((self->servicetype != IRLPT_SERVER_MODE) && 
+	    self->state != IRLPT_CLIENT_CONN) {
+		DEBUG(irlpt_common_debug, __FUNCTION__
+		      ": self->state != IRLPT_CLIENT_CONN\n");
+
+		info.daddr = self->daddr;
+		info.saddr = self->saddr;
+
+		if (self->do_event != NULL) {
+			DEBUG(irlpt_common_debug, __FUNCTION__ 
+			      ": doing a discovery..\n");
+			self->do_event( self, 
+					IRLPT_DISCOVERY_INDICATION, 
+					NULL, &info);
+			DEBUG(irlpt_common_debug, __FUNCTION__ 
+			      ": sleeping until connected.\n");
+			interruptible_sleep_on(&self->read_wait);
+		}
+	}
+
+	/* at this point, if it's a client, we have a connection.
+	 * if it's the server, it's waiting for a connection.
+	 */
+
 	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 
 	return 0;
@@ -420,9 +381,12 @@
  *
  *
  */
-int irlpt_close(struct inode *inode, struct file *file)
+int irlpt_close(struct inode *inode, 
+		struct file *file)
 {
 	struct irlpt_cb *self;
+	struct sk_buff *skb;
+	struct irlpt_info info;
 
 	DEBUG(irlpt_common_debug, "--> " __FUNCTION__ "\n");
 
@@ -433,12 +397,42 @@
 	ASSERT( self != NULL, return -1;);
 	ASSERT( self->magic == IRLPT_MAGIC, return -1;);
 
-	DEBUG(irlpt_common_debug, __FUNCTION__ ": self->count=%d\n", self->count);
+	DEBUG(irlpt_common_debug, 
+	      __FUNCTION__ ": self->count=%d\n", self->count);
+
 	if (self->count > 0)
 		self->count--;
 
-	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
+	while (self->pkt_count > 0) {
+		interruptible_sleep_on(&self->write_wait);
+	}
 
+	/* all done, tear down the connection and wait for the next open */
+	if ((self->servicetype != IRLPT_SERVER_MODE) &&
+	    self->state == IRLPT_CLIENT_CONN) {
+		skb = dev_alloc_skb(64);
+		if (skb == NULL) {
+			DEBUG( 0, __FUNCTION__ "(: Could not allocate an "
+			       "sk_buff of length %d\n", 64);
+			return 0;
+		}
+
+		skb_reserve( skb, LMP_CONTROL_HEADER+LAP_HEADER);
+		irlmp_disconnect_request(self->lsap, skb);
+		DEBUG(irlpt_common_debug, __FUNCTION__
+		      ": irlmp_close_slap(self->lsap)\n");
+		irlmp_close_lsap(self->lsap);
+	}
+
+	info.daddr = self->daddr;
+
+	if (self->do_event != NULL) {
+	        DEBUG(irlpt_common_debug, __FUNCTION__ 
+		      ": closing connection..\n");
+		self->do_event( self, LMP_DISCONNECT, NULL, &info);
+	}
+
+	DEBUG(irlpt_common_debug, __FUNCTION__ " -->\n");
 	return 0;
 }
 
@@ -485,6 +479,10 @@
 }
 
 #ifdef MODULE
+
+MODULE_AUTHOR("Thomas Davis <ratbert@radiks.net>");
+MODULE_DESCRIPTION("The Linux IrDA/IrLPT common");
+MODULE_PARM(irlpt_common_debug,"1i");
 
 /*
  * Function init_module (void)

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