Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
iriap_event.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Filename: iriap_event.c
4  * Version: 0.1
5  * Description: IAP Finite State Machine
6  * Status: Experimental.
7  * Author: Dag Brattli <[email protected]>
8  * Created at: Thu Aug 21 00:02:07 1997
9  * Modified at: Wed Mar 1 11:28:34 2000
10  * Modified by: Dag Brattli <[email protected]>
11  *
12  * Copyright (c) 1997, 1999-2000 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/slab.h>
28 
29 #include <net/irda/irda.h>
30 #include <net/irda/irlmp.h>
31 #include <net/irda/iriap.h>
32 #include <net/irda/iriap_event.h>
33 
34 static void state_s_disconnect (struct iriap_cb *self, IRIAP_EVENT event,
35  struct sk_buff *skb);
36 static void state_s_connecting (struct iriap_cb *self, IRIAP_EVENT event,
37  struct sk_buff *skb);
38 static void state_s_call (struct iriap_cb *self, IRIAP_EVENT event,
39  struct sk_buff *skb);
40 
41 static void state_s_make_call (struct iriap_cb *self, IRIAP_EVENT event,
42  struct sk_buff *skb);
43 static void state_s_calling (struct iriap_cb *self, IRIAP_EVENT event,
44  struct sk_buff *skb);
45 static void state_s_outstanding (struct iriap_cb *self, IRIAP_EVENT event,
46  struct sk_buff *skb);
47 static void state_s_replying (struct iriap_cb *self, IRIAP_EVENT event,
48  struct sk_buff *skb);
49 static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
50  struct sk_buff *skb);
51 static void state_s_wait_active (struct iriap_cb *self, IRIAP_EVENT event,
52  struct sk_buff *skb);
53 
54 static void state_r_disconnect (struct iriap_cb *self, IRIAP_EVENT event,
55  struct sk_buff *skb);
56 static void state_r_call (struct iriap_cb *self, IRIAP_EVENT event,
57  struct sk_buff *skb);
58 static void state_r_waiting (struct iriap_cb *self, IRIAP_EVENT event,
59  struct sk_buff *skb);
60 static void state_r_wait_active (struct iriap_cb *self, IRIAP_EVENT event,
61  struct sk_buff *skb);
62 static void state_r_receiving (struct iriap_cb *self, IRIAP_EVENT event,
63  struct sk_buff *skb);
64 static void state_r_execute (struct iriap_cb *self, IRIAP_EVENT event,
65  struct sk_buff *skb);
66 static void state_r_returning (struct iriap_cb *self, IRIAP_EVENT event,
67  struct sk_buff *skb);
68 
69 static void (*iriap_state[])(struct iriap_cb *self, IRIAP_EVENT event,
70  struct sk_buff *skb) = {
71  /* Client FSM */
72  state_s_disconnect,
73  state_s_connecting,
74  state_s_call,
75 
76  /* S-Call FSM */
77  state_s_make_call,
78  state_s_calling,
79  state_s_outstanding,
80  state_s_replying,
81  state_s_wait_for_call,
82  state_s_wait_active,
83 
84  /* Server FSM */
85  state_r_disconnect,
86  state_r_call,
87 
88  /* R-Connect FSM */
89  state_r_waiting,
90  state_r_wait_active,
91  state_r_receiving,
92  state_r_execute,
93  state_r_returning,
94 };
95 
97 {
98  IRDA_ASSERT(self != NULL, return;);
99  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
100 
101  self->client_state = state;
102 }
103 
105 {
106  IRDA_ASSERT(self != NULL, return;);
107  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
108 
109  self->call_state = state;
110 }
111 
113 {
114  IRDA_ASSERT(self != NULL, return;);
115  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
116 
117  self->server_state = state;
118 }
119 
121 {
122  IRDA_ASSERT(self != NULL, return;);
123  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
124 
125  self->r_connect_state = state;
126 }
127 
129  struct sk_buff *skb)
130 {
131  IRDA_ASSERT(self != NULL, return;);
132  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
133 
134  (*iriap_state[ self->client_state]) (self, event, skb);
135 }
136 
138  struct sk_buff *skb)
139 {
140  IRDA_ASSERT(self != NULL, return;);
141  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
142 
143  (*iriap_state[ self->call_state]) (self, event, skb);
144 }
145 
147  struct sk_buff *skb)
148 {
149  IRDA_ASSERT(self != NULL, return;);
150  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
151 
152  (*iriap_state[ self->server_state]) (self, event, skb);
153 }
154 
156  struct sk_buff *skb)
157 {
158  IRDA_ASSERT(self != NULL, return;);
159  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
160 
161  (*iriap_state[ self->r_connect_state]) (self, event, skb);
162 }
163 
164 
165 /*
166  * Function state_s_disconnect (event, skb)
167  *
168  * S-Disconnect, The device has no LSAP connection to a particular
169  * remote device.
170  */
171 static void state_s_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
172  struct sk_buff *skb)
173 {
174  IRDA_ASSERT(self != NULL, return;);
175  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
176 
177  switch (event) {
180  IRDA_ASSERT(self->request_skb == NULL, return;);
181  /* Don't forget to refcount it -
182  * see iriap_getvaluebyclass_request(). */
183  skb_get(skb);
184  self->request_skb = skb;
185  iriap_connect_request(self);
186  break;
188  break;
189  default:
190  IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
191  break;
192  }
193 }
194 
195 /*
196  * Function state_s_connecting (self, event, skb)
197  *
198  * S-Connecting
199  *
200  */
201 static void state_s_connecting(struct iriap_cb *self, IRIAP_EVENT event,
202  struct sk_buff *skb)
203 {
204  IRDA_ASSERT(self != NULL, return;);
205  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
206 
207  switch (event) {
209  /*
210  * Jump to S-Call FSM
211  */
213  /* iriap_call_request(self, 0,0,0); */
215  break;
217  /* Abort calls */
220  break;
221  default:
222  IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
223  break;
224  }
225 }
226 
227 /*
228  * Function state_s_call (self, event, skb)
229  *
230  * S-Call, The device can process calls to a specific remote
231  * device. Whenever the LSAP connection is disconnected, this state
232  * catches that event and clears up
233  */
234 static void state_s_call(struct iriap_cb *self, IRIAP_EVENT event,
235  struct sk_buff *skb)
236 {
237  IRDA_ASSERT(self != NULL, return;);
238 
239  switch (event) {
241  /* Abort calls */
244  break;
245  default:
246  IRDA_DEBUG(0, "state_s_call: Unknown event %d\n", event);
247  break;
248  }
249 }
250 
251 /*
252  * Function state_s_make_call (event, skb)
253  *
254  * S-Make-Call
255  *
256  */
257 static void state_s_make_call(struct iriap_cb *self, IRIAP_EVENT event,
258  struct sk_buff *skb)
259 {
260  struct sk_buff *tx_skb;
261 
262  IRDA_ASSERT(self != NULL, return;);
263 
264  switch (event) {
265  case IAP_CALL_REQUEST:
266  /* Already refcounted - see state_s_disconnect() */
267  tx_skb = self->request_skb;
268  self->request_skb = NULL;
269 
270  irlmp_data_request(self->lsap, tx_skb);
272  break;
273  default:
274  IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
275  break;
276  }
277 }
278 
279 /*
280  * Function state_s_calling (event, skb)
281  *
282  * S-Calling
283  *
284  */
285 static void state_s_calling(struct iriap_cb *self, IRIAP_EVENT event,
286  struct sk_buff *skb)
287 {
288  IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
289 }
290 
291 /*
292  * Function state_s_outstanding (event, skb)
293  *
294  * S-Outstanding, The device is waiting for a response to a command
295  *
296  */
297 static void state_s_outstanding(struct iriap_cb *self, IRIAP_EVENT event,
298  struct sk_buff *skb)
299 {
300  IRDA_ASSERT(self != NULL, return;);
301 
302  switch (event) {
303  case IAP_RECV_F_LST:
304  /*iriap_send_ack(self);*/
305  /*LM_Idle_request(idle); */
306 
308  break;
309  default:
310  IRDA_DEBUG(0, "%s(), Unknown event %d\n", __func__, event);
311  break;
312  }
313 }
314 
315 /*
316  * Function state_s_replying (event, skb)
317  *
318  * S-Replying, The device is collecting a multiple part response
319  */
320 static void state_s_replying(struct iriap_cb *self, IRIAP_EVENT event,
321  struct sk_buff *skb)
322 {
323  IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
324 }
325 
326 /*
327  * Function state_s_wait_for_call (event, skb)
328  *
329  * S-Wait-for-Call
330  *
331  */
332 static void state_s_wait_for_call(struct iriap_cb *self, IRIAP_EVENT event,
333  struct sk_buff *skb)
334 {
335  IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
336 }
337 
338 
339 /*
340  * Function state_s_wait_active (event, skb)
341  *
342  * S-Wait-Active
343  *
344  */
345 static void state_s_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
346  struct sk_buff *skb)
347 {
348  IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
349 }
350 
351 /**************************************************************************
352  *
353  * Server FSM
354  *
355  **************************************************************************/
356 
357 /*
358  * Function state_r_disconnect (self, event, skb)
359  *
360  * LM-IAS server is disconnected (not processing any requests!)
361  *
362  */
363 static void state_r_disconnect(struct iriap_cb *self, IRIAP_EVENT event,
364  struct sk_buff *skb)
365 {
366  struct sk_buff *tx_skb;
367 
368  switch (event) {
370  tx_skb = alloc_skb(LMP_MAX_HEADER, GFP_ATOMIC);
371  if (tx_skb == NULL) {
372  IRDA_WARNING("%s: unable to malloc!\n", __func__);
373  return;
374  }
375 
376  /* Reserve space for MUX_CONTROL and LAP header */
377  skb_reserve(tx_skb, LMP_MAX_HEADER);
378 
379  irlmp_connect_response(self->lsap, tx_skb);
380  /*LM_Idle_request(idle); */
381 
383 
384  /*
385  * Jump to R-Connect FSM, we skip R-Waiting since we do not
386  * care about LM_Idle_request()!
387  */
389  break;
390  default:
391  IRDA_DEBUG(0, "%s(), unknown event %d\n", __func__, event);
392  break;
393  }
394 }
395 
396 /*
397  * Function state_r_call (self, event, skb)
398  */
399 static void state_r_call(struct iriap_cb *self, IRIAP_EVENT event,
400  struct sk_buff *skb)
401 {
402  IRDA_DEBUG(4, "%s()\n", __func__);
403 
404  switch (event) {
406  /* Abort call */
409  break;
410  default:
411  IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
412  break;
413  }
414 }
415 
416 /*
417  * R-Connect FSM
418  */
419 
420 /*
421  * Function state_r_waiting (self, event, skb)
422  */
423 static void state_r_waiting(struct iriap_cb *self, IRIAP_EVENT event,
424  struct sk_buff *skb)
425 {
426  IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
427 }
428 
429 static void state_r_wait_active(struct iriap_cb *self, IRIAP_EVENT event,
430  struct sk_buff *skb)
431 {
432  IRDA_DEBUG(0, "%s(), Not implemented\n", __func__);
433 }
434 
435 /*
436  * Function state_r_receiving (self, event, skb)
437  *
438  * We are receiving a command
439  *
440  */
441 static void state_r_receiving(struct iriap_cb *self, IRIAP_EVENT event,
442  struct sk_buff *skb)
443 {
444  IRDA_DEBUG(4, "%s()\n", __func__);
445 
446  switch (event) {
447  case IAP_RECV_F_LST:
449 
450  iriap_call_indication(self, skb);
451  break;
452  default:
453  IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
454  break;
455  }
456 }
457 
458 /*
459  * Function state_r_execute (self, event, skb)
460  *
461  * The server is processing the request
462  *
463  */
464 static void state_r_execute(struct iriap_cb *self, IRIAP_EVENT event,
465  struct sk_buff *skb)
466 {
467  IRDA_DEBUG(4, "%s()\n", __func__);
468 
469  IRDA_ASSERT(skb != NULL, return;);
470  IRDA_ASSERT(self != NULL, return;);
471  IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
472 
473  switch (event) {
474  case IAP_CALL_RESPONSE:
475  /*
476  * Since we don't implement the Waiting state, we return
477  * to state Receiving instead, DB.
478  */
480 
481  /* Don't forget to refcount it - see
482  * iriap_getvaluebyclass_response(). */
483  skb_get(skb);
484 
485  irlmp_data_request(self->lsap, skb);
486  break;
487  default:
488  IRDA_DEBUG(0, "%s(), unknown event!\n", __func__);
489  break;
490  }
491 }
492 
493 static void state_r_returning(struct iriap_cb *self, IRIAP_EVENT event,
494  struct sk_buff *skb)
495 {
496  IRDA_DEBUG(0, "%s(), event=%d\n", __func__, event);
497 
498  switch (event) {
499  case IAP_RECV_F_LST:
500  break;
501  default:
502  break;
503  }
504 }