Import 2.3.25pre1
[davej-history.git] / net / irda / iriap.c
blob10fdd4627faf0d89312beed2e77a21062ddcb2cf
1 /*********************************************************************
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 Oct 9 17:00:56 1999
10 * Modified by: Dag Brattli <dagb@cs.uit.no>
12 * Copyright (c) 1998-1999 Dag Brattli <dagb@cs.uit.no>,
13 * All Rights Reserved.
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.
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.
24 ********************************************************************/
26 #include <linux/config.h>
27 #include <linux/types.h>
28 #include <linux/skbuff.h>
29 #include <linux/string.h>
30 #include <linux/init.h>
32 #include <asm/byteorder.h>
33 #include <asm/unaligned.h>
35 #include <net/irda/irda.h>
36 #include <net/irda/irttp.h>
37 #include <net/irda/irmod.h>
38 #include <net/irda/irlmp.h>
39 #include <net/irda/irias_object.h>
40 #include <net/irda/iriap_event.h>
41 #include <net/irda/iriap.h>
43 /* FIXME: This one should go in irlmp.c */
44 static const char *ias_charset_types[] = {
45 "CS_ASCII",
46 "CS_ISO_8859_1",
47 "CS_ISO_8859_2",
48 "CS_ISO_8859_3",
49 "CS_ISO_8859_4",
50 "CS_ISO_8859_5",
51 "CS_ISO_8859_6",
52 "CS_ISO_8859_7",
53 "CS_ISO_8859_8",
54 "CS_ISO_8859_9",
55 "CS_UNICODE"
58 static hashbin_t *iriap = NULL;
59 static __u32 service_handle;
61 extern char *lmp_reasons[];
63 static struct iriap_cb *iriap_open( __u8 slsap, int mode);
64 static void __iriap_close(struct iriap_cb *self);
65 static void iriap_disconnect_indication(void *instance, void *sap,
66 LM_REASON reason, struct sk_buff *skb);
67 static void iriap_connect_indication(void *instance, void *sap,
68 struct qos_info *qos, __u32 max_sdu_size,
69 __u8 max_header_size,
70 struct sk_buff *skb);
71 static void iriap_connect_confirm(void *instance, void *sap,
72 struct qos_info *qos,
73 __u32 max_sdu_size, __u8 max_header_size,
74 struct sk_buff *skb);
75 static int iriap_data_indication(void *instance, void *sap,
76 struct sk_buff *skb);
79 * Function iriap_init (void)
81 * Initializes the IrIAP layer, called by the module initialization code
82 * in irmod.c
84 int __init iriap_init(void)
86 __u16 hints;
87 struct ias_object *obj;
89 /* Allocate master array */
90 iriap = hashbin_new(HB_LOCAL);
91 if (!iriap)
92 return -ENOMEM;
94 objects = hashbin_new(HB_LOCAL);
95 if (!objects) {
96 WARNING(__FUNCTION__ "(), Can't allocate objects hashbin!\n");
97 return -ENOMEM;
101 * Register some default services for IrLMP
103 hints = irlmp_service_to_hint(S_COMPUTER);
104 hints |= irlmp_service_to_hint(S_PNP);
105 service_handle = irlmp_register_service(hints);
108 * Register the Device object with LM-IAS
110 obj = irias_new_object("Device", IAS_DEVICE_ID);
111 irias_add_string_attrib(obj, "DeviceName", "Linux");
112 irias_insert_object(obj);
115 * Register server support with IrLMP so we can accept incoming
116 * connections
118 iriap_open(LSAP_IAS, IAS_SERVER);
120 return 0;
124 * Function iriap_cleanup (void)
126 * Initializes the IrIAP layer, called by the module cleanup code in
127 * irmod.c
129 void iriap_cleanup(void)
131 irlmp_unregister_service(service_handle);
133 hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
134 hashbin_delete(objects, (FREE_FUNC) __irias_delete_object);
138 * Function iriap_open (void)
140 * Opens an instance of the IrIAP layer, and registers with IrLMP
142 struct iriap_cb *iriap_open(__u8 slsap_sel, int mode)
144 struct iriap_cb *self;
145 struct lsap_cb *lsap;
146 notify_t notify;
148 IRDA_DEBUG(4, __FUNCTION__ "()\n");
150 self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
151 if (!self) {
152 WARNING(__FUNCTION__ "(), Unable to kmalloc!\n");
153 return NULL;
157 * Initialize instance
159 memset(self, 0, sizeof(struct iriap_cb));
161 irda_notify_init(&notify);
162 notify.connect_confirm = iriap_connect_confirm;
163 notify.connect_indication = iriap_connect_indication;
164 notify.disconnect_indication = iriap_disconnect_indication;
165 notify.data_indication = iriap_data_indication;
166 notify.instance = self;
167 if (mode == IAS_CLIENT)
168 strcpy(notify.name, "IrIAS cli");
169 else
170 strcpy(notify.name, "IrIAS srv");
172 lsap = irlmp_open_lsap(slsap_sel, &notify);
173 if (lsap == NULL) {
174 ERROR(__FUNCTION__ "(), Unable to allocated LSAP!\n");
175 return NULL;
177 slsap_sel = lsap->slsap_sel;
179 self->magic = IAS_MAGIC;
180 self->lsap = lsap;
181 self->slsap_sel = slsap_sel;
182 self->mode = mode;
184 init_timer(&self->watchdog_timer);
186 hashbin_insert(iriap, (queue_t *) self, slsap_sel, NULL);
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);
194 return self;
198 * Function __iriap_close (self)
200 * Removes (deallocates) the IrIAP instance
203 static void __iriap_close(struct iriap_cb *self)
205 IRDA_DEBUG(4, __FUNCTION__ "()\n");
207 ASSERT(self != NULL, return;);
208 ASSERT(self->magic == IAS_MAGIC, return;);
210 del_timer(&self->watchdog_timer);
212 self->magic = 0;
214 kfree(self);
218 * Function iriap_close (void)
220 * Closes IrIAP and deregisters with IrLMP
222 void iriap_close(struct iriap_cb *self)
224 struct iriap_cb *entry;
226 ASSERT(self != NULL, return;);
227 ASSERT(self->magic == IAS_MAGIC, return;);
229 if (self->lsap) {
230 irlmp_close_lsap(self->lsap);
231 self->lsap = NULL;
234 entry = (struct iriap_cb *) hashbin_remove(iriap, self->slsap_sel,
235 NULL);
236 ASSERT(entry == self, return;);
238 __iriap_close(self);
242 * Function iriap_disconnect_indication (handle, reason)
244 * Got disconnect, so clean up everything assosiated with this connection
247 static void iriap_disconnect_indication(void *instance, void *sap,
248 LM_REASON reason,
249 struct sk_buff *userdata)
251 struct iriap_cb *self;
253 IRDA_DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
255 self = (struct iriap_cb *) instance;
257 ASSERT(self != NULL, return;);
258 ASSERT(self->magic == IAS_MAGIC, return;);
260 ASSERT(iriap != NULL, return;);
262 del_timer(&self->watchdog_timer);
264 if (self->mode == IAS_CLIENT) {
265 IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
268 * Inform service user that the request failed by sending
269 * it a NULL value.
271 if (self->confirm)
272 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
275 iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
276 NULL);
277 /* Close instance only if client */
278 iriap_close(self);
280 } else {
281 IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
282 iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
283 NULL);
286 if (userdata)
287 dev_kfree_skb(userdata);
291 * Function iriap_disconnect_request (handle)
296 void iriap_disconnect_request(struct iriap_cb *self)
298 struct sk_buff *skb;
300 IRDA_DEBUG(4, __FUNCTION__ "()\n");
302 ASSERT(self != NULL, return;);
303 ASSERT(self->magic == IAS_MAGIC, return;);
305 skb = dev_alloc_skb(64);
306 if (skb == NULL) {
307 IRDA_DEBUG(0, __FUNCTION__
308 "(), Could not allocate an sk_buff of length %d\n", 64);
309 return;
313 * Reserve space for MUX control and LAP header
315 skb_reserve(skb, LMP_MAX_HEADER);
317 irlmp_disconnect_request(self->lsap, skb);
320 void iriap_getinfobasedetails_request(void)
322 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
325 void iriap_getinfobasedetails_confirm(void)
327 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
330 void iriap_getobjects_request(void)
332 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
335 void iriap_getobjects_confirm(void)
337 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
340 void iriap_getvalue(void)
342 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
346 * Function iriap_getvaluebyclass (addr, name, attr)
348 * Retreive all values from attribute in all objects with given class
349 * name
351 void iriap_getvaluebyclass_request(char *name, char *attr,
352 __u32 saddr, __u32 daddr,
353 CONFIRM_CALLBACK callback, void *priv)
355 struct sk_buff *skb;
356 struct iriap_cb *self;
357 int name_len, attr_len;
358 __u8 slsap = LSAP_ANY; /* Source LSAP to use */
359 __u8 *frame;
361 /* Client must supply the destination device address */
362 if (!daddr)
363 return;
365 self = iriap_open(slsap, IAS_CLIENT);
366 if (!self)
367 return;
369 self->mode = IAS_CLIENT;
370 self->confirm = callback;
371 self->priv = priv;
373 self->daddr = daddr;
374 self->saddr = saddr;
377 * Save operation, so we know what the later indication is about
379 self->operation = GET_VALUE_BY_CLASS;
381 /* Give ourselves 10 secs to finish this operation */
382 iriap_start_watchdog_timer(self, 10*HZ);
384 skb = dev_alloc_skb(64);
385 if (!skb)
386 return;
388 name_len = strlen(name);
389 attr_len = strlen(attr);
391 /* Reserve space for MUX and LAP header */
392 skb_reserve(skb, self->max_header_size);
393 skb_put(skb, 3+name_len+attr_len);
394 frame = skb->data;
396 /* Build frame */
397 frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
398 frame[1] = name_len; /* Insert length of name */
399 memcpy(frame+2, name, name_len); /* Insert name */
400 frame[2+name_len] = attr_len; /* Insert length of attr */
401 memcpy(frame+3+name_len, attr, attr_len); /* Insert attr */
403 iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
407 * Function iriap_getvaluebyclass_confirm (self, skb)
409 * Got result from GetValueByClass command. Parse it and return result
410 * to service user.
413 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
415 struct ias_value *value;
416 int charset;
417 __u32 value_len;
418 __u32 tmp_cpu32;
419 __u16 obj_id;
420 __u16 len;
421 __u8 type;
422 __u8 *fp;
423 int n;
425 ASSERT(self != NULL, return;);
426 ASSERT(self->magic == IAS_MAGIC, return;);
427 ASSERT(skb != NULL, return;);
429 /* Initialize variables */
430 fp = skb->data;
431 n = 2;
433 /* Get length, MSB first */
434 len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
436 IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
438 /* Get object ID, MSB first */
439 obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
441 type = fp[n++];
442 IRDA_DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
444 switch (type) {
445 case IAS_INTEGER:
446 memcpy(&tmp_cpu32, fp+n, 4); n += 4;
447 be32_to_cpus(&tmp_cpu32);
448 value = irias_new_integer_value(tmp_cpu32);
450 /* Legal values restricted to 0x01-0x6f, page 15 irttp */
451 IRDA_DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer);
452 break;
453 case IAS_STRING:
454 charset = fp[n++];
456 switch (charset) {
457 case CS_ASCII:
458 break;
459 /* case CS_ISO_8859_1: */
460 /* case CS_ISO_8859_2: */
461 /* case CS_ISO_8859_3: */
462 /* case CS_ISO_8859_4: */
463 /* case CS_ISO_8859_5: */
464 /* case CS_ISO_8859_6: */
465 /* case CS_ISO_8859_7: */
466 /* case CS_ISO_8859_8: */
467 /* case CS_ISO_8859_9: */
468 /* case CS_UNICODE: */
469 default:
470 IRDA_DEBUG(0, __FUNCTION__"(), charset %s, not supported\n",
471 ias_charset_types[charset]);
472 return;
473 /* break; */
475 value_len = fp[n++];
476 IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
477 ASSERT(value_len < 64, return;);
479 /* Make sure the string is null-terminated */
480 fp[n+value_len] = 0x00;
482 IRDA_DEBUG(4, "Got string %s\n", fp+n);
483 value = irias_new_string_value(fp+n);
484 break;
485 case IAS_OCT_SEQ:
486 value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
487 n += 2;
489 ASSERT(value_len <= 55, return;);
491 value = irias_new_octseq_value(fp+n, value_len);
492 break;
493 default:
494 value = &missing;
495 break;
498 /* Finished, close connection! */
499 iriap_disconnect_request(self);
501 if (self->confirm)
502 self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
506 * Function iriap_getvaluebyclass_response ()
508 * Send answer back to remote LM-IAS
511 void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
512 __u8 ret_code, struct ias_value *value)
514 struct sk_buff *skb;
515 int n;
516 __u32 tmp_be32, tmp_be16;
517 __u8 *fp;
519 IRDA_DEBUG(4, __FUNCTION__ "()\n");
521 ASSERT(self != NULL, return;);
522 ASSERT(self->magic == IAS_MAGIC, return;);
523 ASSERT(value != NULL, return;);
524 ASSERT(value->len <= 1024, return;);
526 /* Initialize variables */
527 n = 0;
530 * We must adjust the size of the response after the length of the
531 * value. We add 9 bytes because of the 6 bytes for the frame and
532 * max 3 bytes for the value coding.
534 skb = dev_alloc_skb(value->len + self->max_header_size + 9);
535 if (!skb)
536 return;
538 /* Reserve space for MUX and LAP header */
539 skb_reserve(skb, self->max_header_size);
540 skb_put(skb, 6);
542 fp = skb->data;
544 /* Build frame */
545 fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
546 fp[n++] = ret_code;
548 /* Insert list length (MSB first) */
549 tmp_be16 = __constant_htons(0x0001);
550 memcpy(fp+n, &tmp_be16, 2); n += 2;
552 /* Insert object identifier ( MSB first) */
553 tmp_be16 = cpu_to_be16(obj_id);
554 memcpy(fp+n, &tmp_be16, 2); n += 2;
556 switch(value->type) {
557 case IAS_STRING:
558 skb_put(skb, 3 + value->len);
559 fp[n++] = value->type;
560 fp[n++] = 0; /* ASCII */
561 fp[n++] = (__u8) value->len;
562 memcpy(fp+n, value->t.string, value->len); n+=value->len;
563 break;
564 case IAS_INTEGER:
565 skb_put(skb, 5);
566 fp[n++] = value->type;
568 tmp_be32 = cpu_to_be32(value->t.integer);
569 memcpy(fp+n, &tmp_be32, 4); n += 4;
570 break;
571 case IAS_OCT_SEQ:
572 skb_put(skb, 3 + value->len);
573 fp[n++] = value->type;
575 tmp_be16 = cpu_to_be16(value->len);
576 memcpy(fp+n, &tmp_be16, 2); n += 2;
577 memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
578 break;
579 case IAS_MISSING:
580 IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
581 skb_put( skb, 1);
582 fp[n++] = value->type;
583 break;
584 default:
585 IRDA_DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
586 break;
588 iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
592 * Function iriap_getvaluebyclass_indication (self, skb)
594 * getvaluebyclass is requested from peer LM-IAS
597 void iriap_getvaluebyclass_indication(struct iriap_cb *self,
598 struct sk_buff *skb)
600 struct ias_object *obj;
601 struct ias_attrib *attrib;
602 int name_len;
603 int attr_len;
604 char name[64];
605 char attr[64];
606 __u8 *fp;
607 int n;
609 IRDA_DEBUG(4, __FUNCTION__ "()\n");
611 ASSERT(self != NULL, return;);
612 ASSERT(self->magic == IAS_MAGIC, return;);
613 ASSERT(skb != NULL, return;);
615 fp = skb->data;
616 n = 1;
618 name_len = fp[n++];
619 memcpy(name, fp+n, name_len); n+=name_len;
620 name[name_len] = '\0';
622 attr_len = fp[n++];
623 memcpy(attr, fp+n, attr_len); n+=attr_len;
624 attr[attr_len] = '\0';
626 dev_kfree_skb(skb);
629 * Now, do some advanced parsing! :-)
631 IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
632 obj = irias_find_object(name);
634 if (obj == NULL) {
635 IRDA_DEBUG(0, "LM-IAS: Object not found\n");
636 iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
637 &missing);
638 return;
640 IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
642 attrib = irias_find_attrib(obj, attr);
643 if (attrib == NULL) {
644 IRDA_DEBUG(0, "LM-IAS: Attribute %s not found\n", attr);
645 iriap_getvaluebyclass_response(self, obj->id,
646 IAS_ATTRIB_UNKNOWN, &missing);
647 return;
650 IRDA_DEBUG(4, "LM-IAS: found %s\n", attrib->name);
653 * We have a match; send the value.
655 iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
656 attrib->value);
658 return;
662 * Function iriap_send_ack (void)
664 * Currently not used
667 void iriap_send_ack(struct iriap_cb *self)
669 struct sk_buff *skb;
670 __u8 *frame;
672 IRDA_DEBUG(6, __FUNCTION__ "()\n");
674 ASSERT(self != NULL, return;);
675 ASSERT(self->magic == IAS_MAGIC, return;);
677 skb = dev_alloc_skb(64);
678 if (!skb)
679 return;
681 /* Reserve space for MUX and LAP header */
682 skb_reserve(skb, self->max_header_size);
683 skb_put(skb, 1);
684 frame = skb->data;
686 /* Build frame */
687 frame[0] = IAP_LST | self->operation;
691 * Function iriap_connect_confirm (handle, skb)
693 * LSAP connection confirmed!
696 static void iriap_connect_confirm(void *instance, void *sap,
697 struct qos_info *qos,
698 __u32 max_sdu_size, __u8 header_size,
699 struct sk_buff *userdata)
701 struct iriap_cb *self;
703 self = (struct iriap_cb *) instance;
705 ASSERT(self != NULL, return;);
706 ASSERT(self->magic == IAS_MAGIC, return;);
707 ASSERT(userdata != NULL, return;);
709 IRDA_DEBUG(4, __FUNCTION__ "()\n");
711 del_timer(&self->watchdog_timer);
713 iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
717 * Function iriap_connect_indication ( handle, skb)
719 * Remote LM-IAS is requesting connection
722 static void iriap_connect_indication(void *instance, void *sap,
723 struct qos_info *qos, __u32 max_sdu_size,
724 __u8 header_size,
725 struct sk_buff *userdata)
727 struct iriap_cb *self;
729 self = (struct iriap_cb *) instance;
731 ASSERT(self != NULL, return;);
732 ASSERT(self->magic == IAS_MAGIC, return;);
734 iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
738 * Function iriap_data_indication (handle, skb)
740 * Receives data from connection identified by handle from IrLMP
743 static int iriap_data_indication(void *instance, void *sap,
744 struct sk_buff *skb)
746 struct iriap_cb *self;
747 __u8 *frame;
748 __u8 opcode;
750 IRDA_DEBUG( 4, __FUNCTION__ "()\n");
752 self = (struct iriap_cb *) instance;
754 ASSERT(self != NULL, return 0;);
755 ASSERT(self->magic == IAS_MAGIC, return 0;);
757 ASSERT(skb != NULL, return 0;);
759 frame = skb->data;
761 if (self->mode == IAS_SERVER) {
762 /* Call server */
763 IRDA_DEBUG(4, __FUNCTION__ "(), Calling server!\n");
764 iriap_do_r_connect_event( self, IAP_RECV_F_LST, skb);
766 return 0;
768 opcode = frame[0];
769 if (~opcode & IAP_LST) {
770 WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
771 "results is not implemented yet!\n");
772 return 0;
775 /* Check for ack frames since they don't contain any data */
776 if (opcode & IAP_ACK) {
777 IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
778 return 0;
781 opcode &= ~IAP_LST; /* Mask away LST bit */
783 switch (opcode) {
784 case GET_INFO_BASE:
785 IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
786 break;
787 case GET_VALUE_BY_CLASS:
788 switch (frame[1]) {
789 case IAS_SUCCESS:
790 iriap_getvaluebyclass_confirm(self, skb);
791 break;
792 case IAS_CLASS_UNKNOWN:
793 WARNING(__FUNCTION__ "(), No such class!\n");
794 /* Finished, close connection! */
795 iriap_disconnect_request(self);
797 if (self->confirm)
798 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
799 self->priv);
800 break;
801 case IAS_ATTRIB_UNKNOWN:
802 WARNING(__FUNCTION__ "(), No such attribute!\n");
803 /* Finished, close connection! */
804 iriap_disconnect_request(self);
806 if (self->confirm)
807 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
808 self->priv);
809 break;
811 iriap_do_call_event(self, IAP_RECV_F_LST, skb);
814 * We remove LSAPs used by IrIAS as a client since these
815 * are more difficult to reuse!
817 iriap_close(self);
818 break;
819 default:
820 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n", opcode);
821 break;
823 return 0;
827 * Function iriap_call_indication (self, skb)
829 * Received call to server from peer LM-IAS
832 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
834 __u8 *fp;
835 __u8 opcode;
837 IRDA_DEBUG(4, __FUNCTION__ "()\n");
839 ASSERT(self != NULL, return;);
840 ASSERT(self->magic == IAS_MAGIC, return;);
841 ASSERT(skb != NULL, return;);
843 fp = skb->data;
845 opcode = fp[0];
846 if (~opcode & 0x80) {
847 WARNING(__FUNCTION__ "(), IrIAS multiframe commands or results"
848 "is not implemented yet!\n");
849 return;
851 opcode &= 0x7f; /* Mask away LST bit */
853 switch (opcode) {
854 case GET_INFO_BASE:
855 WARNING(__FUNCTION__
856 "(), GetInfoBaseDetails not implemented yet!\n");
857 break;
858 case GET_VALUE_BY_CLASS:
859 iriap_getvaluebyclass_indication(self, skb);
860 break;
865 * Function iriap_watchdog_timer_expired (data)
867 * Query has taken to long time, so abort
870 void iriap_watchdog_timer_expired(void *data)
872 struct iriap_cb *self = (struct iriap_cb *) data;
874 ASSERT(self != NULL, return;);
875 ASSERT(self->magic == IAS_MAGIC, return;);
877 iriap_close(self);
880 #ifdef CONFIG_PROC_FS
882 static char *ias_value_types[] = {
883 "IAS_MISSING",
884 "IAS_INTEGER",
885 "IAS_OCT_SEQ",
886 "IAS_STRING"
889 int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused)
891 struct ias_object *obj;
892 struct ias_attrib *attrib;
893 unsigned long flags;
895 ASSERT( objects != NULL, return 0;);
897 save_flags( flags);
898 cli();
900 len = 0;
902 len += sprintf(buf+len, "LM-IAS Objects:\n");
904 /* List all objects */
905 obj = (struct ias_object *) hashbin_get_first(objects);
906 while ( obj != NULL) {
907 ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
909 len += sprintf(buf+len, "name: %s, ", obj->name);
910 len += sprintf(buf+len, "id=%d", obj->id);
911 len += sprintf(buf+len, "\n");
913 /* List all attributes for this object */
914 attrib = (struct ias_attrib *)
915 hashbin_get_first(obj->attribs);
916 while (attrib != NULL) {
917 ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
919 len += sprintf(buf+len, " - Attribute name: \"%s\", ",
920 attrib->name);
921 len += sprintf(buf+len, "value[%s]: ",
922 ias_value_types[attrib->value->type]);
924 switch (attrib->value->type) {
925 case IAS_INTEGER:
926 len += sprintf(buf+len, "%d\n",
927 attrib->value->t.integer);
928 break;
929 case IAS_STRING:
930 len += sprintf(buf+len, "\"%s\"\n",
931 attrib->value->t.string);
932 break;
933 case IAS_OCT_SEQ:
934 len += sprintf(buf+len, "octet sequence\n");
935 break;
936 case IAS_MISSING:
937 len += sprintf(buf+len, "missing\n");
938 break;
939 default:
940 IRDA_DEBUG(0, __FUNCTION__
941 "(), Unknown value type!\n");
942 return -1;
944 len += sprintf(buf+len, "\n");
946 attrib = (struct ias_attrib *)
947 hashbin_get_next(obj->attribs);
949 obj = (struct ias_object *) hashbin_get_next(objects);
951 restore_flags(flags);
953 return len;
956 #endif /* PROC_FS */