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 pr_debug("%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 pr_debug("%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 pr_debug("%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 pr_debug("%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 /* We always cleanup the log (active & passive discovery) */
175 irlmp_do_discovery(sysctl_discovery_slots
);
178 irlmp_start_discovery_timer(irlmp
, sysctl_discovery_timeout
* HZ
);
181 void irlmp_watchdog_timer_expired(void *data
)
183 struct lsap_cb
*self
= (struct lsap_cb
*) data
;
185 IRDA_ASSERT(self
!= NULL
, return;);
186 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return;);
188 irlmp_do_lsap_event(self
, LM_WATCHDOG_TIMEOUT
, NULL
);
191 void irlmp_idle_timer_expired(void *data
)
193 struct lap_cb
*self
= (struct lap_cb
*) data
;
195 IRDA_ASSERT(self
!= NULL
, return;);
196 IRDA_ASSERT(self
->magic
== LMP_LAP_MAGIC
, return;);
198 irlmp_do_lap_event(self
, LM_LAP_IDLE_TIMEOUT
, NULL
);
202 * Send an event on all LSAPs attached to this LAP.
205 irlmp_do_all_lsap_event(hashbin_t
* lsap_hashbin
,
208 struct lsap_cb
*lsap
;
209 struct lsap_cb
*lsap_next
;
211 /* Note : this function use the new hashbin_find_next()
212 * function, instead of the old hashbin_get_next().
213 * This make sure that we are always pointing one lsap
214 * ahead, so that if the current lsap is removed as the
215 * result of sending the event, we don't care.
216 * Also, as we store the context ourselves, if an enumeration
217 * of the same lsap hashbin happens as the result of sending the
218 * event, we don't care.
219 * The only problem is if the next lsap is removed. In that case,
220 * hashbin_find_next() will return NULL and we will abort the
221 * enumeration. - Jean II */
223 /* Also : we don't accept any skb in input. We can *NOT* pass
224 * the same skb to multiple clients safely, we would need to
225 * skb_clone() it. - Jean II */
227 lsap
= (struct lsap_cb
*) hashbin_get_first(lsap_hashbin
);
229 while (NULL
!= hashbin_find_next(lsap_hashbin
,
232 (void *) &lsap_next
) ) {
233 irlmp_do_lsap_event(lsap
, event
, NULL
);
238 /*********************************************************************
240 * LAP connection control states
242 ********************************************************************/
245 * Function irlmp_state_standby (event, skb, info)
247 * STANDBY, The IrLAP connection does not exist.
250 static void irlmp_state_standby(struct lap_cb
*self
, IRLMP_EVENT event
,
253 IRDA_ASSERT(self
->irlap
!= NULL
, return;);
256 case LM_LAP_DISCOVERY_REQUEST
:
257 /* irlmp_next_station_state( LMP_DISCOVER); */
259 irlap_discovery_request(self
->irlap
, &irlmp
->discovery_cmd
);
261 case LM_LAP_CONNECT_INDICATION
:
262 /* It's important to switch state first, to avoid IrLMP to
263 * think that the link is free since IrLMP may then start
264 * discovery before the connection is properly set up. DB.
266 irlmp_next_lap_state(self
, LAP_ACTIVE
);
268 /* Just accept connection TODO, this should be fixed */
269 irlap_connect_response(self
->irlap
, skb
);
271 case LM_LAP_CONNECT_REQUEST
:
272 pr_debug("%s() LS_CONNECT_REQUEST\n", __func__
);
274 irlmp_next_lap_state(self
, LAP_U_CONNECT
);
276 /* FIXME: need to set users requested QoS */
277 irlap_connect_request(self
->irlap
, self
->daddr
, NULL
, 0);
279 case LM_LAP_DISCONNECT_INDICATION
:
280 pr_debug("%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
283 irlmp_next_lap_state(self
, LAP_STANDBY
);
286 pr_debug("%s(), Unknown event %s\n",
287 __func__
, irlmp_event
[event
]);
293 * Function irlmp_state_u_connect (event, skb, info)
295 * U_CONNECT, The layer above has tried to open an LSAP connection but
296 * since the IrLAP connection does not exist, we must first start an
297 * IrLAP connection. We are now waiting response from IrLAP.
299 static void irlmp_state_u_connect(struct lap_cb
*self
, IRLMP_EVENT event
,
302 pr_debug("%s(), event=%s\n", __func__
, irlmp_event
[event
]);
305 case LM_LAP_CONNECT_INDICATION
:
306 /* It's important to switch state first, to avoid IrLMP to
307 * think that the link is free since IrLMP may then start
308 * discovery before the connection is properly set up. DB.
310 irlmp_next_lap_state(self
, LAP_ACTIVE
);
312 /* Just accept connection TODO, this should be fixed */
313 irlap_connect_response(self
->irlap
, skb
);
315 /* Tell LSAPs that they can start sending data */
316 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
318 /* Note : by the time we get there (LAP retries and co),
319 * the lsaps may already have gone. This avoid getting stuck
320 * forever in LAP_ACTIVE state - Jean II */
321 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
322 pr_debug("%s() NO LSAPs !\n", __func__
);
323 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
326 case LM_LAP_CONNECT_REQUEST
:
327 /* Already trying to connect */
329 case LM_LAP_CONNECT_CONFIRM
:
330 /* For all lsap_ce E Associated do LS_Connect_confirm */
331 irlmp_next_lap_state(self
, LAP_ACTIVE
);
333 /* Tell LSAPs that they can start sending data */
334 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
336 /* Note : by the time we get there (LAP retries and co),
337 * the lsaps may already have gone. This avoid getting stuck
338 * forever in LAP_ACTIVE state - Jean II */
339 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
340 pr_debug("%s() NO LSAPs !\n", __func__
);
341 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
344 case LM_LAP_DISCONNECT_INDICATION
:
345 pr_debug("%s(), LM_LAP_DISCONNECT_INDICATION\n", __func__
);
346 irlmp_next_lap_state(self
, LAP_STANDBY
);
348 /* Send disconnect event to all LSAPs using this link */
349 irlmp_do_all_lsap_event(self
->lsaps
,
350 LM_LAP_DISCONNECT_INDICATION
);
352 case LM_LAP_DISCONNECT_REQUEST
:
353 pr_debug("%s(), LM_LAP_DISCONNECT_REQUEST\n", __func__
);
355 /* One of the LSAP did timeout or was closed, if it was
356 * the last one, try to get out of here - Jean II */
357 if (HASHBIN_GET_SIZE(self
->lsaps
) <= 1) {
358 irlap_disconnect_request(self
->irlap
);
362 pr_debug("%s(), Unknown event %s\n",
363 __func__
, irlmp_event
[event
]);
369 * Function irlmp_state_active (event, skb, info)
371 * ACTIVE, IrLAP connection is active
374 static void irlmp_state_active(struct lap_cb
*self
, IRLMP_EVENT event
,
378 case LM_LAP_CONNECT_REQUEST
:
379 pr_debug("%s(), LS_CONNECT_REQUEST\n", __func__
);
382 * IrLAP may have a pending disconnect. We tried to close
383 * IrLAP, but it was postponed because the link was
384 * busy or we were still sending packets. As we now
385 * need it, make sure it stays on. Jean II
387 irlap_clear_disconnect(self
->irlap
);
390 * LAP connection already active, just bounce back! Since we
391 * don't know which LSAP that tried to do this, we have to
392 * notify all LSAPs using this LAP, but that should be safe to
395 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
397 /* Needed by connect indication */
398 irlmp_do_all_lsap_event(irlmp
->unconnected_lsaps
,
399 LM_LAP_CONNECT_CONFIRM
);
402 case LM_LAP_DISCONNECT_REQUEST
:
404 * Need to find out if we should close IrLAP or not. If there
405 * is only one LSAP connection left on this link, that LSAP
406 * must be the one that tries to close IrLAP. It will be
407 * removed later and moved to the list of unconnected LSAPs
409 if (HASHBIN_GET_SIZE(self
->lsaps
) > 0) {
410 /* Timer value is checked in irsysctl - Jean II */
411 irlmp_start_idle_timer(self
, sysctl_lap_keepalive_time
* HZ
/ 1000);
413 /* No more connections, so close IrLAP */
415 /* We don't want to change state just yet, because
416 * we want to reflect accurately the real state of
417 * the LAP, not the state we wish it was in,
418 * so that we don't lose LM_LAP_CONNECT_REQUEST.
419 * In some cases, IrLAP won't close the LAP
420 * immediately. For example, it might still be
421 * retrying packets or waiting for the pf bit.
422 * As the LAP always send a DISCONNECT_INDICATION
423 * in PCLOSE or SCLOSE, just change state on that.
425 irlap_disconnect_request(self
->irlap
);
428 case LM_LAP_IDLE_TIMEOUT
:
429 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
430 /* Same reasoning as above - keep state */
431 irlap_disconnect_request(self
->irlap
);
434 case LM_LAP_DISCONNECT_INDICATION
:
435 irlmp_next_lap_state(self
, LAP_STANDBY
);
437 /* In some case, at this point our side has already closed
438 * all lsaps, and we are waiting for the idle_timer to
439 * expire. If another device reconnect immediately, the
440 * idle timer will expire in the midle of the connection
441 * initialisation, screwing up things a lot...
442 * Therefore, we must stop the timer... */
443 irlmp_stop_idle_timer(self
);
446 * Inform all connected LSAP's using this link
448 irlmp_do_all_lsap_event(self
->lsaps
,
449 LM_LAP_DISCONNECT_INDICATION
);
451 /* Force an expiry of the discovery log.
452 * Now that the LAP is free, the system may attempt to
453 * connect to another device. Unfortunately, our entries
454 * are stale. There is a small window (<3s) before the
455 * normal discovery will run and where irlmp_connect_request()
456 * can get the wrong info, so make sure things get
457 * cleaned *NOW* ;-) - Jean II */
461 pr_debug("%s(), Unknown event %s\n",
462 __func__
, irlmp_event
[event
]);
467 /*********************************************************************
469 * LSAP connection control states
471 ********************************************************************/
474 * Function irlmp_state_disconnected (event, skb, info)
479 static int irlmp_state_disconnected(struct lsap_cb
*self
, IRLMP_EVENT event
,
484 IRDA_ASSERT(self
!= NULL
, return -1;);
485 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
488 #ifdef CONFIG_IRDA_ULTRA
489 case LM_UDATA_INDICATION
:
490 /* This is most bizarre. Those packets are aka unreliable
491 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
492 * Why do we pass them as Ultra ??? Jean II */
493 irlmp_connless_data_indication(self
, skb
);
495 #endif /* CONFIG_IRDA_ULTRA */
496 case LM_CONNECT_REQUEST
:
497 pr_debug("%s(), LM_CONNECT_REQUEST\n", __func__
);
499 if (self
->conn_skb
) {
500 net_warn_ratelimited("%s: busy with another request!\n",
504 /* Don't forget to refcount it (see irlmp_connect_request()) */
506 self
->conn_skb
= skb
;
508 irlmp_next_lsap_state(self
, LSAP_SETUP_PEND
);
510 /* Start watchdog timer (5 secs for now) */
511 irlmp_start_watchdog_timer(self
, 5*HZ
);
513 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
515 case LM_CONNECT_INDICATION
:
516 if (self
->conn_skb
) {
517 net_warn_ratelimited("%s: busy with another request!\n",
521 /* Don't forget to refcount it (see irlap_driver_rcv()) */
523 self
->conn_skb
= skb
;
525 irlmp_next_lsap_state(self
, LSAP_CONNECT_PEND
);
527 /* Start watchdog timer
528 * This is not mentionned in the spec, but there is a rare
529 * race condition that can get the socket stuck.
530 * If we receive this event while our LAP is closing down,
531 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
532 * CONNECT_PEND state forever.
533 * The other cause of getting stuck down there is if the
534 * higher layer never reply to the CONNECT_INDICATION.
535 * Anyway, it make sense to make sure that we always have
536 * a backup plan. 1 second is plenty (should be immediate).
538 irlmp_start_watchdog_timer(self
, 1*HZ
);
540 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
543 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
544 __func__
, irlmp_event
[event
], self
->slsap_sel
);
551 * Function irlmp_state_connect (self, event, skb)
556 static int irlmp_state_connect(struct lsap_cb
*self
, IRLMP_EVENT event
,
559 struct lsap_cb
*lsap
;
562 IRDA_ASSERT(self
!= NULL
, return -1;);
563 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
566 case LM_CONNECT_RESPONSE
:
568 * Bind this LSAP to the IrLAP link where the connect was
571 lsap
= hashbin_remove(irlmp
->unconnected_lsaps
, (long) self
,
574 IRDA_ASSERT(lsap
== self
, return -1;);
575 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
576 IRDA_ASSERT(self
->lap
->lsaps
!= NULL
, return -1;);
578 hashbin_insert(self
->lap
->lsaps
, (irda_queue_t
*) self
,
581 set_bit(0, &self
->connected
); /* TRUE */
583 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
584 self
->slsap_sel
, CONNECT_CNF
, skb
);
586 del_timer(&self
->watchdog_timer
);
588 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
590 case LM_WATCHDOG_TIMEOUT
:
591 /* May happen, who knows...
593 pr_debug("%s() WATCHDOG_TIMEOUT!\n", __func__
);
595 /* Disconnect, get out... - Jean II */
597 self
->dlsap_sel
= LSAP_ANY
;
598 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
601 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
602 * are *not* yet bound to the IrLAP link. Jean II */
603 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
604 __func__
, irlmp_event
[event
], self
->slsap_sel
);
611 * Function irlmp_state_connect_pend (event, skb, info)
616 static int irlmp_state_connect_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
619 struct sk_buff
*tx_skb
;
622 IRDA_ASSERT(self
!= NULL
, return -1;);
623 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
626 case LM_CONNECT_REQUEST
:
629 case LM_CONNECT_RESPONSE
:
630 pr_debug("%s(), LM_CONNECT_RESPONSE, no indication issued yet\n",
634 case LM_DISCONNECT_REQUEST
:
635 pr_debug("%s(), LM_DISCONNECT_REQUEST, not yet bound to IrLAP connection\n",
639 case LM_LAP_CONNECT_CONFIRM
:
640 pr_debug("%s(), LS_CONNECT_CONFIRM\n", __func__
);
641 irlmp_next_lsap_state(self
, LSAP_CONNECT
);
643 tx_skb
= self
->conn_skb
;
644 self
->conn_skb
= NULL
;
646 irlmp_connect_indication(self
, tx_skb
);
647 /* Drop reference count - see irlmp_connect_indication(). */
648 dev_kfree_skb(tx_skb
);
650 case LM_WATCHDOG_TIMEOUT
:
651 /* Will happen in some rare cases because of a race condition.
652 * Just make sure we don't stay there forever...
654 pr_debug("%s() WATCHDOG_TIMEOUT!\n", __func__
);
656 /* Go back to disconnected mode, keep the socket waiting */
658 self
->dlsap_sel
= LSAP_ANY
;
660 dev_kfree_skb(self
->conn_skb
);
661 self
->conn_skb
= NULL
;
662 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
665 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
666 * are *not* yet bound to the IrLAP link. Jean II */
667 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
668 __func__
, irlmp_event
[event
], self
->slsap_sel
);
675 * Function irlmp_state_dtr (self, event, skb)
677 * DATA_TRANSFER_READY
680 static int irlmp_state_dtr(struct lsap_cb
*self
, IRLMP_EVENT event
,
686 IRDA_ASSERT(self
!= NULL
, return -1;);
687 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
688 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
691 case LM_DATA_REQUEST
: /* Optimize for the common case */
692 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
693 self
->slsap_sel
, FALSE
, skb
);
695 case LM_DATA_INDICATION
: /* Optimize for the common case */
696 irlmp_data_indication(self
, skb
);
698 case LM_UDATA_REQUEST
:
699 IRDA_ASSERT(skb
!= NULL
, return -1;);
700 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
701 self
->slsap_sel
, TRUE
, skb
);
703 case LM_UDATA_INDICATION
:
704 irlmp_udata_indication(self
, skb
);
706 case LM_CONNECT_REQUEST
:
707 pr_debug("%s(), LM_CONNECT_REQUEST, error, LSAP already connected\n",
711 case LM_CONNECT_RESPONSE
:
712 pr_debug("%s(), LM_CONNECT_RESPONSE, error, LSAP already connected\n",
716 case LM_DISCONNECT_REQUEST
:
717 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
, self
->slsap_sel
,
719 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
720 /* Called only from irlmp_disconnect_request(), will
721 * unbind from LAP over there. Jean II */
723 /* Try to close the LAP connection if its still there */
725 pr_debug("%s(), trying to close IrLAP\n",
727 irlmp_do_lap_event(self
->lap
,
728 LM_LAP_DISCONNECT_REQUEST
,
732 case LM_LAP_DISCONNECT_INDICATION
:
733 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
735 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
737 irlmp_disconnect_indication(self
, reason
, NULL
);
739 case LM_DISCONNECT_INDICATION
:
740 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
742 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
743 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
745 IRDA_ASSERT(skb
!= NULL
, return -1;);
746 IRDA_ASSERT(skb
->len
> 3, return -1;);
747 reason
= skb
->data
[3];
749 /* Try to close the LAP connection */
750 pr_debug("%s(), trying to close IrLAP\n", __func__
);
751 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
753 irlmp_disconnect_indication(self
, reason
, skb
);
756 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
757 __func__
, irlmp_event
[event
], self
->slsap_sel
);
764 * Function irlmp_state_setup (event, skb, info)
766 * SETUP, Station Control has set up the underlying IrLAP connection.
767 * An LSAP connection request has been transmitted to the peer
768 * LSAP-Connection Control FSM and we are awaiting reply.
770 static int irlmp_state_setup(struct lsap_cb
*self
, IRLMP_EVENT event
,
776 IRDA_ASSERT(self
!= NULL
, return -1;);
777 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
780 case LM_CONNECT_CONFIRM
:
781 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
783 del_timer(&self
->watchdog_timer
);
785 irlmp_connect_confirm(self
, skb
);
787 case LM_DISCONNECT_INDICATION
:
788 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
790 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
791 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
793 IRDA_ASSERT(skb
!= NULL
, return -1;);
794 IRDA_ASSERT(skb
->len
> 3, return -1;);
795 reason
= skb
->data
[3];
797 /* Try to close the LAP connection */
798 pr_debug("%s(), trying to close IrLAP\n", __func__
);
799 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
801 irlmp_disconnect_indication(self
, reason
, skb
);
803 case LM_LAP_DISCONNECT_INDICATION
:
804 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
806 del_timer(&self
->watchdog_timer
);
808 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
809 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
811 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
813 irlmp_disconnect_indication(self
, reason
, skb
);
815 case LM_WATCHDOG_TIMEOUT
:
816 pr_debug("%s() WATCHDOG_TIMEOUT!\n", __func__
);
818 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
819 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
820 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
822 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
825 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
826 __func__
, irlmp_event
[event
], self
->slsap_sel
);
833 * Function irlmp_state_setup_pend (event, skb, info)
835 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
836 * user to set up an LSAP connection. A request has been sent to the
837 * LAP FSM to set up the underlying IrLAP connection, and we
838 * are awaiting confirm.
840 static int irlmp_state_setup_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
843 struct sk_buff
*tx_skb
;
847 IRDA_ASSERT(self
!= NULL
, return -1;);
848 IRDA_ASSERT(irlmp
!= NULL
, return -1;);
851 case LM_LAP_CONNECT_CONFIRM
:
852 IRDA_ASSERT(self
->conn_skb
!= NULL
, return -1;);
854 tx_skb
= self
->conn_skb
;
855 self
->conn_skb
= NULL
;
857 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
858 self
->slsap_sel
, CONNECT_CMD
, tx_skb
);
859 /* Drop reference count - see irlap_data_request(). */
860 dev_kfree_skb(tx_skb
);
862 irlmp_next_lsap_state(self
, LSAP_SETUP
);
864 case LM_WATCHDOG_TIMEOUT
:
865 pr_debug("%s() : WATCHDOG_TIMEOUT !\n", __func__
);
867 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
868 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
869 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
871 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
873 case LM_LAP_DISCONNECT_INDICATION
: /* LS_Disconnect.indication */
874 del_timer( &self
->watchdog_timer
);
876 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
878 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
880 irlmp_disconnect_indication(self
, reason
, NULL
);
883 pr_debug("%s(), Unknown event %s on LSAP %#02x\n",
884 __func__
, irlmp_event
[event
], self
->slsap_sel
);