vserver 2.0 rc7
[linux-2.6.git] / net / irda / irlmp_event.c
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>
11  *
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>
15  *
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.
20  *
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.
24  *
25  ********************************************************************/
26
27 #include <linux/config.h>
28 #include <linux/kernel.h>
29
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>
36
37 const char *irlmp_state[] = {
38         "LAP_STANDBY",
39         "LAP_U_CONNECT",
40         "LAP_ACTIVE",
41 };
42
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",
50 };
51
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",
58
59         "LM_DISCONNECT_INDICATION",
60         "LM_DISCONNECT_REQUEST",
61
62         "LM_DATA_REQUEST",
63         "LM_UDATA_REQUEST",
64         "LM_DATA_INDICATION",
65         "LM_UDATA_INDICATION",
66
67         "LM_WATCHDOG_TIMEOUT",
68
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",
78 };
79 #endif  /* CONFIG_IRDA_DEBUG */
80
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 *);
88
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 *);
102
103 static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
104 {
105         irlmp_state_standby,
106         irlmp_state_u_connect,
107         irlmp_state_active,
108 };
109
110 static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
111 {
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
118 };
119
120 static inline void irlmp_next_lap_state(struct lap_cb *self,
121                                         IRLMP_STATE state)
122 {
123         /*
124         IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __FUNCTION__, irlmp_state[state]);
125         */
126         self->lap_state = state;
127 }
128
129 static inline void irlmp_next_lsap_state(struct lsap_cb *self,
130                                          LSAP_STATE state)
131 {
132         /*
133         IRDA_ASSERT(self != NULL, return;);
134         IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
135         */
136         self->lsap_state = state;
137 }
138
139 /* Do connection control events */
140 int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
141                         struct sk_buff *skb)
142 {
143         IRDA_ASSERT(self != NULL, return -1;);
144         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
145
146         IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
147                 __FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
148
149         return (*lsap_state[self->lsap_state]) (self, event, skb);
150 }
151
152 /*
153  * Function do_lap_event (event, skb, info)
154  *
155  *    Do IrLAP control events
156  *
157  */
158 void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
159                         struct sk_buff *skb)
160 {
161         IRDA_ASSERT(self != NULL, return;);
162         IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
163
164         IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n", __FUNCTION__,
165                    irlmp_event[event],
166                    irlmp_state[self->lap_state]);
167
168         (*lap_state[self->lap_state]) (self, event, skb);
169 }
170
171 void irlmp_discovery_timer_expired(void *data)
172 {
173         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
174
175         /* We always cleanup the log (active & passive discovery) */
176         irlmp_do_expiry();
177
178         /* Active discovery is conditional */
179         if (sysctl_discovery)
180                 irlmp_do_discovery(sysctl_discovery_slots);
181
182         /* Restart timer */
183         irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
184 }
185
186 void irlmp_watchdog_timer_expired(void *data)
187 {
188         struct lsap_cb *self = (struct lsap_cb *) data;
189
190         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
191
192         IRDA_ASSERT(self != NULL, return;);
193         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
194
195         irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
196 }
197
198 void irlmp_idle_timer_expired(void *data)
199 {
200         struct lap_cb *self = (struct lap_cb *) data;
201
202         IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
203
204         IRDA_ASSERT(self != NULL, return;);
205         IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
206
207         irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
208 }
209
210 /*
211  * Send an event on all LSAPs attached to this LAP.
212  */
213 static inline void
214 irlmp_do_all_lsap_event(hashbin_t *     lsap_hashbin,
215                         IRLMP_EVENT     event)
216 {
217         struct lsap_cb *lsap;
218         struct lsap_cb *lsap_next;
219
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 */
231
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 */
235
236         lsap = (struct lsap_cb *) hashbin_get_first(lsap_hashbin);
237
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;
244         }
245 }
246
247 /*********************************************************************
248  *
249  *    LAP connection control states
250  *
251  ********************************************************************/
252
253 /*
254  * Function irlmp_state_standby (event, skb, info)
255  *
256  *    STANDBY, The IrLAP connection does not exist.
257  *
258  */
259 static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
260                                 struct sk_buff *skb)
261 {
262         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
263         IRDA_ASSERT(self->irlap != NULL, return;);
264
265         switch (event) {
266         case LM_LAP_DISCOVERY_REQUEST:
267                 /* irlmp_next_station_state( LMP_DISCOVER); */
268
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.
275                  */
276                 irlmp_next_lap_state(self, LAP_ACTIVE);
277
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__);
283
284                 irlmp_next_lap_state(self, LAP_U_CONNECT);
285
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__);
292
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;
299         }
300 }
301
302 /*
303  * Function irlmp_state_u_connect (event, skb, info)
304  *
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)
311 {
312         IRDA_DEBUG(2, "%s(), event=%s\n", __FUNCTION__, irlmp_event[event]);
313
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.
319                  */
320                 irlmp_next_lap_state(self, LAP_ACTIVE);
321
322                 /* Just accept connection TODO, this should be fixed */
323                 irlap_connect_response(self->irlap, skb);
324
325                 /* Tell LSAPs that they can start sending data */
326                 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
327
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);
334                 }
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);
342
343                 /* Tell LSAPs that they can start sending data */
344                 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
345
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);
352                 }
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);
357
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__);
364
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);
369                 }
370                 break;
371         default:
372                 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
373                          __FUNCTION__, irlmp_event[event]);
374                 break;
375         }
376 }
377
378 /*
379  * Function irlmp_state_active (event, skb, info)
380  *
381  *    ACTIVE, IrLAP connection is active
382  *
383  */
384 static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
385                                struct sk_buff *skb)
386 {
387         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
388
389         switch (event) {
390         case LM_LAP_CONNECT_REQUEST:
391                 IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __FUNCTION__);
392
393                 /*
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
398                  */
399                 irlap_clear_disconnect(self->irlap);
400
401                 /*
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.
406                  */
407                 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
408
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:
415                 /*
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
420                  */
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 */
426
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);
438                 }
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);
444                 }
445                 break;
446         case LM_LAP_DISCONNECT_INDICATION:
447                 irlmp_next_lap_state(self, LAP_STANDBY);
448
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);
456
457                 /*
458                  *  Inform all connected LSAP's using this link
459                  */
460                 irlmp_do_all_lsap_event(self->lsaps,
461                                         LM_LAP_DISCONNECT_INDICATION);
462
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;
476         }
477 }
478
479 /*********************************************************************
480  *
481  *    LSAP connection control states
482  *
483  ********************************************************************/
484
485 /*
486  * Function irlmp_state_disconnected (event, skb, info)
487  *
488  *    DISCONNECTED
489  *
490  */
491 static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
492                                     struct sk_buff *skb)
493 {
494         int ret = 0;
495
496         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
497
498         IRDA_ASSERT(self != NULL, return -1;);
499         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
500
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__);
512
513                 if (self->conn_skb) {
514                         IRDA_WARNING("%s: busy with another request!\n",
515                                      __FUNCTION__);
516                         return -EBUSY;
517                 }
518                 /* Don't forget to refcount it (see irlmp_connect_request()) */
519                 skb_get(skb);
520                 self->conn_skb = skb;
521
522                 irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
523
524                 /* Start watchdog timer (5 secs for now) */
525                 irlmp_start_watchdog_timer(self, 5*HZ);
526
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;
534                 }
535                 /* Don't forget to refcount it (see irlap_driver_rcv()) */
536                 skb_get(skb);
537                 self->conn_skb = skb;
538
539                 irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
540
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);
553
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;
560         }
561         return ret;
562 }
563
564 /*
565  * Function irlmp_state_connect (self, event, skb)
566  *
567  *    CONNECT
568  *
569  */
570 static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
571                                 struct sk_buff *skb)
572 {
573         struct lsap_cb *lsap;
574         int ret = 0;
575
576         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
577
578         IRDA_ASSERT(self != NULL, return -1;);
579         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
580
581         switch (event) {
582         case LM_CONNECT_RESPONSE:
583                 /*
584                  *  Bind this LSAP to the IrLAP link where the connect was
585                  *  received
586                  */
587                 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
588                                       NULL);
589
590                 IRDA_ASSERT(lsap == self, return -1;);
591                 IRDA_ASSERT(self->lap != NULL, return -1;);
592                 IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
593
594                 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
595                                (long) self, NULL);
596
597                 set_bit(0, &self->connected);   /* TRUE */
598
599                 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
600                                    self->slsap_sel, CONNECT_CNF, skb);
601
602                 del_timer(&self->watchdog_timer);
603
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__);
610
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;
622         }
623         return ret;
624 }
625
626 /*
627  * Function irlmp_state_connect_pend (event, skb, info)
628  *
629  *    CONNECT_PEND
630  *
631  */
632 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
633                                     struct sk_buff *skb)
634 {
635         struct sk_buff *tx_skb;
636         int ret = 0;
637
638         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
639
640         IRDA_ASSERT(self != NULL, return -1;);
641         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
642
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);
660
661                 tx_skb = self->conn_skb;
662                 self->conn_skb = NULL;
663
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__);
673
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;
688         }
689         return ret;
690 }
691
692 /*
693  * Function irlmp_state_dtr (self, event, skb)
694  *
695  *    DATA_TRANSFER_READY
696  *
697  */
698 static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
699                            struct sk_buff *skb)
700 {
701         LM_REASON reason;
702         int ret = 0;
703
704         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
705
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;);
709
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 */
742
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);
750                 }
751                 break;
752         case LM_LAP_DISCONNECT_INDICATION:
753                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
754
755                 reason = irlmp_convert_lap_reason(self->lap->reason);
756
757                 irlmp_disconnect_indication(self, reason, NULL);
758                 break;
759         case LM_DISCONNECT_INDICATION:
760                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
761
762                 IRDA_ASSERT(self->lap != NULL, return -1;);
763                 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
764
765                 IRDA_ASSERT(skb != NULL, return -1;);
766                 IRDA_ASSERT(skb->len > 3, return -1;);
767                 reason = skb->data[3];
768
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);
772
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;
779         }
780         return ret;
781 }
782
783 /*
784  * Function irlmp_state_setup (event, skb, info)
785  *
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.
789  */
790 static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
791                              struct sk_buff *skb)
792 {
793         LM_REASON reason;
794         int ret = 0;
795
796         IRDA_ASSERT(self != NULL, return -1;);
797         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
798
799         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
800
801         switch (event) {
802         case LM_CONNECT_CONFIRM:
803                 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
804
805                 del_timer(&self->watchdog_timer);
806
807                 irlmp_connect_confirm(self, skb);
808                 break;
809         case LM_DISCONNECT_INDICATION:
810                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
811
812                 IRDA_ASSERT(self->lap != NULL, return -1;);
813                 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
814
815                 IRDA_ASSERT(skb != NULL, return -1;);
816                 IRDA_ASSERT(skb->len > 3, return -1;);
817                 reason = skb->data[3];
818
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);
822
823                 irlmp_disconnect_indication(self, reason, skb);
824                 break;
825         case LM_LAP_DISCONNECT_INDICATION:
826                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
827
828                 del_timer(&self->watchdog_timer);
829
830                 IRDA_ASSERT(self->lap != NULL, return -1;);
831                 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
832
833                 reason = irlmp_convert_lap_reason(self->lap->reason);
834
835                 irlmp_disconnect_indication(self, reason, skb);
836                 break;
837         case LM_WATCHDOG_TIMEOUT:
838                 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __FUNCTION__);
839
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);
843
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;
850         }
851         return ret;
852 }
853
854 /*
855  * Function irlmp_state_setup_pend (event, skb, info)
856  *
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.
861  */
862 static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
863                                   struct sk_buff *skb)
864 {
865         struct sk_buff *tx_skb;
866         LM_REASON reason;
867         int ret = 0;
868
869         IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
870
871         IRDA_ASSERT(self != NULL, return -1;);
872         IRDA_ASSERT(irlmp != NULL, return -1;);
873
874         switch (event) {
875         case LM_LAP_CONNECT_CONFIRM:
876                 IRDA_ASSERT(self->conn_skb != NULL, return -1;);
877
878                 tx_skb = self->conn_skb;
879                 self->conn_skb = NULL;
880
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);
885
886                 irlmp_next_lsap_state(self, LSAP_SETUP);
887                 break;
888         case LM_WATCHDOG_TIMEOUT:
889                 IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n",  __FUNCTION__);
890
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);
894
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);
899
900                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
901
902                 reason = irlmp_convert_lap_reason(self->lap->reason);
903
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;
910         }
911         return ret;
912 }