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 *irlmp_state
[] = {
42 const char *irlsap_state
[] = {
46 "LSAP_DATA_TRANSFER_READY",
51 #ifdef CONFIG_IRDA_DEBUG
52 static const char *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", __FUNCTION__, 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", __FUNCTION__, 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 __FUNCTION__
, 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", __FUNCTION__
,
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", __FUNCTION__
);
174 /* We always cleanup the log (active & passive discovery) */
177 /* Active discovery is conditional */
178 if (sysctl_discovery
)
179 irlmp_do_discovery(sysctl_discovery_slots
);
182 irlmp_start_discovery_timer(irlmp
, sysctl_discovery_timeout
* HZ
);
185 void irlmp_watchdog_timer_expired(void *data
)
187 struct lsap_cb
*self
= (struct lsap_cb
*) data
;
189 IRDA_DEBUG(2, "%s()\n", __FUNCTION__
);
191 IRDA_ASSERT(self
!= NULL
, return;);
192 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return;);
194 irlmp_do_lsap_event(self
, LM_WATCHDOG_TIMEOUT
, NULL
);
197 void irlmp_idle_timer_expired(void *data
)
199 struct lap_cb
*self
= (struct lap_cb
*) data
;
201 IRDA_DEBUG(2, "%s()\n", __FUNCTION__
);
203 IRDA_ASSERT(self
!= NULL
, return;);
204 IRDA_ASSERT(self
->magic
== LMP_LAP_MAGIC
, return;);
206 irlmp_do_lap_event(self
, LM_LAP_IDLE_TIMEOUT
, NULL
);
210 * Send an event on all LSAPs attached to this LAP.
213 irlmp_do_all_lsap_event(hashbin_t
* lsap_hashbin
,
216 struct lsap_cb
*lsap
;
217 struct lsap_cb
*lsap_next
;
219 /* Note : this function use the new hashbin_find_next()
220 * function, instead of the old hashbin_get_next().
221 * This make sure that we are always pointing one lsap
222 * ahead, so that if the current lsap is removed as the
223 * result of sending the event, we don't care.
224 * Also, as we store the context ourselves, if an enumeration
225 * of the same lsap hashbin happens as the result of sending the
226 * event, we don't care.
227 * The only problem is if the next lsap is removed. In that case,
228 * hashbin_find_next() will return NULL and we will abort the
229 * enumeration. - Jean II */
231 /* Also : we don't accept any skb in input. We can *NOT* pass
232 * the same skb to multiple clients safely, we would need to
233 * skb_clone() it. - Jean II */
235 lsap
= (struct lsap_cb
*) hashbin_get_first(lsap_hashbin
);
237 while (NULL
!= hashbin_find_next(lsap_hashbin
,
240 (void *) &lsap_next
) ) {
241 irlmp_do_lsap_event(lsap
, event
, NULL
);
246 /*********************************************************************
248 * LAP connection control states
250 ********************************************************************/
253 * Function irlmp_state_standby (event, skb, info)
255 * STANDBY, The IrLAP connection does not exist.
258 static void irlmp_state_standby(struct lap_cb
*self
, IRLMP_EVENT event
,
261 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
262 IRDA_ASSERT(self
->irlap
!= NULL
, return;);
265 case LM_LAP_DISCOVERY_REQUEST
:
266 /* irlmp_next_station_state( LMP_DISCOVER); */
268 irlap_discovery_request(self
->irlap
, &irlmp
->discovery_cmd
);
270 case LM_LAP_CONNECT_INDICATION
:
271 /* It's important to switch state first, to avoid IrLMP to
272 * think that the link is free since IrLMP may then start
273 * discovery before the connection is properly set up. DB.
275 irlmp_next_lap_state(self
, LAP_ACTIVE
);
277 /* Just accept connection TODO, this should be fixed */
278 irlap_connect_response(self
->irlap
, skb
);
280 case LM_LAP_CONNECT_REQUEST
:
281 IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __FUNCTION__
);
283 irlmp_next_lap_state(self
, LAP_U_CONNECT
);
285 /* FIXME: need to set users requested QoS */
286 irlap_connect_request(self
->irlap
, self
->daddr
, NULL
, 0);
288 case LM_LAP_DISCONNECT_INDICATION
:
289 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
292 irlmp_next_lap_state(self
, LAP_STANDBY
);
295 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
296 __FUNCTION__
, irlmp_event
[event
]);
302 * Function irlmp_state_u_connect (event, skb, info)
304 * U_CONNECT, The layer above has tried to open an LSAP connection but
305 * since the IrLAP connection does not exist, we must first start an
306 * IrLAP connection. We are now waiting response from IrLAP.
308 static void irlmp_state_u_connect(struct lap_cb
*self
, IRLMP_EVENT event
,
311 IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__
, irlmp_event
[event
]);
314 case LM_LAP_CONNECT_INDICATION
:
315 /* It's important to switch state first, to avoid IrLMP to
316 * think that the link is free since IrLMP may then start
317 * discovery before the connection is properly set up. DB.
319 irlmp_next_lap_state(self
, LAP_ACTIVE
);
321 /* Just accept connection TODO, this should be fixed */
322 irlap_connect_response(self
->irlap
, skb
);
324 /* Tell LSAPs that they can start sending data */
325 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
327 /* Note : by the time we get there (LAP retries and co),
328 * the lsaps may already have gone. This avoid getting stuck
329 * forever in LAP_ACTIVE state - Jean II */
330 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
331 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__
);
332 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
335 case LM_LAP_CONNECT_REQUEST
:
336 /* Already trying to connect */
338 case LM_LAP_CONNECT_CONFIRM
:
339 /* For all lsap_ce E Associated do LS_Connect_confirm */
340 irlmp_next_lap_state(self
, LAP_ACTIVE
);
342 /* Tell LSAPs that they can start sending data */
343 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
345 /* Note : by the time we get there (LAP retries and co),
346 * the lsaps may already have gone. This avoid getting stuck
347 * forever in LAP_ACTIVE state - Jean II */
348 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
349 IRDA_DEBUG(0, "%s() NO LSAPs !\n", __FUNCTION__
);
350 irlmp_start_idle_timer(self
, LM_IDLE_TIMEOUT
);
353 case LM_LAP_DISCONNECT_INDICATION
:
354 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n", __FUNCTION__
);
355 irlmp_next_lap_state(self
, LAP_STANDBY
);
357 /* Send disconnect event to all LSAPs using this link */
358 irlmp_do_all_lsap_event(self
->lsaps
,
359 LM_LAP_DISCONNECT_INDICATION
);
361 case LM_LAP_DISCONNECT_REQUEST
:
362 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n", __FUNCTION__
);
364 /* One of the LSAP did timeout or was closed, if it was
365 * the last one, try to get out of here - Jean II */
366 if (HASHBIN_GET_SIZE(self
->lsaps
) <= 1) {
367 irlap_disconnect_request(self
->irlap
);
371 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
372 __FUNCTION__
, irlmp_event
[event
]);
378 * Function irlmp_state_active (event, skb, info)
380 * ACTIVE, IrLAP connection is active
383 static void irlmp_state_active(struct lap_cb
*self
, IRLMP_EVENT event
,
386 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
389 case LM_LAP_CONNECT_REQUEST
:
390 IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __FUNCTION__
);
393 * IrLAP may have a pending disconnect. We tried to close
394 * IrLAP, but it was postponed because the link was
395 * busy or we were still sending packets. As we now
396 * need it, make sure it stays on. Jean II
398 irlap_clear_disconnect(self
->irlap
);
401 * LAP connection already active, just bounce back! Since we
402 * don't know which LSAP that tried to do this, we have to
403 * notify all LSAPs using this LAP, but that should be safe to
406 irlmp_do_all_lsap_event(self
->lsaps
, LM_LAP_CONNECT_CONFIRM
);
408 /* Needed by connect indication */
409 irlmp_do_all_lsap_event(irlmp
->unconnected_lsaps
,
410 LM_LAP_CONNECT_CONFIRM
);
413 case LM_LAP_DISCONNECT_REQUEST
:
415 * Need to find out if we should close IrLAP or not. If there
416 * is only one LSAP connection left on this link, that LSAP
417 * must be the one that tries to close IrLAP. It will be
418 * removed later and moved to the list of unconnected LSAPs
420 if (HASHBIN_GET_SIZE(self
->lsaps
) > 0) {
421 /* Timer value is checked in irsysctl - Jean II */
422 irlmp_start_idle_timer(self
, sysctl_lap_keepalive_time
* HZ
/ 1000);
424 /* No more connections, so close IrLAP */
426 /* We don't want to change state just yet, because
427 * we want to reflect accurately the real state of
428 * the LAP, not the state we wish it was in,
429 * so that we don't lose LM_LAP_CONNECT_REQUEST.
430 * In some cases, IrLAP won't close the LAP
431 * immediately. For example, it might still be
432 * retrying packets or waiting for the pf bit.
433 * As the LAP always send a DISCONNECT_INDICATION
434 * in PCLOSE or SCLOSE, just change state on that.
436 irlap_disconnect_request(self
->irlap
);
439 case LM_LAP_IDLE_TIMEOUT
:
440 if (HASHBIN_GET_SIZE(self
->lsaps
) == 0) {
441 /* Same reasoning as above - keep state */
442 irlap_disconnect_request(self
->irlap
);
445 case LM_LAP_DISCONNECT_INDICATION
:
446 irlmp_next_lap_state(self
, LAP_STANDBY
);
448 /* In some case, at this point our side has already closed
449 * all lsaps, and we are waiting for the idle_timer to
450 * expire. If another device reconnect immediately, the
451 * idle timer will expire in the midle of the connection
452 * initialisation, screwing up things a lot...
453 * Therefore, we must stop the timer... */
454 irlmp_stop_idle_timer(self
);
457 * Inform all connected LSAP's using this link
459 irlmp_do_all_lsap_event(self
->lsaps
,
460 LM_LAP_DISCONNECT_INDICATION
);
462 /* Force an expiry of the discovery log.
463 * Now that the LAP is free, the system may attempt to
464 * connect to another device. Unfortunately, our entries
465 * are stale. There is a small window (<3s) before the
466 * normal discovery will run and where irlmp_connect_request()
467 * can get the wrong info, so make sure things get
468 * cleaned *NOW* ;-) - Jean II */
472 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
473 __FUNCTION__
, irlmp_event
[event
]);
478 /*********************************************************************
480 * LSAP connection control states
482 ********************************************************************/
485 * Function irlmp_state_disconnected (event, skb, info)
490 static int irlmp_state_disconnected(struct lsap_cb
*self
, IRLMP_EVENT event
,
495 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
497 IRDA_ASSERT(self
!= NULL
, return -1;);
498 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
501 #ifdef CONFIG_IRDA_ULTRA
502 case LM_UDATA_INDICATION
:
503 /* This is most bizzare. Those packets are aka unreliable
504 * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
505 * Why do we pass them as Ultra ??? Jean II */
506 irlmp_connless_data_indication(self
, skb
);
508 #endif /* CONFIG_IRDA_ULTRA */
509 case LM_CONNECT_REQUEST
:
510 IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __FUNCTION__
);
512 if (self
->conn_skb
) {
513 IRDA_WARNING("%s: busy with another request!\n",
517 /* Don't forget to refcount it (see irlmp_connect_request()) */
519 self
->conn_skb
= skb
;
521 irlmp_next_lsap_state(self
, LSAP_SETUP_PEND
);
523 /* Start watchdog timer (5 secs for now) */
524 irlmp_start_watchdog_timer(self
, 5*HZ
);
526 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
528 case LM_CONNECT_INDICATION
:
529 if (self
->conn_skb
) {
530 IRDA_WARNING("%s: busy with another request!\n",
534 /* Don't forget to refcount it (see irlap_driver_rcv()) */
536 self
->conn_skb
= skb
;
538 irlmp_next_lsap_state(self
, LSAP_CONNECT_PEND
);
540 /* Start watchdog timer
541 * This is not mentionned in the spec, but there is a rare
542 * race condition that can get the socket stuck.
543 * If we receive this event while our LAP is closing down,
544 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
545 * CONNECT_PEND state forever.
546 * The other cause of getting stuck down there is if the
547 * higher layer never reply to the CONNECT_INDICATION.
548 * Anyway, it make sense to make sure that we always have
549 * a backup plan. 1 second is plenty (should be immediate).
551 irlmp_start_watchdog_timer(self
, 1*HZ
);
553 irlmp_do_lap_event(self
->lap
, LM_LAP_CONNECT_REQUEST
, NULL
);
556 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
557 __FUNCTION__
, irlmp_event
[event
], self
->slsap_sel
);
564 * Function irlmp_state_connect (self, event, skb)
569 static int irlmp_state_connect(struct lsap_cb
*self
, IRLMP_EVENT event
,
572 struct lsap_cb
*lsap
;
575 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
577 IRDA_ASSERT(self
!= NULL
, return -1;);
578 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
581 case LM_CONNECT_RESPONSE
:
583 * Bind this LSAP to the IrLAP link where the connect was
586 lsap
= hashbin_remove(irlmp
->unconnected_lsaps
, (long) self
,
589 IRDA_ASSERT(lsap
== self
, return -1;);
590 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
591 IRDA_ASSERT(self
->lap
->lsaps
!= NULL
, return -1;);
593 hashbin_insert(self
->lap
->lsaps
, (irda_queue_t
*) self
,
596 set_bit(0, &self
->connected
); /* TRUE */
598 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
599 self
->slsap_sel
, CONNECT_CNF
, skb
);
601 del_timer(&self
->watchdog_timer
);
603 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
605 case LM_WATCHDOG_TIMEOUT
:
606 /* May happen, who knows...
608 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__
);
610 /* Disconnect, get out... - Jean II */
612 self
->dlsap_sel
= LSAP_ANY
;
613 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
616 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
617 * are *not* yet bound to the IrLAP link. Jean II */
618 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
619 __FUNCTION__
, irlmp_event
[event
], self
->slsap_sel
);
626 * Function irlmp_state_connect_pend (event, skb, info)
631 static int irlmp_state_connect_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
634 struct sk_buff
*tx_skb
;
637 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
639 IRDA_ASSERT(self
!= NULL
, return -1;);
640 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
643 case LM_CONNECT_REQUEST
:
646 case LM_CONNECT_RESPONSE
:
647 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
648 "no indication issued yet\n", __FUNCTION__
);
651 case LM_DISCONNECT_REQUEST
:
652 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
653 "not yet bound to IrLAP connection\n", __FUNCTION__
);
656 case LM_LAP_CONNECT_CONFIRM
:
657 IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n", __FUNCTION__
);
658 irlmp_next_lsap_state(self
, LSAP_CONNECT
);
660 tx_skb
= self
->conn_skb
;
661 self
->conn_skb
= NULL
;
663 irlmp_connect_indication(self
, tx_skb
);
664 /* Drop reference count - see irlmp_connect_indication(). */
665 dev_kfree_skb(tx_skb
);
667 case LM_WATCHDOG_TIMEOUT
:
668 /* Will happen in some rare cases because of a race condition.
669 * Just make sure we don't stay there forever...
671 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__
);
673 /* Go back to disconnected mode, keep the socket waiting */
675 self
->dlsap_sel
= LSAP_ANY
;
677 dev_kfree_skb(self
->conn_skb
);
678 self
->conn_skb
= NULL
;
679 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
682 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
683 * are *not* yet bound to the IrLAP link. Jean II */
684 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
685 __FUNCTION__
, irlmp_event
[event
], self
->slsap_sel
);
692 * Function irlmp_state_dtr (self, event, skb)
694 * DATA_TRANSFER_READY
697 static int irlmp_state_dtr(struct lsap_cb
*self
, IRLMP_EVENT event
,
703 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
705 IRDA_ASSERT(self
!= NULL
, return -1;);
706 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
707 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
710 case LM_DATA_REQUEST
: /* Optimize for the common case */
711 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
712 self
->slsap_sel
, FALSE
, skb
);
714 case LM_DATA_INDICATION
: /* Optimize for the common case */
715 irlmp_data_indication(self
, skb
);
717 case LM_UDATA_REQUEST
:
718 IRDA_ASSERT(skb
!= NULL
, return -1;);
719 irlmp_send_data_pdu(self
->lap
, self
->dlsap_sel
,
720 self
->slsap_sel
, TRUE
, skb
);
722 case LM_UDATA_INDICATION
:
723 irlmp_udata_indication(self
, skb
);
725 case LM_CONNECT_REQUEST
:
726 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
727 "error, LSAP already connected\n", __FUNCTION__
);
730 case LM_CONNECT_RESPONSE
:
731 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
732 "error, LSAP already connected\n", __FUNCTION__
);
735 case LM_DISCONNECT_REQUEST
:
736 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
, self
->slsap_sel
,
738 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
739 /* Called only from irlmp_disconnect_request(), will
740 * unbind from LAP over there. Jean II */
742 /* Try to close the LAP connection if its still there */
744 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
746 irlmp_do_lap_event(self
->lap
,
747 LM_LAP_DISCONNECT_REQUEST
,
751 case LM_LAP_DISCONNECT_INDICATION
:
752 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
754 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
756 irlmp_disconnect_indication(self
, reason
, NULL
);
758 case LM_DISCONNECT_INDICATION
:
759 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
761 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
762 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
764 IRDA_ASSERT(skb
!= NULL
, return -1;);
765 IRDA_ASSERT(skb
->len
> 3, return -1;);
766 reason
= skb
->data
[3];
768 /* Try to close the LAP connection */
769 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__
);
770 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
772 irlmp_disconnect_indication(self
, reason
, skb
);
775 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
776 __FUNCTION__
, irlmp_event
[event
], self
->slsap_sel
);
783 * Function irlmp_state_setup (event, skb, info)
785 * SETUP, Station Control has set up the underlying IrLAP connection.
786 * An LSAP connection request has been transmitted to the peer
787 * LSAP-Connection Control FSM and we are awaiting reply.
789 static int irlmp_state_setup(struct lsap_cb
*self
, IRLMP_EVENT event
,
795 IRDA_ASSERT(self
!= NULL
, return -1;);
796 IRDA_ASSERT(self
->magic
== LMP_LSAP_MAGIC
, return -1;);
798 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
801 case LM_CONNECT_CONFIRM
:
802 irlmp_next_lsap_state(self
, LSAP_DATA_TRANSFER_READY
);
804 del_timer(&self
->watchdog_timer
);
806 irlmp_connect_confirm(self
, skb
);
808 case LM_DISCONNECT_INDICATION
:
809 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
811 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
812 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
814 IRDA_ASSERT(skb
!= NULL
, return -1;);
815 IRDA_ASSERT(skb
->len
> 3, return -1;);
816 reason
= skb
->data
[3];
818 /* Try to close the LAP connection */
819 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __FUNCTION__
);
820 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
822 irlmp_disconnect_indication(self
, reason
, skb
);
824 case LM_LAP_DISCONNECT_INDICATION
:
825 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
827 del_timer(&self
->watchdog_timer
);
829 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
830 IRDA_ASSERT(self
->lap
->magic
== LMP_LAP_MAGIC
, return -1;);
832 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
834 irlmp_disconnect_indication(self
, reason
, skb
);
836 case LM_WATCHDOG_TIMEOUT
:
837 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__
);
839 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
840 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
841 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
843 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
846 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
847 __FUNCTION__
, irlmp_event
[event
], self
->slsap_sel
);
854 * Function irlmp_state_setup_pend (event, skb, info)
856 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
857 * user to set up an LSAP connection. A request has been sent to the
858 * LAP FSM to set up the underlying IrLAP connection, and we
859 * are awaiting confirm.
861 static int irlmp_state_setup_pend(struct lsap_cb
*self
, IRLMP_EVENT event
,
864 struct sk_buff
*tx_skb
;
868 IRDA_DEBUG(4, "%s()\n", __FUNCTION__
);
870 IRDA_ASSERT(self
!= NULL
, return -1;);
871 IRDA_ASSERT(irlmp
!= NULL
, return -1;);
874 case LM_LAP_CONNECT_CONFIRM
:
875 IRDA_ASSERT(self
->conn_skb
!= NULL
, return -1;);
877 tx_skb
= self
->conn_skb
;
878 self
->conn_skb
= NULL
;
880 irlmp_send_lcf_pdu(self
->lap
, self
->dlsap_sel
,
881 self
->slsap_sel
, CONNECT_CMD
, tx_skb
);
882 /* Drop reference count - see irlap_data_request(). */
883 dev_kfree_skb(tx_skb
);
885 irlmp_next_lsap_state(self
, LSAP_SETUP
);
887 case LM_WATCHDOG_TIMEOUT
:
888 IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n", __FUNCTION__
);
890 IRDA_ASSERT(self
->lap
!= NULL
, return -1;);
891 irlmp_do_lap_event(self
->lap
, LM_LAP_DISCONNECT_REQUEST
, NULL
);
892 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
894 irlmp_disconnect_indication(self
, LM_CONNECT_FAILURE
, NULL
);
896 case LM_LAP_DISCONNECT_INDICATION
: /* LS_Disconnect.indication */
897 del_timer( &self
->watchdog_timer
);
899 irlmp_next_lsap_state(self
, LSAP_DISCONNECTED
);
901 reason
= irlmp_convert_lap_reason(self
->lap
->reason
);
903 irlmp_disconnect_indication(self
, reason
, NULL
);
906 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
907 __FUNCTION__
, irlmp_event
[event
], self
->slsap_sel
);