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 <dagb@cs.uit.no>
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 <dagb@cs.uit.no>
11 *
12 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
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 ASSERT(self != NULL, return;);
81 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", __FUNCTION__ );
96
97 ASSERT(self != NULL, return -1;);
98 ASSERT(self->magic == IRLAN_MAGIC, return -1;);
99
100 switch (event) {
101 case IRLAN_DISCOVERY_INDICATION:
102 if (self->client.iriap) {
103 WARNING("%s(), busy with a previous query\n", __FUNCTION__);
104 return -EBUSY;
105 }
106
107 self->client.iriap = iriap_open(LSAP_ANY, IAS_CLIENT, self,
108 irlan_client_get_value_confirm);
109 /* Get some values from peer IAS */
110 irlan_next_client_state(self, IRLAN_QUERY);
111 iriap_getvaluebyclass_request(self->client.iriap,
112 self->saddr, self->daddr,
113 "IrLAN", "IrDA:TinyTP:LsapSel");
114 break;
115 case IRLAN_WATCHDOG_TIMEOUT:
116 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
117 break;
118 default:
119 IRDA_DEBUG(4, "%s(), Unknown event %d\n", __FUNCTION__ , event);
120 break;
121 }
122 if (skb)
123 dev_kfree_skb(skb);
124
125 return 0;
126 }
127
128 /*
129 * Function irlan_client_state_query (event, skb, info)
130 *
131 * QUERY, We have queryed the remote IAS and is ready to connect
132 * to provider, just waiting for the confirm.
133 *
134 */
135 static int irlan_client_state_query(struct irlan_cb *self, IRLAN_EVENT event,
136 struct sk_buff *skb)
137 {
138 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
139
140 ASSERT(self != NULL, return -1;);
141 ASSERT(self->magic == IRLAN_MAGIC, return -1;);
142
143 switch(event) {
144 case IRLAN_IAS_PROVIDER_AVAIL:
145 ASSERT(self->dtsap_sel_ctrl != 0, return -1;);
146
147 self->client.open_retries = 0;
148
149 irttp_connect_request(self->client.tsap_ctrl,
150 self->dtsap_sel_ctrl,
151 self->saddr, self->daddr, NULL,
152 IRLAN_MTU, NULL);
153 irlan_next_client_state(self, IRLAN_CONN);
154 break;
155 case IRLAN_IAS_PROVIDER_NOT_AVAIL:
156 IRDA_DEBUG(2, "%s(), IAS_PROVIDER_NOT_AVAIL\n", __FUNCTION__ );
157 irlan_next_client_state(self, IRLAN_IDLE);
158
159 /* Give the client a kick! */
160 if ((self->provider.access_type == ACCESS_PEER) &&
161 (self->provider.state != IRLAN_IDLE))
162 irlan_client_wakeup(self, self->saddr, self->daddr);
163 break;
164 case IRLAN_LMP_DISCONNECT:
165 case IRLAN_LAP_DISCONNECT:
166 irlan_next_client_state(self, IRLAN_IDLE);
167 break;
168 case IRLAN_WATCHDOG_TIMEOUT:
169 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
170 break;
171 default:
172 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
173 break;
174 }
175 if (skb)
176 dev_kfree_skb(skb);
177
178 return 0;
179 }
180
181 /*
182 * Function irlan_client_state_conn (event, skb, info)
183 *
184 * CONN, We have connected to a provider but has not issued any
185 * commands yet.
186 *
187 */
188 static int irlan_client_state_conn(struct irlan_cb *self, IRLAN_EVENT event,
189 struct sk_buff *skb)
190 {
191 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
192
193 ASSERT(self != NULL, return -1;);
194
195 switch (event) {
196 case IRLAN_CONNECT_COMPLETE:
197 /* Send getinfo cmd */
198 irlan_get_provider_info(self);
199 irlan_next_client_state(self, IRLAN_INFO);
200 break;
201 case IRLAN_LMP_DISCONNECT:
202 case IRLAN_LAP_DISCONNECT:
203 irlan_next_client_state(self, IRLAN_IDLE);
204 break;
205 case IRLAN_WATCHDOG_TIMEOUT:
206 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
207 break;
208 default:
209 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
210 break;
211 }
212 if (skb)
213 dev_kfree_skb(skb);
214
215 return 0;
216 }
217
218 /*
219 * Function irlan_client_state_info (self, event, skb, info)
220 *
221 * INFO, We have issued a GetInfo command and is awaiting a reply.
222 */
223 static int irlan_client_state_info(struct irlan_cb *self, IRLAN_EVENT event,
224 struct sk_buff *skb)
225 {
226 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
227
228 ASSERT(self != NULL, return -1;);
229
230 switch (event) {
231 case IRLAN_DATA_INDICATION:
232 ASSERT(skb != NULL, return -1;);
233
234 irlan_client_parse_response(self, skb);
235
236 irlan_next_client_state(self, IRLAN_MEDIA);
237
238 irlan_get_media_char(self);
239 break;
240
241 case IRLAN_LMP_DISCONNECT:
242 case IRLAN_LAP_DISCONNECT:
243 irlan_next_client_state(self, IRLAN_IDLE);
244 break;
245 case IRLAN_WATCHDOG_TIMEOUT:
246 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
247 break;
248 default:
249 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
250 break;
251 }
252 if (skb)
253 dev_kfree_skb(skb);
254
255 return 0;
256 }
257
258 /*
259 * Function irlan_client_state_media (self, event, skb, info)
260 *
261 * MEDIA, The irlan_client has issued a GetMedia command and is awaiting a
262 * reply.
263 *
264 */
265 static int irlan_client_state_media(struct irlan_cb *self, IRLAN_EVENT event,
266 struct sk_buff *skb)
267 {
268 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
269
270 ASSERT(self != NULL, return -1;);
271
272 switch(event) {
273 case IRLAN_DATA_INDICATION:
274 irlan_client_parse_response(self, skb);
275 irlan_open_data_channel(self);
276 irlan_next_client_state(self, IRLAN_OPEN);
277 break;
278 case IRLAN_LMP_DISCONNECT:
279 case IRLAN_LAP_DISCONNECT:
280 irlan_next_client_state(self, IRLAN_IDLE);
281 break;
282 case IRLAN_WATCHDOG_TIMEOUT:
283 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
284 break;
285 default:
286 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
287 break;
288 }
289 if (skb)
290 dev_kfree_skb(skb);
291
292 return 0;
293 }
294
295 /*
296 * Function irlan_client_state_open (self, event, skb, info)
297 *
298 * OPEN, The irlan_client has issued a OpenData command and is awaiting a
299 * reply
300 *
301 */
302 static int irlan_client_state_open(struct irlan_cb *self, IRLAN_EVENT event,
303 struct sk_buff *skb)
304 {
305 struct qos_info qos;
306
307 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
308
309 ASSERT(self != NULL, return -1;);
310
311 switch(event) {
312 case IRLAN_DATA_INDICATION:
313 irlan_client_parse_response(self, skb);
314
315 /*
316 * Check if we have got the remote TSAP for data
317 * communications
318 */
319 ASSERT(self->dtsap_sel_data != 0, return -1;);
320
321 /* Check which access type we are dealing with */
322 switch (self->client.access_type) {
323 case ACCESS_PEER:
324 if (self->provider.state == IRLAN_OPEN) {
325
326 irlan_next_client_state(self, IRLAN_ARB);
327 irlan_do_client_event(self, IRLAN_CHECK_CON_ARB,
328 NULL);
329 } else {
330
331 irlan_next_client_state(self, IRLAN_WAIT);
332 }
333 break;
334 case ACCESS_DIRECT:
335 case ACCESS_HOSTED:
336 qos.link_disc_time.bits = 0x01; /* 3 secs */
337
338 irttp_connect_request(self->tsap_data,
339 self->dtsap_sel_data,
340 self->saddr, self->daddr, &qos,
341 IRLAN_MTU, NULL);
342
343 irlan_next_client_state(self, IRLAN_DATA);
344 break;
345 default:
346 IRDA_DEBUG(2, "%s(), unknown access type!\n", __FUNCTION__ );
347 break;
348 }
349 break;
350 case IRLAN_LMP_DISCONNECT:
351 case IRLAN_LAP_DISCONNECT:
352 irlan_next_client_state(self, IRLAN_IDLE);
353 break;
354 case IRLAN_WATCHDOG_TIMEOUT:
355 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
356 break;
357 default:
358 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
359 break;
360 }
361
362 if (skb)
363 dev_kfree_skb(skb);
364
365 return 0;
366 }
367
368 /*
369 * Function irlan_client_state_wait (self, event, skb, info)
370 *
371 * WAIT, The irlan_client is waiting for the local provider to enter the
372 * provider OPEN state.
373 *
374 */
375 static int irlan_client_state_wait(struct irlan_cb *self, IRLAN_EVENT event,
376 struct sk_buff *skb)
377 {
378 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
379
380 ASSERT(self != NULL, return -1;);
381
382 switch(event) {
383 case IRLAN_PROVIDER_SIGNAL:
384 irlan_next_client_state(self, IRLAN_ARB);
385 irlan_do_client_event(self, IRLAN_CHECK_CON_ARB, NULL);
386 break;
387 case IRLAN_LMP_DISCONNECT:
388 case IRLAN_LAP_DISCONNECT:
389 irlan_next_client_state(self, IRLAN_IDLE);
390 break;
391 case IRLAN_WATCHDOG_TIMEOUT:
392 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
393 break;
394 default:
395 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
396 break;
397 }
398 if (skb)
399 dev_kfree_skb(skb);
400
401 return 0;
402 }
403
404 static int irlan_client_state_arb(struct irlan_cb *self, IRLAN_EVENT event,
405 struct sk_buff *skb)
406 {
407 struct qos_info qos;
408
409 IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
410
411 ASSERT(self != NULL, return -1;);
412
413 switch(event) {
414 case IRLAN_CHECK_CON_ARB:
415 if (self->client.recv_arb_val == self->provider.send_arb_val) {
416 irlan_next_client_state(self, IRLAN_CLOSE);
417 irlan_close_data_channel(self);
418 } else if (self->client.recv_arb_val <
419 self->provider.send_arb_val)
420 {
421 qos.link_disc_time.bits = 0x01; /* 3 secs */
422
423 irlan_next_client_state(self, IRLAN_DATA);
424 irttp_connect_request(self->tsap_data,
425 self->dtsap_sel_data,
426 self->saddr, self->daddr, &qos,
427 IRLAN_MTU, NULL);
428 } else if (self->client.recv_arb_val >
429 self->provider.send_arb_val)
430 {
431 IRDA_DEBUG(2, "%s(), lost the battle :-(\n", __FUNCTION__ );
432 }
433 break;
434 case IRLAN_DATA_CONNECT_INDICATION:
435 irlan_next_client_state(self, IRLAN_DATA);
436 break;
437 case IRLAN_LMP_DISCONNECT:
438 case IRLAN_LAP_DISCONNECT:
439 irlan_next_client_state(self, IRLAN_IDLE);
440 break;
441 case IRLAN_WATCHDOG_TIMEOUT:
442 IRDA_DEBUG(2, "%s(), IRLAN_WATCHDOG_TIMEOUT\n", __FUNCTION__ );
443 break;
444 default:
445 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
446 break;
447 }
448 if (skb)
449 dev_kfree_skb(skb);
450
451 return 0;
452 }
453
454 /*
455 * Function irlan_client_state_data (self, event, skb, info)
456 *
457 * DATA, The data channel is connected, allowing data transfers between
458 * the local and remote machines.
459 *
460 */
461 static int irlan_client_state_data(struct irlan_cb *self, IRLAN_EVENT event,
462 struct sk_buff *skb)
463 {
464 IRDA_DEBUG(4, "%s()\n", __FUNCTION__ );
465
466 ASSERT(self != NULL, return -1;);
467 ASSERT(self->magic == IRLAN_MAGIC, return -1;);
468
469 switch(event) {
470 case IRLAN_DATA_INDICATION:
471 irlan_client_parse_response(self, skb);
472 break;
473 case IRLAN_LMP_DISCONNECT: /* FALLTHROUGH */
474 case IRLAN_LAP_DISCONNECT:
475 irlan_next_client_state(self, IRLAN_IDLE);
476 break;
477 default:
478 IRDA_DEBUG(2, "%s(), Unknown event %d\n", __FUNCTION__ , event);
479 break;
480 }
481 if (skb)
482 dev_kfree_skb(skb);
483
484 return 0;
485 }
486
487 /*
488 * Function irlan_client_state_close (self, event, skb, info)
489 *
490 *
491 *
492 */
493 static int irlan_client_state_close(struct irlan_cb *self, IRLAN_EVENT event,
494 struct sk_buff *skb)
495 {
496 IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
497
498 if (skb)
499 dev_kfree_skb(skb);
500
501 return 0;
502 }
503
504 /*
505 * Function irlan_client_state_sync (self, event, skb, info)
506 *
507 *
508 *
509 */
510 static int irlan_client_state_sync(struct irlan_cb *self, IRLAN_EVENT event,
511 struct sk_buff *skb)
512 {
513 IRDA_DEBUG(2, "%s()\n", __FUNCTION__ );
514
515 if (skb)
516 dev_kfree_skb(skb);
517
518 return 0;
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532
533
|
This page was automatically generated by the
LXR engine.
|