Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/net/irda/irlan/irlan_client_event.c
17602 views
1
/*********************************************************************
2
*
3
* Filename: irlan_client_event.c
4
* Version: 0.9
5
* Description: IrLAN client state machine
6
* Status: Experimental.
7
* Author: Dag Brattli <[email protected]>
8
* Created at: Sun Aug 31 20:14:37 1997
9
* Modified at: Sun Dec 26 21:52:24 1999
10
* Modified by: Dag Brattli <[email protected]>
11
*
12
* Copyright (c) 1998-1999 Dag Brattli <[email protected]>,
13
* All Rights Reserved.
14
*
15
* This program is free software; you can redistribute it and/or
16
* modify it under the terms of the GNU General Public License as
17
* published by the Free Software Foundation; either version 2 of
18
* the License, or (at your option) any later version.
19
*
20
* Neither Dag Brattli nor University of Tromsø admit liability nor
21
* provide warranty for any of this software. This material is
22
* provided "AS-IS" and at no charge.
23
*
24
********************************************************************/
25
26
#include <linux/skbuff.h>
27
28
#include <net/irda/irda.h>
29
#include <net/irda/timer.h>
30
#include <net/irda/irmod.h>
31
#include <net/irda/iriap.h>
32
#include <net/irda/irlmp.h>
33
#include <net/irda/irttp.h>
34
35
#include <net/irda/irlan_common.h>
36
#include <net/irda/irlan_client.h>
37
#include <net/irda/irlan_event.h>
38
39
static int irlan_client_state_idle (struct irlan_cb *self, IRLAN_EVENT event,
40
struct sk_buff *skb);
41
static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
42
struct sk_buff *skb);
43
static int irlan_client_state_conn (struct irlan_cb *self, IRLAN_EVENT event,
44
struct sk_buff *skb);
45
static int irlan_client_state_info (struct irlan_cb *self, IRLAN_EVENT event,
46
struct sk_buff *skb);
47
static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
48
struct sk_buff *skb);
49
static int irlan_client_state_open (struct irlan_cb *self, IRLAN_EVENT event,
50
struct sk_buff *skb);
51
static int irlan_client_state_wait (struct irlan_cb *self, IRLAN_EVENT event,
52
struct sk_buff *skb);
53
static int irlan_client_state_arb (struct irlan_cb *self, IRLAN_EVENT event,
54
struct sk_buff *skb);
55
static int irlan_client_state_data (struct irlan_cb *self, IRLAN_EVENT event,
56
struct sk_buff *skb);
57
static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
58
struct sk_buff *skb);
59
static int irlan_client_state_sync (struct irlan_cb *self, IRLAN_EVENT event,
60
struct sk_buff *skb);
61
62
static int (*state[])(struct irlan_cb *, IRLAN_EVENT event, struct sk_buff *) =
63
{
64
irlan_client_state_idle,
65
irlan_client_state_query,
66
irlan_client_state_conn,
67
irlan_client_state_info,
68
irlan_client_state_media,
69
irlan_client_state_open,
70
irlan_client_state_wait,
71
irlan_client_state_arb,
72
irlan_client_state_data,
73
irlan_client_state_close,
74
irlan_client_state_sync
75
};
76
77
void irlan_do_client_event(struct irlan_cb *self, IRLAN_EVENT event,
78
struct sk_buff *skb)
79
{
80
IRDA_ASSERT(self != NULL, return;);
81
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return;);
82
83
(*state[ self->client.state]) (self, event, skb);
84
}
85
86
/*
87
* Function irlan_client_state_idle (event, skb, info)
88
*
89
* IDLE, We are waiting for an indication that there is a provider
90
* available.
91
*/
92
static int irlan_client_state_idle(struct irlan_cb *self, IRLAN_EVENT event,
93
struct sk_buff *skb)
94
{
95
IRDA_DEBUG(4, "%s()\n", __func__ );
96
97
IRDA_ASSERT(self != NULL, return -1;);
98
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
99
100
switch (event) {
101
case IRLAN_DISCOVERY_INDICATION:
102
if (self->client.iriap) {
103
IRDA_WARNING("%s(), busy with a previous query\n",
104
__func__);
105
return -EBUSY;
106
}
107
108
self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
109
irlan_client_get_value_confirm);
110
/* Get some values from peer IAS */
111
irlan_next_client_state(self, IRLAN_QUERY);
112
iriap_getvaluebyclass_request(self->client.iriap,
113
self->saddr, self->daddr,
114
"IrLAN", "IrDA:TinyTP:LsapSel");
115
break;
116
case IRLAN_WATCHDOG_TIMEOUT:
117
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
118
break;
119
default:
120
IRDA_DEBUG(4, "%s(), Unknown event %d\n", __func__ , event);
121
break;
122
}
123
if (skb)
124
dev_kfree_skb(skb);
125
126
return 0;
127
}
128
129
/*
130
* Function irlan_client_state_query (event, skb, info)
131
*
132
* QUERY, We have queryed the remote IAS and is ready to connect
133
* to provider, just waiting for the confirm.
134
*
135
*/
136
static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
137
struct sk_buff *skb)
138
{
139
IRDA_DEBUG(4, "%s()\n", __func__ );
140
141
IRDA_ASSERT(self != NULL, return -1;);
142
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
143
144
switch(event) {
145
case IRLAN_IAS_PROVIDER_AVAIL:
146
IRDA_ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
147
148
self->client.open_retries = 0;
149
150
irttp_connect_request(self->client.tsap_ctrl,
151
self->dtsap_sel_ctrl,
152
self->saddr, self->daddr, NULL,
153
IRLAN_MTU, NULL);
154
irlan_next_client_state(self, IRLAN_CONN);
155
break;
156
case IRLAN_IAS_PROVIDER_NOT_AVAIL:
157
IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __func__ );
158
irlan_next_client_state(self, IRLAN_IDLE);
159
160
/* Give the client a kick! */
161
if ((self->provider.access_type == ACCESS_PEER) &&
162
(self->provider.state != IRLAN_IDLE))
163
irlan_client_wakeup(self, self->saddr, self->daddr);
164
break;
165
case IRLAN_LMP_DISCONNECT:
166
case IRLAN_LAP_DISCONNECT:
167
irlan_next_client_state(self, IRLAN_IDLE);
168
break;
169
case IRLAN_WATCHDOG_TIMEOUT:
170
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
171
break;
172
default:
173
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
174
break;
175
}
176
if (skb)
177
dev_kfree_skb(skb);
178
179
return 0;
180
}
181
182
/*
183
* Function irlan_client_state_conn (event, skb, info)
184
*
185
* CONN, We have connected to a provider but has not issued any
186
* commands yet.
187
*
188
*/
189
static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
190
struct sk_buff *skb)
191
{
192
IRDA_DEBUG(4, "%s()\n", __func__ );
193
194
IRDA_ASSERT(self != NULL, return -1;);
195
196
switch (event) {
197
case IRLAN_CONNECT_COMPLETE:
198
/* Send getinfo cmd */
199
irlan_get_provider_info(self);
200
irlan_next_client_state(self, IRLAN_INFO);
201
break;
202
case IRLAN_LMP_DISCONNECT:
203
case IRLAN_LAP_DISCONNECT:
204
irlan_next_client_state(self, IRLAN_IDLE);
205
break;
206
case IRLAN_WATCHDOG_TIMEOUT:
207
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
208
break;
209
default:
210
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
211
break;
212
}
213
if (skb)
214
dev_kfree_skb(skb);
215
216
return 0;
217
}
218
219
/*
220
* Function irlan_client_state_info (self, event, skb, info)
221
*
222
* INFO, We have issued a GetInfo command and is awaiting a reply.
223
*/
224
static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
225
struct sk_buff *skb)
226
{
227
IRDA_DEBUG(4, "%s()\n", __func__ );
228
229
IRDA_ASSERT(self != NULL, return -1;);
230
231
switch (event) {
232
case IRLAN_DATA_INDICATION:
233
IRDA_ASSERT(skb != NULL, return -1;);
234
235
irlan_client_parse_response(self, skb);
236
237
irlan_next_client_state(self, IRLAN_MEDIA);
238
239
irlan_get_media_char(self);
240
break;
241
242
case IRLAN_LMP_DISCONNECT:
243
case IRLAN_LAP_DISCONNECT:
244
irlan_next_client_state(self, IRLAN_IDLE);
245
break;
246
case IRLAN_WATCHDOG_TIMEOUT:
247
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
248
break;
249
default:
250
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
251
break;
252
}
253
if (skb)
254
dev_kfree_skb(skb);
255
256
return 0;
257
}
258
259
/*
260
* Function irlan_client_state_media (self, event, skb, info)
261
*
262
* MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
263
* reply.
264
*
265
*/
266
static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
267
struct sk_buff *skb)
268
{
269
IRDA_DEBUG(4, "%s()\n", __func__ );
270
271
IRDA_ASSERT(self != NULL, return -1;);
272
273
switch(event) {
274
case IRLAN_DATA_INDICATION:
275
irlan_client_parse_response(self, skb);
276
irlan_open_data_channel(self);
277
irlan_next_client_state(self, IRLAN_OPEN);
278
break;
279
case IRLAN_LMP_DISCONNECT:
280
case IRLAN_LAP_DISCONNECT:
281
irlan_next_client_state(self, IRLAN_IDLE);
282
break;
283
case IRLAN_WATCHDOG_TIMEOUT:
284
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
285
break;
286
default:
287
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
288
break;
289
}
290
if (skb)
291
dev_kfree_skb(skb);
292
293
return 0;
294
}
295
296
/*
297
* Function irlan_client_state_open (self, event, skb, info)
298
*
299
* OPEN, The irlan_client has issued a OpenData command and is awaiting a
300
* reply
301
*
302
*/
303
static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
304
struct sk_buff *skb)
305
{
306
struct qos_info qos;
307
308
IRDA_DEBUG(4, "%s()\n", __func__ );
309
310
IRDA_ASSERT(self != NULL, return -1;);
311
312
switch(event) {
313
case IRLAN_DATA_INDICATION:
314
irlan_client_parse_response(self, skb);
315
316
/*
317
* Check if we have got the remote TSAP for data
318
* communications
319
*/
320
IRDA_ASSERT(self->dtsap_sel_data != 0, return -1;);
321
322
/* Check which access type we are dealing with */
323
switch (self->client.access_type) {
324
case ACCESS_PEER:
325
if (self->provider.state == IRLAN_OPEN) {
326
327
irlan_next_client_state(self, IRLAN_ARB);
328
irlan_do_client_event(self, IRLAN_CHECK_CON_ARB,
329
NULL);
330
} else {
331
332
irlan_next_client_state(self, IRLAN_WAIT);
333
}
334
break;
335
case ACCESS_DIRECT:
336
case ACCESS_HOSTED:
337
qos.link_disc_time.bits = 0x01; /* 3 secs */
338
339
irttp_connect_request(self->tsap_data,
340
self->dtsap_sel_data,
341
self->saddr, self->daddr, &qos,
342
IRLAN_MTU, NULL);
343
344
irlan_next_client_state(self, IRLAN_DATA);
345
break;
346
default:
347
IRDA_DEBUG(2, "%s(), unknown access type!\n", __func__ );
348
break;
349
}
350
break;
351
case IRLAN_LMP_DISCONNECT:
352
case IRLAN_LAP_DISCONNECT:
353
irlan_next_client_state(self, IRLAN_IDLE);
354
break;
355
case IRLAN_WATCHDOG_TIMEOUT:
356
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
357
break;
358
default:
359
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
360
break;
361
}
362
363
if (skb)
364
dev_kfree_skb(skb);
365
366
return 0;
367
}
368
369
/*
370
* Function irlan_client_state_wait (self, event, skb, info)
371
*
372
* WAIT, The irlan_client is waiting for the local provider to enter the
373
* provider OPEN state.
374
*
375
*/
376
static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
377
struct sk_buff *skb)
378
{
379
IRDA_DEBUG(4, "%s()\n", __func__ );
380
381
IRDA_ASSERT(self != NULL, return -1;);
382
383
switch(event) {
384
case IRLAN_PROVIDER_SIGNAL:
385
irlan_next_client_state(self, IRLAN_ARB);
386
irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
387
break;
388
case IRLAN_LMP_DISCONNECT:
389
case IRLAN_LAP_DISCONNECT:
390
irlan_next_client_state(self, IRLAN_IDLE);
391
break;
392
case IRLAN_WATCHDOG_TIMEOUT:
393
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
394
break;
395
default:
396
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
397
break;
398
}
399
if (skb)
400
dev_kfree_skb(skb);
401
402
return 0;
403
}
404
405
static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
406
struct sk_buff *skb)
407
{
408
struct qos_info qos;
409
410
IRDA_DEBUG(2, "%s()\n", __func__ );
411
412
IRDA_ASSERT(self != NULL, return -1;);
413
414
switch(event) {
415
case IRLAN_CHECK_CON_ARB:
416
if (self->client.recv_arb_val == self->provider.send_arb_val) {
417
irlan_next_client_state(self, IRLAN_CLOSE);
418
irlan_close_data_channel(self);
419
} else if (self->client.recv_arb_val <
420
self->provider.send_arb_val)
421
{
422
qos.link_disc_time.bits = 0x01; /* 3 secs */
423
424
irlan_next_client_state(self, IRLAN_DATA);
425
irttp_connect_request(self->tsap_data,
426
self->dtsap_sel_data,
427
self->saddr, self->daddr, &qos,
428
IRLAN_MTU, NULL);
429
} else if (self->client.recv_arb_val >
430
self->provider.send_arb_val)
431
{
432
IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __func__ );
433
}
434
break;
435
case IRLAN_DATA_CONNECT_INDICATION:
436
irlan_next_client_state(self, IRLAN_DATA);
437
break;
438
case IRLAN_LMP_DISCONNECT:
439
case IRLAN_LAP_DISCONNECT:
440
irlan_next_client_state(self, IRLAN_IDLE);
441
break;
442
case IRLAN_WATCHDOG_TIMEOUT:
443
IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __func__ );
444
break;
445
default:
446
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
447
break;
448
}
449
if (skb)
450
dev_kfree_skb(skb);
451
452
return 0;
453
}
454
455
/*
456
* Function irlan_client_state_data (self, event, skb, info)
457
*
458
* DATA, The data channel is connected, allowing data transfers between
459
* the local and remote machines.
460
*
461
*/
462
static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
463
struct sk_buff *skb)
464
{
465
IRDA_DEBUG(4, "%s()\n", __func__ );
466
467
IRDA_ASSERT(self != NULL, return -1;);
468
IRDA_ASSERT(self->magic == IRLAN_MAGIC, return -1;);
469
470
switch(event) {
471
case IRLAN_DATA_INDICATION:
472
irlan_client_parse_response(self, skb);
473
break;
474
case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
475
case IRLAN_LAP_DISCONNECT:
476
irlan_next_client_state(self, IRLAN_IDLE);
477
break;
478
default:
479
IRDA_DEBUG(2, "%s(), Unknown event %d\n", __func__ , event);
480
break;
481
}
482
if (skb)
483
dev_kfree_skb(skb);
484
485
return 0;
486
}
487
488
/*
489
* Function irlan_client_state_close (self, event, skb, info)
490
*
491
*
492
*
493
*/
494
static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
495
struct sk_buff *skb)
496
{
497
IRDA_DEBUG(2, "%s()\n", __func__ );
498
499
if (skb)
500
dev_kfree_skb(skb);
501
502
return 0;
503
}
504
505
/*
506
* Function irlan_client_state_sync (self, event, skb, info)
507
*
508
*
509
*
510
*/
511
static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
512
struct sk_buff *skb)
513
{
514
IRDA_DEBUG(2, "%s()\n", __func__ );
515
516
if (skb)
517
dev_kfree_skb(skb);
518
519
return 0;
520
}
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535