patch-2.2.6 linux/net/irda/irobex/irobex.c

Next file: linux/net/irda/irproc.c
Previous file: linux/net/irda/irobex/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.5/linux/net/irda/irobex/irobex.c linux/net/irda/irobex/irobex.c
@@ -1,1170 +0,0 @@
-/*********************************************************************
- *                
- * Filename:      irobex.c
- * Version:       0.4
- * Description:   Kernel side of the IrOBEX layer
- * Status:        Experimental.
- * Author:        Dag Brattli <dagb@cs.uit.no>
- * Created at:    Thu Jun 25 21:21:07 1998
- * Modified at:   Mon Feb  8 09:05:01 1999
- * Modified by:   Dag Brattli <dagb@cs.uit.no>
- * 
- *     Copyright (c) 1998 Dag Brattli, 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/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/proc_fs.h>
-#include <linux/ioctl.h>
-#include <linux/init.h>
-
-#include <asm/byteorder.h>
-#include <asm/segment.h>
-#include <asm/uaccess.h>
-#include <linux/poll.h>
-
-#include <net/irda/irttp.h>
-#include <net/irda/irias_object.h>
-#include <net/irda/iriap.h>
-
-#include <net/irda/irobex.h>
-
-/*
- *  Master structure, only one instance for now!!
- */
-struct irobex_cb *irobex;
-
-extern char *lmp_reasons[];
-
-char *irobex_state[] = {
-	"OBEX_IDLE",
-	"OBEX_DISCOVER",
-	"OBEX_QUERY",
-	"OBEX_CONN",
-	"OBEX_DATA",
-};
-
-static void   irobex_cleanup(void);
-/* static struct irobex_cb *irobex_open(void); */
-/* static void   irobex_close( struct irobex_cb *self); */
-
-static void irobex_data_indication( void *instance, void *sap, 
-				    struct sk_buff *skb);
-static void irobex_disconnect_indication( void *instance, void *sap, 
-					  LM_REASON reason, 
-					  struct sk_buff *skb);
-static void irobex_disconnect_request( struct irobex_cb *self);
-static int irobex_connect_request(struct irobex_cb *self);
-static void irobex_connect_confirm( void *instance, void *sap, 
-				    struct qos_info *qos,
-				    int max_sdu_size, struct sk_buff *skb);
-static void irobex_discovery_indication( DISCOVERY *discovery);
-static void irobex_flow_indication( void *instance, void *sap, 
-				    LOCAL_FLOW flow);
-static void irobex_get_value_confirm(__u16 obj_id, struct ias_value *value, 
-				     void *priv);
-static void irobex_register_server( struct irobex_cb *self);
-static int irobex_ioctl( struct inode *inode, struct file *filp, 
-			 unsigned int cmd, unsigned long arg);
-static int irobex_dev_open( struct inode * inode, struct file *file);
-static int irobex_dev_close( struct inode *inode, struct file *file);
-static ssize_t irobex_read( struct file *file, char *buffer, size_t count, 
-			    loff_t *noidea);
-static ssize_t irobex_write( struct file *file, const char *buffer,
-			     size_t count, loff_t *noidea);
-static loff_t irobex_seek( struct file *, loff_t, int);
-static u_int irobex_poll( struct file *file, poll_table *wait);
-static int irobex_fasync( int, struct file *, int);
-
-static struct file_operations irobex_fops = {
-	irobex_seek,	/* seek */
-	irobex_read,
-	irobex_write,
-	NULL,		/* readdir */
-	irobex_poll,    /* poll */
-	irobex_ioctl,	/* ioctl */
-	NULL,		/* mmap */
-	irobex_dev_open,
-	NULL,
-	irobex_dev_close,
-	NULL,
-	irobex_fasync,
-};
-
-#ifdef CONFIG_PROC_FS
-static int irobex_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_irobex = {
-	0, 6, "irobex",
-	S_IFREG | S_IRUGO, 1, 0, 0,
-	0, NULL,
-	&irobex_proc_read,
-};
-#endif
-
-/*
- * Function irobex_init (dev)
- *
- *   Initializes the irobex control structure, and registers as a misc
- *   device
- *
- */
-__initfunc(int irobex_init(void))
-{
-	struct irmanager_event mgr_event;
-	struct irobex_cb *self;
-
-	self = kmalloc(sizeof(struct irobex_cb), GFP_ATOMIC);
-	if ( self == NULL)
-		return -ENOMEM;
-	
-	memset( self, 0, sizeof(struct irobex_cb));
- 	sprintf( self->devname, "irobex%d", 0); /* Just one instance for now */
-	
-	self->magic = IROBEX_MAGIC;
-	self->rx_flow = self->tx_flow = FLOW_START;
-	
-	self->dev.minor = MISC_DYNAMIC_MINOR;
-	self->dev.name = "irobex";
-	self->dev.fops = &irobex_fops;
-	
-	skb_queue_head_init( &self->rx_queue);
-	init_timer( &self->watchdog_timer);
-
-	irobex = self;
-	
-	misc_register( &self->dev);
-
-#ifdef CONFIG_PROC_FS
-	proc_register( &proc_irda, &proc_irobex);
-#endif /* CONFIG_PROC_FS */
-		
-	irlmp_register_layer( S_OBEX, CLIENT | SERVER, TRUE, 
-			      irobex_discovery_indication);
-
-/* 	mgr_event.event = EVENT_IROBEX_INIT; */
-/* 	sprintf( mgr_event.devname, "%s", self->devname); */
-/* 	irmanager_notify( &mgr_event); */
-	
-	return 0;
-}
-
-/*
- * Function irobex_cleanup (void)
- *
- *     Removes the IrOBEX layer
- *
- */
-#ifdef MODULE
-static void irobex_cleanup(void)
-{
-	struct sk_buff *skb;
-	struct irobex_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = irobex;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);	
-
-	/*
-	 *  Deregister client and server
-	 */
-	irlmp_unregister_layer( S_OBEX, CLIENT | SERVER);
-
-	if ( self->tsap) {
-		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
-		irttp_close_tsap( self->tsap);
-		self->tsap = NULL;
-	}
-
-	/* Stop timers */
-	del_timer( &self->watchdog_timer);
-
-	/*
-	 *  Deallocate buffers
-	 */
-	while (( skb = skb_dequeue( &self->rx_queue)) != NULL)
-		dev_kfree_skb( skb);
-
-#ifdef CONFIG_PROC_FS
-	proc_unregister( &proc_irda, proc_irobex.low_ino);
-#endif
-	
-	misc_deregister( &self->dev);
-	
-	kfree( self);	
-}
-#endif /* MODULE */
-
-/*
- * Function irobex_read (inode, file, buffer, count)
- *
- *    User process wants to read some data
- *
- */
-static ssize_t irobex_read( struct file *file, char *buffer, size_t count, 
-			    loff_t *noidea)
-{
-	int len=0;
-	struct irobex_cb *self;
-	struct sk_buff *skb = NULL;
-	int ret;
-	
-	self = irobex;
-
-	ASSERT( self != NULL, return -EIO;);
-	ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
-  
-	DEBUG( 4, __FUNCTION__ ": count=%d, skb_len=%d, state=%s, eof=%d\n", 
-	       count, skb_queue_len( &self->rx_queue), 
-	       irobex_state[self->state], self->eof);
-
-	if ( self->state != OBEX_DATA) {
-		DEBUG( 0, __FUNCTION__ "(), link not connected yet!\n");
-		return -EIO;
-	}
-
-	/*
-	 *  If there is data to return, then we return it. If not, then we 
-	 *  must check if we are still connected
-	 */
-	if ( skb_queue_len( &self->rx_queue) == 0) {
-
-		/* Still connected?  */
-		if ( self->state != OBEX_DATA) {
-			switch ( self->eof) {
-			case LM_USER_REQUEST:
-				self->eof = FALSE;
-				DEBUG(3, "read_irobex: returning 0\n");
-				ret = 0;
-				break;
-			case LM_LAP_DISCONNECT:
-				self->eof = FALSE;
-				ret = -EIO;
-				break;
-			case LM_LAP_RESET:
-				self->eof = FALSE;
-				ret = -ECONNRESET;
-				break;
-			default:
-				self->eof = FALSE;
-				ret = -EIO;
-				break;
-			}
-			return ret;
-		}
-
-		/* Return if user does not want to block */
-		if ( file->f_flags & O_NONBLOCK)
-			return -EAGAIN;
-
-		/* Go to sleep and wait for data!  */
-		interruptible_sleep_on( &self->read_wait);
-
-		/*
-		 *  Ensure proper reaction to signals, and screen out 
-		 *  blocked signals (page 112. linux device drivers)
-		 */
-		if ( signal_pending( current))
-			return -ERESTARTSYS;
-	}
-	
-	while ( count && skb_queue_len( &self->rx_queue)) {
-
-		skb = skb_dequeue( &self->rx_queue);
-		
-		/*
-		 *  Check if we have previously stopped IrTTP and we know
-		 *  have more free space in our rx_queue. If so tell IrTTP
-		 *  to start delivering frames again before our rx_queue gets
-		 *  empty
-		 */
-		if ( self->rx_flow == FLOW_STOP) {
-			if ( skb_queue_len( &self->rx_queue) < LOW_THRESHOLD) {
-				DEBUG( 4, __FUNCTION__ "(), Starting IrTTP\n");
-				self->rx_flow = FLOW_START;
-				irttp_flow_request( self->tsap, FLOW_START);
-			}
-		}
-
-		/*  
-		 *  Is the request from the user less that the amount in the 
-		 *  current packet?  
-		 */
-		if ( count <  skb->len) {
-			copy_to_user( buffer+len, skb->data, count);
-			len += count;
-			
-			/*
-			 *  Remove copied data from skb and queue
-			 *  it for next read
-			 */
-			skb_pull( skb, count);
-			skb_queue_head( &self->rx_queue, skb);
-			
-			return len;
-		} else {
-			copy_to_user( buffer+len, skb->data, skb->len);
-			count -= skb->len;
-			len += skb->len;
-			
-			dev_kfree_skb( skb);
-		}
-	}
-	return len;
-}
-
-/*
- * Function irobex_write (inode, file, buffer, count)
- *
- *    User process wants to write to device
- *
- */
-static ssize_t irobex_write( struct file *file, const char *buffer, 
-			     size_t count, loff_t *noidea)
-{
-	struct irobex_cb *self;
-	struct sk_buff *skb;
-	int data_len = 0;
-	int len = 0;
-	
-	self = irobex;
-	
-	ASSERT( self != NULL, return -EIO;);
-	ASSERT( self->magic == IROBEX_MAGIC, return -EIO;);
-
-	DEBUG( 4, __FUNCTION__ ": count = %d\n", count);
-	
-	/*
-	 *  If we are not connected then we just give up!
-	 */
-	if ( self->state != OBEX_DATA) {
-		DEBUG( 0, __FUNCTION__ "(): Not connected!\n");
-		
-		return -ENOLINK;
-	} 
-	
-	/* Check if IrTTP is wants us to slow down */
-	if ( self->tx_flow == FLOW_STOP) {
-		DEBUG( 4, __FUNCTION__ 
-		       "(), IrTTP wants us to slow down, going to sleep\n");
-		interruptible_sleep_on( &self->write_wait);
-	}
-	
-	/* Send data to TTP layer possibly as muliple packets */
-	while ( count) {
-		
-		/*
-		 *  Check if request is larger than what fits inside a TTP
-		 *  frame. In that case we must fragment the frame into 
-		 *  multiple TTP frames. IrOBEX should not care about message
-		 *  boundaries.
-		 */
-		if ( count < (self->irlap_data_size - IROBEX_MAX_HEADER))
-			data_len = count;
-		else 
-		        data_len = self->irlap_data_size - IROBEX_MAX_HEADER;
-		
-		DEBUG( 4, __FUNCTION__ "(), data_len=%d, header_len = %d\n", 
-		       data_len, IROBEX_MAX_HEADER);
-		
-		skb = dev_alloc_skb( data_len + IROBEX_MAX_HEADER);
-		if ( skb == NULL) {
-			DEBUG( 0, "irobex - couldn't allocate skbuff!\n");
-			return 0;
-		}
-		
-		skb_reserve( skb, IROBEX_MAX_HEADER);
-		skb_put( skb, data_len);
-		
-		copy_from_user( skb->data, buffer+len, data_len);
-		len += data_len;
-		count -= data_len;
-		
-		DEBUG( 4, __FUNCTION__ "(), skb->len=%d\n", (int) skb->len);
-		ASSERT( skb->len <= (self->irlap_data_size-IROBEX_MAX_HEADER),
-			return len;);
-		
-		irttp_data_request( self->tsap, skb);
-	}
-	return (len);
-}
-
-/*
- * Function irobex_poll (file, wait)
- *
- *    
- *
- */
-static u_int irobex_poll(struct file *file, poll_table *wait)
-{
-	DEBUG( 0, __FUNCTION__ "(), Sorry not implemented yet!\n");
-
-	/* check out /usr/src/pcmcia/modules/ds.c for an example */
-	return 0;
-}
-
-/*
- * Function irobex_fasync (inode, filp, mode)
- *
- *    Implementation for SIGIO
- *
- */
-static int irobex_fasync( int fd, struct file *filp, int on)
-{
-	struct irobex_cb *self;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = irobex;
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IROBEX_MAGIC, return -1;);
-
-	return fasync_helper( fd, filp, on, &self->async);
-}
-
-/*
- * Function irobex_seek (inode, file, buffer, count)
- *
- *    Not implemented yet!
- *
- */
-static loff_t irobex_seek( struct file *file, loff_t off, int whence)
-{
-	DEBUG( 0, __FUNCTION__ "(), Not implemented yet!\n");
-
-	return -ESPIPE;
-}
-
-/*
- * Function irobex_ioctl (inode, filp, cmd, arg)
- *
- *    Drivers IOCTL handler, used for connecting and disconnecting
- *    irobex connections
- *
- */
-static int irobex_ioctl( struct inode *inode, struct file *filp, 
-			 unsigned int cmd, unsigned long arg)
-{
-	struct irobex_cb *self;
-	int err = 0;
-	int size = _IOC_SIZE(cmd);
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = irobex;
-	
-	ASSERT(self != NULL, return -ENOTTY;);
-	ASSERT(self->magic == IROBEX_MAGIC, return -ENOTTY;);
-	
-	if ( _IOC_TYPE(cmd) != IROBEX_IOC_MAGIC) 
-		return -EINVAL;
-	if ( _IOC_NR(cmd) > IROBEX_IOC_MAXNR)
-		return -EINVAL;
-
-	if ( _IOC_DIR(cmd) & _IOC_READ)
-		err = verify_area( VERIFY_WRITE, (void *) arg, size);
-	else if ( _IOC_DIR(cmd) & _IOC_WRITE)
-		err = verify_area( VERIFY_READ, (void *) arg, size);
-	if ( err)
-		return err;
-
-	switch ( cmd) {
-	case IROBEX_IOCSCONNECT:
-		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSCONNECT!\n");
-		return irobex_connect_request( self);		
-		break;
-	case IROBEX_IOCSDISCONNECT:
-		DEBUG( 4, __FUNCTION__ "(): IROBEX_IOCSDISCONNECT!\n");
-		irobex_disconnect_request( self);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-/*
- * Function irobex_dev_open (inode, file)
- *
- *    Device opened by user process
- *
- */
-static int irobex_dev_open( struct inode * inode, struct file *file)
-{
-	struct irobex_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = irobex;
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IROBEX_MAGIC, return -1;);
-
-	if ( self->count++) {
-		DEBUG( 3, "open_irobex: count not zero; actual = %d\n",
-		       self->count);
-		self->count--;
-		return -EBUSY;
-	}
-
-	irobex_register_server( self);
-
-	/* Reset values for this instance */
-	self->state = OBEX_IDLE;
-	self->eof = FALSE;
-	self->daddr = 0;
-	self->dtsap_sel = 0;
-	self->rx_flow = FLOW_START;
-	self->tx_flow = FLOW_START;
-
-	MOD_INC_USE_COUNT;
-	
-	return 0;
-}
-
-static int irobex_dev_close( struct inode *inode, struct file *file)
-{
-	struct irobex_cb *self;
-	struct sk_buff *skb;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = irobex;
-
-	ASSERT( self != NULL, return -ENODEV;);
-	ASSERT( self->magic == IROBEX_MAGIC, return -EBADR;);
-
-	/* Deallocate buffers */
-	while (( skb = skb_dequeue( &self->rx_queue)) != NULL) {
-		DEBUG( 3, "irobex_close: freeing SKB\n");
-		dev_kfree_skb( skb);
-	}
-
-	/* Close TSAP is its still there */
-	if ( self->tsap) {
-		irttp_disconnect_request(self->tsap, NULL, P_NORMAL);
-		irttp_close_tsap( self->tsap);
-		self->tsap = NULL;
-	}
-	self->state = OBEX_IDLE;
-	self->eof = FALSE;
-	self->daddr = 0;
-	self->dtsap_sel = 0;
-	self->rx_flow = FLOW_START;
-	self->tx_flow = FLOW_START;
-
-	/* Remove this filp from the asynchronously notified filp's */
-	irobex_fasync( -1, file, 0);
-
-	self->count--;
-	
-	MOD_DEC_USE_COUNT;
-
-	return 0;
-}
-
-/*
- * Function irobex_discovery_inication (daddr)
- *
- *    Remote device discovered, try query the remote IAS to see which
- *    device it is, and which services it has.
- *
- */
-static void irobex_discovery_indication( DISCOVERY *discovery)
-{
- 	struct irobex_cb *self;
-	
-	DEBUG( 0, __FUNCTION__ "()\n");
-	
-	self = irobex;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-
-	/* Remember address and time if was discovered */
-	self->daddr = discovery->daddr;
-	self->saddr = discovery->saddr;
-	self->time_discovered = jiffies;
-	
-	/* Wake up process if its waiting for device to be discovered */
-	if ( self->state == OBEX_DISCOVER)
-		wake_up_interruptible( &self->write_wait);
-}
-
-static void irobex_disconnect_request( struct irobex_cb *self)
-{
-	if ( self->state != OBEX_DATA)
-		return;
-	
-	irttp_disconnect_request( self->tsap, NULL, P_NORMAL);
-	
-	/* Reset values for this instance */
-	self->state = OBEX_IDLE;
-	self->eof = LM_USER_REQUEST;
-	self->daddr = 0;
-	self->dtsap_sel = 0;
-	self->rx_flow = FLOW_START;
-	self->tx_flow = FLOW_START;
-		
-	wake_up_interruptible( &self->read_wait);
-}
-
-/*
- * Function irobex_disconnect_indication (handle, reason, priv)
- *
- *    Link has been disconnected
- *
- */
-static void irobex_disconnect_indication( void *instance, void *sap, 
-					  LM_REASON reason, 
-					  struct sk_buff *userdata)
-{
-	struct irobex_cb *self;
-	
-	DEBUG( 0, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
-	
-	self = ( struct irobex_cb *) instance;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-	
-	self->state = OBEX_IDLE;
-	self->eof = reason;
-	self->daddr = 0;
-	self->dtsap_sel = 0;
-	self->rx_flow = self->tx_flow = FLOW_START;
-
-	wake_up_interruptible( &self->read_wait);
-	wake_up_interruptible( &self->write_wait);
-	
-	DEBUG( 4, __FUNCTION__ "(), skb_queue_len=%d\n",
-	       skb_queue_len( &irobex->rx_queue));
-	
-	if ( userdata)
-	        dev_kfree_skb( userdata);
-}
-
-int irobex_connect_request(struct irobex_cb *self)
-{
-	int count = 0;
-
-	/* Already connected? */
-	if ( self->state == OBEX_DATA) {
-		DEBUG( 0, __FUNCTION__ "(), already connected!\n");
-		return 0;
-	}
-	
-	/* Timeout after 15 secs. */
-	irobex_start_watchdog_timer( self, 1000);
-	
-	/*
-	 * If we have discovered a remote device we
-	 * check if the discovery is still fresh. If not, we don't
-	 * trust the address.
-	 */
-	if ( self->daddr && ((jiffies - self->time_discovered) > 1000)) {
-		DEBUG( 0, __FUNCTION__ "(), daddr is old <%d>!\n",
-		       jiffies - self->time_discovered);
-		self->daddr = 0;
-	}
-	
-	/* 
-	 * Try to discover remote remote device if it has not been 
-	 * discovered yet. 
-	 */
-	if ( !self->daddr) {
-		self->state = OBEX_DISCOVER;
-		
-		irlmp_discovery_request( 8);
-		
-		/* Wait for discovery to complete */
-		interruptible_sleep_on( &self->write_wait);
-		del_timer( &self->watchdog_timer);
-	}
-	
-	/* Give up if we are unable to discover any remote devices */
-	if ( !self->daddr) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to discover any devices!\n");
-		return -EHOSTUNREACH;
-	}
-	
-	/* Need to find remote destination TSAP selector? */
-	while ( !self->dtsap_sel) {
-		DEBUG( 0, __FUNCTION__ "() : Quering remote IAS!\n");
-		
-		self->state = OBEX_QUERY;
-		
-		/* Timeout after 5 secs. */
-		irobex_start_watchdog_timer( self, 500);
-		iriap_getvaluebyclass_request( 
-			"OBEX", "IrDA:TinyTP:LsapSel",
-			self->saddr, self->daddr,
-			irobex_get_value_confirm,
-			self);
-		
-		interruptible_sleep_on( &self->write_wait);
-		del_timer( &self->watchdog_timer);
-		
-		/* Give up after a few tries */
-		if (( count++ > 2) && !self->dtsap_sel) {
-			DEBUG( 0, __FUNCTION__ 
-			       "(), Unable to query remote LM-IAS!\n");
-			return -ETIMEDOUT;
-		}
-	}
-	self->state = OBEX_CONN;
-	
-	/* Timeout after 5 secs. */
-	irobex_start_watchdog_timer( self, 500);
-	
-	irttp_connect_request( self->tsap, self->dtsap_sel, 
-			       self->saddr, self->daddr, NULL, SAR_DISABLE, 
-			       NULL);
-	
-	/* Go to sleep and wait for connection!  */
-	interruptible_sleep_on( &self->write_wait);
-	del_timer( &self->watchdog_timer);
-	
-	if ( self->state != OBEX_DATA) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), Unable to connect to remote device!\n");
-		return -ETIMEDOUT;
-	}
-	return 0;
-}
-
-/*
- * Function irobex_connect_confirm (instance, sap, qos, userdata)
- *
- *    Connection to peer IrOBEX layer established
- *
- */
-static void irobex_connect_confirm( void *instance, void *sap, 
-				    struct qos_info *qos,
-				    int max_sdu_size, struct sk_buff *userdata)
-{
-	struct irobex_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irobex_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-	ASSERT( qos != NULL, return;);
-
-	DEBUG( 4, __FUNCTION__ "(), IrLAP data size=%d\n", 
-	       qos->data_size.value);
-
-	self->irlap_data_size = qos->data_size.value;
-
-	/*
-	 *  Wake up any blocked process wanting to write. Finally this process
-	 *  can start writing since the connection is now open :-)
-	 */
-	if (self->state == OBEX_CONN) {
-		self->state = OBEX_DATA;
-		wake_up_interruptible( &self->write_wait);
-	}
-	
-	if ( userdata) {
-	        dev_kfree_skb( userdata);
-
-	}
-}
-
-/*
- * Function irobex_connect_response (handle)
- *
- *    Accept incomming connection
- *
- */
-void irobex_connect_response( struct irobex_cb *self)
-{
-	struct sk_buff *skb;
-/* 	__u8 *frame; */
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);	
-
-	self->state = OBEX_DATA;
-
-	skb = dev_alloc_skb( 64);
-	if (skb == NULL) {
-		DEBUG( 0, __FUNCTION__ "() Could not allocate sk_buff!\n");
-		return;
-	}
-
-	/* Reserve space for MUX_CONTROL and LAP header */
-	skb_reserve( skb, TTP_HEADER+LMP_CONTROL_HEADER+LAP_HEADER);
-
-	irttp_connect_response( self->tsap, SAR_DISABLE, skb);
-}
-
-/*
- * Function irobex_connect_indication (handle, skb, priv)
- *
- *    Connection request from a remote device
- *
- */
-void irobex_connect_indication( void *instance, void *sap, 
-				struct qos_info *qos, int max_sdu_size,
-				struct sk_buff *userdata)
-{
-	struct irmanager_event mgr_event;
-	struct irobex_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	self = ( struct irobex_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);	
-	ASSERT( userdata != NULL, return;);
-
-	self->eof = FALSE;
-
-	DEBUG( 4, __FUNCTION__ "(), skb_len = %d\n", 
-	       (int) userdata->len);
-
-	DEBUG( 4, __FUNCTION__ "(), IrLAP data size=%d\n", 
-	       qos->data_size.value);
-
-	ASSERT( qos->data_size.value >= 64, return;);
-
-	self->irlap_data_size = qos->data_size.value;
-
-	/* We just accept the connection */
-	irobex_connect_response( self);
-#if 1
-	mgr_event.event = EVENT_IROBEX_START;
-	sprintf( mgr_event.devname, "%s", self->devname);
-	irmanager_notify( &mgr_event);
-#endif
-	wake_up_interruptible( &self->read_wait);
-
-	if ( userdata) {
-	        dev_kfree_skb( userdata);
-	}
-}
-
-/*
- * Function irobex_data_indication (instance, sap, skb)
- *
- *    This function gets the data that is received on the data channel
- *
- */
-static void irobex_data_indication( void *instance, void *sap, 
-				    struct sk_buff *skb) 
-{
-
-	struct irobex_cb *self;
-	
-	self = ( struct irobex_cb *) instance;
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-	ASSERT( skb != NULL, return;);
-	
-	DEBUG( 4, __FUNCTION__ "(), len=%d\n", (int) skb->len);
-	
-	skb_queue_tail( &self->rx_queue, skb);
-	
-	/*
-	 *  Check if queues are beginning to get filled, and inform 
-	 *  IrTTP to slow down if that is the case
-	 */
-	if ( skb_queue_len( &self->rx_queue) > HIGH_THRESHOLD) {
-		DEBUG( 0, __FUNCTION__ 
-		       "(), rx_queue is full, telling IrTTP to slow down\n");
-		self->rx_flow = FLOW_STOP;
-		irttp_flow_request( self->tsap, FLOW_STOP);
-	}
-
-	/*
-	 *  Wake up process blocked on read or select
-	 */
-	wake_up_interruptible( &self->read_wait);
-
-	/* Send signal to asynchronous readers */
-	if ( self->async)
-		kill_fasync( self->async, SIGIO);
-}
-
-/*
- * Function irobex_flow_indication (instance, sap, cmd)
- *
- *    
- *
- */
-static void irobex_flow_indication( void *instance, void *sap, 
-				    LOCAL_FLOW flow) 
-{
-	struct irobex_cb *self;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-	
-	self = ( struct irobex_cb *) instance;
-	
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-	
-	switch ( flow) {
-	case FLOW_STOP:
-		DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to slow down\n");
-		self->tx_flow = flow;
-		break;
-	case FLOW_START:
-		self->tx_flow = flow;
-		DEBUG( 0, __FUNCTION__ "(), IrTTP wants us to start again\n");
-		wake_up_interruptible( &self->write_wait);
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), Unknown flow command!\n");
-	}
-}
-
-/*
- * Function irobex_get_value_confirm (obj_id, value)
- *
- *    Got results from previous GetValueByClass request
- *
- */
-static void irobex_get_value_confirm( __u16 obj_id, struct ias_value *value, 
-				      void *priv)
-{
-	struct irobex_cb *self;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( priv != NULL, return;);
-	self = ( struct irobex_cb *) priv;
-	
-	if ( !self || self->magic != IROBEX_MAGIC) {
-		DEBUG( 0, __FUNCTION__ "(), bad magic!\n");
-		return;
-	}
-
-	/* Check if request succeeded */
-	if ( !value) {
-		DEBUG( 0, __FUNCTION__ "(), got NULL value!\n");
-
-		return;
-	}
-
-	switch ( value->type) {
-	case IAS_INTEGER:
-		DEBUG( 4, __FUNCTION__ "() int=%d\n", value->t.integer);
-		
-		if ( value->t.integer != -1) {
-			self->dtsap_sel = value->t.integer;
-
-			/*
-			 *  Got the remote TSAP, so wake up any processes
-			 *  blocking on write. We don't do the connect 
-			 *  ourselves since we must make sure there is a 
-			 *  process that wants to make a connection, so we
-			 *  just let that process do the connect itself
-			 */
-			if ( self->state == OBEX_QUERY)
-				wake_up_interruptible( &self->write_wait);
-		} else 
-			self->dtsap_sel = 0;
-		break;
-	case IAS_STRING:
-		DEBUG( 0, __FUNCTION__ "(), got string %s\n", value->t.string);
-		break;
-	case IAS_OCT_SEQ:
-		DEBUG( 0, __FUNCTION__ "(), OCT_SEQ not implemented\n");
-		break;
-	case IAS_MISSING:
-		DEBUG( 0, __FUNCTION__ "(), MISSING not implemented\n");
-		break;
-	default:
-		DEBUG( 0, __FUNCTION__ "(), unknown type!\n");
-		break;
-	}
-}
-
-/*
- * Function irobex_provider_confirm (dlsap)
- *
- *    IrOBEX provider is discovered. We can now establish connections
- *    TODO: This function is currently not used!
- */
-void irobex_provider_confirm( struct irobex_cb *self, __u8 dlsap) 
-{
-	/* struct irobex_cb *self = irobex; */
-	struct notify_t notify;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-
-	notify.data_indication = irobex_data_indication;
-	notify.connect_confirm = irobex_connect_confirm;
-	notify.connect_indication = irobex_connect_indication;
-	notify.flow_indication = irobex_flow_indication;
-	notify.disconnect_indication = irobex_disconnect_indication;
-	notify.instance = self;
-	
-	/* Create TSAP's */
-	self->tsap = irttp_open_tsap( LSAP_ANY, DEFAULT_INITIAL_CREDIT,
-				      &notify);
-	
-/* 	DEBUG( 0, "OBEX allocated TSAP%d for data\n", self->handle); */
-	
-	/* irlan_do_event( IAS_PROVIDER_AVAIL, NULL, &frame); */
-}
-
-/*
- * Function irobex_register_server(void)
- *
- *    Register server support so we can accept incomming connections. We
- *    must register both a TSAP for control and data
- * 
- */
-static void irobex_register_server( struct irobex_cb *self)
-{
-	struct notify_t notify;
-	struct ias_object *obj;
-
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-
-	irda_notify_init( &notify);
-
-	notify.connect_confirm       = irobex_connect_confirm;
-	notify.connect_indication    = irobex_connect_indication;
-	notify.disconnect_indication = irobex_disconnect_indication;
-	notify.data_indication       = irobex_data_indication;
-	notify.flow_indication       = irobex_flow_indication;
-	notify.instance = self;
-	strcpy( notify.name, "IrOBEX");
-
-	self->tsap = irttp_open_tsap( TSAP_IROBEX, DEFAULT_INITIAL_CREDIT,
-				      &notify);	
-	if ( self->tsap == NULL) {
-		DEBUG( 0, __FUNCTION__ "(), Unable to allocate TSAP!\n");
-		return;
-	}
-
-	/* 
-	 *  Register with LM-IAS
-	 */
-	obj = irias_new_object( "OBEX", 0x42343);
-	irias_add_integer_attrib( obj, "IrDA:TinyTP:LsapSel", TSAP_IROBEX);
-	irias_insert_object( obj);
-}
-
-void irobex_watchdog_timer_expired( unsigned long data)
-{
-	struct irobex_cb *self = ( struct irobex_cb *) data;
-	
-	DEBUG( 4, __FUNCTION__ "()\n");
-
-	ASSERT( self != NULL, return;);
-	ASSERT( self->magic == IROBEX_MAGIC, return;);
-
-	switch (self->state) {
-	case OBEX_CONN:      /* FALLTROUGH */
-	case OBEX_DISCOVER:  /* FALLTROUGH */
-	case OBEX_QUERY:     /* FALLTROUGH */
-		wake_up_interruptible( &self->write_wait);
-		break;
-	default:
-		break;
-	}
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- * Function irobex_proc_read (buf, start, offset, len, unused)
- *
- *    Give some info to the /proc file system
- */
-static int irobex_proc_read( char *buf, char **start, off_t offset, 
-			     int len, int unused)
-{
- 	struct irobex_cb *self;
-
-	self = irobex;
-
-	ASSERT( self != NULL, return -1;);
-	ASSERT( self->magic == IROBEX_MAGIC, return -1;);
-
-	len = 0;
-	
-	len += sprintf( buf+len, "ifname: %s ",self->devname);
-	len += sprintf( buf+len, "state: %s ", irobex_state[ self->state]);
-	len += sprintf( buf+len, "EOF: %s\n", self->eof ? "TRUE": "FALSE");
-	
-	return len;
-}
-
-#endif /* CONFIG_PROC_FS */
-
-#ifdef MODULE
-
-MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
-MODULE_DESCRIPTION("The Linux IrOBEX module"); 
-
-/*
- * Function init_module (void)
- *
- *    Initialize the IrOBEX module, this function is called by the
- *    modprobe(1) program.
- */
-int init_module(void) 
-{
-	irobex_init();
-	
-	return 0;
-}
-
-/*
- * Function cleanup_module (void)
- *
- *    Remove the IrOBEX module, this function is called by the rmmod(1)
- *    program
- */
-void cleanup_module(void) 
-{
-	/* 
-	 *  No need to check MOD_IN_USE, as sys_delete_module() checks. 
-	 */
-	
-	/* Free some memory */
-	irobex_cleanup();	
-}
-
-#endif /* MODULE */
-
-
-
-

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