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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*********************************************************************
2
 *
3
 * Filename:      irlan_common.c
4
 * Version:       0.9
5
 * Description:   IrDA LAN Access Protocol Implementation
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:53:10 1999
10
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
11
 *
12
 *     Copyright (c) 1997, 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/config.h>
27
#include <linux/module.h>
28
 
29
#include <linux/kernel.h>
30
#include <linux/string.h>
31
#include <linux/init.h>
32
#include <linux/errno.h>
33
#include <linux/proc_fs.h>
34
#include <linux/netdevice.h>
35
#include <linux/etherdevice.h>
36
 
37
#include <asm/system.h>
38
#include <asm/bitops.h>
39
#include <asm/byteorder.h>
40
 
41
#include <net/irda/irda.h>
42
#include <net/irda/irttp.h>
43
#include <net/irda/irlmp.h>
44
#include <net/irda/iriap.h>
45
#include <net/irda/timer.h>
46
 
47
#include <net/irda/irlan_common.h>
48
#include <net/irda/irlan_client.h>
49
#include <net/irda/irlan_provider.h> 
50
#include <net/irda/irlan_eth.h>
51
#include <net/irda/irlan_filter.h>
52
 
53
 
54
/*
55
 * Send gratuitous ARP when connected to a new AP or not. May be a clever
56
 * thing to do, but for some reason the machine crashes if you use DHCP. So
57
 * lets not use it by default.
58
 */
59
#undef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
60
 
61
/* extern char sysctl_devname[]; */
62
 
63
/*
64
 *  Master structure
65
 */
66
hashbin_t *irlan = NULL;
67
static __u32 ckey, skey;
68
 
69
/* Module parameters */
70
static int eth = 0; /* Use "eth" or "irlan" name for devices */
71
static int access = ACCESS_PEER; /* PEER, DIRECT or HOSTED */
72
 
73
#ifdef CONFIG_PROC_FS
74
static char *irlan_state[] = {
75
        "IRLAN_IDLE",
76
        "IRLAN_QUERY",
77
        "IRLAN_CONN",
78
        "IRLAN_INFO",
79
        "IRLAN_MEDIA",
80
        "IRLAN_OPEN",
81
        "IRLAN_WAIT",
82
        "IRLAN_ARB",
83
        "IRLAN_DATA",
84
        "IRLAN_CLOSE",
85
        "IRLAN_SYNC"
86
};
87
 
88
static char *irlan_access[] = {
89
        "UNKNOWN",
90
        "DIRECT",
91
        "PEER",
92
        "HOSTED"
93
};
94
 
95
static char *irlan_media[] = {
96
        "UNKNOWN",
97
        "802.3",
98
        "802.5"
99
};
100
#endif /* CONFIG_PROC_FS */
101
 
102
static void __irlan_close(struct irlan_cb *self);
103
static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
104
                                __u8 value_byte, __u16 value_short,
105
                                __u8 *value_array, __u16 value_len);
106
void irlan_close_tsaps(struct irlan_cb *self);
107
 
108
#ifdef CONFIG_PROC_FS
109
static int irlan_proc_read(char *buf, char **start, off_t offset, int len);
110
 
111
extern struct proc_dir_entry *proc_irda;
112
#endif /* CONFIG_PROC_FS */
113
 
114
/*
115
 * Function irlan_init (void)
116
 *
117
 *    Initialize IrLAN layer
118
 *
119
 */
120
int __init irlan_init(void)
121
{
122
        struct irlan_cb *new;
123
        __u16 hints;
124
 
125
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
126
        /* Allocate master structure */
127
        irlan = hashbin_new(HB_LOCAL);
128
        if (irlan == NULL) {
129
                printk(KERN_WARNING "IrLAN: Can't allocate hashbin!\n");
130
                return -ENOMEM;
131
        }
132
#ifdef CONFIG_PROC_FS
133
        create_proc_info_entry("irlan", 0, proc_irda, irlan_proc_read);
134
#endif /* CONFIG_PROC_FS */
135
 
136
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
137
        hints = irlmp_service_to_hint(S_LAN);
138
 
139
        /* Register with IrLMP as a client */
140
        ckey = irlmp_register_client(hints, &irlan_client_discovery_indication,
141
                                     NULL, NULL);
142
 
143
        /* Register with IrLMP as a service */
144
        skey = irlmp_register_service(hints);
145
 
146
        /* Start the master IrLAN instance (the only one for now) */
147
        new = irlan_open(DEV_ADDR_ANY, DEV_ADDR_ANY);
148
 
149
        /* The master will only open its (listen) control TSAP */
150
        irlan_provider_open_ctrl_tsap(new);
151
 
152
        /* Do some fast discovery! */
153
        irlmp_discovery_request(DISCOVERY_DEFAULT_SLOTS);
154
 
155
        return 0;
156
}
157
 
158
void irlan_cleanup(void)
159
{
160
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
161
 
162
        irlmp_unregister_client(ckey);
163
        irlmp_unregister_service(skey);
164
 
165
#ifdef CONFIG_PROC_FS
166
        remove_proc_entry("irlan", proc_irda);
167
#endif /* CONFIG_PROC_FS */
168
        /*
169
         *  Delete hashbin and close all irlan client instances in it
170
         */
171
        hashbin_delete(irlan, (FREE_FUNC) __irlan_close);
172
}
173
 
174
/*
175
 * Function irlan_register_netdev (self)
176
 *
177
 *    Registers the network device to be used. We should don't register until
178
 *    we have been binded to a particular provider or client.
179
 */
180
int irlan_register_netdev(struct irlan_cb *self)
181
{
182
        int i=0;
183
 
184
        IRDA_DEBUG(0, "%s()\n", __FUNCTION__);
185
 
186
        /* Check if we should call the device eth<x> or irlan<x> */
187
        if (!eth) {
188
                /* Get the first free irlan<x> name */
189
                do {
190
                        sprintf(self->dev.name, "%s%d", "irlan", i++);
191
                } while (dev_get(self->dev.name));
192
        }
193
 
194
        if (register_netdev(&self->dev) != 0) {
195
                IRDA_DEBUG(2, "%s(), register_netdev() failed!\n", __FUNCTION__);
196
                return -1;
197
        }
198
        return 0;
199
}
200
 
201
/*
202
 * Function irlan_open (void)
203
 *
204
 *    Open new instance of a client/provider, we should only register the
205
 *    network device if this instance is ment for a particular client/provider
206
 */
207
struct irlan_cb *irlan_open(__u32 saddr, __u32 daddr)
208
{
209
        struct irlan_cb *self;
210
 
211
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
212
        ASSERT(irlan != NULL, return NULL;);
213
 
214
        /*
215
         *  Initialize the irlan structure.
216
         */
217
        self = kmalloc(sizeof(struct irlan_cb), GFP_ATOMIC);
218
        if (self == NULL)
219
                return NULL;
220
 
221
        memset(self, 0, sizeof(struct irlan_cb));
222
 
223
        /*
224
         *  Initialize local device structure
225
         */
226
        self->magic = IRLAN_MAGIC;
227
 
228
        sprintf(self->dev.name, "%s", "unknown");
229
 
230
        self->dev.priv = (void *) self;
231
        self->dev.next = NULL;
232
        self->dev.init = irlan_eth_init;
233
 
234
        self->saddr = saddr;
235
        self->daddr = daddr;
236
 
237
        /* Provider access can only be PEER, DIRECT, or HOSTED */
238
        self->provider.access_type = access;
239
        self->media = MEDIA_802_3;
240
        self->disconnect_reason = LM_USER_REQUEST;
241
        init_timer(&self->watchdog_timer);
242
        init_timer(&self->client.kick_timer);
243
        init_waitqueue_head(&self->open_wait);
244
 
245
        hashbin_insert(irlan, (irda_queue_t *) self, daddr, NULL);
246
 
247
        skb_queue_head_init(&self->client.txq);
248
 
249
        irlan_next_client_state(self, IRLAN_IDLE);
250
        irlan_next_provider_state(self, IRLAN_IDLE);
251
 
252
        irlan_register_netdev(self);
253
 
254
        return self;
255
}
256
/*
257
 * Function __irlan_close (self)
258
 *
259
 *    This function closes and deallocates the IrLAN client instances. Be
260
 *    aware that other functions which calles client_close() must call
261
 *    hashbin_remove() first!!!
262
 */
263
static void __irlan_close(struct irlan_cb *self)
264
{
265
        struct sk_buff *skb;
266
 
267
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
268
 
269
        ASSERT(self != NULL, return;);
270
        ASSERT(self->magic == IRLAN_MAGIC, return;);
271
 
272
        del_timer(&self->watchdog_timer);
273
        del_timer(&self->client.kick_timer);
274
 
275
        /* Close all open connections and remove TSAPs */
276
        irlan_close_tsaps(self);
277
 
278
        if (self->client.iriap)
279
                iriap_close(self->client.iriap);
280
 
281
        /* Remove frames queued on the control channel */
282
        while ((skb = skb_dequeue(&self->client.txq)))
283
                dev_kfree_skb(skb);
284
 
285
        unregister_netdev(&self->dev);
286
 
287
        self->magic = 0;
288
        kfree(self);
289
}
290
 
291
/*
292
 * Function irlan_connect_indication (instance, sap, qos, max_sdu_size, skb)
293
 *
294
 *    Here we receive the connect indication for the data channel
295
 *
296
 */
297
void irlan_connect_indication(void *instance, void *sap, struct qos_info *qos,
298
                              __u32 max_sdu_size, __u8 max_header_size,
299
                              struct sk_buff *skb)
300
{
301
        struct irlan_cb *self;
302
        struct tsap_cb *tsap;
303
 
304
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
305
 
306
        self = (struct irlan_cb *) instance;
307
        tsap = (struct tsap_cb *) sap;
308
 
309
        ASSERT(self != NULL, return;);
310
        ASSERT(self->magic == IRLAN_MAGIC, return;);
311
        ASSERT(tsap == self->tsap_data,return;);
312
 
313
        self->max_sdu_size = max_sdu_size;
314
        self->max_header_size = max_header_size;
315
 
316
        IRDA_DEBUG(0, "IrLAN, We are now connected!\n");
317
 
318
        del_timer(&self->watchdog_timer);
319
 
320
        /* If you want to pass the skb to *both* state machines, you will
321
         * need to skb_clone() it, so that you don't free it twice.
322
         * As the state machines don't need it, git rid of it here...
323
         * Jean II */
324
        if (skb)
325
                dev_kfree_skb(skb);
326
 
327
        irlan_do_provider_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
328
        irlan_do_client_event(self, IRLAN_DATA_CONNECT_INDICATION, NULL);
329
 
330
        if (self->provider.access_type == ACCESS_PEER) {
331
                /*
332
                 * Data channel is open, so we are now allowed to
333
                 * configure the remote filter
334
                 */
335
                irlan_get_unicast_addr(self);
336
                irlan_open_unicast_addr(self);
337
        }
338
        /* Ready to transfer Ethernet frames (at last) */
339
        netif_start_queue(&self->dev); /* Clear reason */
340
}
341
 
342
void irlan_connect_confirm(void *instance, void *sap, struct qos_info *qos,
343
                           __u32 max_sdu_size, __u8 max_header_size,
344
                           struct sk_buff *skb)
345
{
346
        struct irlan_cb *self;
347
 
348
        self = (struct irlan_cb *) instance;
349
 
350
        ASSERT(self != NULL, return;);
351
        ASSERT(self->magic == IRLAN_MAGIC, return;);
352
 
353
        self->max_sdu_size = max_sdu_size;
354
        self->max_header_size = max_header_size;
355
 
356
        /* TODO: we could set the MTU depending on the max_sdu_size */
357
 
358
        IRDA_DEBUG(2, "IrLAN, We are now connected!\n");
359
        del_timer(&self->watchdog_timer);
360
 
361
        /*
362
         * Data channel is open, so we are now allowed to configure the remote
363
         * filter
364
         */
365
        irlan_get_unicast_addr(self);
366
        irlan_open_unicast_addr(self);
367
 
368
        /* Open broadcast and multicast filter by default */
369
        irlan_set_broadcast_filter(self, TRUE);
370
        irlan_set_multicast_filter(self, TRUE);
371
 
372
        /* Ready to transfer Ethernet frames */
373
        netif_start_queue(&self->dev);
374
        self->disconnect_reason = 0; /* Clear reason */
375
#ifdef CONFIG_IRLAN_SEND_GRATUITOUS_ARP
376
        irlan_eth_send_gratuitous_arp(&self->dev);
377
#endif
378
        wake_up_interruptible(&self->open_wait);
379
}
380
 
381
/*
382
 * Function irlan_client_disconnect_indication (handle)
383
 *
384
 *    Callback function for the IrTTP layer. Indicates a disconnection of
385
 *    the specified connection (handle)
386
 */
387
void irlan_disconnect_indication(void *instance, void *sap, LM_REASON reason,
388
                                 struct sk_buff *userdata)
389
{
390
        struct irlan_cb *self;
391
        struct tsap_cb *tsap;
392
 
393
        IRDA_DEBUG(0, "%s(), reason=%d\n", __FUNCTION__, reason);
394
 
395
        self = (struct irlan_cb *) instance;
396
        tsap = (struct tsap_cb *) sap;
397
 
398
        ASSERT(self != NULL, return;);
399
        ASSERT(self->magic == IRLAN_MAGIC, return;);
400
        ASSERT(tsap != NULL, return;);
401
        ASSERT(tsap->magic == TTP_TSAP_MAGIC, return;);
402
 
403
        ASSERT(tsap == self->tsap_data, return;);
404
 
405
        IRDA_DEBUG(2, "IrLAN, data channel disconnected by peer!\n");
406
 
407
        /* Save reason so we know if we should try to reconnect or not */
408
        self->disconnect_reason = reason;
409
 
410
        switch (reason) {
411
        case LM_USER_REQUEST: /* User request */
412
                IRDA_DEBUG(2, "%s(), User requested\n", __FUNCTION__);
413
                break;
414
        case LM_LAP_DISCONNECT: /* Unexpected IrLAP disconnect */
415
                IRDA_DEBUG(2, "%s(), Unexpected IrLAP disconnect\n", __FUNCTION__);
416
                break;
417
        case LM_CONNECT_FAILURE: /* Failed to establish IrLAP connection */
418
                IRDA_DEBUG(2, "%s(), IrLAP connect failed\n", __FUNCTION__);
419
                break;
420
        case LM_LAP_RESET:  /* IrLAP reset */
421
                IRDA_DEBUG(2, "%s(), IrLAP reset\n", __FUNCTION__);
422
                break;
423
        case LM_INIT_DISCONNECT:
424
                IRDA_DEBUG(2, "%s(), IrLMP connect failed\n", __FUNCTION__);
425
                break;
426
        default:
427
                ERROR("%s(), Unknown disconnect reason\n", __FUNCTION__);
428
                break;
429
        }
430
 
431
        /* If you want to pass the skb to *both* state machines, you will
432
         * need to skb_clone() it, so that you don't free it twice.
433
         * As the state machines don't need it, git rid of it here...
434
         * Jean II */
435
        if (userdata)
436
                dev_kfree_skb(userdata);
437
 
438
        irlan_do_client_event(self, IRLAN_LMP_DISCONNECT, NULL);
439
        irlan_do_provider_event(self, IRLAN_LMP_DISCONNECT, NULL);
440
 
441
        wake_up_interruptible(&self->open_wait);
442
}
443
 
444
void irlan_open_data_tsap(struct irlan_cb *self)
445
{
446
        struct tsap_cb *tsap;
447
        notify_t notify;
448
 
449
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
450
 
451
        ASSERT(self != NULL, return;);
452
        ASSERT(self->magic == IRLAN_MAGIC, return;);
453
 
454
        /* Check if already open */
455
        if (self->tsap_data)
456
                return;
457
 
458
        irda_notify_init(&notify);
459
 
460
        notify.data_indication       = irlan_eth_receive;
461
        notify.udata_indication      = irlan_eth_receive;
462
        notify.connect_indication    = irlan_connect_indication;
463
        notify.connect_confirm       = irlan_connect_confirm;
464
        /*notify.flow_indication       = irlan_eth_flow_indication;*/
465
        notify.disconnect_indication = irlan_disconnect_indication;
466
        notify.instance              = self;
467
        strncpy(notify.name, "IrLAN data", NOTIFY_MAX_NAME);
468
 
469
        tsap = irttp_open_tsap(LSAP_ANY, DEFAULT_INITIAL_CREDIT, &notify);
470
        if (!tsap) {
471
                IRDA_DEBUG(2, "%s(), Got no tsap!\n", __FUNCTION__);
472
                return;
473
        }
474
        self->tsap_data = tsap;
475
 
476
        /*
477
         *  This is the data TSAP selector which we will pass to the client
478
         *  when the client ask for it.
479
         */
480
        self->stsap_sel_data = self->tsap_data->stsap_sel;
481
}
482
 
483
void irlan_close_tsaps(struct irlan_cb *self)
484
{
485
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
486
 
487
        ASSERT(self != NULL, return;);
488
        ASSERT(self->magic == IRLAN_MAGIC, return;);
489
 
490
        /* Disconnect and close all open TSAP connections */
491
        if (self->tsap_data) {
492
                irttp_disconnect_request(self->tsap_data, NULL, P_NORMAL);
493
                irttp_close_tsap(self->tsap_data);
494
                self->tsap_data = NULL;
495
        }
496
        if (self->client.tsap_ctrl) {
497
                irttp_disconnect_request(self->client.tsap_ctrl, NULL,
498
                                         P_NORMAL);
499
                irttp_close_tsap(self->client.tsap_ctrl);
500
                self->client.tsap_ctrl = NULL;
501
        }
502
        if (self->provider.tsap_ctrl) {
503
                irttp_disconnect_request(self->provider.tsap_ctrl, NULL,
504
                                         P_NORMAL);
505
                irttp_close_tsap(self->provider.tsap_ctrl);
506
                self->provider.tsap_ctrl = NULL;
507
        }
508
        self->disconnect_reason = LM_USER_REQUEST;
509
}
510
 
511
/*
512
 * Function irlan_ias_register (self, tsap_sel)
513
 *
514
 *    Register with LM-IAS
515
 *
516
 */
517
void irlan_ias_register(struct irlan_cb *self, __u8 tsap_sel)
518
{
519
        struct ias_object *obj;
520
        struct ias_value *new_value;
521
 
522
        ASSERT(self != NULL, return;);
523
        ASSERT(self->magic == IRLAN_MAGIC, return;);
524
 
525
        /*
526
         * Check if object has already been registred by a previous provider.
527
         * If that is the case, we just change the value of the attribute
528
         */
529
        if (!irias_find_object("IrLAN")) {
530
                obj = irias_new_object("IrLAN", IAS_IRLAN_ID);
531
                irias_add_integer_attrib(obj, "IrDA:TinyTP:LsapSel", tsap_sel,
532
                                         IAS_KERNEL_ATTR);
533
                irias_insert_object(obj);
534
        } else {
535
                new_value = irias_new_integer_value(tsap_sel);
536
                irias_object_change_attribute("IrLAN", "IrDA:TinyTP:LsapSel",
537
                                              new_value);
538
        }
539
 
540
        /* Register PnP object only if not registred before */
541
        if (!irias_find_object("PnP")) {
542
                obj = irias_new_object("PnP", IAS_PNP_ID);
543
#if 0
544
                irias_add_string_attrib(obj, "Name", sysctl_devname,
545
                                        IAS_KERNEL_ATTR);
546
#else
547
                irias_add_string_attrib(obj, "Name", "Linux", IAS_KERNEL_ATTR);
548
#endif
549
                irias_add_string_attrib(obj, "DeviceID", "HWP19F0",
550
                                        IAS_KERNEL_ATTR);
551
                irias_add_integer_attrib(obj, "CompCnt", 1, IAS_KERNEL_ATTR);
552
                if (self->provider.access_type == ACCESS_PEER)
553
                        irias_add_string_attrib(obj, "Comp#01", "PNP8389",
554
                                                IAS_KERNEL_ATTR);
555
                else
556
                        irias_add_string_attrib(obj, "Comp#01", "PNP8294",
557
                                                IAS_KERNEL_ATTR);
558
 
559
                irias_add_string_attrib(obj, "Manufacturer",
560
                                        "Linux-IrDA Project", IAS_KERNEL_ATTR);
561
                irias_insert_object(obj);
562
        }
563
}
564
 
565
/*
566
 * Function irlan_run_ctrl_tx_queue (self)
567
 *
568
 *    Try to send the next command in the control transmit queue
569
 *
570
 */
571
int irlan_run_ctrl_tx_queue(struct irlan_cb *self)
572
{
573
        struct sk_buff *skb;
574
 
575
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
576
 
577
        if (irda_lock(&self->client.tx_busy) == FALSE)
578
                return -EBUSY;
579
 
580
        skb = skb_dequeue(&self->client.txq);
581
        if (!skb) {
582
                self->client.tx_busy = FALSE;
583
                return 0;
584
        }
585
 
586
        /* Check that it's really possible to send commands */
587
        if ((self->client.tsap_ctrl == NULL) ||
588
            (self->client.state == IRLAN_IDLE))
589
        {
590
                self->client.tx_busy = FALSE;
591
                dev_kfree_skb(skb);
592
                return -1;
593
        }
594
        IRDA_DEBUG(2, "%s(), sending ...\n", __FUNCTION__);
595
 
596
        return irttp_data_request(self->client.tsap_ctrl, skb);
597
}
598
 
599
/*
600
 * Function irlan_ctrl_data_request (self, skb)
601
 *
602
 *    This function makes sure that commands on the control channel is being
603
 *    sent in a command/response fashion
604
 */
605
void irlan_ctrl_data_request(struct irlan_cb *self, struct sk_buff *skb)
606
{
607
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
608
 
609
        /* Queue command */
610
        skb_queue_tail(&self->client.txq, skb);
611
 
612
        /* Try to send command */
613
        irlan_run_ctrl_tx_queue(self);
614
}
615
 
616
/*
617
 * Function irlan_get_provider_info (self)
618
 *
619
 *    Send Get Provider Information command to peer IrLAN layer
620
 *
621
 */
622
void irlan_get_provider_info(struct irlan_cb *self)
623
{
624
        struct sk_buff *skb;
625
        __u8 *frame;
626
 
627
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
628
 
629
        ASSERT(self != NULL, return;);
630
        ASSERT(self->magic == IRLAN_MAGIC, return;);
631
 
632
        skb = dev_alloc_skb(64);
633
        if (!skb)
634
                return;
635
 
636
        /* Reserve space for TTP, LMP, and LAP header */
637
        skb_reserve(skb, self->client.max_header_size);
638
        skb_put(skb, 2);
639
 
640
        frame = skb->data;
641
 
642
        frame[0] = CMD_GET_PROVIDER_INFO;
643
        frame[1] = 0x00;                 /* Zero parameters */
644
 
645
        irlan_ctrl_data_request(self, skb);
646
}
647
 
648
/*
649
 * Function irlan_open_data_channel (self)
650
 *
651
 *    Send an Open Data Command to provider
652
 *
653
 */
654
void irlan_open_data_channel(struct irlan_cb *self)
655
{
656
        struct sk_buff *skb;
657
        __u8 *frame;
658
 
659
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
660
 
661
        ASSERT(self != NULL, return;);
662
        ASSERT(self->magic == IRLAN_MAGIC, return;);
663
 
664
        skb = dev_alloc_skb(64);
665
        if (!skb)
666
                return;
667
 
668
        skb_reserve(skb, self->client.max_header_size);
669
        skb_put(skb, 2);
670
 
671
        frame = skb->data;
672
 
673
        /* Build frame */
674
        frame[0] = CMD_OPEN_DATA_CHANNEL;
675
        frame[1] = 0x02; /* Two parameters */
676
 
677
        irlan_insert_string_param(skb, "MEDIA", "802.3");
678
        irlan_insert_string_param(skb, "ACCESS_TYPE", "DIRECT");
679
        /* irlan_insert_string_param(skb, "MODE", "UNRELIABLE"); */
680
 
681
/*      self->use_udata = TRUE; */
682
 
683
        irlan_ctrl_data_request(self, skb);
684
}
685
 
686
void irlan_close_data_channel(struct irlan_cb *self)
687
{
688
        struct sk_buff *skb;
689
        __u8 *frame;
690
 
691
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
692
 
693
        ASSERT(self != NULL, return;);
694
        ASSERT(self->magic == IRLAN_MAGIC, return;);
695
 
696
        /* Check if the TSAP is still there */
697
        if (self->client.tsap_ctrl == NULL)
698
                return;
699
 
700
        skb = dev_alloc_skb(64);
701
        if (!skb)
702
                return;
703
 
704
        skb_reserve(skb, self->client.max_header_size);
705
        skb_put(skb, 2);
706
 
707
        frame = skb->data;
708
 
709
        /* Build frame */
710
        frame[0] = CMD_CLOSE_DATA_CHAN;
711
        frame[1] = 0x01; /* Two parameters */
712
 
713
        irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
714
 
715
        irlan_ctrl_data_request(self, skb);
716
}
717
 
718
/*
719
 * Function irlan_open_unicast_addr (self)
720
 *
721
 *    Make IrLAN provider accept ethernet frames addressed to the unicast
722
 *    address.
723
 *
724
 */
725
void irlan_open_unicast_addr(struct irlan_cb *self)
726
{
727
        struct sk_buff *skb;
728
        __u8 *frame;
729
 
730
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
731
 
732
        ASSERT(self != NULL, return;);
733
        ASSERT(self->magic == IRLAN_MAGIC, return;);
734
 
735
        skb = dev_alloc_skb(128);
736
        if (!skb)
737
                return;
738
 
739
        /* Reserve space for TTP, LMP, and LAP header */
740
        skb_reserve(skb, self->max_header_size);
741
        skb_put(skb, 2);
742
 
743
        frame = skb->data;
744
 
745
        frame[0] = CMD_FILTER_OPERATION;
746
        frame[1] = 0x03;                 /* Three parameters */
747
        irlan_insert_byte_param(skb, "DATA_CHAN" , self->dtsap_sel_data);
748
        irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
749
        irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
750
 
751
        irlan_ctrl_data_request(self, skb);
752
}
753
 
754
/*
755
 * Function irlan_set_broadcast_filter (self, status)
756
 *
757
 *    Make IrLAN provider accept ethernet frames addressed to the broadcast
758
 *    address. Be careful with the use of this one, since there may be a lot
759
 *    of broadcast traffic out there. We can still function without this
760
 *    one but then _we_ have to initiate all communication with other
761
 *    hosts, since ARP request for this host will not be answered.
762
 */
763
void irlan_set_broadcast_filter(struct irlan_cb *self, int status)
764
{
765
        struct sk_buff *skb;
766
        __u8 *frame;
767
 
768
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
769
 
770
        ASSERT(self != NULL, return;);
771
        ASSERT(self->magic == IRLAN_MAGIC, return;);
772
 
773
        skb = dev_alloc_skb(128);
774
        if (!skb)
775
                return;
776
 
777
        /* Reserve space for TTP, LMP, and LAP header */
778
        skb_reserve(skb, self->client.max_header_size);
779
        skb_put(skb, 2);
780
 
781
        frame = skb->data;
782
 
783
        frame[0] = CMD_FILTER_OPERATION;
784
        frame[1] = 0x03;                 /* Three parameters */
785
        irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
786
        irlan_insert_string_param(skb, "FILTER_TYPE", "BROADCAST");
787
        if (status)
788
                irlan_insert_string_param(skb, "FILTER_MODE", "FILTER");
789
        else
790
                irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
791
 
792
        irlan_ctrl_data_request(self, skb);
793
}
794
 
795
/*
796
 * Function irlan_set_multicast_filter (self, status)
797
 *
798
 *    Make IrLAN provider accept ethernet frames addressed to the multicast
799
 *    address.
800
 *
801
 */
802
void irlan_set_multicast_filter(struct irlan_cb *self, int status)
803
{
804
        struct sk_buff *skb;
805
        __u8 *frame;
806
 
807
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
808
 
809
        ASSERT(self != NULL, return;);
810
        ASSERT(self->magic == IRLAN_MAGIC, return;);
811
 
812
        skb = dev_alloc_skb(128);
813
        if (!skb)
814
                return;
815
 
816
        /* Reserve space for TTP, LMP, and LAP header */
817
        skb_reserve(skb, self->client.max_header_size);
818
        skb_put(skb, 2);
819
 
820
        frame = skb->data;
821
 
822
        frame[0] = CMD_FILTER_OPERATION;
823
        frame[1] = 0x03;                 /* Three parameters */
824
        irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
825
        irlan_insert_string_param(skb, "FILTER_TYPE", "MULTICAST");
826
        if (status)
827
                irlan_insert_string_param(skb, "FILTER_MODE", "ALL");
828
        else
829
                irlan_insert_string_param(skb, "FILTER_MODE", "NONE");
830
 
831
        irlan_ctrl_data_request(self, skb);
832
}
833
 
834
/*
835
 * Function irlan_get_unicast_addr (self)
836
 *
837
 *    Retrives the unicast address from the IrLAN provider. This address
838
 *    will be inserted into the devices structure, so the ethernet layer
839
 *    can construct its packets.
840
 *
841
 */
842
void irlan_get_unicast_addr(struct irlan_cb *self)
843
{
844
        struct sk_buff *skb;
845
        __u8 *frame;
846
 
847
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
848
 
849
        ASSERT(self != NULL, return;);
850
        ASSERT(self->magic == IRLAN_MAGIC, return;);
851
 
852
        skb = dev_alloc_skb(128);
853
        if (!skb)
854
                return;
855
 
856
        /* Reserve space for TTP, LMP, and LAP header */
857
        skb_reserve(skb, self->client.max_header_size);
858
        skb_put(skb, 2);
859
 
860
        frame = skb->data;
861
 
862
        frame[0] = CMD_FILTER_OPERATION;
863
        frame[1] = 0x03;                 /* Three parameters */
864
        irlan_insert_byte_param(skb, "DATA_CHAN", self->dtsap_sel_data);
865
        irlan_insert_string_param(skb, "FILTER_TYPE", "DIRECTED");
866
        irlan_insert_string_param(skb, "FILTER_OPERATION", "DYNAMIC");
867
 
868
        irlan_ctrl_data_request(self, skb);
869
}
870
 
871
/*
872
 * Function irlan_get_media_char (self)
873
 *
874
 *
875
 *
876
 */
877
void irlan_get_media_char(struct irlan_cb *self)
878
{
879
        struct sk_buff *skb;
880
        __u8 *frame;
881
 
882
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
883
 
884
        ASSERT(self != NULL, return;);
885
        ASSERT(self->magic == IRLAN_MAGIC, return;);
886
 
887
        skb = dev_alloc_skb(64);
888
        if (!skb)
889
                return;
890
 
891
        /* Reserve space for TTP, LMP, and LAP header */
892
        skb_reserve(skb, self->client.max_header_size);
893
        skb_put(skb, 2);
894
 
895
        frame = skb->data;
896
 
897
        /* Build frame */
898
        frame[0] = CMD_GET_MEDIA_CHAR;
899
        frame[1] = 0x01; /* One parameter */
900
 
901
        irlan_insert_string_param(skb, "MEDIA", "802.3");
902
        irlan_ctrl_data_request(self, skb);
903
}
904
 
905
/*
906
 * Function insert_byte_param (skb, param, value)
907
 *
908
 *    Insert byte parameter into frame
909
 *
910
 */
911
int irlan_insert_byte_param(struct sk_buff *skb, char *param, __u8 value)
912
{
913
        return __irlan_insert_param(skb, param, IRLAN_BYTE, value, 0, NULL, 0);
914
}
915
 
916
int irlan_insert_short_param(struct sk_buff *skb, char *param, __u16 value)
917
{
918
        return __irlan_insert_param(skb, param, IRLAN_SHORT, 0, value, NULL, 0);
919
}
920
 
921
/*
922
 * Function insert_string (skb, param, value)
923
 *
924
 *    Insert string parameter into frame
925
 *
926
 */
927
int irlan_insert_string_param(struct sk_buff *skb, char *param, char *string)
928
{
929
        int string_len = strlen(string);
930
 
931
        return __irlan_insert_param(skb, param, IRLAN_ARRAY, 0, 0, string,
932
                                    string_len);
933
}
934
 
935
/*
936
 * Function insert_array_param(skb, param, value, len_value)
937
 *
938
 *    Insert array parameter into frame
939
 *
940
 */
941
int irlan_insert_array_param(struct sk_buff *skb, char *name, __u8 *array,
942
                             __u16 array_len)
943
{
944
        return __irlan_insert_param(skb, name, IRLAN_ARRAY, 0, 0, array,
945
                                    array_len);
946
}
947
 
948
/*
949
 * Function insert_param (skb, param, value, byte)
950
 *
951
 *    Insert parameter at end of buffer, structure of a parameter is:
952
 *
953
 *    -----------------------------------------------------------------------
954
 *    | Name Length[1] | Param Name[1..255] | Val Length[2] | Value[0..1016]|
955
 *    -----------------------------------------------------------------------
956
 */
957
static int __irlan_insert_param(struct sk_buff *skb, char *param, int type,
958
                                __u8 value_byte, __u16 value_short,
959
                                __u8 *value_array, __u16 value_len)
960
{
961
        __u8 *frame;
962
        __u8 param_len;
963
        __u16 tmp_le; /* Temporary value in little endian format */
964
        int n=0;
965
 
966
        if (skb == NULL) {
967
                IRDA_DEBUG(2, "%s(), Got NULL skb\n", __FUNCTION__);
968
                return 0;
969
        }
970
 
971
        param_len = strlen(param);
972
        switch (type) {
973
        case IRLAN_BYTE:
974
                value_len = 1;
975
                break;
976
        case IRLAN_SHORT:
977
                value_len = 2;
978
                break;
979
        case IRLAN_ARRAY:
980
                ASSERT(value_array != NULL, return 0;);
981
                ASSERT(value_len > 0, return 0;);
982
                break;
983
        default:
984
                IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __FUNCTION__);
985
                return 0;
986
                break;
987
        }
988
 
989
        /* Insert at end of sk-buffer */
990
        frame = skb->tail;
991
 
992
        /* Make space for data */
993
        if (skb_tailroom(skb) < (param_len+value_len+3)) {
994
                IRDA_DEBUG(2, "%s(), No more space at end of skb\n", __FUNCTION__);
995
                return 0;
996
        }
997
        skb_put(skb, param_len+value_len+3);
998
 
999
        /* Insert parameter length */
1000
        frame[n++] = param_len;
1001
 
1002
        /* Insert parameter */
1003
        memcpy(frame+n, param, param_len); n += param_len;
1004
 
1005
        /* Insert value length (2 byte little endian format, LSB first) */
1006
        tmp_le = cpu_to_le16(value_len);
1007
        memcpy(frame+n, &tmp_le, 2); n += 2; /* To avoid alignment problems */
1008
 
1009
        /* Insert value */
1010
        switch (type) {
1011
        case IRLAN_BYTE:
1012
                frame[n++] = value_byte;
1013
                break;
1014
        case IRLAN_SHORT:
1015
                tmp_le = cpu_to_le16(value_short);
1016
                memcpy(frame+n, &tmp_le, 2); n += 2;
1017
                break;
1018
        case IRLAN_ARRAY:
1019
                memcpy(frame+n, value_array, value_len); n+=value_len;
1020
                break;
1021
        default:
1022
                break;
1023
        }
1024
        ASSERT(n == (param_len+value_len+3), return 0;);
1025
 
1026
        return param_len+value_len+3;
1027
}
1028
 
1029
/*
1030
 * Function irlan_extract_param (buf, name, value, len)
1031
 *
1032
 *    Extracts a single parameter name/value pair from buffer and updates
1033
 *    the buffer pointer to point to the next name/value pair.
1034
 */
1035
int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
1036
{
1037
        __u8 name_len;
1038
        __u16 val_len;
1039
        int n=0;
1040
 
1041
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
1042
 
1043
        /* get length of parameter name (1 byte) */
1044
        name_len = buf[n++];
1045
 
1046
        if (name_len > 254) {
1047
                IRDA_DEBUG(2, "%s(), name_len > 254\n", __FUNCTION__);
1048
                return -RSP_INVALID_COMMAND_FORMAT;
1049
        }
1050
 
1051
        /* get parameter name */
1052
        memcpy(name, buf+n, name_len);
1053
        name[name_len] = '\0';
1054
        n+=name_len;
1055
 
1056
        /*
1057
         *  Get length of parameter value (2 bytes in little endian
1058
         *  format)
1059
         */
1060
        memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
1061
        le16_to_cpus(&val_len); n+=2;
1062
 
1063
        if (val_len > 1016) {
1064
                IRDA_DEBUG(2, "%s(), parameter length to long\n", __FUNCTION__);
1065
                return -RSP_INVALID_COMMAND_FORMAT;
1066
        }
1067
        *len = val_len;
1068
 
1069
        /* get parameter value */
1070
        memcpy(value, buf+n, val_len);
1071
        value[val_len] = '\0';
1072
        n+=val_len;
1073
 
1074
        IRDA_DEBUG(4, "Parameter: %s ", name);
1075
        IRDA_DEBUG(4, "Value: %s\n", value);
1076
 
1077
        return n;
1078
}
1079
 
1080
#ifdef CONFIG_PROC_FS
1081
/*
1082
 * Function irlan_client_proc_read (buf, start, offset, len, unused)
1083
 *
1084
 *    Give some info to the /proc file system
1085
 */
1086
static int irlan_proc_read(char *buf, char **start, off_t offset, int len)
1087
{
1088
        struct irlan_cb *self;
1089
        unsigned long flags;
1090
        ASSERT(irlan != NULL, return 0;);
1091
 
1092
        save_flags(flags);
1093
        cli();
1094
 
1095
        len = 0;
1096
 
1097
        len += sprintf(buf+len, "IrLAN instances:\n");
1098
 
1099
        self = (struct irlan_cb *) hashbin_get_first(irlan);
1100
        while (self != NULL) {
1101
                ASSERT(self->magic == IRLAN_MAGIC, break;);
1102
 
1103
                len += sprintf(buf+len, "ifname: %s,\n",
1104
                               self->dev.name);
1105
                len += sprintf(buf+len, "client state: %s, ",
1106
                               irlan_state[ self->client.state]);
1107
                len += sprintf(buf+len, "provider state: %s,\n",
1108
                               irlan_state[ self->provider.state]);
1109
                len += sprintf(buf+len, "saddr: %#08x, ",
1110
                               self->saddr);
1111
                len += sprintf(buf+len, "daddr: %#08x\n",
1112
                               self->daddr);
1113
                len += sprintf(buf+len, "version: %d.%d,\n",
1114
                               self->version[1], self->version[0]);
1115
                len += sprintf(buf+len, "access type: %s\n",
1116
                               irlan_access[self->client.access_type]);
1117
                len += sprintf(buf+len, "media: %s\n",
1118
                               irlan_media[self->media]);
1119
 
1120
                len += sprintf(buf+len, "local filter:\n");
1121
                len += sprintf(buf+len, "remote filter: ");
1122
                len += irlan_print_filter(self->client.filter_type,
1123
                                          buf+len);
1124
 
1125
                len += sprintf(buf+len, "tx busy: %s\n",
1126
                               netif_queue_stopped(&self->dev) ? "TRUE" : "FALSE");
1127
 
1128
                len += sprintf(buf+len, "\n");
1129
 
1130
                self = (struct irlan_cb *) hashbin_get_next(irlan);
1131
        }
1132
        restore_flags(flags);
1133
 
1134
        return len;
1135
}
1136
#endif
1137
 
1138
/*
1139
 * Function print_ret_code (code)
1140
 *
1141
 *    Print return code of request to peer IrLAN layer.
1142
 *
1143
 */
1144
void print_ret_code(__u8 code)
1145
{
1146
        switch(code) {
1147
        case 0:
1148
                printk(KERN_INFO "Success\n");
1149
                break;
1150
        case 1:
1151
                WARNING("IrLAN: Insufficient resources\n");
1152
                break;
1153
        case 2:
1154
                WARNING("IrLAN: Invalid command format\n");
1155
                break;
1156
        case 3:
1157
                WARNING("IrLAN: Command not supported\n");
1158
                break;
1159
        case 4:
1160
                WARNING("IrLAN: Parameter not supported\n");
1161
                break;
1162
        case 5:
1163
                WARNING("IrLAN: Value not supported\n");
1164
                break;
1165
        case 6:
1166
                WARNING("IrLAN: Not open\n");
1167
                break;
1168
        case 7:
1169
                WARNING("IrLAN: Authentication required\n");
1170
                break;
1171
        case 8:
1172
                WARNING("IrLAN: Invalid password\n");
1173
                break;
1174
        case 9:
1175
                WARNING("IrLAN: Protocol error\n");
1176
                break;
1177
        case 255:
1178
                WARNING("IrLAN: Asynchronous status\n");
1179
                break;
1180
        }
1181
}
1182
 
1183
void irlan_mod_inc_use_count(void)
1184
{
1185
#ifdef MODULE
1186
        MOD_INC_USE_COUNT;
1187
#endif
1188
}
1189
 
1190
void irlan_mod_dec_use_count(void)
1191
{
1192
#ifdef MODULE
1193
        MOD_DEC_USE_COUNT;
1194
#endif
1195
}
1196
 
1197
#ifdef MODULE
1198
 
1199
MODULE_AUTHOR("Dag Brattli <dagb@cs.uit.no>");
1200
MODULE_DESCRIPTION("The Linux IrDA LAN protocol");
1201
MODULE_LICENSE("GPL");
1202
 
1203
MODULE_PARM(eth, "i");
1204
MODULE_PARM_DESC(eth, "Name devices ethX (0) or irlanX (1)");
1205
MODULE_PARM(access, "i");
1206
MODULE_PARM_DESC(access, "Access type DIRECT=1, PEER=2, HOSTED=3");
1207
 
1208
/*
1209
 * Function init_module (void)
1210
 *
1211
 *    Initialize the IrLAN module, this function is called by the
1212
 *    modprobe(1) program.
1213
 */
1214
int init_module(void)
1215
{
1216
        return irlan_init();
1217
}
1218
 
1219
/*
1220
 * Function cleanup_module (void)
1221
 *
1222
 *    Remove the IrLAN module, this function is called by the rmmod(1)
1223
 *    program
1224
 */
1225
void cleanup_module(void)
1226
{
1227
        /* Free some memory */
1228
        irlan_cleanup();
1229
}
1230
 
1231
#endif /* MODULE */
1232
 

powered by: WebSVN 2.1.0

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