Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[platform/adaptation/renesas_rcar/renesas_kernel.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", __func__, 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", __func__, 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                 __func__, 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", __func__,
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", __func__);
173
174         /* We always cleanup the log (active & passive discovery) */
175         irlmp_do_expiry();
176
177         irlmp_do_discovery(sysctl_discovery_slots);
178
179         /* Restart timer */
180         irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
181 }
182
183 void irlmp_watchdog_timer_expired(void *data)
184 {
185         struct lsap_cb *self = (struct lsap_cb *) data;
186
187         IRDA_DEBUG(2, "%s()\n", __func__);
188
189         IRDA_ASSERT(self != NULL, return;);
190         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
191
192         irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
193 }
194
195 void irlmp_idle_timer_expired(void *data)
196 {
197         struct lap_cb *self = (struct lap_cb *) data;
198
199         IRDA_DEBUG(2, "%s()\n", __func__);
200
201         IRDA_ASSERT(self != NULL, return;);
202         IRDA_ASSERT(self->magic == LMP_LAP_MAGIC, return;);
203
204         irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
205 }
206
207 /*
208  * Send an event on all LSAPs attached to this LAP.
209  */
210 static inline void
211 irlmp_do_all_lsap_event(hashbin_t *     lsap_hashbin,
212                         IRLMP_EVENT     event)
213 {
214         struct lsap_cb *lsap;
215         struct lsap_cb *lsap_next;
216
217         /* Note : this function use the new hashbin_find_next()
218          * function, instead of the old hashbin_get_next().
219          * This make sure that we are always pointing one lsap
220          * ahead, so that if the current lsap is removed as the
221          * result of sending the event, we don't care.
222          * Also, as we store the context ourselves, if an enumeration
223          * of the same lsap hashbin happens as the result of sending the
224          * event, we don't care.
225          * The only problem is if the next lsap is removed. In that case,
226          * hashbin_find_next() will return NULL and we will abort the
227          * enumeration. - Jean II */
228
229         /* Also : we don't accept any skb in input. We can *NOT* pass
230          * the same skb to multiple clients safely, we would need to
231          * skb_clone() it. - Jean II */
232
233         lsap = (struct lsap_cb *) hashbin_get_first(lsap_hashbin);
234
235         while (NULL != hashbin_find_next(lsap_hashbin,
236                                          (long) lsap,
237                                          NULL,
238                                          (void *) &lsap_next) ) {
239                 irlmp_do_lsap_event(lsap, event, NULL);
240                 lsap = lsap_next;
241         }
242 }
243
244 /*********************************************************************
245  *
246  *    LAP connection control states
247  *
248  ********************************************************************/
249
250 /*
251  * Function irlmp_state_standby (event, skb, info)
252  *
253  *    STANDBY, The IrLAP connection does not exist.
254  *
255  */
256 static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
257                                 struct sk_buff *skb)
258 {
259         IRDA_DEBUG(4, "%s()\n", __func__);
260         IRDA_ASSERT(self->irlap != NULL, return;);
261
262         switch (event) {
263         case LM_LAP_DISCOVERY_REQUEST:
264                 /* irlmp_next_station_state( LMP_DISCOVER); */
265
266                 irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
267                 break;
268         case LM_LAP_CONNECT_INDICATION:
269                 /*  It's important to switch state first, to avoid IrLMP to
270                  *  think that the link is free since IrLMP may then start
271                  *  discovery before the connection is properly set up. DB.
272                  */
273                 irlmp_next_lap_state(self, LAP_ACTIVE);
274
275                 /* Just accept connection TODO, this should be fixed */
276                 irlap_connect_response(self->irlap, skb);
277                 break;
278         case LM_LAP_CONNECT_REQUEST:
279                 IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __func__);
280
281                 irlmp_next_lap_state(self, LAP_U_CONNECT);
282
283                 /* FIXME: need to set users requested QoS */
284                 irlap_connect_request(self->irlap, self->daddr, NULL, 0);
285                 break;
286         case LM_LAP_DISCONNECT_INDICATION:
287                 IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n",
288                            __func__);
289
290                 irlmp_next_lap_state(self, LAP_STANDBY);
291                 break;
292         default:
293                 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
294                            __func__, irlmp_event[event]);
295                 break;
296         }
297 }
298
299 /*
300  * Function irlmp_state_u_connect (event, skb, info)
301  *
302  *    U_CONNECT, The layer above has tried to open an LSAP connection but
303  *    since the IrLAP connection does not exist, we must first start an
304  *    IrLAP connection. We are now waiting response from IrLAP.
305  * */
306 static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
307                                   struct sk_buff *skb)
308 {
309         IRDA_DEBUG(2, "%s(), event=%s\n", __func__, irlmp_event[event]);
310
311         switch (event) {
312         case LM_LAP_CONNECT_INDICATION:
313                 /*  It's important to switch state first, to avoid IrLMP to
314                  *  think that the link is free since IrLMP may then start
315                  *  discovery before the connection is properly set up. DB.
316                  */
317                 irlmp_next_lap_state(self, LAP_ACTIVE);
318
319                 /* Just accept connection TODO, this should be fixed */
320                 irlap_connect_response(self->irlap, skb);
321
322                 /* Tell LSAPs that they can start sending data */
323                 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
324
325                 /* Note : by the time we get there (LAP retries and co),
326                  * the lsaps may already have gone. This avoid getting stuck
327                  * forever in LAP_ACTIVE state - Jean II */
328                 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
329                         IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __func__);
330                         irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
331                 }
332                 break;
333         case LM_LAP_CONNECT_REQUEST:
334                 /* Already trying to connect */
335                 break;
336         case LM_LAP_CONNECT_CONFIRM:
337                 /* For all lsap_ce E Associated do LS_Connect_confirm */
338                 irlmp_next_lap_state(self, LAP_ACTIVE);
339
340                 /* Tell LSAPs that they can start sending data */
341                 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
342
343                 /* Note : by the time we get there (LAP retries and co),
344                  * the lsaps may already have gone. This avoid getting stuck
345                  * forever in LAP_ACTIVE state - Jean II */
346                 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
347                         IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __func__);
348                         irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
349                 }
350                 break;
351         case LM_LAP_DISCONNECT_INDICATION:
352                 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n",  __func__);
353                 irlmp_next_lap_state(self, LAP_STANDBY);
354
355                 /* Send disconnect event to all LSAPs using this link */
356                 irlmp_do_all_lsap_event(self->lsaps,
357                                         LM_LAP_DISCONNECT_INDICATION);
358                 break;
359         case LM_LAP_DISCONNECT_REQUEST:
360                 IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n",  __func__);
361
362                 /* One of the LSAP did timeout or was closed, if it was
363                  * the last one, try to get out of here - Jean II */
364                 if (HASHBIN_GET_SIZE(self->lsaps) <= 1) {
365                         irlap_disconnect_request(self->irlap);
366                 }
367                 break;
368         default:
369                 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
370                          __func__, irlmp_event[event]);
371                 break;
372         }
373 }
374
375 /*
376  * Function irlmp_state_active (event, skb, info)
377  *
378  *    ACTIVE, IrLAP connection is active
379  *
380  */
381 static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
382                                struct sk_buff *skb)
383 {
384         IRDA_DEBUG(4, "%s()\n", __func__);
385
386         switch (event) {
387         case LM_LAP_CONNECT_REQUEST:
388                 IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n", __func__);
389
390                 /*
391                  * IrLAP may have a pending disconnect. We tried to close
392                  * IrLAP, but it was postponed because the link was
393                  * busy or we were still sending packets. As we now
394                  * need it, make sure it stays on. Jean II
395                  */
396                 irlap_clear_disconnect(self->irlap);
397
398                 /*
399                  *  LAP connection already active, just bounce back! Since we
400                  *  don't know which LSAP that tried to do this, we have to
401                  *  notify all LSAPs using this LAP, but that should be safe to
402                  *  do anyway.
403                  */
404                 irlmp_do_all_lsap_event(self->lsaps, LM_LAP_CONNECT_CONFIRM);
405
406                 /* Needed by connect indication */
407                 irlmp_do_all_lsap_event(irlmp->unconnected_lsaps,
408                                         LM_LAP_CONNECT_CONFIRM);
409                 /* Keep state */
410                 break;
411         case LM_LAP_DISCONNECT_REQUEST:
412                 /*
413                  *  Need to find out if we should close IrLAP or not. If there
414                  *  is only one LSAP connection left on this link, that LSAP
415                  *  must be the one that tries to close IrLAP. It will be
416                  *  removed later and moved to the list of unconnected LSAPs
417                  */
418                 if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
419                         /* Timer value is checked in irsysctl - Jean II */
420                         irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000);
421                 } else {
422                         /* No more connections, so close IrLAP */
423
424                         /* We don't want to change state just yet, because
425                          * we want to reflect accurately the real state of
426                          * the LAP, not the state we wish it was in,
427                          * so that we don't lose LM_LAP_CONNECT_REQUEST.
428                          * In some cases, IrLAP won't close the LAP
429                          * immediately. For example, it might still be
430                          * retrying packets or waiting for the pf bit.
431                          * As the LAP always send a DISCONNECT_INDICATION
432                          * in PCLOSE or SCLOSE, just change state on that.
433                          * Jean II */
434                         irlap_disconnect_request(self->irlap);
435                 }
436                 break;
437         case LM_LAP_IDLE_TIMEOUT:
438                 if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
439                         /* Same reasoning as above - keep state */
440                         irlap_disconnect_request(self->irlap);
441                 }
442                 break;
443         case LM_LAP_DISCONNECT_INDICATION:
444                 irlmp_next_lap_state(self, LAP_STANDBY);
445
446                 /* In some case, at this point our side has already closed
447                  * all lsaps, and we are waiting for the idle_timer to
448                  * expire. If another device reconnect immediately, the
449                  * idle timer will expire in the midle of the connection
450                  * initialisation, screwing up things a lot...
451                  * Therefore, we must stop the timer... */
452                 irlmp_stop_idle_timer(self);
453
454                 /*
455                  *  Inform all connected LSAP's using this link
456                  */
457                 irlmp_do_all_lsap_event(self->lsaps,
458                                         LM_LAP_DISCONNECT_INDICATION);
459
460                 /* Force an expiry of the discovery log.
461                  * Now that the LAP is free, the system may attempt to
462                  * connect to another device. Unfortunately, our entries
463                  * are stale. There is a small window (<3s) before the
464                  * normal discovery will run and where irlmp_connect_request()
465                  * can get the wrong info, so make sure things get
466                  * cleaned *NOW* ;-) - Jean II */
467                 irlmp_do_expiry();
468                 break;
469         default:
470                 IRDA_DEBUG(0, "%s(), Unknown event %s\n",
471                          __func__, irlmp_event[event]);
472                 break;
473         }
474 }
475
476 /*********************************************************************
477  *
478  *    LSAP connection control states
479  *
480  ********************************************************************/
481
482 /*
483  * Function irlmp_state_disconnected (event, skb, info)
484  *
485  *    DISCONNECTED
486  *
487  */
488 static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
489                                     struct sk_buff *skb)
490 {
491         int ret = 0;
492
493         IRDA_DEBUG(4, "%s()\n", __func__);
494
495         IRDA_ASSERT(self != NULL, return -1;);
496         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
497
498         switch (event) {
499 #ifdef CONFIG_IRDA_ULTRA
500         case LM_UDATA_INDICATION:
501                 /* This is most bizzare. Those packets are  aka unreliable
502                  * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA.
503                  * Why do we pass them as Ultra ??? Jean II */
504                 irlmp_connless_data_indication(self, skb);
505                 break;
506 #endif /* CONFIG_IRDA_ULTRA */
507         case LM_CONNECT_REQUEST:
508                 IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n", __func__);
509
510                 if (self->conn_skb) {
511                         IRDA_WARNING("%s: busy with another request!\n",
512                                      __func__);
513                         return -EBUSY;
514                 }
515                 /* Don't forget to refcount it (see irlmp_connect_request()) */
516                 skb_get(skb);
517                 self->conn_skb = skb;
518
519                 irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
520
521                 /* Start watchdog timer (5 secs for now) */
522                 irlmp_start_watchdog_timer(self, 5*HZ);
523
524                 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
525                 break;
526         case LM_CONNECT_INDICATION:
527                 if (self->conn_skb) {
528                         IRDA_WARNING("%s: busy with another request!\n",
529                                      __func__);
530                         return -EBUSY;
531                 }
532                 /* Don't forget to refcount it (see irlap_driver_rcv()) */
533                 skb_get(skb);
534                 self->conn_skb = skb;
535
536                 irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
537
538                 /* Start watchdog timer
539                  * This is not mentionned in the spec, but there is a rare
540                  * race condition that can get the socket stuck.
541                  * If we receive this event while our LAP is closing down,
542                  * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
543                  * CONNECT_PEND state forever.
544                  * The other cause of getting stuck down there is if the
545                  * higher layer never reply to the CONNECT_INDICATION.
546                  * Anyway, it make sense to make sure that we always have
547                  * a backup plan. 1 second is plenty (should be immediate).
548                  * Jean II */
549                 irlmp_start_watchdog_timer(self, 1*HZ);
550
551                 irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
552                 break;
553         default:
554                 IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
555                            __func__, irlmp_event[event], self->slsap_sel);
556                 break;
557         }
558         return ret;
559 }
560
561 /*
562  * Function irlmp_state_connect (self, event, skb)
563  *
564  *    CONNECT
565  *
566  */
567 static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
568                                 struct sk_buff *skb)
569 {
570         struct lsap_cb *lsap;
571         int ret = 0;
572
573         IRDA_DEBUG(4, "%s()\n", __func__);
574
575         IRDA_ASSERT(self != NULL, return -1;);
576         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
577
578         switch (event) {
579         case LM_CONNECT_RESPONSE:
580                 /*
581                  *  Bind this LSAP to the IrLAP link where the connect was
582                  *  received
583                  */
584                 lsap = hashbin_remove(irlmp->unconnected_lsaps, (long) self,
585                                       NULL);
586
587                 IRDA_ASSERT(lsap == self, return -1;);
588                 IRDA_ASSERT(self->lap != NULL, return -1;);
589                 IRDA_ASSERT(self->lap->lsaps != NULL, return -1;);
590
591                 hashbin_insert(self->lap->lsaps, (irda_queue_t *) self,
592                                (long) self, NULL);
593
594                 set_bit(0, &self->connected);   /* TRUE */
595
596                 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
597                                    self->slsap_sel, CONNECT_CNF, skb);
598
599                 del_timer(&self->watchdog_timer);
600
601                 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
602                 break;
603         case LM_WATCHDOG_TIMEOUT:
604                 /* May happen, who knows...
605                  * Jean II */
606                 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __func__);
607
608                 /* Disconnect, get out... - Jean II */
609                 self->lap = NULL;
610                 self->dlsap_sel = LSAP_ANY;
611                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
612                 break;
613         default:
614                 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
615                  * are *not* yet bound to the IrLAP link. Jean II */
616                 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
617                            __func__, irlmp_event[event], self->slsap_sel);
618                 break;
619         }
620         return ret;
621 }
622
623 /*
624  * Function irlmp_state_connect_pend (event, skb, info)
625  *
626  *    CONNECT_PEND
627  *
628  */
629 static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
630                                     struct sk_buff *skb)
631 {
632         struct sk_buff *tx_skb;
633         int ret = 0;
634
635         IRDA_DEBUG(4, "%s()\n", __func__);
636
637         IRDA_ASSERT(self != NULL, return -1;);
638         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
639
640         switch (event) {
641         case LM_CONNECT_REQUEST:
642                 /* Keep state */
643                 break;
644         case LM_CONNECT_RESPONSE:
645                 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
646                            "no indication issued yet\n",  __func__);
647                 /* Keep state */
648                 break;
649         case LM_DISCONNECT_REQUEST:
650                 IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
651                            "not yet bound to IrLAP connection\n",  __func__);
652                 /* Keep state */
653                 break;
654         case LM_LAP_CONNECT_CONFIRM:
655                 IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n",  __func__);
656                 irlmp_next_lsap_state(self, LSAP_CONNECT);
657
658                 tx_skb = self->conn_skb;
659                 self->conn_skb = NULL;
660
661                 irlmp_connect_indication(self, tx_skb);
662                 /* Drop reference count - see irlmp_connect_indication(). */
663                 dev_kfree_skb(tx_skb);
664                 break;
665         case LM_WATCHDOG_TIMEOUT:
666                 /* Will happen in some rare cases because of a race condition.
667                  * Just make sure we don't stay there forever...
668                  * Jean II */
669                 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __func__);
670
671                 /* Go back to disconnected mode, keep the socket waiting */
672                 self->lap = NULL;
673                 self->dlsap_sel = LSAP_ANY;
674                 if(self->conn_skb)
675                         dev_kfree_skb(self->conn_skb);
676                 self->conn_skb = NULL;
677                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
678                 break;
679         default:
680                 /* LM_LAP_DISCONNECT_INDICATION : Should never happen, we
681                  * are *not* yet bound to the IrLAP link. Jean II */
682                 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
683                            __func__, irlmp_event[event], self->slsap_sel);
684                 break;
685         }
686         return ret;
687 }
688
689 /*
690  * Function irlmp_state_dtr (self, event, skb)
691  *
692  *    DATA_TRANSFER_READY
693  *
694  */
695 static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
696                            struct sk_buff *skb)
697 {
698         LM_REASON reason;
699         int ret = 0;
700
701         IRDA_DEBUG(4, "%s()\n", __func__);
702
703         IRDA_ASSERT(self != NULL, return -1;);
704         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
705         IRDA_ASSERT(self->lap != NULL, return -1;);
706
707         switch (event) {
708         case LM_DATA_REQUEST: /* Optimize for the common case */
709                 irlmp_send_data_pdu(self->lap, self->dlsap_sel,
710                                     self->slsap_sel, FALSE, skb);
711                 break;
712         case LM_DATA_INDICATION: /* Optimize for the common case */
713                 irlmp_data_indication(self, skb);
714                 break;
715         case LM_UDATA_REQUEST:
716                 IRDA_ASSERT(skb != NULL, return -1;);
717                 irlmp_send_data_pdu(self->lap, self->dlsap_sel,
718                                     self->slsap_sel, TRUE, skb);
719                 break;
720         case LM_UDATA_INDICATION:
721                 irlmp_udata_indication(self, skb);
722                 break;
723         case LM_CONNECT_REQUEST:
724                 IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
725                            "error, LSAP already connected\n", __func__);
726                 /* Keep state */
727                 break;
728         case LM_CONNECT_RESPONSE:
729                 IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
730                            "error, LSAP already connected\n", __func__);
731                 /* Keep state */
732                 break;
733         case LM_DISCONNECT_REQUEST:
734                 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
735                                    DISCONNECT, skb);
736                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
737                 /* Called only from irlmp_disconnect_request(), will
738                  * unbind from LAP over there. Jean II */
739
740                 /* Try to close the LAP connection if its still there */
741                 if (self->lap) {
742                         IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",
743                                    __func__);
744                         irlmp_do_lap_event(self->lap,
745                                            LM_LAP_DISCONNECT_REQUEST,
746                                            NULL);
747                 }
748                 break;
749         case LM_LAP_DISCONNECT_INDICATION:
750                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
751
752                 reason = irlmp_convert_lap_reason(self->lap->reason);
753
754                 irlmp_disconnect_indication(self, reason, NULL);
755                 break;
756         case LM_DISCONNECT_INDICATION:
757                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
758
759                 IRDA_ASSERT(self->lap != NULL, return -1;);
760                 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
761
762                 IRDA_ASSERT(skb != NULL, return -1;);
763                 IRDA_ASSERT(skb->len > 3, return -1;);
764                 reason = skb->data[3];
765
766                  /* Try to close the LAP connection */
767                 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n", __func__);
768                 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
769
770                 irlmp_disconnect_indication(self, reason, skb);
771                 break;
772         default:
773                 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
774                            __func__, irlmp_event[event], self->slsap_sel);
775                 break;
776         }
777         return ret;
778 }
779
780 /*
781  * Function irlmp_state_setup (event, skb, info)
782  *
783  *    SETUP, Station Control has set up the underlying IrLAP connection.
784  *    An LSAP connection request has been transmitted to the peer
785  *    LSAP-Connection Control FSM and we are awaiting reply.
786  */
787 static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
788                              struct sk_buff *skb)
789 {
790         LM_REASON reason;
791         int ret = 0;
792
793         IRDA_ASSERT(self != NULL, return -1;);
794         IRDA_ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
795
796         IRDA_DEBUG(4, "%s()\n", __func__);
797
798         switch (event) {
799         case LM_CONNECT_CONFIRM:
800                 irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
801
802                 del_timer(&self->watchdog_timer);
803
804                 irlmp_connect_confirm(self, skb);
805                 break;
806         case LM_DISCONNECT_INDICATION:
807                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
808
809                 IRDA_ASSERT(self->lap != NULL, return -1;);
810                 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
811
812                 IRDA_ASSERT(skb != NULL, return -1;);
813                 IRDA_ASSERT(skb->len > 3, return -1;);
814                 reason = skb->data[3];
815
816                  /* Try to close the LAP connection */
817                 IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",  __func__);
818                 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
819
820                 irlmp_disconnect_indication(self, reason, skb);
821                 break;
822         case LM_LAP_DISCONNECT_INDICATION:
823                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
824
825                 del_timer(&self->watchdog_timer);
826
827                 IRDA_ASSERT(self->lap != NULL, return -1;);
828                 IRDA_ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
829
830                 reason = irlmp_convert_lap_reason(self->lap->reason);
831
832                 irlmp_disconnect_indication(self, reason, skb);
833                 break;
834         case LM_WATCHDOG_TIMEOUT:
835                 IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n", __func__);
836
837                 IRDA_ASSERT(self->lap != NULL, return -1;);
838                 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
839                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
840
841                 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
842                 break;
843         default:
844                 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
845                            __func__, irlmp_event[event], self->slsap_sel);
846                 break;
847         }
848         return ret;
849 }
850
851 /*
852  * Function irlmp_state_setup_pend (event, skb, info)
853  *
854  *    SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
855  *    user to set up an LSAP connection. A request has been sent to the
856  *    LAP FSM to set up the underlying IrLAP connection, and we
857  *    are awaiting confirm.
858  */
859 static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
860                                   struct sk_buff *skb)
861 {
862         struct sk_buff *tx_skb;
863         LM_REASON reason;
864         int ret = 0;
865
866         IRDA_DEBUG(4, "%s()\n", __func__);
867
868         IRDA_ASSERT(self != NULL, return -1;);
869         IRDA_ASSERT(irlmp != NULL, return -1;);
870
871         switch (event) {
872         case LM_LAP_CONNECT_CONFIRM:
873                 IRDA_ASSERT(self->conn_skb != NULL, return -1;);
874
875                 tx_skb = self->conn_skb;
876                 self->conn_skb = NULL;
877
878                 irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
879                                    self->slsap_sel, CONNECT_CMD, tx_skb);
880                 /* Drop reference count - see irlap_data_request(). */
881                 dev_kfree_skb(tx_skb);
882
883                 irlmp_next_lsap_state(self, LSAP_SETUP);
884                 break;
885         case LM_WATCHDOG_TIMEOUT:
886                 IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n",  __func__);
887
888                 IRDA_ASSERT(self->lap != NULL, return -1;);
889                 irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
890                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
891
892                 irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
893                 break;
894         case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
895                 del_timer( &self->watchdog_timer);
896
897                 irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
898
899                 reason = irlmp_convert_lap_reason(self->lap->reason);
900
901                 irlmp_disconnect_indication(self, reason, NULL);
902                 break;
903         default:
904                 IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
905                            __func__, irlmp_event[event], self->slsap_sel);
906                 break;
907         }
908         return ret;
909 }