1 #include "e_ofono_private.h"
6 * Maximum size for elements hash key.
8 * The elements hash key is contructed by concatenating the object path and the
9 * interface for the element (with a colon separating the two strings). D-Bus
10 * interfaces have a maximum size of 255 but object paths have unlimited size.
11 * We're assuming a maximum key size of 4k here, but this might need to be
12 * increased if oFono object paths grows bigger than that.
14 #define MAX_KEY_SIZE 4096
15 static Eina_Hash *elements = NULL;
17 typedef struct _E_Ofono_Element_Pending E_Ofono_Element_Pending;
18 typedef struct _E_Ofono_Element_Call_Data E_Ofono_Element_Call_Data;
19 typedef struct _E_Ofono_Element_Property E_Ofono_Element_Property;
20 typedef struct _E_Ofono_Element_Listener E_Ofono_Element_Listener;
21 typedef struct _E_Ofono_Element_Dict_Entry E_Ofono_Element_Dict_Entry;
23 struct _E_Ofono_Element_Pending
26 DBusPendingCall *pending;
28 E_DBus_Method_Return_Cb user_cb;
32 struct _E_Ofono_Element_Call_Data
34 E_Ofono_Element *element;
35 E_DBus_Method_Return_Cb cb;
36 E_Ofono_Element_Pending *pending;
40 struct _E_Ofono_Element_Property
57 struct _E_Ofono_Element_Dict_Entry
71 struct _E_Ofono_Element_Listener
74 void (*cb)(void *data, const E_Ofono_Element *element);
76 void (*free_data)(void *data);
80 _e_ofono_element_event_no_free(void *data __UNUSED__, void *ev)
82 E_Ofono_Element *element = ev;
83 e_ofono_element_unref(element);
87 e_ofono_element_event_add(int event_type, E_Ofono_Element *element)
89 e_ofono_element_ref(element);
91 (event_type, element, _e_ofono_element_event_no_free, element);
95 e_ofono_element_call_dispatch_and_free(void *d, DBusMessage *msg, DBusError *err)
97 E_Ofono_Element_Call_Data *data = d;
98 E_Ofono_Element_Pending *pending;
100 pending = data->pending;
101 pending->pending = NULL;
104 data->cb(data->element, msg, err);
106 if (pending->user_cb)
107 pending->user_cb(pending->user_data, msg, err);
109 pending->data = NULL;
110 *data->p_list = eina_inlist_remove(*data->p_list, EINA_INLIST_GET(pending));
116 e_ofono_element_pending_cancel_and_free(Eina_Inlist **pending)
120 E_Ofono_Element_Pending *p = (E_Ofono_Element_Pending *)*pending;
123 dbus_pending_call_cancel(p->pending);
125 dbus_error_init(&err);
126 dbus_set_error(&err, "Canceled", "Pending method call was canceled.");
127 e_ofono_element_call_dispatch_and_free(p->data, NULL, &err);
128 dbus_error_free(&err);
133 e_ofono_element_listener_add(E_Ofono_Element *element, void (*cb)(void *data, const E_Ofono_Element *element), const void *data, void (*free_data)(void *data))
135 E_Ofono_Element_Listener *l;
139 ERR("safety check failed: element == NULL");
145 ERR("safety check failed: cb == NULL");
149 l = malloc(sizeof(*l));
152 ERR("could not allocate E_Ofono_Element_Listener");
157 l->data = (void *)data;
158 l->free_data = free_data;
160 element->_listeners = eina_inlist_append
161 (element->_listeners, EINA_INLIST_GET(l));
167 free_data((void *)data);
171 e_ofono_element_listener_del(E_Ofono_Element *element, void (*cb)(void *data, const E_Ofono_Element *element), const void *data)
173 E_Ofono_Element_Listener *l;
175 EINA_SAFETY_ON_NULL_RETURN(element);
176 EINA_SAFETY_ON_NULL_RETURN(cb);
178 EINA_INLIST_FOREACH(element->_listeners, l)
179 if ((l->cb == cb) && (l->data == data))
181 element->_listeners = eina_inlist_remove
182 (element->_listeners, EINA_INLIST_GET(l));
184 l->free_data(l->data);
192 _e_ofono_element_listeners_call_do(E_Ofono_Element *element)
194 E_Ofono_Element_Listener *l, **shadow;
195 unsigned int i, count;
197 /* NB: iterate on a copy in order to allow listeners to be deleted
198 * from callbacks. number of listeners should be small, so the
199 * following should do fine.
201 count = eina_inlist_count(element->_listeners);
205 shadow = alloca(sizeof(*shadow) * count);
210 EINA_INLIST_FOREACH(element->_listeners, l)
213 for (i = 0; i < count; i++)
214 shadow[i]->cb(shadow[i]->data, element);
217 e_ofono_element_event_add(E_OFONO_EVENT_ELEMENT_UPDATED, element);
221 _e_ofono_element_listeners_call_idler(void *data)
223 E_Ofono_Element *element = data;
224 _e_ofono_element_listeners_call_do(element);
225 element->_idler.changed = NULL;
226 return ECORE_CALLBACK_CANCEL;
230 _e_ofono_element_listeners_call(E_Ofono_Element *element)
232 if (element->_idler.changed)
235 element->_idler.changed = ecore_idler_add
236 (_e_ofono_element_listeners_call_idler, element);
239 /***********************************************************************
241 ***********************************************************************/
244 _e_ofono_element_dict_entry_free(E_Ofono_Element_Dict_Entry *entry)
248 case DBUS_TYPE_BOOLEAN:
250 case DBUS_TYPE_UINT16:
251 case DBUS_TYPE_UINT32:
254 case DBUS_TYPE_OBJECT_PATH:
255 eina_stringshare_del(entry->value.path);
258 case DBUS_TYPE_STRING:
259 eina_stringshare_del(entry->value.str);
263 ERR("don't know how to free dict entry '%s' of type %c (%d)",
264 entry->name, entry->type, entry->type);
267 eina_stringshare_del(entry->name);
271 static E_Ofono_Element_Dict_Entry *
272 _e_ofono_element_dict_entry_new(DBusMessageIter *itr)
274 E_Ofono_Element_Dict_Entry *entry;
275 DBusMessageIter e_itr, v_itr;
277 const char *key = NULL;
280 dbus_message_iter_recurse(itr, &e_itr);
282 t = dbus_message_iter_get_arg_type(&e_itr);
283 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
285 ERR("invalid format for dict entry. first type not a string: %c (%d)",
290 dbus_message_iter_get_basic(&e_itr, &key);
293 ERR("invalid format for dict entry. no key.");
297 dbus_message_iter_next(&e_itr);
298 t = dbus_message_iter_get_arg_type(&e_itr);
299 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
301 ERR("invalid format for dict entry '%s'. "
302 "second type not a variant: %c (%d)",
307 dbus_message_iter_recurse(&e_itr, &v_itr);
309 t = dbus_message_iter_get_arg_type(&v_itr);
310 if ((t == DBUS_TYPE_INVALID) || (t == DBUS_TYPE_ARRAY))
312 ERR("invalid type for dict value for entry '%s': %c (%d)",
317 entry = calloc(1, sizeof(*entry));
320 ERR("could not allocate memory for dict entry.");
324 dbus_message_iter_get_basic(&v_itr, &value);
327 case DBUS_TYPE_BOOLEAN:
328 entry->value.boolean = (Eina_Bool)(long)value;
332 entry->value.byte = (unsigned char)(long)value;
335 case DBUS_TYPE_UINT16:
336 entry->value.u16 = (unsigned short)(long)value;
339 case DBUS_TYPE_UINT32:
340 entry->value.u32 = (unsigned int)(long)value;
343 case DBUS_TYPE_STRING:
344 entry->value.str = eina_stringshare_add(value);
347 case DBUS_TYPE_OBJECT_PATH:
348 entry->value.path = eina_stringshare_add(value);
352 ERR("don't know how to create dict entry '%s' for of type %c (%d)",
358 entry->name = eina_stringshare_add(key);
363 static E_Ofono_Element_Dict_Entry *
364 _e_ofono_element_array_dict_find_stringshared(const E_Ofono_Array *array, const char *key)
366 E_Ofono_Element_Dict_Entry *entry;
367 Eina_Array_Iterator iterator;
370 EINA_ARRAY_ITER_NEXT(array->array, i, entry, iterator)
371 if (entry->name == key)
378 _e_ofono_element_array_free(E_Ofono_Array *array, E_Ofono_Array *new __UNUSED__)
380 Eina_Array_Iterator iterator;
389 case DBUS_TYPE_BOOLEAN:
391 case DBUS_TYPE_UINT16:
392 case DBUS_TYPE_UINT32:
395 case DBUS_TYPE_OBJECT_PATH:
396 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
397 eina_stringshare_del(item);
400 case DBUS_TYPE_STRING:
401 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
402 eina_stringshare_del(item);
405 case DBUS_TYPE_DICT_ENTRY:
406 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
407 _e_ofono_element_dict_entry_free(item);
411 ERR("don't know how to free array of values of type %c (%d)",
412 array->type, array->type);
415 eina_array_free(array->array);
420 _e_ofono_element_property_value_free(E_Ofono_Element_Property *property)
422 switch (property->type)
427 case DBUS_TYPE_BOOLEAN:
429 case DBUS_TYPE_UINT16:
430 case DBUS_TYPE_UINT32:
433 case DBUS_TYPE_STRING:
434 eina_stringshare_del(property->value.str);
437 case DBUS_TYPE_OBJECT_PATH:
438 eina_stringshare_del(property->value.path);
441 case DBUS_TYPE_ARRAY:
442 _e_ofono_element_array_free(property->value.array, NULL);
446 ERR("don't know how to free value of property type %c (%d)",
447 property->type, property->type);
452 _e_ofono_element_get_interface(const char *key)
454 const char *interface = NULL, *tail;
463 if (strcmp(tail, "odems") == 0)
464 interface = e_ofono_iface_modem;
473 ERR("failed to find interface for property \"%s\"", key);
478 static E_Ofono_Element *
479 _e_ofono_element_item_register(const char *key, const char *item)
481 E_Ofono_Element *element;
482 const char *interface;
484 interface = _e_ofono_element_get_interface(key);
488 element = e_ofono_element_register(item, interface);
489 if ((element) && (!e_ofono_element_properties_sync(element)))
490 WRN("could not get properties of %s", element->path);
495 /* Match 2 arrays to find which are new and which are old elements
496 * For new elements, register them under prop_name property
497 * For old elements, unregister them, sending proper DEL event
500 _e_ofono_element_array_match(E_Ofono_Array *old, E_Ofono_Array *new, const char *prop_name, E_Ofono_Element *element)
502 Eina_List *deleted = NULL;
503 Eina_Array_Iterator iter_old, iter_new;
504 unsigned int i_old = 0, i_new = 0;
505 void *item_old = NULL, *item_new;
508 Eina_Bool interfaces = EINA_FALSE;
513 if ((old->type != DBUS_TYPE_OBJECT_PATH) &&
514 (old->type != DBUS_TYPE_STRING))
517 /* is this a list of interfaces? */
518 interfaces = !strcmp(prop_name, "Interfaces");
520 if ((!new) || (!new->array) || eina_array_count_get(new->array) == 0)
522 if ((!old) || (!old->array) || eina_array_count_get(old->array) == 0)
528 iter_old = old->array->data;
529 goto out_remove_remaining;
533 iter_new = new->array->data;
534 item_new = *iter_new;
535 EINA_ARRAY_ITER_NEXT(old->array, i_old, item_old, iter_old)
537 if (item_old == item_new)
540 if (i_new >= eina_array_count_get(new->array))
547 item_new = *iter_new;
551 deleted = eina_list_append(deleted, item_old);
555 for(; i_new < eina_array_count_get(new->array); iter_new++, i_new++)
557 Eina_Bool found = EINA_FALSE;
558 item_new = *iter_new;
562 EINA_LIST_FOREACH(deleted, l, data)
564 if (data == item_new)
566 deleted = eina_list_remove_list(deleted, l);
573 E_Ofono_Element *e = NULL;
576 e = e_ofono_element_register(item_new, element->path);
578 e = _e_ofono_element_item_register(prop_name, item_new);
581 DBG("Add element %s (%s)\n", e->path, e->interface);
585 /* everybody after i_old on old->array + everybody from deleted list
588 EINA_LIST_FREE(deleted, data)
592 e = e_ofono_element_get(element->path, item_old);
594 e = e_ofono_element_get(data,
595 _e_ofono_element_get_interface(prop_name));
599 e_ofono_element_unregister(e);
600 DBG("Deleted element %s %s\n", e->path, e->interface);
604 out_remove_remaining:
605 for(; i_old < eina_array_count_get(old->array); iter_old++, i_old++)
608 item_old = *iter_old;
613 e = e_ofono_element_get(element->path, item_old);
615 e = e_ofono_element_get(item_old,
616 _e_ofono_element_get_interface(prop_name));
620 e_ofono_element_unregister(e);
621 DBG("Deleted element %s %s\n", e->path, e->interface);
627 _e_ofono_element_property_update(E_Ofono_Element_Property *property, int type, void *data, E_Ofono_Element *element)
629 Eina_Bool changed = EINA_FALSE;
631 if ((type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) && data)
632 data = (char *)eina_stringshare_add(data);
634 if (property->type != type)
637 DBG("property type changed from '%c' to '%c'",
638 property->type, type);
640 _e_ofono_element_property_value_free(property);
641 memset(&property->value, 0, sizeof(property->value));
642 property->type = type;
648 case DBUS_TYPE_BOOLEAN:
649 if (changed || property->value.boolean != (Eina_Bool)(long)data)
651 property->value.boolean = (Eina_Bool)(long)data;
658 if (changed || property->value.byte != (unsigned char)(long)data)
660 property->value.byte = (unsigned char)(long)data;
666 case DBUS_TYPE_UINT16:
667 if (changed || property->value.u16 != (unsigned short)(long)data)
669 property->value.u16 = (unsigned short)(long)data;
675 case DBUS_TYPE_UINT32:
676 if (changed || property->value.u32 != (unsigned int)(long)data)
678 property->value.u32 = (unsigned int)(long)data;
684 case DBUS_TYPE_STRING:
687 property->value.str = data;
691 if (property->value.str)
692 eina_stringshare_del(property->value.str);
694 if (property->value.str != data)
696 property->value.str = data;
703 case DBUS_TYPE_OBJECT_PATH:
706 property->value.path = data;
710 if (property->value.path)
711 eina_stringshare_del(property->value.path);
713 if (property->value.path != data)
715 property->value.path = data;
722 case DBUS_TYPE_ARRAY:
724 if (property->value.array)
726 _e_ofono_element_array_match(property->value.array, data,
727 property->name, element);
728 _e_ofono_element_array_free(property->value.array, data);
731 property->value.array = data;
736 ERR("don't know how to update property type %c (%d)", type, type);
742 static E_Ofono_Element_Property *
743 _e_ofono_element_property_new(const char *name, int type, void *data, E_Ofono_Element *element)
745 E_Ofono_Element_Property *property;
747 property = calloc(1, sizeof(*property));
750 eina_stringshare_del(name);
751 ERR("could not allocate property: %s", strerror(errno));
755 property->name = name;
756 _e_ofono_element_property_update(property, type, data, element);
761 _e_ofono_element_property_free(E_Ofono_Element_Property *property)
763 _e_ofono_element_property_value_free(property);
764 eina_stringshare_del(property->name);
768 /***********************************************************************
770 ***********************************************************************/
772 e_ofono_element_bytes_array_get_stringshared(const E_Ofono_Element *element, const char *property, unsigned int *count)
774 Eina_Array_Iterator iterator;
775 E_Ofono_Array *array;
776 unsigned char *ret, *p;
780 EINA_SAFETY_ON_NULL_RETURN_VAL(element, NULL);
781 EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
782 EINA_SAFETY_ON_NULL_RETURN_VAL(count, NULL);
786 if (!e_ofono_element_property_get_stringshared
787 (element, property, NULL, &array))
790 if ((!array) || (!(array->array)))
793 *count = eina_array_count_get(array->array);
794 ret = malloc(*count * sizeof(unsigned char));
797 ERR("could not allocate return array of %d bytes: %s",
798 *count, strerror(errno));
804 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
806 *p = (unsigned char)(long)item;
813 e_ofono_element_objects_array_get_stringshared(const E_Ofono_Element *element, const char *property, unsigned int *count, E_Ofono_Element ***p_elements)
815 E_Ofono_Element **ret, **p;
816 Eina_Array_Iterator iterator;
817 E_Ofono_Array *array;
822 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
823 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
824 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
825 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
830 if (!e_ofono_element_property_get_stringshared
831 (element, property, &type, &array))
834 if (type != DBUS_TYPE_ARRAY)
836 ERR("property %s is not an array!", property);
840 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
843 if (array->type != DBUS_TYPE_OBJECT_PATH)
845 ERR("property %s is not an array of object paths!", property);
849 *count = eina_array_count_get(array->array);
850 ret = malloc(*count * sizeof(E_Ofono_Element *));
853 ERR("could not allocate return array of %d elements: %s",
854 *count, strerror(errno));
861 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
863 E_Ofono_Element *e = e_ofono_element_get(item, property);
875 /* strings are just pointers (references), no strdup or stringshare_add/ref */
877 e_ofono_element_strings_array_get_stringshared(const E_Ofono_Element *element, const char *property, unsigned int *count, const char ***strings)
879 const char **ret, **p;
880 Eina_Array_Iterator iterator;
881 E_Ofono_Array *array;
886 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
887 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
888 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
889 EINA_SAFETY_ON_NULL_RETURN_VAL(strings, EINA_FALSE);
894 if (!e_ofono_element_property_get_stringshared
895 (element, property, &type, &array))
898 if (type != DBUS_TYPE_ARRAY)
900 ERR("property %s is not an array!", property);
904 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
907 if (array->type != DBUS_TYPE_STRING)
909 ERR("property %s is not an array of strings!", property);
913 *count = eina_array_count_get(array->array);
914 ret = malloc(*count * sizeof(char *));
917 ERR("could not allocate return array of %d strings: %s",
918 *count, strerror(errno));
925 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
939 _e_ofono_element_array_print(FILE *fp, E_Ofono_Array *array)
941 Eina_Array_Iterator iterator;
950 case DBUS_TYPE_OBJECT_PATH:
951 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
952 fprintf(fp, "\"%s\", ", (const char *)item);
955 case DBUS_TYPE_STRING:
956 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
957 fprintf(fp, "\"%s\", ", (const char *)item);
961 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
962 fprintf(fp, "%#02hhx (\"%c\"), ", (unsigned char)(long)item,
963 (unsigned char)(long)item);
966 case DBUS_TYPE_UINT16:
967 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
968 fprintf(fp, "%#04hx (%hu), ", (unsigned short)(long)item,
969 (unsigned short)(long)item);
972 case DBUS_TYPE_UINT32:
973 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
974 fprintf(fp, "%#08x (%u), ", (unsigned int)(long)item,
975 (unsigned int)(long)item);
978 case DBUS_TYPE_DICT_ENTRY:
980 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
982 E_Ofono_Element_Dict_Entry *entry = item;
983 fprintf(fp, "%s: ", entry->name);
986 case DBUS_TYPE_OBJECT_PATH:
987 fprintf(fp, "\"%s\", ", entry->value.path);
990 case DBUS_TYPE_STRING:
991 fprintf(fp, "\"%s\", ", entry->value.str);
995 fprintf(fp, "%#02hhx (\"%c\"), ",
996 entry->value.byte, entry->value.byte);
999 case DBUS_TYPE_UINT16:
1000 fprintf(fp, "%#04hx (%hu), ",
1001 entry->value.u16, entry->value.u16);
1004 case DBUS_TYPE_UINT32:
1005 fprintf(fp, "%#08x (%u), ",
1006 entry->value.u32, entry->value.u32);
1010 fprintf(fp, "<UNKNOWN TYPE '%c'>", entry->type);
1017 fprintf(fp, "<UNKNOWN ARRAY TYPE '%c'>", array->type);
1022 * Print element to file descriptor.
1025 e_ofono_element_print(FILE *fp, const E_Ofono_Element *element)
1027 const E_Ofono_Element_Property *p;
1029 EINA_SAFETY_ON_NULL_RETURN(fp);
1032 fputs("Error: no element to print\n", fp);
1037 "Element %p: %s [%s]\n"
1039 element, element->path, element->interface);
1041 EINA_INLIST_FOREACH(element->props, p)
1043 fprintf(fp, "\t\t%s (%c) = ", p->name, p->type);
1047 case DBUS_TYPE_STRING:
1048 fprintf(fp, "\"%s\"", p->value.str);
1051 case DBUS_TYPE_OBJECT_PATH:
1052 fprintf(fp, "\"%s\"", p->value.path);
1055 case DBUS_TYPE_BOOLEAN:
1056 fprintf(fp, "%hhu", p->value.boolean);
1059 case DBUS_TYPE_BYTE:
1060 fprintf(fp, "%#02hhx (%d), ", p->value.byte, p->value.byte);
1063 case DBUS_TYPE_UINT16:
1064 fprintf(fp, "%hu", p->value.u16);
1067 case DBUS_TYPE_UINT32:
1068 fprintf(fp, "%u", p->value.u32);
1071 case DBUS_TYPE_ARRAY:
1072 _e_ofono_element_array_print(fp, p->value.array);
1076 fputs("don't know how to print type", fp);
1083 static E_Ofono_Element *
1084 e_ofono_element_new(const char *path, const char *interface)
1086 E_Ofono_Element *element;
1088 element = calloc(1, sizeof(*element));
1091 ERR("could not allocate element: %s", strerror(errno));
1095 element->path = eina_stringshare_add(path);
1096 element->interface = eina_stringshare_ref(interface);
1097 element->_references = 1;
1103 e_ofono_element_extra_properties_free(E_Ofono_Element *element)
1105 while (element->props)
1107 E_Ofono_Element_Property *prop;
1108 prop = (E_Ofono_Element_Property *)element->props;
1109 element->props = element->props->next;
1110 _e_ofono_element_property_free(prop);
1115 e_ofono_element_free(E_Ofono_Element *element)
1117 if (element->_idler.changed)
1118 ecore_idler_del(element->_idler.changed);
1120 while (element->_listeners)
1122 E_Ofono_Element_Listener *l = (void *)element->_listeners;
1123 element->_listeners = eina_inlist_remove
1124 (element->_listeners, element->_listeners);
1127 l->free_data(l->data);
1132 e_ofono_element_pending_cancel_and_free(&element->_pending.properties_get);
1133 e_ofono_element_pending_cancel_and_free(&element->_pending.property_set);
1134 e_ofono_element_pending_cancel_and_free(&element->_pending.send_sms);
1136 e_ofono_element_extra_properties_free(element);
1137 eina_stringshare_del(element->interface);
1138 eina_stringshare_del(element->path);
1143 * Add reference to element.
1146 e_ofono_element_ref(E_Ofono_Element *element)
1148 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1149 return ++element->_references;
1153 * Remove reference from element.
1155 * If reference count drops to 0 element will be freed.
1158 e_ofono_element_unref(E_Ofono_Element *element)
1161 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1163 i = --element->_references;
1165 e_ofono_element_free(element);
1167 ERR("element %p references %d < 0", element, i);
1173 * Send message with callbacks set to work with ofono elements.
1175 * If this call fails (returns 0), pending callbacks will not be called,
1176 * not even with error messages.
1178 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1181 e_ofono_element_message_send(E_Ofono_Element *element, const char *method_name, const char *interface, E_DBus_Method_Return_Cb cb, DBusMessage *msg, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1183 E_Ofono_Element_Call_Data *data;
1184 E_Ofono_Element_Pending *p;
1186 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1187 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1188 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1189 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
1191 interface = interface ? : element->interface;
1193 data = malloc(sizeof(*data));
1196 ERR("could not alloc e_ofono_element_call_data: %s",
1198 dbus_message_unref(msg);
1202 p = malloc(sizeof(*p));
1205 ERR("could not alloc E_Ofono_Element_Pending: %s",
1208 dbus_message_unref(msg);
1212 data->element = element;
1215 data->p_list = pending;
1216 p->user_cb = user_cb;
1217 p->user_data = (void *)user_data;
1219 p->pending = e_dbus_message_send
1220 (e_ofono_conn, msg, e_ofono_element_call_dispatch_and_free, -1, data);
1221 dbus_message_unref(msg);
1225 *pending = eina_inlist_append(*pending, EINA_INLIST_GET(p));
1229 ERR("failed to call %s (obj=%s, path=%s, iface=%s)",
1230 method_name, e_ofono_system_bus_name_get(),
1231 element->path, interface);
1238 e_ofono_element_call_full(E_Ofono_Element *element, const char *method_name, const char *interface, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1242 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1243 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1244 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1246 interface = interface ? : element->interface;
1248 msg = dbus_message_new_method_call
1249 (e_ofono_system_bus_name_get(), element->path, interface,
1252 return e_ofono_element_message_send
1253 (element, method_name, interface, cb, msg, pending, user_cb, user_data);
1257 _e_ofono_element_property_value_add(E_Ofono_Element *element, const char *name, int type, void *value)
1259 E_Ofono_Element_Property *p;
1261 name = eina_stringshare_add(name);
1262 EINA_INLIST_FOREACH(element->props, p)
1264 if (p->name == name)
1266 eina_stringshare_del(name);
1267 return _e_ofono_element_property_update(p, type, value, element);
1271 p = _e_ofono_element_property_new(name, type, value, element);
1274 ERR("could not create property %s (%c)", name, type);
1278 element->props = eina_inlist_append(element->props, EINA_INLIST_GET(p));
1282 static E_Ofono_Array *
1283 _e_ofono_element_iter_get_array(DBusMessageIter *itr, const char *key)
1285 E_Ofono_Array *array;
1286 DBusMessageIter e_itr;
1288 array = malloc(sizeof(E_Ofono_Array));
1291 ERR("could not create new e_ofono array.");
1295 array->array = eina_array_new(16);
1296 if (!(array->array))
1298 ERR("could not create new eina array.");
1303 dbus_message_iter_recurse(itr, &e_itr);
1304 array->type = dbus_message_iter_get_arg_type(&e_itr);
1305 if (array->type == DBUS_TYPE_INVALID)
1307 DBG("array %s is of type 'invalid' (empty?)", key);
1308 eina_array_free(array->array);
1315 switch (array->type)
1317 case DBUS_TYPE_OBJECT_PATH:
1321 dbus_message_iter_get_basic(&e_itr, &path);
1322 path = eina_stringshare_add(path);
1323 eina_array_push(array->array, path);
1324 _e_ofono_element_item_register(key, path);
1328 case DBUS_TYPE_STRING:
1332 dbus_message_iter_get_basic(&e_itr, &str);
1333 str = eina_stringshare_add(str);
1334 eina_array_push(array->array, str);
1338 case DBUS_TYPE_BYTE:
1341 dbus_message_iter_get_basic(&e_itr, &byte);
1342 eina_array_push(array->array, (void *)(long)byte);
1346 case DBUS_TYPE_DICT_ENTRY:
1348 E_Ofono_Element_Dict_Entry *entry;
1349 entry = _e_ofono_element_dict_entry_new(&e_itr);
1351 eina_array_push(array->array, entry);
1356 ERR("don't know how to build array '%s' of type %c (%d)",
1357 key, array->type, array->type);
1358 eina_array_free(array->array);
1363 while (dbus_message_iter_next(&e_itr));
1368 _e_ofono_element_get_properties_callback(void *user_data, DBusMessage *msg, DBusError *err)
1370 E_Ofono_Element *element = user_data;
1371 DBusMessageIter itr, s_itr;
1374 DBG("get_properties msg=%p", msg);
1376 if (!_dbus_callback_check_and_init(msg, &itr, err))
1379 t = dbus_message_iter_get_arg_type(&itr);
1380 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1384 dbus_message_iter_recurse(&itr, &s_itr);
1387 DBusMessageIter e_itr, v_itr;
1392 t = dbus_message_iter_get_arg_type(&s_itr);
1393 if (!_dbus_iter_type_check(t, DBUS_TYPE_DICT_ENTRY))
1396 dbus_message_iter_recurse(&s_itr, &e_itr);
1398 t = dbus_message_iter_get_arg_type(&e_itr);
1399 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
1402 dbus_message_iter_get_basic(&e_itr, &key);
1403 dbus_message_iter_next(&e_itr);
1404 t = dbus_message_iter_get_arg_type(&e_itr);
1405 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
1408 dbus_message_iter_recurse(&e_itr, &v_itr);
1409 t = dbus_message_iter_get_arg_type(&v_itr);
1410 if (t == DBUS_TYPE_ARRAY)
1412 value = _e_ofono_element_iter_get_array(&v_itr, key);
1414 else if (t != DBUS_TYPE_INVALID)
1416 dbus_message_iter_get_basic(&v_itr, &value);
1420 ERR("property has invalid type %s", key);
1424 r = _e_ofono_element_property_value_add(element, key, t, value);
1427 ERR("failed to add property value %s (%c)", key, t);
1431 INF("property value changed %s (%c)", key, t);
1433 if ((strcmp(key, "Interfaces") == 0) && value)
1436 Eina_Array_Iterator iterator;
1440 EINA_ARRAY_ITER_NEXT(((E_Ofono_Array *)value)->array, i,
1441 interface, iterator)
1443 DBG("Found interface %s on %s", interface, element->path);
1444 e = e_ofono_element_register(element->path, interface);
1445 if ((e) && (!e_ofono_element_properties_sync(e)))
1446 WRN("could not get properties of %s", e->path);
1451 while (dbus_message_iter_next(&s_itr));
1454 _e_ofono_element_listeners_call(element);
1458 * Sync element properties with server.
1460 * Call method GetProperties() at the given element on server in order to sync
1463 * @param element to call method on server.
1464 * @param cb function to call when server replies or some error happens.
1465 * @param data data to give to cb when it is called.
1467 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1470 e_ofono_element_sync_properties_full(E_Ofono_Element *element, E_DBus_Method_Return_Cb cb, const void *data)
1472 const char name[] = "GetProperties";
1474 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1475 return e_ofono_element_call_full
1476 (element, name, element->interface,
1477 _e_ofono_element_get_properties_callback,
1478 &element->_pending.properties_get, cb, data);
1482 * Sync element properties with server, simple version.
1484 * Call method GetProperties() at the given element on server in order to sync
1485 * them. This is the simple version and there is no check of server reply
1488 * @param element to call method on server.
1490 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1493 e_ofono_element_properties_sync(E_Ofono_Element *element)
1495 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1496 return e_ofono_element_sync_properties_full(element, NULL, NULL);
1500 * Call method SetProperty(prop, {key: value}) at the given element on server.
1502 * This is a server call, not local, so it may fail and in that case
1503 * no property is updated locally. If the value was set the event
1504 * E_OFONO_EVENT_ELEMENT_UPDATED will be added to main loop.
1506 * @param element to call method on server.
1507 * @param prop property name.
1508 * @param key dict key name.
1509 * @param type DBus type to use for value.
1510 * @param value pointer to value, just like regular DBus, see
1511 * dbus_message_iter_append_basic().
1512 * @param cb function to call when server replies or some error happens.
1513 * @param data data to give to cb when it is called.
1515 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1518 e_ofono_element_property_dict_set_full(E_Ofono_Element *element, const char *prop, const char *key, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
1520 const char name[] = "SetProperty";
1522 DBusMessageIter itr, variant, dict, entry;
1525 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1526 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1528 msg = dbus_message_new_method_call
1529 (e_ofono_system_bus_name_get(), element->path, element->interface, name);
1534 dbus_message_iter_init_append(msg, &itr);
1535 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1537 if ((size_t)snprintf(typestr, sizeof(typestr),
1538 (DBUS_TYPE_ARRAY_AS_STRING
1539 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1540 DBUS_TYPE_STRING_AS_STRING
1542 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1543 type) >= sizeof(typestr))
1545 ERR("sizeof(typestr) is too small!");
1549 if (dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &variant))
1551 snprintf(typestr, sizeof(typestr),
1552 (DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1553 DBUS_TYPE_STRING_AS_STRING
1555 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1558 if (dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, typestr, &dict))
1560 if (dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry))
1562 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1564 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1565 dbus_message_iter_append_basic(&entry, type, &value);
1567 dbus_message_iter_append_basic(&entry, type, value);
1569 dbus_message_iter_close_container(&dict, &entry);
1573 ERR("dbus_message_iter_open_container() failed");
1575 dbus_message_iter_close_container(&variant, &dict);
1579 ERR("dbus_message_iter_open_container() failed");
1581 dbus_message_iter_close_container(&itr, &variant);
1585 ERR("dbus_message_iter_open_container() failed");
1588 return e_ofono_element_message_send
1589 (element, name, NULL, NULL, msg,
1590 &element->_pending.property_set, cb, data);
1594 * Call method SetProperty(prop, value) at the given element on server.
1596 * This is a server call, not local, so it may fail and in that case
1597 * no property is updated locally. If the value was set the event
1598 * E_OFONO_EVENT_ELEMENT_UPDATED will be added to main loop.
1600 * @param element to call method on server.
1601 * @param prop property name.
1602 * @param type DBus type to use for value.
1603 * @param value pointer to value, just like regular DBus, see
1604 * dbus_message_iter_append_basic().
1605 * @param cb function to call when server replies or some error happens.
1606 * @param data data to give to cb when it is called.
1608 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1611 e_ofono_element_property_set_full(E_Ofono_Element *element, const char *prop, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
1613 const char name[] = "SetProperty";
1617 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1618 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1620 msg = dbus_message_new_method_call
1621 (e_ofono_system_bus_name_get(), element->path, element->interface, name);
1626 DBusMessageIter itr, v;
1627 dbus_message_iter_init_append(msg, &itr);
1628 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1632 dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &v);
1633 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1635 dbus_message_iter_append_basic(&v, type, &value);
1637 else if (type == DBUS_TYPE_BOOLEAN)
1639 unsigned int b = *(Eina_Bool *)value;
1640 dbus_message_iter_append_basic(&v, type, &b);
1644 dbus_message_iter_append_basic(&v, type, value);
1647 dbus_message_iter_close_container(&itr, &v);
1649 return e_ofono_element_message_send
1650 (element, name, NULL, NULL, msg,
1651 &element->_pending.property_set, cb, data);
1655 * Call method SetProperty(prop, value) at the given element on server.
1657 * This is the simple version and there is no check of server reply
1660 * @param element to call method on server.
1661 * @param prop property name.
1662 * @param type DBus type to use for value.
1663 * @param value pointer to value, just like regular DBus, see
1664 * dbus_message_iter_append_basic().
1666 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1669 e_ofono_element_property_set(E_Ofono_Element *element, const char *prop, int type, const void *value)
1671 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1672 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1673 return e_ofono_element_property_set_full
1674 (element, prop, type, value, NULL, NULL);
1678 e_ofono_element_call_with_path(E_Ofono_Element *element, const char *method_name, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1680 DBusMessageIter itr;
1683 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1684 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1685 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1686 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1688 msg = dbus_message_new_method_call
1689 (e_ofono_system_bus_name_get(), element->path, element->interface,
1695 dbus_message_iter_init_append(msg, &itr);
1696 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &string);
1698 return e_ofono_element_message_send
1699 (element, method_name, NULL, cb, msg, pending, user_cb, user_data);
1703 e_ofono_element_call_with_string(E_Ofono_Element *element, const char *method_name, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1705 DBusMessageIter itr;
1708 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1709 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1710 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1711 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1713 msg = dbus_message_new_method_call
1714 (e_ofono_system_bus_name_get(), element->path, element->interface,
1720 dbus_message_iter_init_append(msg, &itr);
1721 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1723 return e_ofono_element_message_send
1724 (element, method_name, NULL, cb, msg, pending, user_cb, user_data);
1728 e_ofono_element_call_with_path_and_string(E_Ofono_Element *element, const char *method_name, const char *path, const char *string, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1730 DBusMessageIter itr;
1733 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1734 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1735 EINA_SAFETY_ON_NULL_RETURN_VAL(path, EINA_FALSE);
1736 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1737 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1739 msg = dbus_message_new_method_call
1740 (e_ofono_system_bus_name_get(), element->path, element->interface,
1746 dbus_message_iter_init_append(msg, &itr);
1747 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &path);
1748 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1750 return e_ofono_element_message_send
1751 (element, method_name, NULL, cb, msg, pending, user_cb, user_data);
1755 * Get property type.
1757 * If zero is returned, then this call failed and parameter-returned
1758 * values shall be considered invalid.
1760 * @param element which element to get the property
1761 * @param name property name, must be previously stringshared
1762 * @param type will contain the value type.
1764 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1767 e_ofono_element_property_type_get_stringshared(const E_Ofono_Element *element, const char *name, int *type)
1769 const E_Ofono_Element_Property *p;
1771 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1772 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1773 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
1775 EINA_INLIST_FOREACH(element->props, p)
1777 if (p->name == name)
1784 WRN("element %s (%p) has no property with name \"%s\".",
1785 element->path, element, name);
1790 * Get property type.
1792 * If zero is returned, then this call failed and parameter-returned
1793 * values shall be considered invalid.
1795 * @param element which element to get the property
1796 * @param name property name
1797 * @param type will contain the value type.
1799 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1802 e_ofono_element_property_type_get(const E_Ofono_Element *element, const char *name, int *type)
1805 name = eina_stringshare_add(name);
1806 ret = e_ofono_element_property_type_get_stringshared(element, name, type);
1807 eina_stringshare_del(name);
1812 e_ofono_element_list_properties(const E_Ofono_Element *element, Eina_Bool (*cb)(void *data, const E_Ofono_Element *element, const char *name, int type, const void *value), const void *data)
1814 const E_Ofono_Element_Property *p;
1816 EINA_SAFETY_ON_NULL_RETURN(element);
1817 EINA_SAFETY_ON_NULL_RETURN(cb);
1819 EINA_INLIST_FOREACH(element->props, p)
1821 const void *value = NULL;
1825 case DBUS_TYPE_STRING:
1826 value = &p->value.str;
1829 case DBUS_TYPE_OBJECT_PATH:
1830 value = &p->value.path;
1833 case DBUS_TYPE_BOOLEAN:
1834 value = (void *)(unsigned long)p->value.boolean;
1837 case DBUS_TYPE_UINT16:
1838 value = &p->value.u16;
1841 case DBUS_TYPE_UINT32:
1842 value = &p->value.u32;
1846 ERR("unsupported type %c", p->type);
1849 if (!cb((void *)data, element, p->name, p->type, value))
1855 * Get dict value given its key inside a dict property.
1857 * This will look into properties for one of type dict that contains
1858 * the given key, to find the property. If no property is found then
1861 * If zero is returned, then this call failed and parameter-returned
1862 * values shall be considered invalid.
1864 * @param element which element to get the property
1865 * @param dict_name property name, must be previously stringshared
1866 * @param key key inside dict, must be previously stringshared
1867 * @param type if provided it will contain the value type.
1868 * @param value where to store the property value, must be a pointer to the
1869 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1871 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1874 e_ofono_element_property_dict_get_stringshared(const E_Ofono_Element *element, const char *dict_name, const char *key, int *type, void *value)
1876 const E_Ofono_Element_Property *p;
1878 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1879 EINA_SAFETY_ON_NULL_RETURN_VAL(dict_name, EINA_FALSE);
1880 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
1881 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1883 EINA_INLIST_FOREACH(element->props, p)
1885 E_Ofono_Element_Dict_Entry *entry;
1886 E_Ofono_Array *array;
1888 if (p->name != dict_name)
1891 if (p->type != DBUS_TYPE_ARRAY)
1893 WRN("element %s (%p) has property \"%s\" is not an array: %c (%d)",
1894 element->path, element, dict_name, p->type, p->type);
1898 array = p->value.array;
1899 if ((!array) || (array->type != DBUS_TYPE_DICT_ENTRY))
1901 int t = array ? array->type : DBUS_TYPE_INVALID;
1902 WRN("element %s (%p) has property \"%s\" is not a dict: %c (%d)",
1903 element->path, element, dict_name, t, t);
1907 entry = _e_ofono_element_array_dict_find_stringshared(array, key);
1910 WRN("element %s (%p) has no dict property with name \"%s\" with "
1912 element->path, element, dict_name, key);
1917 *type = entry->type;
1919 switch (entry->type)
1921 case DBUS_TYPE_BOOLEAN:
1922 *(Eina_Bool *)value = entry->value.boolean;
1925 case DBUS_TYPE_BYTE:
1926 *(unsigned char *)value = entry->value.byte;
1929 case DBUS_TYPE_UINT16:
1930 *(unsigned short *)value = entry->value.u16;
1933 case DBUS_TYPE_UINT32:
1934 *(unsigned int *)value = entry->value.u32;
1937 case DBUS_TYPE_STRING:
1938 *(const char **)value = entry->value.str;
1941 case DBUS_TYPE_OBJECT_PATH:
1942 *(const char **)value = entry->value.path;
1946 ERR("don't know how to get property %s, key %s type %c (%d)",
1947 dict_name, key, entry->type, entry->type);
1952 WRN("element %s (%p) has no property with name \"%s\".",
1953 element->path, element, dict_name);
1958 * Get property value given its name.
1960 * This will look into properties, to find the property.
1961 * If no property is found then 0 is returned.
1963 * If zero is returned, then this call failed and parameter-returned
1964 * values shall be considered invalid.
1966 * @param element which element to get the property
1967 * @param name property name, must be previously stringshared
1968 * @param type if provided it will contain the value type.
1969 * @param value where to store the property value, must be a pointer to the
1970 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1972 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1975 e_ofono_element_property_get_stringshared(const E_Ofono_Element *element, const char *name, int *type, void *value)
1977 const E_Ofono_Element_Property *p;
1979 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1980 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1981 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1983 EINA_INLIST_FOREACH(element->props, p)
1985 if (p->name != name)
1993 case DBUS_TYPE_BOOLEAN:
1994 *(Eina_Bool *)value = p->value.boolean;
1997 case DBUS_TYPE_BYTE:
1998 *(unsigned char *)value = p->value.byte;
2001 case DBUS_TYPE_UINT16:
2002 *(unsigned short *)value = p->value.u16;
2005 case DBUS_TYPE_UINT32:
2006 *(unsigned int *)value = p->value.u32;
2009 case DBUS_TYPE_STRING:
2010 *(const char **)value = p->value.str;
2013 case DBUS_TYPE_OBJECT_PATH:
2014 *(const char **)value = p->value.path;
2017 case DBUS_TYPE_ARRAY:
2018 *(E_Ofono_Array **)value = p->value.array;
2022 ERR("don't know how to get property type %c (%d)",
2028 WRN("element %s (%p) has no property with name \"%s\".",
2029 element->path, element, name);
2034 * Get property value given its name.
2036 * This will look into properties, to find the property.
2037 * If no property is found then 0 is returned.
2039 * If zero is returned, then this call failed and parameter-returned
2040 * values shall be considered invalid.
2042 * @param element which element to get the property
2043 * @param name property name
2044 * @param type if provided it will contain the value type.
2045 * @param value where to store the property value, must be a pointer to the
2046 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
2048 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2051 e_ofono_element_property_get(const E_Ofono_Element *element, const char *name, int *type, void *value)
2054 name = eina_stringshare_add(name);
2055 ret = e_ofono_element_property_get_stringshared
2056 (element, name, type, value);
2057 eina_stringshare_del(name);
2061 struct e_ofono_elements_for_each_data
2063 Eina_Hash_Foreach cb;
2068 _e_ofono_elements_for_each(Eina_Hash *hash __UNUSED__, const char *key, void *data, void *fdata)
2070 struct e_ofono_elements_for_each_data *each_data = fdata;
2072 each_data->cb(elements, key, data, each_data->data);
2077 * Call the given function for each existing element.
2079 * @param cb function to call for each element. It will get as parameters,
2080 * in order: the element pointer and the given @a user_data.
2081 * @param user_data data to give to @a cb for each element.
2084 e_ofono_elements_for_each(Eina_Hash_Foreach cb, const void *user_data)
2086 struct e_ofono_elements_for_each_data data = {cb, (void *)user_data};
2088 EINA_SAFETY_ON_NULL_RETURN(cb);
2091 (elements, (Eina_Hash_Foreach)_e_ofono_elements_for_each, &data);
2095 _e_ofono_elements_get_allocate(unsigned int *count, E_Ofono_Element ***p_elements)
2097 *count = eina_hash_population(elements);
2104 *p_elements = malloc(*count * sizeof(E_Ofono_Element *));
2107 ERR("could not allocate return array of %d elements: %s",
2108 *count, strerror(errno));
2117 _e_ofono_elements_get_all(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *data, void *fdata)
2119 E_Ofono_Element *element = data;
2120 E_Ofono_Element ***p_ret = fdata;
2128 * Get all known elements.
2130 * No reference is added to these elements, since there are no threads
2131 * in the system, you are free to add references yourself right after
2132 * the return of this call without race condition, elements by the
2133 * system (ie: elementRemoved signal)could only be touched on the next
2134 * main loop iteration.
2136 * @param count return the number of elements in array.
2137 * @param p_elements array with all elements, these are not referenced
2138 * and in no particular order, just set if return is 1.
2140 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2143 e_ofono_elements_get_all(unsigned int *count, E_Ofono_Element ***p_elements)
2145 E_Ofono_Element **p;
2147 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2148 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2150 if (!_e_ofono_elements_get_allocate(count, p_elements))
2155 (elements, (Eina_Hash_Foreach)_e_ofono_elements_get_all, &p);
2159 struct e_ofono_elements_get_all_str_data
2161 E_Ofono_Element **elements;
2167 _e_ofono_elements_get_all_type(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *e, void *user_data)
2169 struct e_ofono_elements_get_all_str_data *data = user_data;
2170 E_Ofono_Element *element = e;
2172 if ((data->str) && (element->interface != data->str))
2175 data->elements[data->count] = element;
2181 * Get all known elements of type.
2183 * No reference is added to these elements, since there are no threads
2184 * in the system, you are free to add references yourself right after
2185 * the return of this call without race condition, elements by the
2186 * system (ie: ElementRemoved signal) could only be touched on the next
2187 * main loop iteration.
2189 * @param type type to filter, or NULL to get all.
2190 * @param count return the number of elements in array.
2191 * @param p_elements array with all elements, these are not referenced
2192 * and in no particular order, just set if return is 1.
2194 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2196 * @see e_ofono_elements_get_all()
2199 e_ofono_elements_get_all_type(const char *type, unsigned int *count, E_Ofono_Element ***p_elements)
2201 struct e_ofono_elements_get_all_str_data data;
2203 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2204 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2206 if (!_e_ofono_elements_get_allocate(count, p_elements))
2209 data.elements = *p_elements;
2211 data.str = eina_stringshare_add(type);
2212 eina_hash_foreach(elements,
2213 (Eina_Hash_Foreach)_e_ofono_elements_get_all_type,
2216 eina_stringshare_del(data.str);
2217 *count = data.count;
2222 * Get the element registered at given path.
2224 * @param path the path to query for registered object.
2226 * @return element pointer if found, NULL otherwise. No references are added.
2229 e_ofono_element_get(const char *path, const char *interface)
2231 E_Ofono_Element *element;
2232 char key[MAX_KEY_SIZE];
2234 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2235 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
2237 snprintf(key, MAX_KEY_SIZE, "%s:%s", path, interface);
2238 element = eina_hash_find(elements, key);
2244 _e_ofono_element_property_changed_callback(void *data, DBusMessage *msg)
2246 E_Ofono_Element *element = (E_Ofono_Element *)data;
2247 DBusMessageIter itr, v_itr;
2248 int t, r, changed = 0;
2249 const char *name = NULL;
2252 DBG("Property changed in element %s %s", element->path, element->interface);
2254 if (!_dbus_callback_check_and_init(msg, &itr, NULL))
2257 t = dbus_message_iter_get_arg_type(&itr);
2258 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
2260 ERR("missing name in property changed signal");
2264 dbus_message_iter_get_basic(&itr, &name);
2266 dbus_message_iter_next(&itr);
2267 t = dbus_message_iter_get_arg_type(&itr);
2268 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
2270 ERR("missing value in property changed signal");
2274 dbus_message_iter_recurse(&itr, &v_itr);
2275 t = dbus_message_iter_get_arg_type(&v_itr);
2277 if (t == DBUS_TYPE_ARRAY)
2279 value = _e_ofono_element_iter_get_array(&v_itr, name);
2281 else if (t != DBUS_TYPE_INVALID)
2283 dbus_message_iter_get_basic(&v_itr, &value);
2287 ERR("property has invalid type %s", name);
2291 r = _e_ofono_element_property_value_add(element, name, t, value);
2294 ERR("failed to add property value %s (%c)", name, t);
2298 INF("property value changed %s (%c)", name, t);
2300 if ((strcmp(name, "Interfaces") == 0) && value)
2303 Eina_Array_Iterator iterator;
2307 EINA_ARRAY_ITER_NEXT(((E_Ofono_Array *)value)->array, i,
2308 interface, iterator)
2310 DBG("Found interface %s on %s", interface, element->path);
2311 e_ofono_element_register(element->path, interface);
2312 e = e_ofono_element_register(element->path, interface);
2313 if ((e) && (!e_ofono_element_properties_sync(e)))
2314 WRN("could not get properties of %s", e->path);
2320 _e_ofono_element_listeners_call(element);
2324 * Register the given pair (path, interface), possibly creating an
2325 * element and return it.
2327 * This will check if (path, interface) is already registered, in
2328 * that case the exiting element is returned. If it was not registered
2329 * yet, a new element is created, registered and returned.
2331 * This call will not add extra references to the object.
2333 * @param path the path to register the element
2335 * @return the registered object, no references are added.
2338 e_ofono_element_register(const char *path, const char *interface)
2340 E_Ofono_Element *element;
2341 char key[MAX_KEY_SIZE];
2343 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2344 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
2346 snprintf(key, MAX_KEY_SIZE, "%s:%s", path, interface);
2347 element = eina_hash_find(elements, key);
2351 element = e_ofono_element_new(path, interface);
2355 if (!eina_hash_add(elements, key, element))
2357 ERR("could not add element %s to hash, delete it.", path);
2358 e_ofono_element_free(element);
2362 element->signal_handler =
2363 e_dbus_signal_handler_add
2364 (e_ofono_conn, e_ofono_system_bus_name_get(),
2365 element->path, element->interface, "PropertyChanged",
2366 _e_ofono_element_property_changed_callback, element);
2368 e_ofono_element_event_add(E_OFONO_EVENT_ELEMENT_ADD, element);
2374 _e_ofono_element_event_unregister_and_free(void *data __UNUSED__, void *ev)
2376 E_Ofono_Element *element = ev;
2377 e_ofono_element_unref(element);
2381 _e_ofono_element_unregister_internal(E_Ofono_Element *element)
2383 if (element->signal_handler)
2385 e_dbus_signal_handler_del(e_ofono_conn, element->signal_handler);
2386 element->signal_handler = NULL;
2389 ecore_event_add(E_OFONO_EVENT_ELEMENT_DEL, element,
2390 _e_ofono_element_event_unregister_and_free, NULL);
2394 * Forget about the given element.
2396 * This will remove the element from the pool of known objects, then
2397 * add an E_OFONO_EVENT_ELEMENT_DEL and after that will unreference it,
2398 * possible freeing it.
2400 * @param element element to forget about. Its reference will be removed.
2403 e_ofono_element_unregister(E_Ofono_Element *element)
2405 char key[MAX_KEY_SIZE];
2410 snprintf(key, MAX_KEY_SIZE, "%s:%s", element->path, element->interface);
2412 eina_hash_del_by_key(elements, key);
2416 * Remove all known elements.
2418 * This will remove all known elements but will NOT add any
2419 * E_OFONO_EVENT_ELEMENT_DEL to main loop.
2421 * This is just useful to make sure next e_ofono_manager_sync_elements()
2422 * will not leave any stale elements. This is unlikely to happen, as
2423 * E_Ofono is supposed to catch all required events to avoid stale elements.
2426 e_ofono_manager_clear_elements(void)
2428 e_ofono_elements_shutdown();
2429 e_ofono_elements_init();
2433 * Creates elements hash.
2435 * This has no init counter since its already guarded by other code.
2439 e_ofono_elements_init(void)
2441 EINA_SAFETY_ON_FALSE_RETURN(!elements);
2443 eina_hash_string_superfast_new
2444 (EINA_FREE_CB(_e_ofono_element_unregister_internal));
2448 e_ofono_elements_shutdown(void)
2450 EINA_SAFETY_ON_FALSE_RETURN(!!elements);
2451 eina_hash_free(elements);
2455 static inline Eina_Bool
2456 _e_ofono_element_is(const E_Ofono_Element *element, const char *interface)
2458 return element->interface == interface;
2462 e_ofono_element_is_manager(const E_Ofono_Element *element)
2464 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2465 return _e_ofono_element_is(element, e_ofono_iface_manager);
2469 e_ofono_element_is_modem(const E_Ofono_Element *element)
2471 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2472 return _e_ofono_element_is(element, e_ofono_iface_modem);
2476 e_ofono_element_is_netreg(const E_Ofono_Element *element)
2478 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2479 return _e_ofono_element_is(element, e_ofono_iface_netreg);