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