Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/irda/iriap_event.c
15109 views
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
96
void iriap_next_client_state(struct iriap_cb *self, IRIAP_STATE state)
97
{
98
IRDA_ASSERT(self != NULL, return;);
99
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
100
101
self->client_state = state;
102
}
103
104
void iriap_next_call_state(struct iriap_cb *self, IRIAP_STATE state)
105
{
106
IRDA_ASSERT(self != NULL, return;);
107
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
108
109
self->call_state = state;
110
}
111
112
void iriap_next_server_state(struct iriap_cb *self, IRIAP_STATE state)
113
{
114
IRDA_ASSERT(self != NULL, return;);
115
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
116
117
self->server_state = state;
118
}
119
120
void iriap_next_r_connect_state(struct iriap_cb *self, IRIAP_STATE state)
121
{
122
IRDA_ASSERT(self != NULL, return;);
123
IRDA_ASSERT(self->magic == IAS_MAGIC, return;);
124
125
self->r_connect_state = state;
126
}
127
128
void iriap_do_client_event(struct iriap_cb *self, IRIAP_EVENT event,
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
137
void iriap_do_call_event(struct iriap_cb *self, IRIAP_EVENT event,
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
146
void iriap_do_server_event(struct iriap_cb *self, IRIAP_EVENT event,
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
155
void iriap_do_r_connect_event(struct iriap_cb *self, IRIAP_EVENT event,
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) {
178
case IAP_CALL_REQUEST_GVBC:
179
iriap_next_client_state(self, S_CONNECTING);
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;
187
case IAP_LM_DISCONNECT_INDICATION:
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) {
208
case IAP_LM_CONNECT_CONFIRM:
209
/*
210
* Jump to S-Call FSM
211
*/
212
iriap_do_call_event(self, IAP_CALL_REQUEST, skb);
213
/* iriap_call_request(self, 0,0,0); */
214
iriap_next_client_state(self, S_CALL);
215
break;
216
case IAP_LM_DISCONNECT_INDICATION:
217
/* Abort calls */
218
iriap_next_call_state(self, S_MAKE_CALL);
219
iriap_next_client_state(self, S_DISCONNECT);
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) {
240
case IAP_LM_DISCONNECT_INDICATION:
241
/* Abort calls */
242
iriap_next_call_state(self, S_MAKE_CALL);
243
iriap_next_client_state(self, S_DISCONNECT);
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);
271
iriap_next_call_state(self, S_OUTSTANDING);
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
307
iriap_next_call_state(self, S_WAIT_FOR_CALL);
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) {
369
case IAP_LM_CONNECT_INDICATION:
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
382
iriap_next_server_state(self, R_CALL);
383
384
/*
385
* Jump to R-Connect FSM, we skip R-Waiting since we do not
386
* care about LM_Idle_request()!
387
*/
388
iriap_next_r_connect_state(self, R_RECEIVING);
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) {
405
case IAP_LM_DISCONNECT_INDICATION:
406
/* Abort call */
407
iriap_next_server_state(self, R_DISCONNECT);
408
iriap_next_r_connect_state(self, R_WAITING);
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:
448
iriap_next_r_connect_state(self, R_EXECUTE);
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
*/
479
iriap_next_r_connect_state(self, R_RECEIVING);
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
}
505
506