Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / net / irda / irlmp_event.c
blob26649f6528e6c4388324c84895423d32304b9a23
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/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[] = {
38 "LAP_STANDBY",
39 "LAP_U_CONNECT",
40 "LAP_ACTIVE",
43 const char *irlsap_state[] = {
44 "LSAP_DISCONNECTED",
45 "LSAP_CONNECT",
46 "LSAP_CONNECT_PEND",
47 "LSAP_DATA_TRANSFER_READY",
48 "LSAP_SETUP",
49 "LSAP_SETUP_PEND",
52 #ifdef CONFIG_IRDA_DEBUG
53 static const char *irlmp_event[] = {
54 "LM_CONNECT_REQUEST",
55 "LM_CONNECT_CONFIRM",
56 "LM_CONNECT_RESPONSE",
57 "LM_CONNECT_INDICATION",
59 "LM_DISCONNECT_INDICATION",
60 "LM_DISCONNECT_REQUEST",
62 "LM_DATA_REQUEST",
63 "LM_UDATA_REQUEST",
64 "LM_DATA_INDICATION",
65 "LM_UDATA_INDICATION",
67 "LM_WATCHDOG_TIMEOUT",
69 /* IrLAP events */
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,
83 struct sk_buff *);
84 static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT,
85 struct sk_buff *);
86 static void irlmp_state_active (struct lap_cb *, IRLMP_EVENT,
87 struct sk_buff *);
89 /* LSAP Connection control proto declarations */
90 static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT,
91 struct sk_buff *);
92 static int irlmp_state_connect (struct lsap_cb *, IRLMP_EVENT,
93 struct sk_buff *);
94 static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
95 struct sk_buff *);
96 static int irlmp_state_dtr (struct lsap_cb *, IRLMP_EVENT,
97 struct sk_buff *);
98 static int irlmp_state_setup (struct lsap_cb *, IRLMP_EVENT,
99 struct sk_buff *);
100 static int irlmp_state_setup_pend (struct lsap_cb *, IRLMP_EVENT,
101 struct sk_buff *);
103 static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
105 irlmp_state_standby,
106 irlmp_state_u_connect,
107 irlmp_state_active,
110 static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
112 irlmp_state_disconnected,
113 irlmp_state_connect,
114 irlmp_state_connect_pend,
115 irlmp_state_dtr,
116 irlmp_state_setup,
117 irlmp_state_setup_pend
120 static inline void irlmp_next_lap_state(struct lap_cb *self,
121 IRLMP_STATE state)
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,
130 LSAP_STATE state)
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,
141 struct sk_buff *skb)
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,
159 struct sk_buff *skb)
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__,
165 irlmp_event[event],
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) */
176 irlmp_do_expiry();
178 /* Active discovery is conditional */
179 if (sysctl_discovery)
180 irlmp_do_discovery(sysctl_discovery_slots);
182 /* Restart timer */
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.
213 static inline void
214 irlmp_do_all_lsap_event(hashbin_t * lsap_hashbin,
215 IRLMP_EVENT event)
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,
239 (long) lsap,
240 NULL,
241 (void *) &lsap_next) ) {
242 irlmp_do_lsap_event(lsap, event, NULL);
243 lsap = lsap_next;
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,
260 struct sk_buff *skb)
262 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
263 IRDA_ASSERT(self->irlap != NULL, return;);
265 switch (event) {
266 case LM_LAP_DISCOVERY_REQUEST:
267 /* irlmp_next_station_state( LMP_DISCOVER); */
269 irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
270 break;
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);
280 break;
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);
288 break;
289 case LM_LAP_DISCONNECT_INDICATION:
290 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
291 __FUNCTION__);
293 irlmp_next_lap_state(self, LAP_STANDBY);
294 break;
295 default:
296 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
297 __FUNCTION__, irlmp_event[event]);
298 break;
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.
308 * */
309 static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
310 struct sk_buff *skb)
312 IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
314 switch (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);
335 break;
336 case LM_LAP_CONNECT_REQUEST:
337 /* Already trying to connect */
338 break;
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);
353 break;
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);
361 break;
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);
370 break;
371 default:
372 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
373 __FUNCTION__, irlmp_event[event]);
374 break;
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,
385 struct sk_buff *skb)
387 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
389 switch (event) {
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
405 * do anyway.
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);
412 /* Keep state */
413 break;
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);
424 } else {
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.
436 * Jean II */
437 irlap_disconnect_request(self->irlap);
439 break;
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);
445 break;
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 */
470 irlmp_do_expiry();
471 break;
472 default:
473 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
474 __FUNCTION__, irlmp_event[event]);
475 break;
479 /*********************************************************************
481 * LSAP connection control states
483 ********************************************************************/
486 * Function irlmp_state_disconnected (event, skb, info)
488 * DISCONNECTED
491 static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
492 struct sk_buff *skb)
494 int ret = 0;
496 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
498 IRDA_ASSERT(self != NULL, return -1;);
499 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
501 switch (event) {
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);
508 break;
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",
515 __FUNCTION__);
516 return -EBUSY;
518 /* Don't forget to refcount it (see irlmp_connect_request()) */
519 skb_get(skb);
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);
528 break;
529 case LM_CONNECT_INDICATION:
530 if (self->conn_skb) {
531 IRDA_WARNING("%s: busy with another request!\n",
532 __FUNCTION__);
533 return -EBUSY;
535 /* Don't forget to refcount it (see irlap_driver_rcv()) */
536 skb_get(skb);
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).
551 * Jean II */
552 irlmp_start_watchdog_timer(self, 1*HZ);
554 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
555 break;
556 default:
557 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
558 __FUNCTION__, irlmp_event[event], self->slsap_sel);
559 break;
561 return ret;
565 * Function irlmp_state_connect (self, event, skb)
567 * CONNECT
570 static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
571 struct sk_buff *skb)
573 struct lsap_cb *lsap;
574 int ret = 0;
576 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
578 IRDA_ASSERT(self != NULL, return -1;);
579 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
581 switch (event) {
582 case LM_CONNECT_RESPONSE:
584 * Bind this LSAP to the IrLAP link where the connect was
585 * received
587 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
588 NULL);
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,
595 (long) self, NULL);
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);
605 break;
606 case LM_WATCHDOG_TIMEOUT:
607 /* May happen, who knows...
608 * Jean II */
609 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
611 /* Disconnect, get out... - Jean II */
612 self->lap = NULL;
613 self->dlsap_sel = LSAP_ANY;
614 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
615 break;
616 default:
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);
621 break;
623 return ret;
627 * Function irlmp_state_connect_pend (event, skb, info)
629 * CONNECT_PEND
632 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
633 struct sk_buff *skb)
635 struct sk_buff *tx_skb;
636 int ret = 0;
638 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
640 IRDA_ASSERT(self != NULL, return -1;);
641 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
643 switch (event) {
644 case LM_CONNECT_REQUEST:
645 /* Keep state */
646 break;
647 case LM_CONNECT_RESPONSE:
648 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
649 "no indication issued yet\n", __FUNCTION__);
650 /* Keep state */
651 break;
652 case LM_DISCONNECT_REQUEST:
653 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
654 "not yet bound to IrLAP connection\n", __FUNCTION__);
655 /* Keep state */
656 break;
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);
667 break;
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...
671 * Jean II */
672 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
674 /* Go back to disconnected mode, keep the socket waiting */
675 self->lap = NULL;
676 self->dlsap_sel = LSAP_ANY;
677 if(self->conn_skb)
678 dev_kfree_skb(self->conn_skb);
679 self->conn_skb = NULL;
680 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
681 break;
682 default:
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);
687 break;
689 return ret;
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,
699 struct sk_buff *skb)
701 LM_REASON reason;
702 int ret = 0;
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;);
710 switch (event) {
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);
714 break;
715 case LM_DATA_INDICATION: /* Optimize for the common case */
716 irlmp_data_indication(self, skb);
717 break;
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);
722 break;
723 case LM_UDATA_INDICATION:
724 irlmp_udata_indication(self, skb);
725 break;
726 case LM_CONNECT_REQUEST:
727 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
728 "error, LSAP already connected\n", __FUNCTION__);
729 /* Keep state */
730 break;
731 case LM_CONNECT_RESPONSE:
732 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
733 "error, LSAP already connected\n", __FUNCTION__);
734 /* Keep state */
735 break;
736 case LM_DISCONNECT_REQUEST:
737 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
738 DISCONNECT, skb);
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 */
744 if (self->lap) {
745 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
746 __FUNCTION__);
747 irlmp_do_lap_event(self->lap,
748 LM_LAP_DISCONNECT_REQUEST,
749 NULL);
751 break;
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);
758 break;
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);
774 break;
775 default:
776 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
777 __FUNCTION__, irlmp_event[event], self->slsap_sel);
778 break;
780 return ret;
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,
791 struct sk_buff *skb)
793 LM_REASON reason;
794 int ret = 0;
796 IRDA_ASSERT(self != NULL, return -1;);
797 IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
799 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
801 switch (event) {
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);
808 break;
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);
824 break;
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);
836 break;
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);
845 break;
846 default:
847 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
848 __FUNCTION__, irlmp_event[event], self->slsap_sel);
849 break;
851 return ret;
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,
863 struct sk_buff *skb)
865 struct sk_buff *tx_skb;
866 LM_REASON reason;
867 int ret = 0;
869 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
871 IRDA_ASSERT(self != NULL, return -1;);
872 IRDA_ASSERT(irlmp != NULL, return -1;);
874 switch (event) {
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);
887 break;
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);
896 break;
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);
905 break;
906 default:
907 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
908 __FUNCTION__, irlmp_event[event], self->slsap_sel);
909 break;
911 return ret;