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