1 /*********************************************************************
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>
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>
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.
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.
25 ********************************************************************/
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>
33 #include <asm/byteorder.h>
34 #include <asm/unaligned.h>
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>
44 #ifdef CONFIG_IRDA_DEBUG
45 /* FIXME: This one should go in irlmp.c */
46 static const char *ias_charset_types[] = {
59 #endif /* CONFIG_IRDA_DEBUG */
61 static hashbin_t *iriap = NULL;
62 static __u32 service_handle;
64 extern char *lmp_reasons[];
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,
74 static void iriap_connect_confirm(void *instance, void *sap,
76 __u32 max_sdu_size, __u8 max_header_size,
78 static int iriap_data_indication(void *instance, void *sap,
82 * Function iriap_init (void)
84 * Initializes the IrIAP layer, called by the module initialization code
87 int __init iriap_init(void)
89 struct ias_object *obj;
90 struct iriap_cb *server;
94 /* Allocate master array */
95 iriap = hashbin_new(HB_LOCAL);
99 objects = hashbin_new(HB_LOCAL);
101 WARNING("%s(), Can't allocate objects hashbin!\n", __FUNCTION__);
106 * Register some default services for IrLMP
108 hints = irlmp_service_to_hint(S_COMPUTER);
109 service_handle = irlmp_register_service(hints);
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);
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 */
121 irias_add_octseq_attrib(obj, "IrLMPSupport", oct_seq, 3,
123 irias_insert_object(obj);
126 * Register server support with IrLMP so we can accept incoming
129 server = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
131 IRDA_DEBUG(0, "%s(), unable to open server\n", __FUNCTION__);
134 iriap_register_lsap(server, LSAP_IAS, IAS_SERVER);
140 * Function iriap_cleanup (void)
142 * Initializes the IrIAP layer, called by the module cleanup code in
145 void iriap_cleanup(void)
147 irlmp_unregister_service(service_handle);
149 hashbin_delete(iriap, (FREE_FUNC) __iriap_close);
150 hashbin_delete(objects, (FREE_FUNC) __irias_delete_object);
154 * Function iriap_open (void)
156 * Opens an instance of the IrIAP layer, and registers with IrLMP
158 struct iriap_cb *iriap_open(__u8 slsap_sel, int mode, void *priv,
159 CONFIRM_CALLBACK callback)
161 struct iriap_cb *self;
163 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
165 self = kmalloc(sizeof(struct iriap_cb), GFP_ATOMIC);
167 WARNING("%s(), Unable to kmalloc!\n", __FUNCTION__);
172 * Initialize instance
174 memset(self, 0, sizeof(struct iriap_cb));
176 self->magic = IAS_MAGIC;
178 if (mode == IAS_CLIENT)
179 iriap_register_lsap(self, slsap_sel, mode);
181 self->confirm = callback;
184 init_timer(&self->watchdog_timer);
186 hashbin_insert(iriap, (irda_queue_t *) self, (int) self, 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);
198 * Function __iriap_close (self)
200 * Removes (deallocates) the IrIAP instance
203 static void __iriap_close(struct iriap_cb *self)
205 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
207 ASSERT(self != NULL, return;);
208 ASSERT(self->magic == IAS_MAGIC, return;);
210 del_timer(&self->watchdog_timer);
213 dev_kfree_skb(self->skb);
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 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
231 ASSERT(self != NULL, return;);
232 ASSERT(self->magic == IAS_MAGIC, return;);
235 irlmp_close_lsap(self->lsap);
239 entry = (struct iriap_cb *) hashbin_remove(iriap, (int) self, NULL);
240 ASSERT(entry == self, return;);
245 static int iriap_register_lsap(struct iriap_cb *self, __u8 slsap_sel, int mode)
249 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
251 irda_notify_init(¬ify);
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");
260 strcpy(notify.name, "IrIAS srv");
262 self->lsap = irlmp_open_lsap(slsap_sel, ¬ify, 0);
263 if (self->lsap == NULL) {
264 ERROR("%s(), Unable to allocated LSAP!\n", __FUNCTION__);
267 self->slsap_sel = self->lsap->slsap_sel;
273 * Function iriap_disconnect_indication (handle, reason)
275 * Got disconnect, so clean up everything assosiated with this connection
278 static void iriap_disconnect_indication(void *instance, void *sap,
280 struct sk_buff *userdata)
282 struct iriap_cb *self;
284 IRDA_DEBUG(4, "%s(), reason=%s\n", __FUNCTION__, lmp_reasons[reason]);
286 self = (struct iriap_cb *) instance;
288 ASSERT(self != NULL, return;);
289 ASSERT(self->magic == IAS_MAGIC, return;);
291 ASSERT(iriap != NULL, return;);
293 del_timer(&self->watchdog_timer);
295 if (self->mode == IAS_CLIENT) {
296 IRDA_DEBUG(4, "%s(), disconnect as client\n", __FUNCTION__);
299 iriap_do_client_event(self, IAP_LM_DISCONNECT_INDICATION,
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
307 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
309 IRDA_DEBUG(4, "%s(), disconnect as server\n", __FUNCTION__);
310 iriap_do_server_event(self, IAP_LM_DISCONNECT_INDICATION,
316 dev_kfree_skb(userdata);
320 * Function iriap_disconnect_request (handle)
325 void iriap_disconnect_request(struct iriap_cb *self)
329 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
331 ASSERT(self != NULL, return;);
332 ASSERT(self->magic == IAS_MAGIC, return;);
334 skb = dev_alloc_skb(64);
336 IRDA_DEBUG(0, "%s(), Could not allocate an sk_buff of length %d\n",
342 * Reserve space for MUX control and LAP header
344 skb_reserve(skb, LMP_MAX_HEADER);
346 irlmp_disconnect_request(self->lsap, skb);
349 void iriap_getinfobasedetails_request(void)
351 IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
354 void iriap_getinfobasedetails_confirm(void)
356 IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
359 void iriap_getobjects_request(void)
361 IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
364 void iriap_getobjects_confirm(void)
366 IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
369 void iriap_getvalue(void)
371 IRDA_DEBUG(0, "%s(), Not implemented!\n", __FUNCTION__);
375 * Function iriap_getvaluebyclass (addr, name, attr)
377 * Retreive all values from attribute in all objects with given class
380 int iriap_getvaluebyclass_request(struct iriap_cb *self,
381 __u32 saddr, __u32 daddr,
382 char *name, char *attr)
385 int name_len, attr_len, skb_len;
388 ASSERT(self != NULL, return -1;);
389 ASSERT(self->magic == IAS_MAGIC, return -1;);
391 /* Client must supply the destination device address */
399 * Save operation, so we know what the later indication is about
401 self->operation = GET_VALUE_BY_CLASS;
403 /* Give ourselves 10 secs to finish this operation */
404 iriap_start_watchdog_timer(self, 10*HZ);
406 name_len = strlen(name); /* Up to IAS_MAX_CLASSNAME = 60 */
407 attr_len = strlen(attr); /* Up to IAS_MAX_ATTRIBNAME = 60 */
409 skb_len = self->max_header_size+2+name_len+1+attr_len+4;
410 skb = dev_alloc_skb(skb_len);
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);
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 */
426 iriap_do_client_event(self, IAP_CALL_REQUEST_GVBC, skb);
432 * Function iriap_getvaluebyclass_confirm (self, skb)
434 * Got result from GetValueByClass command. Parse it and return result
438 void iriap_getvaluebyclass_confirm(struct iriap_cb *self, struct sk_buff *skb)
440 struct ias_value *value;
450 ASSERT(self != NULL, return;);
451 ASSERT(self->magic == IAS_MAGIC, return;);
452 ASSERT(skb != NULL, return;);
454 /* Initialize variables */
458 /* Get length, MSB first */
459 len = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
461 IRDA_DEBUG(4, "%s(), len=%d\n", __FUNCTION__, len);
463 /* Get object ID, MSB first */
464 obj_id = be16_to_cpu(get_unaligned((__u16 *)(fp+n))); n += 2;
467 IRDA_DEBUG(4, "%s(), Value type = %d\n", __FUNCTION__, type);
471 memcpy(&tmp_cpu32, fp+n, 4); n += 4;
472 be32_to_cpus(&tmp_cpu32);
473 value = irias_new_integer_value(tmp_cpu32);
475 /* Legal values restricted to 0x01-0x6f, page 15 irttp */
476 IRDA_DEBUG(4, "%s(), lsap=%d\n", __FUNCTION__, value->t.integer);
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: */
495 IRDA_DEBUG(0, "%s(), charset %s, not supported\n",
496 __FUNCTION__, ias_charset_types[charset]);
498 /* Aborting, close connection! */
499 iriap_disconnect_request(self);
505 IRDA_DEBUG(4, "%s(), strlen=%d\n", __FUNCTION__, value_len);
507 /* Make sure the string is null-terminated */
508 fp[n+value_len] = 0x00;
509 IRDA_DEBUG(4, "Got string %s\n", fp+n);
511 /* Will truncate to IAS_MAX_STRING bytes */
512 value = irias_new_string_value(fp+n);
515 value_len = be16_to_cpu(get_unaligned((__u16 *)(fp+n)));
518 /* Will truncate to IAS_MAX_OCTET_STRING bytes */
519 value = irias_new_octseq_value(fp+n, value_len);
522 value = irias_new_missing_value();
526 /* Finished, close connection! */
527 iriap_disconnect_request(self);
529 /* Warning, the client might close us, so remember no to use self
530 * anymore after calling confirm
533 self->confirm(IAS_SUCCESS, obj_id, value, self->priv);
535 IRDA_DEBUG(0, "%s(), missing handler!\n", __FUNCTION__);
536 irias_delete_value(value);
542 * Function iriap_getvaluebyclass_response ()
544 * Send answer back to remote LM-IAS
547 void iriap_getvaluebyclass_response(struct iriap_cb *self, __u16 obj_id,
548 __u8 ret_code, struct ias_value *value)
552 __u32 tmp_be32, tmp_be16;
555 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
557 ASSERT(self != NULL, return;);
558 ASSERT(self->magic == IAS_MAGIC, return;);
559 ASSERT(value != NULL, return;);
560 ASSERT(value->len <= 1024, return;);
562 /* Initialize variables */
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.
570 skb = dev_alloc_skb(value->len + self->max_header_size + 32);
574 /* Reserve space for MUX and LAP header */
575 skb_reserve(skb, self->max_header_size);
581 fp[n++] = GET_VALUE_BY_CLASS | IAP_LST;
584 /* Insert list length (MSB first) */
585 tmp_be16 = __constant_htons(0x0001);
586 memcpy(fp+n, &tmp_be16, 2); n += 2;
588 /* Insert object identifier ( MSB first) */
589 tmp_be16 = cpu_to_be16(obj_id);
590 memcpy(fp+n, &tmp_be16, 2); n += 2;
592 switch (value->type) {
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;
602 fp[n++] = value->type;
604 tmp_be32 = cpu_to_be32(value->t.integer);
605 memcpy(fp+n, &tmp_be32, 4); n += 4;
608 skb_put(skb, 3 + value->len);
609 fp[n++] = value->type;
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;
616 IRDA_DEBUG( 3, "%s: sending IAS_MISSING\n", __FUNCTION__);
618 fp[n++] = value->type;
621 IRDA_DEBUG(0, "%s(), type not implemented!\n", __FUNCTION__);
624 iriap_do_r_connect_event(self, IAP_CALL_RESPONSE, skb);
628 * Function iriap_getvaluebyclass_indication (self, skb)
630 * getvaluebyclass is requested from peer LM-IAS
633 void iriap_getvaluebyclass_indication(struct iriap_cb *self,
636 struct ias_object *obj;
637 struct ias_attrib *attrib;
640 char name[IAS_MAX_CLASSNAME + 1]; /* 60 bytes */
641 char attr[IAS_MAX_ATTRIBNAME + 1]; /* 60 bytes */
645 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
647 ASSERT(self != NULL, return;);
648 ASSERT(self->magic == IAS_MAGIC, return;);
649 ASSERT(skb != NULL, return;);
655 memcpy(name, fp+n, name_len); n+=name_len;
656 name[name_len] = '\0';
659 memcpy(attr, fp+n, attr_len); n+=attr_len;
660 attr[attr_len] = '\0';
662 /* We do not need the buffer anymore */
665 IRDA_DEBUG(4, "LM-IAS: Looking up %s: %s\n", name, attr);
666 obj = irias_find_object(name);
669 IRDA_DEBUG(2, "LM-IAS: Object %s not found\n", name);
670 iriap_getvaluebyclass_response(self, 0x1235, IAS_CLASS_UNKNOWN,
674 IRDA_DEBUG(4, "LM-IAS: found %s, id=%d\n", obj->name, obj->id);
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);
684 /* We have a match; send the value. */
685 iriap_getvaluebyclass_response(self, obj->id, IAS_SUCCESS,
692 * Function iriap_send_ack (void)
697 void iriap_send_ack(struct iriap_cb *self)
702 IRDA_DEBUG(2, "%s()\n", __FUNCTION__);
704 ASSERT(self != NULL, return;);
705 ASSERT(self->magic == IAS_MAGIC, return;);
707 skb = dev_alloc_skb(64);
711 /* Reserve space for MUX and LAP header */
712 skb_reserve(skb, self->max_header_size);
717 frame[0] = IAP_LST | IAP_ACK | self->operation;
719 irlmp_data_request(self->lsap, skb);
722 void iriap_connect_request(struct iriap_cb *self)
726 ASSERT(self != NULL, return;);
727 ASSERT(self->magic == IAS_MAGIC, return;);
729 ret = irlmp_connect_request(self->lsap, LSAP_IAS,
730 self->saddr, self->daddr,
733 IRDA_DEBUG(0, "%s(), connect failed!\n", __FUNCTION__);
734 self->confirm(IAS_DISCONNECT, 0, NULL, self->priv);
739 * Function iriap_connect_confirm (handle, skb)
741 * LSAP connection confirmed!
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)
749 struct iriap_cb *self;
751 self = (struct iriap_cb *) instance;
753 ASSERT(self != NULL, return;);
754 ASSERT(self->magic == IAS_MAGIC, return;);
755 ASSERT(userdata != NULL, return;);
757 self->max_data_size = max_seg_size;
758 self->max_header_size = max_header_size;
760 del_timer(&self->watchdog_timer);
762 iriap_do_client_event(self, IAP_LM_CONNECT_CONFIRM, userdata);
766 * Function iriap_connect_indication ( handle, skb)
768 * Remote LM-IAS is requesting connection
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)
776 struct iriap_cb *self, *new;
778 IRDA_DEBUG(1, "%s()\n", __FUNCTION__);
780 self = (struct iriap_cb *) instance;
782 ASSERT(self != NULL, return;);
783 ASSERT(self->magic == IAS_MAGIC, return;);
785 /* Start new server */
786 new = iriap_open(LSAP_IAS, IAS_SERVER, NULL, NULL);
788 IRDA_DEBUG(0, "%s(), open failed\n", __FUNCTION__);
789 dev_kfree_skb(userdata);
793 /* Now attach up the new "socket" */
794 new->lsap = irlmp_dup(self->lsap, new);
796 IRDA_DEBUG(0, "%s(), dup failed!\n", __FUNCTION__);
800 new->max_data_size = max_seg_size;
801 new->max_header_size = max_header_size;
803 /* Clean up the original one to keep it in listen state */
804 irlmp_listen(self->lsap);
806 iriap_do_server_event(new, IAP_LM_CONNECT_INDICATION, userdata);
810 * Function iriap_data_indication (handle, skb)
812 * Receives data from connection identified by handle from IrLMP
815 static int iriap_data_indication(void *instance, void *sap,
818 struct iriap_cb *self;
822 IRDA_DEBUG(3, "%s()\n", __FUNCTION__);
824 self = (struct iriap_cb *) instance;
826 ASSERT(self != NULL, return 0;);
827 ASSERT(self->magic == IAS_MAGIC, return 0;);
829 ASSERT(skb != NULL, return 0;);
833 if (self->mode == IAS_SERVER) {
835 IRDA_DEBUG(4, "%s(), Calling server!\n", __FUNCTION__);
836 iriap_do_r_connect_event(self, IAP_RECV_F_LST, skb);
841 if (~opcode & IAP_LST) {
842 WARNING("%s(), IrIAS multiframe commands or "
843 "results is not implemented yet!\n", __FUNCTION__);
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__);
855 opcode &= ~IAP_LST; /* Mask away LST bit */
859 IRDA_DEBUG(0, "IrLMP GetInfoBaseDetails not implemented!\n");
862 case GET_VALUE_BY_CLASS:
863 iriap_do_call_event(self, IAP_RECV_F_LST, NULL);
867 iriap_getvaluebyclass_confirm(self, skb);
869 case IAS_CLASS_UNKNOWN:
870 IRDA_DEBUG(1, "%s(), No such class!\n", __FUNCTION__);
871 /* Finished, close connection! */
872 iriap_disconnect_request(self);
875 * Warning, the client might close us, so remember
876 * no to use self anymore after calling confirm
879 self->confirm(IAS_CLASS_UNKNOWN, 0, NULL,
883 case IAS_ATTRIB_UNKNOWN:
884 IRDA_DEBUG(1, "%s(), No such attribute!\n", __FUNCTION__);
885 /* Finished, close connection! */
886 iriap_disconnect_request(self);
889 * Warning, the client might close us, so remember
890 * no to use self anymore after calling confirm
893 self->confirm(IAS_ATTRIB_UNKNOWN, 0, NULL,
900 IRDA_DEBUG(0, "%s(), Unknown op-code: %02x\n", __FUNCTION__, opcode);
908 * Function iriap_call_indication (self, skb)
910 * Received call to server from peer LM-IAS
913 void iriap_call_indication(struct iriap_cb *self, struct sk_buff *skb)
918 IRDA_DEBUG(4, "%s()\n", __FUNCTION__);
920 ASSERT(self != NULL, return;);
921 ASSERT(self->magic == IAS_MAGIC, return;);
922 ASSERT(skb != NULL, return;);
927 if (~opcode & 0x80) {
928 WARNING("%s(), IrIAS multiframe commands or results"
929 "is not implemented yet!\n", __FUNCTION__);
932 opcode &= 0x7f; /* Mask away LST bit */
936 WARNING("%s(), GetInfoBaseDetails not implemented yet!\n",
939 case GET_VALUE_BY_CLASS:
940 iriap_getvaluebyclass_indication(self, skb);
946 * Function iriap_watchdog_timer_expired (data)
948 * Query has taken to long time, so abort
951 void iriap_watchdog_timer_expired(void *data)
953 struct iriap_cb *self = (struct iriap_cb *) data;
955 ASSERT(self != NULL, return;);
956 ASSERT(self->magic == IAS_MAGIC, return;);
958 /* iriap_close(self); */
961 #ifdef CONFIG_PROC_FS
963 static char *ias_value_types[] = {
970 int irias_proc_read(char *buf, char **start, off_t offset, int len)
972 struct ias_object *obj;
973 struct ias_attrib *attrib;
976 ASSERT( objects != NULL, return 0;);
983 len += sprintf(buf+len, "LM-IAS Objects:\n");
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;);
990 len += sprintf(buf+len, "name: %s, ", obj->name);
991 len += sprintf(buf+len, "id=%d", obj->id);
992 len += sprintf(buf+len, "\n");
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;);
1000 len += sprintf(buf+len, " - Attribute name: \"%s\", ",
1002 len += sprintf(buf+len, "value[%s]: ",
1003 ias_value_types[attrib->value->type]);
1005 switch (attrib->value->type) {
1007 len += sprintf(buf+len, "%d\n",
1008 attrib->value->t.integer);
1011 len += sprintf(buf+len, "\"%s\"\n",
1012 attrib->value->t.string);
1015 len += sprintf(buf+len, "octet sequence (%d bytes)\n", attrib->value->len);
1018 len += sprintf(buf+len, "missing\n");
1021 IRDA_DEBUG(0, "%s(), Unknown value type!\n", __FUNCTION__);
1024 len += sprintf(buf+len, "\n");
1026 attrib = (struct ias_attrib *)
1027 hashbin_get_next(obj->attribs);
1029 obj = (struct ias_object *) hashbin_get_next(objects);
1031 restore_flags(flags);
1036 #endif /* PROC_FS */