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
);