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 #ifdef CONFIG_IRDA_DEBUG
52 static const char *const irlmp_event
[] = {
55 "LM_CONNECT_RESPONSE",
56 "LM_CONNECT_INDICATION",
58 "LM_DISCONNECT_INDICATION",
59 "LM_DISCONNECT_REQUEST",
64 "LM_UDATA_INDICATION",
66 "LM_WATCHDOG_TIMEOUT",
69 "LM_LAP_CONNECT_REQUEST",
70 "LM_LAP_CONNECT_INDICATION",
71 "LM_LAP_CONNECT_CONFIRM",
72 "LM_LAP_DISCONNECT_INDICATION",
73 "LM_LAP_DISCONNECT_REQUEST",
74 "LM_LAP_DISCOVERY_REQUEST",
75 "LM_LAP_DISCOVERY_CONFIRM",
76 "LM_LAP_IDLE_TIMEOUT",
78 #endif /* CONFIG_IRDA_DEBUG */
80 /* LAP Connection control proto declarations */
81 static void irlmp_state_standby (struct lap_cb
*, IRLMP_EVENT
,
83 static void irlmp_state_u_connect(struct lap_cb
*, IRLMP_EVENT
,
85 static void irlmp_state_active (struct lap_cb
*, IRLMP_EVENT
,
88 /* LSAP Connection control proto declarations */
89 static int irlmp_state_disconnected(struct lsap_cb
*, IRLMP_EVENT
,
91 static int irlmp_state_connect (struct lsap_cb
*, IRLMP_EVENT
,
93 static int irlmp_state_connect_pend(struct lsap_cb
*, IRLMP_EVENT
,
95 static int irlmp_state_dtr (struct lsap_cb
*, IRLMP_EVENT
,
97 static int irlmp_state_setup (struct lsap_cb
*, IRLMP_EVENT
,
99 static int irlmp_state_setup_pend (struct lsap_cb
*, IRLMP_EVENT
,
102 static void (*lap_state
[]) (struct lap_cb
*, IRLMP_EVENT
, struct sk_buff
*) =
105 irlmp_state_u_connect
,
109 static int (*lsap_state
[])( struct lsap_cb
*, IRLMP_EVENT
, struct sk_buff
*) =
111 irlmp_state_disconnected
,
113 irlmp_state_connect_pend
,
116 irlmp_state_setup_pend
119 static inline void irlmp_next_lap_state(struct lap_cb
*self
,
123 IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __func__, irlmp_state[state]);
125 self
->lap_state
= state
;
128 static inline void irlmp_next_lsap_state(struct lsap_cb
*self
,
132 IRDA_ASSERT(self != NULL, return;);
133 IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __func__, irlsap_state[state]);
135 self
->lsap_state
= state
;
138 /* Do connection control events */
139 int irlmp_do_lsap_event(struct lsap_cb
*self
, IRLMP_EVENT event
,
142 IRDA_ASSERT(self
!= NULL
, return -1;);
143 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
145 IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
146 __func__
, irlmp_event
[event
], irlsap_state
[ self
->lsap_state
]);
148 return (*lsap_state
[self
->lsap_state
]) (self
, event
, skb
);
152 * Function do_lap_event (event, skb, info)
154 * Do IrLAP control events
157 void irlmp_do_lap_event(struct lap_cb
*self
, IRLMP_EVENT event
,
160 IRDA_ASSERT(self
!= NULL
, return;);
161 IRDA_ASSERT(self
->magic
== LMP_LAP_MAGIC
, return;);
163 IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __func__
,
165 irlmp_state
[self
->lap_state
]);
167 (*lap_state
[self
->lap_state
]) (self
, event
, skb
);
170 void irlmp_discovery_timer_expired(void *data
)
172 IRDA_DEBUG(4, "%s()\n", __func__
);
174 /* We always cleanup the log (active & passive discovery) */
177 irlmp_do_discovery(sysctl_discovery_slots
);
180 irlmp_start_discovery_timer(irlmp
, sysctl_discovery_timeout
* HZ
);
183 void irlmp_watchdog_timer_expired(void *data
)
185 struct lsap_cb
*self
= (struct lsap_cb
*) data
;
187 IRDA_DEBUG(2, "%s()\n", __func__
);
189 IRDA_ASSERT(self
!= NULL
, return;);
190 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return;);
192 irlmp_do_lsap_event(self
, LM_WATCHDOG_TIMEOUT
, NULL
);
195 void irlmp_idle_timer_expired(void *data
)
197 struct lap_cb
*self
= (struct lap_cb
*) data
;
199 IRDA_DEBUG(2, "%s()\n", __func__
);
201 IRDA_ASSERT(self
!= NULL
, return;);
202 IRDA_ASSERT(self
->magic
== LMP_LAP_MAGIC
, return;);
204 irlmp_do_lap_event(self
, LM_LAP_IDLE_TIMEOUT
, NULL
);
208 * Send an event on all LSAPs attached to this LAP.
211 irlmp_do_all_lsap_event(hashbin_t
* lsap_hashbin
,
214 struct lsap_cb
*lsap
;
215 struct lsap_cb
*lsap_next
;
217 /* Note : this function use the new hashbin_find_next()
218 * function, instead of the old hashbin_get_next().
219 * This make sure that we are always pointing one lsap
220 * ahead, so that if the current lsap is removed as the
221 * result of sending the event, we don't care.
222 * Also, as we store the context ourselves, if an enumeration
223 * of the same lsap hashbin happens as the result of sending the
224 * event, we don't care.
225 * The only problem is if the next lsap is removed. In that case,
226 * hashbin_find_next() will return NULL and we will abort the
227 * enumeration. - Jean II */
229 /* Also : we don't accept any skb in input. We can *NOT* pass
230 * the same skb to multiple clients safely, we would need to
231 * skb_clone() it. - Jean II */
233 lsap
= (struct lsap_cb
*) hashbin_get_first(lsap_hashbin
);
235 while (NULL
!= hashbin_find_next(lsap_hashbin
,
238 (void *) &lsap_next
) ) {
239 irlmp_do_lsap_event(lsap
, event
, NULL
);
244 /*********************************************************************
246 * LAP connection control states
248 ********************************************************************/
251 * Function irlmp_state_standby (event, skb, info)
253 * STANDBY, The IrLAP connection does not exist.
256 static void irlmp_state_standby(struct lap_cb
*self
, IRLMP_EVENT event
,
259 IRDA_DEBUG(4, "%s()\n", __func__
);
260 IRDA_ASSERT(self
->irlap
!= NULL
, return;);
263 case LM_LAP_DISCOVERY_REQUEST
:
264 /* irlmp_next_station_state( LMP_DISCOVER); */
266 irlap_discovery_request(self
->irlap
, &irlmp
->discovery_cmd
);
268 case LM_LAP_CONNECT_INDICATION
:
269 /* It's important to switch state first, to avoid IrLMP to
270 * think that the link is free since IrLMP may then start
271 * discovery before the connection is properly set up. DB.
273 irlmp_next_lap_state(self
, LAP_ACTIVE
);
275 /* Just accept connection TODO, this should be fixed */
276 irlap_connect_response(self
->irlap
, skb
);
278 case LM_LAP_CONNECT_REQUEST
:
279 IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __func__
);
281 irlmp_next_lap_state(self
, LAP_U_CONNECT
);
283 /* FIXME: need to set users requested QoS */
284 irlap_connect_request(self
->irlap
, self
->daddr
, NULL
, 0);
286 case LM_LAP_DISCONNECT_INDICATION
:
287 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
290 irlmp_next_lap_state(self
, LAP_STANDBY
);
293 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
294 __func__
, irlmp_event
[event
]);
300 * Function irlmp_state_u_connect (event, skb, info)
302 * U_CONNECT, The layer above has tried to open an LSAP connection but
303 * since the IrLAP connection does not exist, we must first start an
304 * IrLAP connection. We are now waiting response from IrLAP.
306 static void irlmp_state_u_connect(struct lap_cb
*self
, IRLMP_EVENT event
,
309 IRDA_DEBUG(2, "%s(), event=%s\n", __func__
, irlmp_event
[event
]);
312 case LM_LAP_CONNECT_INDICATION
:
313 /* It's important to switch state first, to avoid IrLMP to
314 * think that the link is free since IrLMP may then start
315 * discovery before the connection is properly set up. DB.
317 irlmp_next_lap_state(self
, LAP_ACTIVE
);
319 /* Just accept connection TODO, this should be fixed */
320 irlap_connect_response(self
->irlap
, skb
);
322 /* Tell LSAPs that they can start sending data */
323 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
325 /* Note : by the time we get there (LAP retries and co),
326 * the lsaps may already have gone. This avoid getting stuck
327 * forever in LAP_ACTIVE state - Jean II */
328 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
329 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __func__
);
330 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
333 case LM_LAP_CONNECT_REQUEST
:
334 /* Already trying to connect */
336 case LM_LAP_CONNECT_CONFIRM
:
337 /* For all lsap_ce E Associated do LS_Connect_confirm */
338 irlmp_next_lap_state(self
, LAP_ACTIVE
);
340 /* Tell LSAPs that they can start sending data */
341 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
343 /* Note : by the time we get there (LAP retries and co),
344 * the lsaps may already have gone. This avoid getting stuck
345 * forever in LAP_ACTIVE state - Jean II */
346 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
347 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __func__
);
348 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
351 case LM_LAP_DISCONNECT_INDICATION
:
352 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __func__
);
353 irlmp_next_lap_state(self
, LAP_STANDBY
);
355 /* Send disconnect event to all LSAPs using this link */
356 irlmp_do_all_lsap_event(self
->lsaps
,
357 LM_LAP_DISCONNECT_INDICATION
);
359 case LM_LAP_DISCONNECT_REQUEST
:
360 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __func__
);
362 /* One of the LSAP did timeout or was closed, if it was
363 * the last one, try to get out of here - Jean II */
364 if (HASHBIN_GET_SIZE(self
->lsaps
) <= 1) {
365 irlap_disconnect_request(self
->irlap
);
369 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
370 __func__
, irlmp_event
[event
]);
376 * Function irlmp_state_active (event, skb, info)
378 * ACTIVE, IrLAP connection is active
381 static void irlmp_state_active(struct lap_cb
*self
, IRLMP_EVENT event
,
384 IRDA_DEBUG(4, "%s()\n", __func__
);
387 case LM_LAP_CONNECT_REQUEST
:
388 IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __func__
);
391 * IrLAP may have a pending disconnect. We tried to close
392 * IrLAP, but it was postponed because the link was
393 * busy or we were still sending packets. As we now
394 * need it, make sure it stays on. Jean II
396 irlap_clear_disconnect(self
->irlap
);
399 * LAP connection already active, just bounce back! Since we
400 * don't know which LSAP that tried to do this, we have to
401 * notify all LSAPs using this LAP, but that should be safe to
404 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
406 /* Needed by connect indication */
407 irlmp_do_all_lsap_event(irlmp
->unconnected_lsaps
,
408 LM_LAP_CONNECT_CONFIRM
);
411 case LM_LAP_DISCONNECT_REQUEST
:
413 * Need to find out if we should close IrLAP or not. If there
414 * is only one LSAP connection left on this link, that LSAP
415 * must be the one that tries to close IrLAP. It will be
416 * removed later and moved to the list of unconnected LSAPs
418 if (HASHBIN_GET_SIZE(self
->lsaps
) > 0) {
419 /* Timer value is checked in irsysctl - Jean II */
420 irlmp_start_idle_timer(self
, sysctl_lap_keepalive_time
* HZ
/ 1000);
422 /* No more connections, so close IrLAP */
424 /* We don't want to change state just yet, because
425 * we want to reflect accurately the real state of
426 * the LAP, not the state we wish it was in,
427 * so that we don't lose LM_LAP_CONNECT_REQUEST.
428 * In some cases, IrLAP won't close the LAP
429 * immediately. For example, it might still be
430 * retrying packets or waiting for the pf bit.
431 * As the LAP always send a DISCONNECT_INDICATION
432 * in PCLOSE or SCLOSE, just change state on that.
434 irlap_disconnect_request(self
->irlap
);
437 case LM_LAP_IDLE_TIMEOUT
:
438 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
439 /* Same reasoning as above - keep state */
440 irlap_disconnect_request(self
->irlap
);
443 case LM_LAP_DISCONNECT_INDICATION
:
444 irlmp_next_lap_state(self
, LAP_STANDBY
);
446 /* In some case, at this point our side has already closed
447 * all lsaps, and we are waiting for the idle_timer to
448 * expire. If another device reconnect immediately, the
449 * idle timer will expire in the midle of the connection
450 * initialisation, screwing up things a lot...
451 * Therefore, we must stop the timer... */
452 irlmp_stop_idle_timer(self
);
455 * Inform all connected LSAP's using this link
457 irlmp_do_all_lsap_event(self
->lsaps
,
458 LM_LAP_DISCONNECT_INDICATION
);
460 /* Force an expiry of the discovery log.
461 * Now that the LAP is free, the system may attempt to
462 * connect to another device. Unfortunately, our entries
463 * are stale. There is a small window (<3s) before the
464 * normal discovery will run and where irlmp_connect_request()
465 * can get the wrong info, so make sure things get
466 * cleaned *NOW* ;-) - Jean II */
470 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
471 __func__
, irlmp_event
[event
]);
476 /*********************************************************************
478 * LSAP connection control states
480 ********************************************************************/
483 * Function irlmp_state_disconnected (event, skb, info)
488 static int irlmp_state_disconnected(struct lsap_cb
*self
, IRLMP_EVENT event
,
493 IRDA_DEBUG(4, "%s()\n", __func__
);
495 IRDA_ASSERT(self
!= NULL
, return -1;);
496 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
499 #ifdef CONFIG_IRDA_ULTRA
500 case LM_UDATA_INDICATION
:
501 /* This is most bizzare. Those packets are aka unreliable
502 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
503 * Why do we pass them as Ultra ??? Jean II */
504 irlmp_connless_data_indication(self
, skb
);
506 #endif /* CONFIG_IRDA_ULTRA */
507 case LM_CONNECT_REQUEST
:
508 IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __func__
);
510 if (self
->conn_skb
) {
511 IRDA_WARNING("%s: busy with another request!\n",
515 /* Don't forget to refcount it (see irlmp_connect_request()) */
517 self
->conn_skb
= skb
;
519 irlmp_next_lsap_state(self
, LSAP_SETUP_PEND
);
521 /* Start watchdog timer (5 secs for now) */
522 irlmp_start_watchdog_timer(self
, 5*HZ
);
524 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
526 case LM_CONNECT_INDICATION
:
527 if (self
->conn_skb
) {
528 IRDA_WARNING("%s: busy with another request!\n",
532 /* Don't forget to refcount it (see irlap_driver_rcv()) */
534 self
->conn_skb
= skb
;
536 irlmp_next_lsap_state(self
, LSAP_CONNECT_PEND
);
538 /* Start watchdog timer
539 * This is not mentionned in the spec, but there is a rare
540 * race condition that can get the socket stuck.
541 * If we receive this event while our LAP is closing down,
542 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
543 * CONNECT_PEND state forever.
544 * The other cause of getting stuck down there is if the
545 * higher layer never reply to the CONNECT_INDICATION.
546 * Anyway, it make sense to make sure that we always have
547 * a backup plan. 1 second is plenty (should be immediate).
549 irlmp_start_watchdog_timer(self
, 1*HZ
);
551 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
554 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
555 __func__
, irlmp_event
[event
], self
->slsap_sel
);
562 * Function irlmp_state_connect (self, event, skb)
567 static int irlmp_state_connect(struct lsap_cb
*self
, IRLMP_EVENT event
,
570 struct lsap_cb
*lsap
;
573 IRDA_DEBUG(4, "%s()\n", __func__
);
575 IRDA_ASSERT(self
!= NULL
, return -1;);
576 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
579 case LM_CONNECT_RESPONSE
:
581 * Bind this LSAP to the IrLAP link where the connect was
584 lsap
= hashbin_remove(irlmp
->unconnected_lsaps
, (long) self
,
587 IRDA_ASSERT(lsap
== self
, return -1;);
588 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
589 IRDA_ASSERT(self
->lap
->lsaps
!= NULL
, return -1;);
591 hashbin_insert(self
->lap
->lsaps
, (irda_queue_t
*) self
,
594 set_bit(0, &self
->connected
); /* TRUE */
596 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
597 self
->slsap_sel
, CONNECT_CNF
, skb
);
599 del_timer(&self
->watchdog_timer
);
601 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
603 case LM_WATCHDOG_TIMEOUT
:
604 /* May happen, who knows...
606 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__
);
608 /* Disconnect, get out... - Jean II */
610 self
->dlsap_sel
= LSAP_ANY
;
611 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
614 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
615 * are *not* yet bound to the IrLAP link. Jean II */
616 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
617 __func__
, irlmp_event
[event
], self
->slsap_sel
);
624 * Function irlmp_state_connect_pend (event, skb, info)
629 static int irlmp_state_connect_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
632 struct sk_buff
*tx_skb
;
635 IRDA_DEBUG(4, "%s()\n", __func__
);
637 IRDA_ASSERT(self
!= NULL
, return -1;);
638 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
641 case LM_CONNECT_REQUEST
:
644 case LM_CONNECT_RESPONSE
:
645 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
646 "no indication issued yet\n", __func__
);
649 case LM_DISCONNECT_REQUEST
:
650 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
651 "not yet bound to IrLAP connection\n", __func__
);
654 case LM_LAP_CONNECT_CONFIRM
:
655 IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __func__
);
656 irlmp_next_lsap_state(self
, LSAP_CONNECT
);
658 tx_skb
= self
->conn_skb
;
659 self
->conn_skb
= NULL
;
661 irlmp_connect_indication(self
, tx_skb
);
662 /* Drop reference count - see irlmp_connect_indication(). */
663 dev_kfree_skb(tx_skb
);
665 case LM_WATCHDOG_TIMEOUT
:
666 /* Will happen in some rare cases because of a race condition.
667 * Just make sure we don't stay there forever...
669 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__
);
671 /* Go back to disconnected mode, keep the socket waiting */
673 self
->dlsap_sel
= LSAP_ANY
;
675 dev_kfree_skb(self
->conn_skb
);
676 self
->conn_skb
= NULL
;
677 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
680 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
681 * are *not* yet bound to the IrLAP link. Jean II */
682 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
683 __func__
, irlmp_event
[event
], self
->slsap_sel
);
690 * Function irlmp_state_dtr (self, event, skb)
692 * DATA_TRANSFER_READY
695 static int irlmp_state_dtr(struct lsap_cb
*self
, IRLMP_EVENT event
,
701 IRDA_DEBUG(4, "%s()\n", __func__
);
703 IRDA_ASSERT(self
!= NULL
, return -1;);
704 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
705 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
708 case LM_DATA_REQUEST
: /* Optimize for the common case */
709 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
710 self
->slsap_sel
, FALSE
, skb
);
712 case LM_DATA_INDICATION
: /* Optimize for the common case */
713 irlmp_data_indication(self
, skb
);
715 case LM_UDATA_REQUEST
:
716 IRDA_ASSERT(skb
!= NULL
, return -1;);
717 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
718 self
->slsap_sel
, TRUE
, skb
);
720 case LM_UDATA_INDICATION
:
721 irlmp_udata_indication(self
, skb
);
723 case LM_CONNECT_REQUEST
:
724 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
725 "error, LSAP already connected\n", __func__
);
728 case LM_CONNECT_RESPONSE
:
729 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
730 "error, LSAP already connected\n", __func__
);
733 case LM_DISCONNECT_REQUEST
:
734 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
, self
->slsap_sel
,
736 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
737 /* Called only from irlmp_disconnect_request(), will
738 * unbind from LAP over there. Jean II */
740 /* Try to close the LAP connection if its still there */
742 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
744 irlmp_do_lap_event(self
->lap
,
745 LM_LAP_DISCONNECT_REQUEST
,
749 case LM_LAP_DISCONNECT_INDICATION
:
750 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
752 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
754 irlmp_disconnect_indication(self
, reason
, NULL
);
756 case LM_DISCONNECT_INDICATION
:
757 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
759 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
760 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
762 IRDA_ASSERT(skb
!= NULL
, return -1;);
763 IRDA_ASSERT(skb
->len
> 3, return -1;);
764 reason
= skb
->data
[3];
766 /* Try to close the LAP connection */
767 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__
);
768 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
770 irlmp_disconnect_indication(self
, reason
, skb
);
773 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
774 __func__
, irlmp_event
[event
], self
->slsap_sel
);
781 * Function irlmp_state_setup (event, skb, info)
783 * SETUP, Station Control has set up the underlying IrLAP connection.
784 * An LSAP connection request has been transmitted to the peer
785 * LSAP-Connection Control FSM and we are awaiting reply.
787 static int irlmp_state_setup(struct lsap_cb
*self
, IRLMP_EVENT event
,
793 IRDA_ASSERT(self
!= NULL
, return -1;);
794 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
796 IRDA_DEBUG(4, "%s()\n", __func__
);
799 case LM_CONNECT_CONFIRM
:
800 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
802 del_timer(&self
->watchdog_timer
);
804 irlmp_connect_confirm(self
, skb
);
806 case LM_DISCONNECT_INDICATION
:
807 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
809 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
810 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
812 IRDA_ASSERT(skb
!= NULL
, return -1;);
813 IRDA_ASSERT(skb
->len
> 3, return -1;);
814 reason
= skb
->data
[3];
816 /* Try to close the LAP connection */
817 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__
);
818 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
820 irlmp_disconnect_indication(self
, reason
, skb
);
822 case LM_LAP_DISCONNECT_INDICATION
:
823 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
825 del_timer(&self
->watchdog_timer
);
827 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
828 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
830 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
832 irlmp_disconnect_indication(self
, reason
, skb
);
834 case LM_WATCHDOG_TIMEOUT
:
835 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__
);
837 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
838 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
839 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
841 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
844 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
845 __func__
, irlmp_event
[event
], self
->slsap_sel
);
852 * Function irlmp_state_setup_pend (event, skb, info)
854 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
855 * user to set up an LSAP connection. A request has been sent to the
856 * LAP FSM to set up the underlying IrLAP connection, and we
857 * are awaiting confirm.
859 static int irlmp_state_setup_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
862 struct sk_buff
*tx_skb
;
866 IRDA_DEBUG(4, "%s()\n", __func__
);
868 IRDA_ASSERT(self
!= NULL
, return -1;);
869 IRDA_ASSERT(irlmp
!= NULL
, return -1;);
872 case LM_LAP_CONNECT_CONFIRM
:
873 IRDA_ASSERT(self
->conn_skb
!= NULL
, return -1;);
875 tx_skb
= self
->conn_skb
;
876 self
->conn_skb
= NULL
;
878 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
879 self
->slsap_sel
, CONNECT_CMD
, tx_skb
);
880 /* Drop reference count - see irlap_data_request(). */
881 dev_kfree_skb(tx_skb
);
883 irlmp_next_lsap_state(self
, LSAP_SETUP
);
885 case LM_WATCHDOG_TIMEOUT
:
886 IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __func__
);
888 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
889 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
890 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
892 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
894 case LM_LAP_DISCONNECT_INDICATION
: /* LS_Disconnect.indication */
895 del_timer( &self
->watchdog_timer
);
897 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
899 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
901 irlmp_disconnect_indication(self
, reason
, NULL
);
904 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
905 __func__
, irlmp_event
[event
], self
->slsap_sel
);