patch-2.4.0-test11 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: 343
- Date:
Sat Nov 11 18:11:23 2000
- Orig file:
v2.4.0-test10/linux/net/irda/irlmp.c
- Orig date:
Thu Jan 6 14:46:18 2000
diff -u --recursive --new-file v2.4.0-test10/linux/net/irda/irlmp.c linux/net/irda/irlmp.c
@@ -74,6 +74,7 @@
*/
int __init irlmp_init(void)
{
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
/* Initialize the irlmp structure. */
irlmp = kmalloc( sizeof(struct irlmp_cb), GFP_KERNEL);
if (irlmp == NULL)
@@ -81,7 +82,7 @@
memset(irlmp, 0, sizeof(struct irlmp_cb));
irlmp->magic = LMP_MAGIC;
- spin_lock_init(&irlmp->lock);
+ spin_lock_init(&irlmp->log_lock);
irlmp->clients = hashbin_new(HB_GLOBAL);
irlmp->services = hashbin_new(HB_GLOBAL);
@@ -178,7 +179,7 @@
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
/* Insert into queue of unconnected LSAPs */
- hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self,
+ hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
NULL);
return self;
@@ -284,9 +285,9 @@
init_timer(&lap->idle_timer);
/*
- * Insert into queue of unconnected LSAPs
+ * Insert into queue of LMP links
*/
- hashbin_insert(irlmp->links, (queue_t *) lap, lap->saddr, NULL);
+ hashbin_insert(irlmp->links, (irda_queue_t *) lap, lap->saddr, NULL);
/*
* We set only this variable so IrLAP can tell us on which link the
@@ -395,9 +396,25 @@
return -EHOSTUNREACH;
}
+ /* Check if LAP is disconnected or already connected */
if (lap->daddr == DEV_ADDR_ANY)
lap->daddr = daddr;
else if (lap->daddr != daddr) {
+ struct lsap_cb *any_lsap;
+
+ /* Check if some LSAPs are active on this LAP */
+ any_lsap = (struct lsap_cb *) hashbin_get_first(lap->lsaps);
+ if (any_lsap == NULL) {
+ /* No active connection, but LAP hasn't been
+ * disconnected yet (waiting for timeout in LAP).
+ * Maybe we could give LAP a bit of help in this case.
+ */
+ IRDA_DEBUG(0, __FUNCTION__ "(), sorry, but I'm waiting for LAP to timeout!\n");
+ return -EAGAIN;
+ }
+
+ /* LAP is already connected to a different node, and LAP
+ * can only talk to one node at a time */
IRDA_DEBUG(0, __FUNCTION__ "(), sorry, but link is busy!\n");
return -EBUSY;
}
@@ -415,7 +432,7 @@
ASSERT(lsap->lap != NULL, return -1;);
ASSERT(lsap->lap->magic == LMP_LAP_MAGIC, return -1;);
- hashbin_insert(self->lap->lsaps, (queue_t *) self, (int) self, NULL);
+ hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self, NULL);
self->connected = TRUE;
@@ -557,7 +574,7 @@
init_timer(&new->watchdog_timer);
- hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) new, (int) new,
+ hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new, (int) new,
NULL);
/* Make sure that we invalidate the cache */
@@ -612,7 +629,7 @@
ASSERT(lsap->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(lsap == self, return -1;);
- hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) self, (int) self,
+ hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) self, (int) self,
NULL);
/* Reset some values */
@@ -658,7 +675,7 @@
ASSERT(lsap != NULL, return;);
ASSERT(lsap == self, return;);
- hashbin_insert(irlmp->unconnected_lsaps, (queue_t *) lsap, (int) lsap,
+ hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) lsap, (int) lsap,
NULL);
self->lap = NULL;
@@ -749,6 +766,18 @@
irlmp_do_discovery(nslots);
}
+/*
+ * Function irlmp_get_discoveries (pn, mask)
+ *
+ * Return the current discovery log
+ *
+ */
+struct irda_device_info *irlmp_get_discoveries(int *pn, __u16 mask)
+{
+ /* Return current cached discovery log */
+ return(irlmp_copy_discoveries(irlmp->cachelog, pn, mask));
+}
+
#if 0
/*
* Function irlmp_check_services (discovery)
@@ -759,7 +788,6 @@
void irlmp_check_services(discovery_t *discovery)
{
struct irlmp_client *client;
- struct irmanager_event event;
__u8 *service_log;
__u8 service;
int i = 0;
@@ -787,14 +815,7 @@
continue;
/*
* Found no clients for dealing with this service,
- * so ask the user space irmanager to try to load
- * the right module for us
*/
- event.event = EVENT_DEVICE_DISCOVERED;
- event.service = service;
- event.daddr = discovery->daddr;
- sprintf(event.info, "%s", discovery->info);
- irmanager_notify(&event);
}
}
kfree(service_log);
@@ -805,17 +826,24 @@
*
* Notify all about discovered devices
*
+ * Clients registered with IrLMP are :
+ * o IrComm
+ * o IrLAN
+ * o Any socket (in any state - ouch, that may be a lot !)
+ * The client may have defined a callback to be notified in case of
+ * partial/selective discovery based on the hints that it passed to IrLMP.
*/
-void irlmp_notify_client(irlmp_client_t *client, hashbin_t *log)
+static inline void
+irlmp_notify_client(irlmp_client_t *client, hashbin_t *log)
{
discovery_t *discovery;
IRDA_DEBUG(3, __FUNCTION__ "()\n");
- /* Check if client wants the whole log */
- if (client->callback2)
- client->callback2(log);
-
+ /* Check if client wants or not partial/selective log (optimisation) */
+ if (!client->disco_callback)
+ return;
+
/*
* Now, check all discovered devices (if any), and notify client
* only about the services that the client is interested in
@@ -828,10 +856,9 @@
* Any common hint bits? Remember to mask away the extension
* bits ;-)
*/
- if (client->hint_mask & discovery->hints.word & 0x7f7f) {
- if (client->callback1)
- client->callback1(discovery);
- }
+ if (client->hint_mask & discovery->hints.word & 0x7f7f)
+ client->disco_callback(discovery, client->priv);
+
discovery = (discovery_t *) hashbin_get_next(log);
}
}
@@ -864,9 +891,40 @@
}
/*
+ * Function irlmp_discovery_expiry (expiry)
+ *
+ * This device is no longer been discovered, and therefore it is beeing
+ * purged from the discovery log. Inform all clients who have
+ * registered for this event...
+ *
+ * Note : called exclusively from discovery.c
+ * Note : as we are currently processing the log, the clients callback
+ * should *NOT* attempt to touch the log now.
+ */
+void irlmp_discovery_expiry(discovery_t *expiry)
+{
+ irlmp_client_t *client;
+
+ IRDA_DEBUG(3, __FUNCTION__ "()\n");
+
+ ASSERT(expiry != NULL, return;);
+
+ client = (irlmp_client_t *) hashbin_get_first(irlmp->clients);
+ while (client != NULL) {
+ /* Check if we should notify client */
+ if ((client->expir_callback) &&
+ (client->hint_mask & expiry->hints.word & 0x7f7f))
+ client->expir_callback(expiry, client->priv);
+
+ /* Next client */
+ client = (irlmp_client_t *) hashbin_get_next(irlmp->clients);
+ }
+}
+
+/*
* Function irlmp_get_discovery_response ()
*
- * Used by IrLAP to get the disocvery info it needs when answering
+ * Used by IrLAP to get the discovery info it needs when answering
* discovery requests by other devices.
*/
discovery_t *irlmp_get_discovery_response()
@@ -1046,9 +1104,35 @@
IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented\n");
}
-void irlmp_status_indication(LINK_STATUS link, LOCK_STATUS lock)
-{
- IRDA_DEBUG(1, __FUNCTION__ "(), Not implemented\n");
+/*
+ * Propagate status indication from LAP to LSAPs (via LMP)
+ * This don't trigger any change of state in lap_cb, lmp_cb or lsap_cb,
+ * and the event is stateless, therefore we can bypass both state machines
+ * and send the event direct to the LSAP user.
+ * Jean II
+ */
+void irlmp_status_indication(struct lap_cb *self,
+ LINK_STATUS link, LOCK_STATUS lock)
+{
+ struct lsap_cb *next;
+ struct lsap_cb *curr;
+
+ /* Send status_indication to all LSAPs using this link */
+ next = (struct lsap_cb *) hashbin_get_first( self->lsaps);
+ while (next != NULL ) {
+ curr = next;
+ next = (struct lsap_cb *) hashbin_get_next(self->lsaps);
+
+ ASSERT(curr->magic == LMP_LSAP_MAGIC, return;);
+ /*
+ * Inform service user if he has requested it
+ */
+ if (curr->notify.status_indication != NULL)
+ curr->notify.status_indication(curr->notify.instance,
+ link, lock);
+ else
+ IRDA_DEBUG(2, __FUNCTION__ "(), no handler\n");
+ }
}
/*
@@ -1207,7 +1291,7 @@
return 0;
}
service->hints = hints;
- hashbin_insert(irlmp->services, (queue_t *) service, handle, NULL);
+ hashbin_insert(irlmp->services, (irda_queue_t *) service, handle, NULL);
return handle;
}
@@ -1255,15 +1339,20 @@
* Function irlmp_register_client (hint_mask, callback1, callback2)
*
* Register a local client with IrLMP
+ * First callback is selective discovery (based on hints)
+ * Second callback is for selective discovery expiries
*
* Returns: handle > 0 on success, 0 on error
*/
-__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)
{
irlmp_client_t *client;
__u32 handle;
+ IRDA_DEBUG(0, __FUNCTION__ "()\n");
+ ASSERT(irlmp != NULL, return 0;);
+
/* Get a unique handle for this client */
get_random_bytes(&handle, sizeof(handle));
while (hashbin_find(irlmp->clients, handle, NULL) || !handle)
@@ -1273,16 +1362,16 @@
client = kmalloc(sizeof(irlmp_client_t), GFP_ATOMIC);
if (!client) {
IRDA_DEBUG( 1, __FUNCTION__ "(), Unable to kmalloc!\n");
-
return 0;
}
/* Register the details */
client->hint_mask = hint_mask;
- client->callback1 = callback1;
- client->callback2 = callback2;
+ client->disco_callback = disco_clb;
+ client->expir_callback = expir_clb;
+ client->priv = priv;
- hashbin_insert(irlmp->clients, (queue_t *) client, handle, NULL);
+ hashbin_insert(irlmp->clients, (irda_queue_t *) client, handle, NULL);
return handle;
}
@@ -1296,8 +1385,8 @@
* Returns: 0 on success, -1 on error
*/
int irlmp_update_client(__u32 handle, __u16 hint_mask,
- DISCOVERY_CALLBACK1 callback1,
- DISCOVERY_CALLBACK2 callback2)
+ DISCOVERY_CALLBACK1 disco_clb,
+ DISCOVERY_CALLBACK1 expir_clb, void *priv)
{
irlmp_client_t *client;
@@ -1311,8 +1400,9 @@
}
client->hint_mask = hint_mask;
- client->callback1 = callback1;
- client->callback2 = callback2;
+ client->disco_callback = disco_clb;
+ client->expir_callback = expir_clb;
+ client->priv = priv;
return 0;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)