diff -urpN linux-2.2.18-23/drivers/net/irda/actisys.c linux/drivers/net/irda/actisys.c --- linux-2.2.18-23/drivers/net/irda/actisys.c Thu May 4 02:16:41 2000 +++ linux/drivers/net/irda/actisys.c Tue Nov 28 19:53:20 2000 @@ -42,7 +42,6 @@ #include #include -#include #include /* diff -urpN linux-2.2.18-23/drivers/net/irda/esi.c linux/drivers/net/irda/esi.c --- linux-2.2.18-23/drivers/net/irda/esi.c Thu May 4 02:16:41 2000 +++ linux/drivers/net/irda/esi.c Tue Nov 28 19:53:20 2000 @@ -38,7 +38,6 @@ #include #include -#include #include static void esi_open(dongle_t *self, struct qos_info *qos); diff -urpN linux-2.2.18-23/drivers/net/irda/girbil.c linux/drivers/net/irda/girbil.c --- linux-2.2.18-23/drivers/net/irda/girbil.c Wed Jun 7 23:26:43 2000 +++ linux/drivers/net/irda/girbil.c Tue Nov 28 19:53:20 2000 @@ -29,7 +29,6 @@ #include #include -#include #include #include diff -urpN linux-2.2.18-23/drivers/net/irda/irport.c linux/drivers/net/irda/irport.c --- linux-2.2.18-23/drivers/net/irda/irport.c Wed Jun 7 23:26:43 2000 +++ linux/drivers/net/irda/irport.c Tue Nov 28 19:57:39 2000 @@ -55,7 +55,6 @@ #include #include -#include #include #include @@ -625,8 +624,16 @@ int irport_hard_xmit(struct sk_buff *skb } /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + irda_task_execute(self, __irport_change_speed, + irport_change_speed_complete, + NULL, (void *) speed); + return 0; + } else + self->new_speed = speed; + } spin_lock_irqsave(&self->lock, flags); @@ -948,7 +955,7 @@ static int irport_net_ioctl(struct devic * speed, so we still must allow for speed change within * interrupt context. */ - if (!in_interrupt() && !capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; irda_task_execute(self, __irport_change_speed, NULL, NULL, (void *) irq->ifr_baudrate); @@ -1006,7 +1013,9 @@ static struct net_device_stats *irport_n #ifdef MODULE MODULE_PARM(io, "1-4i"); +MODULE_PARM_DESC(io, "Base I/O adresses"); MODULE_PARM(irq, "1-4i"); +MODULE_PARM_DESC(irq, "IRQ lines"); MODULE_AUTHOR("Dag Brattli "); MODULE_DESCRIPTION("Half duplex serial driver for IrDA SIR mode"); diff -urpN linux-2.2.18-23/drivers/net/irda/irtty.c linux/drivers/net/irda/irtty.c --- linux-2.2.18-23/drivers/net/irda/irtty.c Wed Jun 7 23:26:43 2000 +++ linux/drivers/net/irda/irtty.c Tue Nov 28 21:13:20 2000 @@ -177,7 +177,7 @@ static int irtty_open(struct tty_struct MINOR(tty->device) - tty->driver.minor_start + tty->driver.name_base); - hashbin_insert(irtty, (queue_t *) self, (int) self, NULL); + hashbin_insert(irtty, (irda_queue_t *) self, (int) self, NULL); if (tty->driver.flush_buffer) tty->driver.flush_buffer(tty); @@ -648,8 +648,16 @@ static int irtty_hard_xmit(struct sk_buf return -EBUSY; /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + irda_task_execute(self, irtty_change_speed, + irtty_change_speed_complete, + NULL, (void *) speed); + return 0; + } else + self->new_speed = speed; + } /* Init tx buffer*/ self->tx_buff.data = self->tx_buff.head; @@ -966,7 +974,7 @@ static int irtty_net_ioctl(struct device ASSERT(self != NULL, return -1;); ASSERT(self->magic == IRTTY_MAGIC, return -1;); - IRDA_DEBUG(2, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); + IRDA_DEBUG(3, __FUNCTION__ "(), %s, (cmd=0x%X)\n", dev->name, cmd); /* Disable interrupts & save flags */ save_flags(flags); @@ -979,7 +987,7 @@ static int irtty_net_ioctl(struct device * speed, so we still must allow for speed change within * interrupt context. */ - if (!in_interrupt() && !capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; irda_task_execute(self, irtty_change_speed, NULL, NULL, (void *) irq->ifr_baudrate); @@ -1046,6 +1054,7 @@ MODULE_AUTHOR("Dag Brattli #include -#include #include #define MIN_DELAY 25 /* 15 us, but wait a little more to be sure */ diff -urpN linux-2.2.18-23/drivers/net/irda/nsc-ircc.c linux/drivers/net/irda/nsc-ircc.c --- linux-2.2.18-23/drivers/net/irda/nsc-ircc.c Wed Jun 7 23:26:43 2000 +++ linux/drivers/net/irda/nsc-ircc.c Tue Nov 28 19:57:18 2000 @@ -64,7 +64,6 @@ #include #include -#include #include #include @@ -719,9 +718,12 @@ static int nsc_ircc_setup(chipio_t *info switch_bank(iobase, BANK0); /* Set FIFO threshold to TX17, RX16, reset and enable FIFO's */ - switch_bank(iobase, BANK0); + switch_bank(iobase, BANK0); outb(FCR_RXTH|FCR_TXTH|FCR_TXSR|FCR_RXSR|FCR_FIFO_EN, iobase+FCR); - + + outb(0x03, iobase+LCR); /* 8 bit word length */ + outb(MCR_SIR, iobase+MCR); /* Start at SIR-mode, also clears LSR*/ + /* Set FIFO size to 32 */ switch_bank(iobase, BANK2); outb(EXCR2_RFSIZ|EXCR2_TFSIZ, iobase+EXCR2); @@ -734,7 +736,7 @@ static int nsc_ircc_setup(chipio_t *info switch_bank(iobase, BANK6); outb(0x20, iobase+0); /* Set 32 bits FIR CRC */ outb(0x0a, iobase+1); /* Set MIR pulse width */ - outb(0x0d, iobase+2); /* Set SIR pulse width */ + outb(0x0d, iobase+2); /* Set SIR pulse width to 1.6us */ outb(0x2a, iobase+4); /* Set beginning frag, and preamble length */ MESSAGE("%s, driver loaded (Dag Brattli)\n", driver_name); @@ -815,8 +817,6 @@ static void nsc_ircc_init_dongle_interfa dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ - IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", - dongle_types[dongle_id]); break; case 0x05: /* Reserved, but this is what the Thinkpad reports */ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", @@ -903,8 +903,7 @@ static void nsc_ircc_change_dongle_speed dongle_types[dongle_id]); break; case 0x04: /* Sharp RY5HD01 */ - IRDA_DEBUG(0, __FUNCTION__ "(), %s not supported yet\n", - dongle_types[dongle_id]); + break; case 0x05: /* Reserved */ IRDA_DEBUG(0, __FUNCTION__ "(), %s not defined by irda yet\n", dongle_types[dongle_id]); @@ -1089,9 +1088,15 @@ static int nsc_ircc_hard_xmit_sir(struct return -EBUSY; /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; - + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + nsc_ircc_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } + spin_lock_irqsave(&self->lock, flags); /* Save current bank */ @@ -1135,8 +1140,14 @@ static int nsc_ircc_hard_xmit_fir(struct return -EBUSY; /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + nsc_ircc_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } spin_lock_irqsave(&self->lock, flags); @@ -1975,7 +1986,7 @@ static int nsc_ircc_net_ioctl(struct dev * speed, so we still must allow for speed change within * interrupt context. */ - if (!in_interrupt() && !capable(CAP_NET_ADMIN)) { + if (!capable(CAP_NET_ADMIN)) { IRDA_DEBUG(0, __FUNCTION__ "(), not capable sysadm\n"); return -EPERM; } @@ -2076,10 +2087,15 @@ MODULE_AUTHOR("Dag Brattli #include -#include #include /* diff -urpN linux-2.2.18-23/drivers/net/irda/smc-ircc.c linux/drivers/net/irda/smc-ircc.c --- linux-2.2.18-23/drivers/net/irda/smc-ircc.c Thu May 4 02:16:41 2000 +++ linux/drivers/net/irda/smc-ircc.c Tue Nov 28 19:53:20 2000 @@ -56,7 +56,6 @@ #include #include -#include #include #include @@ -589,6 +588,8 @@ static void ircc_change_speed(void *priv register_bank(iobase, 0); outb(fast, iobase+IRCC_LCR_A); + + dev->tbusy = 0; } /* @@ -615,8 +616,14 @@ static int ircc_hard_xmit(struct sk_buff spin_lock_irqsave(&self->lock, flags); /* Check if we need to change the speed after this frame */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + ircc_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } /* Lock transmit buffer */ if (irda_lock((void *) &dev->tbusy) == FALSE) @@ -821,7 +828,7 @@ static void ircc_dma_receive_complete(st else len -= 4; - if ((len < 2) && (len > 2050)) { + if ((len < 2) || (len > 2050)) { WARNING(__FUNCTION__ "(), bogus len=%d\n", len); return; } @@ -1065,7 +1072,9 @@ static int ircc_apmproc(apm_event_t even MODULE_AUTHOR("Thomas Davis "); MODULE_DESCRIPTION("SMC IrCC controller driver"); MODULE_PARM(ircc_dma, "1i"); +MODULE_PARM_DESC(ircc_dma, "DMA channel"); MODULE_PARM(ircc_irq, "1i"); +MODULE_PARM_DESC(ircc_irq, "IRQ line"); int init_module(void) { diff -urpN linux-2.2.18-23/drivers/net/irda/tekram.c linux/drivers/net/irda/tekram.c --- linux-2.2.18-23/drivers/net/irda/tekram.c Thu May 4 02:16:41 2000 +++ linux/drivers/net/irda/tekram.c Tue Nov 28 19:53:20 2000 @@ -29,7 +29,6 @@ #include #include -#include #include #include diff -urpN linux-2.2.18-23/drivers/net/irda/toshoboe.c linux/drivers/net/irda/toshoboe.c --- linux-2.2.18-23/drivers/net/irda/toshoboe.c Thu Nov 23 14:47:52 2000 +++ linux/drivers/net/irda/toshoboe.c Tue Nov 28 19:56:32 2000 @@ -73,7 +73,6 @@ static char *rcsid = "$Id: toshoboe.c,v #include #include -#include #include #include @@ -274,8 +273,14 @@ toshoboe_hard_xmit (struct sk_buff *skb, ); /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + toshoboe_setbaud(self, speed); + return 0; + } else + self->new_speed = speed; + } if (self->stopped) { dev_kfree_skb(skb); @@ -617,7 +622,7 @@ static int toshoboe_net_ioctl(struct dev * speed, so we still must allow for speed change within * interrupt context. */ - if (!in_interrupt() && !capable(CAP_NET_ADMIN)) + if (!capable(CAP_NET_ADMIN)) return -EPERM; /* toshoboe_setbaud(self, irq->ifr_baudrate); */ /* Just change speed once - inserted by Paul Bristow */ @@ -642,7 +647,10 @@ static int toshoboe_net_ioctl(struct dev #ifdef MODULE +MODULE_DESCRIPTION("Toshiba OBOE IrDA Device Driver"); +MODULE_AUTHOR("James McKenzie "); MODULE_PARM (max_baud, "i"); +MODULE_PARM_DESC(max_baus, "Maximum baud rate"); static int toshoboe_close (struct toshoboe_cb *self) diff -urpN linux-2.2.18-23/drivers/net/irda/w83977af_ir.c linux/drivers/net/irda/w83977af_ir.c --- linux-2.2.18-23/drivers/net/irda/w83977af_ir.c Wed Jun 7 23:26:43 2000 +++ linux/drivers/net/irda/w83977af_ir.c Tue Nov 28 19:53:20 2000 @@ -56,7 +56,6 @@ #include #include -#include #include #include #include @@ -519,8 +518,14 @@ int w83977af_hard_xmit(struct sk_buff *s return -EBUSY; /* Check if we need to change the speed */ - if ((speed = irda_get_speed(skb)) != self->io.speed) - self->new_speed = speed; + if ((speed = irda_get_speed(skb)) != self->io.speed) { + /* Check for empty frame */ + if (!skb->len) { + w83977af_change_speed(self, speed); + return 0; + } else + self->new_speed = speed; + } /* Save current set */ set = inb(iobase+SSR); @@ -1386,9 +1391,11 @@ MODULE_AUTHOR("Dag Brattli */ +struct lsap_cb; /* in */ +struct iriap_cb; /* in */ +struct ias_value; /* in */ +struct discovery_t; /* in */ + /* IrDA Socket */ -struct tsap_cb; struct irda_sock { __u32 saddr; /* my local address */ __u32 daddr; /* peer address */ @@ -139,12 +145,16 @@ struct irda_sock { struct iriap_cb *iriap; /* Used to query remote IAS */ struct ias_value *ias_result; /* Used by getsockopt(IRLMP_IAS_QUERY) */ + hashbin_t *cachelog; /* Result of discovery query */ + struct discovery_t *cachediscovery; /* Result of selective discovery query */ + int nslots; /* Number of slots to use for discovery */ int errno; /* status of the IAS query */ struct sock *sk; - struct wait_queue *ias_wait; /* Wait for LM-IAS answer */ + struct wait_queue *query_wait; /* Wait for LM-IAS answer */ + struct timer_list watchdog; /* Timeout for discovery */ LOCAL_FLOW tx_flow; LOCAL_FLOW rx_flow; @@ -166,12 +176,14 @@ typedef union { * (must not exceed 48 bytes, check with struct sk_buff) */ struct irda_skb_cb { - magic_t magic; /* Be sure that we can trust the information */ - __u32 speed; /* The Speed this frame should be sent with */ - __u16 mtt; /* Minimum turn around time */ - int xbofs; /* Number of xbofs required, used by SIR mode */ - __u8 line; /* Used by IrCOMM in IrLPT mode */ - void (*destructor)(struct sk_buff *skb); /* Used for flow control */ + magic_t magic; /* Be sure that we can trust the information */ + __u32 speed; /* The Speed this frame should be sent with */ + __u16 mtt; /* Minimum turn around time */ + __u16 xbofs; /* Number of xbofs required, used by SIR mode */ + void *context; /* May be used by drivers */ + void (*destructor)(struct sk_buff *skb); /* Used for flow control */ + __u16 xbofs_delay; /* Number of xbofs used for generating the mtt */ + __u8 line; /* Used by IrCOMM in IrLPT mode */ }; /* Misc status information */ @@ -232,10 +244,41 @@ typedef struct { void (*disconnect_indication)(void *instance, void *sap, LM_REASON reason, struct sk_buff *); void (*flow_indication)(void *instance, void *sap, LOCAL_FLOW flow); + void (*status_indication)(void *instance, + LINK_STATUS link, LOCK_STATUS lock); void *instance; /* Layer instance pointer */ char name[16]; /* Name of layer */ } notify_t; #define NOTIFY_MAX_NAME 16 +extern void irda_notify_init(notify_t *notify); + +static inline int irda_lock(int *lock) +{ + if (test_and_set_bit( 0, (void *) lock)) { + IRDA_DEBUG(2, __FUNCTION__ + "(), Trying to lock, already locked variable!\n"); + return FALSE; + } + return TRUE; +} + +static inline int irda_unlock(int *lock) +{ + if (!test_and_clear_bit(0, (void *) lock)) { + IRDA_DEBUG(2, __FUNCTION__ + "(), Trying to unlock already unlocked variable!\n"); + return FALSE; + } + return TRUE; +} + + +/* Not in 2.2 yet */ +static inline struct sk_buff *skb_get(struct sk_buff *skb) +{ + atomic_inc(&skb->users); + return skb; +} #endif /* NET_IRDA_H */ diff -urpN linux-2.2.18-23/include/net/irda/irda_device.h linux/include/net/irda/irda_device.h --- linux-2.2.18-23/include/net/irda/irda_device.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irda_device.h Tue Nov 28 20:34:35 2000 @@ -79,7 +79,7 @@ struct irda_task; typedef int (*TASK_CALLBACK) (struct irda_task *task); struct irda_task { - queue_t q; + irda_queue_t q; magic_t magic; TASK_STATE state; @@ -111,7 +111,7 @@ typedef struct { /* Dongle registration info */ struct dongle_reg { - queue_t q; /* Must be first */ + irda_queue_t q; /* Must be first */ IRDA_DONGLE type; void (*open)(dongle_t *dongle, struct qos_info *qos); diff -urpN linux-2.2.18-23/include/net/irda/iriap.h linux/include/net/irda/iriap.h --- linux-2.2.18-23/include/net/irda/iriap.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/iriap.h Tue Nov 28 20:35:45 2000 @@ -58,7 +58,7 @@ typedef void (*CONFIRM_CALLBACK)(int res struct ias_value *value, void *priv); struct iriap_cb { - queue_t q; /* Must be first */ + irda_queue_t q; /* Must be first */ magic_t magic; /* Magic cookie */ int mode; /* Client or server */ diff -urpN linux-2.2.18-23/include/net/irda/irias_object.h linux/include/net/irda/irias_object.h --- linux-2.2.18-23/include/net/irda/irias_object.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irias_object.h Tue Nov 28 20:35:45 2000 @@ -34,11 +34,15 @@ #define IAS_OCT_SEQ 2 #define IAS_STRING 3 +/* Object ownership of attributes (user or kernel) */ +#define IAS_KERNEL_ATTR 0 +#define IAS_USER_ATTR 1 + /* * LM-IAS Object */ struct ias_object { - queue_t q; /* Must be first! */ + irda_queue_t q; /* Must be first! */ magic_t magic; char *name; @@ -51,6 +55,7 @@ struct ias_object { */ struct ias_value { __u8 type; /* Value description */ + __u8 owner; /* Managed from user/kernel space */ int charset; /* Only used by string type */ int len; @@ -66,7 +71,7 @@ struct ias_value { * Attributes used by LM-IAS objects */ struct ias_attrib { - queue_t q; /* Must be first! */ + irda_queue_t q; /* Must be first! */ int magic; char *name; /* Attribute name */ @@ -78,12 +83,15 @@ char *strdup(char *str); struct ias_object *irias_new_object(char *name, int id); void irias_insert_object(struct ias_object *obj); int irias_delete_object(struct ias_object *obj); +int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib); void __irias_delete_object(struct ias_object *obj); -void irias_add_integer_attrib(struct ias_object *obj, char *name, int value); -void irias_add_string_attrib(struct ias_object *obj, char *name, char *value); +void irias_add_integer_attrib(struct ias_object *obj, char *name, int value, + int user); +void irias_add_string_attrib(struct ias_object *obj, char *name, char *value, + int user); void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets, - int len); + int len, int user); int irias_object_change_attribute(char *obj_name, char *attrib_name, struct ias_value *new_value); struct ias_object *irias_find_object(char *name); diff -urpN linux-2.2.18-23/include/net/irda/irlan_client.h linux/include/net/irda/irlan_client.h --- linux-2.2.18-23/include/net/irda/irlan_client.h Sun Apr 25 02:50:05 1999 +++ linux/include/net/irda/irlan_client.h Tue Nov 28 20:36:00 2000 @@ -34,7 +34,7 @@ #include void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout); -void irlan_client_discovery_indication(discovery_t *); +void irlan_client_discovery_indication(discovery_t *, void *); void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr); void irlan_client_open_ctrl_tsap( struct irlan_cb *self); diff -urpN linux-2.2.18-23/include/net/irda/irlan_common.h linux/include/net/irda/irlan_common.h --- linux-2.2.18-23/include/net/irda/irlan_common.h Wed Jun 7 23:26:44 2000 +++ linux/include/net/irda/irlan_common.h Tue Nov 28 20:36:00 2000 @@ -161,7 +161,7 @@ struct irlan_provider_cb { * IrLAN control block */ struct irlan_cb { - queue_t q; /* Must be first */ + irda_queue_t q; /* Must be first */ int magic; char ifname[9]; diff -urpN linux-2.2.18-23/include/net/irda/irlap.h linux/include/net/irda/irlap.h --- linux-2.2.18-23/include/net/irda/irlap.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irlap.h Tue Nov 28 20:34:35 2000 @@ -81,7 +81,7 @@ #define irda_incomp (*self->decompressor.cp->incomp) struct irda_compressor { - queue_t q; + irda_queue_t q; struct compressor *cp; void *state; /* Not used by IrDA */ @@ -90,7 +90,7 @@ struct irda_compressor { /* Main structure of IrLAP */ struct irlap_cb { - queue_t q; /* Must be first */ + irda_queue_t q; /* Must be first */ magic_t magic; struct device *netdev; @@ -214,7 +214,7 @@ void irlap_unitdata_indication(struct ir void irlap_disconnect_request(struct irlap_cb *); void irlap_disconnect_indication(struct irlap_cb *, LAP_REASON reason); -void irlap_status_indication(int quality_of_link); +void irlap_status_indication(struct irlap_cb *, int quality_of_link); void irlap_test_request(__u8 *info, int len); diff -urpN linux-2.2.18-23/include/net/irda/irlap_frame.h linux/include/net/irda/irlap_frame.h --- linux-2.2.18-23/include/net/irda/irlap_frame.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irlap_frame.h Tue Nov 28 20:34:35 2000 @@ -110,6 +110,7 @@ struct snrm_frame { __u8 ncaddr; } PACK; +void irlap_queue_xmit(struct irlap_cb *self, struct sk_buff *skb); void irlap_send_discovery_xid_frame(struct irlap_cb *, int S, __u8 s, __u8 command, discovery_t *discovery); void irlap_send_snrm_frame(struct irlap_cb *, struct qos_info *); diff -urpN linux-2.2.18-23/include/net/irda/irlmp.h linux/include/net/irda/irlmp.h --- linux-2.2.18-23/include/net/irda/irlmp.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irlmp.h Tue Nov 28 20:34:36 2000 @@ -71,22 +71,23 @@ typedef enum { S_END, } SERVICE; -typedef void (*DISCOVERY_CALLBACK1) (discovery_t *); -typedef void (*DISCOVERY_CALLBACK2) (hashbin_t *); +typedef void (*DISCOVERY_CALLBACK1) (discovery_t *, void *); +typedef void (*DISCOVERY_CALLBACK2) (hashbin_t *, void *); typedef struct { - queue_t queue; /* Must be first */ + irda_queue_t queue; /* Must be first */ __u16 hints; /* Hint bits */ } irlmp_service_t; typedef struct { - queue_t queue; /* Must be first */ + irda_queue_t queue; /* Must be first */ __u16 hint_mask; - DISCOVERY_CALLBACK1 callback1; - DISCOVERY_CALLBACK2 callback2; + DISCOVERY_CALLBACK1 disco_callback; /* Selective discovery */ + DISCOVERY_CALLBACK1 expir_callback; /* Selective expiration */ + void *priv; /* Used to identify client */ } irlmp_client_t; struct lap_cb; /* Forward decl. */ @@ -95,7 +96,7 @@ struct lap_cb; /* Forward decl. */ * Information about each logical LSAP connection */ struct lsap_cb { - queue_t queue; /* Must be first */ + irda_queue_t queue; /* Must be first */ magic_t magic; int connected; @@ -121,7 +122,7 @@ struct lsap_cb { * Information about each registred IrLAP layer */ struct lap_cb { - queue_t queue; /* Must be first */ + irda_queue_t queue; /* Must be first */ magic_t magic; int reason; /* LAP disconnect reason */ @@ -174,10 +175,10 @@ struct irlmp_cb { hashbin_t *clients; hashbin_t *services; - hashbin_t *cachelog; - int running; + hashbin_t *cachelog; /* Current discovery log */ + spinlock_t log_lock; /* discovery log spinlock */ - spinlock_t lock; + int running; __u16_host_order hints; /* Hint bits */ }; @@ -191,11 +192,12 @@ void irlmp_close_lsap( struct lsap_cb *s __u16 irlmp_service_to_hint(int service); __u32 irlmp_register_service(__u16 hints); int irlmp_unregister_service(__u32 handle); -__u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 callback1, - DISCOVERY_CALLBACK2 callback2); +__u32 irlmp_register_client(__u16 hint_mask, DISCOVERY_CALLBACK1 disco_clb, + DISCOVERY_CALLBACK1 expir_clb, void *priv); int irlmp_unregister_client(__u32 handle); int irlmp_update_client(__u32 handle, __u16 hint_mask, - DISCOVERY_CALLBACK1, DISCOVERY_CALLBACK2); + DISCOVERY_CALLBACK1 disco_clb, + DISCOVERY_CALLBACK1 expir_clb, void *priv); void irlmp_register_link(struct irlap_cb *, __u32 saddr, notify_t *); void irlmp_unregister_link(__u32 saddr); @@ -214,8 +216,10 @@ int irlmp_disconnect_request(struct lsa void irlmp_discovery_confirm(hashbin_t *discovery_log); void irlmp_discovery_request(int nslots); +struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask); void irlmp_do_discovery(int nslots); discovery_t *irlmp_get_discovery_response(void); +void irlmp_discovery_expiry(discovery_t *expiry); int irlmp_data_request(struct lsap_cb *, struct sk_buff *); void irlmp_data_indication(struct lsap_cb *, struct sk_buff *); @@ -229,7 +233,7 @@ void irlmp_connless_data_indication(stru #endif /* CONFIG_IRDA_ULTRA */ void irlmp_status_request(void); -void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock); +void irlmp_status_indication(struct lap_cb *, LINK_STATUS link, LOCK_STATUS lock); int irlmp_slsap_inuse(__u8 slsap); __u8 irlmp_find_free_slsap(void); @@ -248,9 +252,12 @@ static inline hashbin_t *irlmp_get_cache static inline int irlmp_get_lap_tx_queue_len(struct lsap_cb *self) { - ASSERT(self != NULL, return 0;); - ASSERT(self->lap != NULL, return 0;); - ASSERT(self->lap->irlap != NULL, return 0;); + if (self == NULL) + return 0; + if (self->lap == NULL) + return 0; + if (self->lap->irlap == NULL) + return 0; return IRLAP_GET_TX_QUEUE_LEN(self->lap->irlap); } diff -urpN linux-2.2.18-23/include/net/irda/irmod.h linux/include/net/irda/irmod.h --- linux-2.2.18-23/include/net/irda/irmod.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irmod.h Thu Jan 1 01:00:00 1970 @@ -1,140 +0,0 @@ -/********************************************************************* - * - * Filename: irmod.h - * Version: 0.3 - * Description: IrDA module and utilities functions - * Status: Experimental. - * Author: Dag Brattli - * Created at: Mon Dec 15 13:58:52 1997 - * Modified at: Sun Oct 31 20:01:17 1999 - * Modified by: Dag Brattli - * - * Copyright (c) 1998-1999 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 charg. - * - ********************************************************************/ - -#ifndef IRMOD_H -#define IRMOD_H - -#include -#include - -#include - -#define IRMGR_IOC_MAGIC 'm' -#define IRMGR_IOCTNPC _IO(IRMGR_IOC_MAGIC, 1) -#define IRMGR_IOC_MAXNR 1 - -/* - * Events that we pass to the user space manager - */ -typedef enum { - EVENT_DEVICE_DISCOVERED = 0, - EVENT_REQUEST_MODULE, - EVENT_IRLAN_START, - EVENT_IRLAN_STOP, - EVENT_IRLPT_START, /* Obsolete */ - EVENT_IRLPT_STOP, /* Obsolete */ - EVENT_IROBEX_START, /* Obsolete */ - EVENT_IROBEX_STOP, /* Obsolete */ - EVENT_IRDA_STOP, - EVENT_NEED_PROCESS_CONTEXT, -} IRMGR_EVENT; - -/* - * Event information passed to the IrManager daemon process - */ -struct irmanager_event { - IRMGR_EVENT event; - char devname[10]; - char info[32]; - int service; - __u32 saddr; - __u32 daddr; -}; - -typedef void (*TODO_CALLBACK)( void *self, __u32 param); - -/* - * Same as irmanager_event but this one can be queued and inclueds some - * addtional information - */ -struct irda_event { - queue_t q; /* Must be first */ - - struct irmanager_event event; -}; - -/* - * Funtions with needs to be called with a process context - */ -struct irda_todo { - queue_t q; /* Must be first */ - - void *self; - TODO_CALLBACK callback; - __u32 param; -}; - -/* - * Main structure for the IrDA device (not much here :-) - */ -struct irda_cb { - struct miscdevice dev; - struct wait_queue *wait_queue; - - int in_use; - - queue_t *event_queue; /* Events queued for the irmanager */ - queue_t *todo_queue; /* Todo list */ -}; - -int irmod_init_module(void); -void irmod_cleanup_module(void); - -/* - * Function irda_lock (lock) - * - * Lock variable. Returns false if the lock is already set. - * - */ -static inline int irda_lock(int *lock) -{ - if (test_and_set_bit( 0, (void *) lock)) { - IRDA_DEBUG(3, __FUNCTION__ - "(), Trying to lock, already locked variable!\n"); - return FALSE; - } - return TRUE; -} - -inline int irda_unlock(int *lock); - -void irda_notify_init(notify_t *notify); - -void irda_execute_as_process(void *self, TODO_CALLBACK callback, __u32 param); -void irmanager_notify(struct irmanager_event *event); - -extern void irda_proc_modcount(struct inode *, int); -void irda_mod_inc_use_count(void); -void irda_mod_dec_use_count(void); - -#endif /* IRMOD_H */ - - - - - - - - - diff -urpN linux-2.2.18-23/include/net/irda/irqueue.h linux/include/net/irda/irqueue.h --- linux-2.2.18-23/include/net/irda/irqueue.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irqueue.h Tue Nov 28 20:32:41 2000 @@ -30,8 +30,8 @@ #include #include -#ifndef QUEUE_H -#define QUEUE_H +#ifndef IRDA_QUEUE_H +#define IRDA_QUEUE_H #define NAME_SIZE 32 @@ -62,39 +62,40 @@ typedef void (*FREE_FUNC)(void *arg); */ #define GET_HASHBIN(x) ( x & HASHBIN_MASK ) -struct irqueue { - struct irqueue *q_next; - struct irqueue *q_prev; +struct irda_queue { + struct irda_queue *q_next; + struct irda_queue *q_prev; char q_name[NAME_SIZE]; __u32 q_hash; }; -typedef struct irqueue queue_t; +typedef struct irda_queue irda_queue_t; typedef struct hashbin_t { __u32 magic; int hb_type; int hb_size; spinlock_t hb_mutex[HASHBIN_SIZE] ALIGN; - queue_t *hb_queue[HASHBIN_SIZE] ALIGN; + irda_queue_t *hb_queue[HASHBIN_SIZE] ALIGN; - queue_t* hb_current; + irda_queue_t* hb_current; } hashbin_t; hashbin_t *hashbin_new(int type); int hashbin_delete(hashbin_t* hashbin, FREE_FUNC func); int hashbin_clear(hashbin_t* hashbin, FREE_FUNC free_func); -void hashbin_insert(hashbin_t* hashbin, queue_t* entry, __u32 hashv, +void hashbin_insert(hashbin_t* hashbin, irda_queue_t* entry, __u32 hashv, char* name); void* hashbin_find(hashbin_t* hashbin, __u32 hashv, char* name); void* hashbin_remove(hashbin_t* hashbin, __u32 hashv, char* name); void* hashbin_remove_first(hashbin_t *hashbin); -queue_t *hashbin_get_first(hashbin_t *hashbin); -queue_t *hashbin_get_next(hashbin_t *hashbin); - -void enqueue_last(queue_t **queue, queue_t* element); -void enqueue_first(queue_t **queue, queue_t* element); -queue_t *dequeue_first(queue_t **queue); +void* hashbin_remove_this( hashbin_t* hashbin, irda_queue_t* entry); +irda_queue_t *hashbin_get_first(hashbin_t *hashbin); +irda_queue_t *hashbin_get_next(hashbin_t *hashbin); + +void enqueue_last(irda_queue_t **queue, irda_queue_t* element); +void enqueue_first(irda_queue_t **queue, irda_queue_t* element); +irda_queue_t *dequeue_first(irda_queue_t **queue); #define HASHBIN_GET_SIZE(hashbin) hashbin->hb_size diff -urpN linux-2.2.18-23/include/net/irda/irttp.h linux/include/net/irda/irttp.h --- linux-2.2.18-23/include/net/irda/irttp.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irttp.h Tue Nov 28 20:35:45 2000 @@ -63,7 +63,7 @@ * connection. */ struct tsap_cb { - queue_t q; /* Must be first */ + irda_queue_t q; /* Must be first */ magic_t magic; /* Just in case */ __u8 stsap_sel; /* Source TSAP */ @@ -129,6 +129,8 @@ int irttp_connect_response(struct tsap_c int irttp_disconnect_request(struct tsap_cb *self, struct sk_buff *skb, int priority); void irttp_flow_request(struct tsap_cb *self, LOCAL_FLOW flow); +void irttp_status_indication(void *instance, + LINK_STATUS link, LOCK_STATUS lock); struct tsap_cb *irttp_dup(struct tsap_cb *self, void *instance); static __inline __u32 irttp_get_saddr(struct tsap_cb *self) diff -urpN linux-2.2.18-23/include/net/irda/irtty.h linux/include/net/irda/irtty.h --- linux-2.2.18-23/include/net/irda/irtty.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/irtty.h Tue Nov 28 20:34:36 2000 @@ -45,7 +45,7 @@ struct irtty_info { #define IRTTY_IOC_MAXNR 2 struct irtty_cb { - queue_t q; /* Must be first */ + irda_queue_t q; /* Must be first */ magic_t magic; struct device *netdev; /* Yes! we are some kind of netdevice */ diff -urpN linux-2.2.18-23/include/net/irda/qos.h linux/include/net/irda/qos.h --- linux-2.2.18-23/include/net/irda/qos.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/qos.h Tue Nov 28 20:32:41 2000 @@ -86,6 +86,9 @@ struct qos_info { #endif }; +extern int sysctl_max_baud_rate; +extern int sysctl_max_inactive_time; + extern __u32 baud_rates[]; extern __u32 data_sizes[]; extern __u32 min_turn_times[]; @@ -100,15 +103,7 @@ __u32 irlap_requested_line_capacity(stru __u32 irlap_min_turn_time_in_bytes(__u32 speed, __u32 min_turn_time); int msb_index(__u16 byte); -int value_index(__u32 value, __u32 *array); -__u32 byte_value(__u8 byte, __u32 *array); -__u32 index_value(int index, __u32 *array); - void irda_qos_bits_to_value(struct qos_info *qos); #endif - - - - diff -urpN linux-2.2.18-23/include/net/irda/timer.h linux/include/net/irda/timer.h --- linux-2.2.18-23/include/net/irda/timer.h Thu May 4 02:16:52 2000 +++ linux/include/net/irda/timer.h Tue Nov 28 20:34:36 2000 @@ -31,7 +31,6 @@ #include /* for HZ */ #include -#include #include #include #include @@ -76,12 +75,14 @@ inline void irlap_start_wd_timer(struct inline void irlap_start_backoff_timer(struct irlap_cb *self, int timeout); void irlap_start_mbusy_timer(struct irlap_cb *); +void irlap_stop_mbusy_timer(struct irlap_cb *); struct lsap_cb; struct lap_cb; inline void irlmp_start_watchdog_timer(struct lsap_cb *, int timeout); inline void irlmp_start_discovery_timer(struct irlmp_cb *, int timeout); inline void irlmp_start_idle_timer(struct lap_cb *, int timeout); +inline void irlmp_stop_idle_timer(struct lap_cb *self); #endif diff -urpN linux-2.2.18-23/net/irda/Config.in linux/net/irda/Config.in --- linux-2.2.18-23/net/irda/Config.in Thu May 4 02:16:53 2000 +++ linux/net/irda/Config.in Sun Nov 26 22:23:51 2000 @@ -23,7 +23,6 @@ if [ "$CONFIG_NET" != "n" ]; then fi if [ "$CONFIG_IRDA" != "n" ]; then - source net/irda/compressors/Config.in source drivers/net/irda/Config.in fi endmenu diff -urpN linux-2.2.18-23/net/irda/Makefile linux/net/irda/Makefile --- linux-2.2.18-23/net/irda/Makefile Thu May 4 02:16:53 2000 +++ linux/net/irda/Makefile Sun Nov 26 22:23:31 2000 @@ -7,7 +7,7 @@ # # Note 2! The CFLAGS definition is now in the main makefile... -ALL_SUB_DIRS := irlan ircomm compressors +ALL_SUB_DIRS := irlan ircomm SUB_DIRS := MOD_SUB_DIRS := OX_OBJS := @@ -15,9 +15,9 @@ OX_OBJS := O_TARGET := irda.o O_OBJS := iriap.o iriap_event.o irlmp.o irlmp_event.o irlmp_frame.o \ irlap.o irlap_event.o irlap_frame.o timer.o qos.o irqueue.o \ - irttp.o irda_device.o irias_object.o crc.o wrapper.o af_irda.o \ + irttp.o irda_device.o irias_object.o crc.o wrapper.o \ discovery.o parameters.o -OX_OBJS := irmod.o +OX_OBJS := af_irda.o MOD_LIST_NAME := IRDA_MODULES @@ -43,19 +43,6 @@ O_OBJS += irlan/irlan.o else ifeq ($(CONFIG_IRLAN),m) MOD_SUB_DIRS += irlan - endif -endif - -ifeq ($(CONFIG_IRDA_COMPRESSION),y) -SUB_DIRS += compressors -MOD_IN_SUB_DIRS += compressors -endif - -ifeq ($(CONFIG_IRDA_DEFLATE),y) -O_OBJS += compressors/irda_deflate.o -else - ifeq ($(CONFIG_IRDA_DEFLATE),m) - MOD_TO_LIST += irda_deflate.o endif endif diff -urpN linux-2.2.18-23/net/irda/af_irda.c linux/net/irda/af_irda.c --- linux-2.2.18-23/net/irda/af_irda.c Thu Nov 23 14:46:43 2000 +++ linux/net/irda/af_irda.c Tue Nov 28 19:53:11 2000 @@ -11,7 +11,7 @@ * Sources: af_netrom.c, af_ax25.c, af_rose.c, af_x25.c etc. * * Copyright (c) 1999-2000 Dag Brattli - * Copyright (c) 1999 Jean Tourrilhes + * Copyright (c) 1999 Jean Tourrilhes * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -42,6 +42,8 @@ * ********************************************************************/ +#include +#include #include #include #include @@ -50,20 +52,39 @@ #include #include #include +#include #include #include #include +#include #include #include #include #include #include +#include +#include +#include + +extern struct proc_dir_entry *proc_irda; + +extern void irda_proc_register(void); +extern void irda_proc_unregister(void); +extern int irda_sysctl_register(void); +extern void irda_sysctl_unregister(void); + +extern int irda_device_init(void); +extern int irlan_init(void); +extern int irlan_client_init(void); +extern int irlan_server_init(void); +extern int ircomm_init(void); +extern int ircomm_tty_init(void); +extern int irlpt_client_init(void); +extern int irlpt_server_init(void); -extern int irda_init(void); -extern void irda_cleanup(void); extern int irlap_driver_rcv(struct sk_buff *, struct device *, struct packet_type *); @@ -77,11 +98,80 @@ static struct proto_ops irda_dgram_ops; static struct proto_ops irda_ultra_ops; #define ULTRA_MAX_DATA 382 #endif /* CONFIG_IRDA_ULTRA */ +#define IRDA_MAX_HEADER (TTP_MAX_HEADER) -static hashbin_t *cachelog = NULL; -static struct wait_queue *discovery_wait; /* Wait for discovery */ +#ifdef CONFIG_IRDA_DEBUG +__u32 irda_debug = IRDA_DEBUG_LEVEL; +#endif -#define IRDA_MAX_HEADER (TTP_MAX_HEADER) +static int __init irda_init(void) +{ + IRDA_DEBUG(0, __FUNCTION__ "()\n"); + + irlmp_init(); + irlap_init(); + + iriap_init(); + irttp_init(); + +#ifdef CONFIG_PROC_FS + irda_proc_register(); +#endif +#ifdef CONFIG_SYSCTL + irda_sysctl_register(); +#endif + /* + * Initialize modules that got compiled into the kernel + */ +#ifdef CONFIG_IRLAN + irlan_init(); +#endif +#ifdef CONFIG_IRCOMM + ircomm_init(); + ircomm_tty_init(); +#endif + return 0; +} + +static void irda_cleanup(void) +{ +#ifdef CONFIG_SYSCTL + irda_sysctl_unregister(); +#endif + +#ifdef CONFIG_PROC_FS + irda_proc_unregister(); +#endif + /* Remove higher layers */ + irttp_cleanup(); + iriap_cleanup(); + + /* Remove lower layers */ + irda_device_cleanup(); + irlap_cleanup(); /* Must be done before irlmp_cleanup()! DB */ + + /* Remove middle layer */ + irlmp_cleanup(); +} + +/* + * Function irda_notify_init (notify) + * + * Used for initializing the notify structure + * + */ +void irda_notify_init(notify_t *notify) +{ + notify->data_indication = NULL; + notify->udata_indication = NULL; + notify->connect_confirm = NULL; + notify->connect_indication = NULL; + notify->disconnect_indication = NULL; + notify->flow_indication = NULL; + notify->status_indication = NULL; + notify->instance = NULL; + strncpy(notify->name, "Unknown", NOTIFY_MAX_NAME); +} /* * Function irda_data_indication (instance, sap, skb) @@ -116,7 +206,7 @@ static int irda_data_indication(void *in /* * Function irda_disconnect_indication (instance, sap, reason, skb) * - * Connection has been closed. Chech reason to find out why + * Connection has been closed. Check reason to find out why * */ static void irda_disconnect_indication(void *instance, void *sap, @@ -140,6 +230,27 @@ static void irda_disconnect_indication(v sk->state_change(sk); sk->dead = 1; } + + /* Close our TSAP. + * If we leave it open, IrLMP put it back into the list of + * unconnected LSAPs. The problem is that any incomming request + * can then be matched to this socket (and it will be, because + * it is at the head of the list). This would prevent any + * listening socket waiting on the same TSAP to get those requests. + * Some apps forget to close sockets, or hang to it a bit too long, + * so we may stay in this dead state long enough to be noticed... + * Note : all socket function do check sk->state, so we are safe... + * Jean II + */ + irttp_close_tsap(self->tsap); + self->tsap = NULL; + + /* Note : once we are there, there is not much you want to do + * with the socket anymore, apart from closing it. + * For example, bind() and connect() won't reset sk->err, + * sk->shutdown and sk->dead to valid values... + * Jean II + */ } /* @@ -325,19 +436,19 @@ static void irda_flow_indication(void *i /* * Function irda_getvalue_confirm (obj_id, value, priv) * - * Got answer from remote LM-IAS + * Got answer from remote LM-IAS, just pass object to requester... * + * Note : duplicate from above, but we need our own version that + * doesn't touch the dtsap_sel and save the full value structure... */ static void irda_getvalue_confirm(int result, __u16 obj_id, - struct ias_value *value, void *priv) + struct ias_value *value, void *priv) { struct irda_sock *self; IRDA_DEBUG(2, __FUNCTION__ "()\n"); - ASSERT(priv != NULL, return;); self = (struct irda_sock *) priv; - if (!self) { WARNING(__FUNCTION__ "(), lost myself!\n"); return; @@ -347,51 +458,90 @@ static void irda_getvalue_confirm(int re iriap_close(self->iriap); self->iriap = NULL; - self->errno = result; - /* Check if request succeeded */ if (result != IAS_SUCCESS) { - IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n"); + IRDA_DEBUG(1, __FUNCTION__ "(), IAS query failed! (%d)\n", + result); + + self->errno = result; /* We really need it later */ /* Wake up any processes waiting for result */ - wake_up_interruptible(&self->ias_wait); + wake_up_interruptible(&self->query_wait); return; } - switch (value->type) { - case IAS_INTEGER: - IRDA_DEBUG(4, __FUNCTION__ "() int=%d\n", value->t.integer); - - if (value->t.integer != -1) { - self->dtsap_sel = value->t.integer; - } else - self->dtsap_sel = 0; - break; - default: - IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n"); - break; - } - irias_delete_value(value); + /* Pass the object to the caller (so the caller must delete it) */ + self->ias_result = value; + self->errno = 0; /* Wake up any processes waiting for result */ - wake_up_interruptible(&self->ias_wait); + wake_up_interruptible(&self->query_wait); } /* - * Function irda_discovery_indication (log) + * Function irda_selective_discovery_indication (discovery) * - * Got a discovery log from IrLMP, wake ut any process waiting for answer + * Got a selective discovery indication from IrLMP. * + * IrLMP is telling us that this node is matching our hint bit + * filter. Check if it's a newly discovered node (or if node changed its + * hint bits), and then wake up any process waiting for answer... */ -static void irda_discovery_indication(hashbin_t *log) +static void irda_selective_discovery_indication(discovery_t *discovery, + void *priv) { + struct irda_sock *self; + IRDA_DEBUG(2, __FUNCTION__ "()\n"); - cachelog = log; + self = (struct irda_sock *) priv; + if (!self) { + WARNING(__FUNCTION__ "(), lost myself!\n"); + return; + } + + /* Check if node is discovered is a new one or an old one. + * We check when how long ago this node was discovered, with a + * coarse timeout (we may miss some discovery events or be delayed). + * Note : by doing this test here, we avoid waking up a process ;-) + */ + if((jiffies - discovery->first_timestamp) > + (sysctl_discovery_timeout * HZ)) { + return; /* Too old, not interesting -> goodbye */ + } + + /* Pass parameter to the caller */ + self->cachediscovery = discovery; /* Wake up process if its waiting for device to be discovered */ - wake_up_interruptible(&discovery_wait); + wake_up_interruptible(&self->query_wait); +} + +/* + * Function irda_discovery_timeout (priv) + * + * Timeout in the selective discovery process + * + * We were waiting for a node to be discovered, but nothing has come up + * so far. Wake up the user and tell him that we failed... + */ +static void irda_discovery_timeout(u_long priv) +{ + struct irda_sock *self; + + IRDA_DEBUG(2, __FUNCTION__ "()\n"); + + self = (struct irda_sock *) priv; + ASSERT(self != NULL, return;); + + /* Nothing for the caller */ + self->cachelog = NULL; + self->cachediscovery = NULL; + self->errno = -ETIME; + + /* Wake up process if its still waiting... */ + wake_up_interruptible(&self->query_wait); } /* @@ -469,6 +619,11 @@ static int irda_open_lsap(struct irda_so * * Try to lookup LSAP selector in remote LM-IAS * + * Basically, we start a IAP query, and then go to sleep. When the query + * return, irda_getvalue_confirm will wake us up, and we can examine the + * result of the query... + * Note that in some case, the query fail even before we go to sleep, + * creating some races... */ static int irda_find_lsap_sel(struct irda_sock *self, char *name) { @@ -484,19 +639,53 @@ static int irda_find_lsap_sel(struct ird self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, irda_getvalue_confirm); + /* Treat unexpected signals as disconnect */ + self->errno = -EHOSTUNREACH; + /* Query remote LM-IAS */ iriap_getvaluebyclass_request(self->iriap, self->saddr, self->daddr, name, "IrDA:TinyTP:LsapSel"); - /* Wait for answer */ - interruptible_sleep_on(&self->ias_wait); + /* Wait for answer (if not already failed) */ + if(self->iriap != NULL) + interruptible_sleep_on(&self->query_wait); + + /* Check what happened */ + if (self->errno) + { + /* Requested object/attribute doesn't exist */ + if((self->errno == IAS_CLASS_UNKNOWN) || + (self->errno == IAS_ATTRIB_UNKNOWN)) + return (-EADDRNOTAVAIL); + else + return (-EHOSTUNREACH); + } + + /* Get the remote TSAP selector */ + switch (self->ias_result->type) { + case IAS_INTEGER: + IRDA_DEBUG(4, __FUNCTION__ "() int=%d\n", + self->ias_result->t.integer); + + if (self->ias_result->t.integer != -1) + self->dtsap_sel = self->ias_result->t.integer; + else + self->dtsap_sel = 0; + break; + default: + self->dtsap_sel = 0; + IRDA_DEBUG(0, __FUNCTION__ "(), bad type!\n"); + break; + } + if (self->ias_result) + irias_delete_value(self->ias_result); if (self->dtsap_sel) return 0; - return -ENETUNREACH; /* May not be true */ + return -EADDRNOTAVAIL; } - /* +/* * Function irda_discover_daddr_and_lsap_sel (self, name) * * This try to find a device with the requested service. @@ -515,71 +704,78 @@ static int irda_find_lsap_sel(struct ird */ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) { - discovery_t *discovery; - int err = -ENETUNREACH; - __u32 daddr = 0x0; /* Address we found the service on */ + struct irda_device_info *discoveries; /* Copy of the discovery log */ + int number; /* Number of nodes in the log */ + int i; + int err = -ENETUNREACH; + __u32 daddr = DEV_ADDR_ANY; /* Address we found the service on */ __u8 dtsap_sel = 0x0; /* TSAP associated with it */ IRDA_DEBUG(2, __FUNCTION__ "(), name=%s\n", name); ASSERT(self != NULL, return -1;); - /* Tell IrLMP we want to be notified */ - irlmp_update_client(self->ckey, self->mask, NULL, - irda_discovery_indication); - - /* Do some discovery */ - irlmp_discovery_request(self->nslots); - + /* Ask lmp for the current discovery log + * Note : we have to use irlmp_get_discoveries(), as opposed + * to play with the cachelog directly, because while we are + * making our ias query, le log might change... */ + discoveries = irlmp_get_discoveries(&number, self->mask); /* Check if the we got some results */ - if (!cachelog) - /* Wait for answer */ - /*interruptible_sleep_on(&self->discovery_wait);*/ - return -EAGAIN; + if (discoveries == NULL) + return -ENETUNREACH; /* No nodes discovered */ /* * Now, check all discovered devices (if any), and connect * client only about the services that the client is * interested in... */ - discovery = (discovery_t *) hashbin_get_first(cachelog); - while (discovery != NULL) { - /* Mask out the ones we don't want */ - if (discovery->hints.word & self->mask) { - /* Try this address */ - self->daddr = discovery->daddr; - self->saddr = 0x0; - IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n", - self->daddr); - - /* Query remote LM-IAS for this service */ - err = irda_find_lsap_sel(self, name); - if (err == 0) { - /* We found the requested service */ - if(daddr != 0x0) { - IRDA_DEBUG(0, __FUNCTION__ - "(), discovered service ''%s'' in two different devices !!!\n", - name); - return(-ENOTUNIQ); - } - /* First time we foun that one, save it ! */ - daddr = self->daddr; - dtsap_sel = self->dtsap_sel; + for(i = 0; i < number; i++) { + /* Try the address in the log */ + self->daddr = discoveries[i].daddr; + self->saddr = 0x0; + IRDA_DEBUG(1, __FUNCTION__ "(), trying daddr = %08x\n", + self->daddr); + + /* Query remote LM-IAS for this service */ + err = irda_find_lsap_sel(self, name); + switch (err) { + case 0: + /* We found the requested service */ + if(daddr != DEV_ADDR_ANY) { + IRDA_DEBUG(1, __FUNCTION__ + "(), discovered service ''%s'' in two different devices !!!\n", + name); + self->daddr = DEV_ADDR_ANY; + kfree(discoveries); + return(-ENOTUNIQ); } + /* First time we found that one, save it ! */ + daddr = self->daddr; + dtsap_sel = self->dtsap_sel; + break; + case -EADDRNOTAVAIL: + /* Requested service simply doesn't exist on this node */ + break; + default: + /* Something bad did happen :-( */ + IRDA_DEBUG(0, __FUNCTION__ + "(), unexpected IAS query failure\n"); + self->daddr = DEV_ADDR_ANY; + kfree(discoveries); + return(-EHOSTUNREACH); + break; } - - /* Next node, maybe we will be more lucky... */ - discovery = (discovery_t *) hashbin_get_next(cachelog); } - cachelog = NULL; + /* Cleanup our copy of the discovery log */ + kfree(discoveries); /* Check out what we found */ - if(daddr == 0x0) { - IRDA_DEBUG(0, __FUNCTION__ + if(daddr == DEV_ADDR_ANY) { + IRDA_DEBUG(1, __FUNCTION__ "(), cannot discover service ''%s'' in any device !!!\n", name); - self->daddr = 0; /* Guessing */ - return(-ENETUNREACH); + self->daddr = DEV_ADDR_ANY; + return(-EADDRNOTAVAIL); } /* Revert back to discovered device & service */ @@ -587,7 +783,7 @@ static int irda_discover_daddr_and_lsap_ self->saddr = 0x0; self->dtsap_sel = dtsap_sel; - IRDA_DEBUG(0, __FUNCTION__ + IRDA_DEBUG(1, __FUNCTION__ "(), discovered requested service ''%s'' at address %08x\n", name, self->daddr); @@ -605,25 +801,26 @@ static int irda_getname(struct socket *s { struct sockaddr_irda saddr; struct sock *sk = sock->sk; + struct irda_sock *self = sk->protinfo.irda; if (peer) { if (sk->state != TCP_ESTABLISHED) return -ENOTCONN; saddr.sir_family = AF_IRDA; - saddr.sir_lsap_sel = sk->protinfo.irda->dtsap_sel; - saddr.sir_addr = sk->protinfo.irda->daddr; + saddr.sir_lsap_sel = self->dtsap_sel; + saddr.sir_addr = self->daddr; } else { saddr.sir_family = AF_IRDA; - saddr.sir_lsap_sel = sk->protinfo.irda->stsap_sel; - saddr.sir_addr = sk->protinfo.irda->saddr; + saddr.sir_lsap_sel = self->stsap_sel; + saddr.sir_addr = self->saddr; } IRDA_DEBUG(1, __FUNCTION__ "(), tsap_sel = %#x\n", saddr.sir_lsap_sel); IRDA_DEBUG(1, __FUNCTION__ "(), addr = %08x\n", saddr.sir_addr); - if (*uaddr_len > sizeof (struct sockaddr_irda)) - *uaddr_len = sizeof (struct sockaddr_irda); + /* uaddr_len come to us uninitialised */ + *uaddr_len = sizeof (struct sockaddr_irda); memcpy(uaddr, &saddr, *uaddr_len); return 0; @@ -708,7 +905,7 @@ static int irda_bind(struct socket *sock /* Register with LM-IAS */ self->ias_obj = irias_new_object(addr->sir_name, jiffies); irias_add_integer_attrib(self->ias_obj, "IrDA:TinyTP:LsapSel", - self->stsap_sel); + self->stsap_sel, IAS_KERNEL_ATTR); irias_insert_object(self->ias_obj); #if 1 /* Will be removed in near future */ @@ -822,6 +1019,20 @@ static int irda_accept(struct socket *so * * Connect to a IrDA device * + * The main difference with a "standard" connect is that with IrDA we need + * to resolve the service name into a TSAP selector (in TCP, port number + * doesn't have to be resolved). + * Because of this service name resoltion, we can offer "auto-connect", + * where we connect to a service without specifying a destination address. + * + * Note : by consulting "errno", the user space caller may learn the cause + * of the failure. Most of them are visible in the function, others may come + * from subroutines called and are listed here : + * o EBUSY : already processing a connect + * o EHOSTUNREACH : bad addr->sir_addr argument + * o EADDRNOTAVAIL : bad addr->sir_name argument + * o ENOTUNIQ : more than one node has addr->sir_name (auto-connect) + * o ENETUNREACH : no node found on the network (auto-connect) */ static int irda_connect(struct socket *sock, struct sockaddr *uaddr, int addr_len, int flags) @@ -859,13 +1070,13 @@ static int irda_connect(struct socket *s return -EINVAL; /* Check if user supplied any destination device address */ - if (!addr->sir_addr) { + if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) { /* Try to find one suitable */ err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name); if (err) { IRDA_DEBUG(0, __FUNCTION__ "(), auto-connect failed!\n"); - return -EINVAL; + return err; } } else { /* Use the one provided by the user */ @@ -922,7 +1133,10 @@ static int irda_connect(struct socket *s sock->state = SS_CONNECTED; sti(); - + + /* At this point, IrLMP has assigned our source address */ + self->saddr = irttp_get_saddr(self->tsap); + return 0; } @@ -995,14 +1209,14 @@ static int irda_create(struct socket *so sk->protocol = protocol; /* Register as a client with IrLMP */ - self->ckey = irlmp_register_client(0, NULL, NULL); + self->ckey = irlmp_register_client(0, NULL, NULL, NULL); self->mask = 0xffff; self->rx_flow = self->tx_flow = FLOW_START; self->nslots = DISCOVERY_DEFAULT_SLOTS; - self->daddr = DEV_ADDR_ANY; + self->daddr = DEV_ADDR_ANY; /* Until we get connected */ + self->saddr = 0x0; /* so IrLMP assign us any link */ - /* Notify that we are using the irda module, so nobody removes it */ - irda_mod_inc_use_count(); + MOD_INC_USE_COUNT; return 0; } @@ -1024,11 +1238,15 @@ void irda_destroy_socket(struct irda_soc irlmp_unregister_service(self->skey); /* Unregister with LM-IAS */ - if (self->ias_obj) + if (self->ias_obj) { irias_delete_object(self->ias_obj); + self->ias_obj = NULL; + } - if (self->iriap) + if (self->iriap) { iriap_close(self->iriap); + self->iriap = NULL; + } if (self->tsap) { irttp_disconnect_request(self->tsap, NULL, P_NORMAL); @@ -1042,10 +1260,8 @@ void irda_destroy_socket(struct irda_soc } #endif /* CONFIG_IRDA_ULTRA */ kfree(self); - - /* Notify that we are not using the irda module anymore */ - irda_mod_dec_use_count(); - + MOD_DEC_USE_COUNT; + return; } @@ -1074,6 +1290,7 @@ static int irda_release(struct socket *s sock->sk = NULL; sk->socket = NULL; /* Not used, but we should do this. */ sk->protinfo.irda = NULL; + return 0; } @@ -1095,7 +1312,8 @@ static int irda_sendmsg(struct socket *s IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len); - if (msg->msg_flags & ~MSG_DONTWAIT) + /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ + if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR)) return -EINVAL; if (sk->shutdown & SEND_SHUTDOWN) { @@ -1473,15 +1691,22 @@ static int irda_shutdown(struct socket * sk->shutdown |= SEND_SHUTDOWN; sk->state_change(sk); - if (self->iriap) + if (self->iriap) { iriap_close(self->iriap); - + self->iriap = NULL; + } + if (self->tsap) { irttp_disconnect_request(self->tsap, NULL, P_NORMAL); irttp_close_tsap(self->tsap); self->tsap = NULL; } + /* A few cleanup so the socket look as good as new... */ + self->rx_flow = self->tx_flow = FLOW_START; /* needed ??? */ + self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */ + self->saddr = 0x0; /* so IrLMP assign us any link */ + return 0; } @@ -1605,6 +1830,7 @@ static int irda_setsockopt(struct socket struct irda_sock *self; struct irda_ias_set ias_opt; struct ias_object *ias_obj; + struct ias_attrib * ias_attr; /* Attribute in IAS object */ int opt; self = sk->protinfo.irda; @@ -1615,6 +1841,13 @@ static int irda_setsockopt(struct socket switch (optname) { case IRLMP_IAS_SET: + /* The user want to add an attribute to an existing IAS object + * (in the IAS database) or to create a new object with this + * attribute. + * We first query IAS to know if the object exist, and then + * create the right attribute... + */ + if (optlen != sizeof(struct irda_ias_set)) return -EINVAL; @@ -1638,9 +1871,11 @@ static int irda_setsockopt(struct socket switch(ias_opt.irda_attrib_type) { case IAS_INTEGER: /* Add an integer attribute */ - irias_add_integer_attrib(ias_obj, - ias_opt.irda_attrib_name, - ias_opt.attribute.irda_attrib_int); + irias_add_integer_attrib( + ias_obj, + ias_opt.irda_attrib_name, + ias_opt.attribute.irda_attrib_int, + IAS_USER_ATTR); break; case IAS_OCT_SEQ: /* Check length */ @@ -1652,7 +1887,8 @@ static int irda_setsockopt(struct socket ias_obj, ias_opt.irda_attrib_name, ias_opt.attribute.irda_attrib_octet_seq.octet_seq, - ias_opt.attribute.irda_attrib_octet_seq.len); + ias_opt.attribute.irda_attrib_octet_seq.len, + IAS_USER_ATTR); break; case IAS_STRING: /* Should check charset & co */ @@ -1666,16 +1902,49 @@ static int irda_setsockopt(struct socket irias_add_string_attrib( ias_obj, ias_opt.irda_attrib_name, - ias_opt.attribute.irda_attrib_string.string); + ias_opt.attribute.irda_attrib_string.string, + IAS_USER_ATTR); break; default : return -EINVAL; } irias_insert_object(ias_obj); break; + case IRLMP_IAS_DEL: + /* The user want to delete an object from our local IAS + * database. We just need to query the IAS, check is the + * object is not owned by the kernel and delete it. + */ - IRDA_DEBUG(0, __FUNCTION__ "(), sorry not impl. yet!\n"); - return -ENOPROTOOPT; + if (optlen != sizeof(struct irda_ias_set)) + return -EINVAL; + + /* Copy query to the driver. */ + if (copy_from_user(&ias_opt, (char *)optval, optlen)) + return -EFAULT; + + /* Find the object we target */ + ias_obj = irias_find_object(ias_opt.irda_class_name); + if(ias_obj == (struct ias_object *) NULL) + return -EINVAL; + + /* Find the attribute (in the object) we target */ + ias_attr = irias_find_attrib(ias_obj, + ias_opt.irda_attrib_name); + if(ias_attr == (struct ias_attrib *) NULL) + return -EINVAL; + + /* Check is the user space own the object */ + if(ias_attr->value->owner != IAS_USER_ATTR) { + IRDA_DEBUG(1, __FUNCTION__ + "(), attempting to delete a kernel attribute\n"); + return -EPERM; + } + + /* Remove the attribute (and maybe the object) */ + irias_delete_attrib(ias_obj, ias_attr); + + break; case IRLMP_MAX_SDU_SIZE: if (optlen < sizeof(int)) return -EINVAL; @@ -1708,60 +1977,31 @@ static int irda_setsockopt(struct socket self->skey = irlmp_register_service((__u16) opt); break; - default: - return -ENOPROTOOPT; - } - return 0; -} - - /* - * Function irda_simple_getvalue_confirm (obj_id, value, priv) - * - * Got answer from remote LM-IAS, just copy object to requester... - * - * Note : duplicate from above, but we need our own version that - * doesn't touch the dtsap_sel and save the full value structure... - */ -static void irda_simple_getvalue_confirm(int result, __u16 obj_id, - struct ias_value *value, void *priv) -{ - struct irda_sock *self; - - IRDA_DEBUG(2, __FUNCTION__ "()\n"); - - ASSERT(priv != NULL, return;); - self = (struct irda_sock *) priv; + case IRLMP_HINT_MASK_SET: + /* As opposed to the previous case which set the hint bits + * that we advertise, this one set the filter we use when + * making a discovery (nodes which don't match any hint + * bit in the mask are not reported). + */ + if (optlen < sizeof(int)) + return -EINVAL; - if (!self) { - WARNING(__FUNCTION__ "(), lost myself!\n"); - return; - } - - /* We probably don't need to make any more queries */ - iriap_close(self->iriap); - self->iriap = NULL; - - /* Check if request succeeded */ - if (result != IAS_SUCCESS) { - IRDA_DEBUG(0, __FUNCTION__ "(), IAS query failed!\n"); - - self->errno = -EHOSTUNREACH; + if (get_user(opt, (int *)optval)) + return -EFAULT; - /* Wake up any processes waiting for result */ - wake_up_interruptible(&self->ias_wait); + /* Set the new hint mask */ + self->mask = (__u16) opt; + /* Mask out extension bits */ + self->mask &= 0x7f7f; + /* Check if no bits */ + if(!self->mask) + self->mask = 0xFFFF; - return; + break; + default: + return -ENOPROTOOPT; } - - /* Clone the object (so the requester can free it) */ - self->ias_result = kmalloc(sizeof(struct ias_value), GFP_ATOMIC); - memcpy(self->ias_result, value, sizeof(struct ias_value)); - irias_delete_value(value); - - self->errno = 0; - - /* Wake up any processes waiting for result */ - wake_up_interruptible(&self->ias_wait); + return 0; } /* @@ -1802,6 +2042,7 @@ static int irda_extract_ias_value(struct /* NULL terminate the string (avoid troubles) */ ias_opt->attribute.irda_attrib_string.string[ias_value->len] = '\0'; break; + case IAS_MISSING: default : return -EINVAL; } @@ -1824,11 +2065,11 @@ static int irda_getsockopt(struct socket struct sock *sk = sock->sk; struct irda_sock *self; struct irda_device_list list; - struct irda_device_info *info; - discovery_t *discovery; + struct irda_device_info *discoveries; struct irda_ias_set ias_opt; /* IAS get/query params */ struct ias_object * ias_obj; /* Object in IAS */ struct ias_attrib * ias_attr; /* Attribute in IAS object */ + int daddr = DEV_ADDR_ANY; /* Dest address for IAS queries */ int val = 0; int len = 0; int err; @@ -1844,72 +2085,40 @@ static int irda_getsockopt(struct socket switch (optname) { case IRLMP_ENUMDEVICES: - /* Tell IrLMP we want to be notified */ - irlmp_update_client(self->ckey, self->mask, NULL, - irda_discovery_indication); - - /* Do some discovery */ - irlmp_discovery_request(self->nslots); - + /* Ask lmp for the current discovery log */ + discoveries = irlmp_get_discoveries(&list.len, self->mask); /* Check if the we got some results */ - if (!cachelog) - return -EAGAIN; + if (discoveries == NULL) + return -EAGAIN; /* Didn't find any devices */ + err = 0; - info = &list.dev[0]; + /* Write total list length back to client */ + if (copy_to_user(optval, &list, + sizeof(struct irda_device_list) - + sizeof(struct irda_device_info))) + err = -EFAULT; /* Offset to first device entry */ offset = sizeof(struct irda_device_list) - sizeof(struct irda_device_info); - total = offset; /* Initialized to size of the device list */ - list.len = 0; /* Initialize lenght of list */ - - /* - * Now, check all discovered devices (if any), and notify - * client only about the services that the client is - * interested in - */ - discovery = (discovery_t *) hashbin_get_first(cachelog); - while (discovery != NULL) { - /* Mask out the ones we don't want */ - if (discovery->hints.word & self->mask) { - /* Check if room for this device entry */ - if (len-totalsaddr = discovery->saddr; - info->daddr = discovery->daddr; - info->charset = discovery->charset; - info->hints[0] = discovery->hints.byte[0]; - info->hints[1] = discovery->hints.byte[1]; - strncpy(info->info, discovery->nickname, - NICKNAME_MAX_LEN); - - if (copy_to_user(optval+total, info, - sizeof(struct irda_device_info))) - return -EFAULT; - list.len++; - total += sizeof(struct irda_device_info); - } - discovery = (discovery_t *) hashbin_get_next(cachelog); - } - cachelog = NULL; + /* Copy the list itself */ + total = offset + (list.len * sizeof(struct irda_device_info)); + if (total > len) + total = len; + if (copy_to_user(optval+offset, discoveries, total - offset)) + err = -EFAULT; /* Write total number of bytes used back to client */ if (put_user(total, optlen)) - return -EFAULT; + err = -EFAULT; - /* Write total list length back to client */ - if (copy_to_user(optval, &list, - sizeof(struct irda_device_list) - - sizeof(struct irda_device_info))) - return -EFAULT; + /* Free up our buffer */ + kfree(discoveries); + if (err) + return err; break; case IRLMP_MAX_SDU_SIZE: - IRDA_DEBUG(2, __FUNCTION__ "(), max_data_size=%d\n", - self->max_data_size); - val = self->max_data_size; len = sizeof(int); if (put_user(len, optlen)) @@ -1966,6 +2175,26 @@ static int irda_getsockopt(struct socket if (copy_from_user((char *) &ias_opt, (char *)optval, len)) return -EFAULT; + /* At this point, there are two cases... + * 1) the socket is connected - that's the easy case, we + * just query the device we are connected to... + * 2) the socket is not connected - the user doesn't want + * to connect and/or may not have a valid service name + * (so can't create a fake connection). In this case, + * we assume that the user pass us a valid destination + * address in the requesting structure... + */ + if(self->daddr != DEV_ADDR_ANY) { + /* We are connected - reuse known daddr */ + daddr = self->daddr; + } else { + /* We are not connected, we must specify a valid + * destination address */ + daddr = ias_opt.daddr; + if((!daddr) || (daddr == DEV_ADDR_ANY)) + return -EINVAL; + } + /* Check that we can proceed with IAP */ if (self->iriap) { WARNING(__FUNCTION__ @@ -1974,26 +2203,34 @@ static int irda_getsockopt(struct socket } self->iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, - irda_simple_getvalue_confirm); + irda_getvalue_confirm); /* Treat unexpected signals as disconnect */ self->errno = -EHOSTUNREACH; /* Query remote LM-IAS */ - iriap_getvaluebyclass_request(self->iriap, - self->saddr, self->daddr, + iriap_getvaluebyclass_request(self->iriap, + self->saddr, daddr, ias_opt.irda_class_name, ias_opt.irda_attrib_name); - /* Wait for answer */ - interruptible_sleep_on(&self->ias_wait); + /* Wait for answer (if not already failed) */ + if(self->iriap != NULL) + interruptible_sleep_on(&self->query_wait); /* Check what happened */ if (self->errno) - return (self->errno); + { + /* Requested object/attribute doesn't exist */ + if((self->errno == IAS_CLASS_UNKNOWN) || + (self->errno == IAS_ATTRIB_UNKNOWN)) + return (-EADDRNOTAVAIL); + else + return (-EHOSTUNREACH); + } /* Translate from internal to user structure */ err = irda_extract_ias_value(&ias_opt, self->ias_result); if (self->ias_result) - kfree(self->ias_result); + irias_delete_value(self->ias_result); if (err) return err; @@ -2003,6 +2240,76 @@ static int irda_getsockopt(struct socket return -EFAULT; /* Note : don't need to put optlen, we checked it */ break; + case IRLMP_WAITDEVICE: + /* This function is just another way of seeing life ;-) + * IRLMP_ENUMDEVICES assumes that you have a static network, + * and that you just want to pick one of the devices present. + * On the other hand, in here we assume that no device is + * present and that at some point in the future a device will + * come into range. When this device arrive, we just wake + * up the caller, so that he has time to connect to it before + * the device goes away... + * Note : once the node has been discovered for more than a + * few second, it won't trigger this function, unless it + * goes away and come back changes its hint bits (so we + * might call it IRLMP_WAITNEWDEVICE). + */ + + /* Check that the user is passing us an int */ + if (len != sizeof(int)) + return -EINVAL; + /* Get timeout in ms (max time we block the caller) */ + if (get_user(val, (int *)optval)) + return -EFAULT; + + /* Tell IrLMP we want to be notified */ + irlmp_update_client(self->ckey, self->mask, + irda_selective_discovery_indication, NULL, + (void *) self); + + /* Do some discovery (and also return cached results) */ + irlmp_discovery_request(self->nslots); + + /* Wait until a node is discovered */ + if (!self->cachediscovery) { + IRDA_DEBUG(1, __FUNCTION__ + "(), nothing discovered yet, going to sleep...\n"); + + /* Set watchdog timer to expire in ms. */ + self->watchdog.function = irda_discovery_timeout; + self->watchdog.data = (unsigned long) self; + self->watchdog.expires = jiffies + (val * HZ/1000); + add_timer(&(self->watchdog)); + + /* Wait for IR-LMP to call us back */ + interruptible_sleep_on(&self->query_wait); + + /* If watchdog is still activated, kill it! */ + if(timer_pending(&(self->watchdog))) + del_timer(&(self->watchdog)); + + IRDA_DEBUG(1, __FUNCTION__ + "(), ...waking up !\n"); + } + else + IRDA_DEBUG(1, __FUNCTION__ + "(), found immediately !\n"); + + /* Tell IrLMP that we have been notified */ + irlmp_update_client(self->ckey, self->mask, NULL, NULL, NULL); + + /* Check if the we got some results */ + if (!self->cachediscovery) + return -EAGAIN; /* Didn't find any devices */ + /* Cleanup */ + self->cachediscovery = NULL; + + /* Note : We don't return anything to the user. + * We could return the device that triggered the wake up, + * but it's probably better to force the user to query + * the whole discovery log and let him pick one device... + */ + break; default: return -ENOPROTOOPT; } @@ -2165,6 +2472,9 @@ void __init irda_proto_init(struct net_p register_netdevice_notifier(&irda_dev_notifier); +#ifdef MODULE + irda_device_init(); /* Called by init/main.c when non-modular */ +#endif irda_init(); } @@ -2174,7 +2484,6 @@ void __init irda_proto_init(struct net_p * Remove IrDA protocol layer * */ -#ifdef MODULE void irda_proto_cleanup(void) { irda_packet_type.type = htons(ETH_P_IRDA); @@ -2187,4 +2496,158 @@ void irda_proto_cleanup(void) return; } + +#ifdef MODULE +/* IrTTP */ +EXPORT_SYMBOL(irttp_open_tsap); +EXPORT_SYMBOL(irttp_close_tsap); +EXPORT_SYMBOL(irttp_connect_response); +EXPORT_SYMBOL(irttp_data_request); +EXPORT_SYMBOL(irttp_disconnect_request); +EXPORT_SYMBOL(irttp_flow_request); +EXPORT_SYMBOL(irttp_connect_request); +EXPORT_SYMBOL(irttp_udata_request); +EXPORT_SYMBOL(irttp_dup); + +/* Main IrDA module */ +#ifdef CONFIG_IRDA_DEBUG +EXPORT_SYMBOL(irda_debug); +#endif +EXPORT_SYMBOL(irda_notify_init); +EXPORT_SYMBOL(irda_lock); +#ifdef CONFIG_PROC_FS +EXPORT_SYMBOL(proc_irda); +#endif +EXPORT_SYMBOL(irda_param_insert); +EXPORT_SYMBOL(irda_param_extract); +EXPORT_SYMBOL(irda_param_extract_all); +EXPORT_SYMBOL(irda_param_pack); +EXPORT_SYMBOL(irda_param_unpack); + +/* IrIAP/IrIAS */ +EXPORT_SYMBOL(iriap_open); +EXPORT_SYMBOL(iriap_close); +EXPORT_SYMBOL(iriap_getvaluebyclass_request); +EXPORT_SYMBOL(irias_object_change_attribute); +EXPORT_SYMBOL(irias_add_integer_attrib); +EXPORT_SYMBOL(irias_add_octseq_attrib); +EXPORT_SYMBOL(irias_add_string_attrib); +EXPORT_SYMBOL(irias_insert_object); +EXPORT_SYMBOL(irias_new_object); +EXPORT_SYMBOL(irias_delete_object); +EXPORT_SYMBOL(irias_delete_value); +EXPORT_SYMBOL(irias_find_object); +EXPORT_SYMBOL(irias_find_attrib); +EXPORT_SYMBOL(irias_new_integer_value); +EXPORT_SYMBOL(irias_new_string_value); +EXPORT_SYMBOL(irias_new_octseq_value); + +/* IrLMP */ +EXPORT_SYMBOL(irlmp_discovery_request); +EXPORT_SYMBOL(irlmp_get_discoveries); +EXPORT_SYMBOL(sysctl_discovery_timeout); +EXPORT_SYMBOL(irlmp_register_client); +EXPORT_SYMBOL(irlmp_unregister_client); +EXPORT_SYMBOL(irlmp_update_client); +EXPORT_SYMBOL(irlmp_register_service); +EXPORT_SYMBOL(irlmp_unregister_service); +EXPORT_SYMBOL(irlmp_service_to_hint); +EXPORT_SYMBOL(irlmp_data_request); +EXPORT_SYMBOL(irlmp_open_lsap); +EXPORT_SYMBOL(irlmp_close_lsap); +EXPORT_SYMBOL(irlmp_connect_request); +EXPORT_SYMBOL(irlmp_connect_response); +EXPORT_SYMBOL(irlmp_disconnect_request); +EXPORT_SYMBOL(irlmp_get_daddr); +EXPORT_SYMBOL(irlmp_get_saddr); +EXPORT_SYMBOL(irlmp_dup); +EXPORT_SYMBOL(lmp_reasons); + +/* Queue */ +EXPORT_SYMBOL(hashbin_find); +EXPORT_SYMBOL(hashbin_new); +EXPORT_SYMBOL(hashbin_insert); +EXPORT_SYMBOL(hashbin_delete); +EXPORT_SYMBOL(hashbin_remove); +EXPORT_SYMBOL(hashbin_remove_this); +EXPORT_SYMBOL(hashbin_get_next); +EXPORT_SYMBOL(hashbin_get_first); + +/* IrLAP */ +EXPORT_SYMBOL(irlap_open); +EXPORT_SYMBOL(irlap_close); +#ifdef CONFIG_IRDA_COMPRESSION +EXPORT_SYMBOL(irda_unregister_compressor); +EXPORT_SYMBOL(irda_register_compressor); +#endif /* CONFIG_IRDA_COMPRESSION */ +EXPORT_SYMBOL(irda_init_max_qos_capabilies); +EXPORT_SYMBOL(irda_qos_bits_to_value); +EXPORT_SYMBOL(irda_device_setup); +EXPORT_SYMBOL(irda_device_set_media_busy); +EXPORT_SYMBOL(irda_device_txqueue_empty); + +EXPORT_SYMBOL(irda_device_dongle_init); +EXPORT_SYMBOL(irda_device_dongle_cleanup); +EXPORT_SYMBOL(irda_device_register_dongle); +EXPORT_SYMBOL(irda_device_unregister_dongle); +EXPORT_SYMBOL(irda_task_execute); +EXPORT_SYMBOL(irda_task_kick); +EXPORT_SYMBOL(irda_task_next_state); +EXPORT_SYMBOL(irda_task_delete); + +EXPORT_SYMBOL(async_wrap_skb); +EXPORT_SYMBOL(async_unwrap_char); +EXPORT_SYMBOL(irda_start_timer); +EXPORT_SYMBOL(setup_dma); +EXPORT_SYMBOL(infrared_mode); + +#ifdef CONFIG_IRTTY +EXPORT_SYMBOL(irtty_set_dtr_rts); +EXPORT_SYMBOL(irtty_register_dongle); +EXPORT_SYMBOL(irtty_unregister_dongle); +EXPORT_SYMBOL(irtty_set_packet_mode); +#endif + +/* + * Function irda_proc_modcount (inode, fill) + * + * Use by the proc file system functions to prevent the irda module + * being removed while the use is standing in the net/irda directory + */ +void irda_proc_modcount(struct inode *inode, int fill) +{ +#ifdef MODULE +#ifdef CONFIG_PROC_FS + if (fill) + MOD_INC_USE_COUNT; + else + MOD_DEC_USE_COUNT; +#endif /* CONFIG_PROC_FS */ +#endif /* MODULE */ +} + +/* + * Function init_module (void) + * + * Initialize the irda module + * + */ +int init_module(void) +{ + irda_proto_init(NULL); + + return 0; +} + +/* + * Function cleanup_module (void) + * + * Cleanup the irda module + * + */ +void cleanup_module(void) +{ + irda_proto_cleanup(); +} #endif /* MODULE */ + diff -urpN linux-2.2.18-23/net/irda/compressors/Config.in linux/net/irda/compressors/Config.in --- linux-2.2.18-23/net/irda/compressors/Config.in Thu Nov 23 14:47:59 2000 +++ linux/net/irda/compressors/Config.in Thu Jan 1 01:00:00 1970 @@ -1,11 +0,0 @@ - -bool ' IrLAP compression' CONFIG_IRDA_COMPRESSION - -if [ "$CONFIG_IRDA_COMPRESSION" != "n" ]; then - comment ' IrDA compressors' - if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then - dep_tristate ' Deflate compression (EXPERIMENTAL)' CONFIG_IRDA_DEFLATE $CONFIG_IRDA m - fi -# tristate ' BZIP2 compression' CONFIG_IRDA_BZIP2 -# tristate ' BSD compression' CONFIG_IRDA_BSD -fi diff -urpN linux-2.2.18-23/net/irda/compressors/Makefile linux/net/irda/compressors/Makefile --- linux-2.2.18-23/net/irda/compressors/Makefile Thu Dec 17 18:01:03 1998 +++ linux/net/irda/compressors/Makefile Thu Jan 1 01:00:00 1970 @@ -1,26 +0,0 @@ -# -# Makefile for the Linux IRDA compression protocols -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# -# Note 2! The CFLAGS definition is now in the main makefile... - -O_TARGET := -O_OBJS := -MOD_LIST_NAME := IRDA_MODULES -M_OBJS := - -ifeq ($(CONFIG_IRDA_DEFLATE),y) -O_OBJS += irda_deflate.o -else - ifeq ($(CONFIG_IRDA_DEFLATE),m) - M_OBJS += irda_deflate.o - endif -endif - -include $(TOPDIR)/Rules.make - -tar: - tar -cvf /dev/f1 . diff -urpN linux-2.2.18-23/net/irda/compressors/irda_deflate.c linux/net/irda/compressors/irda_deflate.c --- linux-2.2.18-23/net/irda/compressors/irda_deflate.c Thu May 4 02:16:53 2000 +++ linux/net/irda/compressors/irda_deflate.c Thu Jan 1 01:00:00 1970 @@ -1,634 +0,0 @@ -/********************************************************************* - * - * Filename: irda_deflate.c - * Version: - * Description: - * Status: Experimental. - * Author: Dag Brattli - * Created at: Fri Oct 9 02:52:08 1998 - * Modified at: Mon Dec 14 19:48:54 1998 - * Modified by: Dag Brattli - * - * ==FILEVERSION 980319== - * - * irda_deflate.c - interface the zlib procedures for Deflate compression - * and decompression (as used by gzip) to the IrDA code. - * This version is for use with Linux kernel 2.1.X. - * - * Copyright (c) 1994 The Australian National University. - * All rights reserved. - * - * Permission to use, copy, modify, and distribute this software and its - * documentation is hereby granted, provided that the above copyright - * notice appears in all copies. This software is provided without any - * warranty, express or implied. The Australian National University - * makes no representations about the suitability of this software for - * any purpose. - * - * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY - * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES - * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - * THE AUSTRALIAN NATIONAL UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, - * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY - * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS - * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO - * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, - * OR MODIFICATIONS. - * - * From: deflate.c,v 1.1 1996/01/18 03:17:48 paulus Exp - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* used in new tty drivers */ -#include /* used in new tty drivers */ - -#include - -#include -#include -#include -#include - -#include -#include - -/* - * This is not that nice, but what can we do when the code has been placed - * elsewhere - */ - -#include "../../../drivers/net/zlib.c" - -/* - * State for a Deflate (de)compressor. - */ -struct irda_deflate_state { - int seqno; - int w_size; - int unit; - int mru; - int debug; - z_stream strm; - struct compstat stats; -}; - -#define DEFLATE_OVHD 2 /* Deflate overhead/packet */ - -static void *zalloc __P((void *, unsigned int items, unsigned int size)); -static void *zalloc_init __P((void *, unsigned int items, - unsigned int size)); -static void zfree __P((void *, void *ptr)); -static void *z_comp_alloc __P((unsigned char *options, int opt_len)); -static void *z_decomp_alloc __P((unsigned char *options, int opt_len)); -static void z_comp_free __P((void *state)); -static void z_decomp_free __P((void *state)); -static int z_comp_init __P((void *state, unsigned char *options, - int opt_len, - int unit, int hdrlen, int debug)); -static int z_decomp_init __P((void *state, unsigned char *options, - int opt_len, - int unit, int hdrlen, int mru, int debug)); -static int z_compress __P((void *state, unsigned char *rptr, - unsigned char *obuf, - int isize, int osize)); -static void z_incomp __P((void *state, unsigned char *ibuf, int icnt)); -static int z_decompress __P((void *state, unsigned char *ibuf, - int isize, unsigned char *obuf, int osize)); -static void z_comp_reset __P((void *state)); -static void z_decomp_reset __P((void *state)); -static void z_comp_stats __P((void *state, struct compstat *stats)); - -struct chunk_header { - int valloced; /* allocated with valloc, not kmalloc */ - int guard; /* check for overwritten header */ -}; - -#define GUARD_MAGIC 0x77a8011a -#define MIN_VMALLOC 2048 /* use kmalloc for blocks < this */ - -/* - * Space allocation and freeing routines for use by zlib routines. - */ -void zfree(void *arg, void *ptr) -{ - struct chunk_header *hdr = ((struct chunk_header *)ptr) - 1; - - if (hdr->guard != GUARD_MAGIC) { - printk(KERN_WARNING "zfree: header corrupted (%x %x) at %p\n", - hdr->valloced, hdr->guard, hdr); - return; - } - if (hdr->valloced) - vfree(hdr); - else - kfree(hdr); -} - -void * -zalloc(arg, items, size) - void *arg; - unsigned int items, size; -{ - struct chunk_header *hdr; - unsigned nbytes; - - nbytes = items * size + sizeof(*hdr); - hdr = kmalloc(nbytes, GFP_ATOMIC); - if (hdr == 0) - return 0; - hdr->valloced = 0; - hdr->guard = GUARD_MAGIC; - return (void *) (hdr + 1); -} - -void * zalloc_init(void *arg, unsigned int items, unsigned int size) -{ - struct chunk_header *hdr; - unsigned nbytes; - - nbytes = items * size + sizeof(*hdr); - if (nbytes >= MIN_VMALLOC) - hdr = vmalloc(nbytes); - else - hdr = kmalloc(nbytes, GFP_KERNEL); - if (hdr == 0) - return 0; - hdr->valloced = nbytes >= MIN_VMALLOC; - hdr->guard = GUARD_MAGIC; - return (void *) (hdr + 1); -} - -static void -z_comp_free(arg) - void *arg; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - if (state) { - deflateEnd(&state->strm); - kfree(state); - MOD_DEC_USE_COUNT; - } -} - -/* - * Allocate space for a compressor. - */ -static void * -z_comp_alloc(options, opt_len) - unsigned char *options; - int opt_len; -{ - struct irda_deflate_state *state; - int w_size; - - if (opt_len != CILEN_DEFLATE - || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) - || options[1] != CILEN_DEFLATE - || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL - || options[3] != DEFLATE_CHK_SEQUENCE) - return NULL; - w_size = DEFLATE_SIZE(options[2]); - w_size = MAX_WBITS; - if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) - return NULL; - - state = (struct irda_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); - if (state == NULL) - return NULL; - - MOD_INC_USE_COUNT; - memset (state, 0, sizeof (struct irda_deflate_state)); - state->strm.next_in = NULL; - state->strm.zalloc = zalloc_init; - state->strm.zfree = zfree; - state->w_size = w_size; - - if (deflateInit2(&state->strm, Z_DEFAULT_COMPRESSION, - DEFLATE_METHOD_VAL, -w_size, 8, Z_DEFAULT_STRATEGY) - != Z_OK) - goto out_free; - state->strm.zalloc = zalloc; - return (void *) state; - -out_free: - z_comp_free(state); - MOD_DEC_USE_COUNT; - return NULL; -} - -static int -z_comp_init(arg, options, opt_len, unit, hdrlen, debug) - void *arg; - unsigned char *options; - int opt_len, unit, hdrlen, debug; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - if (opt_len < CILEN_DEFLATE - || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) - || options[1] != CILEN_DEFLATE - || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL - || DEFLATE_SIZE(options[2]) != state->w_size - || options[3] != DEFLATE_CHK_SEQUENCE) - return 0; - - state->seqno = 0; - state->unit = unit; - state->debug = debug; - - deflateReset(&state->strm); - - return 1; -} - -static void z_comp_reset(void *arg) -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - state->seqno = 0; - deflateReset(&state->strm); -} - -int -z_compress(arg, rptr, obuf, isize, osize) - void *arg; - unsigned char *rptr; /* uncompressed packet (in) */ - unsigned char *obuf; /* compressed packet (out) */ - int isize, osize; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - int r, olen, oavail; - - olen = 0; - - /* Don't generate compressed packets which are larger than - the uncompressed packet. */ - if (osize > isize) - osize = isize; - - state->strm.next_out = obuf; - state->strm.avail_out = oavail = osize; - - state->strm.next_in = rptr; - state->strm.avail_in = isize; - - for (;;) { - r = deflate(&state->strm, Z_PACKET_FLUSH); - if (r != Z_OK) { - if (state->debug) - printk(KERN_ERR - "z_compress: deflate returned %d\n", r); - break; - } - if (state->strm.avail_out == 0) { - olen += oavail; - state->strm.next_out = NULL; - state->strm.avail_out = oavail = 1000000; - } else { - break; /* all done */ - } - } - olen += oavail - state->strm.avail_out; - - /* - * See if we managed to reduce the size of the packet. - */ - if (olen < isize) { - state->stats.comp_bytes += olen; - state->stats.comp_packets++; - } else { - state->stats.inc_bytes += isize; - state->stats.inc_packets++; - olen = 0; - } - state->stats.unc_bytes += isize; - state->stats.unc_packets++; - - return olen; -} - -static void -z_comp_stats(arg, stats) - void *arg; - struct compstat *stats; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - *stats = state->stats; -} - -static void z_decomp_free(void *arg) -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - if (state) { - inflateEnd(&state->strm); - kfree(state); - MOD_DEC_USE_COUNT; - } -} - -/* - * Allocate space for a decompressor. - */ -static void * -z_decomp_alloc(options, opt_len) - unsigned char *options; - int opt_len; -{ - struct irda_deflate_state *state; - int w_size; - - if (opt_len != CILEN_DEFLATE - || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) - || options[1] != CILEN_DEFLATE - || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL - || options[3] != DEFLATE_CHK_SEQUENCE) - return NULL; - w_size = DEFLATE_SIZE(options[2]); - w_size = MAX_WBITS; - if (w_size < DEFLATE_MIN_SIZE || w_size > DEFLATE_MAX_SIZE) - return NULL; - - state = (struct irda_deflate_state *) kmalloc(sizeof(*state), GFP_KERNEL); - if (state == NULL) - return NULL; - - MOD_INC_USE_COUNT; - memset (state, 0, sizeof (struct irda_deflate_state)); - state->w_size = w_size; - state->strm.next_out = NULL; - state->strm.zalloc = zalloc_init; - state->strm.zfree = zfree; - - if (inflateInit2(&state->strm, -w_size) != Z_OK) - goto out_free; - state->strm.zalloc = zalloc; - return (void *) state; - -out_free: - z_decomp_free(state); - MOD_DEC_USE_COUNT; - return NULL; -} - -static int -z_decomp_init(arg, options, opt_len, unit, hdrlen, mru, debug) - void *arg; - unsigned char *options; - int opt_len, unit, hdrlen, mru, debug; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - if (opt_len < CILEN_DEFLATE - || (options[0] != CI_DEFLATE && options[0] != CI_DEFLATE_DRAFT) - || options[1] != CILEN_DEFLATE - || DEFLATE_METHOD(options[2]) != DEFLATE_METHOD_VAL - || DEFLATE_SIZE(options[2]) != state->w_size - || options[3] != DEFLATE_CHK_SEQUENCE) - return 0; - - state->seqno = 0; - state->unit = unit; - state->debug = debug; - state->mru = mru; - - inflateReset(&state->strm); - - return 1; -} - -static void z_decomp_reset(void *arg) -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - - state->seqno = 0; - inflateReset(&state->strm); -} - -/* - * Decompress a Deflate-compressed packet. - * - * Because of patent problems, we return DECOMP_ERROR for errors - * found by inspecting the input data and for system problems, but - * DECOMP_FATALERROR for any errors which could possibly be said to - * be being detected "after" decompression. For DECOMP_ERROR, - * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be - * infringing a patent of Motorola's if we do, so we take CCP down - * instead. - * - * Given that the frame has the correct sequence number and a good FCS, - * errors such as invalid codes in the input most likely indicate a - * bug, so we return DECOMP_FATALERROR for them in order to turn off - * compression, even though they are detected by inspecting the input. - */ -int -z_decompress(arg, ibuf, isize, obuf, osize) - void *arg; - unsigned char *ibuf; - int isize; - unsigned char *obuf; - int osize; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - int olen, r; - int overflow; - unsigned char overflow_buf[1]; - - if (isize <= DEFLATE_OVHD) { - if (state->debug) - printk(KERN_DEBUG "z_decompress%d: short pkt (%d)\n", - state->unit, isize); - return DECOMP_ERROR; - } - - /* - * Set up to call inflate. - */ - state->strm.next_in = ibuf; - state->strm.avail_in = isize; - state->strm.next_out = obuf; - state->strm.avail_out = osize; - overflow = 0; - - /* - * Call inflate, supplying more input or output as needed. - */ - for (;;) { - r = inflate(&state->strm, Z_PACKET_FLUSH); - if (r != Z_OK) { - if (state->debug) - printk(KERN_DEBUG "z_decompress%d: inflate returned %d (%s)\n", - state->unit, r, (state->strm.msg? state->strm.msg: "")); - return DECOMP_FATALERROR; - } - if (state->strm.avail_out != 0) - break; /* all done */ - - if (!overflow) { - /* - * We've filled up the output buffer; the only way to - * find out whether inflate has any more characters - * left is to give it another byte of output space. - */ - state->strm.next_out = overflow_buf; - state->strm.avail_out = 1; - overflow = 1; - } else { - if (state->debug) - printk(KERN_DEBUG "z_decompress%d: ran out of mru\n", - state->unit); - return DECOMP_FATALERROR; - } - } - - olen = osize + overflow - state->strm.avail_out; - state->stats.unc_bytes += olen; - state->stats.unc_packets++; - state->stats.comp_bytes += isize; - state->stats.comp_packets++; - - return olen; -} - -/* - * Incompressible data has arrived - add it to the history. - */ -static void -z_incomp(arg, ibuf, icnt) - void *arg; - unsigned char *ibuf; - int icnt; -{ - struct irda_deflate_state *state = (struct irda_deflate_state *) arg; - int r; - - /* - * Check that the protocol is one we handle. - */ - - /* - * We start at the either the 1st or 2nd byte of the protocol field, - * depending on whether the protocol value is compressible. - */ - state->strm.next_in = ibuf; - state->strm.avail_in = icnt; - - r = inflateIncomp(&state->strm); - if (r != Z_OK) { - /* gak! */ - if (state->debug) { - printk(KERN_DEBUG "z_incomp%d: inflateIncomp returned %d (%s)\n", - state->unit, r, (state->strm.msg? state->strm.msg: "")); - } - return; - } - - /* - * Update stats. - */ - state->stats.inc_bytes += icnt; - state->stats.inc_packets++; - state->stats.unc_bytes += icnt; - state->stats.unc_packets++; -} - -/************************************************************* - * Module interface table - *************************************************************/ - -/* These are in ppp.c */ -extern int irda_register_compressor (struct compressor *cp); -extern void irda_unregister_compressor (struct compressor *cp); - -/* - * Procedures exported to if_ppp.c. - */ -static struct compressor irda_deflate = { - CI_DEFLATE, /* compress_proto */ - z_comp_alloc, /* comp_alloc */ - z_comp_free, /* comp_free */ - z_comp_init, /* comp_init */ - z_comp_reset, /* comp_reset */ - z_compress, /* compress */ - z_comp_stats, /* comp_stat */ - z_decomp_alloc, /* decomp_alloc */ - z_decomp_free, /* decomp_free */ - z_decomp_init, /* decomp_init */ - z_decomp_reset, /* decomp_reset */ - z_decompress, /* decompress */ - z_incomp, /* incomp */ - z_comp_stats, /* decomp_stat */ -}; - -static struct compressor irda_deflate_draft = { - CI_DEFLATE_DRAFT, /* compress_proto */ - z_comp_alloc, /* comp_alloc */ - z_comp_free, /* comp_free */ - z_comp_init, /* comp_init */ - z_comp_reset, /* comp_reset */ - z_compress, /* compress */ - z_comp_stats, /* comp_stat */ - z_decomp_alloc, /* decomp_alloc */ - z_decomp_free, /* decomp_free */ - z_decomp_init, /* decomp_init */ - z_decomp_reset, /* decomp_reset */ - z_decompress, /* decompress */ - z_incomp, /* incomp */ - z_comp_stats, /* decomp_stat */ -}; - -int __init irda_deflate_init(void) -{ - int answer = irda_register_compressor ( &irda_deflate); - if (answer == 0) - printk (KERN_INFO - "IrDA Deflate Compression module registered\n"); - irda_register_compressor( &irda_deflate_draft); - return answer; -} - -void irda_deflate_cleanup(void) -{ - - irda_unregister_compressor (&irda_deflate); - irda_unregister_compressor (&irda_deflate_draft); -} - -#ifdef MODULE -/************************************************************* - * Module support routines - *************************************************************/ - -int init_module(void) -{ - return irda_deflate_init(); -} - -void -cleanup_module(void) -{ - if (MOD_IN_USE) - printk (KERN_INFO - "Deflate Compression module busy, remove delayed\n"); - else { - irda_deflate_cleanup(); - } -} -#endif diff -urpN linux-2.2.18-23/net/irda/discovery.c linux/net/irda/discovery.c --- linux-2.2.18-23/net/irda/discovery.c Thu May 4 02:16:53 2000 +++ linux/net/irda/discovery.c Tue Nov 28 19:53:11 2000 @@ -43,13 +43,25 @@ * * Add a new discovery to the cachelog, and remove any old discoveries * from the same device + * + * Note : we try to preserve the time this device was *first* discovered + * (as opposed to the time of last discovery used for cleanup). This is + * used by clients waiting for discovery events to tell if the device + * discovered is "new" or just the same old one. They can't rely there + * on a binary flag (new/old), because not all discovery events are + * propagated to them, and they might not always listen, so they would + * miss some new devices popping up... + * Jean II */ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) { discovery_t *discovery, *node; unsigned long flags; - spin_lock_irqsave(&irlmp->lock, flags); + /* Set time of first discovery if node is new (see below) */ + new->first_timestamp = new->timestamp; + + spin_lock_irqsave(&irlmp->log_lock, flags); /* * Remove all discoveries of devices that has previously been @@ -59,27 +71,31 @@ void irlmp_add_discovery(hashbin_t *cach */ discovery = (discovery_t *) hashbin_get_first(cachelog); while (discovery != NULL ) { - node = discovery; + node = discovery; - /* Be sure to stay one item ahead */ - discovery = (discovery_t *) hashbin_get_next(cachelog); - - if ((node->daddr == new->daddr) || - (strcmp(node->nickname, new->nickname) == 0)) - { - /* This discovery is a previous discovery - * from the same device, so just remove it - */ - hashbin_remove(cachelog, node->daddr, NULL); - kfree(node); - } - } + /* Be sure to stay one item ahead */ + discovery = (discovery_t *) hashbin_get_next(cachelog); + if ((node->saddr == new->saddr) && + ((node->daddr == new->daddr) || + (strcmp(node->nickname, new->nickname) == 0))) + { + /* This discovery is a previous discovery + * from the same device, so just remove it + */ + hashbin_remove_this(cachelog, (irda_queue_t *) node); + /* Check if hints bits have changed */ + if(node->hints.word == new->hints.word) + /* Set time of first discovery for this node */ + new->first_timestamp = node->first_timestamp; + kfree(node); + } + } /* Insert the new and updated version */ - hashbin_insert(cachelog, (queue_t *) new, new->daddr, NULL); + hashbin_insert(cachelog, (irda_queue_t *) new, new->daddr, NULL); - spin_unlock_irqrestore(&irlmp->lock, flags); + spin_unlock_irqrestore(&irlmp->log_lock, flags); } /* @@ -120,13 +136,18 @@ void irlmp_add_discovery_log(hashbin_t * * * Go through all discoveries and expire all that has stayed to long * + * Note : this assume that IrLAP won't change its saddr, which + * currently is a valid assumption... */ void irlmp_expire_discoveries(hashbin_t *log, __u32 saddr, int force) { discovery_t *discovery, *curr; + unsigned long flags; IRDA_DEBUG(4, __FUNCTION__ "()\n"); + spin_lock_irqsave(&irlmp->log_lock, flags); + discovery = (discovery_t *) hashbin_get_first(log); while (discovery != NULL) { curr = discovery; @@ -135,14 +156,20 @@ void irlmp_expire_discoveries(hashbin_t discovery = (discovery_t *) hashbin_get_next(log); /* Test if it's time to expire this discovery */ - if ((curr->saddr == saddr) && (force || - ((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT))) + if ((curr->saddr == saddr) && + (force || + ((jiffies - curr->timestamp) > DISCOVERY_EXPIRE_TIMEOUT))) { - curr = hashbin_remove(log, curr->daddr, NULL); + /* Tell IrLMP and registered clients about it */ + irlmp_discovery_expiry(curr); + /* Remove it from the log */ + curr = hashbin_remove_this(log, (irda_queue_t *) curr); if (curr) kfree(curr); } } + + spin_unlock_irqrestore(&irlmp->log_lock, flags); } /* @@ -169,6 +196,75 @@ void irlmp_dump_discoveries(hashbin_t *l } /* + * Function irlmp_copy_discoveries (log, pn, mask) + * + * Copy all discoveries in a buffer + * + * This function implement a safe way for lmp clients to access the + * discovery log. The basic problem is that we don't want the log + * to change (add/remove) while the client is reading it. If the + * lmp client manipulate directly the hashbin, he is sure to get + * into troubles... + * The idea is that we copy all the current discovery log in a buffer + * which is specific to the client and pass this copy to him. As we + * do this operation with the spinlock grabbed, we are safe... + * Note : we don't want those clients to grab the spinlock, because + * we have no control on how long they will hold it... + * Note : we choose to copy the log in "struct irda_device_info" to + * save space... + * Note : the client must kfree himself() the log... + * Jean II + */ +struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, __u16 mask) +{ + discovery_t * discovery; + unsigned long flags; + struct irda_device_info * buffer; + int i = 0; + int n; + + ASSERT(pn != NULL, return NULL;); + + /* Check if log is empty */ + if(log == NULL) + return NULL; + + /* Save spin lock - spinlock should be discovery specific */ + spin_lock_irqsave(&irlmp->log_lock, flags); + + /* Create the client specific buffer */ + n = HASHBIN_GET_SIZE(log); + buffer = kmalloc(n * sizeof(struct irda_device_info), GFP_ATOMIC); + if (buffer == NULL) { + spin_unlock_irqrestore(&irlmp->log_lock, flags); + return NULL; + } + + discovery = (discovery_t *) hashbin_get_first(log); + while ((discovery != NULL) && (i < n)) { + /* Mask out the ones we don't want */ + if (discovery->hints.word & mask) { + /* Copy discovery information */ + buffer[i].saddr = discovery->saddr; + buffer[i].daddr = discovery->daddr; + buffer[i].charset = discovery->charset; + buffer[i].hints[0] = discovery->hints.byte[0]; + buffer[i].hints[1] = discovery->hints.byte[1]; + strncpy(buffer[i].info, discovery->nickname, + NICKNAME_MAX_LEN); + i++; + } + discovery = (discovery_t *) hashbin_get_next(log); + } + + spin_unlock_irqrestore(&irlmp->log_lock, flags); + + /* Get the actual number of device in the buffer and return */ + *pn = i; + return(buffer); +} + +/* * Function irlmp_find_device (name, saddr) * * Look through the discovery log at each of the links and try to find @@ -180,7 +276,7 @@ __u32 irlmp_find_device(hashbin_t *cache unsigned long flags; discovery_t *d; - spin_lock_irqsave(&irlmp->lock, flags); + spin_lock_irqsave(&irlmp->log_lock, flags); /* Look at all discoveries for that link */ d = (discovery_t *) hashbin_get_first(cachelog); @@ -192,13 +288,13 @@ __u32 irlmp_find_device(hashbin_t *cache if (strcmp(name, d->nickname) == 0) { *saddr = d->saddr; - spin_unlock_irqrestore(&irlmp->lock, flags); + spin_unlock_irqrestore(&irlmp->log_lock, flags); return d->daddr; } d = (discovery_t *) hashbin_get_next(cachelog); } - spin_unlock_irqrestore(&irlmp->lock, flags); + spin_unlock_irqrestore(&irlmp->log_lock, flags); return 0; } @@ -209,23 +305,23 @@ __u32 irlmp_find_device(hashbin_t *cache * Print discovery information in /proc file system * */ -int discovery_proc_read(char *buf, char **start, off_t offset, int len, +int discovery_proc_read(char *buf, char **start, off_t offset, int length, int unused) { discovery_t *discovery; unsigned long flags; hashbin_t *cachelog = irlmp_get_cachelog(); + int len = 0; if (!irlmp) return len; len = sprintf(buf, "IrLMP: Discovery log:\n\n"); - save_flags(flags); - cli(); - + spin_lock_irqsave(&irlmp->log_lock, flags); + discovery = (discovery_t *) hashbin_get_first(cachelog); - while ( discovery != NULL) { + while (( discovery != NULL) && (len < length)) { len += sprintf(buf+len, "nickname: %s,", discovery->nickname); len += sprintf(buf+len, " hint: 0x%02x%02x", @@ -266,7 +362,7 @@ int discovery_proc_read(char *buf, char discovery = (discovery_t *) hashbin_get_next(cachelog); } - restore_flags(flags); + spin_unlock_irqrestore(&irlmp->log_lock, flags); return len; } diff -urpN linux-2.2.18-23/net/irda/ircomm/ircomm_core.c linux/net/irda/ircomm/ircomm_core.c --- linux-2.2.18-23/net/irda/ircomm/ircomm_core.c Thu May 4 02:16:54 2000 +++ linux/net/irda/ircomm/ircomm_core.c Tue Nov 28 17:58:08 2000 @@ -35,7 +35,6 @@ #include #include -#include #include #include #include @@ -128,7 +127,7 @@ struct ircomm_cb *ircomm_open(notify_t * self->service_type = service_type; self->line = line; - hashbin_insert(ircomm, (queue_t *) self, line, NULL); + hashbin_insert(ircomm, (irda_queue_t *) self, line, NULL); ircomm_next_state(self, IRCOMM_IDLE); @@ -514,6 +513,9 @@ int ircomm_proc_read(char *buf, char **s #endif /* CONFIG_PROC_FS */ #ifdef MODULE +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("IrCOMM protocol"); + int init_module(void) { return ircomm_init(); diff -urpN linux-2.2.18-23/net/irda/ircomm/ircomm_tty.c linux/net/irda/ircomm/ircomm_tty.c --- linux-2.2.18-23/net/irda/ircomm/ircomm_tty.c Wed Jun 7 23:26:44 2000 +++ linux/net/irda/ircomm/ircomm_tty.c Tue Nov 28 17:58:29 2000 @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -69,9 +68,10 @@ static int ircomm_tty_control_indication struct sk_buff *skb); static void ircomm_tty_flow_indication(void *instance, void *sap, LOCAL_FLOW cmd); +#ifdef CONFIG_PROC_FS static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused); - +#endif /* CONFIG_PROC_FS */ static struct tty_driver driver; static int ircomm_tty_refcount; /* If we manage several devices */ @@ -98,7 +98,11 @@ int __init ircomm_tty_init(void) memset(&driver, 0, sizeof(struct tty_driver)); driver.magic = TTY_DRIVER_MAGIC; driver.driver_name = "ircomm"; +#ifdef CONFIG_DEVFS_FS + driver.name = "ircomm%d"; +#else driver.name = "ircomm"; +#endif driver.major = IRCOMM_TTY_MAJOR; driver.minor_start = IRCOMM_TTY_MINOR; driver.num = IRCOMM_TTY_PORTS; @@ -126,8 +130,9 @@ int __init ircomm_tty_init(void) driver.start = ircomm_tty_start; driver.hangup = ircomm_tty_hangup; driver.wait_until_sent = ircomm_tty_wait_until_sent; +#ifdef CONFIG_PROC_FS driver.read_proc = ircomm_tty_read_proc; - +#endif /* CONFIG_PROC_FS */ if (tty_register_driver(&driver)) { ERROR(__FUNCTION__ "Couldn't register serial driver\n"); return -1; @@ -430,7 +435,7 @@ static int ircomm_tty_open(struct tty_st tty->termios->c_oflag = 0; /* Insert into hash */ - hashbin_insert(ircomm_tty, (queue_t *) self, line, NULL); + hashbin_insert(ircomm_tty, (irda_queue_t *) self, line, NULL); } self->open_count++; @@ -1320,6 +1325,7 @@ static int ircomm_tty_line_info(struct i * * */ +#ifdef CONFIG_PROC_FS static int ircomm_tty_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *unused) { @@ -1350,9 +1356,12 @@ done: *start = buf + (offset-begin); return ((len < begin+count-offset) ? len : begin+count-offset); } - +#endif /* CONFIG_PROC_FS */ #ifdef MODULE +MODULE_AUTHOR("Dag Brattli "); +MODULE_DESCRIPTION("IrCOMM serial TTY driver"); + int init_module(void) { return ircomm_tty_init(); diff -urpN linux-2.2.18-23/net/irda/ircomm/ircomm_tty_attach.c linux/net/irda/ircomm/ircomm_tty_attach.c --- linux-2.2.18-23/net/irda/ircomm/ircomm_tty_attach.c Thu May 4 02:16:54 2000 +++ linux/net/irda/ircomm/ircomm_tty_attach.c Sun Nov 26 16:38:49 2000 @@ -46,7 +46,8 @@ #include static void ircomm_tty_ias_register(struct ircomm_tty_cb *self); -static void ircomm_tty_discovery_indication(discovery_t *discovery); +static void ircomm_tty_discovery_indication(discovery_t *discovery, + void *priv); static void ircomm_tty_getvalue_confirm(int result, __u16 obj_id, struct ias_value *value, void *priv); void ircomm_tty_start_watchdog_timer(struct ircomm_tty_cb *self, int timeout); @@ -213,7 +214,7 @@ static void ircomm_tty_ias_register(stru /* Register IrLPT with LM-IAS */ self->obj = irias_new_object("IrLPT", IAS_IRLPT_ID); irias_add_integer_attrib(self->obj, "IrDA:IrLMP:LsapSel", - self->slsap_sel); + self->slsap_sel, IAS_KERNEL_ATTR); irias_insert_object(self->obj); } else { hints = irlmp_service_to_hint(S_COMM); @@ -221,7 +222,7 @@ static void ircomm_tty_ias_register(stru /* Register IrCOMM with LM-IAS */ self->obj = irias_new_object("IrDA:IrCOMM", IAS_IRCOMM_ID); irias_add_integer_attrib(self->obj, "IrDA:TinyTP:LsapSel", - self->slsap_sel); + self->slsap_sel, IAS_KERNEL_ATTR); /* Code the parameters into the buffer */ irda_param_pack(oct_seq, "bbbbbb", @@ -229,12 +230,13 @@ static void ircomm_tty_ias_register(stru IRCOMM_PORT_TYPE, 1, IRCOMM_SERIAL); /* Register parameters with LM-IAS */ - irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6); + irias_add_octseq_attrib(self->obj, "Parameters", oct_seq, 6, + IAS_KERNEL_ATTR); irias_insert_object(self->obj); } self->skey = irlmp_register_service(hints); self->ckey = irlmp_register_client( - hints, ircomm_tty_discovery_indication, NULL); + hints, ircomm_tty_discovery_indication, NULL, (void *) self); } /* @@ -302,7 +304,8 @@ int ircomm_tty_send_initial_parameters(s * device it is, and which services it has. * */ -static void ircomm_tty_discovery_indication(discovery_t *discovery) +static void ircomm_tty_discovery_indication(discovery_t *discovery, + void *priv) { struct ircomm_tty_cb *self; struct ircomm_tty_info info; diff -urpN linux-2.2.18-23/net/irda/ircomm/ircomm_tty_ioctl.c linux/net/irda/ircomm/ircomm_tty_ioctl.c --- linux-2.2.18-23/net/irda/ircomm/ircomm_tty_ioctl.c Thu May 4 02:16:54 2000 +++ linux/net/irda/ircomm/ircomm_tty_ioctl.c Tue Nov 28 17:58:56 2000 @@ -39,8 +39,6 @@ #include #include -#include - #include #include #include diff -urpN linux-2.2.18-23/net/irda/irda_device.c linux/net/irda/irda_device.c --- linux-2.2.18-23/net/irda/irda_device.c Thu Nov 23 14:46:43 2000 +++ linux/net/irda/irda_device.c Tue Nov 28 19:53:11 2000 @@ -58,6 +58,8 @@ extern int irtty_init(void); extern int nsc_ircc_init(void); extern int ircc_init(void); +extern int toshoboe_init(void); +extern int litelink_init(void); extern int w83977af_init(void); extern int esi_init(void); extern int tekram_init(void); @@ -185,7 +187,7 @@ void irda_device_set_media_busy(struct d IRDA_DEBUG( 4, "Media busy!\n"); } else { self->media_busy = FALSE; - del_timer(&self->media_busy_timer); + irlap_stop_mbusy_timer(self); } } @@ -241,8 +243,6 @@ int irda_device_is_receiving(struct devi struct if_irda_req req; int ret; - IRDA_DEBUG(2, __FUNCTION__ "()\n"); - if (!dev->do_ioctl) { ERROR(__FUNCTION__ "(), do_ioctl not impl. by " "device driver\n"); @@ -380,7 +380,7 @@ struct irda_task *irda_task_execute(void init_timer(&task->timer); /* Register task */ - hashbin_insert(tasks, (queue_t *) task, (int) task, NULL); + hashbin_insert(tasks, (irda_queue_t *) task, (int) task, NULL); /* No time to waste, so lets get going! */ ret = irda_task_kick(task); @@ -523,7 +523,7 @@ int irda_device_register_dongle(struct d } /* Insert IrDA dongle into hashbin */ - hashbin_insert(dongles, (queue_t *) new, new->type, NULL); + hashbin_insert(dongles, (irda_queue_t *) new, new->type, NULL); return 0; } diff -urpN linux-2.2.18-23/net/irda/iriap.c linux/net/irda/iriap.c --- linux-2.2.18-23/net/irda/iriap.c Thu May 4 02:16:54 2000 +++ linux/net/irda/iriap.c Tue Nov 28 19:53:11 2000 @@ -34,7 +34,6 @@ #include #include -#include #include #include #include @@ -107,7 +106,7 @@ int __init iriap_init(void) /* Register the Device object with LM-IAS */ obj = irias_new_object("Device", IAS_DEVICE_ID); - irias_add_string_attrib(obj, "DeviceName", "Linux"); + irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR); oct_seq[0] = 0x01; /* Version 1 */ oct_seq[1] = 0x00; /* IAS support bits */ @@ -115,7 +114,8 @@ int __init iriap_init(void) #ifdef CONFIG_IRDA_ULTRA oct_seq[2] |= 0x04; /* Connectionless Data support */ #endif - irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3); + irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3, + IAS_KERNEL_ATTR); irias_insert_object(obj); /* @@ -179,7 +179,7 @@ struct iriap_cb *iriap_open(__u8 slsap_s init_timer(&self->watchdog_timer); - hashbin_insert(iriap, (queue_t *) self, (int) self, NULL); + hashbin_insert(iriap, (irda_queue_t *) self, (int) self, NULL); /* Initialize state machines */ iriap_next_client_state(self, S_DISCONNECT); @@ -289,7 +289,7 @@ static void iriap_disconnect_indication( del_timer(&self->watchdog_timer); if (self->mode == IAS_CLIENT) { - IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n"); + IRDA_DEBUG(0, __FUNCTION__ "(), disconnect as client\n"); iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION, @@ -866,7 +866,7 @@ static int iriap_data_indication(void *i iriap_getvaluebyclass_confirm(self, skb); break; case IAS_CLASS_UNKNOWN: - WARNING(__FUNCTION__ "(), No such class!\n"); + IRDA_DEBUG(1, __FUNCTION__ "(), No such class!\n"); /* Finished, close connection! */ iriap_disconnect_request(self); @@ -880,7 +880,7 @@ static int iriap_data_indication(void *i dev_kfree_skb(skb); break; case IAS_ATTRIB_UNKNOWN: - WARNING(__FUNCTION__ "(), No such attribute!\n"); + IRDA_DEBUG(1, __FUNCTION__ "(), No such attribute!\n"); /* Finished, close connection! */ iriap_disconnect_request(self); @@ -889,7 +889,7 @@ static int iriap_data_indication(void *i * no to use self anymore after calling confirm */ if (self->confirm) - self->confirm(IAS_CLASS_UNKNOWN, 0, NULL, + self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL, self->priv); dev_kfree_skb(skb); break; diff -urpN linux-2.2.18-23/net/irda/irias_object.c linux/net/irda/irias_object.c --- linux-2.2.18-23/net/irda/irias_object.c Thu May 4 02:16:54 2000 +++ linux/net/irda/irias_object.c Tue Nov 28 19:53:11 2000 @@ -26,7 +26,6 @@ #include #include -#include #include hashbin_t *objects = NULL; @@ -148,6 +147,37 @@ int irias_delete_object(struct ias_objec } /* + * Function irias_delete_attrib (obj) + * + * Remove attribute from hashbin and, if it was the last attribute of + * the object, remove the object as well. + * + */ +int irias_delete_attrib(struct ias_object *obj, struct ias_attrib *attrib) +{ + struct ias_attrib *node; + + ASSERT(obj != NULL, return -1;); + ASSERT(obj->magic == IAS_OBJECT_MAGIC, return -1;); + ASSERT(attrib != NULL, return -1;); + + /* Remove atribute from object */ + node = hashbin_remove(obj->attribs, 0, attrib->name); + if (!node) + return 0; /* Already removed or non-existent */ + + /* Deallocate attribute */ + __irias_delete_attrib(node); + + /* Check if object has still some attributes */ + node = (struct ias_attrib *) hashbin_get_first(obj->attribs); + if (!node) + irias_delete_object(obj); + + return 0; +} + +/* * Function irias_insert_object (obj) * * Insert an object into the LM-IAS database @@ -158,7 +188,7 @@ void irias_insert_object(struct ias_obje ASSERT(obj != NULL, return;); ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); - hashbin_insert(objects, (queue_t *) obj, 0, obj->name); + hashbin_insert(objects, (irda_queue_t *) obj, 0, obj->name); } /* @@ -201,7 +231,8 @@ struct ias_attrib *irias_find_attrib(str * Add attribute to object * */ -void irias_add_attrib( struct ias_object *obj, struct ias_attrib *attrib) +void irias_add_attrib( struct ias_object *obj, struct ias_attrib *attrib, + int owner) { ASSERT(obj != NULL, return;); ASSERT(obj->magic == IAS_OBJECT_MAGIC, return;); @@ -209,7 +240,10 @@ void irias_add_attrib( struct ias_object ASSERT(attrib != NULL, return;); ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return;); - hashbin_insert(obj->attribs, (queue_t *) attrib, 0, attrib->name); + /* Set if attrib is owned by kernel or user space */ + attrib->value->owner = owner; + + hashbin_insert(obj->attribs, (irda_queue_t *) attrib, 0, attrib->name); } /* @@ -262,7 +296,8 @@ int irias_object_change_attribute(char * * Add an integer attribute to an LM-IAS object * */ -void irias_add_integer_attrib(struct ias_object *obj, char *name, int value) +void irias_add_integer_attrib(struct ias_object *obj, char *name, int value, + int owner) { struct ias_attrib *attrib; @@ -284,7 +319,7 @@ void irias_add_integer_attrib(struct ias /* Insert value */ attrib->value = irias_new_integer_value(value); - irias_add_attrib(obj, attrib); + irias_add_attrib(obj, attrib, owner); } /* @@ -295,7 +330,7 @@ void irias_add_integer_attrib(struct ias */ void irias_add_octseq_attrib(struct ias_object *obj, char *name, __u8 *octets, - int len) + int len, int owner) { struct ias_attrib *attrib; @@ -319,7 +354,7 @@ void irias_add_octseq_attrib(struct ias_ attrib->value = irias_new_octseq_value( octets, len); - irias_add_attrib(obj, attrib); + irias_add_attrib(obj, attrib, owner); } /* @@ -328,7 +363,8 @@ void irias_add_octseq_attrib(struct ias_ * Add a string attribute to an LM-IAS object * */ -void irias_add_string_attrib(struct ias_object *obj, char *name, char *value) +void irias_add_string_attrib(struct ias_object *obj, char *name, char *value, + int owner) { struct ias_attrib *attrib; @@ -351,7 +387,7 @@ void irias_add_string_attrib(struct ias_ attrib->value = irias_new_string_value(value); - irias_add_attrib(obj, attrib); + irias_add_attrib(obj, attrib, owner); } /* Binary files linux-2.2.18-23/net/irda/irlan/.irlan_eth.c.swp and linux/net/irda/irlan/.irlan_eth.c.swp differ diff -urpN linux-2.2.18-23/net/irda/irlan/irlan_client.c linux/net/irda/irlan/irlan_client.c --- linux-2.2.18-23/net/irda/irlan/irlan_client.c Wed Jun 7 23:26:44 2000 +++ linux/net/irda/irlan/irlan_client.c Sun Nov 26 22:26:44 2000 @@ -6,13 +6,13 @@ * Status: Experimental. * Author: Dag Brattli * Created at: Sun Aug 31 20:14:37 1997 - * Modified at: Fri Apr 21 14:57:47 2000 + * Modified at: Tue Dec 14 15:47:02 1999 * Modified by: Dag Brattli * Sources: skeleton.c by Donald Becker * slip.c by Laurence Culhane, * Fred N. van Kempen, * - * Copyright (c) 1998-2000 Dag Brattli , + * Copyright (c) 1998-1999 Dag Brattli , * All Rights Reserved. * * This program is free software; you can redistribute it and/or @@ -99,11 +99,11 @@ void irlan_client_start_kick_timer(struc /* * Function irlan_client_wakeup (self, saddr, daddr) * - * Wake up client. This function is called when a remote IrLAN device - * is discovered, or .. + * Wake up client + * */ void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr) -{ +{ IRDA_DEBUG(1, __FUNCTION__ "()\n"); ASSERT(self != NULL, return;); @@ -116,31 +116,24 @@ void irlan_client_wakeup(struct irlan_cb if ((self->client.state != IRLAN_IDLE) || (self->provider.access_type == ACCESS_DIRECT)) { - IRDA_DEBUG(0, __FUNCTION__ "(), already awake!\n"); - return; + IRDA_DEBUG(0, __FUNCTION__ "(), already awake!\n"); + return; } - /* Addresses may have changed! */ + /* Address may have changed! */ self->saddr = saddr; - self->daddr = daddr; -#if 0 - if (!self->dev.start) { - IRDA_DEBUG(0, __FUNCTION__ "(), not started yet\n"); - return; - } -#endif if (self->disconnect_reason == LM_USER_REQUEST) { - IRDA_DEBUG(0, __FUNCTION__ "(), still stopped by user\n"); - return; + IRDA_DEBUG(0, __FUNCTION__ "(), still stopped by user\n"); + return; } - + /* Open TSAPs */ irlan_client_open_ctrl_tsap(self); irlan_open_data_tsap(self); - - irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL); + irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL); + /* Start kick timer */ irlan_client_start_kick_timer(self, 2*HZ); } @@ -151,7 +144,7 @@ void irlan_client_wakeup(struct irlan_cb * Remote device with IrLAN server support discovered * */ -void irlan_client_discovery_indication(discovery_t *discovery) +void irlan_client_discovery_indication(discovery_t *discovery, void *priv) { struct irlan_cb *self; __u32 saddr, daddr; @@ -166,11 +159,11 @@ void irlan_client_discovery_indication(d /* Find instance */ self = (struct irlan_cb *) hashbin_get_first(irlan); - if (self) { + if (self) { ASSERT(self->magic == IRLAN_MAGIC, return;); - + IRDA_DEBUG(1, __FUNCTION__ "(), Found instance (%08x)!\n", - daddr); + daddr); irlan_client_wakeup(self, saddr, daddr); } @@ -424,9 +417,7 @@ static void irlan_check_response_param(s ASSERT(self != NULL, return;); ASSERT(self->magic == IRLAN_MAGIC, return;); - /* - * Media type - */ + /* Media type */ if (strcmp(param, "MEDIA") == 0) { if (strcmp(value, "802.3") == 0) self->media = MEDIA_802_3; @@ -462,9 +453,7 @@ static void irlan_check_response_param(s IRDA_DEBUG(2, __FUNCTION__ "(), unknown access type!\n"); } } - /* - * IRLAN version - */ + /* IRLAN version */ if (strcmp(param, "IRLAN_VER") == 0) { IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0], (__u8) value[1]); @@ -473,9 +462,7 @@ static void irlan_check_response_param(s self->version[1] = value[1]; return; } - /* - * Which remote TSAP to use for data channel - */ + /* Which remote TSAP to use for data channel */ if (strcmp(param, "DATA_CHAN") == 0) { self->dtsap_sel_data = value[0]; IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data); @@ -496,9 +483,7 @@ static void irlan_check_response_param(s self->client.max_frame); } - /* - * RECONNECT_KEY, in case the link goes down! - */ + /* RECONNECT_KEY, in case the link goes down! */ if (strcmp(param, "RECONNECT_KEY") == 0) { IRDA_DEBUG(4, "Got reconnect key: "); /* for (i = 0; i < val_len; i++) */ @@ -507,9 +492,7 @@ static void irlan_check_response_param(s self->client.key_len = val_len; IRDA_DEBUG(4, "\n"); } - /* - * FILTER_ENTRY, have we got an ethernet address? - */ + /* FILTER_ENTRY, have we got an ethernet address? */ if (strcmp(param, "FILTER_ENTRY") == 0) { bytes = value; IRDA_DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -531,7 +514,7 @@ void irlan_client_get_value_confirm(int { struct irlan_cb *self; - IRDA_DEBUG(4, __FUNCTION__ "()\n"); + IRDA_DEBUG(0, __FUNCTION__ "()\n"); ASSERT(priv != NULL, return;); @@ -553,6 +536,7 @@ void irlan_client_get_value_confirm(int switch (value->type) { case IAS_INTEGER: self->dtsap_sel_ctrl = value->t.integer; + IRDA_DEBUG(2, __FUNCTION__ "(), value=%d!\n", value->t.integer); if (value->t.integer != -1) { irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL, @@ -565,5 +549,6 @@ void irlan_client_get_value_confirm(int IRDA_DEBUG(2, __FUNCTION__ "(), unknown type!\n"); break; } + IRDA_DEBUG(2, __FUNCTION__ "(), Provider not available!\n"); irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL); } diff -urpN linux-2.2.18-23/net/irda/irlan/irlan_client_event.c linux/net/irda/irlan/irlan_client_event.c --- linux-2.2.18-23/net/irda/irlan/irlan_client_event.c Thu May 4 02:16:54 2000 +++ linux/net/irda/irlan/irlan_client_event.c Tue Nov 28 17:57:48 2000 @@ -27,7 +27,6 @@ #include #include -#include #include #include #include @@ -108,11 +107,10 @@ static int irlan_client_state_idle(struc self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self, irlan_client_get_value_confirm); /* Get some values from peer IAS */ + irlan_next_client_state(self, IRLAN_QUERY); iriap_getvaluebyclass_request(self->client.iriap, self->saddr, self->daddr, "IrLAN", "IrDA:TinyTP:LsapSel"); - - irlan_next_client_state(self, IRLAN_QUERY); break; case IRLAN_WATCHDOG_TIMEOUT: IRDA_DEBUG(2, __FUNCTION__ "(), IRLAN_WATCHDOG_TIMEOUT\n"); diff -urpN linux-2.2.18-23/net/irda/irlan/irlan_common.c linux/net/irda/irlan/irlan_common.c --- linux-2.2.18-23/net/irda/irlan/irlan_common.c Wed Jun 7 23:26:44 2