- pre3:
[davej-history.git] / net / irda / irlmp_event.c
bloba4646b274f20a4f33e7f7c282369f81825a3c483
1 /*********************************************************************
2 *
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.
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * Neither Dag Brattli nor University of Tromsø admit liability nor
21 * provide warranty for any of this software. This material is
22 * provided "AS-IS" and at no charge.
24 ********************************************************************/
26 #include <linux/config.h>
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 static const char *irlmp_event[] = {
52 "LM_CONNECT_REQUEST",
53 "LM_CONNECT_CONFIRM",
54 "LM_CONNECT_RESPONSE",
55 "LM_CONNECT_INDICATION",
57 "LM_DISCONNECT_INDICATION",
58 "LM_DISCONNECT_REQUEST",
60 "LM_DATA_REQUEST",
61 "LM_UDATA_REQUEST",
62 "LM_DATA_INDICATION",
63 "LM_UDATA_INDICATION",
65 "LM_WATCHDOG_TIMEOUT",
67 /* IrLAP events */
68 "LM_LAP_CONNECT_REQUEST",
69 "LM_LAP_CONNECT_INDICATION",
70 "LM_LAP_CONNECT_CONFIRM",
71 "LM_LAP_DISCONNECT_INDICATION",
72 "LM_LAP_DISCONNECT_REQUEST",
73 "LM_LAP_DISCOVERY_REQUEST",
74 "LM_LAP_DISCOVERY_CONFIRM",
75 "LM_LAP_IDLE_TIMEOUT",
78 /* LAP Connection control proto declarations */
79 static void irlmp_state_standby (struct lap_cb *, IRLMP_EVENT,
80 struct sk_buff *);
81 static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT,
82 struct sk_buff *);
83 static void irlmp_state_active (struct lap_cb *, IRLMP_EVENT,
84 struct sk_buff *);
86 /* LSAP Connection control proto declarations */
87 static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT,
88 struct sk_buff *);
89 static int irlmp_state_connect (struct lsap_cb *, IRLMP_EVENT,
90 struct sk_buff *);
91 static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
92 struct sk_buff *);
93 static int irlmp_state_dtr (struct lsap_cb *, IRLMP_EVENT,
94 struct sk_buff *);
95 static int irlmp_state_setup (struct lsap_cb *, IRLMP_EVENT,
96 struct sk_buff *);
97 static int irlmp_state_setup_pend (struct lsap_cb *, IRLMP_EVENT,
98 struct sk_buff *);
100 static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
102 irlmp_state_standby,
103 irlmp_state_u_connect,
104 irlmp_state_active,
107 static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
109 irlmp_state_disconnected,
110 irlmp_state_connect,
111 irlmp_state_connect_pend,
112 irlmp_state_dtr,
113 irlmp_state_setup,
114 irlmp_state_setup_pend
117 /* Do connection control events */
118 int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
119 struct sk_buff *skb)
121 ASSERT(self != NULL, return -1;);
122 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
124 IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
125 irlmp_event[event], irlsap_state[ self->lsap_state]);
127 return (*lsap_state[self->lsap_state]) (self, event, skb);
131 * Function do_lap_event (event, skb, info)
133 * Do IrLAP control events
136 void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
137 struct sk_buff *skb)
139 ASSERT(self != NULL, return;);
140 ASSERT(self->magic == LMP_LAP_MAGIC, return;);
142 IRDA_DEBUG(4, __FUNCTION__ "(), EVENT = %s, STATE = %s\n",
143 irlmp_event[event],
144 irlmp_state[self->lap_state]);
146 (*lap_state[self->lap_state]) (self, event, skb);
149 void irlmp_discovery_timer_expired(void *data)
151 IRDA_DEBUG(4, __FUNCTION__ "()\n");
153 if (sysctl_discovery)
154 irlmp_do_discovery(sysctl_discovery_slots);
156 /* Restart timer */
157 irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
160 void irlmp_watchdog_timer_expired(void *data)
162 struct lsap_cb *self = (struct lsap_cb *) data;
164 IRDA_DEBUG(2, __FUNCTION__ "()\n");
166 ASSERT(self != NULL, return;);
167 ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
169 irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
172 void irlmp_idle_timer_expired(void *data)
174 struct lap_cb *self = (struct lap_cb *) data;
176 IRDA_DEBUG(2, __FUNCTION__ "()\n");
178 ASSERT(self != NULL, return;);
179 ASSERT(self->magic == LMP_LAP_MAGIC, return;);
181 irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
184 /*********************************************************************
186 * LAP connection control states
188 ********************************************************************/
191 * Function irlmp_state_standby (event, skb, info)
193 * STANDBY, The IrLAP connection does not exist.
196 static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
197 struct sk_buff *skb)
199 IRDA_DEBUG(4, __FUNCTION__ "()\n");
200 ASSERT(self->irlap != NULL, return;);
202 switch (event) {
203 case LM_LAP_DISCOVERY_REQUEST:
204 /* irlmp_next_station_state( LMP_DISCOVER); */
206 irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
207 break;
208 case LM_LAP_DISCOVERY_CONFIRM:
209 /* irlmp_next_station_state( LMP_READY); */
210 irlmp_discovery_confirm(irlmp->cachelog);
211 break;
212 case LM_LAP_CONNECT_INDICATION:
213 /* It's important to switch state first, to avoid IrLMP to
214 * think that the link is free since IrLMP may then start
215 * discovery before the connection is properly set up. DB.
217 irlmp_next_lap_state(self, LAP_ACTIVE);
219 /* Just accept connection TODO, this should be fixed */
220 irlap_connect_response(self->irlap, skb);
221 break;
222 case LM_LAP_CONNECT_REQUEST:
223 IRDA_DEBUG(4, __FUNCTION__ "() LS_CONNECT_REQUEST\n");
225 irlmp_next_lap_state(self, LAP_U_CONNECT);
226 self->refcount++;
228 /* FIXME: need to set users requested QoS */
229 irlap_connect_request(self->irlap, self->daddr, NULL, 0);
230 break;
231 case LM_LAP_DISCONNECT_INDICATION:
232 IRDA_DEBUG(4, __FUNCTION__
233 "(), Error LM_LAP_DISCONNECT_INDICATION\n");
235 irlmp_next_lap_state(self, LAP_STANDBY);
236 break;
237 default:
238 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
239 irlmp_event[event]);
240 if (skb)
241 dev_kfree_skb(skb);
242 break;
247 * Function irlmp_state_u_connect (event, skb, info)
249 * U_CONNECT, The layer above has tried to open an LSAP connection but
250 * since the IrLAP connection does not exist, we must first start an
251 * IrLAP connection. We are now waiting response from IrLAP.
252 * */
253 static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
254 struct sk_buff *skb)
256 struct lsap_cb *lsap;
257 struct lsap_cb *lsap_current;
259 IRDA_DEBUG(2, __FUNCTION__ "(), event=%s\n", irlmp_event[event]);
261 switch (event) {
262 case LM_LAP_CONNECT_INDICATION:
263 /* It's important to switch state first, to avoid IrLMP to
264 * think that the link is free since IrLMP may then start
265 * discovery before the connection is properly set up. DB.
267 irlmp_next_lap_state(self, LAP_ACTIVE);
269 /* Just accept connection TODO, this should be fixed */
270 irlap_connect_response(self->irlap, skb);
272 lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
273 while (lsap != NULL) {
274 irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
275 lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
277 break;
278 case LM_LAP_CONNECT_REQUEST:
279 /* Already trying to connect */
280 self->refcount++;
281 break;
282 case LM_LAP_CONNECT_CONFIRM:
283 /* For all lsap_ce E Associated do LS_Connect_confirm */
284 irlmp_next_lap_state(self, LAP_ACTIVE);
286 lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
287 while (lsap != NULL) {
288 irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
289 lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
291 break;
292 case LM_LAP_DISCONNECT_INDICATION:
293 irlmp_next_lap_state(self, LAP_STANDBY);
294 self->refcount = 0;
296 /* Send disconnect event to all LSAPs using this link */
297 lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
298 while (lsap != NULL ) {
299 ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
301 lsap_current = lsap;
303 /* Be sure to stay one item ahead */
304 lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
305 irlmp_do_lsap_event(lsap_current,
306 LM_LAP_DISCONNECT_INDICATION,
307 NULL);
309 break;
310 case LM_LAP_DISCONNECT_REQUEST:
311 IRDA_DEBUG(4, __FUNCTION__ "(), LM_LAP_DISCONNECT_REQUEST\n");
313 self->refcount--;
314 if (self->refcount == 0)
315 irlmp_next_lap_state(self, LAP_STANDBY);
316 break;
317 default:
318 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
319 irlmp_event[event]);
320 if (skb)
321 dev_kfree_skb(skb);
322 break;
327 * Function irlmp_state_active (event, skb, info)
329 * ACTIVE, IrLAP connection is active
332 static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
333 struct sk_buff *skb)
335 struct lsap_cb *lsap;
336 struct lsap_cb *lsap_current;
338 IRDA_DEBUG(4, __FUNCTION__ "()\n");
340 switch (event) {
341 case LM_LAP_CONNECT_REQUEST:
342 IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_REQUEST\n");
343 self->refcount++;
346 * LAP connection allready active, just bounce back! Since we
347 * don't know which LSAP that tried to do this, we have to
348 * notify all LSAPs using this LAP, but that should be safe to
349 * do anyway.
351 lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
352 while (lsap != NULL) {
353 irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
354 lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
357 /* Needed by connect indication */
358 lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
359 while (lsap != NULL) {
360 lsap_current = lsap;
362 /* Be sure to stay one item ahead */
363 lsap = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
364 irlmp_do_lsap_event(lsap_current,
365 LM_LAP_CONNECT_CONFIRM, NULL);
367 /* Keep state */
368 break;
369 case LM_LAP_DISCONNECT_REQUEST:
370 self->refcount--;
373 * Need to find out if we should close IrLAP or not. If there
374 * is only one LSAP connection left on this link, that LSAP
375 * must be the one that tries to close IrLAP. It will be
376 * removed later and moved to the list of unconnected LSAPs
378 if (HASHBIN_GET_SIZE(self->lsaps) > 0)
379 irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
380 else {
381 /* No more connections, so close IrLAP */
382 irlmp_next_lap_state(self, LAP_STANDBY);
383 irlap_disconnect_request(self->irlap);
385 break;
386 case LM_LAP_IDLE_TIMEOUT:
387 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
388 irlmp_next_lap_state(self, LAP_STANDBY);
389 irlap_disconnect_request(self->irlap);
391 break;
392 case LM_LAP_DISCONNECT_INDICATION:
393 irlmp_next_lap_state(self, LAP_STANDBY);
394 self->refcount = 0;
396 /* In some case, at this point our side has already closed
397 * all lsaps, and we are waiting for the idle_timer to
398 * expire. If another device reconnect immediately, the
399 * idle timer will expire in the midle of the connection
400 * initialisation, screwing up things a lot...
401 * Therefore, we must stop the timer... */
402 irlmp_stop_idle_timer(self);
405 * Inform all connected LSAP's using this link
407 lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
408 while (lsap != NULL ) {
409 ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
411 lsap_current = lsap;
413 /* Be sure to stay one item ahead */
414 lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
415 irlmp_do_lsap_event(lsap_current,
416 LM_LAP_DISCONNECT_INDICATION,
417 NULL);
419 break;
420 default:
421 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
422 irlmp_event[event]);
423 if (skb)
424 dev_kfree_skb(skb);
425 break;
429 /*********************************************************************
431 * LSAP connection control states
433 ********************************************************************/
436 * Function irlmp_state_disconnected (event, skb, info)
438 * DISCONNECTED
441 static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
442 struct sk_buff *skb)
444 int ret = 0;
446 IRDA_DEBUG(4, __FUNCTION__ "()\n");
448 ASSERT(self != NULL, return -1;);
449 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
451 switch (event) {
452 #ifdef CONFIG_IRDA_ULTRA
453 case LM_UDATA_INDICATION:
454 irlmp_connless_data_indication(self, skb);
455 break;
456 #endif /* CONFIG_IRDA_ULTRA */
457 case LM_CONNECT_REQUEST:
458 IRDA_DEBUG(4, __FUNCTION__ "(), LM_CONNECT_REQUEST\n");
460 if (self->conn_skb) {
461 WARNING(__FUNCTION__
462 "(), busy with another request!\n");
463 return -EBUSY;
465 self->conn_skb = skb;
467 irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
469 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
471 /* Start watchdog timer (5 secs for now) */
472 irlmp_start_watchdog_timer(self, 5*HZ);
473 break;
474 case LM_CONNECT_INDICATION:
475 irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
477 if (self->conn_skb) {
478 WARNING(__FUNCTION__
479 "(), busy with another request!\n");
480 return -EBUSY;
482 self->conn_skb = skb;
484 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
485 break;
486 default:
487 IRDA_DEBUG(2, __FUNCTION__ "(), Unknown event %s\n",
488 irlmp_event[event]);
489 if (skb)
490 dev_kfree_skb(skb);
491 break;
493 return ret;
497 * Function irlmp_state_connect (self, event, skb)
499 * CONNECT
502 static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
503 struct sk_buff *skb)
505 struct lsap_cb *lsap;
506 int ret = 0;
508 IRDA_DEBUG(4, __FUNCTION__ "()\n");
510 ASSERT(self != NULL, return -1;);
511 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
513 switch (event) {
514 case LM_CONNECT_RESPONSE:
516 * Bind this LSAP to the IrLAP link where the connect was
517 * received
519 lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
520 NULL);
522 ASSERT(lsap == self, return -1;);
523 ASSERT(self->lap != NULL, return -1;);
524 ASSERT(self->lap->lsaps != NULL, return -1;);
526 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self,
527 NULL);
529 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
530 self->slsap_sel, CONNECT_CNF, skb);
532 del_timer(&self->watchdog_timer);
534 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
535 break;
536 default:
537 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
538 irlmp_event[event]);
539 if (skb)
540 dev_kfree_skb(skb);
541 break;
543 return ret;
547 * Function irlmp_state_connect_pend (event, skb, info)
549 * CONNECT_PEND
552 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
553 struct sk_buff *skb)
555 int ret = 0;
557 IRDA_DEBUG(4, __FUNCTION__ "()\n");
559 ASSERT(self != NULL, return -1;);
560 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
562 switch (event) {
563 case LM_CONNECT_REQUEST:
564 /* Keep state */
565 break;
566 case LM_CONNECT_RESPONSE:
567 IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
568 "no indication issued yet\n");
569 /* Keep state */
570 break;
571 case LM_DISCONNECT_REQUEST:
572 IRDA_DEBUG(0, __FUNCTION__ "(), LM_DISCONNECT_REQUEST, "
573 "not yet bound to IrLAP connection\n");
574 /* Keep state */
575 break;
576 case LM_LAP_CONNECT_CONFIRM:
577 IRDA_DEBUG(4, __FUNCTION__ "(), LS_CONNECT_CONFIRM\n");
578 irlmp_next_lsap_state(self, LSAP_CONNECT);
580 skb = self->conn_skb;
581 self->conn_skb = NULL;
583 irlmp_connect_indication(self, skb);
584 break;
585 default:
586 IRDA_DEBUG(0, __FUNCTION__ "Unknown event %s\n",
587 irlmp_event[event]);
588 if (skb)
589 dev_kfree_skb(skb);
590 break;
592 return ret;
596 * Function irlmp_state_dtr (self, event, skb)
598 * DATA_TRANSFER_READY
601 static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
602 struct sk_buff *skb)
604 LM_REASON reason;
605 int ret = 0;
607 IRDA_DEBUG(4, __FUNCTION__ "()\n");
609 ASSERT(self != NULL, return -1;);
610 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
611 ASSERT(self->lap != NULL, return -1;);
613 switch (event) {
614 case LM_DATA_REQUEST: /* Optimize for the common case */
615 irlmp_send_data_pdu(self->lap, self->dlsap_sel,
616 self->slsap_sel, FALSE, skb);
617 break;
618 case LM_DATA_INDICATION: /* Optimize for the common case */
619 irlmp_data_indication(self, skb);
620 break;
621 case LM_UDATA_REQUEST:
622 ASSERT(skb != NULL, return -1;);
623 irlmp_send_data_pdu(self->lap, self->dlsap_sel,
624 self->slsap_sel, TRUE, skb);
625 break;
626 case LM_UDATA_INDICATION:
627 irlmp_udata_indication(self, skb);
628 break;
629 case LM_CONNECT_REQUEST:
630 IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_REQUEST, "
631 "error, LSAP already connected\n");
632 /* Keep state */
633 break;
634 case LM_CONNECT_RESPONSE:
635 IRDA_DEBUG(0, __FUNCTION__ "(), LM_CONNECT_RESPONSE, "
636 "error, LSAP allready connected\n");
637 /* Keep state */
638 break;
639 case LM_DISCONNECT_REQUEST:
640 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
641 DISCONNECT, skb);
642 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
644 /* Try to close the LAP connection if its still there */
645 if (self->lap) {
646 IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
647 irlmp_do_lap_event(self->lap,
648 LM_LAP_DISCONNECT_REQUEST,
649 NULL);
651 break;
652 case LM_LAP_DISCONNECT_INDICATION:
653 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
655 reason = irlmp_convert_lap_reason(self->lap->reason);
657 irlmp_disconnect_indication(self, reason, NULL);
658 break;
659 case LM_DISCONNECT_INDICATION:
660 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
662 ASSERT(self->lap != NULL, return -1;);
663 ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
665 ASSERT(skb != NULL, return -1;);
666 ASSERT(skb->len > 3, return -1;);
667 reason = skb->data[3];
669 /* Try to close the LAP connection */
670 IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
671 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
673 irlmp_disconnect_indication(self, reason, skb);
674 break;
675 default:
676 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
677 irlmp_event[event]);
678 if (skb)
679 dev_kfree_skb(skb);
680 break;
682 return ret;
686 * Function irlmp_state_setup (event, skb, info)
688 * SETUP, Station Control has set up the underlying IrLAP connection.
689 * An LSAP connection request has been transmitted to the peer
690 * LSAP-Connection Control FSM and we are awaiting reply.
692 static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
693 struct sk_buff *skb)
695 LM_REASON reason;
696 int ret = 0;
698 ASSERT(self != NULL, return -1;);
699 ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
701 IRDA_DEBUG(4, __FUNCTION__ "()\n");
703 switch (event) {
704 case LM_CONNECT_CONFIRM:
705 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
707 del_timer(&self->watchdog_timer);
709 irlmp_connect_confirm(self, skb);
710 break;
711 case LM_DISCONNECT_INDICATION:
712 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
714 ASSERT(self->lap != NULL, return -1;);
715 ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
717 ASSERT(skb != NULL, return -1;);
718 ASSERT(skb->len > 3, return -1;);
719 reason = skb->data[3];
721 /* Try to close the LAP connection */
722 IRDA_DEBUG(4, __FUNCTION__ "(), trying to close IrLAP\n");
723 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
725 irlmp_disconnect_indication(self, reason, skb);
726 break;
727 case LM_LAP_DISCONNECT_INDICATION:
728 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
730 del_timer(&self->watchdog_timer);
732 ASSERT(self->lap != NULL, return -1;);
733 ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
735 reason = irlmp_convert_lap_reason(self->lap->reason);
737 irlmp_disconnect_indication(self, reason, skb);
738 break;
739 case LM_WATCHDOG_TIMEOUT:
740 IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
742 ASSERT(self->lap != NULL, return -1;);
743 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
744 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
746 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
747 break;
748 default:
749 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
750 irlmp_event[event]);
751 if (skb)
752 dev_kfree_skb(skb);
753 break;
755 return ret;
759 * Function irlmp_state_setup_pend (event, skb, info)
761 * SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
762 * user to set up an LSAP connection. A request has been sent to the
763 * LAP FSM to set up the underlying IrLAP connection, and we
764 * are awaiting confirm.
766 static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
767 struct sk_buff *skb)
769 LM_REASON reason;
770 int ret = 0;
772 IRDA_DEBUG(4, __FUNCTION__ "()\n");
774 ASSERT(self != NULL, return -1;);
775 ASSERT(irlmp != NULL, return -1;);
777 switch (event) {
778 case LM_LAP_CONNECT_CONFIRM:
779 ASSERT(self->conn_skb != NULL, return -1;);
781 skb = self->conn_skb;
782 self->conn_skb = NULL;
784 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
785 self->slsap_sel, CONNECT_CMD, skb);
787 irlmp_next_lsap_state(self, LSAP_SETUP);
788 break;
789 case LM_WATCHDOG_TIMEOUT:
790 IRDA_DEBUG(0, __FUNCTION__ "() WATCHDOG_TIMEOUT!\n");
792 ASSERT(self->lap != NULL, return -1;);
793 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
794 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
796 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
797 break;
798 case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
799 del_timer( &self->watchdog_timer);
801 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
803 reason = irlmp_convert_lap_reason(self->lap->reason);
805 irlmp_disconnect_indication(self, reason, NULL);
806 break;
807 default:
808 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown event %s\n",
809 irlmp_event[event]);
810 if (skb)
811 dev_kfree_skb(skb);
812 break;
814 return ret;
817 void irlmp_next_lap_state(struct lap_cb *self, IRLMP_STATE state)
819 IRDA_DEBUG(4, __FUNCTION__ "(), LMP LAP = %s\n", irlmp_state[state]);
820 self->lap_state = state;
823 void irlmp_next_lsap_state(struct lsap_cb *self, LSAP_STATE state)
825 ASSERT(self != NULL, return;);
827 IRDA_DEBUG(4, __FUNCTION__ "(), LMP LSAP = %s\n", irlsap_state[state]);
828 self->lsap_state = state;