patch-2.3.19 linux/net/irda/ircomm/ircomm_tty.c

Next file: linux/net/irda/ircomm/ircomm_tty_attach.c
Previous file: linux/net/irda/ircomm/ircomm_ttp.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.18/linux/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c
@@ -6,7 +6,7 @@
  * Status:        Experimental.
  * Author:        Dag Brattli <dagb@cs.uit.no>
  * Created at:    Sun Jun  6 21:00:56 1999
- * Modified at:   Wed Aug 25 15:12:18 1999
+ * Modified at:   Tue Sep 21 11:46:59 1999
  * Modified by:   Dag Brattli <dagb@cs.uit.no>
  * Sources:       serial.c and previous IrCOMM work by Takahide Higuchi
  * 
@@ -60,11 +60,8 @@
 static void ircomm_tty_send_xchar(struct tty_struct *tty, char ch);
 static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout);
 static void ircomm_tty_hangup(struct tty_struct *tty);
-static void ircomm_tty_break(struct tty_struct *tty, int break_state);
 static void ircomm_tty_do_softint(void *private_);
-static void ircomm_tty_disconnect_indication(void *instance, void *sap, 
-					     LM_REASON reason,
-					     struct sk_buff *skb);
+
 static int ircomm_tty_data_indication(void *instance, void *sap,
 				      struct sk_buff *skb);
 static int ircomm_tty_control_indication(void *instance, void *sap,
@@ -127,7 +124,6 @@
 	driver.stop            = ircomm_tty_stop;
 	driver.start           = ircomm_tty_start;
 	driver.hangup          = ircomm_tty_hangup;
-	driver.break_ctl       = ircomm_tty_break;
 	driver.wait_until_sent = ircomm_tty_wait_until_sent;
 	driver.read_proc       = ircomm_tty_read_proc;
 
@@ -170,9 +166,12 @@
 	notify_t notify;
 	int ret;
 
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
+
 	/* Already open */
 	if (self->flags & ASYNC_INITIALIZED) {
-		DEBUG(0, __FUNCTION__ "(), already open so break out!\n");
+		DEBUG(2, __FUNCTION__ "(), already open so break out!\n");
 		return 0;
 	}
 
@@ -181,10 +180,10 @@
 	/* These callbacks we must handle ourselves */
 	notify.data_indication       = ircomm_tty_data_indication;
 	notify.udata_indication      = ircomm_tty_control_indication;
- 	notify.disconnect_indication = ircomm_tty_disconnect_indication;
  	notify.flow_indication       = ircomm_tty_flow_indication;
 
 	/* Use the ircomm_tty interface for these ones */
+ 	notify.disconnect_indication = ircomm_tty_disconnect_indication;
 	notify.connect_confirm       = ircomm_tty_connect_confirm;
  	notify.connect_indication    = ircomm_tty_connect_indication;
 	strncpy(notify.name, "ircomm_tty", NOTIFY_MAX_NAME);
@@ -201,7 +200,7 @@
 	/* Connect IrCOMM link with remote device */
 	ret = ircomm_tty_attach_cable(self);
 	if (ret < 0) {
-		DEBUG(0, __FUNCTION__ "(), error attaching cable!\n");
+		ERROR(__FUNCTION__ "(), error attaching cable!\n");
 		return ret;
 	}
 
@@ -227,7 +226,7 @@
 	
 	tty = self->tty;
 
-	DEBUG(1, __FUNCTION__ "()\n");
+	DEBUG(2, __FUNCTION__ "()\n");
 
 	if (tty->driver.subtype == SERIAL_TYPE_CALLOUT) {
 		/* this is a callout device */
@@ -283,7 +282,7 @@
 	retval = 0;
 	add_wait_queue(&self->open_wait, &wait);
 	
-	DEBUG(1, "%s(%d):block_til_ready before block on %s open_count=%d\n",
+	DEBUG(2, "%s(%d):block_til_ready before block on %s open_count=%d\n",
 	      __FILE__,__LINE__, tty->driver.name, self->open_count );
 
 	save_flags(flags); cli();
@@ -391,16 +390,25 @@
 		self->tqueue.routine = ircomm_tty_do_softint;
 		self->tqueue.data = self;
 		self->max_header_size = 5;
-		self->max_data_size = 2048-self->max_header_size;
+		self->max_data_size = 64-self->max_header_size;
+		self->close_delay = 5*HZ/10;
+		self->closing_wait = 30*HZ;
 
 		/* Init some important stuff */
 		init_timer(&self->watchdog_timer);
 		init_waitqueue_head(&self->open_wait);
-		skb_queue_head_init(&self->tx_queue);
+		init_waitqueue_head(&self->close_wait);
+
+		/* 
+		 * Force TTY into raw mode by default which is usually what
+		 * we want for IrCOMM and IrLPT. This way applications will
+		 * not have to twiddle with printcap etc.  
+		 */
+		tty->termios->c_iflag = 0;
+		tty->termios->c_oflag = 0;
 
 		/* Insert into hash */
 		hashbin_insert(ircomm_tty, (QUEUE *) self, line, NULL);
-
 	}
 	self->open_count++;
 
@@ -413,12 +421,28 @@
 	/* Not really used by us, but lets do it anyway */
 	self->tty->low_latency = (self->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
 
+	/*
+	 * If the port is the middle of closing, bail out now
+	 */
+	if (tty_hung_up_p(filp) ||
+	    (self->flags & ASYNC_CLOSING)) {
+		if (self->flags & ASYNC_CLOSING)
+			interruptible_sleep_on(&self->close_wait);
+		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+#ifdef SERIAL_DO_RESTART
+		return ((self->flags & ASYNC_HUP_NOTIFY) ?
+			-EAGAIN : -ERESTARTSYS);
+#else
+		return -EAGAIN;
+#endif
+	}
+
 	/* Check if this is a "normal" ircomm device, or an irlpt device */
 	if (line < 0x10) {
 		self->service_type = IRCOMM_3_WIRE | IRCOMM_9_WIRE;
-		DEBUG(0, __FUNCTION__ "(), IrCOMM device\n");
+		DEBUG(2, __FUNCTION__ "(), IrCOMM device\n");
 	} else {
-		DEBUG(0, __FUNCTION__ "(), IrLPT device\n");
+		DEBUG(2, __FUNCTION__ "(), IrLPT device\n");
 		self->service_type = IRCOMM_3_WIRE_RAW;
 	}
 
@@ -452,7 +476,6 @@
 static void ircomm_tty_close(struct tty_struct *tty, struct file *filp)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
-	struct sk_buff *skb;
 	unsigned long flags;
 
 	DEBUG(2, __FUNCTION__ "()\n");
@@ -484,7 +507,7 @@
 		MOD_DEC_USE_COUNT;
 		restore_flags(flags);
 
-		DEBUG(2, __FUNCTION__ "(), returning 2\n");
+		DEBUG(2, __FUNCTION__ "(), open count > 0\n");
 		return;
 	}
 	self->flags |= ASYNC_CLOSING;
@@ -494,6 +517,10 @@
 	 * the line discipline to only process XON/XOFF characters.
 	 */
 	tty->closing = 1;
+	if (self->closing_wait != ASYNC_CLOSING_WAIT_NONE)
+		tty_wait_until_sent(tty, self->closing_wait);
+
+	self->flags &= ~ASYNC_INITIALIZED;
 
 	if (tty->driver.flush_buffer)
 		tty->driver.flush_buffer(tty);
@@ -503,35 +530,47 @@
 	tty->closing = 0;
 	self->tty = 0;
 
-	wake_up_interruptible(&self->open_wait);
-	
+	if (self->blocked_open) {
+		if (self->close_delay) {
+			current->state = TASK_INTERRUPTIBLE;
+			schedule_timeout(self->close_delay);
+		}
+		wake_up_interruptible(&self->open_wait);
+	}
+
 	self->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE|
 			 ASYNC_CLOSING);
+	wake_up_interruptible(&self->close_wait);
 
 	MOD_DEC_USE_COUNT;
-	restore_flags(flags);
 
 	del_timer(&self->watchdog_timer);
 	
-	/* Free frames queued for transmission */
-	while ((skb = skb_dequeue(&self->tx_queue)) != NULL)
-		dev_kfree_skb(skb);
-
 	/* Free parameter buffer */
 	if (self->ctrl_skb) {
 		dev_kfree_skb(self->ctrl_skb);
 		self->ctrl_skb = NULL;
 	}
 
+	/* Free transmit buffer */
+	if (self->tx_skb) {
+		dev_kfree_skb(self->tx_skb);
+		self->tx_skb = NULL;
+	}
+
+	restore_flags(flags);
+
 	ircomm_tty_detach_cable(self);
 	ircomm_close(self->ircomm);
-
 	self->ircomm = NULL;
+
+#if IRCOMM_TTY_CLOSE_WILL_DEALLOC
 	self->magic = 0;
 
 	hashbin_remove(ircomm_tty, self->line, NULL);
 
 	kfree(self);
+#endif
 }
 
 /*
@@ -544,18 +583,15 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
-	DEBUG(2, __FUNCTION__ "()\n");
-
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
-	/* Flush transmit buffer if any */
-	if ((self->tx_skb) && (!tty->hw_stopped)) {
-		DEBUG(0, __FUNCTION__ "(), flushing!\n");
-		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, 
-				    self->tx_skb, NULL);
-		self->tx_skb = NULL;
-	}
+	/* 
+	 * Let do_softint() do this to avoid race condition with 
+	 * do_softint() ;-) 
+	 */
+	queue_task(&self->tqueue, &tq_immediate);
+	mark_bh(IMMEDIATE_BH);
 }
 
 /*
@@ -569,28 +605,31 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) private_;
 	struct tty_struct *tty;
+	unsigned long flags;
+	struct sk_buff *skb;
 
-	DEBUG(2, __FUNCTION__ "()\n");
-	
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
+	if (!self || self->magic != IRCOMM_TTY_MAGIC)
+		return;
 
 	tty = self->tty;
 	if (!tty)
 		return;
 
-	if (tty->hw_stopped) {
-		DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
+	if (tty->hw_stopped)
 		return;
-	}
+
+	/* Unlink transmit buffer */
+	save_flags(flags);
+	cli();
+	
+	skb = self->tx_skb;
+	self->tx_skb = NULL;
+
+	restore_flags(flags);
 
 	/* Flush transmit buffer if any */
-	if (self->tx_skb) {
-		DEBUG(1, __FUNCTION__ "(), flushing!\n");
-		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, 
-				    self->tx_skb, NULL);
-		self->tx_skb = NULL;
-	}
+	if (skb)
+		ircomm_tty_do_event(self, IRCOMM_TTY_DATA_REQUEST, skb, NULL);
 		
 	/* Check if user (still) wants to be waken up */
 	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && 
@@ -625,9 +664,9 @@
 	ASSERT(self != NULL, return -1;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-/*	save_flags(flags);
+	save_flags(flags);
 	cli();
-*/
+
 	/* Fetch current transmit buffer */
 	skb = self->tx_skb;
 
@@ -637,20 +676,19 @@
 	 * max data size. The normal case however is just the opposite, and
 	 * this function may be called multiple times, and will then actually
 	 * defragment the data and send it out as one packet as soon as 
-	 * possible, but at a safer point in time 
+	 * possible, but at a safer point in time
 	 */
-	while (count && !tty->hw_stopped) {
+	while (count) {
 		size = count;
 
 		/* Adjust data size to the max data size */
-		if (size > self->max_data_size) {
-			DEBUG(1, __FUNCTION__ 
-			      "(), size %d to big, clipping to %d!\n",
-			      size, self->max_data_size);
+		if (size > self->max_data_size)
 			size = self->max_data_size;
-		}
 		
-		/* Do we already have a buffer ready for transmit? */
+		/* 
+		 * Do we already have a buffer ready for transmit, or do
+		 * we need to allocate a new frame 
+		 */
 		if (skb) {			
 			/* 
 			 * Any room for more data at the end of the current 
@@ -663,25 +701,18 @@
 				if (size > tailroom)
 					size = tailroom;
 			} else {
-				/* Current transmit frame is full */
-				DEBUG(1, __FUNCTION__ "(), flushing!\n");
-				ircomm_tty_do_event(self, 
-						    IRCOMM_TTY_DATA_REQUEST, 
-						    skb, NULL);
-				skb = self->tx_skb = NULL;
+				/* 
+				 * Current transmit frame is full, so break 
+				 * out, so we can send it as soon as possible
+				 */
+				break;
 			}
-		}
-
-		/* Check if we need to allocate a new frame */
-		if (!skb) {
-			DEBUG(3, __FUNCTION__ 
-			      "(), allocating new buffer of size %d!\n",
-			      self->max_data_size+self->max_header_size);
+		} else {
 			/* Prepare a full sized frame */
 			skb = dev_alloc_skb(self->max_data_size+
 					    self->max_header_size);
 			if (!skb) {
-				/*restore_flags(flags);*/
+				restore_flags(flags);
 				return -ENOBUFS;
 			}
 			skb_reserve(skb, self->max_header_size);
@@ -694,12 +725,12 @@
 		else
 			memcpy(skb_put(skb,size), buf+len, size);
 		
-		DEBUG(1, __FUNCTION__ "(), size=%d\n", size);
-
 		count -= size;
 		len += size;
 	}
 
+	restore_flags(flags);
+
 	/*     
 	 * Schedule a new thread which will transmit the frame as soon
 	 * as possible, but at a safe point in time. We do this so the
@@ -710,8 +741,6 @@
 	queue_task(&self->tqueue, &tq_immediate);
 	mark_bh(IMMEDIATE_BH);
 	
-	/*restore_flags(flags);*/
-
 	return len;
 }
 
@@ -725,6 +754,7 @@
 static int ircomm_tty_write_room(struct tty_struct *tty)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
 	int ret;
 
 	ASSERT(self != NULL, return -1;);
@@ -734,10 +764,13 @@
 	if (tty->hw_stopped)
 		ret = 0;
 	else {
+		save_flags(flags);
+		cli();
 		if (self->tx_skb)
 			ret = self->max_data_size - self->tx_skb->len;
 		else
 			ret = self->max_data_size;
+		restore_flags(flags);
 	}
 	DEBUG(2, __FUNCTION__ "(), ret=%d\n", ret);
 
@@ -753,8 +786,27 @@
 static void ircomm_tty_wait_until_sent(struct tty_struct *tty, int timeout)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long orig_jiffies, poll_time;
+	
+	DEBUG(0, __FUNCTION__ "()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
-	DEBUG(2, __FUNCTION__ "(), not impl\n");
+	orig_jiffies = jiffies;
+
+	/* Set poll time to 200 ms */
+	poll_time = MIN(timeout, MSECS_TO_JIFFIES(200));
+
+	while (self->tx_skb && self->tx_skb->len) {
+		current->state = TASK_INTERRUPTIBLE;
+		schedule_timeout(poll_time);
+		if (signal_pending(current))
+			break;
+		if (timeout && time_after(jiffies, orig_jiffies + timeout))
+			break;
+	}
+	current->state = TASK_RUNNING;
 }
 
 /*
@@ -785,7 +837,6 @@
 		ircomm_param_request(self, IRCOMM_DTE, TRUE);
 	}
 
-	DEBUG(1, __FUNCTION__"(), FLOW_STOP\n");
         ircomm_flow_request(self->ircomm, FLOW_STOP);
 }
 
@@ -829,10 +880,21 @@
 static int ircomm_tty_chars_in_buffer(struct tty_struct *tty)
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
+	unsigned long flags;
+	int len = 0;
 
-	DEBUG(4, __FUNCTION__ "()\n");
+	ASSERT(self != NULL, return -1;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return -1;);
 
-	return 0; /* We don't have any "buffer" */
+	save_flags(flags);
+	cli();
+
+	if (self->tx_skb)
+		len = self->tx_skb->len;
+
+	restore_flags(flags);
+
+	return len;
 }
 
 /*
@@ -846,7 +908,10 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
-	DEBUG(0, __FUNCTION__"()\n");
+	DEBUG(2, __FUNCTION__"()\n");
+
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
 	if (!tty)
 		return;
@@ -889,8 +954,6 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
-	DEBUG(2, __FUNCTION__"()\n");
-
 	ircomm_flow_request(self->ircomm, FLOW_START);
 }
 
@@ -904,25 +967,13 @@
 {
 	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
 
- 	DEBUG(2, __FUNCTION__"()\n");
+	ASSERT(self != NULL, return;);
+	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
 	ircomm_flow_request(self->ircomm, FLOW_STOP);
 }
 
 /*
- * Function ircomm_tty_break (tty, break_state)
- *
- *    
- *
- */
-static void ircomm_tty_break(struct tty_struct *tty, int break_state)
-{
-	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) tty->driver_data;
-
- 	DEBUG(0, __FUNCTION__"(), not impl\n");
-}
-
-/*
  * Function ircomm_check_modem_status (self)
  *
  *    Check for any changes in the DCE's line settings. This function should
@@ -934,8 +985,6 @@
 	struct tty_struct *tty;
 	int status;
 
-	DEBUG(4, __FUNCTION__ "()\n");
-	
 	ASSERT(self != NULL, return;);
 	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
 
@@ -967,13 +1016,9 @@
 				DEBUG(2, __FUNCTION__ "(), CTS tx start...\n");
 				
 				tty->hw_stopped = 0;
-				
-				if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) 
-				    && tty->ldisc.write_wakeup)
-				{
-					(tty->ldisc.write_wakeup)(tty);
-				}
-				wake_up_interruptible(&tty->write_wait);
+
+				queue_task(&self->tqueue, &tq_immediate);
+				mark_bh(IMMEDIATE_BH);
 				return;
 			}
 		} else {
@@ -1045,35 +1090,6 @@
 }
 
 /*
- * Function ircomm_tty_disconnect_indication (instance, sap, reason, skb)
- *
- *    Link disconnected
- *
- */
-static void ircomm_tty_disconnect_indication(void *instance, void *sap, 
-					     LM_REASON reason,
-					     struct sk_buff *skb)
-{
-	struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance;
-
-	DEBUG(2, __FUNCTION__ "()\n");
-
-	ASSERT(self != NULL, return;);
-	ASSERT(self->magic == IRCOMM_TTY_MAGIC, return;);
-
-	if (!self->tty)
-		return;
-
-	/* Drop carrier */
-	self->session.dce = IRCOMM_DELTA_CD;
-	ircomm_tty_check_modem_status(self);
-#if 0
-	/* Disconnect */
-	tty_hangup(self->tty);
-#endif
-}
-
-/*
  * Function ircomm_tty_flow_indication (instance, sap, cmd)
  *
  *    This function is called by IrTTP when it wants us to slow down the
@@ -1093,18 +1109,17 @@
 
 	switch (cmd) {
 	case FLOW_START:
-		DEBUG(1, __FUNCTION__ "(), hw start!\n");
+		DEBUG(2, __FUNCTION__ "(), hw start!\n");
 		tty->hw_stopped = 0;
-		
-		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) 
-		    && tty->ldisc.write_wakeup)
-			(tty->ldisc.write_wakeup)(tty);
-		wake_up_interruptible(&tty->write_wait);
+
+		/* ircomm_tty_do_softint will take care of the rest */
+		queue_task(&self->tqueue, &tq_immediate);
+		mark_bh(IMMEDIATE_BH);		
 		break;
 	default:
 		/* If we get here, something is very wrong, better stop */
 	case FLOW_STOP:
-		DEBUG(1, __FUNCTION__ "(), hw stopped!\n");
+		DEBUG(2, __FUNCTION__ "(), hw stopped!\n");
 		tty->hw_stopped = 1;
 		break;
 	}
@@ -1114,6 +1129,8 @@
 {
         int  ret=0;
 
+	ret += sprintf(buf+ret, "State: %s\n", ircomm_tty_state[self->state]);
+
 	ret += sprintf(buf+ret, "Service type: ");
 	if (self->service_type & IRCOMM_9_WIRE)
 		ret += sprintf(buf+ret, "9_WIRE");
@@ -1125,12 +1142,15 @@
 		ret += sprintf(buf+ret, "No common service type!\n");
         ret += sprintf(buf+ret, "\n");
 
+	ret += sprintf(buf+ret, "Port name: %s\n", self->session.port_name);
+
 	ret += sprintf(buf+ret, "DTE status: ");	
         if (self->session.dte & IRCOMM_RTS)
                 ret += sprintf(buf+ret, "RTS|");
         if (self->session.dte & IRCOMM_DTR)
                 ret += sprintf(buf+ret, "DTR|");
-	ret--; /* remove the last | */
+	if (self->session.dte)
+		ret--; /* remove the last | */
         ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "DCE status: ");
@@ -1142,7 +1162,8 @@
                 ret += sprintf(buf+ret, "CD|");
         if (self->session.dce & IRCOMM_RI) 
                 ret += sprintf(buf+ret, "RI|");
-	ret--; /* remove the last | */
+	if (self->session.dce)
+		ret--; /* remove the last | */
         ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Configuration: ");
@@ -1171,7 +1192,8 @@
 		ret += sprintf(buf+ret, "ENQ_ACK_IN|");
 	if (self->session.flow_control & IRCOMM_ENQ_ACK_OUT)
 		ret += sprintf(buf+ret, "ENQ_ACK_OUT|");
-	ret--; /* remove the last | */
+	if (self->session.flow_control)
+		ret--; /* remove the last | */
         ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Flags: ");
@@ -1189,7 +1211,8 @@
 		ret += sprintf(buf+ret, "ASYNC_NORMAL_ACTIVE|");
 	if (self->flags & ASYNC_CALLOUT_ACTIVE)
 		ret += sprintf(buf+ret, "ASYNC_CALLOUT_ACTIVE|");
-	ret--; /* remove the last | */
+	if (self->flags)
+		ret--; /* remove the last | */
 	ret += sprintf(buf+ret, "\n");
 
 	ret += sprintf(buf+ret, "Open count: %d\n", self->open_count);
@@ -1197,7 +1220,6 @@
 		ret += sprintf(buf+ret, "Hardware: %s\n", 
 			       self->tty->hw_stopped ? "Stopped" : "Running");
 
- exit:
         ret += sprintf(buf+ret, "\n");
         return ret;
 }
@@ -1213,7 +1235,7 @@
 				int *eof, void *unused)
 {
 	struct ircomm_tty_cb *self;
-        int i, count = 0, l;
+        int count = 0, l;
         off_t begin = 0;
 
 	self = (struct ircomm_tty_cb *) hashbin_get_first(ircomm_tty);

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