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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*********************************************************************
2
 *
3
 * Filename:      iriap.c
4
 * Version:       0.8
5
 * Description:   Information Access Protocol (IAP)
6
 * Status:        Experimental.
7
 * Author:        Dag Brattli <dagb@cs.uit.no>
8
 * Created at:    Thu Aug 21 00:02:07 1997
9
 * Modified at:   Sat Dec 25 16:42:42 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/types.h>
29
#include <linux/skbuff.h>
30
#include <linux/string.h>
31
#include <linux/init.h>
32
 
33
#include <asm/byteorder.h>
34
#include <asm/unaligned.h>
35
 
36
#include <net/irda/irda.h>
37
#include <net/irda/irttp.h>
38
#include <net/irda/irmod.h>
39
#include <net/irda/irlmp.h>
40
#include <net/irda/irias_object.h>
41
#include <net/irda/iriap_event.h>
42
#include <net/irda/iriap.h>
43
 
44
#ifdef CONFIG_IRDA_DEBUG
45
/* FIXME: This one should go in irlmp.c */
46
static const char *ias_charset_types[] = {
47
        "CS_ASCII",
48
        "CS_ISO_8859_1",
49
        "CS_ISO_8859_2",
50
        "CS_ISO_8859_3",
51
        "CS_ISO_8859_4",
52
        "CS_ISO_8859_5",
53
        "CS_ISO_8859_6",
54
        "CS_ISO_8859_7",
55
        "CS_ISO_8859_8",
56
        "CS_ISO_8859_9",
57
        "CS_UNICODE"
58
};
59
#endif  /* CONFIG_IRDA_DEBUG */
60
 
61
static hashbin_t *iriap = NULL;
62
static __u32 service_handle;
63
 
64
extern char *lmp_reasons[];
65
 
66
static void __iriap_close(struct iriap_cb *self);
67
static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode);
68
static void iriap_disconnect_indication(void *instance, void *sap,
69
                                        LM_REASON reason, struct sk_buff *skb);
70
static void iriap_connect_indication(void *instance, void *sap,
71
                                     struct qos_info *qos, __u32 max_sdu_size,
72
                                     __u8 max_header_size,
73
                                     struct sk_buff *skb);
74
static void iriap_connect_confirm(void *instance, void *sap,
75
                                  struct qos_info *qos,
76
                                  __u32 max_sdu_size, __u8 max_header_size,
77
                                  struct sk_buff *skb);
78
static int iriap_data_indication(void *instance, void *sap,
79
                                 struct sk_buff *skb);
80
 
81
/*
82
 * Function iriap_init (void)
83
 *
84
 *    Initializes the IrIAP layer, called by the module initialization code
85
 *    in irmod.c
86
 */
87
int __init iriap_init(void)
88
{
89
        struct ias_object *obj;
90
        struct iriap_cb *server;
91
        __u8 oct_seq[6];
92
        __u16 hints;
93
 
94
        /* Allocate master array */
95
        iriap = hashbin_new(HB_LOCAL);
96
        if (!iriap)
97
                return -ENOMEM;
98
 
99
        objects = hashbin_new(HB_LOCAL);
100
        if (!objects) {
101
                WARNING("%s(), Can't allocate objects hashbin!\n", __FUNCTION__);
102
                return -ENOMEM;
103
        }
104
 
105
        /*
106
         *  Register some default services for IrLMP
107
         */
108
        hints  = irlmp_service_to_hint(S_COMPUTER);
109
        service_handle = irlmp_register_service(hints);
110
 
111
        /* Register the Device object with LM-IAS */
112
        obj = irias_new_object("Device", IAS_DEVICE_ID);
113
        irias_add_string_attrib(obj, "DeviceName", "Linux", IAS_KERNEL_ATTR);
114
 
115
        oct_seq[0] = 0x01;  /* Version 1 */
116
        oct_seq[1] = 0x00;  /* IAS support bits */
117
        oct_seq[2] = 0x00;  /* LM-MUX support bits */
118
#ifdef CONFIG_IRDA_ULTRA
119
        oct_seq[2] |= 0x04; /* Connectionless Data support */
120
#endif
121
        irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3,
122
                                IAS_KERNEL_ATTR);
123
        irias_insert_object(obj);
124
 
125
        /*
126
         *  Register server support with IrLMP so we can accept incoming
127
         *  connections
128
         */
129
        server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
130
        if (!server) {
131
                IRDA_DEBUG(0, "%s(), unable to open server\n", __FUNCTION__);
132
                return -1;
133
        }
134
        iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
135
 
136
        return 0;
137
}
138
 
139
/*
140
 * Function iriap_cleanup (void)
141
 *
142
 *    Initializes the IrIAP layer, called by the module cleanup code in
143
 *    irmod.c
144
 */
145
void iriap_cleanup(void)
146
{
147
        irlmp_unregister_service(service_handle);
148
 
149
        hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
150
        hashbin_delete(objects, (FREE_FUNC) __irias_delete_object);
151
}
152
 
153
/*
154
 * Function iriap_open (void)
155
 *
156
 *    Opens an instance of the IrIAP layer, and registers with IrLMP
157
 */
158
struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
159
                            CONFIRM_CALLBACK callback)
160
{
161
        struct iriap_cb *self;
162
 
163
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
164
 
165
        self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
166
        if (!self) {
167
                WARNING("%s(), Unable to kmalloc!\n", __FUNCTION__);
168
                return NULL;
169
        }
170
 
171
        /*
172
         *  Initialize instance
173
         */
174
        memset(self, 0, sizeof(struct iriap_cb));
175
 
176
        self->magic = IAS_MAGIC;
177
        self->mode = mode;
178
        if (mode == IAS_CLIENT)
179
                iriap_register_lsap(self, slsap_sel, mode);
180
 
181
        self->confirm = callback;
182
        self->priv = priv;
183
 
184
        init_timer(&self->watchdog_timer);
185
 
186
        hashbin_insert(iriap, (irda_queue_t *) self, (int) self, NULL);
187
 
188
        /* Initialize state machines */
189
        iriap_next_client_state(self, S_DISCONNECT);
190
        iriap_next_call_state(self, S_MAKE_CALL);
191
        iriap_next_server_state(self, R_DISCONNECT);
192
        iriap_next_r_connect_state(self, R_WAITING);
193
 
194
        return self;
195
}
196
 
197
/*
198
 * Function __iriap_close (self)
199
 *
200
 *    Removes (deallocates) the IrIAP instance
201
 *
202
 */
203
static void __iriap_close(struct iriap_cb *self)
204
{
205
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
206
 
207
        ASSERT(self != NULL, return;);
208
        ASSERT(self->magic == IAS_MAGIC, return;);
209
 
210
        del_timer(&self->watchdog_timer);
211
 
212
        if (self->skb)
213
                dev_kfree_skb(self->skb);
214
 
215
        self->magic = 0;
216
 
217
        kfree(self);
218
}
219
 
220
/*
221
 * Function iriap_close (void)
222
 *
223
 *    Closes IrIAP and deregisters with IrLMP
224
 */
225
void iriap_close(struct iriap_cb *self)
226
{
227
        struct iriap_cb *entry;
228
 
229
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
230
 
231
        ASSERT(self != NULL, return;);
232
        ASSERT(self->magic == IAS_MAGIC, return;);
233
 
234
        if (self->lsap) {
235
                irlmp_close_lsap(self->lsap);
236
                self->lsap = NULL;
237
        }
238
 
239
        entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL);
240
        ASSERT(entry == self, return;);
241
 
242
        __iriap_close(self);
243
}
244
 
245
static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
246
{
247
        notify_t notify;
248
 
249
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
250
 
251
        irda_notify_init(&notify);
252
        notify.connect_confirm       = iriap_connect_confirm;
253
        notify.connect_indication    = iriap_connect_indication;
254
        notify.disconnect_indication = iriap_disconnect_indication;
255
        notify.data_indication       = iriap_data_indication;
256
        notify.instance = self;
257
        if (mode == IAS_CLIENT)
258
                strcpy(notify.name, "IrIAS cli");
259
        else
260
                strcpy(notify.name, "IrIAS srv");
261
 
262
        self->lsap = irlmp_open_lsap(slsap_sel, &notify, 0);
263
        if (self->lsap == NULL) {
264
                ERROR("%s(), Unable to allocated LSAP!\n", __FUNCTION__);
265
                return -1;
266
        }
267
        self->slsap_sel = self->lsap->slsap_sel;
268
 
269
        return 0;
270
}
271
 
272
/*
273
 * Function iriap_disconnect_indication (handle, reason)
274
 *
275
 *    Got disconnect, so clean up everything assosiated with this connection
276
 *
277
 */
278
static void iriap_disconnect_indication(void *instance, void *sap,
279
                                        LM_REASON reason,
280
                                        struct sk_buff *userdata)
281
{
282
        struct iriap_cb *self;
283
 
284
        IRDA_DEBUG(4, "%s(), reason=%s\n", __FUNCTION__, lmp_reasons[reason]);
285
 
286
        self = (struct iriap_cb *) instance;
287
 
288
        ASSERT(self != NULL, return;);
289
        ASSERT(self->magic == IAS_MAGIC, return;);
290
 
291
        ASSERT(iriap != NULL, return;);
292
 
293
        del_timer(&self->watchdog_timer);
294
 
295
        if (self->mode == IAS_CLIENT) {
296
                IRDA_DEBUG(4, "%s(), disconnect as client\n", __FUNCTION__);
297
 
298
 
299
                iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
300
                                      NULL);
301
                /*
302
                 * Inform service user that the request failed by sending
303
                 * it a NULL value. Warning, the client might close us, so
304
                 * remember no to use self anymore after calling confirm
305
                 */
306
                if (self->confirm)
307
                        self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
308
        } else {
309
                IRDA_DEBUG(4, "%s(), disconnect as server\n", __FUNCTION__);
310
                iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
311
                                      NULL);
312
                iriap_close(self);
313
        }
314
 
315
        if (userdata)
316
                dev_kfree_skb(userdata);
317
}
318
 
319
/*
320
 * Function iriap_disconnect_request (handle)
321
 *
322
 *
323
 *
324
 */
325
void iriap_disconnect_request(struct iriap_cb *self)
326
{
327
        struct sk_buff *skb;
328
 
329
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
330
 
331
        ASSERT(self != NULL, return;);
332
        ASSERT(self->magic == IAS_MAGIC, return;);
333
 
334
        skb = dev_alloc_skb(64);
335
        if (skb == NULL) {
336
                IRDA_DEBUG(0, "%s(), Could not allocate an sk_buff of length %d\n",
337
                        __FUNCTION__, 64);
338
                return;
339
        }
340
 
341
        /*
342
         *  Reserve space for MUX control and LAP header
343
         */
344
        skb_reserve(skb, LMP_MAX_HEADER);
345
 
346
        irlmp_disconnect_request(self->lsap, skb);
347
}
348
 
349
void iriap_getinfobasedetails_request(void)
350
{
351
        IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
352
}
353
 
354
void iriap_getinfobasedetails_confirm(void)
355
{
356
        IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
357
}
358
 
359
void iriap_getobjects_request(void)
360
{
361
        IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
362
}
363
 
364
void iriap_getobjects_confirm(void)
365
{
366
        IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
367
}
368
 
369
void iriap_getvalue(void)
370
{
371
        IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
372
}
373
 
374
/*
375
 * Function iriap_getvaluebyclass (addr, name, attr)
376
 *
377
 *    Retreive all values from attribute in all objects with given class
378
 *    name
379
 */
380
int iriap_getvaluebyclass_request(struct iriap_cb *self,
381
                                  __u32 saddr, __u32 daddr,
382
                                  char *name, char *attr)
383
{
384
        struct sk_buff *skb;
385
        int name_len, attr_len, skb_len;
386
        __u8 *frame;
387
 
388
        ASSERT(self != NULL, return -1;);
389
        ASSERT(self->magic == IAS_MAGIC, return -1;);
390
 
391
        /* Client must supply the destination device address */
392
        if (!daddr)
393
                return -1;
394
 
395
        self->daddr = daddr;
396
        self->saddr = saddr;
397
 
398
        /*
399
         *  Save operation, so we know what the later indication is about
400
         */
401
        self->operation = GET_VALUE_BY_CLASS;
402
 
403
        /* Give ourselves 10 secs to finish this operation */
404
        iriap_start_watchdog_timer(self, 10*HZ);
405
 
406
        name_len = strlen(name);        /* Up to IAS_MAX_CLASSNAME = 60 */
407
        attr_len = strlen(attr);        /* Up to IAS_MAX_ATTRIBNAME = 60 */
408
 
409
        skb_len = self->max_header_size+2+name_len+1+attr_len+4;
410
        skb = dev_alloc_skb(skb_len);
411
        if (!skb)
412
                return -ENOMEM;
413
 
414
        /* Reserve space for MUX and LAP header */
415
        skb_reserve(skb, self->max_header_size);
416
        skb_put(skb, 3+name_len+attr_len);
417
        frame = skb->data;
418
 
419
        /* Build frame */
420
        frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
421
        frame[1] = name_len;                       /* Insert length of name */
422
        memcpy(frame+2, name, name_len);           /* Insert name */
423
        frame[2+name_len] = attr_len;              /* Insert length of attr */
424
        memcpy(frame+3+name_len, attr, attr_len);  /* Insert attr */
425
 
426
        iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
427
 
428
        return 0;
429
}
430
 
431
/*
432
 * Function iriap_getvaluebyclass_confirm (self, skb)
433
 *
434
 *    Got result from GetValueByClass command. Parse it and return result
435
 *    to service user.
436
 *
437
 */
438
void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
439
{
440
        struct ias_value *value;
441
        int charset;
442
        __u32 value_len;
443
        __u32 tmp_cpu32;
444
        __u16 obj_id;
445
        __u16 len;
446
        __u8  type;
447
        __u8 *fp;
448
        int n;
449
 
450
        ASSERT(self != NULL, return;);
451
        ASSERT(self->magic == IAS_MAGIC, return;);
452
        ASSERT(skb != NULL, return;);
453
 
454
        /* Initialize variables */
455
        fp = skb->data;
456
        n = 2;
457
 
458
        /* Get length, MSB first */
459
        len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
460
 
461
        IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len);
462
 
463
        /* Get object ID, MSB first */
464
        obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
465
 
466
        type = fp[n++];
467
        IRDA_DEBUG(4, "%s(), Value type = %d\n", __FUNCTION__, type);
468
 
469
        switch (type) {
470
        case IAS_INTEGER:
471
                memcpy(&tmp_cpu32, fp+n, 4); n += 4;
472
                be32_to_cpus(&tmp_cpu32);
473
                value = irias_new_integer_value(tmp_cpu32);
474
 
475
                /*  Legal values restricted to 0x01-0x6f, page 15 irttp */
476
                IRDA_DEBUG(4, "%s(), lsap=%d\n", __FUNCTION__, value->t.integer);
477
                break;
478
        case IAS_STRING:
479
                charset = fp[n++];
480
 
481
                switch (charset) {
482
                case CS_ASCII:
483
                        break;
484
/*              case CS_ISO_8859_1: */
485
/*              case CS_ISO_8859_2: */
486
/*              case CS_ISO_8859_3: */
487
/*              case CS_ISO_8859_4: */
488
/*              case CS_ISO_8859_5: */
489
/*              case CS_ISO_8859_6: */
490
/*              case CS_ISO_8859_7: */
491
/*              case CS_ISO_8859_8: */
492
/*              case CS_ISO_8859_9: */
493
/*              case CS_UNICODE: */
494
                default:
495
                        IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
496
                                   __FUNCTION__, ias_charset_types[charset]);
497
 
498
                        /* Aborting, close connection! */
499
                        iriap_disconnect_request(self);
500
                        dev_kfree_skb(skb);
501
                        return;
502
                        /* break; */
503
                }
504
                value_len = fp[n++];
505
                IRDA_DEBUG(4, "%s(), strlen=%d\n", __FUNCTION__, value_len);
506
 
507
                /* Make sure the string is null-terminated */
508
                fp[n+value_len] = 0x00;
509
                IRDA_DEBUG(4, "Got string %s\n", fp+n);
510
 
511
                /* Will truncate to IAS_MAX_STRING bytes */
512
                value = irias_new_string_value(fp+n);
513
                break;
514
        case IAS_OCT_SEQ:
515
                value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
516
                n += 2;
517
 
518
                /* Will truncate to IAS_MAX_OCTET_STRING bytes */
519
                value = irias_new_octseq_value(fp+n, value_len);
520
                break;
521
        default:
522
                value = irias_new_missing_value();
523
                break;
524
        }
525
 
526
        /* Finished, close connection! */
527
        iriap_disconnect_request(self);
528
 
529
        /* Warning, the client might close us, so remember no to use self
530
         * anymore after calling confirm
531
         */
532
        if (self->confirm)
533
                self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
534
        else {
535
                IRDA_DEBUG(0, "%s(), missing handler!\n", __FUNCTION__);
536
                irias_delete_value(value);
537
        }
538
        dev_kfree_skb(skb);
539
}
540
 
541
/*
542
 * Function iriap_getvaluebyclass_response ()
543
 *
544
 *    Send answer back to remote LM-IAS
545
 *
546
 */
547
void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
548
                                    __u8 ret_code, struct ias_value *value)
549
{
550
        struct sk_buff *skb;
551
        int n;
552
        __u32 tmp_be32, tmp_be16;
553
        __u8 *fp;
554
 
555
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
556
 
557
        ASSERT(self != NULL, return;);
558
        ASSERT(self->magic == IAS_MAGIC, return;);
559
        ASSERT(value != NULL, return;);
560
        ASSERT(value->len <= 1024, return;);
561
 
562
        /* Initialize variables */
563
        n = 0;
564
 
565
        /*
566
         *  We must adjust the size of the response after the length of the
567
         *  value. We add 32 bytes because of the 6 bytes for the frame and
568
         *  max 5 bytes for the value coding.
569
         */
570
        skb = dev_alloc_skb(value->len + self->max_header_size + 32);
571
        if (!skb)
572
                return;
573
 
574
        /* Reserve space for MUX and LAP header */
575
        skb_reserve(skb, self->max_header_size);
576
        skb_put(skb, 6);
577
 
578
        fp = skb->data;
579
 
580
        /* Build frame */
581
        fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
582
        fp[n++] = ret_code;
583
 
584
        /* Insert list length (MSB first) */
585
        tmp_be16 = __constant_htons(0x0001);
586
        memcpy(fp+n, &tmp_be16, 2);  n += 2;
587
 
588
        /* Insert object identifier ( MSB first) */
589
        tmp_be16 = cpu_to_be16(obj_id);
590
        memcpy(fp+n, &tmp_be16, 2); n += 2;
591
 
592
        switch (value->type) {
593
        case IAS_STRING:
594
                skb_put(skb, 3 + value->len);
595
                fp[n++] = value->type;
596
                fp[n++] = 0; /* ASCII */
597
                fp[n++] = (__u8) value->len;
598
                memcpy(fp+n, value->t.string, value->len); n+=value->len;
599
                break;
600
        case IAS_INTEGER:
601
                skb_put(skb, 5);
602
                fp[n++] = value->type;
603
 
604
                tmp_be32 = cpu_to_be32(value->t.integer);
605
                memcpy(fp+n, &tmp_be32, 4); n += 4;
606
                break;
607
        case IAS_OCT_SEQ:
608
                skb_put(skb, 3 + value->len);
609
                fp[n++] = value->type;
610
 
611
                tmp_be16 = cpu_to_be16(value->len);
612
                memcpy(fp+n, &tmp_be16, 2); n += 2;
613
                memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
614
                break;
615
        case IAS_MISSING:
616
                IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __FUNCTION__);
617
                skb_put(skb, 1);
618
                fp[n++] = value->type;
619
                break;
620
        default:
621
                IRDA_DEBUG(0, "%s(), type not implemented!\n", __FUNCTION__);
622
                break;
623
        }
624
        iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
625
}
626
 
627
/*
628
 * Function iriap_getvaluebyclass_indication (self, skb)
629
 *
630
 *    getvaluebyclass is requested from peer LM-IAS
631
 *
632
 */
633
void iriap_getvaluebyclass_indication(struct iriap_cb *self,
634
                                      struct sk_buff *skb)
635
{
636
        struct ias_object *obj;
637
        struct ias_attrib *attrib;
638
        int name_len;
639
        int attr_len;
640
        char name[IAS_MAX_CLASSNAME + 1];       /* 60 bytes */
641
        char attr[IAS_MAX_ATTRIBNAME + 1];      /* 60 bytes */
642
        __u8 *fp;
643
        int n;
644
 
645
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
646
 
647
        ASSERT(self != NULL, return;);
648
        ASSERT(self->magic == IAS_MAGIC, return;);
649
        ASSERT(skb != NULL, return;);
650
 
651
        fp = skb->data;
652
        n = 1;
653
 
654
        name_len = fp[n++];
655
        memcpy(name, fp+n, name_len); n+=name_len;
656
        name[name_len] = '\0';
657
 
658
        attr_len = fp[n++];
659
        memcpy(attr, fp+n, attr_len); n+=attr_len;
660
        attr[attr_len] = '\0';
661
 
662
        /* We do not need the buffer anymore */
663
        dev_kfree_skb(skb);
664
 
665
        IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
666
        obj = irias_find_object(name);
667
 
668
        if (obj == NULL) {
669
                IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
670
                iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
671
                                               &missing);
672
                return;
673
        }
674
        IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
675
 
676
        attrib = irias_find_attrib(obj, attr);
677
        if (attrib == NULL) {
678
                IRDA_DEBUG(2, "LM-IAS: Attribute %s not found\n", attr);
679
                iriap_getvaluebyclass_response(self, obj->id,
680
                                               IAS_ATTRIB_UNKNOWN, &missing);
681
                return;
682
        }
683
 
684
        /* We have a match; send the value.  */
685
        iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
686
                                       attrib->value);
687
 
688
        return;
689
}
690
 
691
/*
692
 * Function iriap_send_ack (void)
693
 *
694
 *    Currently not used
695
 *
696
 */
697
void iriap_send_ack(struct iriap_cb *self)
698
{
699
        struct sk_buff *skb;
700
        __u8 *frame;
701
 
702
        IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
703
 
704
        ASSERT(self != NULL, return;);
705
        ASSERT(self->magic == IAS_MAGIC, return;);
706
 
707
        skb = dev_alloc_skb(64);
708
        if (!skb)
709
                return;
710
 
711
        /* Reserve space for MUX and LAP header */
712
        skb_reserve(skb, self->max_header_size);
713
        skb_put(skb, 1);
714
        frame = skb->data;
715
 
716
        /* Build frame */
717
        frame[0] = IAP_LST | IAP_ACK | self->operation;
718
 
719
        irlmp_data_request(self->lsap, skb);
720
}
721
 
722
void iriap_connect_request(struct iriap_cb *self)
723
{
724
        int ret;
725
 
726
        ASSERT(self != NULL, return;);
727
        ASSERT(self->magic == IAS_MAGIC, return;);
728
 
729
        ret = irlmp_connect_request(self->lsap, LSAP_IAS,
730
                                    self->saddr, self->daddr,
731
                                    NULL, NULL);
732
        if (ret < 0) {
733
                IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
734
                self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
735
        }
736
}
737
 
738
/*
739
 * Function iriap_connect_confirm (handle, skb)
740
 *
741
 *    LSAP connection confirmed!
742
 *
743
 */
744
static void iriap_connect_confirm(void *instance, void *sap,
745
                                  struct qos_info *qos, __u32 max_seg_size,
746
                                  __u8 max_header_size,
747
                                  struct sk_buff *userdata)
748
{
749
        struct iriap_cb *self;
750
 
751
        self = (struct iriap_cb *) instance;
752
 
753
        ASSERT(self != NULL, return;);
754
        ASSERT(self->magic == IAS_MAGIC, return;);
755
        ASSERT(userdata != NULL, return;);
756
 
757
        self->max_data_size = max_seg_size;
758
        self->max_header_size = max_header_size;
759
 
760
        del_timer(&self->watchdog_timer);
761
 
762
        iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
763
}
764
 
765
/*
766
 * Function iriap_connect_indication ( handle, skb)
767
 *
768
 *    Remote LM-IAS is requesting connection
769
 *
770
 */
771
static void iriap_connect_indication(void *instance, void *sap,
772
                                     struct qos_info *qos, __u32 max_seg_size,
773
                                     __u8 max_header_size,
774
                                     struct sk_buff *userdata)
775
{
776
        struct iriap_cb *self, *new;
777
 
778
        IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
779
 
780
        self = (struct iriap_cb *) instance;
781
 
782
        ASSERT(self != NULL, return;);
783
        ASSERT(self->magic == IAS_MAGIC, return;);
784
 
785
        /* Start new server */
786
        new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
787
        if (!new) {
788
                IRDA_DEBUG(0, "%s(), open failed\n", __FUNCTION__);
789
                dev_kfree_skb(userdata);
790
                return;
791
        }
792
 
793
        /* Now attach up the new "socket" */
794
        new->lsap = irlmp_dup(self->lsap, new);
795
        if (!new->lsap) {
796
                IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
797
                return;
798
        }
799
 
800
        new->max_data_size = max_seg_size;
801
        new->max_header_size = max_header_size;
802
 
803
        /* Clean up the original one to keep it in listen state */
804
        irlmp_listen(self->lsap);
805
 
806
        iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
807
}
808
 
809
/*
810
 * Function iriap_data_indication (handle, skb)
811
 *
812
 *    Receives data from connection identified by handle from IrLMP
813
 *
814
 */
815
static int iriap_data_indication(void *instance, void *sap,
816
                                 struct sk_buff *skb)
817
{
818
        struct iriap_cb *self;
819
        __u8  *frame;
820
        __u8  opcode;
821
 
822
        IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
823
 
824
        self = (struct iriap_cb *) instance;
825
 
826
        ASSERT(self != NULL, return 0;);
827
        ASSERT(self->magic == IAS_MAGIC, return 0;);
828
 
829
        ASSERT(skb != NULL, return 0;);
830
 
831
        frame = skb->data;
832
 
833
        if (self->mode == IAS_SERVER) {
834
                /* Call server */
835
                IRDA_DEBUG(4, "%s(), Calling server!\n", __FUNCTION__);
836
                iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
837
 
838
                return 0;
839
        }
840
        opcode = frame[0];
841
        if (~opcode & IAP_LST) {
842
                WARNING("%s(), IrIAS multiframe commands or "
843
                        "results is not implemented yet!\n", __FUNCTION__);
844
                dev_kfree_skb(skb);
845
                return 0;
846
        }
847
 
848
        /* Check for ack frames since they don't contain any data */
849
        if (opcode & IAP_ACK) {
850
                IRDA_DEBUG(0, "%s() Got ack frame!\n", __FUNCTION__);
851
                dev_kfree_skb(skb);
852
                return 0;
853
        }
854
 
855
        opcode &= ~IAP_LST; /* Mask away LST bit */
856
 
857
        switch (opcode) {
858
        case GET_INFO_BASE:
859
                IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
860
                dev_kfree_skb(skb);
861
                break;
862
        case GET_VALUE_BY_CLASS:
863
                iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
864
 
865
                switch (frame[1]) {
866
                case IAS_SUCCESS:
867
                        iriap_getvaluebyclass_confirm(self, skb);
868
                        break;
869
                case IAS_CLASS_UNKNOWN:
870
                        IRDA_DEBUG(1, "%s(), No such class!\n", __FUNCTION__);
871
                        /* Finished, close connection! */
872
                        iriap_disconnect_request(self);
873
 
874
                        /*
875
                         * Warning, the client might close us, so remember
876
                         * no to use self anymore after calling confirm
877
                         */
878
                        if (self->confirm)
879
                                self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
880
                                              self->priv);
881
                        dev_kfree_skb(skb);
882
                        break;
883
                case IAS_ATTRIB_UNKNOWN:
884
                        IRDA_DEBUG(1, "%s(), No such attribute!\n", __FUNCTION__);
885
                        /* Finished, close connection! */
886
                        iriap_disconnect_request(self);
887
 
888
                        /*
889
                         * Warning, the client might close us, so remember
890
                         * no to use self anymore after calling confirm
891
                         */
892
                        if (self->confirm)
893
                                self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL,
894
                                              self->priv);
895
                        dev_kfree_skb(skb);
896
                        break;
897
                }
898
                break;
899
        default:
900
                IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __FUNCTION__, opcode);
901
                dev_kfree_skb(skb);
902
                break;
903
        }
904
        return 0;
905
}
906
 
907
/*
908
 * Function iriap_call_indication (self, skb)
909
 *
910
 *    Received call to server from peer LM-IAS
911
 *
912
 */
913
void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
914
{
915
        __u8 *fp;
916
        __u8 opcode;
917
 
918
        IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
919
 
920
        ASSERT(self != NULL, return;);
921
        ASSERT(self->magic == IAS_MAGIC, return;);
922
        ASSERT(skb != NULL, return;);
923
 
924
        fp = skb->data;
925
 
926
        opcode = fp[0];
927
        if (~opcode & 0x80) {
928
                WARNING("%s(), IrIAS multiframe commands or results"
929
                        "is not implemented yet!\n", __FUNCTION__);
930
                return;
931
        }
932
        opcode &= 0x7f; /* Mask away LST bit */
933
 
934
        switch (opcode) {
935
        case GET_INFO_BASE:
936
                WARNING("%s(), GetInfoBaseDetails not implemented yet!\n",
937
                        __FUNCTION__);
938
                break;
939
        case GET_VALUE_BY_CLASS:
940
                iriap_getvaluebyclass_indication(self, skb);
941
                break;
942
        }
943
}
944
 
945
/*
946
 * Function iriap_watchdog_timer_expired (data)
947
 *
948
 *    Query has taken to long time, so abort
949
 *
950
 */
951
void iriap_watchdog_timer_expired(void *data)
952
{
953
        struct iriap_cb *self = (struct iriap_cb *) data;
954
 
955
        ASSERT(self != NULL, return;);
956
        ASSERT(self->magic == IAS_MAGIC, return;);
957
 
958
        /* iriap_close(self); */
959
}
960
 
961
#ifdef CONFIG_PROC_FS
962
 
963
static char *ias_value_types[] = {
964
        "IAS_MISSING",
965
        "IAS_INTEGER",
966
        "IAS_OCT_SEQ",
967
        "IAS_STRING"
968
};
969
 
970
int irias_proc_read(char *buf, char **start, off_t offset, int len)
971
{
972
        struct ias_object *obj;
973
        struct ias_attrib *attrib;
974
        unsigned long flags;
975
 
976
        ASSERT( objects != NULL, return 0;);
977
 
978
        save_flags( flags);
979
        cli();
980
 
981
        len = 0;
982
 
983
        len += sprintf(buf+len, "LM-IAS Objects:\n");
984
 
985
        /* List all objects */
986
        obj = (struct ias_object *) hashbin_get_first(objects);
987
        while ( obj != NULL) {
988
                ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
989
 
990
                len += sprintf(buf+len, "name: %s, ", obj->name);
991
                len += sprintf(buf+len, "id=%d", obj->id);
992
                len += sprintf(buf+len, "\n");
993
 
994
                /* List all attributes for this object */
995
                attrib = (struct ias_attrib *)
996
                        hashbin_get_first(obj->attribs);
997
                while (attrib != NULL) {
998
                        ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
999
 
1000
                        len += sprintf(buf+len, " - Attribute name: \"%s\", ",
1001
                                       attrib->name);
1002
                        len += sprintf(buf+len, "value[%s]: ",
1003
                                       ias_value_types[attrib->value->type]);
1004
 
1005
                        switch (attrib->value->type) {
1006
                        case IAS_INTEGER:
1007
                                len += sprintf(buf+len, "%d\n",
1008
                                               attrib->value->t.integer);
1009
                                break;
1010
                        case IAS_STRING:
1011
                                len += sprintf(buf+len, "\"%s\"\n",
1012
                                               attrib->value->t.string);
1013
                                break;
1014
                        case IAS_OCT_SEQ:
1015
                                len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
1016
                                break;
1017
                        case IAS_MISSING:
1018
                                len += sprintf(buf+len, "missing\n");
1019
                                break;
1020
                        default:
1021
                                IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
1022
                                return -1;
1023
                        }
1024
                        len += sprintf(buf+len, "\n");
1025
 
1026
                        attrib = (struct ias_attrib *)
1027
                                hashbin_get_next(obj->attribs);
1028
                }
1029
                obj = (struct ias_object *) hashbin_get_next(objects);
1030
        }
1031
        restore_flags(flags);
1032
 
1033
        return len;
1034
}
1035
 
1036
#endif /* PROC_FS */

powered by: WebSVN 2.1.0

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