ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
ASSERT(userdata != NULL, return -1;);
- set_bit(0, &self->connected); /* TRUE */
+ /* We set the connected bit and move the lsap to the connected list
+ * in the state machine itself. Jean II */
IRDA_DEBUG(2, "%s(), slsap_sel=%02x, dlsap_sel=%02x\n",
__FUNCTION__, self->slsap_sel, self->dlsap_sel);
spin_lock_irqsave(&irlmp->unconnected_lsaps->hb_spinlock, flags);
- /* Only allowed to duplicate unconnected LSAP's */
- if (!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) {
- IRDA_DEBUG(0, "%s(), unable to find LSAP\n", __FUNCTION__);
+ /* Only allowed to duplicate unconnected LSAP's, and only LSAPs
+ * that have received a connect indication. Jean II */
+ if ((!hashbin_find(irlmp->unconnected_lsaps, (long) orig, NULL)) ||
+ (orig->lap == NULL)) {
+ IRDA_DEBUG(0, "%s(), invalid LSAP (wrong state)\n",
+ __FUNCTION__);
spin_unlock_irqrestore(&irlmp->unconnected_lsaps->hb_spinlock,
flags);
return NULL;
}
+
/* Allocate a new instance */
new = kmalloc(sizeof(struct lsap_cb), GFP_ATOMIC);
if (!new) {
hashbin_insert(irlmp->unconnected_lsaps, (irda_queue_t *) new,
(long) new, NULL);
- /* Make sure that we invalidate the cache */
#ifdef CONFIG_IRDA_CACHE_LAST_LSAP
+ /* Make sure that we invalidate the LSAP cache */
new->lap->cache.valid = FALSE;
#endif /* CONFIG_IRDA_CACHE_LAST_LSAP */
hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
(long) self, NULL);
+ set_bit(0, &self->connected); /* TRUE */
+
irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
self->slsap_sel, CONNECT_CNF, skb);
IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
/* Disconnect, get out... - Jean II */
+ self->lap = NULL;
self->dlsap_sel = LSAP_ANY;
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
break;
default:
+ /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
+ * are *not* yet bound to the IrLAP link. Jean II */
IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
__FUNCTION__, irlmp_event[event], self->slsap_sel);
break;
IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
/* Go back to disconnected mode, keep the socket waiting */
+ self->lap = NULL;
self->dlsap_sel = LSAP_ANY;
if(self->conn_skb)
dev_kfree_skb(self->conn_skb);
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
break;
default:
+ /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
+ * are *not* yet bound to the IrLAP link. Jean II */
IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
__FUNCTION__, irlmp_event[event], self->slsap_sel);
break;
irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
DISCONNECT, skb);
irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
+ /* Called only from irlmp_disconnect_request(), will
+ * unbind from LAP over there. Jean II */
/* Try to close the LAP connection if its still there */
if (self->lap) {
/* We don't need the old instance any more */
spin_unlock_irqrestore(&irttp->tsaps->hb_spinlock, flags);
+ /* Try to dup the LSAP (may fail if we were too slow) */
+ new->lsap = irlmp_dup(orig->lsap, new);
+ if (!new->lsap) {
+ IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
+ kfree(new);
+ return NULL;
+ }
+
/* Not everything should be copied */
new->notify.instance = instance;
- new->lsap = irlmp_dup(orig->lsap, new);
init_timer(&new->todo_timer);
skb_queue_head_init(&new->rx_queue);