Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
irlmp_event.c
Go to the documentation of this file.
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 <[email protected]>
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 <[email protected]>
11  *
12  * Copyright (c) 1998-1999 Dag Brattli <[email protected]>,
13  * All Rights Reserved.
14  * Copyright (c) 2000-2003 Jean Tourrilhes <[email protected]>
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 *const irlmp_state[] = {
37  "LAP_STANDBY",
38  "LAP_U_CONNECT",
39  "LAP_ACTIVE",
40 };
41 
42 const char *const 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 *const 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,
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,
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 
171 {
172  IRDA_DEBUG(4, "%s()\n", __func__);
173 
174  /* We always cleanup the log (active & passive discovery) */
175  irlmp_do_expiry();
176 
178 
179  /* Restart timer */
181 }
182 
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 
193 }
194 
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 
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) {
264  /* irlmp_next_station_state( LMP_DISCOVER); */
265 
266  irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
267  break;
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;
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;
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) {
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__);
331  }
332  break;
334  /* Already trying to connect */
335  break;
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__);
349  }
350  break;
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,
358  break;
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) {
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,
409  /* Keep state */
410  break;
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 */
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;
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,
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 bizarre. 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) */
523 
525  break;
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 */
550 
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;
650  IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
651  "not yet bound to IrLAP connection\n", __func__);
652  /* Keep state */
653  break;
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 {
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;
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,
746  NULL);
747  }
748  break;
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;
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__);
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 {
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;
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__);
819 
820  irlmp_disconnect_indication(self, reason, skb);
821  break;
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;);
839  irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
840 
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;
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) {
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;);
890  irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
891 
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 }