patch-2.3.4 linux/net/irda/irlan/irlan_provider.c
Next file: linux/net/irda/irlan/irlan_provider_event.c
Previous file: linux/net/irda/irlan/irlan_filter.c
Back to the patch index
Back to the overall index
- Lines: 212
- Date:
Sun May 30 10:27:04 1999
- Orig file:
v2.3.3/linux/net/irda/irlan/irlan_provider.c
- Orig date:
Sat Apr 24 17:50:06 1999
diff -u --recursive --new-file v2.3.3/linux/net/irda/irlan/irlan_provider.c linux/net/irda/irlan/irlan_provider.c
@@ -6,13 +6,14 @@
* Status: Experimental.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 31 20:14:37 1997
- * Modified at: Thu Apr 22 14:28:52 1999
+ * Modified at: Sun May 9 12:22:56 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
* Sources: skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
* slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
* Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
*
- * Copyright (c) 1998 Dag Brattli <dagb@cs.uit.no>, All Rights Reserved.
+ * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
+ * 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
@@ -31,6 +32,7 @@
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/init.h>
+#include <linux/random.h>
#include <asm/system.h>
#include <asm/bitops.h>
@@ -50,14 +52,20 @@
#include <net/irda/irlan_filter.h>
#include <net/irda/irlan_client.h>
+static void irlan_provider_connect_indication(void *instance, void *sap,
+ struct qos_info *qos,
+ __u32 max_sdu_size,
+ __u8 max_header_size,
+ struct sk_buff *skb);
+
/*
* Function irlan_provider_control_data_indication (handle, skb)
*
* This function gets the data that is received on the control channel
*
*/
-int irlan_provider_data_indication(void *instance, void *sap,
- struct sk_buff *skb)
+static int irlan_provider_data_indication(void *instance, void *sap,
+ struct sk_buff *skb)
{
struct irlan_cb *self;
__u8 code;
@@ -111,14 +119,17 @@
* Got connection from peer IrLAN layer
*
*/
-void irlan_provider_connect_indication(void *instance, void *sap,
- struct qos_info *qos,
- __u32 max_sdu_size, struct sk_buff *skb)
+static void irlan_provider_connect_indication(void *instance, void *sap,
+ struct qos_info *qos,
+ __u32 max_sdu_size,
+ __u8 max_header_size,
+ struct sk_buff *skb)
{
- struct irlan_cb *self, *entry, *new;
+ struct irlan_cb *self, *new;
struct tsap_cb *tsap;
+ __u32 saddr, daddr;
- DEBUG(2, __FUNCTION__ "()\n");
+ DEBUG(0, __FUNCTION__ "()\n");
self = (struct irlan_cb *) instance;
tsap = (struct tsap_cb *) sap;
@@ -126,34 +137,69 @@
ASSERT(self != NULL, return;);
ASSERT(self->magic == IRLAN_MAGIC, return;);
+ self->provider.max_sdu_size = max_sdu_size;
+ self->provider.max_header_size = max_header_size;
+
ASSERT(tsap == self->provider.tsap_ctrl,return;);
ASSERT(self->provider.state == IRLAN_IDLE, return;);
- /* Check if this provider is currently unused */
- if (self->daddr == DEV_ADDR_ANY) {
- /*
- * Rehash instance, now we have a client (daddr) to serve.
- */
- entry = hashbin_remove(irlan, self->daddr, NULL);
- ASSERT( entry == self, return;);
-
- self->daddr = irttp_get_daddr(tsap);
- DEBUG(2, __FUNCTION__ "(), daddr=%08x\n", self->daddr);
- hashbin_insert(irlan, (QUEUE*) self, self->daddr, NULL);
+ daddr = irttp_get_daddr(tsap);
+ saddr = irttp_get_saddr(tsap);
+
+ /* Check if we already dealing with this client or peer */
+ new = (struct irlan_cb *) hashbin_find(irlan, daddr, NULL);
+ if (new) {
+ ASSERT(new->magic == IRLAN_MAGIC, return;);
+ DEBUG(0, __FUNCTION__ "(), found instance!\n");
+
+ /* Update saddr, since client may have moved to a new link */
+ new->saddr = saddr;
+ DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", new->saddr);
+
+ /* Make sure that any old provider control TSAP is removed */
+ if ((new != self) && new->provider.tsap_ctrl) {
+ irttp_disconnect_request(new->provider.tsap_ctrl,
+ NULL, P_NORMAL);
+ irttp_close_tsap(new->provider.tsap_ctrl);
+ new->provider.tsap_ctrl = NULL;
+ }
} else {
- /*
- * If we already have the daddr set, this means that the
- * client must already have started (peer mode). We must
- * make sure that this connection attempt is from the same
- * device as the client is dealing with!
+ /* This must be the master instance, so start a new instance */
+ DEBUG(0, __FUNCTION__ "(), starting new provider!\n");
+
+ new = irlan_open(saddr, daddr, TRUE);
+ }
+
+ /*
+ * Check if the connection came in on the master server, or the
+ * slave server. If it came on the slave, then everything is
+ * really, OK (reconnect), if not we need to dup the connection and
+ * hand it over to the slave.
+ */
+ if (new != self) {
+
+ /* Now attach up the new "socket" */
+ new->provider.tsap_ctrl = irttp_dup(self->provider.tsap_ctrl,
+ new);
+ if (!new->provider.tsap_ctrl) {
+ DEBUG(0, __FUNCTION__ "(), dup failed!\n");
+ return;
+ }
+
+ /* new->stsap_sel = new->tsap->stsap_sel; */
+ new->dtsap_sel_ctrl = new->provider.tsap_ctrl->dtsap_sel;
+
+ /* Clean up the original one to keep it in listen state */
+ self->provider.tsap_ctrl->dtsap_sel = LSAP_ANY;
+ self->provider.tsap_ctrl->lsap->dlsap_sel = LSAP_ANY;
+ self->provider.tsap_ctrl->lsap->lsap_state = LSAP_DISCONNECTED;
+
+ /*
+ * Use the new instance from here instead of the master
+ * struct!
*/
- ASSERT(self->daddr == irttp_get_daddr(tsap), return;);
+ self = new;
}
-
- /* Update saddr, since client may have moved to a new link */
- self->saddr = irttp_get_saddr(tsap);
- DEBUG(2, __FUNCTION__ "(), saddr=%08x\n", self->saddr);
-
/* Check if network device has been registered */
if (!self->netdev_registered)
irlan_register_netdev(self);
@@ -165,9 +211,10 @@
* indication it needs to make progress. If the client is still in
* IDLE state, we must kick it to
*/
- if ((self->access_type == ACCESS_PEER) &&
- (self->client.state == IRLAN_IDLE))
+ if ((self->provider.access_type == ACCESS_PEER) &&
+ (self->client.state == IRLAN_IDLE)) {
irlan_client_wakeup(self, self->saddr, self->daddr);
+ }
}
/*
@@ -225,6 +272,9 @@
ret = irlan_provider_parse_command(self, CMD_OPEN_DATA_CHANNEL, skb);
+ /* Open data channel */
+ irlan_open_data_tsap(self);
+
return ret;
}
@@ -314,7 +364,7 @@
return;
/* Reserve space for TTP, LMP, and LAP header */
- skb_reserve(skb, TTP_HEADER+LMP_HEADER+LAP_HEADER);
+ skb_reserve(skb, self->provider.max_header_size);
skb_put(skb, 2);
switch (command) {
@@ -334,6 +384,7 @@
}
irlan_insert_short_param(skb, "IRLAN_VER", 0x0101);
break;
+
case CMD_GET_MEDIA_CHAR:
skb->data[0] = 0x00; /* Success */
skb->data[1] = 0x05; /* 5 parameters */
@@ -341,7 +392,7 @@
irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
- switch(self->access_type) {
+ switch (self->provider.access_type) {
case ACCESS_DIRECT:
irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
break;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)