OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [net/] [irda/] [irlmp_event.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*********************************************************************
2
 *
3
 * Filename:      irlmp_event.c
4
 * Version:       0.8
5
 * Description:   An IrDA LMP event driver for Linux
6
 * Status:        Experimental.
7
 * Author:        Dag Brattli <dagb@cs.uit.no>
8
 * Created at:    Mon Aug  4 20:40:53 1997
9
 * Modified at:   Tue Dec 14 23:04:16 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
 *     Copyright (c) 2000-2001 Jean Tourrilhes <jt@hpl.hp.com>
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/config.h>
28
#include <linux/kernel.h>
29
 
30
#include <net/irda/irda.h>
31
#include <net/irda/timer.h>
32
#include <net/irda/irlap.h>
33
#include <net/irda/irlmp.h>
34
#include <net/irda/irlmp_frame.h>
35
#include <net/irda/irlmp_event.h>
36
 
37
const char *irlmp_state[] = {
38
        "LAP_STANDBY",
39
        "LAP_U_CONNECT",
40
        "LAP_ACTIVE",
41
};
42
 
43
const char *irlsap_state[] = {
44
        "LSAP_DISCONNECTED",
45
        "LSAP_CONNECT",
46
        "LSAP_CONNECT_PEND",
47
        "LSAP_DATA_TRANSFER_READY",
48
        "LSAP_SETUP",
49
        "LSAP_SETUP_PEND",
50
};
51
 
52
#ifdef CONFIG_IRDA_DEBUG
53
static const char *irlmp_event[] = {
54
        "LM_CONNECT_REQUEST",
55
        "LM_CONNECT_CONFIRM",
56
        "LM_CONNECT_RESPONSE",
57
        "LM_CONNECT_INDICATION",
58
 
59
        "LM_DISCONNECT_INDICATION",
60
        "LM_DISCONNECT_REQUEST",
61
 
62
        "LM_DATA_REQUEST",
63
        "LM_UDATA_REQUEST",
64
        "LM_DATA_INDICATION",
65
        "LM_UDATA_INDICATION",
66
 
67
        "LM_WATCHDOG_TIMEOUT",
68
 
69
        /* IrLAP events */
70
        "LM_LAP_CONNECT_REQUEST",
71
        "LM_LAP_CONNECT_INDICATION",
72
        "LM_LAP_CONNECT_CONFIRM",
73
        "LM_LAP_DISCONNECT_INDICATION",
74
        "LM_LAP_DISCONNECT_REQUEST",
75
        "LM_LAP_DISCOVERY_REQUEST",
76
        "LM_LAP_DISCOVERY_CONFIRM",
77
        "LM_LAP_IDLE_TIMEOUT",
78
};
79
#endif  /* CONFIG_IRDA_DEBUG */
80
 
81
/* LAP Connection control proto declarations */
82
static void irlmp_state_standby  (struct lap_cb *, IRLMP_EVENT,
83
                                  struct sk_buff *);
84
static void irlmp_state_u_connect(struct lap_cb *, IRLMP_EVENT,
85
                                  struct sk_buff *);
86
static void irlmp_state_active   (struct lap_cb *, IRLMP_EVENT,
87
                                  struct sk_buff *);
88
 
89
/* LSAP Connection control proto declarations */
90
static int irlmp_state_disconnected(struct lsap_cb *, IRLMP_EVENT,
91
                                    struct sk_buff *);
92
static int irlmp_state_connect     (struct lsap_cb *, IRLMP_EVENT,
93
                                    struct sk_buff *);
94
static int irlmp_state_connect_pend(struct lsap_cb *, IRLMP_EVENT,
95
                                    struct sk_buff *);
96
static int irlmp_state_dtr         (struct lsap_cb *, IRLMP_EVENT,
97
                                    struct sk_buff *);
98
static int irlmp_state_setup       (struct lsap_cb *, IRLMP_EVENT,
99
                                    struct sk_buff *);
100
static int irlmp_state_setup_pend  (struct lsap_cb *, IRLMP_EVENT,
101
                                    struct sk_buff *);
102
 
103
static void (*lap_state[]) (struct lap_cb *, IRLMP_EVENT, struct sk_buff *) =
104
{
105
        irlmp_state_standby,
106
        irlmp_state_u_connect,
107
        irlmp_state_active,
108
};
109
 
110
static int (*lsap_state[])( struct lsap_cb *, IRLMP_EVENT, struct sk_buff *) =
111
{
112
        irlmp_state_disconnected,
113
        irlmp_state_connect,
114
        irlmp_state_connect_pend,
115
        irlmp_state_dtr,
116
        irlmp_state_setup,
117
        irlmp_state_setup_pend
118
};
119
 
120
static inline void irlmp_next_lap_state(struct lap_cb *self,
121
                                        IRLMP_STATE state)
122
{
123
        /*
124
        IRDA_DEBUG(4, "%s(), LMP LAP = %s\n", __FUNCTION__, irlmp_state[state]);
125
        */
126
        self->lap_state = state;
127
}
128
 
129
static inline void irlmp_next_lsap_state(struct lsap_cb *self,
130
                                         LSAP_STATE state)
131
{
132
        /*
133
        ASSERT(self != NULL, return;);
134
        IRDA_DEBUG(4, "%s(), LMP LSAP = %s\n", __FUNCTION__, irlsap_state[state]);
135
        */
136
        self->lsap_state = state;
137
}
138
 
139
/* Do connection control events */
140
int irlmp_do_lsap_event(struct lsap_cb *self, IRLMP_EVENT event,
141
                        struct sk_buff *skb)
142
{
143
        ASSERT(self != NULL, return -1;);
144
        ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
145
 
146
        IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
147
                __FUNCTION__, irlmp_event[event], irlsap_state[ self->lsap_state]);
148
 
149
        return (*lsap_state[self->lsap_state]) (self, event, skb);
150
}
151
 
152
/*
153
 * Function do_lap_event (event, skb, info)
154
 *
155
 *    Do IrLAP control events
156
 *
157
 */
158
void irlmp_do_lap_event(struct lap_cb *self, IRLMP_EVENT event,
159
                        struct sk_buff *skb)
160
{
161
        ASSERT(self != NULL, return;);
162
        ASSERT(self->magic == LMP_LAP_MAGIC, return;);
163
 
164
        IRDA_DEBUG(4, "%s(), EVENT = %s, STATE = %s\n",
165
                __FUNCTION__, irlmp_event[event],
166
                irlmp_state[self->lap_state]);
167
 
168
        (*lap_state[self->lap_state]) (self, event, skb);
169
}
170
 
171
void irlmp_discovery_timer_expired(void *data)
172
{
173
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
174
 
175
        /* We always cleanup the log (active & passive discovery) */
176
        irlmp_do_expiry();
177
 
178
        /* Active discovery is conditional */
179
        if (sysctl_discovery)
180
                irlmp_do_discovery(sysctl_discovery_slots);
181
 
182
        /* Restart timer */
183
        irlmp_start_discovery_timer(irlmp, sysctl_discovery_timeout * HZ);
184
}
185
 
186
void irlmp_watchdog_timer_expired(void *data)
187
{
188
        struct lsap_cb *self = (struct lsap_cb *) data;
189
 
190
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
191
 
192
        ASSERT(self != NULL, return;);
193
        ASSERT(self->magic == LMP_LSAP_MAGIC, return;);
194
 
195
        irlmp_do_lsap_event(self, LM_WATCHDOG_TIMEOUT, NULL);
196
}
197
 
198
void irlmp_idle_timer_expired(void *data)
199
{
200
        struct lap_cb *self = (struct lap_cb *) data;
201
 
202
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
203
 
204
        ASSERT(self != NULL, return;);
205
        ASSERT(self->magic == LMP_LAP_MAGIC, return;);
206
 
207
        irlmp_do_lap_event(self, LM_LAP_IDLE_TIMEOUT, NULL);
208
}
209
 
210
/*********************************************************************
211
 *
212
 *    LAP connection control states
213
 *
214
 ********************************************************************/
215
 
216
/*
217
 * Function irlmp_state_standby (event, skb, info)
218
 *
219
 *    STANDBY, The IrLAP connection does not exist.
220
 *
221
 */
222
static void irlmp_state_standby(struct lap_cb *self, IRLMP_EVENT event,
223
                                struct sk_buff *skb)
224
{
225
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
226
        ASSERT(self->irlap != NULL, return;);
227
 
228
        switch (event) {
229
        case LM_LAP_DISCOVERY_REQUEST:
230
                /* irlmp_next_station_state( LMP_DISCOVER); */
231
 
232
                irlap_discovery_request(self->irlap, &irlmp->discovery_cmd);
233
                break;
234
        case LM_LAP_CONNECT_INDICATION:
235
                /*  It's important to switch state first, to avoid IrLMP to
236
                 *  think that the link is free since IrLMP may then start
237
                 *  discovery before the connection is properly set up. DB.
238
                 */
239
                irlmp_next_lap_state(self, LAP_ACTIVE);
240
 
241
                /* Just accept connection TODO, this should be fixed */
242
                irlap_connect_response(self->irlap, skb);
243
                break;
244
        case LM_LAP_CONNECT_REQUEST:
245
                IRDA_DEBUG(4, "%s() LS_CONNECT_REQUEST\n", __FUNCTION__);
246
 
247
                irlmp_next_lap_state(self, LAP_U_CONNECT);
248
 
249
                /* FIXME: need to set users requested QoS */
250
                irlap_connect_request(self->irlap, self->daddr, NULL, 0);
251
                break;
252
        case LM_LAP_DISCONNECT_INDICATION:
253
                IRDA_DEBUG(4, "%s(), Error LM_LAP_DISCONNECT_INDICATION\n", __FUNCTION__);
254
 
255
                irlmp_next_lap_state(self, LAP_STANDBY);
256
                break;
257
        default:
258
                IRDA_DEBUG(0, "%s(), Unknown event %s\n", __FUNCTION__, irlmp_event[event]);
259
                if (skb)
260
                        dev_kfree_skb(skb);
261
                break;
262
        }
263
}
264
 
265
/*
266
 * Function irlmp_state_u_connect (event, skb, info)
267
 *
268
 *    U_CONNECT, The layer above has tried to open an LSAP connection but
269
 *    since the IrLAP connection does not exist, we must first start an
270
 *    IrLAP connection. We are now waiting response from IrLAP.
271
 * */
272
static void irlmp_state_u_connect(struct lap_cb *self, IRLMP_EVENT event,
273
                                  struct sk_buff *skb)
274
{
275
        struct lsap_cb *lsap;
276
        struct lsap_cb *lsap_current;
277
 
278
        IRDA_DEBUG(2, "%s(), event=%s\n",  __FUNCTION__, irlmp_event[event]);
279
 
280
        switch (event) {
281
        case LM_LAP_CONNECT_INDICATION:
282
                /*  It's important to switch state first, to avoid IrLMP to
283
                 *  think that the link is free since IrLMP may then start
284
                 *  discovery before the connection is properly set up. DB.
285
                 */
286
                irlmp_next_lap_state(self, LAP_ACTIVE);
287
 
288
                /* Just accept connection TODO, this should be fixed */
289
                irlap_connect_response(self->irlap, skb);
290
 
291
                lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
292
                while (lsap != NULL) {
293
                        irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
294
                        lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
295
                }
296
                /* Note : by the time we get there (LAP retries and co),
297
                 * the lsaps may already have gone. This avoid getting stuck
298
                 * forever in LAP_ACTIVE state - Jean II */
299
                if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
300
                        IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __FUNCTION__);
301
                        irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
302
                }
303
                break;
304
        case LM_LAP_CONNECT_REQUEST:
305
                /* Already trying to connect */
306
                break;
307
        case LM_LAP_CONNECT_CONFIRM:
308
                /* For all lsap_ce E Associated do LS_Connect_confirm */
309
                irlmp_next_lap_state(self, LAP_ACTIVE);
310
 
311
                lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
312
                while (lsap != NULL) {
313
                        irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
314
                        lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
315
                }
316
                /* Note : by the time we get there (LAP retries and co),
317
                 * the lsaps may already have gone. This avoid getting stuck
318
                 * forever in LAP_ACTIVE state - Jean II */
319
                if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
320
                        IRDA_DEBUG(0, "%s() NO LSAPs !\n",  __FUNCTION__);
321
                        irlmp_start_idle_timer(self, LM_IDLE_TIMEOUT);
322
                }
323
                break;
324
        case LM_LAP_DISCONNECT_INDICATION:
325
                IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_INDICATION\n",  __FUNCTION__);
326
                irlmp_next_lap_state(self, LAP_STANDBY);
327
 
328
                /* Send disconnect event to all LSAPs using this link */
329
                lsap = (struct lsap_cb *) hashbin_get_first( self->lsaps);
330
                while (lsap != NULL ) {
331
                        ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
332
 
333
                        lsap_current = lsap;
334
 
335
                        /* Be sure to stay one item ahead */
336
                        lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
337
                        irlmp_do_lsap_event(lsap_current,
338
                                            LM_LAP_DISCONNECT_INDICATION,
339
                                            NULL);
340
                }
341
                break;
342
        case LM_LAP_DISCONNECT_REQUEST:
343
                IRDA_DEBUG(4, "%s(), LM_LAP_DISCONNECT_REQUEST\n",  __FUNCTION__);
344
 
345
                /* One of the LSAP did timeout or was closed, if it was
346
                 * the last one, try to get out of here - Jean II */
347
                if (HASHBIN_GET_SIZE(self->lsaps) <= 1) {
348
                        irlap_disconnect_request(self->irlap);
349
                }
350
                break;
351
        default:
352
                IRDA_DEBUG(0, "%s(), Unknown event %s\n",
353
                         __FUNCTION__, irlmp_event[event]);
354
                if (skb)
355
                        dev_kfree_skb(skb);
356
                break;
357
        }
358
}
359
 
360
/*
361
 * Function irlmp_state_active (event, skb, info)
362
 *
363
 *    ACTIVE, IrLAP connection is active
364
 *
365
 */
366
static void irlmp_state_active(struct lap_cb *self, IRLMP_EVENT event,
367
                               struct sk_buff *skb)
368
{
369
        struct lsap_cb *lsap;
370
        struct lsap_cb *lsap_current;
371
 
372
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
373
 
374
        switch (event) {
375
        case LM_LAP_CONNECT_REQUEST:
376
                IRDA_DEBUG(4, "%s(), LS_CONNECT_REQUEST\n",  __FUNCTION__);
377
 
378
                /*
379
                 *  LAP connection allready active, just bounce back! Since we
380
                 *  don't know which LSAP that tried to do this, we have to
381
                 *  notify all LSAPs using this LAP, but that should be safe to
382
                 *  do anyway.
383
                 */
384
                lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
385
                while (lsap != NULL) {
386
                        irlmp_do_lsap_event(lsap, LM_LAP_CONNECT_CONFIRM, NULL);
387
                        lsap = (struct lsap_cb*) hashbin_get_next(self->lsaps);
388
                }
389
 
390
                /* Needed by connect indication */
391
                lsap = (struct lsap_cb *) hashbin_get_first(irlmp->unconnected_lsaps);
392
                while (lsap != NULL) {
393
                        lsap_current = lsap;
394
 
395
                        /* Be sure to stay one item ahead */
396
                        lsap = (struct lsap_cb*) hashbin_get_next(irlmp->unconnected_lsaps);
397
                        irlmp_do_lsap_event(lsap_current,
398
                                            LM_LAP_CONNECT_CONFIRM, NULL);
399
                }
400
                /* Keep state */
401
                break;
402
        case LM_LAP_DISCONNECT_REQUEST:
403
                /*
404
                 *  Need to find out if we should close IrLAP or not. If there
405
                 *  is only one LSAP connection left on this link, that LSAP
406
                 *  must be the one that tries to close IrLAP. It will be
407
                 *  removed later and moved to the list of unconnected LSAPs
408
                 */
409
                if (HASHBIN_GET_SIZE(self->lsaps) > 0) {
410
                        /* Timer value is checked in irsysctl - Jean II */
411
                        irlmp_start_idle_timer(self, sysctl_lap_keepalive_time * HZ / 1000);
412
                } else {
413
                        /* No more connections, so close IrLAP */
414
 
415
                        /* We don't want to change state just yet, because
416
                         * we want to reflect accurately the real state of
417
                         * the LAP, not the state we wish it was in,
418
                         * so that we don't loose LM_LAP_CONNECT_REQUEST.
419
                         * In some cases, IrLAP won't close the LAP
420
                         * immediately. For example, it might still be
421
                         * retrying packets or waiting for the pf bit.
422
                         * As the LAP always send a DISCONNECT_INDICATION
423
                         * in PCLOSE or SCLOSE, just change state on that.
424
                         * Jean II */
425
                        irlap_disconnect_request(self->irlap);
426
                }
427
                break;
428
        case LM_LAP_IDLE_TIMEOUT:
429
                if (HASHBIN_GET_SIZE(self->lsaps) == 0) {
430
                        /* Same reasoning as above - keep state */
431
                        irlap_disconnect_request(self->irlap);
432
                }
433
                break;
434
        case LM_LAP_DISCONNECT_INDICATION:
435
                irlmp_next_lap_state(self, LAP_STANDBY);
436
 
437
                /* In some case, at this point our side has already closed
438
                 * all lsaps, and we are waiting for the idle_timer to
439
                 * expire. If another device reconnect immediately, the
440
                 * idle timer will expire in the midle of the connection
441
                 * initialisation, screwing up things a lot...
442
                 * Therefore, we must stop the timer... */
443
                irlmp_stop_idle_timer(self);
444
 
445
                /*
446
                 *  Inform all connected LSAP's using this link
447
                 */
448
                lsap = (struct lsap_cb *) hashbin_get_first(self->lsaps);
449
                while (lsap != NULL ) {
450
                        ASSERT(lsap->magic == LMP_LSAP_MAGIC, return;);
451
 
452
                        lsap_current = lsap;
453
 
454
                        /* Be sure to stay one item ahead */
455
                        lsap = (struct lsap_cb *) hashbin_get_next(self->lsaps);
456
                        irlmp_do_lsap_event(lsap_current,
457
                                            LM_LAP_DISCONNECT_INDICATION,
458
                                            NULL);
459
                }
460
 
461
                /* Force an expiry of the discovery log.
462
                 * Now that the LAP is free, the system may attempt to
463
                 * connect to another device. Unfortunately, our entries
464
                 * are stale. There is a small window (<3s) before the
465
                 * normal discovery will run and where irlmp_connect_request()
466
                 * can get the wrong info, so make sure things get
467
                 * cleaned *NOW* ;-) - Jean II */
468
                irlmp_do_expiry();
469
                break;
470
        default:
471
                IRDA_DEBUG(0, "%s(), Unknown event %s\n",
472
                         __FUNCTION__, irlmp_event[event]);
473
                if (skb)
474
                        dev_kfree_skb(skb);
475
                break;
476
        }
477
}
478
 
479
/*********************************************************************
480
 *
481
 *    LSAP connection control states
482
 *
483
 ********************************************************************/
484
 
485
/*
486
 * Function irlmp_state_disconnected (event, skb, info)
487
 *
488
 *    DISCONNECTED
489
 *
490
 */
491
static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event,
492
                                    struct sk_buff *skb)
493
{
494
        int ret = 0;
495
 
496
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
497
 
498
        ASSERT(self != NULL, return -1;);
499
        ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
500
 
501
        switch (event) {
502
#ifdef CONFIG_IRDA_ULTRA
503
        case LM_UDATA_INDICATION:
504
                irlmp_connless_data_indication(self, skb);
505
                break;
506
#endif /* CONFIG_IRDA_ULTRA */
507
        case LM_CONNECT_REQUEST:
508
                IRDA_DEBUG(4, "%s(), LM_CONNECT_REQUEST\n",  __FUNCTION__);
509
 
510
                if (self->conn_skb) {
511
                        WARNING("%s(), busy with another request!\n",  __FUNCTION__);
512
                        return -EBUSY;
513
                }
514
                self->conn_skb = skb;
515
 
516
                irlmp_next_lsap_state(self, LSAP_SETUP_PEND);
517
 
518
                /* Start watchdog timer (5 secs for now) */
519
                irlmp_start_watchdog_timer(self, 5*HZ);
520
 
521
                irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
522
                break;
523
        case LM_CONNECT_INDICATION:
524
                if (self->conn_skb) {
525
                        WARNING("%s(), busy with another request!\n",  __FUNCTION__);
526
                        return -EBUSY;
527
                }
528
                self->conn_skb = skb;
529
 
530
                irlmp_next_lsap_state(self, LSAP_CONNECT_PEND);
531
 
532
                /* Start watchdog timer
533
                 * This is not mentionned in the spec, but there is a rare
534
                 * race condition that can get the socket stuck.
535
                 * If we receive this event while our LAP is closing down,
536
                 * the LM_LAP_CONNECT_REQUEST get lost and we get stuck in
537
                 * CONNECT_PEND state forever.
538
                 * The other cause of getting stuck down there is if the
539
                 * higher layer never reply to the CONNECT_INDICATION.
540
                 * Anyway, it make sense to make sure that we always have
541
                 * a backup plan. 1 second is plenty (should be immediate).
542
                 * Jean II */
543
                irlmp_start_watchdog_timer(self, 1*HZ);
544
 
545
                irlmp_do_lap_event(self->lap, LM_LAP_CONNECT_REQUEST, NULL);
546
                break;
547
        default:
548
                IRDA_DEBUG(1, "%s(), Unknown event %s on LSAP %#02x\n",
549
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
550
                if (skb)
551
                        dev_kfree_skb(skb);
552
                break;
553
        }
554
        return ret;
555
}
556
 
557
/*
558
 * Function irlmp_state_connect (self, event, skb)
559
 *
560
 *    CONNECT
561
 *
562
 */
563
static int irlmp_state_connect(struct lsap_cb *self, IRLMP_EVENT event,
564
                                struct sk_buff *skb)
565
{
566
        struct lsap_cb *lsap;
567
        int ret = 0;
568
 
569
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
570
 
571
        ASSERT(self != NULL, return -1;);
572
        ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
573
 
574
        switch (event) {
575
        case LM_CONNECT_RESPONSE:
576
                /*
577
                 *  Bind this LSAP to the IrLAP link where the connect was
578
                 *  received
579
                 */
580
                lsap = hashbin_remove(irlmp->unconnected_lsaps, (int) self,
581
                                      NULL);
582
 
583
                ASSERT(lsap == self, return -1;);
584
                ASSERT(self->lap != NULL, return -1;);
585
                ASSERT(self->lap->lsaps != NULL, return -1;);
586
 
587
                hashbin_insert(self->lap->lsaps, (irda_queue_t *) self, (int) self,
588
                               NULL);
589
 
590
                irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
591
                                   self->slsap_sel, CONNECT_CNF, skb);
592
 
593
                del_timer(&self->watchdog_timer);
594
 
595
                irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
596
                break;
597
        case LM_WATCHDOG_TIMEOUT:
598
                /* May happen, who knows...
599
                 * Jean II */
600
                IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __FUNCTION__);
601
 
602
                /* Disconnect, get out... - Jean II */
603
                self->dlsap_sel = LSAP_ANY;
604
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
605
                break;
606
        default:
607
                IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
608
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
609
                if (skb)
610
                        dev_kfree_skb(skb);
611
                break;
612
        }
613
        return ret;
614
}
615
 
616
/*
617
 * Function irlmp_state_connect_pend (event, skb, info)
618
 *
619
 *    CONNECT_PEND
620
 *
621
 */
622
static int irlmp_state_connect_pend(struct lsap_cb *self, IRLMP_EVENT event,
623
                                    struct sk_buff *skb)
624
{
625
        int ret = 0;
626
 
627
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
628
 
629
        ASSERT(self != NULL, return -1;);
630
        ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
631
 
632
        switch (event) {
633
        case LM_CONNECT_REQUEST:
634
                /* Keep state */
635
                break;
636
        case LM_CONNECT_RESPONSE:
637
                IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
638
                           "no indication issued yet\n",  __FUNCTION__);
639
                /* Keep state */
640
                break;
641
        case LM_DISCONNECT_REQUEST:
642
                IRDA_DEBUG(0, "%s(), LM_DISCONNECT_REQUEST, "
643
                           "not yet bound to IrLAP connection\n",  __FUNCTION__);
644
                /* Keep state */
645
                break;
646
        case LM_LAP_CONNECT_CONFIRM:
647
                IRDA_DEBUG(4, "%s(), LS_CONNECT_CONFIRM\n",  __FUNCTION__);
648
                irlmp_next_lsap_state(self, LSAP_CONNECT);
649
 
650
                skb = self->conn_skb;
651
                self->conn_skb = NULL;
652
 
653
                irlmp_connect_indication(self, skb);
654
                break;
655
        case LM_WATCHDOG_TIMEOUT:
656
                /* Will happen in some rare cases because of a race condition.
657
                 * Just make sure we don't stay there forever...
658
                 * Jean II */
659
                IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __FUNCTION__);
660
 
661
                /* Go back to disconnected mode, keep the socket waiting */
662
                self->dlsap_sel = LSAP_ANY;
663
                if(self->conn_skb)
664
                        dev_kfree_skb(self->conn_skb);
665
                self->conn_skb = NULL;
666
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
667
                break;
668
        default:
669
                IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
670
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
671
                if (skb)
672
                        dev_kfree_skb(skb);
673
                break;
674
        }
675
        return ret;
676
}
677
 
678
/*
679
 * Function irlmp_state_dtr (self, event, skb)
680
 *
681
 *    DATA_TRANSFER_READY
682
 *
683
 */
684
static int irlmp_state_dtr(struct lsap_cb *self, IRLMP_EVENT event,
685
                           struct sk_buff *skb)
686
{
687
        LM_REASON reason;
688
        int ret = 0;
689
 
690
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
691
 
692
        ASSERT(self != NULL, return -1;);
693
        ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
694
        ASSERT(self->lap != NULL, return -1;);
695
 
696
        switch (event) {
697
        case LM_DATA_REQUEST: /* Optimize for the common case */
698
                irlmp_send_data_pdu(self->lap, self->dlsap_sel,
699
                                    self->slsap_sel, FALSE, skb);
700
                break;
701
        case LM_DATA_INDICATION: /* Optimize for the common case */
702
                irlmp_data_indication(self, skb);
703
                break;
704
        case LM_UDATA_REQUEST:
705
                ASSERT(skb != NULL, return -1;);
706
                irlmp_send_data_pdu(self->lap, self->dlsap_sel,
707
                                    self->slsap_sel, TRUE, skb);
708
                break;
709
        case LM_UDATA_INDICATION:
710
                irlmp_udata_indication(self, skb);
711
                break;
712
        case LM_CONNECT_REQUEST:
713
                IRDA_DEBUG(0, "%s(), LM_CONNECT_REQUEST, "
714
                           "error, LSAP already connected\n",  __FUNCTION__);
715
                /* Keep state */
716
                break;
717
        case LM_CONNECT_RESPONSE:
718
                IRDA_DEBUG(0, "%s(), LM_CONNECT_RESPONSE, "
719
                           "error, LSAP allready connected\n",  __FUNCTION__);
720
                /* Keep state */
721
                break;
722
        case LM_DISCONNECT_REQUEST:
723
                irlmp_send_lcf_pdu(self->lap, self->dlsap_sel, self->slsap_sel,
724
                                   DISCONNECT, skb);
725
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
726
 
727
                /* Try to close the LAP connection if its still there */
728
                if (self->lap) {
729
                        IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",  __FUNCTION__);
730
                        irlmp_do_lap_event(self->lap,
731
                                           LM_LAP_DISCONNECT_REQUEST,
732
                                           NULL);
733
                }
734
                break;
735
        case LM_LAP_DISCONNECT_INDICATION:
736
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
737
 
738
                reason = irlmp_convert_lap_reason(self->lap->reason);
739
 
740
                irlmp_disconnect_indication(self, reason, NULL);
741
                break;
742
        case LM_DISCONNECT_INDICATION:
743
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
744
 
745
                ASSERT(self->lap != NULL, return -1;);
746
                ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
747
 
748
                ASSERT(skb != NULL, return -1;);
749
                ASSERT(skb->len > 3, return -1;);
750
                reason = skb->data[3];
751
 
752
                 /* Try to close the LAP connection */
753
                IRDA_DEBUG(4, "%ss(), trying to close IrLAP\n",  __FUNCTION__);
754
                irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
755
 
756
                irlmp_disconnect_indication(self, reason, skb);
757
                break;
758
        default:
759
                IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
760
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
761
                if (skb)
762
                        dev_kfree_skb(skb);
763
                break;
764
        }
765
        return ret;
766
}
767
 
768
/*
769
 * Function irlmp_state_setup (event, skb, info)
770
 *
771
 *    SETUP, Station Control has set up the underlying IrLAP connection.
772
 *    An LSAP connection request has been transmitted to the peer
773
 *    LSAP-Connection Control FSM and we are awaiting reply.
774
 */
775
static int irlmp_state_setup(struct lsap_cb *self, IRLMP_EVENT event,
776
                             struct sk_buff *skb)
777
{
778
        LM_REASON reason;
779
        int ret = 0;
780
 
781
        ASSERT(self != NULL, return -1;);
782
        ASSERT(self->magic == LMP_LSAP_MAGIC, return -1;);
783
 
784
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
785
 
786
        switch (event) {
787
        case LM_CONNECT_CONFIRM:
788
                irlmp_next_lsap_state(self, LSAP_DATA_TRANSFER_READY);
789
 
790
                del_timer(&self->watchdog_timer);
791
 
792
                irlmp_connect_confirm(self, skb);
793
                break;
794
        case LM_DISCONNECT_INDICATION:
795
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
796
 
797
                ASSERT(self->lap != NULL, return -1;);
798
                ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
799
 
800
                ASSERT(skb != NULL, return -1;);
801
                ASSERT(skb->len > 3, return -1;);
802
                reason = skb->data[3];
803
 
804
                 /* Try to close the LAP connection */
805
                IRDA_DEBUG(4, "%s(), trying to close IrLAP\n",  __FUNCTION__);
806
                irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
807
 
808
                irlmp_disconnect_indication(self, reason, skb);
809
                break;
810
        case LM_LAP_DISCONNECT_INDICATION:
811
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
812
 
813
                del_timer(&self->watchdog_timer);
814
 
815
                ASSERT(self->lap != NULL, return -1;);
816
                ASSERT(self->lap->magic == LMP_LAP_MAGIC, return -1;);
817
 
818
                reason = irlmp_convert_lap_reason(self->lap->reason);
819
 
820
                irlmp_disconnect_indication(self, reason, skb);
821
                break;
822
        case LM_WATCHDOG_TIMEOUT:
823
                IRDA_DEBUG(0, "%s() WATCHDOG_TIMEOUT!\n",  __FUNCTION__);
824
 
825
                ASSERT(self->lap != NULL, return -1;);
826
                irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
827
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
828
 
829
                irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
830
                break;
831
        default:
832
                IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
833
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
834
                if (skb)
835
                        dev_kfree_skb(skb);
836
                break;
837
        }
838
        return ret;
839
}
840
 
841
/*
842
 * Function irlmp_state_setup_pend (event, skb, info)
843
 *
844
 *    SETUP_PEND, An LM_CONNECT_REQUEST has been received from the service
845
 *    user to set up an LSAP connection. A request has been sent to the
846
 *    LAP FSM to set up the underlying IrLAP connection, and we
847
 *    are awaiting confirm.
848
 */
849
static int irlmp_state_setup_pend(struct lsap_cb *self, IRLMP_EVENT event,
850
                                  struct sk_buff *skb)
851
{
852
        LM_REASON reason;
853
        int ret = 0;
854
 
855
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
856
 
857
        ASSERT(self != NULL, return -1;);
858
        ASSERT(irlmp != NULL, return -1;);
859
 
860
        switch (event) {
861
        case LM_LAP_CONNECT_CONFIRM:
862
                ASSERT(self->conn_skb != NULL, return -1;);
863
 
864
                skb = self->conn_skb;
865
                self->conn_skb = NULL;
866
 
867
                irlmp_send_lcf_pdu(self->lap, self->dlsap_sel,
868
                                   self->slsap_sel, CONNECT_CMD, skb);
869
 
870
                irlmp_next_lsap_state(self, LSAP_SETUP);
871
                break;
872
        case LM_WATCHDOG_TIMEOUT:
873
                IRDA_DEBUG(0, "%s() : WATCHDOG_TIMEOUT !\n",  __FUNCTION__);
874
 
875
                ASSERT(self->lap != NULL, return -1;);
876
                irlmp_do_lap_event(self->lap, LM_LAP_DISCONNECT_REQUEST, NULL);
877
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
878
 
879
                irlmp_disconnect_indication(self, LM_CONNECT_FAILURE, NULL);
880
                break;
881
        case LM_LAP_DISCONNECT_INDICATION: /* LS_Disconnect.indication */
882
                del_timer( &self->watchdog_timer);
883
 
884
                irlmp_next_lsap_state(self, LSAP_DISCONNECTED);
885
 
886
                reason = irlmp_convert_lap_reason(self->lap->reason);
887
 
888
                irlmp_disconnect_indication(self, reason, NULL);
889
                break;
890
        default:
891
                IRDA_DEBUG(0, "%s(), Unknown event %s on LSAP %#02x\n",
892
                           __FUNCTION__, irlmp_event[event], self->slsap_sel);
893
                if (skb)
894
                        dev_kfree_skb(skb);
895
                break;
896
        }
897
        return ret;
898
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.