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/kernel.h>
29 #include <net/irda/irda.h>
30 #include <net/irda/timer.h>
31 #include <net/irda/irlap.h>
32 #include <net/irda/irlmp.h>
33 #include <net/irda/irlmp_frame.h>
34 #include <net/irda/irlmp_event.h>
36 const char *const irlmp_state
[] = {
42 const char *const irlsap_state
[] = {
46 "LSAP_DATA_TRANSFER_READY",
51 static const char *const irlmp_event
[] __maybe_unused
= {
54 "LM_CONNECT_RESPONSE",
55 "LM_CONNECT_INDICATION",
57 "LM_DISCONNECT_INDICATION",
58 "LM_DISCONNECT_REQUEST",
63 "LM_UDATA_INDICATION",
65 "LM_WATCHDOG_TIMEOUT",
68 "LM_LAP_CONNECT_REQUEST",
69 "LM_LAP_CONNECT_INDICATION",
70 "LM_LAP_CONNECT_CONFIRM",
71 "LM_LAP_DISCONNECT_INDICATION",
72 "LM_LAP_DISCONNECT_REQUEST",
73 "LM_LAP_DISCOVERY_REQUEST",
74 "LM_LAP_DISCOVERY_CONFIRM",
75 "LM_LAP_IDLE_TIMEOUT",
78 /* LAP Connection control proto declarations */
79 static void irlmp_state_standby (struct lap_cb
*, IRLMP_EVENT
,
81 static void irlmp_state_u_connect(struct lap_cb
*, IRLMP_EVENT
,
83 static void irlmp_state_active (struct lap_cb
*, IRLMP_EVENT
,
86 /* LSAP Connection control proto declarations */
87 static int irlmp_state_disconnected(struct lsap_cb
*, IRLMP_EVENT
,
89 static int irlmp_state_connect (struct lsap_cb
*, IRLMP_EVENT
,
91 static int irlmp_state_connect_pend(struct lsap_cb
*, IRLMP_EVENT
,
93 static int irlmp_state_dtr (struct lsap_cb
*, IRLMP_EVENT
,
95 static int irlmp_state_setup (struct lsap_cb
*, IRLMP_EVENT
,
97 static int irlmp_state_setup_pend (struct lsap_cb
*, IRLMP_EVENT
,
100 static void (*lap_state
[]) (struct lap_cb
*, IRLMP_EVENT
, struct sk_buff
*) =
103 irlmp_state_u_connect
,
107 static int (*lsap_state
[])( struct lsap_cb
*, IRLMP_EVENT
, struct sk_buff
*) =
109 irlmp_state_disconnected
,
111 irlmp_state_connect_pend
,
114 irlmp_state_setup_pend
117 static inline void irlmp_next_lap_state(struct lap_cb
*self
,
121 pr_debug("%s(), LMP LAP = %s\n", __func__, irlmp_state[state]);
123 self
->lap_state
= state
;
126 static inline void irlmp_next_lsap_state(struct lsap_cb
*self
,
130 IRDA_ASSERT(self != NULL, return;);
131 pr_debug("%s(), LMP LSAP = %s\n", __func__, irlsap_state[state]);
133 self
->lsap_state
= state
;
136 /* Do connection control events */
137 int irlmp_do_lsap_event(struct lsap_cb
*self
, IRLMP_EVENT event
,
140 IRDA_ASSERT(self
!= NULL
, return -1;);
141 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
143 pr_debug("%s(), EVENT = %s, STATE = %s\n",
144 __func__
, irlmp_event
[event
], irlsap_state
[self
->lsap_state
]);
146 return (*lsap_state
[self
->lsap_state
]) (self
, event
, skb
);
150 * Function do_lap_event (event, skb, info)
152 * Do IrLAP control events
155 void irlmp_do_lap_event(struct lap_cb
*self
, IRLMP_EVENT event
,
158 IRDA_ASSERT(self
!= NULL
, return;);
159 IRDA_ASSERT(self
->magic
== LMP_LAP_MAGIC
, return;);
161 pr_debug("%s(), EVENT = %s, STATE = %s\n", __func__
,
163 irlmp_state
[self
->lap_state
]);
165 (*lap_state
[self
->lap_state
]) (self
, event
, skb
);
168 void irlmp_discovery_timer_expired(void *data
)
170 /* We always cleanup the log (active & passive discovery) */
173 irlmp_do_discovery(sysctl_discovery_slots
);
176 irlmp_start_discovery_timer(irlmp
, sysctl_discovery_timeout
* HZ
);
179 void irlmp_watchdog_timer_expired(void *data
)
181 struct lsap_cb
*self
= (struct lsap_cb
*) data
;
183 IRDA_ASSERT(self
!= NULL
, return;);
184 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return;);
186 irlmp_do_lsap_event(self
, LM_WATCHDOG_TIMEOUT
, NULL
);
189 void irlmp_idle_timer_expired(void *data
)
191 struct lap_cb
*self
= (struct lap_cb
*) data
;
193 IRDA_ASSERT(self
!= NULL
, return;);
194 IRDA_ASSERT(self
->magic
== LMP_LAP_MAGIC
, return;);
196 irlmp_do_lap_event(self
, LM_LAP_IDLE_TIMEOUT
, NULL
);
200 * Send an event on all LSAPs attached to this LAP.
203 irlmp_do_all_lsap_event(hashbin_t
* lsap_hashbin
,
206 struct lsap_cb
*lsap
;
207 struct lsap_cb
*lsap_next
;
209 /* Note : this function use the new hashbin_find_next()
210 * function, instead of the old hashbin_get_next().
211 * This make sure that we are always pointing one lsap
212 * ahead, so that if the current lsap is removed as the
213 * result of sending the event, we don't care.
214 * Also, as we store the context ourselves, if an enumeration
215 * of the same lsap hashbin happens as the result of sending the
216 * event, we don't care.
217 * The only problem is if the next lsap is removed. In that case,
218 * hashbin_find_next() will return NULL and we will abort the
219 * enumeration. - Jean II */
221 /* Also : we don't accept any skb in input. We can *NOT* pass
222 * the same skb to multiple clients safely, we would need to
223 * skb_clone() it. - Jean II */
225 lsap
= (struct lsap_cb
*) hashbin_get_first(lsap_hashbin
);
227 while (NULL
!= hashbin_find_next(lsap_hashbin
,
230 (void *) &lsap_next
) ) {
231 irlmp_do_lsap_event(lsap
, event
, NULL
);
236 /*********************************************************************
238 * LAP connection control states
240 ********************************************************************/
243 * Function irlmp_state_standby (event, skb, info)
245 * STANDBY, The IrLAP connection does not exist.
248 static void irlmp_state_standby(struct lap_cb
*self
, IRLMP_EVENT event
,
251 IRDA_ASSERT(self
->irlap
!= NULL
, return;);
254 case LM_LAP_DISCOVERY_REQUEST
:
255 /* irlmp_next_station_state( LMP_DISCOVER); */
257 irlap_discovery_request(self
->irlap
, &irlmp
->discovery_cmd
);
259 case LM_LAP_CONNECT_INDICATION
:
260 /* It's important to switch state first, to avoid IrLMP to
261 * think that the link is free since IrLMP may then start
262 * discovery before the connection is properly set up. DB.
264 irlmp_next_lap_state(self
, LAP_ACTIVE
);
266 /* Just accept connection TODO, this should be fixed */
267 irlap_connect_response(self
->irlap
, skb
);
269 case LM_LAP_CONNECT_REQUEST
:
270 pr_debug("%s() LS_CONNECT_REQUEST\n", __func__
);
272 irlmp_next_lap_state(self
, LAP_U_CONNECT
);
274 /* FIXME: need to set users requested QoS */
275 irlap_connect_request(self
->irlap
, self
->daddr
, NULL
, 0);
277 case LM_LAP_DISCONNECT_INDICATION
:
278 pr_debug("%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
281 irlmp_next_lap_state(self
, LAP_STANDBY
);
284 pr_debug("%s(), Unknown event %s\n",
285 __func__
, irlmp_event
[event
]);
291 * Function irlmp_state_u_connect (event, skb, info)
293 * U_CONNECT, The layer above has tried to open an LSAP connection but
294 * since the IrLAP connection does not exist, we must first start an
295 * IrLAP connection. We are now waiting response from IrLAP.
297 static void irlmp_state_u_connect(struct lap_cb
*self
, IRLMP_EVENT event
,
300 pr_debug("%s(), event=%s\n", __func__
, irlmp_event
[event
]);
303 case LM_LAP_CONNECT_INDICATION
:
304 /* It's important to switch state first, to avoid IrLMP to
305 * think that the link is free since IrLMP may then start
306 * discovery before the connection is properly set up. DB.
308 irlmp_next_lap_state(self
, LAP_ACTIVE
);
310 /* Just accept connection TODO, this should be fixed */
311 irlap_connect_response(self
->irlap
, skb
);
313 /* Tell LSAPs that they can start sending data */
314 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
316 /* Note : by the time we get there (LAP retries and co),
317 * the lsaps may already have gone. This avoid getting stuck
318 * forever in LAP_ACTIVE state - Jean II */
319 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
320 pr_debug("%s() NO LSAPs !\n", __func__
);
321 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
324 case LM_LAP_CONNECT_REQUEST
:
325 /* Already trying to connect */
327 case LM_LAP_CONNECT_CONFIRM
:
328 /* For all lsap_ce E Associated do LS_Connect_confirm */
329 irlmp_next_lap_state(self
, LAP_ACTIVE
);
331 /* Tell LSAPs that they can start sending data */
332 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
334 /* Note : by the time we get there (LAP retries and co),
335 * the lsaps may already have gone. This avoid getting stuck
336 * forever in LAP_ACTIVE state - Jean II */
337 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
338 pr_debug("%s() NO LSAPs !\n", __func__
);
339 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
342 case LM_LAP_DISCONNECT_INDICATION
:
343 pr_debug("%s(), LM_LAP_DISCONNECT_INDICATION\n", __func__
);
344 irlmp_next_lap_state(self
, LAP_STANDBY
);
346 /* Send disconnect event to all LSAPs using this link */
347 irlmp_do_all_lsap_event(self
->lsaps
,
348 LM_LAP_DISCONNECT_INDICATION
);
350 case LM_LAP_DISCONNECT_REQUEST
:
351 pr_debug("%s(), LM_LAP_DISCONNECT_REQUEST\n", __func__
);
353 /* One of the LSAP did timeout or was closed, if it was
354 * the last one, try to get out of here - Jean II */
355 if (HASHBIN_GET_SIZE(self
->lsaps
) <= 1) {
356 irlap_disconnect_request(self
->irlap
);
360 pr_debug("%s(), Unknown event %s\n",
361 __func__
, irlmp_event
[event
]);
367 * Function irlmp_state_active (event, skb, info)
369 * ACTIVE, IrLAP connection is active
372 static void irlmp_state_active(struct lap_cb
*self
, IRLMP_EVENT event
,
376 case LM_LAP_CONNECT_REQUEST
:
377 pr_debug("%s(), LS_CONNECT_REQUEST\n", __func__
);
380 * IrLAP may have a pending disconnect. We tried to close
381 * IrLAP, but it was postponed because the link was
382 * busy or we were still sending packets. As we now
383 * need it, make sure it stays on. Jean II
385 irlap_clear_disconnect(self
->irlap
);
388 * LAP connection already active, just bounce back! Since we
389 * don't know which LSAP that tried to do this, we have to
390 * notify all LSAPs using this LAP, but that should be safe to
393 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
395 /* Needed by connect indication */
396 irlmp_do_all_lsap_event(irlmp
->unconnected_lsaps
,
397 LM_LAP_CONNECT_CONFIRM
);
400 case LM_LAP_DISCONNECT_REQUEST
:
402 * Need to find out if we should close IrLAP or not. If there
403 * is only one LSAP connection left on this link, that LSAP
404 * must be the one that tries to close IrLAP. It will be
405 * removed later and moved to the list of unconnected LSAPs
407 if (HASHBIN_GET_SIZE(self
->lsaps
) > 0) {
408 /* Timer value is checked in irsysctl - Jean II */
409 irlmp_start_idle_timer(self
, sysctl_lap_keepalive_time
* HZ
/ 1000);
411 /* No more connections, so close IrLAP */
413 /* We don't want to change state just yet, because
414 * we want to reflect accurately the real state of
415 * the LAP, not the state we wish it was in,
416 * so that we don't lose LM_LAP_CONNECT_REQUEST.
417 * In some cases, IrLAP won't close the LAP
418 * immediately. For example, it might still be
419 * retrying packets or waiting for the pf bit.
420 * As the LAP always send a DISCONNECT_INDICATION
421 * in PCLOSE or SCLOSE, just change state on that.
423 irlap_disconnect_request(self
->irlap
);
426 case LM_LAP_IDLE_TIMEOUT
:
427 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
428 /* Same reasoning as above - keep state */
429 irlap_disconnect_request(self
->irlap
);
432 case LM_LAP_DISCONNECT_INDICATION
:
433 irlmp_next_lap_state(self
, LAP_STANDBY
);
435 /* In some case, at this point our side has already closed
436 * all lsaps, and we are waiting for the idle_timer to
437 * expire. If another device reconnect immediately, the
438 * idle timer will expire in the midle of the connection
439 * initialisation, screwing up things a lot...
440 * Therefore, we must stop the timer... */
441 irlmp_stop_idle_timer(self
);
444 * Inform all connected LSAP's using this link
446 irlmp_do_all_lsap_event(self
->lsaps
,
447 LM_LAP_DISCONNECT_INDICATION
);
449 /* Force an expiry of the discovery log.
450 * Now that the LAP is free, the system may attempt to
451 * connect to another device. Unfortunately, our entries
452 * are stale. There is a small window (<3s) before the
453 * normal discovery will run and where irlmp_connect_request()
454 * can get the wrong info, so make sure things get
455 * cleaned *NOW* ;-) - Jean II */
459 pr_debug("%s(), Unknown event %s\n",
460 __func__
, irlmp_event
[event
]);
465 /*********************************************************************
467 * LSAP connection control states
469 ********************************************************************/
472 * Function irlmp_state_disconnected (event, skb, info)
477 static int irlmp_state_disconnected(struct lsap_cb
*self
, IRLMP_EVENT event
,
482 IRDA_ASSERT(self
!= NULL
, return -1;);
483 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
486 #ifdef CONFIG_IRDA_ULTRA
487 case LM_UDATA_INDICATION
:
488 /* This is most bizarre. Those packets are aka unreliable
489 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
490 * Why do we pass them as Ultra ??? Jean II */
491 irlmp_connless_data_indication(self
, skb
);
493 #endif /* CONFIG_IRDA_ULTRA */
494 case LM_CONNECT_REQUEST
:
495 pr_debug("%s(), LM_CONNECT_REQUEST\n", __func__
);
497 if (self
->conn_skb
) {
498 net_warn_ratelimited("%s: busy with another request!\n",
502 /* Don't forget to refcount it (see irlmp_connect_request()) */
504 self
->conn_skb
= skb
;
506 irlmp_next_lsap_state(self
, LSAP_SETUP_PEND
);
508 /* Start watchdog timer (5 secs for now) */
509 irlmp_start_watchdog_timer(self
, 5*HZ
);
511 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
513 case LM_CONNECT_INDICATION
:
514 if (self
->conn_skb
) {
515 net_warn_ratelimited("%s: busy with another request!\n",
519 /* Don't forget to refcount it (see irlap_driver_rcv()) */
521 self
->conn_skb
= skb
;
523 irlmp_next_lsap_state(self
, LSAP_CONNECT_PEND
);
525 /* Start watchdog timer
526 * This is not mentionned in the spec, but there is a rare
527 * race condition that can get the socket stuck.
528 * If we receive this event while our LAP is closing down,
529 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
530 * CONNECT_PEND state forever.
531 * The other cause of getting stuck down there is if the
532 * higher layer never reply to the CONNECT_INDICATION.
533 * Anyway, it make sense to make sure that we always have
534 * a backup plan. 1 second is plenty (should be immediate).
536 irlmp_start_watchdog_timer(self
, 1*HZ
);
538 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
541 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
542 __func__
, irlmp_event
[event
], self
->slsap_sel
);
549 * Function irlmp_state_connect (self, event, skb)
554 static int irlmp_state_connect(struct lsap_cb
*self
, IRLMP_EVENT event
,
557 struct lsap_cb
*lsap
;
560 IRDA_ASSERT(self
!= NULL
, return -1;);
561 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
564 case LM_CONNECT_RESPONSE
:
566 * Bind this LSAP to the IrLAP link where the connect was
569 lsap
= hashbin_remove(irlmp
->unconnected_lsaps
, (long) self
,
572 IRDA_ASSERT(lsap
== self
, return -1;);
573 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
574 IRDA_ASSERT(self
->lap
->lsaps
!= NULL
, return -1;);
576 hashbin_insert(self
->lap
->lsaps
, (irda_queue_t
*) self
,
579 set_bit(0, &self
->connected
); /* TRUE */
581 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
582 self
->slsap_sel
, CONNECT_CNF
, skb
);
584 del_timer(&self
->watchdog_timer
);
586 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
588 case LM_WATCHDOG_TIMEOUT
:
589 /* May happen, who knows...
591 pr_debug("%s() WATCHDOG_TIMEOUT!\n", __func__
);
593 /* Disconnect, get out... - Jean II */
595 self
->dlsap_sel
= LSAP_ANY
;
596 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
599 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
600 * are *not* yet bound to the IrLAP link. Jean II */
601 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
602 __func__
, irlmp_event
[event
], self
->slsap_sel
);
609 * Function irlmp_state_connect_pend (event, skb, info)
614 static int irlmp_state_connect_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
617 struct sk_buff
*tx_skb
;
620 IRDA_ASSERT(self
!= NULL
, return -1;);
621 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
624 case LM_CONNECT_REQUEST
:
627 case LM_CONNECT_RESPONSE
:
628 pr_debug("%s(), LM_CONNECT_RESPONSE, no indication issued yet\n",
632 case LM_DISCONNECT_REQUEST
:
633 pr_debug("%s(), LM_DISCONNECT_REQUEST, not yet bound to IrLAP connection\n",
637 case LM_LAP_CONNECT_CONFIRM
:
638 pr_debug("%s(), LS_CONNECT_CONFIRM\n", __func__
);
639 irlmp_next_lsap_state(self
, LSAP_CONNECT
);
641 tx_skb
= self
->conn_skb
;
642 self
->conn_skb
= NULL
;
644 irlmp_connect_indication(self
, tx_skb
);
645 /* Drop reference count - see irlmp_connect_indication(). */
646 dev_kfree_skb(tx_skb
);
648 case LM_WATCHDOG_TIMEOUT
:
649 /* Will happen in some rare cases because of a race condition.
650 * Just make sure we don't stay there forever...
652 pr_debug("%s() WATCHDOG_TIMEOUT!\n", __func__
);
654 /* Go back to disconnected mode, keep the socket waiting */
656 self
->dlsap_sel
= LSAP_ANY
;
658 dev_kfree_skb(self
->conn_skb
);
659 self
->conn_skb
= NULL
;
660 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
663 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
664 * are *not* yet bound to the IrLAP link. Jean II */
665 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
666 __func__
, irlmp_event
[event
], self
->slsap_sel
);
673 * Function irlmp_state_dtr (self, event, skb)
675 * DATA_TRANSFER_READY
678 static int irlmp_state_dtr(struct lsap_cb
*self
, IRLMP_EVENT event
,
684 IRDA_ASSERT(self
!= NULL
, return -1;);
685 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
686 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
689 case LM_DATA_REQUEST
: /* Optimize for the common case */
690 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
691 self
->slsap_sel
, FALSE
, skb
);
693 case LM_DATA_INDICATION
: /* Optimize for the common case */
694 irlmp_data_indication(self
, skb
);
696 case LM_UDATA_REQUEST
:
697 IRDA_ASSERT(skb
!= NULL
, return -1;);
698 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
699 self
->slsap_sel
, TRUE
, skb
);
701 case LM_UDATA_INDICATION
:
702 irlmp_udata_indication(self
, skb
);
704 case LM_CONNECT_REQUEST
:
705 pr_debug("%s(), LM_CONNECT_REQUEST, error, LSAP already connected\n",
709 case LM_CONNECT_RESPONSE
:
710 pr_debug("%s(), LM_CONNECT_RESPONSE, error, LSAP already connected\n",
714 case LM_DISCONNECT_REQUEST
:
715 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
, self
->slsap_sel
,
717 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
718 /* Called only from irlmp_disconnect_request(), will
719 * unbind from LAP over there. Jean II */
721 /* Try to close the LAP connection if its still there */
723 pr_debug("%s(), trying to close IrLAP\n",
725 irlmp_do_lap_event(self
->lap
,
726 LM_LAP_DISCONNECT_REQUEST
,
730 case LM_LAP_DISCONNECT_INDICATION
:
731 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
733 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
735 irlmp_disconnect_indication(self
, reason
, NULL
);
737 case LM_DISCONNECT_INDICATION
:
738 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
740 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
741 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
743 IRDA_ASSERT(skb
!= NULL
, return -1;);
744 IRDA_ASSERT(skb
->len
> 3, return -1;);
745 reason
= skb
->data
[3];
747 /* Try to close the LAP connection */
748 pr_debug("%s(), trying to close IrLAP\n", __func__
);
749 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
751 irlmp_disconnect_indication(self
, reason
, skb
);
754 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
755 __func__
, irlmp_event
[event
], self
->slsap_sel
);
762 * Function irlmp_state_setup (event, skb, info)
764 * SETUP, Station Control has set up the underlying IrLAP connection.
765 * An LSAP connection request has been transmitted to the peer
766 * LSAP-Connection Control FSM and we are awaiting reply.
768 static int irlmp_state_setup(struct lsap_cb
*self
, IRLMP_EVENT event
,
774 IRDA_ASSERT(self
!= NULL
, return -1;);
775 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
778 case LM_CONNECT_CONFIRM
:
779 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
781 del_timer(&self
->watchdog_timer
);
783 irlmp_connect_confirm(self
, skb
);
785 case LM_DISCONNECT_INDICATION
:
786 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
788 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
789 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
791 IRDA_ASSERT(skb
!= NULL
, return -1;);
792 IRDA_ASSERT(skb
->len
> 3, return -1;);
793 reason
= skb
->data
[3];
795 /* Try to close the LAP connection */
796 pr_debug("%s(), trying to close IrLAP\n", __func__
);
797 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
799 irlmp_disconnect_indication(self
, reason
, skb
);
801 case LM_LAP_DISCONNECT_INDICATION
:
802 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
804 del_timer(&self
->watchdog_timer
);
806 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
807 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
809 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
811 irlmp_disconnect_indication(self
, reason
, skb
);
813 case LM_WATCHDOG_TIMEOUT
:
814 pr_debug("%s() WATCHDOG_TIMEOUT!\n", __func__
);
816 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
817 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
818 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
820 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
823 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
824 __func__
, irlmp_event
[event
], self
->slsap_sel
);
831 * Function irlmp_state_setup_pend (event, skb, info)
833 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
834 * user to set up an LSAP connection. A request has been sent to the
835 * LAP FSM to set up the underlying IrLAP connection, and we
836 * are awaiting confirm.
838 static int irlmp_state_setup_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
841 struct sk_buff
*tx_skb
;
845 IRDA_ASSERT(self
!= NULL
, return -1;);
846 IRDA_ASSERT(irlmp
!= NULL
, return -1;);
849 case LM_LAP_CONNECT_CONFIRM
:
850 IRDA_ASSERT(self
->conn_skb
!= NULL
, return -1;);
852 tx_skb
= self
->conn_skb
;
853 self
->conn_skb
= NULL
;
855 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
856 self
->slsap_sel
, CONNECT_CMD
, tx_skb
);
857 /* Drop reference count - see irlap_data_request(). */
858 dev_kfree_skb(tx_skb
);
860 irlmp_next_lsap_state(self
, LSAP_SETUP
);
862 case LM_WATCHDOG_TIMEOUT
:
863 pr_debug("%s() : WATCHDOG_TIMEOUT !\n", __func__
);
865 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
866 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
867 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
869 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
871 case LM_LAP_DISCONNECT_INDICATION
: /* LS_Disconnect.indication */
872 del_timer( &self
->watchdog_timer
);
874 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
876 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
878 irlmp_disconnect_indication(self
, reason
, NULL
);
881 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
882 __func__
, irlmp_event
[event
], self
->slsap_sel
);