1 /*********************************************************************
3 * Filename: irlmp_event.c
5 * Description: An IrDA LMP event driver for Linux
6 * Status: Experimental.
7 * Author: Dag Brattli <dagb@cs.uit.no>
8 * Created at: Mon Aug 4 20:40:53 1997
9 * Modified at: Tue Dec 14 23:04:16 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
13 * All Rights Reserved.
14 * Copyright (c) 2000-2003 Jean Tourrilhes <jt@hpl.hp.com>
16 * This program is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU General Public License as
18 * published by the Free Software Foundation; either version 2 of
19 * the License, or (at your option) any later version.
21 * Neither Dag Brattli nor University of Tromsø admit liability nor
22 * provide warranty for any of this software. This material is
23 * provided "AS-IS" and at no charge.
25 ********************************************************************/
27 #include <linux/config.h>
28 #include <linux/kernel.h>
30 #include <net/irda/irda.h>
31 #include <net/irda/timer.h>
32 #include <net/irda/irlap.h>
33 #include <net/irda/irlmp.h>
34 #include <net/irda/irlmp_frame.h>
35 #include <net/irda/irlmp_event.h>
37 const char *irlmp_state[] = {
43 const char *irlsap_state[] = {
47 "LSAP_DATA_TRANSFER_READY",
52 #ifdef CONFIG_IRDA_DEBUG
53 static const char *irlmp_event[] = {
56 "LM_CONNECT_RESPONSE",
57 "LM_CONNECT_INDICATION",
59 "LM_DISCONNECT_INDICATION",
60 "LM_DISCONNECT_REQUEST",
65 "LM_UDATA_INDICATION",
67 "LM_WATCHDOG_TIMEOUT",
70 "LM_LAP_CONNECT_REQUEST",
71 "LM_LAP_CONNECT_INDICATION",
72 "LM_LAP_CONNECT_CONFIRM",
73 "LM_LAP_DISCONNECT_INDICATION",
74 "LM_LAP_DISCONNECT_REQUEST",
75 "LM_LAP_DISCOVERY_REQUEST",
76 "LM_LAP_DISCOVERY_CONFIRM",
77 "LM_LAP_IDLE_TIMEOUT",
79 #endif /* CONFIG_IRDA_DEBUG */
81 /* LAP Connection control proto declarations */
82 static void irlmp_state_standby (struct lap_cb *, IRLMP_EVENT,
84 static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT,
86 static void irlmp_state_active (struct lap_cb *, IRLMP_EVENT,
89 /* LSAP Connection control proto declarations */
90 static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT,
92 static int irlmp_state_connect (struct lsap_cb *, IRLMP_EVENT,
94 static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
96 static int irlmp_state_dtr (struct lsap_cb *, IRLMP_EVENT,
98 static int irlmp_state_setup (struct lsap_cb *, IRLMP_EVENT,
100 static int irlmp_state_setup_pend (struct lsap_cb *, IRLMP_EVENT,
103 static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
106 irlmp_state_u_connect,
110 static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
112 irlmp_state_disconnected,
114 irlmp_state_connect_pend,
117 irlmp_state_setup_pend
120 static inline void irlmp_next_lap_state(struct lap_cb *self,
124 IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __FUNCTION__, irlmp_state[state]);
126 self->lap_state = state;
129 static inline void irlmp_next_lsap_state(struct lsap_cb *self,
133 IRDA_ASSERT(self != NULL, return;);
134 IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
136 self->lsap_state = state;
139 /* Do connection control events */
140 int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
143 IRDA_ASSERT(self != NULL, return -1;);
144 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
146 IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
147 __FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
149 return (*lsap_state[self->lsap_state]) (self, event, skb);
153 * Function do_lap_event (event, skb, info)
155 * Do IrLAP control events
158 void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
161 IRDA_ASSERT(self != NULL, return;);
162 IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
164 IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __FUNCTION__,
166 irlmp_state[self->lap_state]);
168 (*lap_state[self->lap_state]) (self, event, skb);
171 void irlmp_discovery_timer_expired(void *data)
173 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
175 /* We always cleanup the log (active & passive discovery) */
178 /* Active discovery is conditional */
179 if (sysctl_discovery)
180 irlmp_do_discovery(sysctl_discovery_slots);
183 irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
186 void irlmp_watchdog_timer_expired(void *data)
188 struct lsap_cb *self = (struct lsap_cb *) data;
190 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
192 IRDA_ASSERT(self != NULL, return;);
193 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
195 irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
198 void irlmp_idle_timer_expired(void *data)
200 struct lap_cb *self = (struct lap_cb *) data;
202 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
204 IRDA_ASSERT(self != NULL, return;);
205 IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
207 irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
211 * Send an event on all LSAPs attached to this LAP.
214 irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
217 struct lsap_cb *lsap;
218 struct lsap_cb *lsap_next;
220 /* Note : this function use the new hashbin_find_next()
221 * function, instead of the old hashbin_get_next().
222 * This make sure that we are always pointing one lsap
223 * ahead, so that if the current lsap is removed as the
224 * result of sending the event, we don't care.
225 * Also, as we store the context ourselves, if an enumeration
226 * of the same lsap hashbin happens as the result of sending the
227 * event, we don't care.
228 * The only problem is if the next lsap is removed. In that case,
229 * hashbin_find_next() will return NULL and we will abort the
230 * enumeration. - Jean II */
232 /* Also : we don't accept any skb in input. We can *NOT* pass
233 * the same skb to multiple clients safely, we would need to
234 * skb_clone() it. - Jean II */
236 lsap = (struct lsap_cb *) hashbin_get_first(lsap_hashbin);
238 while (NULL != hashbin_find_next(lsap_hashbin,
241 (void *) &lsap_next) ) {
242 irlmp_do_lsap_event(lsap, event, NULL);
247 /*********************************************************************
249 * LAP connection control states
251 ********************************************************************/
254 * Function irlmp_state_standby (event, skb, info)
256 * STANDBY, The IrLAP connection does not exist.
259 static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
262 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
263 IRDA_ASSERT(self->irlap != NULL, return;);
266 case LM_LAP_DISCOVERY_REQUEST:
267 /* irlmp_next_station_state( LMP_DISCOVER); */
269 irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
271 case LM_LAP_CONNECT_INDICATION:
272 /* It's important to switch state first, to avoid IrLMP to
273 * think that the link is free since IrLMP may then start
274 * discovery before the connection is properly set up. DB.
276 irlmp_next_lap_state(self, LAP_ACTIVE);
278 /* Just accept connection TODO, this should be fixed */
279 irlap_connect_response(self->irlap, skb);
281 case LM_LAP_CONNECT_REQUEST:
282 IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __FUNCTION__);
284 irlmp_next_lap_state(self, LAP_U_CONNECT);
286 /* FIXME: need to set users requested QoS */
287 irlap_connect_request(self->irlap, self->daddr, NULL, 0);
289 case LM_LAP_DISCONNECT_INDICATION:
290 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
293 irlmp_next_lap_state(self, LAP_STANDBY);
296 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
297 __FUNCTION__, irlmp_event[event]);
303 * Function irlmp_state_u_connect (event, skb, info)
305 * U_CONNECT, The layer above has tried to open an LSAP connection but
306 * since the IrLAP connection does not exist, we must first start an
307 * IrLAP connection. We are now waiting response from IrLAP.
309 static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
312 IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
315 case LM_LAP_CONNECT_INDICATION:
316 /* It's important to switch state first, to avoid IrLMP to
317 * think that the link is free since IrLMP may then start
318 * discovery before the connection is properly set up. DB.
320 irlmp_next_lap_state(self, LAP_ACTIVE);
322 /* Just accept connection TODO, this should be fixed */
323 irlap_connect_response(self->irlap, skb);
325 /* Tell LSAPs that they can start sending data */
326 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
328 /* Note : by the time we get there (LAP retries and co),
329 * the lsaps may already have gone. This avoid getting stuck
330 * forever in LAP_ACTIVE state - Jean II */
331 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
332 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__);
333 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
336 case LM_LAP_CONNECT_REQUEST:
337 /* Already trying to connect */
339 case LM_LAP_CONNECT_CONFIRM:
340 /* For all lsap_ce E Associated do LS_Connect_confirm */
341 irlmp_next_lap_state(self, LAP_ACTIVE);
343 /* Tell LSAPs that they can start sending data */
344 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
346 /* Note : by the time we get there (LAP retries and co),
347 * the lsaps may already have gone. This avoid getting stuck
348 * forever in LAP_ACTIVE state - Jean II */
349 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
350 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__);
351 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
354 case LM_LAP_DISCONNECT_INDICATION:
355 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __FUNCTION__);
356 irlmp_next_lap_state(self, LAP_STANDBY);
358 /* Send disconnect event to all LSAPs using this link */
359 irlmp_do_all_lsap_event(self->lsaps,
360 LM_LAP_DISCONNECT_INDICATION);
362 case LM_LAP_DISCONNECT_REQUEST:
363 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __FUNCTION__);
365 /* One of the LSAP did timeout or was closed, if it was
366 * the last one, try to get out of here - Jean II */
367 if (HASHBIN_GET_SIZE(self->lsaps) <= 1) {
368 irlap_disconnect_request(self->irlap);
372 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
373 __FUNCTION__, irlmp_event[event]);
379 * Function irlmp_state_active (event, skb, info)
381 * ACTIVE, IrLAP connection is active
384 static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
387 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
390 case LM_LAP_CONNECT_REQUEST:
391 IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __FUNCTION__);
394 * IrLAP may have a pending disconnect. We tried to close
395 * IrLAP, but it was postponed because the link was
396 * busy or we were still sending packets. As we now
397 * need it, make sure it stays on. Jean II
399 irlap_clear_disconnect(self->irlap);
402 * LAP connection already active, just bounce back! Since we
403 * don't know which LSAP that tried to do this, we have to
404 * notify all LSAPs using this LAP, but that should be safe to
407 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
409 /* Needed by connect indication */
410 irlmp_do_all_lsap_event(irlmp->unconnected_lsaps,
411 LM_LAP_CONNECT_CONFIRM);
414 case LM_LAP_DISCONNECT_REQUEST:
416 * Need to find out if we should close IrLAP or not. If there
417 * is only one LSAP connection left on this link, that LSAP
418 * must be the one that tries to close IrLAP. It will be
419 * removed later and moved to the list of unconnected LSAPs
421 if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
422 /* Timer value is checked in irsysctl - Jean II */
423 irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000);
425 /* No more connections, so close IrLAP */
427 /* We don't want to change state just yet, because
428 * we want to reflect accurately the real state of
429 * the LAP, not the state we wish it was in,
430 * so that we don't lose LM_LAP_CONNECT_REQUEST.
431 * In some cases, IrLAP won't close the LAP
432 * immediately. For example, it might still be
433 * retrying packets or waiting for the pf bit.
434 * As the LAP always send a DISCONNECT_INDICATION
435 * in PCLOSE or SCLOSE, just change state on that.
437 irlap_disconnect_request(self->irlap);
440 case LM_LAP_IDLE_TIMEOUT:
441 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
442 /* Same reasoning as above - keep state */
443 irlap_disconnect_request(self->irlap);
446 case LM_LAP_DISCONNECT_INDICATION:
447 irlmp_next_lap_state(self, LAP_STANDBY);
449 /* In some case, at this point our side has already closed
450 * all lsaps, and we are waiting for the idle_timer to
451 * expire. If another device reconnect immediately, the
452 * idle timer will expire in the midle of the connection
453 * initialisation, screwing up things a lot...
454 * Therefore, we must stop the timer... */
455 irlmp_stop_idle_timer(self);
458 * Inform all connected LSAP's using this link
460 irlmp_do_all_lsap_event(self->lsaps,
461 LM_LAP_DISCONNECT_INDICATION);
463 /* Force an expiry of the discovery log.
464 * Now that the LAP is free, the system may attempt to
465 * connect to another device. Unfortunately, our entries
466 * are stale. There is a small window (<3s) before the
467 * normal discovery will run and where irlmp_connect_request()
468 * can get the wrong info, so make sure things get
469 * cleaned *NOW* ;-) - Jean II */
473 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
474 __FUNCTION__, irlmp_event[event]);
479 /*********************************************************************
481 * LSAP connection control states
483 ********************************************************************/
486 * Function irlmp_state_disconnected (event, skb, info)
491 static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
496 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
498 IRDA_ASSERT(self != NULL, return -1;);
499 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
502 #ifdef CONFIG_IRDA_ULTRA
503 case LM_UDATA_INDICATION:
504 /* This is most bizzare. Those packets are aka unreliable
505 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
506 * Why do we pass them as Ultra ??? Jean II */
507 irlmp_connless_data_indication(self, skb);
509 #endif /* CONFIG_IRDA_ULTRA */
510 case LM_CONNECT_REQUEST:
511 IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __FUNCTION__);
513 if (self->conn_skb) {
514 IRDA_WARNING("%s: busy with another request!\n",
518 /* Don't forget to refcount it (see irlmp_connect_request()) */
520 self->conn_skb = skb;
522 irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
524 /* Start watchdog timer (5 secs for now) */
525 irlmp_start_watchdog_timer(self, 5*HZ);
527 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
529 case LM_CONNECT_INDICATION:
530 if (self->conn_skb) {
531 IRDA_WARNING("%s: busy with another request!\n",
535 /* Don't forget to refcount it (see irlap_driver_rcv()) */
537 self->conn_skb = skb;
539 irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
541 /* Start watchdog timer
542 * This is not mentionned in the spec, but there is a rare
543 * race condition that can get the socket stuck.
544 * If we receive this event while our LAP is closing down,
545 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
546 * CONNECT_PEND state forever.
547 * The other cause of getting stuck down there is if the
548 * higher layer never reply to the CONNECT_INDICATION.
549 * Anyway, it make sense to make sure that we always have
550 * a backup plan. 1 second is plenty (should be immediate).
552 irlmp_start_watchdog_timer(self, 1*HZ);
554 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
557 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
558 __FUNCTION__, irlmp_event[event], self->slsap_sel);
565 * Function irlmp_state_connect (self, event, skb)
570 static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
573 struct lsap_cb *lsap;
576 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
578 IRDA_ASSERT(self != NULL, return -1;);
579 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
582 case LM_CONNECT_RESPONSE:
584 * Bind this LSAP to the IrLAP link where the connect was
587 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
590 IRDA_ASSERT(lsap == self, return -1;);
591 IRDA_ASSERT(self->lap != NULL, return -1;);
592 IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
594 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
597 set_bit(0, &self->connected); /* TRUE */
599 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
600 self->slsap_sel, CONNECT_CNF, skb);
602 del_timer(&self->watchdog_timer);
604 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
606 case LM_WATCHDOG_TIMEOUT:
607 /* May happen, who knows...
609 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
611 /* Disconnect, get out... - Jean II */
613 self->dlsap_sel = LSAP_ANY;
614 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
617 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
618 * are *not* yet bound to the IrLAP link. Jean II */
619 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
620 __FUNCTION__, irlmp_event[event], self->slsap_sel);
627 * Function irlmp_state_connect_pend (event, skb, info)
632 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
635 struct sk_buff *tx_skb;
638 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
640 IRDA_ASSERT(self != NULL, return -1;);
641 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
644 case LM_CONNECT_REQUEST:
647 case LM_CONNECT_RESPONSE:
648 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
649 "no indication issued yet\n", __FUNCTION__);
652 case LM_DISCONNECT_REQUEST:
653 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
654 "not yet bound to IrLAP connection\n", __FUNCTION__);
657 case LM_LAP_CONNECT_CONFIRM:
658 IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __FUNCTION__);
659 irlmp_next_lsap_state(self, LSAP_CONNECT);
661 tx_skb = self->conn_skb;
662 self->conn_skb = NULL;
664 irlmp_connect_indication(self, tx_skb);
665 /* Drop reference count - see irlmp_connect_indication(). */
666 dev_kfree_skb(tx_skb);
668 case LM_WATCHDOG_TIMEOUT:
669 /* Will happen in some rare cases because of a race condition.
670 * Just make sure we don't stay there forever...
672 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
674 /* Go back to disconnected mode, keep the socket waiting */
676 self->dlsap_sel = LSAP_ANY;
678 dev_kfree_skb(self->conn_skb);
679 self->conn_skb = NULL;
680 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
683 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
684 * are *not* yet bound to the IrLAP link. Jean II */
685 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
686 __FUNCTION__, irlmp_event[event], self->slsap_sel);
693 * Function irlmp_state_dtr (self, event, skb)
695 * DATA_TRANSFER_READY
698 static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
704 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
706 IRDA_ASSERT(self != NULL, return -1;);
707 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
708 IRDA_ASSERT(self->lap != NULL, return -1;);
711 case LM_DATA_REQUEST: /* Optimize for the common case */
712 irlmp_send_data_pdu(self->lap, self->dlsap_sel,
713 self->slsap_sel, FALSE, skb);
715 case LM_DATA_INDICATION: /* Optimize for the common case */
716 irlmp_data_indication(self, skb);
718 case LM_UDATA_REQUEST:
719 IRDA_ASSERT(skb != NULL, return -1;);
720 irlmp_send_data_pdu(self->lap, self->dlsap_sel,
721 self->slsap_sel, TRUE, skb);
723 case LM_UDATA_INDICATION:
724 irlmp_udata_indication(self, skb);
726 case LM_CONNECT_REQUEST:
727 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
728 "error, LSAP already connected\n", __FUNCTION__);
731 case LM_CONNECT_RESPONSE:
732 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
733 "error, LSAP already connected\n", __FUNCTION__);
736 case LM_DISCONNECT_REQUEST:
737 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
739 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
740 /* Called only from irlmp_disconnect_request(), will
741 * unbind from LAP over there. Jean II */
743 /* Try to close the LAP connection if its still there */
745 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
747 irlmp_do_lap_event(self->lap,
748 LM_LAP_DISCONNECT_REQUEST,
752 case LM_LAP_DISCONNECT_INDICATION:
753 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
755 reason = irlmp_convert_lap_reason(self->lap->reason);
757 irlmp_disconnect_indication(self, reason, NULL);
759 case LM_DISCONNECT_INDICATION:
760 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
762 IRDA_ASSERT(self->lap != NULL, return -1;);
763 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
765 IRDA_ASSERT(skb != NULL, return -1;);
766 IRDA_ASSERT(skb->len > 3, return -1;);
767 reason = skb->data[3];
769 /* Try to close the LAP connection */
770 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
771 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
773 irlmp_disconnect_indication(self, reason, skb);
776 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
777 __FUNCTION__, irlmp_event[event], self->slsap_sel);
784 * Function irlmp_state_setup (event, skb, info)
786 * SETUP, Station Control has set up the underlying IrLAP connection.
787 * An LSAP connection request has been transmitted to the peer
788 * LSAP-Connection Control FSM and we are awaiting reply.
790 static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
796 IRDA_ASSERT(self != NULL, return -1;);
797 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
799 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
802 case LM_CONNECT_CONFIRM:
803 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
805 del_timer(&self->watchdog_timer);
807 irlmp_connect_confirm(self, skb);
809 case LM_DISCONNECT_INDICATION:
810 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
812 IRDA_ASSERT(self->lap != NULL, return -1;);
813 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
815 IRDA_ASSERT(skb != NULL, return -1;);
816 IRDA_ASSERT(skb->len > 3, return -1;);
817 reason = skb->data[3];
819 /* Try to close the LAP connection */
820 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__);
821 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
823 irlmp_disconnect_indication(self, reason, skb);
825 case LM_LAP_DISCONNECT_INDICATION:
826 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
828 del_timer(&self->watchdog_timer);
830 IRDA_ASSERT(self->lap != NULL, return -1;);
831 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
833 reason = irlmp_convert_lap_reason(self->lap->reason);
835 irlmp_disconnect_indication(self, reason, skb);
837 case LM_WATCHDOG_TIMEOUT:
838 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
840 IRDA_ASSERT(self->lap != NULL, return -1;);
841 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
842 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
844 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
847 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
848 __FUNCTION__, irlmp_event[event], self->slsap_sel);
855 * Function irlmp_state_setup_pend (event, skb, info)
857 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
858 * user to set up an LSAP connection. A request has been sent to the
859 * LAP FSM to set up the underlying IrLAP connection, and we
860 * are awaiting confirm.
862 static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
865 struct sk_buff *tx_skb;
869 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
871 IRDA_ASSERT(self != NULL, return -1;);
872 IRDA_ASSERT(irlmp != NULL, return -1;);
875 case LM_LAP_CONNECT_CONFIRM:
876 IRDA_ASSERT(self->conn_skb != NULL, return -1;);
878 tx_skb = self->conn_skb;
879 self->conn_skb = NULL;
881 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
882 self->slsap_sel, CONNECT_CMD, tx_skb);
883 /* Drop reference count - see irlap_data_request(). */
884 dev_kfree_skb(tx_skb);
886 irlmp_next_lsap_state(self, LSAP_SETUP);
888 case LM_WATCHDOG_TIMEOUT:
889 IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __FUNCTION__);
891 IRDA_ASSERT(self->lap != NULL, return -1;);
892 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
893 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
895 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
897 case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
898 del_timer( &self->watchdog_timer);
900 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
902 reason = irlmp_convert_lap_reason(self->lap->reason);
904 irlmp_disconnect_indication(self, reason, NULL);
907 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
908 __FUNCTION__, irlmp_event[event], self->slsap_sel);