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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*********************************************************************
2
 *
3
 * Filename:      irlan_client.c
4
 * Version:       0.9
5
 * Description:   IrDA LAN Access Protocol (IrLAN) Client
6
 * Status:        Experimental.
7
 * Author:        Dag Brattli <dagb@cs.uit.no>
8
 * Created at:    Sun Aug 31 20:14:37 1997
9
 * Modified at:   Tue Dec 14 15:47:02 1999
10
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
11
 * Sources:       skeleton.c by Donald Becker <becker@CESDIS.gsfc.nasa.gov>
12
 *                slip.c by Laurence Culhane, <loz@holmes.demon.co.uk>
13
 *                          Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
14
 *
15
 *     Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
16
 *     All Rights Reserved.
17
 *
18
 *     This program is free software; you can redistribute it and/or
19
 *     modify it under the terms of the GNU General Public License as
20
 *     published by the Free Software Foundation; either version 2 of
21
 *     the License, or (at your option) any later version.
22
 *
23
 *     Neither Dag Brattli nor University of Tromsø admit liability nor
24
 *     provide warranty for any of this software. This material is
25
 *     provided "AS-IS" and at no charge.
26
 *
27
 ********************************************************************/
28
 
29
#include <linux/kernel.h>
30
#include <linux/string.h>
31
#include <linux/errno.h>
32
#include <linux/init.h>
33
#include <linux/netdevice.h>
34
#include <linux/etherdevice.h>
35
#include <linux/if_arp.h>
36
#include <net/arp.h>
37
 
38
#include <asm/system.h>
39
#include <asm/bitops.h>
40
#include <asm/byteorder.h>
41
 
42
#include <net/irda/irda.h>
43
#include <net/irda/irttp.h>
44
#include <net/irda/irlmp.h>
45
#include <net/irda/irias_object.h>
46
#include <net/irda/iriap.h>
47
#include <net/irda/timer.h>
48
 
49
#include <net/irda/irlan_common.h>
50
#include <net/irda/irlan_event.h>
51
#include <net/irda/irlan_eth.h>
52
#include <net/irda/irlan_provider.h>
53
#include <net/irda/irlan_client.h>
54
 
55
#undef CONFIG_IRLAN_GRATUITOUS_ARP
56
 
57
static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
58
                                                    LM_REASON reason,
59
                                                    struct sk_buff *);
60
static int irlan_client_ctrl_data_indication(void *instance, void *sap,
61
                                             struct sk_buff *skb);
62
static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
63
                                              struct qos_info *qos,
64
                                              __u32 max_sdu_size,
65
                                              __u8 max_header_size,
66
                                              struct sk_buff *);
67
static void irlan_check_response_param(struct irlan_cb *self, char *param,
68
                                       char *value, int val_len);
69
 
70
static void irlan_client_kick_timer_expired(void *data)
71
{
72
        struct irlan_cb *self = (struct irlan_cb *) data;
73
 
74
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
75
 
76
        ASSERT(self != NULL, return;);
77
        ASSERT(self->magic == IRLAN_MAGIC, return;);
78
 
79
        /*
80
         * If we are in peer mode, the client may not have got the discovery
81
         * indication it needs to make progress. If the client is still in
82
         * IDLE state, we must kick it to, but only if the provider is not IDLE
83
         */
84
        if ((self->provider.access_type == ACCESS_PEER) &&
85
            (self->client.state == IRLAN_IDLE) &&
86
            (self->provider.state != IRLAN_IDLE)) {
87
                irlan_client_wakeup(self, self->saddr, self->daddr);
88
        }
89
}
90
 
91
void irlan_client_start_kick_timer(struct irlan_cb *self, int timeout)
92
{
93
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
94
 
95
        irda_start_timer(&self->client.kick_timer, timeout, (void *) self,
96
                         irlan_client_kick_timer_expired);
97
}
98
 
99
/*
100
 * Function irlan_client_wakeup (self, saddr, daddr)
101
 *
102
 *    Wake up client
103
 *
104
 */
105
void irlan_client_wakeup(struct irlan_cb *self, __u32 saddr, __u32 daddr)
106
{
107
        IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
108
 
109
        ASSERT(self != NULL, return;);
110
        ASSERT(self->magic == IRLAN_MAGIC, return;);
111
 
112
        /*
113
         * Check if we are already awake, or if we are a provider in direct
114
         * mode (in that case we must leave the client idle
115
         */
116
        if ((self->client.state != IRLAN_IDLE) ||
117
            (self->provider.access_type == ACCESS_DIRECT))
118
        {
119
                        IRDA_DEBUG(0, "%s(), already awake!\n", __FUNCTION__);
120
                        return;
121
        }
122
 
123
        /* Addresses may have changed! */
124
        self->saddr = saddr;
125
        self->daddr = daddr;
126
 
127
        if (self->disconnect_reason == LM_USER_REQUEST) {
128
                        IRDA_DEBUG(0, "%s(), still stopped by user\n", __FUNCTION__);
129
                        return;
130
        }
131
 
132
        /* Open TSAPs */
133
        irlan_client_open_ctrl_tsap(self);
134
        irlan_open_data_tsap(self);
135
 
136
        irlan_do_client_event(self, IRLAN_DISCOVERY_INDICATION, NULL);
137
 
138
        /* Start kick timer */
139
        irlan_client_start_kick_timer(self, 2*HZ);
140
}
141
 
142
/*
143
 * Function irlan_discovery_indication (daddr)
144
 *
145
 *    Remote device with IrLAN server support discovered
146
 *
147
 */
148
void irlan_client_discovery_indication(discovery_t *discovery,
149
                                       DISCOVERY_MODE mode,
150
                                       void *priv)
151
{
152
        struct irlan_cb *self;
153
        __u32 saddr, daddr;
154
 
155
        IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
156
 
157
        ASSERT(irlan != NULL, return;);
158
        ASSERT(discovery != NULL, return;);
159
 
160
        /*
161
         * I didn't check it, but I bet that IrLAN suffer from the same
162
         * deficiency as IrComm and doesn't handle two instances
163
         * simultaneously connecting to each other.
164
         * Same workaround, drop passive discoveries.
165
         * Jean II */
166
        if(mode == DISCOVERY_PASSIVE)
167
                return;
168
 
169
        saddr = discovery->saddr;
170
        daddr = discovery->daddr;
171
 
172
        /* Find instance */
173
        self = (struct irlan_cb *) hashbin_get_first(irlan);
174
        if (self) {
175
                ASSERT(self->magic == IRLAN_MAGIC, return;);
176
 
177
                IRDA_DEBUG(1, "%s(), Found instance (%08x)!\n", __FUNCTION__,
178
                      daddr);
179
 
180
                irlan_client_wakeup(self, saddr, daddr);
181
        }
182
}
183
 
184
/*
185
 * Function irlan_client_data_indication (handle, skb)
186
 *
187
 *    This function gets the data that is received on the control channel
188
 *
189
 */
190
static int irlan_client_ctrl_data_indication(void *instance, void *sap,
191
                                             struct sk_buff *skb)
192
{
193
        struct irlan_cb *self;
194
 
195
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
196
 
197
        self = (struct irlan_cb *) instance;
198
 
199
        ASSERT(self != NULL, return -1;);
200
        ASSERT(self->magic == IRLAN_MAGIC, return -1;);
201
        ASSERT(skb != NULL, return -1;);
202
 
203
        irlan_do_client_event(self, IRLAN_DATA_INDICATION, skb);
204
 
205
        /* Ready for a new command */
206
        IRDA_DEBUG(2, "%s(), clearing tx_busy\n", __FUNCTION__);
207
        self->client.tx_busy = FALSE;
208
 
209
        /* Check if we have some queued commands waiting to be sent */
210
        irlan_run_ctrl_tx_queue(self);
211
 
212
        return 0;
213
}
214
 
215
static void irlan_client_ctrl_disconnect_indication(void *instance, void *sap,
216
                                                    LM_REASON reason,
217
                                                    struct sk_buff *userdata)
218
{
219
        struct irlan_cb *self;
220
        struct tsap_cb *tsap;
221
        struct sk_buff *skb;
222
 
223
        IRDA_DEBUG(4, "%s(), reason=%d\n", __FUNCTION__, reason);
224
 
225
        self = (struct irlan_cb *) instance;
226
        tsap = (struct tsap_cb *) sap;
227
 
228
        ASSERT(self != NULL, return;);
229
        ASSERT(self->magic == IRLAN_MAGIC, return;);
230
        ASSERT(tsap != NULL, return;);
231
        ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
232
 
233
        ASSERT(tsap == self->client.tsap_ctrl, return;);
234
 
235
        /* Remove frames queued on the control channel */
236
        while ((skb = skb_dequeue(&self->client.txq))) {
237
                dev_kfree_skb(skb);
238
        }
239
        self->client.tx_busy = FALSE;
240
 
241
        irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
242
}
243
 
244
/*
245
 * Function irlan_client_open_tsaps (self)
246
 *
247
 *    Initialize callbacks and open IrTTP TSAPs
248
 *
249
 */
250
void irlan_client_open_ctrl_tsap(struct irlan_cb *self)
251
{
252
        struct tsap_cb *tsap;
253
        notify_t notify;
254
 
255
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
256
 
257
        ASSERT(self != NULL, return;);
258
        ASSERT(self->magic == IRLAN_MAGIC, return;);
259
 
260
        /* Check if already open */
261
        if (self->client.tsap_ctrl)
262
                return;
263
 
264
        irda_notify_init(&notify);
265
 
266
        /* Set up callbacks */
267
        notify.data_indication       = irlan_client_ctrl_data_indication;
268
        notify.connect_confirm       = irlan_client_ctrl_connect_confirm;
269
        notify.disconnect_indication = irlan_client_ctrl_disconnect_indication;
270
        notify.instance = self;
271
        strncpy(notify.name, "IrLAN ctrl (c)", NOTIFY_MAX_NAME);
272
 
273
        tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
274
        if (!tsap) {
275
                IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__);
276
                return;
277
        }
278
        self->client.tsap_ctrl = tsap;
279
}
280
 
281
/*
282
 * Function irlan_client_connect_confirm (handle, skb)
283
 *
284
 *    Connection to peer IrLAN laye confirmed
285
 *
286
 */
287
static void irlan_client_ctrl_connect_confirm(void *instance, void *sap,
288
                                              struct qos_info *qos,
289
                                              __u32 max_sdu_size,
290
                                              __u8 max_header_size,
291
                                              struct sk_buff *skb)
292
{
293
        struct irlan_cb *self;
294
 
295
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
296
 
297
        self = (struct irlan_cb *) instance;
298
 
299
        ASSERT(self != NULL, return;);
300
        ASSERT(self->magic == IRLAN_MAGIC, return;);
301
 
302
        self->client.max_sdu_size = max_sdu_size;
303
        self->client.max_header_size = max_header_size;
304
 
305
        /* TODO: we could set the MTU depending on the max_sdu_size */
306
 
307
        irlan_do_client_event(self, IRLAN_CONNECT_COMPLETE, NULL);
308
}
309
 
310
/*
311
 * Function irlan_client_reconnect_data_channel (self)
312
 *
313
 *    Try to reconnect data channel (currently not used)
314
 *
315
 */
316
void irlan_client_reconnect_data_channel(struct irlan_cb *self)
317
{
318
        struct sk_buff *skb;
319
        __u8 *frame;
320
 
321
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
322
 
323
        ASSERT(self != NULL, return;);
324
        ASSERT(self->magic == IRLAN_MAGIC, return;);
325
 
326
        skb = dev_alloc_skb(128);
327
        if (!skb)
328
                return;
329
 
330
        /* Reserve space for TTP, LMP, and LAP header */
331
        skb_reserve(skb, self->max_header_size);
332
        skb_put(skb, 2);
333
 
334
        frame = skb->data;
335
 
336
        frame[0] = CMD_RECONNECT_DATA_CHAN;
337
        frame[1] = 0x01;
338
        irlan_insert_array_param(skb, "RECONNECT_KEY",
339
                                 self->client.reconnect_key,
340
                                 self->client.key_len);
341
 
342
        irttp_data_request(self->client.tsap_ctrl, skb);
343
}
344
 
345
/*
346
 * Function irlan_client_parse_response (self, skb)
347
 *
348
 *    Extract all parameters from received buffer, then feed them to
349
 *    check_params for parsing
350
 */
351
void irlan_client_parse_response(struct irlan_cb *self, struct sk_buff *skb)
352
{
353
        __u8 *frame;
354
        __u8 *ptr;
355
        int count;
356
        int ret;
357
        __u16 val_len;
358
        int i;
359
        char *name;
360
        char *value;
361
 
362
        ASSERT(skb != NULL, return;);
363
 
364
        IRDA_DEBUG(4, "%s() skb->len=%d\n", __FUNCTION__, (int) skb->len);
365
 
366
        ASSERT(self != NULL, return;);
367
        ASSERT(self->magic == IRLAN_MAGIC, return;);
368
 
369
        if (!skb) {
370
                ERROR("%s(), Got NULL skb!\n", __FUNCTION__);
371
                return;
372
        }
373
        frame = skb->data;
374
 
375
        /*
376
         *  Check return code and print it if not success
377
         */
378
        if (frame[0]) {
379
                print_ret_code(frame[0]);
380
                return;
381
        }
382
 
383
        name = kmalloc(255, GFP_ATOMIC);
384
        if (!name)
385
                return;
386
        value = kmalloc(1016, GFP_ATOMIC);
387
        if (!value) {
388
                kfree(name);
389
                return;
390
        }
391
 
392
        /* How many parameters? */
393
        count = frame[1];
394
 
395
        IRDA_DEBUG(4, "%s(), got %d parameters\n", __FUNCTION__, count);
396
 
397
        ptr = frame+2;
398
 
399
        /* For all parameters */
400
        for (i=0; i<count;i++) {
401
                ret = irlan_extract_param(ptr, name, value, &val_len);
402
                if (ret < 0) {
403
                        IRDA_DEBUG(2, "%s(), IrLAN, Error!\n", __FUNCTION__);
404
                        break;
405
                }
406
                ptr += ret;
407
                irlan_check_response_param(self, name, value, val_len);
408
        }
409
        /* Cleanup */
410
        kfree(name);
411
        kfree(value);
412
}
413
 
414
/*
415
 * Function irlan_check_response_param (self, param, value, val_len)
416
 *
417
 *     Check which parameter is received and update local variables
418
 *
419
 */
420
static void irlan_check_response_param(struct irlan_cb *self, char *param,
421
                                       char *value, int val_len)
422
{
423
        __u16 tmp_cpu; /* Temporary value in host order */
424
        __u8 *bytes;
425
        int i;
426
 
427
        IRDA_DEBUG(4, "%s(), parm=%s\n", __FUNCTION__, param);
428
 
429
        ASSERT(self != NULL, return;);
430
        ASSERT(self->magic == IRLAN_MAGIC, return;);
431
 
432
        /* Media type */
433
        if (strcmp(param, "MEDIA") == 0) {
434
                if (strcmp(value, "802.3") == 0)
435
                        self->media = MEDIA_802_3;
436
                else
437
                        self->media = MEDIA_802_5;
438
                return;
439
        }
440
        if (strcmp(param, "FILTER_TYPE") == 0) {
441
                if (strcmp(value, "DIRECTED") == 0)
442
                        self->client.filter_type |= IRLAN_DIRECTED;
443
                else if (strcmp(value, "FUNCTIONAL") == 0)
444
                        self->client.filter_type |= IRLAN_FUNCTIONAL;
445
                else if (strcmp(value, "GROUP") == 0)
446
                        self->client.filter_type |= IRLAN_GROUP;
447
                else if (strcmp(value, "MAC_FRAME") == 0)
448
                        self->client.filter_type |= IRLAN_MAC_FRAME;
449
                else if (strcmp(value, "MULTICAST") == 0)
450
                        self->client.filter_type |= IRLAN_MULTICAST;
451
                else if (strcmp(value, "BROADCAST") == 0)
452
                        self->client.filter_type |= IRLAN_BROADCAST;
453
                else if (strcmp(value, "IPX_SOCKET") == 0)
454
                        self->client.filter_type |= IRLAN_IPX_SOCKET;
455
 
456
        }
457
        if (strcmp(param, "ACCESS_TYPE") == 0) {
458
                if (strcmp(value, "DIRECT") == 0)
459
                        self->client.access_type = ACCESS_DIRECT;
460
                else if (strcmp(value, "PEER") == 0)
461
                        self->client.access_type = ACCESS_PEER;
462
                else if (strcmp(value, "HOSTED") == 0)
463
                        self->client.access_type = ACCESS_HOSTED;
464
                else {
465
                        IRDA_DEBUG(2, "%s(), unknown access type!\n", __FUNCTION__);
466
                }
467
        }
468
        /* IRLAN version */
469
        if (strcmp(param, "IRLAN_VER") == 0) {
470
                IRDA_DEBUG(4, "IrLAN version %d.%d\n", (__u8) value[0],
471
                      (__u8) value[1]);
472
 
473
                self->version[0] = value[0];
474
                self->version[1] = value[1];
475
                return;
476
        }
477
        /* Which remote TSAP to use for data channel */
478
        if (strcmp(param, "DATA_CHAN") == 0) {
479
                self->dtsap_sel_data = value[0];
480
                IRDA_DEBUG(4, "Data TSAP = %02x\n", self->dtsap_sel_data);
481
                return;
482
        }
483
        if (strcmp(param, "CON_ARB") == 0) {
484
                memcpy(&tmp_cpu, value, 2); /* Align value */
485
                le16_to_cpus(&tmp_cpu);     /* Convert to host order */
486
                self->client.recv_arb_val = tmp_cpu;
487
                IRDA_DEBUG(2, "%s(), receive arb val=%d\n", __FUNCTION__,
488
                           self->client.recv_arb_val);
489
        }
490
        if (strcmp(param, "MAX_FRAME") == 0) {
491
                memcpy(&tmp_cpu, value, 2); /* Align value */
492
                le16_to_cpus(&tmp_cpu);     /* Convert to host order */
493
                self->client.max_frame = tmp_cpu;
494
                IRDA_DEBUG(4, "%s(), max frame=%d\n", __FUNCTION__,
495
                           self->client.max_frame);
496
        }
497
 
498
        /* RECONNECT_KEY, in case the link goes down! */
499
        if (strcmp(param, "RECONNECT_KEY") == 0) {
500
                IRDA_DEBUG(4, "Got reconnect key: ");
501
                /* for (i = 0; i < val_len; i++) */
502
/*                      printk("%02x", value[i]); */
503
                memcpy(self->client.reconnect_key, value, val_len);
504
                self->client.key_len = val_len;
505
                IRDA_DEBUG(4, "\n");
506
        }
507
        /* FILTER_ENTRY, have we got an ethernet address? */
508
        if (strcmp(param, "FILTER_ENTRY") == 0) {
509
                bytes = value;
510
                IRDA_DEBUG(4, "Ethernet address = %02x:%02x:%02x:%02x:%02x:%02x\n",
511
                      bytes[0], bytes[1], bytes[2], bytes[3], bytes[4],
512
                      bytes[5]);
513
                for (i = 0; i < 6; i++)
514
                        self->dev.dev_addr[i] = bytes[i];
515
        }
516
}
517
 
518
/*
519
 * Function irlan_client_get_value_confirm (obj_id, value)
520
 *
521
 *    Got results from remote LM-IAS
522
 *
523
 */
524
void irlan_client_get_value_confirm(int result, __u16 obj_id,
525
                                    struct ias_value *value, void *priv)
526
{
527
        struct irlan_cb *self;
528
 
529
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
530
 
531
        ASSERT(priv != NULL, return;);
532
 
533
        self = (struct irlan_cb *) priv;
534
        ASSERT(self->magic == IRLAN_MAGIC, return;);
535
 
536
        /* We probably don't need to make any more queries */
537
        iriap_close(self->client.iriap);
538
        self->client.iriap = NULL;
539
 
540
        /* Check if request succeeded */
541
        if (result != IAS_SUCCESS) {
542
                IRDA_DEBUG(2, "%s(), got NULL value!\n", __FUNCTION__);
543
                irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL,
544
                                      NULL);
545
                return;
546
        }
547
 
548
        switch (value->type) {
549
        case IAS_INTEGER:
550
                self->dtsap_sel_ctrl = value->t.integer;
551
 
552
                if (value->t.integer != -1) {
553
                        irlan_do_client_event(self, IRLAN_IAS_PROVIDER_AVAIL,
554
                                              NULL);
555
                        return;
556
                }
557
                irias_delete_value(value);
558
                break;
559
        default:
560
                IRDA_DEBUG(2, "%s(), unknown type!\n", __FUNCTION__);
561
                break;
562
        }
563
        irlan_do_client_event(self, IRLAN_IAS_PROVIDER_NOT_AVAIL, NULL);
564
}

powered by: WebSVN 2.1.0

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