Import 2.3.27pre2
[davej-history.git] / net / irda / iriap.c
blobbcd43e8c06ef004f479666d9c0fd6d59c206ebbe
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: Sun Oct 31 22:10:45 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 void __iriap_close(struct iriap_cb *self);
64 static void iriap_disconnect_indication(void *instance, void *sap,
65 LM_REASON reason, struct sk_buff *skb);
66 static void iriap_connect_indication(void *instance, void *sap,
67 struct qos_info *qos, __u32 max_sdu_size,
68 __u8 max_header_size,
69 struct sk_buff *skb);
70 static void iriap_connect_confirm(void *instance, void *sap,
71 struct qos_info *qos,
72 __u32 max_sdu_size, __u8 max_header_size,
73 struct sk_buff *skb);
74 static int iriap_data_indication(void *instance, void *sap,
75 struct sk_buff *skb);
78 * Function iriap_init (void)
80 * Initializes the IrIAP layer, called by the module initialization code
81 * in irmod.c
83 int __init iriap_init(void)
85 __u16 hints;
86 struct ias_object *obj;
88 /* Allocate master array */
89 iriap = hashbin_new(HB_LOCAL);
90 if (!iriap)
91 return -ENOMEM;
93 objects = hashbin_new(HB_LOCAL);
94 if (!objects) {
95 WARNING(__FUNCTION__ "(), Can't allocate objects hashbin!\n");
96 return -ENOMEM;
99 /*
100 * Register some default services for IrLMP
102 hints = irlmp_service_to_hint(S_COMPUTER);
103 hints |= irlmp_service_to_hint(S_PNP);
104 service_handle = irlmp_register_service(hints);
107 * Register the Device object with LM-IAS
109 obj = irias_new_object("Device", IAS_DEVICE_ID);
110 irias_add_string_attrib(obj, "DeviceName", "Linux");
111 irias_insert_object(obj);
114 * Register server support with IrLMP so we can accept incoming
115 * connections
117 iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
119 return 0;
123 * Function iriap_cleanup (void)
125 * Initializes the IrIAP layer, called by the module cleanup code in
126 * irmod.c
128 void iriap_cleanup(void)
130 irlmp_unregister_service(service_handle);
132 hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
133 hashbin_delete(objects, (FREE_FUNC) __irias_delete_object);
137 * Function iriap_open (void)
139 * Opens an instance of the IrIAP layer, and registers with IrLMP
141 struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
142 CONFIRM_CALLBACK callback)
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 self->confirm = callback;
185 self->priv = priv;
187 init_timer(&self->watchdog_timer);
189 hashbin_insert(iriap, (queue_t *) self, slsap_sel, NULL);
191 /* Initialize state machines */
192 iriap_next_client_state(self, S_DISCONNECT);
193 iriap_next_call_state(self, S_MAKE_CALL);
194 iriap_next_server_state(self, R_DISCONNECT);
195 iriap_next_r_connect_state(self, R_WAITING);
197 return self;
201 * Function __iriap_close (self)
203 * Removes (deallocates) the IrIAP instance
206 static void __iriap_close(struct iriap_cb *self)
208 IRDA_DEBUG(4, __FUNCTION__ "()\n");
210 ASSERT(self != NULL, return;);
211 ASSERT(self->magic == IAS_MAGIC, return;);
213 del_timer(&self->watchdog_timer);
215 self->magic = 0;
217 kfree(self);
221 * Function iriap_close (void)
223 * Closes IrIAP and deregisters with IrLMP
225 void iriap_close(struct iriap_cb *self)
227 struct iriap_cb *entry;
229 ASSERT(self != NULL, return;);
230 ASSERT(self->magic == IAS_MAGIC, return;);
232 if (self->lsap) {
233 irlmp_close_lsap(self->lsap);
234 self->lsap = NULL;
237 entry = (struct iriap_cb *) hashbin_remove(iriap, self->slsap_sel,
238 NULL);
239 ASSERT(entry == self, return;);
241 __iriap_close(self);
245 * Function iriap_disconnect_indication (handle, reason)
247 * Got disconnect, so clean up everything assosiated with this connection
250 static void iriap_disconnect_indication(void *instance, void *sap,
251 LM_REASON reason,
252 struct sk_buff *userdata)
254 struct iriap_cb *self;
256 IRDA_DEBUG(4, __FUNCTION__ "(), reason=%s\n", lmp_reasons[reason]);
258 self = (struct iriap_cb *) instance;
260 ASSERT(self != NULL, return;);
261 ASSERT(self->magic == IAS_MAGIC, return;);
263 ASSERT(iriap != NULL, return;);
265 del_timer(&self->watchdog_timer);
267 if (self->mode == IAS_CLIENT) {
268 IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as client\n");
271 * Inform service user that the request failed by sending
272 * it a NULL value.
274 if (self->confirm)
275 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
278 iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
279 NULL);
280 /* Close instance only if client */
281 /* iriap_close(self); */
283 } else {
284 IRDA_DEBUG(4, __FUNCTION__ "(), disconnect as server\n");
285 iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
286 NULL);
289 if (userdata)
290 dev_kfree_skb(userdata);
294 * Function iriap_disconnect_request (handle)
299 void iriap_disconnect_request(struct iriap_cb *self)
301 struct sk_buff *skb;
303 IRDA_DEBUG(4, __FUNCTION__ "()\n");
305 ASSERT(self != NULL, return;);
306 ASSERT(self->magic == IAS_MAGIC, return;);
308 skb = dev_alloc_skb(64);
309 if (skb == NULL) {
310 IRDA_DEBUG(0, __FUNCTION__
311 "(), Could not allocate an sk_buff of length %d\n", 64);
312 return;
316 * Reserve space for MUX control and LAP header
318 skb_reserve(skb, LMP_MAX_HEADER);
320 irlmp_disconnect_request(self->lsap, skb);
323 void iriap_getinfobasedetails_request(void)
325 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
328 void iriap_getinfobasedetails_confirm(void)
330 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
333 void iriap_getobjects_request(void)
335 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
338 void iriap_getobjects_confirm(void)
340 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
343 void iriap_getvalue(void)
345 IRDA_DEBUG(0, __FUNCTION__ "(), Not implemented!\n");
349 * Function iriap_getvaluebyclass (addr, name, attr)
351 * Retreive all values from attribute in all objects with given class
352 * name
354 int iriap_getvaluebyclass_request(struct iriap_cb *self,
355 __u32 saddr, __u32 daddr,
356 char *name, char *attr)
358 struct sk_buff *skb;
359 int name_len, attr_len;
360 __u8 *frame;
362 ASSERT(self != NULL, return -1;);
363 ASSERT(self->magic == IAS_MAGIC, return -1;);
365 /* Client must supply the destination device address */
366 if (!daddr)
367 return -1;
369 self->daddr = daddr;
370 self->saddr = saddr;
373 * Save operation, so we know what the later indication is about
375 self->operation = GET_VALUE_BY_CLASS;
377 /* Give ourselves 10 secs to finish this operation */
378 iriap_start_watchdog_timer(self, 10*HZ);
380 skb = dev_alloc_skb(64);
381 if (!skb)
382 return -ENOMEM;
384 name_len = strlen(name);
385 attr_len = strlen(attr);
387 /* Reserve space for MUX and LAP header */
388 skb_reserve(skb, self->max_header_size);
389 skb_put(skb, 3+name_len+attr_len);
390 frame = skb->data;
392 /* Build frame */
393 frame[0] = IAP_LST | GET_VALUE_BY_CLASS;
394 frame[1] = name_len; /* Insert length of name */
395 memcpy(frame+2, name, name_len); /* Insert name */
396 frame[2+name_len] = attr_len; /* Insert length of attr */
397 memcpy(frame+3+name_len, attr, attr_len); /* Insert attr */
399 iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
401 return 0;
405 * Function iriap_getvaluebyclass_confirm (self, skb)
407 * Got result from GetValueByClass command. Parse it and return result
408 * to service user.
411 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
413 struct ias_value *value;
414 int charset;
415 __u32 value_len;
416 __u32 tmp_cpu32;
417 __u16 obj_id;
418 __u16 len;
419 __u8 type;
420 __u8 *fp;
421 int n;
423 ASSERT(self != NULL, return;);
424 ASSERT(self->magic == IAS_MAGIC, return;);
425 ASSERT(skb != NULL, return;);
427 /* Initialize variables */
428 fp = skb->data;
429 n = 2;
431 /* Get length, MSB first */
432 len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
434 IRDA_DEBUG(4, __FUNCTION__ "(), len=%d\n", len);
436 /* Get object ID, MSB first */
437 obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
439 type = fp[n++];
440 IRDA_DEBUG(4, __FUNCTION__ "(), Value type = %d\n", type);
442 switch (type) {
443 case IAS_INTEGER:
444 memcpy(&tmp_cpu32, fp+n, 4); n += 4;
445 be32_to_cpus(&tmp_cpu32);
446 value = irias_new_integer_value(tmp_cpu32);
448 /* Legal values restricted to 0x01-0x6f, page 15 irttp */
449 IRDA_DEBUG(4, __FUNCTION__ "(), lsap=%d\n", value->t.integer);
450 break;
451 case IAS_STRING:
452 charset = fp[n++];
454 switch (charset) {
455 case CS_ASCII:
456 break;
457 /* case CS_ISO_8859_1: */
458 /* case CS_ISO_8859_2: */
459 /* case CS_ISO_8859_3: */
460 /* case CS_ISO_8859_4: */
461 /* case CS_ISO_8859_5: */
462 /* case CS_ISO_8859_6: */
463 /* case CS_ISO_8859_7: */
464 /* case CS_ISO_8859_8: */
465 /* case CS_ISO_8859_9: */
466 /* case CS_UNICODE: */
467 default:
468 IRDA_DEBUG(0, __FUNCTION__
469 "(), charset %s, not supported\n",
470 ias_charset_types[charset]);
471 return;
472 /* break; */
474 value_len = fp[n++];
475 IRDA_DEBUG(4, __FUNCTION__ "(), strlen=%d\n", value_len);
476 ASSERT(value_len < 64, return;);
478 /* Make sure the string is null-terminated */
479 fp[n+value_len] = 0x00;
481 IRDA_DEBUG(4, "Got string %s\n", fp+n);
482 value = irias_new_string_value(fp+n);
483 break;
484 case IAS_OCT_SEQ:
485 value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
486 n += 2;
488 ASSERT(value_len <= 55, return;);
490 value = irias_new_octseq_value(fp+n, value_len);
491 break;
492 default:
493 value = &missing;
494 break;
497 /* Finished, close connection! */
498 iriap_disconnect_request(self);
500 if (self->confirm)
501 self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
505 * Function iriap_getvaluebyclass_response ()
507 * Send answer back to remote LM-IAS
510 void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
511 __u8 ret_code, struct ias_value *value)
513 struct sk_buff *skb;
514 int n;
515 __u32 tmp_be32, tmp_be16;
516 __u8 *fp;
518 IRDA_DEBUG(4, __FUNCTION__ "()\n");
520 ASSERT(self != NULL, return;);
521 ASSERT(self->magic == IAS_MAGIC, return;);
522 ASSERT(value != NULL, return;);
523 ASSERT(value->len <= 1024, return;);
525 /* Initialize variables */
526 n = 0;
529 * We must adjust the size of the response after the length of the
530 * value. We add 9 bytes because of the 6 bytes for the frame and
531 * max 3 bytes for the value coding.
533 skb = dev_alloc_skb(value->len + self->max_header_size + 9);
534 if (!skb)
535 return;
537 /* Reserve space for MUX and LAP header */
538 skb_reserve(skb, self->max_header_size);
539 skb_put(skb, 6);
541 fp = skb->data;
543 /* Build frame */
544 fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
545 fp[n++] = ret_code;
547 /* Insert list length (MSB first) */
548 tmp_be16 = __constant_htons(0x0001);
549 memcpy(fp+n, &tmp_be16, 2); n += 2;
551 /* Insert object identifier ( MSB first) */
552 tmp_be16 = cpu_to_be16(obj_id);
553 memcpy(fp+n, &tmp_be16, 2); n += 2;
555 switch(value->type) {
556 case IAS_STRING:
557 skb_put(skb, 3 + value->len);
558 fp[n++] = value->type;
559 fp[n++] = 0; /* ASCII */
560 fp[n++] = (__u8) value->len;
561 memcpy(fp+n, value->t.string, value->len); n+=value->len;
562 break;
563 case IAS_INTEGER:
564 skb_put(skb, 5);
565 fp[n++] = value->type;
567 tmp_be32 = cpu_to_be32(value->t.integer);
568 memcpy(fp+n, &tmp_be32, 4); n += 4;
569 break;
570 case IAS_OCT_SEQ:
571 skb_put(skb, 3 + value->len);
572 fp[n++] = value->type;
574 tmp_be16 = cpu_to_be16(value->len);
575 memcpy(fp+n, &tmp_be16, 2); n += 2;
576 memcpy(fp+n, value->t.oct_seq, value->len); n+=value->len;
577 break;
578 case IAS_MISSING:
579 IRDA_DEBUG( 3, __FUNCTION__ ": sending IAS_MISSING\n");
580 skb_put( skb, 1);
581 fp[n++] = value->type;
582 break;
583 default:
584 IRDA_DEBUG(0, __FUNCTION__ "(), type not implemented!\n");
585 break;
587 iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
591 * Function iriap_getvaluebyclass_indication (self, skb)
593 * getvaluebyclass is requested from peer LM-IAS
596 void iriap_getvaluebyclass_indication(struct iriap_cb *self,
597 struct sk_buff *skb)
599 struct ias_object *obj;
600 struct ias_attrib *attrib;
601 int name_len;
602 int attr_len;
603 char name[64];
604 char attr[64];
605 __u8 *fp;
606 int n;
608 IRDA_DEBUG(4, __FUNCTION__ "()\n");
610 ASSERT(self != NULL, return;);
611 ASSERT(self->magic == IAS_MAGIC, return;);
612 ASSERT(skb != NULL, return;);
614 fp = skb->data;
615 n = 1;
617 name_len = fp[n++];
618 memcpy(name, fp+n, name_len); n+=name_len;
619 name[name_len] = '\0';
621 attr_len = fp[n++];
622 memcpy(attr, fp+n, attr_len); n+=attr_len;
623 attr[attr_len] = '\0';
625 dev_kfree_skb(skb);
628 * Now, do some advanced parsing! :-)
630 IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
631 obj = irias_find_object(name);
633 if (obj == NULL) {
634 IRDA_DEBUG(0, "LM-IAS: Object not found\n");
635 iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
636 &missing);
637 return;
639 IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
641 attrib = irias_find_attrib(obj, attr);
642 if (attrib == NULL) {
643 IRDA_DEBUG(0, "LM-IAS: Attribute %s not found\n", attr);
644 iriap_getvaluebyclass_response(self, obj->id,
645 IAS_ATTRIB_UNKNOWN, &missing);
646 return;
649 IRDA_DEBUG(4, "LM-IAS: found %s\n", attrib->name);
652 * We have a match; send the value.
654 iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
655 attrib->value);
657 return;
661 * Function iriap_send_ack (void)
663 * Currently not used
666 void iriap_send_ack(struct iriap_cb *self)
668 struct sk_buff *skb;
669 __u8 *frame;
671 IRDA_DEBUG(6, __FUNCTION__ "()\n");
673 ASSERT(self != NULL, return;);
674 ASSERT(self->magic == IAS_MAGIC, return;);
676 skb = dev_alloc_skb(64);
677 if (!skb)
678 return;
680 /* Reserve space for MUX and LAP header */
681 skb_reserve(skb, self->max_header_size);
682 skb_put(skb, 1);
683 frame = skb->data;
685 /* Build frame */
686 frame[0] = IAP_LST | self->operation;
690 * Function iriap_connect_confirm (handle, skb)
692 * LSAP connection confirmed!
695 static void iriap_connect_confirm(void *instance, void *sap,
696 struct qos_info *qos,
697 __u32 max_sdu_size, __u8 header_size,
698 struct sk_buff *userdata)
700 struct iriap_cb *self;
702 self = (struct iriap_cb *) instance;
704 ASSERT(self != NULL, return;);
705 ASSERT(self->magic == IAS_MAGIC, return;);
706 ASSERT(userdata != NULL, return;);
708 IRDA_DEBUG(4, __FUNCTION__ "()\n");
710 del_timer(&self->watchdog_timer);
712 iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
716 * Function iriap_connect_indication ( handle, skb)
718 * Remote LM-IAS is requesting connection
721 static void iriap_connect_indication(void *instance, void *sap,
722 struct qos_info *qos, __u32 max_sdu_size,
723 __u8 header_size,
724 struct sk_buff *userdata)
726 struct iriap_cb *self;
728 self = (struct iriap_cb *) instance;
730 ASSERT(self != NULL, return;);
731 ASSERT(self->magic == IAS_MAGIC, return;);
733 iriap_do_server_event(self, IAP_LM_CONNECT_INDICATION, userdata);
737 * Function iriap_data_indication (handle, skb)
739 * Receives data from connection identified by handle from IrLMP
742 static int iriap_data_indication(void *instance, void *sap,
743 struct sk_buff *skb)
745 struct iriap_cb *self;
746 __u8 *frame;
747 __u8 opcode;
749 IRDA_DEBUG( 4, __FUNCTION__ "()\n");
751 self = (struct iriap_cb *) instance;
753 ASSERT(self != NULL, return 0;);
754 ASSERT(self->magic == IAS_MAGIC, return 0;);
756 ASSERT(skb != NULL, return 0;);
758 frame = skb->data;
760 if (self->mode == IAS_SERVER) {
761 /* Call server */
762 IRDA_DEBUG(4, __FUNCTION__ "(), Calling server!\n");
763 iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
765 return 0;
767 opcode = frame[0];
768 if (~opcode & IAP_LST) {
769 WARNING(__FUNCTION__ "(), IrIAS multiframe commands or "
770 "results is not implemented yet!\n");
771 return 0;
774 /* Check for ack frames since they don't contain any data */
775 if (opcode & IAP_ACK) {
776 IRDA_DEBUG(0, __FUNCTION__ "() Got ack frame!\n");
777 return 0;
780 opcode &= ~IAP_LST; /* Mask away LST bit */
782 switch (opcode) {
783 case GET_INFO_BASE:
784 IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
785 break;
786 case GET_VALUE_BY_CLASS:
787 iriap_do_call_event(self, IAP_RECV_F_LST, skb);
789 switch (frame[1]) {
790 case IAS_SUCCESS:
791 iriap_getvaluebyclass_confirm(self, skb);
792 break;
793 case IAS_CLASS_UNKNOWN:
794 WARNING(__FUNCTION__ "(), No such class!\n");
795 /* Finished, close connection! */
796 iriap_disconnect_request(self);
798 if (self->confirm)
799 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
800 self->priv);
801 break;
802 case IAS_ATTRIB_UNKNOWN:
803 WARNING(__FUNCTION__ "(), No such attribute!\n");
804 /* Finished, close connection! */
805 iriap_disconnect_request(self);
807 if (self->confirm)
808 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
809 self->priv);
810 break;
813 /* iriap_close(self); */
814 break;
815 default:
816 IRDA_DEBUG(0, __FUNCTION__ "(), Unknown op-code: %02x\n",
817 opcode);
818 break;
820 return 0;
824 * Function iriap_call_indication (self, skb)
826 * Received call to server from peer LM-IAS
829 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
831 __u8 *fp;
832 __u8 opcode;
834 IRDA_DEBUG(4, __FUNCTION__ "()\n");
836 ASSERT(self != NULL, return;);
837 ASSERT(self->magic == IAS_MAGIC, return;);
838 ASSERT(skb != NULL, return;);
840 fp = skb->data;
842 opcode = fp[0];
843 if (~opcode & 0x80) {
844 WARNING(__FUNCTION__ "(), IrIAS multiframe commands or results"
845 "is not implemented yet!\n");
846 return;
848 opcode &= 0x7f; /* Mask away LST bit */
850 switch (opcode) {
851 case GET_INFO_BASE:
852 WARNING(__FUNCTION__
853 "(), GetInfoBaseDetails not implemented yet!\n");
854 break;
855 case GET_VALUE_BY_CLASS:
856 iriap_getvaluebyclass_indication(self, skb);
857 break;
862 * Function iriap_watchdog_timer_expired (data)
864 * Query has taken to long time, so abort
867 void iriap_watchdog_timer_expired(void *data)
869 struct iriap_cb *self = (struct iriap_cb *) data;
871 ASSERT(self != NULL, return;);
872 ASSERT(self->magic == IAS_MAGIC, return;);
874 /* iriap_close(self); */
877 #ifdef CONFIG_PROC_FS
879 static char *ias_value_types[] = {
880 "IAS_MISSING",
881 "IAS_INTEGER",
882 "IAS_OCT_SEQ",
883 "IAS_STRING"
886 int irias_proc_read(char *buf, char **start, off_t offset, int len, int unused)
888 struct ias_object *obj;
889 struct ias_attrib *attrib;
890 unsigned long flags;
892 ASSERT( objects != NULL, return 0;);
894 save_flags( flags);
895 cli();
897 len = 0;
899 len += sprintf(buf+len, "LM-IAS Objects:\n");
901 /* List all objects */
902 obj = (struct ias_object *) hashbin_get_first(objects);
903 while ( obj != NULL) {
904 ASSERT(obj->magic == IAS_OBJECT_MAGIC, return 0;);
906 len += sprintf(buf+len, "name: %s, ", obj->name);
907 len += sprintf(buf+len, "id=%d", obj->id);
908 len += sprintf(buf+len, "\n");
910 /* List all attributes for this object */
911 attrib = (struct ias_attrib *)
912 hashbin_get_first(obj->attribs);
913 while (attrib != NULL) {
914 ASSERT(attrib->magic == IAS_ATTRIB_MAGIC, return 0;);
916 len += sprintf(buf+len, " - Attribute name: \"%s\", ",
917 attrib->name);
918 len += sprintf(buf+len, "value[%s]: ",
919 ias_value_types[attrib->value->type]);
921 switch (attrib->value->type) {
922 case IAS_INTEGER:
923 len += sprintf(buf+len, "%d\n",
924 attrib->value->t.integer);
925 break;
926 case IAS_STRING:
927 len += sprintf(buf+len, "\"%s\"\n",
928 attrib->value->t.string);
929 break;
930 case IAS_OCT_SEQ:
931 len += sprintf(buf+len, "octet sequence\n");
932 break;
933 case IAS_MISSING:
934 len += sprintf(buf+len, "missing\n");
935 break;
936 default:
937 IRDA_DEBUG(0, __FUNCTION__
938 "(), Unknown value type!\n");
939 return -1;
941 len += sprintf(buf+len, "\n");
943 attrib = (struct ias_attrib *)
944 hashbin_get_next(obj->attribs);
946 obj = (struct ias_object *) hashbin_get_next(objects);
948 restore_flags(flags);
950 return len;
953 #endif /* PROC_FS */