patch-2.3.35 linux/net/irda/irlmp.c
Next file: linux/net/irda/irlmp_event.c
Previous file: linux/net/irda/irlap_frame.c
Back to the patch index
Back to the overall index
- Lines: 403
- Date:
Tue Dec 21 10:17:58 1999
- Orig file:
v2.3.34/linux/net/irda/irlmp.c
- Orig date:
Tue Nov 23 22:42:21 1999
diff -u --recursive --new-file v2.3.34/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
@@ -1,12 +1,12 @@
/*********************************************************************
*
* Filename: irlmp.c
- * Version: 0.9
+ * Version: 1.0
* Description: IrDA Link Management Protocol (LMP) layer
* Status: Stable.
* Author: Dag Brattli <dagb@cs.uit.no>
* Created at: Sun Aug 17 20:54:32 1997
- * Modified at: Sat Oct 9 17:00:49 1999
+ * Modified at: Thu Dec 16 22:59:40 1999
* Modified by: Dag Brattli <dagb@cs.uit.no>
*
* Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
@@ -90,7 +90,7 @@
irlmp->unconnected_lsaps = hashbin_new(HB_GLOBAL);
irlmp->cachelog = hashbin_new(HB_GLOBAL);
- irlmp->free_lsap_sel = 0x10; /* Servers use 0x00-0x0f */
+ irlmp->free_lsap_sel = 0x10; /* Reserved 0x00-0x0f */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
irlmp->cache.valid = FALSE;
#endif
@@ -134,7 +134,7 @@
* Register with IrLMP and create a local LSAP,
* returns handle to LSAP.
*/
-struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify)
+struct lsap_cb *irlmp_open_lsap(__u8 slsap_sel, notify_t *notify, __u8 pid)
{
struct lsap_cb *self;
@@ -142,40 +142,33 @@
ASSERT(irlmp != NULL, return NULL;);
ASSERT(irlmp->magic == LMP_MAGIC, return NULL;);
- /*
- * Does the client care which Source LSAP selector it gets?
- */
+ /* Does the client care which Source LSAP selector it gets? */
if (slsap_sel == LSAP_ANY) {
- /*
- * Find unused LSAP
- */
slsap_sel = irlmp_find_free_slsap();
- if ( slsap_sel == 0)
- return NULL;
- } else {
- /*
- * Client wants specific LSAP, so check if it's already
- * in use
- */
- if (irlmp_slsap_inuse(slsap_sel)) {
+ if (!slsap_sel)
return NULL;
- }
- }
+ } else if (irlmp_slsap_inuse(slsap_sel))
+ return NULL;
- /*
- * Allocate new instance of a LSAP connection
- */
+ /* Allocate new instance of a LSAP connection */
self = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (self == NULL) {
- printk( KERN_ERR "IrLMP: Can't allocate memory for "
- "LSAP control block!\n");
+ ERROR(__FUNCTION__ "(), can't allocate memory");
return NULL;
}
memset(self, 0, sizeof(struct lsap_cb));
self->magic = LMP_LSAP_MAGIC;
self->slsap_sel = slsap_sel;
- self->dlsap_sel = LSAP_ANY;
+
+ /* Fix connectionless LSAP's */
+ if (slsap_sel == LSAP_CONNLESS) {
+#ifdef CONFIG_IRDA_ULTRA
+ self->dlsap_sel = LSAP_CONNLESS;
+ self->pid = pid;
+#endif /* CONFIG_IRDA_ULTRA */
+ } else
+ self->dlsap_sel = LSAP_ANY;
self->connected = FALSE;
init_timer(&self->watchdog_timer);
@@ -185,9 +178,7 @@
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
- /*
- * Insert into queue of unconnected LSAPs
- */
+ /* Insert into queue of unconnected LSAPs */
hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self,
NULL);
@@ -209,9 +200,12 @@
/*
* Set some of the variables to preset values
*/
- self->magic = ~LMP_LSAP_MAGIC;
+ self->magic = 0;
del_timer(&self->watchdog_timer); /* Important! */
+ if (self->conn_skb)
+ dev_kfree_skb(self->conn_skb);
+
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
ASSERT(irlmp != NULL, return;);
irlmp->cache.valid = FALSE;
@@ -249,7 +243,7 @@
}
if (!lsap) {
IRDA_DEBUG(0, __FUNCTION__
- "(), Looks like somebody has removed me already!\n");
+ "(), Looks like somebody has removed me already!\n");
return;
}
__irlmp_close_lsap(self);
@@ -373,7 +367,6 @@
skb_push(skb, LMP_CONTROL_HEADER);
self->dlsap_sel = dlsap_sel;
- self->tmp_skb = skb;
/*
* Find the link to where we should try to connect since there may
@@ -447,22 +440,17 @@
ASSERT(self->lap != NULL, return;);
IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
- self->slsap_sel, self->dlsap_sel);
-
+ self->slsap_sel, self->dlsap_sel);
+
self->qos = *self->lap->qos;
max_seg_size = self->lap->qos->data_size.value-LMP_HEADER;
- IRDA_DEBUG(2, __FUNCTION__ "(), max_seg_size=%d\n", max_seg_size);
-
lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);
-
max_header_size = LMP_HEADER + lap_header_size;
- IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
-
/* Hide LMP_CONTROL_HEADER header from layer above */
skb_pull(skb, LMP_CONTROL_HEADER);
-
+
if (self->notify.connect_indication)
self->notify.connect_indication(self->notify.instance, self,
&self->qos, max_seg_size,
@@ -484,9 +472,9 @@
self->connected = TRUE;
IRDA_DEBUG(2, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
- self->slsap_sel, self->dlsap_sel);
+ self->slsap_sel, self->dlsap_sel);
- /* Make room for MUX control header ( 3 bytes) */
+ /* Make room for MUX control header (3 bytes) */
ASSERT(skb_headroom(userdata) >= LMP_CONTROL_HEADER, return -1;);
skb_push(userdata, LMP_CONTROL_HEADER);
@@ -519,7 +507,8 @@
lap_header_size = IRLAP_GET_HEADER_SIZE(self->lap->irlap);
max_header_size = LMP_HEADER + lap_header_size;
- IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n", max_header_size);
+ IRDA_DEBUG(2, __FUNCTION__ "(), max_header_size=%d\n",
+ max_header_size);
/* Hide LMP_CONTROL_HEADER header from layer above */
skb_pull(skb, LMP_CONTROL_HEADER);
@@ -637,13 +626,12 @@
struct lsap_cb *lsap;
IRDA_DEBUG(1, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
-
ASSERT(self != NULL, return;);
ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
ASSERT(self->connected == TRUE, return;);
IRDA_DEBUG(3, __FUNCTION__ "(), slsap_sel=%02x, dlsap_sel=%02x\n",
- self->slsap_sel, self->dlsap_sel);
+ self->slsap_sel, self->dlsap_sel);
self->connected = FALSE;
self->dlsap_sel = LSAP_ANY;
@@ -670,9 +658,12 @@
/*
* Inform service user
*/
- if (self->notify.disconnect_indication) {
+ if (self->notify.disconnect_indication)
self->notify.disconnect_indication(self->notify.instance,
self, reason, userdata);
+ else {
+ IRDA_DEBUG(0, __FUNCTION__ "(), no handler\n");
+ dev_kfree_skb(userdata);
}
}
@@ -687,9 +678,7 @@
struct lap_cb *lap;
/* Make sure the value is sane */
- if ((nslots != 1) && (nslots != 6) &&
- (nslots != 8) && (nslots != 16))
- {
+ if ((nslots != 1) && (nslots != 6) && (nslots != 8) && (nslots != 16)){
WARNING(__FUNCTION__
"(), invalid value for number of slots!\n");
nslots = sysctl_discovery_slots = 8;
@@ -918,13 +907,15 @@
* Got data from LAP layer so pass it up to upper layer
*
*/
-inline void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb)
+void irlmp_data_indication(struct lsap_cb *self, struct sk_buff *skb)
{
/* Hide LMP header from layer above */
skb_pull(skb, LMP_HEADER);
if (self->notify.data_indication)
self->notify.data_indication(self->notify.instance, self, skb);
+ else
+ dev_kfree_skb(skb);
}
/*
@@ -933,17 +924,17 @@
*
*
*/
-inline void irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb)
+int irlmp_udata_request(struct lsap_cb *self, struct sk_buff *skb)
{
IRDA_DEBUG(4, __FUNCTION__ "()\n");
- ASSERT(skb != NULL, return;);
+ ASSERT(skb != NULL, return -1;);
/* Make room for MUX header */
- ASSERT(skb_headroom(skb) >= LMP_HEADER, return;);
+ ASSERT(skb_headroom(skb) >= LMP_HEADER, return -1;);
skb_push(skb, LMP_HEADER);
- irlmp_do_lsap_event(self, LM_UDATA_REQUEST, skb);
+ return irlmp_do_lsap_event(self, LM_UDATA_REQUEST, skb);
}
/*
@@ -964,30 +955,83 @@
skb_pull(skb, LMP_HEADER);
if (self->notify.udata_indication)
- self->notify.udata_indication(self->notify.instance, self, skb);
+ self->notify.udata_indication(self->notify.instance, self,
+ skb);
+ else
+ dev_kfree_skb(skb);
}
/*
- * Function irlmp_connection_less_data_request (skb)
+ * Function irlmp_connless_data_request (self, skb)
*
- * Send out of connection UI frames
+ *
*
*/
-void irlmp_connectionless_data_request( struct sk_buff *skb)
+#ifdef CONFIG_IRDA_ULTRA
+int irlmp_connless_data_request(struct lsap_cb *self, struct sk_buff *skb)
{
- IRDA_DEBUG( 1, __FUNCTION__ "(), Sorry not implemented\n");
+ struct sk_buff *clone_skb;
+ struct lap_cb *lap;
+
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(skb != NULL, return -1;);
+
+ /* Make room for MUX and PID header */
+ ASSERT(skb_headroom(skb) >= LMP_HEADER+LMP_PID_HEADER, return -1;);
+
+ /* Insert protocol identifier */
+ skb_push(skb, LMP_PID_HEADER);
+ skb->data[0] = self->pid;
+
+ /* Connectionless sockets must use 0x70 */
+ skb_push(skb, LMP_HEADER);
+ skb->data[0] = skb->data[1] = LSAP_CONNLESS;
+
+ /* Try to send Connectionless packets out on all links */
+ lap = (struct lap_cb *) hashbin_get_first(irlmp->links);
+ while (lap != NULL) {
+ ASSERT(lap->magic == LMP_LAP_MAGIC, return -1;);
+
+ clone_skb = skb_clone(skb, GFP_ATOMIC);
+ if (!clone_skb)
+ return -ENOMEM;
+
+ irlap_unitdata_request(lap->irlap, clone_skb);
+
+ lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
+ }
+ dev_kfree_skb(skb);
+
+ return 0;
}
+#endif /* CONFIG_IRDA_ULTRA */
/*
- * Function irlmp_connection_less_data_indication (skb)
+ * Function irlmp_connless_data_indication (self, skb)
*
- *
+ * Receive unreliable data outside any connection. Mostly used by Ultra
*
*/
-void irlmp_connectionless_data_indication(struct sk_buff *skb)
+#ifdef CONFIG_IRDA_ULTRA
+void irlmp_connless_data_indication(struct lsap_cb *self, struct sk_buff *skb)
{
- IRDA_DEBUG( 1, __FUNCTION__ "()\n");
+ IRDA_DEBUG(4, __FUNCTION__ "()\n");
+
+ ASSERT(self != NULL, return;);
+ ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
+ ASSERT(skb != NULL, return;);
+
+ /* Hide LMP and PID header from layer above */
+ skb_pull(skb, LMP_HEADER+LMP_PID_HEADER);
+
+ if (self->notify.udata_indication)
+ self->notify.udata_indication(self->notify.instance, self,
+ skb);
+ else
+ dev_kfree_skb(skb);
}
+#endif /* CONFIG_IRDA_ULTRA */
void irlmp_status_request(void)
{
@@ -1310,8 +1354,14 @@
IRDA_DEBUG(4, __FUNCTION__ "()\n");
+#ifdef CONFIG_IRDA_ULTRA
+ /* Accept all bindings to the connectionless LSAP */
+ if (slsap_sel == LSAP_CONNLESS)
+ return FALSE;
+#endif /* CONFIG_IRDA_ULTRA */
+
/* Valid values are between 0 and 127 */
- if (slsap_sel > 127)
+ if (slsap_sel > LSAP_MAX)
return TRUE;
/*
@@ -1359,8 +1409,8 @@
while (irlmp_slsap_inuse(irlmp->free_lsap_sel)) {
irlmp->free_lsap_sel++;
- /* Check if we need to wraparound */
- if (irlmp->free_lsap_sel > 127) {
+ /* Check if we need to wraparound (0x70-0x7f are reserved) */
+ if (irlmp->free_lsap_sel > LSAP_MAX) {
irlmp->free_lsap_sel = 10;
/* Make sure we terminate the loop */
@@ -1431,7 +1481,7 @@
#ifdef CONFIG_PROC_FS
/*
- * Function irlmp_proc_read (buf, start, offset, len)
+ * Function irlmp_proc_read (buf, start, offset, len, unused)
*
* Give some info to the /proc file system
*
@@ -1474,6 +1524,7 @@
len += sprintf(buf+len, "saddr: %#08x, daddr: %#08x, ",
lap->saddr, lap->daddr);
+ len += sprintf(buf+len, "refcount: %d", lap->refcount);
len += sprintf(buf+len, "\n");
len += sprintf(buf+len, "\nConnected LSAPs:\n");
@@ -1495,7 +1546,6 @@
lap = (struct lap_cb *) hashbin_get_next(irlmp->links);
}
-
restore_flags(flags);
return len;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)