Linux 2.6.24.5
[linux/fpc-iii.git] / net / irda / irlmp_event.c
blob1bba87e7860943ac444d6f55b4aa78fa8c5dad30
1 /*********************************************************************
3 * Filename: irlmp_event.c
4 * Version: 0.8
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[] = {
37 "LAP_STANDBY",
38 "LAP_U_CONNECT",
39 "LAP_ACTIVE",
42 const char *irlsap_state[] = {
43 "LSAP_DISCONNECTED",
44 "LSAP_CONNECT",
45 "LSAP_CONNECT_PEND",
46 "LSAP_DATA_TRANSFER_READY",
47 "LSAP_SETUP",
48 "LSAP_SETUP_PEND",
51 #ifdef CONFIG_IRDA_DEBUG
52 static const char *irlmp_event[] = {
53 "LM_CONNECT_REQUEST",
54 "LM_CONNECT_CONFIRM",
55 "LM_CONNECT_RESPONSE",
56 "LM_CONNECT_INDICATION",
58 "LM_DISCONNECT_INDICATION",
59 "LM_DISCONNECT_REQUEST",
61 "LM_DATA_REQUEST",
62 "LM_UDATA_REQUEST",
63 "LM_DATA_INDICATION",
64 "LM_UDATA_INDICATION",
66 "LM_WATCHDOG_TIMEOUT",
68 /* IrLAP events */
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,
82 struct sk_buff *);
83 static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT,
84 struct sk_buff *);
85 static void irlmp_state_active (struct lap_cb *, IRLMP_EVENT,
86 struct sk_buff *);
88 /* LSAP Connection control proto declarations */
89 static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT,
90 struct sk_buff *);
91 static int irlmp_state_connect (struct lsap_cb *, IRLMP_EVENT,
92 struct sk_buff *);
93 static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
94 struct sk_buff *);
95 static int irlmp_state_dtr (struct lsap_cb *, IRLMP_EVENT,
96 struct sk_buff *);
97 static int irlmp_state_setup (struct lsap_cb *, IRLMP_EVENT,
98 struct sk_buff *);
99 static int irlmp_state_setup_pend (struct lsap_cb *, IRLMP_EVENT,
100 struct sk_buff *);
102 static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
104 irlmp_state_standby,
105 irlmp_state_u_connect,
106 irlmp_state_active,
109 static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
111 irlmp_state_disconnected,
112 irlmp_state_connect,
113 irlmp_state_connect_pend,
114 irlmp_state_dtr,
115 irlmp_state_setup,
116 irlmp_state_setup_pend
119 static inline void irlmp_next_lap_state(struct lap_cb *self,
120 IRLMP_STATE state)
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,
129 LSAP_STATE state)
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,
140 struct sk_buff *skb)
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,
158 struct sk_buff *skb)
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__,
164 irlmp_event[event],
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) */
175 irlmp_do_expiry();
177 /* Active discovery is conditional */
178 if (sysctl_discovery)
179 irlmp_do_discovery(sysctl_discovery_slots);
181 /* Restart timer */
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.
212 static inline void
213 irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
214 IRLMP_EVENT event)
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,
238 (long) lsap,
239 NULL,
240 (void *) &lsap_next) ) {
241 irlmp_do_lsap_event(lsap, event, NULL);
242 lsap = lsap_next;
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,
259 struct sk_buff *skb)
261 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
262 IRDA_ASSERT(self->irlap != NULL, return;);
264 switch (event) {
265 case LM_LAP_DISCOVERY_REQUEST:
266 /* irlmp_next_station_state( LMP_DISCOVER); */
268 irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
269 break;
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);
279 break;
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);
287 break;
288 case LM_LAP_DISCONNECT_INDICATION:
289 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
290 __FUNCTION__);
292 irlmp_next_lap_state(self, LAP_STANDBY);
293 break;
294 default:
295 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
296 __FUNCTION__, irlmp_event[event]);
297 break;
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.
307 * */
308 static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
309 struct sk_buff *skb)
311 IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
313 switch (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);
334 break;
335 case LM_LAP_CONNECT_REQUEST:
336 /* Already trying to connect */
337 break;
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);
352 break;
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);
360 break;
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);
369 break;
370 default:
371 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
372 __FUNCTION__, irlmp_event[event]);
373 break;
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,
384 struct sk_buff *skb)
386 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
388 switch (event) {
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
404 * do anyway.
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);
411 /* Keep state */
412 break;
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);
423 } else {
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.
435 * Jean II */
436 irlap_disconnect_request(self->irlap);
438 break;
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);
444 break;
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 */
469 irlmp_do_expiry();
470 break;
471 default:
472 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
473 __FUNCTION__, irlmp_event[event]);
474 break;
478 /*********************************************************************
480 * LSAP connection control states
482 ********************************************************************/
485 * Function irlmp_state_disconnected (event, skb, info)
487 * DISCONNECTED
490 static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
491 struct sk_buff *skb)
493 int ret = 0;
495 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
497 IRDA_ASSERT(self != NULL, return -1;);
498 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
500 switch (event) {
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);
507 break;
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",
514 __FUNCTION__);
515 return -EBUSY;
517 /* Don't forget to refcount it (see irlmp_connect_request()) */
518 skb_get(skb);
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);
527 break;
528 case LM_CONNECT_INDICATION:
529 if (self->conn_skb) {
530 IRDA_WARNING("%s: busy with another request!\n",
531 __FUNCTION__);
532 return -EBUSY;
534 /* Don't forget to refcount it (see irlap_driver_rcv()) */
535 skb_get(skb);
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).
550 * Jean II */
551 irlmp_start_watchdog_timer(self, 1*HZ);
553 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
554 break;
555 default:
556 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
557 __FUNCTION__, irlmp_event[event], self->slsap_sel);
558 break;
560 return ret;
564 * Function irlmp_state_connect (self, event, skb)
566 * CONNECT
569 static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
570 struct sk_buff *skb)
572 struct lsap_cb *lsap;
573 int ret = 0;
575 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
577 IRDA_ASSERT(self != NULL, return -1;);
578 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
580 switch (event) {
581 case LM_CONNECT_RESPONSE:
583 * Bind this LSAP to the IrLAP link where the connect was
584 * received
586 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
587 NULL);
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,
594 (long) self, NULL);
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);
604 break;
605 case LM_WATCHDOG_TIMEOUT:
606 /* May happen, who knows...
607 * Jean II */
608 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
610 /* Disconnect, get out... - Jean II */
611 self->lap = NULL;
612 self->dlsap_sel = LSAP_ANY;
613 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
614 break;
615 default:
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);
620 break;
622 return ret;
626 * Function irlmp_state_connect_pend (event, skb, info)
628 * CONNECT_PEND
631 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
632 struct sk_buff *skb)
634 struct sk_buff *tx_skb;
635 int ret = 0;
637 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
639 IRDA_ASSERT(self != NULL, return -1;);
640 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
642 switch (event) {
643 case LM_CONNECT_REQUEST:
644 /* Keep state */
645 break;
646 case LM_CONNECT_RESPONSE:
647 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
648 "no indication issued yet\n", __FUNCTION__);
649 /* Keep state */
650 break;
651 case LM_DISCONNECT_REQUEST:
652 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
653 "not yet bound to IrLAP connection\n", __FUNCTION__);
654 /* Keep state */
655 break;
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);
666 break;
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...
670 * Jean II */
671 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
673 /* Go back to disconnected mode, keep the socket waiting */
674 self->lap = NULL;
675 self->dlsap_sel = LSAP_ANY;
676 if(self->conn_skb)
677 dev_kfree_skb(self->conn_skb);
678 self->conn_skb = NULL;
679 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
680 break;
681 default:
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);
686 break;
688 return ret;
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,
698 struct sk_buff *skb)
700 LM_REASON reason;
701 int ret = 0;
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;);
709 switch (event) {
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);
713 break;
714 case LM_DATA_INDICATION: /* Optimize for the common case */
715 irlmp_data_indication(self, skb);
716 break;
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);
721 break;
722 case LM_UDATA_INDICATION:
723 irlmp_udata_indication(self, skb);
724 break;
725 case LM_CONNECT_REQUEST:
726 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
727 "error, LSAP already connected\n", __FUNCTION__);
728 /* Keep state */
729 break;
730 case LM_CONNECT_RESPONSE:
731 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
732 "error, LSAP already connected\n", __FUNCTION__);
733 /* Keep state */
734 break;
735 case LM_DISCONNECT_REQUEST:
736 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
737 DISCONNECT, skb);
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 */
743 if (self->lap) {
744 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
745 __FUNCTION__);
746 irlmp_do_lap_event(self->lap,
747 LM_LAP_DISCONNECT_REQUEST,
748 NULL);
750 break;
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);
757 break;
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);
773 break;
774 default:
775 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
776 __FUNCTION__, irlmp_event[event], self->slsap_sel);
777 break;
779 return ret;
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,
790 struct sk_buff *skb)
792 LM_REASON reason;
793 int ret = 0;
795 IRDA_ASSERT(self != NULL, return -1;);
796 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
798 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
800 switch (event) {
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);
807 break;
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);
823 break;
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);
835 break;
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);
844 break;
845 default:
846 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
847 __FUNCTION__, irlmp_event[event], self->slsap_sel);
848 break;
850 return ret;
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,
862 struct sk_buff *skb)
864 struct sk_buff *tx_skb;
865 LM_REASON reason;
866 int ret = 0;
868 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
870 IRDA_ASSERT(self != NULL, return -1;);
871 IRDA_ASSERT(irlmp != NULL, return -1;);
873 switch (event) {
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);
886 break;
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);
895 break;
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);
904 break;
905 default:
906 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
907 __FUNCTION__, irlmp_event[event], self->slsap_sel);
908 break;
910 return ret;