1 #include "e_ofono_private.h"
7 * Maximum size for elements hash key.
9 * The elements hash key is contructed by concatenating the object path and the
10 * interface for the element (with a colon separating the two strings). D-Bus
11 * interfaces have a maximum size of 255 but object paths have unlimited size.
12 * We're assuming a maximum key size of 4k here, but this might need to be
13 * increased if oFono object paths grows bigger than that.
15 #define MAX_KEY_SIZE 4096
16 static Eina_Hash *elements = NULL;
18 typedef struct _E_Ofono_Element_Pending E_Ofono_Element_Pending;
19 typedef struct _E_Ofono_Element_Call_Data E_Ofono_Element_Call_Data;
20 typedef struct _E_Ofono_Element_Property E_Ofono_Element_Property;
21 typedef struct _E_Ofono_Element_Listener E_Ofono_Element_Listener;
22 typedef struct _E_Ofono_Element_Dict_Entry E_Ofono_Element_Dict_Entry;
24 struct _E_Ofono_Element_Pending
27 DBusPendingCall *pending;
29 E_DBus_Method_Return_Cb user_cb;
33 struct _E_Ofono_Element_Call_Data
35 E_Ofono_Element *element;
36 E_DBus_Method_Return_Cb cb;
37 E_Ofono_Element_Pending *pending;
41 struct _E_Ofono_Element_Property
58 struct _E_Ofono_Element_Dict_Entry
72 struct _E_Ofono_Element_Listener
75 void (*cb)(void *data, const E_Ofono_Element *element);
77 void (*free_data)(void *data);
81 _e_ofono_element_event_no_free(void *data __UNUSED__, void *ev)
83 E_Ofono_Element *element = ev;
84 e_ofono_element_unref(element);
88 e_ofono_element_event_add(int event_type, E_Ofono_Element *element)
90 e_ofono_element_ref(element);
92 (event_type, element, _e_ofono_element_event_no_free, element);
96 e_ofono_element_call_dispatch_and_free(void *d, DBusMessage *msg, DBusError *err)
98 E_Ofono_Element_Call_Data *data = d;
99 E_Ofono_Element_Pending *pending;
101 pending = data->pending;
102 pending->pending = NULL;
105 data->cb(data->element, msg, err);
107 if (pending->user_cb)
108 pending->user_cb(pending->user_data, msg, err);
110 pending->data = NULL;
111 *data->p_list = eina_inlist_remove(*data->p_list, EINA_INLIST_GET(pending));
117 e_ofono_element_pending_cancel_and_free(Eina_Inlist **pending)
121 E_Ofono_Element_Pending *p = (E_Ofono_Element_Pending *)*pending;
124 dbus_pending_call_cancel(p->pending);
126 dbus_error_init(&err);
127 dbus_set_error(&err, "Canceled", "Pending method call was canceled.");
128 e_ofono_element_call_dispatch_and_free(p->data, NULL, &err);
129 dbus_error_free(&err);
134 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))
136 E_Ofono_Element_Listener *l;
140 ERR("safety check failed: element == NULL");
146 ERR("safety check failed: cb == NULL");
150 l = malloc(sizeof(*l));
153 ERR("could not allocate E_Ofono_Element_Listener");
158 l->data = (void *)data;
159 l->free_data = free_data;
161 element->_listeners = eina_inlist_append
162 (element->_listeners, EINA_INLIST_GET(l));
168 free_data((void *)data);
172 e_ofono_element_listener_del(E_Ofono_Element *element, void (*cb)(void *data, const E_Ofono_Element *element), const void *data)
174 E_Ofono_Element_Listener *l;
176 EINA_SAFETY_ON_NULL_RETURN(element);
177 EINA_SAFETY_ON_NULL_RETURN(cb);
179 EINA_INLIST_FOREACH(element->_listeners, l)
180 if ((l->cb == cb) && (l->data == data))
182 element->_listeners = eina_inlist_remove
183 (element->_listeners, EINA_INLIST_GET(l));
185 l->free_data(l->data);
193 _e_ofono_element_listeners_call_do(E_Ofono_Element *element)
195 E_Ofono_Element_Listener *l, **shadow;
196 unsigned int i, count;
198 /* NB: iterate on a copy in order to allow listeners to be deleted
199 * from callbacks. number of listeners should be small, so the
200 * following should do fine.
202 count = eina_inlist_count(element->_listeners);
206 shadow = alloca(sizeof(*shadow) * count);
211 EINA_INLIST_FOREACH(element->_listeners, l)
214 for (i = 0; i < count; i++)
215 shadow[i]->cb(shadow[i]->data, element);
218 e_ofono_element_event_add(E_OFONO_EVENT_ELEMENT_UPDATED, element);
222 _e_ofono_element_listeners_call_idler(void *data)
224 E_Ofono_Element *element = data;
225 _e_ofono_element_listeners_call_do(element);
226 element->_idler.changed = NULL;
227 return ECORE_CALLBACK_CANCEL;
231 _e_ofono_element_listeners_call(E_Ofono_Element *element)
233 if (element->_idler.changed)
236 element->_idler.changed = ecore_idler_add
237 (_e_ofono_element_listeners_call_idler, element);
240 /***********************************************************************
242 ***********************************************************************/
245 _e_ofono_element_dict_entry_free(E_Ofono_Element_Dict_Entry *entry)
249 case DBUS_TYPE_BOOLEAN:
251 case DBUS_TYPE_UINT16:
252 case DBUS_TYPE_UINT32:
255 case DBUS_TYPE_OBJECT_PATH:
256 eina_stringshare_del(entry->value.path);
259 case DBUS_TYPE_STRING:
260 eina_stringshare_del(entry->value.str);
264 ERR("don't know how to free dict entry '%s' of type %c (%d)",
265 entry->name, entry->type, entry->type);
268 eina_stringshare_del(entry->name);
272 static E_Ofono_Element_Dict_Entry *
273 _e_ofono_element_dict_entry_new(DBusMessageIter *itr)
275 E_Ofono_Element_Dict_Entry *entry;
276 DBusMessageIter e_itr, v_itr;
278 const char *key = NULL;
281 dbus_message_iter_recurse(itr, &e_itr);
283 t = dbus_message_iter_get_arg_type(&e_itr);
284 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
286 ERR("invalid format for dict entry. first type not a string: %c (%d)",
291 dbus_message_iter_get_basic(&e_itr, &key);
294 ERR("invalid format for dict entry. no key.");
298 dbus_message_iter_next(&e_itr);
299 t = dbus_message_iter_get_arg_type(&e_itr);
300 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
302 ERR("invalid format for dict entry '%s'. "
303 "second type not a variant: %c (%d)",
308 dbus_message_iter_recurse(&e_itr, &v_itr);
310 t = dbus_message_iter_get_arg_type(&v_itr);
311 if ((t == DBUS_TYPE_INVALID) || (t == DBUS_TYPE_ARRAY))
313 ERR("invalid type for dict value for entry '%s': %c (%d)",
318 entry = calloc(1, sizeof(*entry));
321 ERR("could not allocate memory for dict entry.");
325 dbus_message_iter_get_basic(&v_itr, &value);
328 case DBUS_TYPE_BOOLEAN:
329 entry->value.boolean = (Eina_Bool)(long)value;
333 entry->value.byte = (unsigned char)(long)value;
336 case DBUS_TYPE_UINT16:
337 entry->value.u16 = (unsigned short)(long)value;
340 case DBUS_TYPE_UINT32:
341 entry->value.u32 = (unsigned int)(long)value;
344 case DBUS_TYPE_STRING:
345 entry->value.str = eina_stringshare_add(value);
348 case DBUS_TYPE_OBJECT_PATH:
349 entry->value.path = eina_stringshare_add(value);
353 ERR("don't know how to create dict entry '%s' for of type %c (%d)",
359 entry->name = eina_stringshare_add(key);
364 static E_Ofono_Element_Dict_Entry *
365 _e_ofono_element_array_dict_find_stringshared(const E_Ofono_Array *array, const char *key)
367 E_Ofono_Element_Dict_Entry *entry;
368 Eina_Array_Iterator iterator;
371 EINA_ARRAY_ITER_NEXT(array->array, i, entry, iterator)
372 if (entry->name == key)
379 _e_ofono_element_array_free(E_Ofono_Array *array, E_Ofono_Array *new __UNUSED__)
381 Eina_Array_Iterator iterator;
390 case DBUS_TYPE_BOOLEAN:
392 case DBUS_TYPE_UINT16:
393 case DBUS_TYPE_UINT32:
396 case DBUS_TYPE_OBJECT_PATH:
397 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
398 eina_stringshare_del(item);
401 case DBUS_TYPE_STRING:
402 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
403 eina_stringshare_del(item);
406 case DBUS_TYPE_DICT_ENTRY:
407 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
408 _e_ofono_element_dict_entry_free(item);
412 ERR("don't know how to free array of values of type %c (%d)",
413 array->type, array->type);
416 eina_array_free(array->array);
421 _e_ofono_element_property_value_free(E_Ofono_Element_Property *property)
423 switch (property->type)
428 case DBUS_TYPE_BOOLEAN:
430 case DBUS_TYPE_UINT16:
431 case DBUS_TYPE_UINT32:
434 case DBUS_TYPE_STRING:
435 eina_stringshare_del(property->value.str);
438 case DBUS_TYPE_OBJECT_PATH:
439 eina_stringshare_del(property->value.path);
442 case DBUS_TYPE_ARRAY:
443 _e_ofono_element_array_free(property->value.array, NULL);
447 ERR("don't know how to free value of property type %c (%d)",
448 property->type, property->type);
453 _e_ofono_element_get_interface(const char *key)
455 const char *interface = NULL, *tail;
464 if (strcmp(tail, "odems") == 0)
465 interface = e_ofono_iface_modem;
474 ERR("failed to find interface for property \"%s\"", key);
479 static E_Ofono_Element *
480 _e_ofono_element_item_register(const char *key, const char *item)
482 E_Ofono_Element *element;
483 const char *interface;
485 interface = _e_ofono_element_get_interface(key);
489 element = e_ofono_element_register(item, interface);
490 if ((element) && (!e_ofono_element_properties_sync(element)))
491 WRN("could not get properties of %s", element->path);
496 /* Match 2 arrays to find which are new and which are old elements
497 * For new elements, register them under prop_name property
498 * For old elements, unregister them, sending proper DEL event
501 _e_ofono_element_array_match(E_Ofono_Array *old, E_Ofono_Array *new, const char *prop_name, E_Ofono_Element *element)
503 Eina_List *deleted = NULL;
504 Eina_Array_Iterator iter_old, iter_new;
505 unsigned int i_old = 0, i_new = 0;
506 void *item_old = NULL, *item_new;
509 Eina_Bool interfaces = EINA_FALSE;
514 if ((old->type != DBUS_TYPE_OBJECT_PATH) &&
515 (old->type != DBUS_TYPE_STRING))
518 /* is this a list of interfaces? */
519 interfaces = !strcmp(prop_name, "Interfaces");
521 if ((!new) || (!new->array) || eina_array_count(new->array) == 0)
523 if ((!old) || (!old->array) || eina_array_count(old->array) == 0)
529 iter_old = old->array->data;
530 goto out_remove_remaining;
534 iter_new = new->array->data;
535 item_new = *iter_new;
536 EINA_ARRAY_ITER_NEXT(old->array, i_old, item_old, iter_old)
538 if (item_old == item_new)
541 if (i_new >= eina_array_count(new->array))
548 item_new = *iter_new;
552 deleted = eina_list_append(deleted, item_old);
556 for(; i_new < eina_array_count(new->array); iter_new++, i_new++)
558 Eina_Bool found = EINA_FALSE;
559 item_new = *iter_new;
563 EINA_LIST_FOREACH(deleted, l, data)
565 if (data == item_new)
567 deleted = eina_list_remove_list(deleted, l);
574 E_Ofono_Element *e = NULL;
577 e = e_ofono_element_register(item_new, element->path);
579 e = _e_ofono_element_item_register(prop_name, item_new);
582 DBG("Add element %s (%s)\n", e->path, e->interface);
586 /* everybody after i_old on old->array + everybody from deleted list
589 EINA_LIST_FREE(deleted, data)
593 e = e_ofono_element_get(element->path, item_old);
595 e = e_ofono_element_get(data,
596 _e_ofono_element_get_interface(prop_name));
600 e_ofono_element_unregister(e);
601 DBG("Deleted element %s %s\n", e->path, e->interface);
605 out_remove_remaining:
606 for(; i_old < eina_array_count(old->array); iter_old++, i_old++)
609 item_old = *iter_old;
614 e = e_ofono_element_get(element->path, item_old);
616 e = e_ofono_element_get(item_old,
617 _e_ofono_element_get_interface(prop_name));
621 e_ofono_element_unregister(e);
622 DBG("Deleted element %s %s\n", e->path, e->interface);
628 _e_ofono_element_property_update(E_Ofono_Element_Property *property, int type, void *data, E_Ofono_Element *element)
630 Eina_Bool changed = EINA_FALSE;
632 if ((type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) && data)
633 data = (char *)eina_stringshare_add(data);
635 if (property->type != type)
638 DBG("property type changed from '%c' to '%c'",
639 property->type, type);
641 _e_ofono_element_property_value_free(property);
642 memset(&property->value, 0, sizeof(property->value));
643 property->type = type;
649 case DBUS_TYPE_BOOLEAN:
650 if (changed || property->value.boolean != (Eina_Bool)(long)data)
652 property->value.boolean = (Eina_Bool)(long)data;
659 if (changed || property->value.byte != (unsigned char)(long)data)
661 property->value.byte = (unsigned char)(long)data;
667 case DBUS_TYPE_UINT16:
668 if (changed || property->value.u16 != (unsigned short)(long)data)
670 property->value.u16 = (unsigned short)(long)data;
676 case DBUS_TYPE_UINT32:
677 if (changed || property->value.u32 != (unsigned int)(long)data)
679 property->value.u32 = (unsigned int)(long)data;
685 case DBUS_TYPE_STRING:
688 property->value.str = data;
692 if (property->value.str)
693 eina_stringshare_del(property->value.str);
695 if (property->value.str != data)
697 property->value.str = data;
704 case DBUS_TYPE_OBJECT_PATH:
707 property->value.path = data;
711 if (property->value.path)
712 eina_stringshare_del(property->value.path);
714 if (property->value.path != data)
716 property->value.path = data;
723 case DBUS_TYPE_ARRAY:
725 if (property->value.array)
727 _e_ofono_element_array_match(property->value.array, data,
728 property->name, element);
729 _e_ofono_element_array_free(property->value.array, data);
732 property->value.array = data;
737 ERR("don't know how to update property type %c (%d)", type, type);
743 static E_Ofono_Element_Property *
744 _e_ofono_element_property_new(const char *name, int type, void *data, E_Ofono_Element *element)
746 E_Ofono_Element_Property *property;
748 property = calloc(1, sizeof(*property));
751 eina_stringshare_del(name);
752 ERR("could not allocate property: %s", strerror(errno));
756 property->name = name;
757 _e_ofono_element_property_update(property, type, data, element);
762 _e_ofono_element_property_free(E_Ofono_Element_Property *property)
764 _e_ofono_element_property_value_free(property);
765 eina_stringshare_del(property->name);
769 /***********************************************************************
771 ***********************************************************************/
773 e_ofono_element_bytes_array_get_stringshared(const E_Ofono_Element *element, const char *property, unsigned int *count)
775 Eina_Array_Iterator iterator;
776 E_Ofono_Array *array;
777 unsigned char *ret, *p;
781 EINA_SAFETY_ON_NULL_RETURN_VAL(element, NULL);
782 EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
783 EINA_SAFETY_ON_NULL_RETURN_VAL(count, NULL);
787 if (!e_ofono_element_property_get_stringshared
788 (element, property, NULL, &array))
791 if ((!array) || (!(array->array)))
794 *count = eina_array_count(array->array);
795 ret = malloc(*count * sizeof(unsigned char));
798 ERR("could not allocate return array of %d bytes: %s",
799 *count, strerror(errno));
805 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
807 *p = (unsigned char)(long)item;
814 e_ofono_element_objects_array_get_stringshared(const E_Ofono_Element *element, const char *property, unsigned int *count, E_Ofono_Element ***p_elements)
816 E_Ofono_Element **ret, **p;
817 Eina_Array_Iterator iterator;
818 E_Ofono_Array *array;
823 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
824 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
825 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
826 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
831 if (!e_ofono_element_property_get_stringshared
832 (element, property, &type, &array))
835 if (type != DBUS_TYPE_ARRAY)
837 ERR("property %s is not an array!", property);
841 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
844 if (array->type != DBUS_TYPE_OBJECT_PATH)
846 ERR("property %s is not an array of object paths!", property);
850 *count = eina_array_count(array->array);
851 ret = malloc(*count * sizeof(E_Ofono_Element *));
854 ERR("could not allocate return array of %d elements: %s",
855 *count, strerror(errno));
862 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
864 E_Ofono_Element *e = e_ofono_element_get(item, property);
876 /* strings are just pointers (references), no strdup or stringshare_add/ref */
878 e_ofono_element_strings_array_get_stringshared(const E_Ofono_Element *element, const char *property, unsigned int *count, const char ***strings)
880 const char **ret, **p;
881 Eina_Array_Iterator iterator;
882 E_Ofono_Array *array;
887 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
888 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
889 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
890 EINA_SAFETY_ON_NULL_RETURN_VAL(strings, EINA_FALSE);
895 if (!e_ofono_element_property_get_stringshared
896 (element, property, &type, &array))
899 if (type != DBUS_TYPE_ARRAY)
901 ERR("property %s is not an array!", property);
905 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
908 if (array->type != DBUS_TYPE_STRING)
910 ERR("property %s is not an array of strings!", property);
914 *count = eina_array_count(array->array);
915 ret = malloc(*count * sizeof(char *));
918 ERR("could not allocate return array of %d strings: %s",
919 *count, strerror(errno));
926 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
940 _e_ofono_element_array_print(FILE *fp, E_Ofono_Array *array)
942 Eina_Array_Iterator iterator;
951 case DBUS_TYPE_OBJECT_PATH:
952 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
953 fprintf(fp, "\"%s\", ", (const char *)item);
956 case DBUS_TYPE_STRING:
957 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
958 fprintf(fp, "\"%s\", ", (const char *)item);
962 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
963 fprintf(fp, "%#02hhx (\"%c\"), ", (unsigned char)(long)item,
964 (unsigned char)(long)item);
967 case DBUS_TYPE_UINT16:
968 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
969 fprintf(fp, "%#04hx (%hu), ", (unsigned short)(long)item,
970 (unsigned short)(long)item);
973 case DBUS_TYPE_UINT32:
974 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
975 fprintf(fp, "%#08x (%u), ", (unsigned int)(long)item,
976 (unsigned int)(long)item);
979 case DBUS_TYPE_DICT_ENTRY:
981 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
983 E_Ofono_Element_Dict_Entry *entry = item;
984 fprintf(fp, "%s: ", entry->name);
987 case DBUS_TYPE_OBJECT_PATH:
988 fprintf(fp, "\"%s\", ", entry->value.path);
991 case DBUS_TYPE_STRING:
992 fprintf(fp, "\"%s\", ", entry->value.str);
996 fprintf(fp, "%#02hhx (\"%c\"), ",
997 entry->value.byte, entry->value.byte);
1000 case DBUS_TYPE_UINT16:
1001 fprintf(fp, "%#04hx (%hu), ",
1002 entry->value.u16, entry->value.u16);
1005 case DBUS_TYPE_UINT32:
1006 fprintf(fp, "%#08x (%u), ",
1007 entry->value.u32, entry->value.u32);
1011 fprintf(fp, "<UNKNOWN TYPE '%c'>", entry->type);
1018 fprintf(fp, "<UNKNOWN ARRAY TYPE '%c'>", array->type);
1023 * Print element to file descriptor.
1026 e_ofono_element_print(FILE *fp, const E_Ofono_Element *element)
1028 const E_Ofono_Element_Property *p;
1030 EINA_SAFETY_ON_NULL_RETURN(fp);
1033 fputs("Error: no element to print\n", fp);
1038 "Element %p: %s [%s]\n"
1040 element, element->path, element->interface);
1042 EINA_INLIST_FOREACH(element->props, p)
1044 fprintf(fp, "\t\t%s (%c) = ", p->name, p->type);
1048 case DBUS_TYPE_STRING:
1049 fprintf(fp, "\"%s\"", p->value.str);
1052 case DBUS_TYPE_OBJECT_PATH:
1053 fprintf(fp, "\"%s\"", p->value.path);
1056 case DBUS_TYPE_BOOLEAN:
1057 fprintf(fp, "%hhu", p->value.boolean);
1060 case DBUS_TYPE_BYTE:
1061 fprintf(fp, "%#02hhx (%d), ", p->value.byte, p->value.byte);
1064 case DBUS_TYPE_UINT16:
1065 fprintf(fp, "%hu", p->value.u16);
1068 case DBUS_TYPE_UINT32:
1069 fprintf(fp, "%u", p->value.u32);
1072 case DBUS_TYPE_ARRAY:
1073 _e_ofono_element_array_print(fp, p->value.array);
1077 fputs("don't know how to print type", fp);
1084 static E_Ofono_Element *
1085 e_ofono_element_new(const char *path, const char *interface)
1087 E_Ofono_Element *element;
1089 element = calloc(1, sizeof(*element));
1092 ERR("could not allocate element: %s", strerror(errno));
1096 element->path = eina_stringshare_add(path);
1097 element->interface = eina_stringshare_ref(interface);
1098 element->_references = 1;
1104 e_ofono_element_extra_properties_free(E_Ofono_Element *element)
1106 while (element->props)
1108 E_Ofono_Element_Property *prop;
1109 prop = (E_Ofono_Element_Property *)element->props;
1110 element->props = element->props->next;
1111 _e_ofono_element_property_free(prop);
1116 e_ofono_element_free(E_Ofono_Element *element)
1118 if (element->_idler.changed)
1119 ecore_idler_del(element->_idler.changed);
1121 while (element->_listeners)
1123 E_Ofono_Element_Listener *l = (void *)element->_listeners;
1124 element->_listeners = eina_inlist_remove
1125 (element->_listeners, element->_listeners);
1128 l->free_data(l->data);
1133 e_ofono_element_pending_cancel_and_free(&element->_pending.properties_get);
1134 e_ofono_element_pending_cancel_and_free(&element->_pending.property_set);
1135 e_ofono_element_pending_cancel_and_free(&element->_pending.send_sms);
1137 e_ofono_element_extra_properties_free(element);
1138 eina_stringshare_del(element->interface);
1139 eina_stringshare_del(element->path);
1144 * Add reference to element.
1147 e_ofono_element_ref(E_Ofono_Element *element)
1149 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1150 return ++element->_references;
1154 * Remove reference from element.
1156 * If reference count drops to 0 element will be freed.
1159 e_ofono_element_unref(E_Ofono_Element *element)
1162 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1164 i = --element->_references;
1166 e_ofono_element_free(element);
1168 ERR("element %p references %d < 0", element, i);
1174 * Send message with callbacks set to work with ofono elements.
1176 * If this call fails (returns 0), pending callbacks will not be called,
1177 * not even with error messages.
1179 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1182 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)
1184 E_Ofono_Element_Call_Data *data;
1185 E_Ofono_Element_Pending *p;
1187 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1188 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1189 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1190 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
1192 interface = interface ? : element->interface;
1194 data = malloc(sizeof(*data));
1197 ERR("could not alloc e_ofono_element_call_data: %s",
1199 dbus_message_unref(msg);
1203 p = malloc(sizeof(*p));
1206 ERR("could not alloc E_Ofono_Element_Pending: %s",
1209 dbus_message_unref(msg);
1213 data->element = element;
1216 data->p_list = pending;
1217 p->user_cb = user_cb;
1218 p->user_data = (void *)user_data;
1220 p->pending = e_dbus_message_send
1221 (e_ofono_conn, msg, e_ofono_element_call_dispatch_and_free, -1, data);
1222 dbus_message_unref(msg);
1226 *pending = eina_inlist_append(*pending, EINA_INLIST_GET(p));
1230 ERR("failed to call %s (obj=%s, path=%s, iface=%s)",
1231 method_name, e_ofono_system_bus_name_get(),
1232 element->path, interface);
1239 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)
1243 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1244 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1245 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1247 interface = interface ? : element->interface;
1249 msg = dbus_message_new_method_call
1250 (e_ofono_system_bus_name_get(), element->path, interface,
1253 return e_ofono_element_message_send
1254 (element, method_name, interface, cb, msg, pending, user_cb, user_data);
1258 _e_ofono_element_property_value_add(E_Ofono_Element *element, const char *name, int type, void *value)
1260 E_Ofono_Element_Property *p;
1262 name = eina_stringshare_add(name);
1263 EINA_INLIST_FOREACH(element->props, p)
1265 if (p->name == name)
1267 eina_stringshare_del(name);
1268 return _e_ofono_element_property_update(p, type, value, element);
1272 p = _e_ofono_element_property_new(name, type, value, element);
1275 ERR("could not create property %s (%c)", name, type);
1279 element->props = eina_inlist_append(element->props, EINA_INLIST_GET(p));
1283 static E_Ofono_Array *
1284 _e_ofono_element_iter_get_array(DBusMessageIter *itr, const char *key)
1286 E_Ofono_Array *array;
1287 DBusMessageIter e_itr;
1289 array = malloc(sizeof(E_Ofono_Array));
1292 ERR("could not create new e_ofono array.");
1296 array->array = eina_array_new(16);
1297 if (!(array->array))
1299 ERR("could not create new eina array.");
1304 dbus_message_iter_recurse(itr, &e_itr);
1305 array->type = dbus_message_iter_get_arg_type(&e_itr);
1306 if (array->type == DBUS_TYPE_INVALID)
1308 DBG("array %s is of type 'invalid' (empty?)", key);
1309 eina_array_free(array->array);
1316 switch (array->type)
1318 case DBUS_TYPE_OBJECT_PATH:
1322 dbus_message_iter_get_basic(&e_itr, &path);
1323 path = eina_stringshare_add(path);
1324 eina_array_push(array->array, path);
1325 _e_ofono_element_item_register(key, path);
1329 case DBUS_TYPE_STRING:
1333 dbus_message_iter_get_basic(&e_itr, &str);
1334 str = eina_stringshare_add(str);
1335 eina_array_push(array->array, str);
1339 case DBUS_TYPE_BYTE:
1342 dbus_message_iter_get_basic(&e_itr, &byte);
1343 eina_array_push(array->array, (void *)(long)byte);
1347 case DBUS_TYPE_DICT_ENTRY:
1349 E_Ofono_Element_Dict_Entry *entry;
1350 entry = _e_ofono_element_dict_entry_new(&e_itr);
1352 eina_array_push(array->array, entry);
1357 ERR("don't know how to build array '%s' of type %c (%d)",
1358 key, array->type, array->type);
1359 eina_array_free(array->array);
1364 while (dbus_message_iter_next(&e_itr));
1369 _e_ofono_element_get_properties_callback(void *user_data, DBusMessage *msg, DBusError *err)
1371 E_Ofono_Element *element = user_data;
1372 DBusMessageIter itr, s_itr;
1375 DBG("get_properties msg=%p", msg);
1377 if (!_dbus_callback_check_and_init(msg, &itr, err))
1380 t = dbus_message_iter_get_arg_type(&itr);
1381 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1385 dbus_message_iter_recurse(&itr, &s_itr);
1388 DBusMessageIter e_itr, v_itr;
1393 t = dbus_message_iter_get_arg_type(&s_itr);
1394 if (!_dbus_iter_type_check(t, DBUS_TYPE_DICT_ENTRY))
1397 dbus_message_iter_recurse(&s_itr, &e_itr);
1399 t = dbus_message_iter_get_arg_type(&e_itr);
1400 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
1403 dbus_message_iter_get_basic(&e_itr, &key);
1404 dbus_message_iter_next(&e_itr);
1405 t = dbus_message_iter_get_arg_type(&e_itr);
1406 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
1409 dbus_message_iter_recurse(&e_itr, &v_itr);
1410 t = dbus_message_iter_get_arg_type(&v_itr);
1411 if (t == DBUS_TYPE_ARRAY)
1413 value = _e_ofono_element_iter_get_array(&v_itr, key);
1415 else if (t != DBUS_TYPE_INVALID)
1417 dbus_message_iter_get_basic(&v_itr, &value);
1421 ERR("property has invalid type %s", key);
1425 r = _e_ofono_element_property_value_add(element, key, t, value);
1428 ERR("failed to add property value %s (%c)", key, t);
1432 INF("property value changed %s (%c)", key, t);
1434 if ((strcmp(key, "Interfaces") == 0) && value)
1437 Eina_Array_Iterator iterator;
1441 EINA_ARRAY_ITER_NEXT(((E_Ofono_Array *)value)->array, i,
1442 interface, iterator)
1444 DBG("Found interface %s on %s", interface, element->path);
1445 e = e_ofono_element_register(element->path, interface);
1446 if ((e) && (!e_ofono_element_properties_sync(e)))
1447 WRN("could not get properties of %s", e->path);
1452 while (dbus_message_iter_next(&s_itr));
1455 _e_ofono_element_listeners_call(element);
1459 * Sync element properties with server.
1461 * Call method GetProperties() at the given element on server in order to sync
1464 * @param element to call method on server.
1465 * @param cb function to call when server replies or some error happens.
1466 * @param data data to give to cb when it is called.
1468 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1471 e_ofono_element_sync_properties_full(E_Ofono_Element *element, E_DBus_Method_Return_Cb cb, const void *data)
1473 const char name[] = "GetProperties";
1475 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1476 return e_ofono_element_call_full
1477 (element, name, element->interface,
1478 _e_ofono_element_get_properties_callback,
1479 &element->_pending.properties_get, cb, data);
1483 * Sync element properties with server, simple version.
1485 * Call method GetProperties() at the given element on server in order to sync
1486 * them. This is the simple version and there is no check of server reply
1489 * @param element to call method on server.
1491 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1494 e_ofono_element_properties_sync(E_Ofono_Element *element)
1496 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1497 return e_ofono_element_sync_properties_full(element, NULL, NULL);
1501 * Call method SetProperty(prop, {key: value}) at the given element on server.
1503 * This is a server call, not local, so it may fail and in that case
1504 * no property is updated locally. If the value was set the event
1505 * E_OFONO_EVENT_ELEMENT_UPDATED will be added to main loop.
1507 * @param element to call method on server.
1508 * @param prop property name.
1509 * @param key dict key name.
1510 * @param type DBus type to use for value.
1511 * @param value pointer to value, just like regular DBus, see
1512 * dbus_message_iter_append_basic().
1513 * @param cb function to call when server replies or some error happens.
1514 * @param data data to give to cb when it is called.
1516 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1519 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)
1521 const char name[] = "SetProperty";
1523 DBusMessageIter itr, variant, dict, entry;
1526 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1527 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1529 msg = dbus_message_new_method_call
1530 (e_ofono_system_bus_name_get(), element->path, element->interface, name);
1535 dbus_message_iter_init_append(msg, &itr);
1536 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1538 if ((size_t)snprintf(typestr, sizeof(typestr),
1539 (DBUS_TYPE_ARRAY_AS_STRING
1540 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1541 DBUS_TYPE_STRING_AS_STRING
1543 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1544 type) >= sizeof(typestr))
1546 ERR("sizeof(typestr) is too small!");
1550 if (dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &variant))
1552 snprintf(typestr, sizeof(typestr),
1553 (DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1554 DBUS_TYPE_STRING_AS_STRING
1556 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1559 if (dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, typestr, &dict))
1561 if (dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry))
1563 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1565 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1566 dbus_message_iter_append_basic(&entry, type, &value);
1568 dbus_message_iter_append_basic(&entry, type, value);
1570 dbus_message_iter_close_container(&dict, &entry);
1574 ERR("dbus_message_iter_open_container() failed");
1576 dbus_message_iter_close_container(&variant, &dict);
1580 ERR("dbus_message_iter_open_container() failed");
1582 dbus_message_iter_close_container(&itr, &variant);
1586 ERR("dbus_message_iter_open_container() failed");
1589 return e_ofono_element_message_send
1590 (element, name, NULL, NULL, msg,
1591 &element->_pending.property_set, cb, data);
1595 * Call method SetProperty(prop, value) at the given element on server.
1597 * This is a server call, not local, so it may fail and in that case
1598 * no property is updated locally. If the value was set the event
1599 * E_OFONO_EVENT_ELEMENT_UPDATED will be added to main loop.
1601 * @param element to call method on server.
1602 * @param prop property name.
1603 * @param type DBus type to use for value.
1604 * @param value pointer to value, just like regular DBus, see
1605 * dbus_message_iter_append_basic().
1606 * @param cb function to call when server replies or some error happens.
1607 * @param data data to give to cb when it is called.
1609 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1612 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)
1614 const char name[] = "SetProperty";
1618 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1619 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1621 msg = dbus_message_new_method_call
1622 (e_ofono_system_bus_name_get(), element->path, element->interface, name);
1627 DBusMessageIter itr, v;
1628 dbus_message_iter_init_append(msg, &itr);
1629 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1633 dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &v);
1634 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1636 dbus_message_iter_append_basic(&v, type, &value);
1638 else if (type == DBUS_TYPE_BOOLEAN)
1640 unsigned int b = *(Eina_Bool *)value;
1641 dbus_message_iter_append_basic(&v, type, &b);
1645 dbus_message_iter_append_basic(&v, type, value);
1648 dbus_message_iter_close_container(&itr, &v);
1650 return e_ofono_element_message_send
1651 (element, name, NULL, NULL, msg,
1652 &element->_pending.property_set, cb, data);
1656 * Call method SetProperty(prop, value) at the given element on server.
1658 * This is the simple version and there is no check of server reply
1661 * @param element to call method on server.
1662 * @param prop property name.
1663 * @param type DBus type to use for value.
1664 * @param value pointer to value, just like regular DBus, see
1665 * dbus_message_iter_append_basic().
1667 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1670 e_ofono_element_property_set(E_Ofono_Element *element, const char *prop, int type, const void *value)
1672 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1673 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1674 return e_ofono_element_property_set_full
1675 (element, prop, type, value, NULL, NULL);
1679 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)
1681 DBusMessageIter itr;
1684 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1685 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1686 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1687 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1689 msg = dbus_message_new_method_call
1690 (e_ofono_system_bus_name_get(), element->path, element->interface,
1696 dbus_message_iter_init_append(msg, &itr);
1697 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &string);
1699 return e_ofono_element_message_send
1700 (element, method_name, NULL, cb, msg, pending, user_cb, user_data);
1704 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)
1706 DBusMessageIter itr;
1709 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1710 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1711 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1712 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1714 msg = dbus_message_new_method_call
1715 (e_ofono_system_bus_name_get(), element->path, element->interface,
1721 dbus_message_iter_init_append(msg, &itr);
1722 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1724 return e_ofono_element_message_send
1725 (element, method_name, NULL, cb, msg, pending, user_cb, user_data);
1729 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)
1731 DBusMessageIter itr;
1734 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1735 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1736 EINA_SAFETY_ON_NULL_RETURN_VAL(path, EINA_FALSE);
1737 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1738 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1740 msg = dbus_message_new_method_call
1741 (e_ofono_system_bus_name_get(), element->path, element->interface,
1747 dbus_message_iter_init_append(msg, &itr);
1748 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &path);
1749 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1751 return e_ofono_element_message_send
1752 (element, method_name, NULL, cb, msg, pending, user_cb, user_data);
1756 * Get property type.
1758 * If zero is returned, then this call failed and parameter-returned
1759 * values shall be considered invalid.
1761 * @param element which element to get the property
1762 * @param name property name, must be previously stringshared
1763 * @param type will contain the value type.
1765 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1768 e_ofono_element_property_type_get_stringshared(const E_Ofono_Element *element, const char *name, int *type)
1770 const E_Ofono_Element_Property *p;
1772 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1773 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1774 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
1776 EINA_INLIST_FOREACH(element->props, p)
1778 if (p->name == name)
1785 WRN("element %s (%p) has no property with name \"%s\".",
1786 element->path, element, name);
1791 * Get property type.
1793 * If zero is returned, then this call failed and parameter-returned
1794 * values shall be considered invalid.
1796 * @param element which element to get the property
1797 * @param name property name
1798 * @param type will contain the value type.
1800 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1803 e_ofono_element_property_type_get(const E_Ofono_Element *element, const char *name, int *type)
1806 name = eina_stringshare_add(name);
1807 ret = e_ofono_element_property_type_get_stringshared(element, name, type);
1808 eina_stringshare_del(name);
1813 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)
1815 const E_Ofono_Element_Property *p;
1817 EINA_SAFETY_ON_NULL_RETURN(element);
1818 EINA_SAFETY_ON_NULL_RETURN(cb);
1820 EINA_INLIST_FOREACH(element->props, p)
1822 const void *value = NULL;
1826 case DBUS_TYPE_STRING:
1827 value = &p->value.str;
1830 case DBUS_TYPE_OBJECT_PATH:
1831 value = &p->value.path;
1834 case DBUS_TYPE_BOOLEAN:
1835 value = (void *)(unsigned long)p->value.boolean;
1838 case DBUS_TYPE_UINT16:
1839 value = &p->value.u16;
1842 case DBUS_TYPE_UINT32:
1843 value = &p->value.u32;
1847 ERR("unsupported type %c", p->type);
1850 if (!cb((void *)data, element, p->name, p->type, value))
1856 * Get dict value given its key inside a dict property.
1858 * This will look into properties for one of type dict that contains
1859 * the given key, to find the property. If no property is found then
1862 * If zero is returned, then this call failed and parameter-returned
1863 * values shall be considered invalid.
1865 * @param element which element to get the property
1866 * @param dict_name property name, must be previously stringshared
1867 * @param key key inside dict, must be previously stringshared
1868 * @param type if provided it will contain the value type.
1869 * @param value where to store the property value, must be a pointer to the
1870 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1872 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1875 e_ofono_element_property_dict_get_stringshared(const E_Ofono_Element *element, const char *dict_name, const char *key, int *type, void *value)
1877 const E_Ofono_Element_Property *p;
1879 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1880 EINA_SAFETY_ON_NULL_RETURN_VAL(dict_name, EINA_FALSE);
1881 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
1882 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1884 EINA_INLIST_FOREACH(element->props, p)
1886 E_Ofono_Element_Dict_Entry *entry;
1887 E_Ofono_Array *array;
1889 if (p->name != dict_name)
1892 if (p->type != DBUS_TYPE_ARRAY)
1894 WRN("element %s (%p) has property \"%s\" is not an array: %c (%d)",
1895 element->path, element, dict_name, p->type, p->type);
1899 array = p->value.array;
1900 if ((!array) || (array->type != DBUS_TYPE_DICT_ENTRY))
1902 int t = array ? array->type : DBUS_TYPE_INVALID;
1903 WRN("element %s (%p) has property \"%s\" is not a dict: %c (%d)",
1904 element->path, element, dict_name, t, t);
1908 entry = _e_ofono_element_array_dict_find_stringshared(array, key);
1911 WRN("element %s (%p) has no dict property with name \"%s\" with "
1913 element->path, element, dict_name, key);
1918 *type = entry->type;
1920 switch (entry->type)
1922 case DBUS_TYPE_BOOLEAN:
1923 *(Eina_Bool *)value = entry->value.boolean;
1926 case DBUS_TYPE_BYTE:
1927 *(unsigned char *)value = entry->value.byte;
1930 case DBUS_TYPE_UINT16:
1931 *(unsigned short *)value = entry->value.u16;
1934 case DBUS_TYPE_UINT32:
1935 *(unsigned int *)value = entry->value.u32;
1938 case DBUS_TYPE_STRING:
1939 *(const char **)value = entry->value.str;
1942 case DBUS_TYPE_OBJECT_PATH:
1943 *(const char **)value = entry->value.path;
1947 ERR("don't know how to get property %s, key %s type %c (%d)",
1948 dict_name, key, entry->type, entry->type);
1953 WRN("element %s (%p) has no property with name \"%s\".",
1954 element->path, element, dict_name);
1959 * Get property value given its name.
1961 * This will look into properties, to find the property.
1962 * If no property is found then 0 is returned.
1964 * If zero is returned, then this call failed and parameter-returned
1965 * values shall be considered invalid.
1967 * @param element which element to get the property
1968 * @param name property name, must be previously stringshared
1969 * @param type if provided it will contain the value type.
1970 * @param value where to store the property value, must be a pointer to the
1971 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1973 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1976 e_ofono_element_property_get_stringshared(const E_Ofono_Element *element, const char *name, int *type, void *value)
1978 const E_Ofono_Element_Property *p;
1980 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1981 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1982 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1984 EINA_INLIST_FOREACH(element->props, p)
1986 if (p->name != name)
1994 case DBUS_TYPE_BOOLEAN:
1995 *(Eina_Bool *)value = p->value.boolean;
1998 case DBUS_TYPE_BYTE:
1999 *(unsigned char *)value = p->value.byte;
2002 case DBUS_TYPE_UINT16:
2003 *(unsigned short *)value = p->value.u16;
2006 case DBUS_TYPE_UINT32:
2007 *(unsigned int *)value = p->value.u32;
2010 case DBUS_TYPE_STRING:
2011 *(const char **)value = p->value.str;
2014 case DBUS_TYPE_OBJECT_PATH:
2015 *(const char **)value = p->value.path;
2018 case DBUS_TYPE_ARRAY:
2019 *(E_Ofono_Array **)value = p->value.array;
2023 ERR("don't know how to get property type %c (%d)",
2029 WRN("element %s (%p) has no property with name \"%s\".",
2030 element->path, element, name);
2035 * Get property value given its name.
2037 * This will look into properties, to find the property.
2038 * If no property is found then 0 is returned.
2040 * If zero is returned, then this call failed and parameter-returned
2041 * values shall be considered invalid.
2043 * @param element which element to get the property
2044 * @param name property name
2045 * @param type if provided it will contain the value type.
2046 * @param value where to store the property value, must be a pointer to the
2047 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
2049 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2052 e_ofono_element_property_get(const E_Ofono_Element *element, const char *name, int *type, void *value)
2055 name = eina_stringshare_add(name);
2056 ret = e_ofono_element_property_get_stringshared
2057 (element, name, type, value);
2058 eina_stringshare_del(name);
2062 struct e_ofono_elements_for_each_data
2064 Eina_Hash_Foreach cb;
2069 _e_ofono_elements_for_each(Eina_Hash *hash __UNUSED__, const char *key, void *data, void *fdata)
2071 struct e_ofono_elements_for_each_data *each_data = fdata;
2073 each_data->cb(elements, key, data, each_data->data);
2078 * Call the given function for each existing element.
2080 * @param cb function to call for each element. It will get as parameters,
2081 * in order: the element pointer and the given @a user_data.
2082 * @param user_data data to give to @a cb for each element.
2085 e_ofono_elements_for_each(Eina_Hash_Foreach cb, const void *user_data)
2087 struct e_ofono_elements_for_each_data data = {cb, (void *)user_data};
2089 EINA_SAFETY_ON_NULL_RETURN(cb);
2092 (elements, (Eina_Hash_Foreach)_e_ofono_elements_for_each, &data);
2096 _e_ofono_elements_get_allocate(unsigned int *count, E_Ofono_Element ***p_elements)
2098 *count = eina_hash_population(elements);
2105 *p_elements = malloc(*count * sizeof(E_Ofono_Element *));
2108 ERR("could not allocate return array of %d elements: %s",
2109 *count, strerror(errno));
2118 _e_ofono_elements_get_all(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *data, void *fdata)
2120 E_Ofono_Element *element = data;
2121 E_Ofono_Element ***p_ret = fdata;
2129 * Get all known elements.
2131 * No reference is added to these elements, since there are no threads
2132 * in the system, you are free to add references yourself right after
2133 * the return of this call without race condition, elements by the
2134 * system (ie: elementRemoved signal)could only be touched on the next
2135 * main loop iteration.
2137 * @param count return the number of elements in array.
2138 * @param p_elements array with all elements, these are not referenced
2139 * and in no particular order, just set if return is 1.
2141 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2144 e_ofono_elements_get_all(unsigned int *count, E_Ofono_Element ***p_elements)
2146 E_Ofono_Element **p;
2148 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2149 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2151 if (!_e_ofono_elements_get_allocate(count, p_elements))
2156 (elements, (Eina_Hash_Foreach)_e_ofono_elements_get_all, &p);
2160 struct e_ofono_elements_get_all_str_data
2162 E_Ofono_Element **elements;
2168 _e_ofono_elements_get_all_type(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *e, void *user_data)
2170 struct e_ofono_elements_get_all_str_data *data = user_data;
2171 E_Ofono_Element *element = e;
2173 if ((data->str) && (element->interface != data->str))
2176 data->elements[data->count] = element;
2182 * Get all known elements of type.
2184 * No reference is added to these elements, since there are no threads
2185 * in the system, you are free to add references yourself right after
2186 * the return of this call without race condition, elements by the
2187 * system (ie: ElementRemoved signal) could only be touched on the next
2188 * main loop iteration.
2190 * @param type type to filter, or NULL to get all.
2191 * @param count return the number of elements in array.
2192 * @param p_elements array with all elements, these are not referenced
2193 * and in no particular order, just set if return is 1.
2195 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2197 * @see e_ofono_elements_get_all()
2200 e_ofono_elements_get_all_type(const char *type, unsigned int *count, E_Ofono_Element ***p_elements)
2202 struct e_ofono_elements_get_all_str_data data;
2204 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2205 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2207 if (!_e_ofono_elements_get_allocate(count, p_elements))
2210 data.elements = *p_elements;
2212 data.str = eina_stringshare_add(type);
2213 eina_hash_foreach(elements,
2214 (Eina_Hash_Foreach)_e_ofono_elements_get_all_type,
2217 eina_stringshare_del(data.str);
2218 *count = data.count;
2223 * Get the element registered at given path.
2225 * @param path the path to query for registered object.
2227 * @return element pointer if found, NULL otherwise. No references are added.
2230 e_ofono_element_get(const char *path, const char *interface)
2232 E_Ofono_Element *element;
2233 char key[MAX_KEY_SIZE];
2235 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2236 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
2238 snprintf(key, MAX_KEY_SIZE, "%s:%s", path, interface);
2239 element = eina_hash_find(elements, key);
2245 _e_ofono_element_property_changed_callback(void *data, DBusMessage *msg)
2247 E_Ofono_Element *element = (E_Ofono_Element *)data;
2248 DBusMessageIter itr, v_itr;
2249 int t, r, changed = 0;
2250 const char *name = NULL;
2253 DBG("Property changed in element %s %s", element->path, element->interface);
2255 if (!_dbus_callback_check_and_init(msg, &itr, NULL))
2258 t = dbus_message_iter_get_arg_type(&itr);
2259 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
2261 ERR("missing name in property changed signal");
2265 dbus_message_iter_get_basic(&itr, &name);
2267 dbus_message_iter_next(&itr);
2268 t = dbus_message_iter_get_arg_type(&itr);
2269 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
2271 ERR("missing value in property changed signal");
2275 dbus_message_iter_recurse(&itr, &v_itr);
2276 t = dbus_message_iter_get_arg_type(&v_itr);
2278 if (t == DBUS_TYPE_ARRAY)
2280 value = _e_ofono_element_iter_get_array(&v_itr, name);
2282 else if (t != DBUS_TYPE_INVALID)
2284 dbus_message_iter_get_basic(&v_itr, &value);
2288 ERR("property has invalid type %s", name);
2292 r = _e_ofono_element_property_value_add(element, name, t, value);
2295 ERR("failed to add property value %s (%c)", name, t);
2299 INF("property value changed %s (%c)", name, t);
2301 if ((strcmp(name, "Interfaces") == 0) && value)
2304 Eina_Array_Iterator iterator;
2308 EINA_ARRAY_ITER_NEXT(((E_Ofono_Array *)value)->array, i,
2309 interface, iterator)
2311 DBG("Found interface %s on %s", interface, element->path);
2312 e_ofono_element_register(element->path, interface);
2313 e = e_ofono_element_register(element->path, interface);
2314 if ((e) && (!e_ofono_element_properties_sync(e)))
2315 WRN("could not get properties of %s", e->path);
2321 _e_ofono_element_listeners_call(element);
2325 * Register the given pair (path, interface), possibly creating an
2326 * element and return it.
2328 * This will check if (path, interface) is already registered, in
2329 * that case the exiting element is returned. If it was not registered
2330 * yet, a new element is created, registered and returned.
2332 * This call will not add extra references to the object.
2334 * @param path the path to register the element
2336 * @return the registered object, no references are added.
2339 e_ofono_element_register(const char *path, const char *interface)
2341 E_Ofono_Element *element;
2342 char key[MAX_KEY_SIZE];
2344 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2345 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
2347 snprintf(key, MAX_KEY_SIZE, "%s:%s", path, interface);
2348 element = eina_hash_find(elements, key);
2352 element = e_ofono_element_new(path, interface);
2356 if (!eina_hash_add(elements, key, element))
2358 ERR("could not add element %s to hash, delete it.", path);
2359 e_ofono_element_free(element);
2363 element->signal_handler =
2364 e_dbus_signal_handler_add
2365 (e_ofono_conn, e_ofono_system_bus_name_get(),
2366 element->path, element->interface, "PropertyChanged",
2367 _e_ofono_element_property_changed_callback, element);
2369 e_ofono_element_event_add(E_OFONO_EVENT_ELEMENT_ADD, element);
2375 _e_ofono_element_event_unregister_and_free(void *data __UNUSED__, void *ev)
2377 E_Ofono_Element *element = ev;
2378 e_ofono_element_unref(element);
2382 _e_ofono_element_unregister_internal(E_Ofono_Element *element)
2384 if (element->signal_handler)
2386 e_dbus_signal_handler_del(e_ofono_conn, element->signal_handler);
2387 element->signal_handler = NULL;
2390 ecore_event_add(E_OFONO_EVENT_ELEMENT_DEL, element,
2391 _e_ofono_element_event_unregister_and_free, NULL);
2395 * Forget about the given element.
2397 * This will remove the element from the pool of known objects, then
2398 * add an E_OFONO_EVENT_ELEMENT_DEL and after that will unreference it,
2399 * possible freeing it.
2401 * @param element element to forget about. Its reference will be removed.
2404 e_ofono_element_unregister(E_Ofono_Element *element)
2406 char key[MAX_KEY_SIZE];
2411 snprintf(key, MAX_KEY_SIZE, "%s:%s", element->path, element->interface);
2413 eina_hash_del_by_key(elements, key);
2417 * Remove all known elements.
2419 * This will remove all known elements but will NOT add any
2420 * E_OFONO_EVENT_ELEMENT_DEL to main loop.
2422 * This is just useful to make sure next e_ofono_manager_sync_elements()
2423 * will not leave any stale elements. This is unlikely to happen, as
2424 * E_Ofono is supposed to catch all required events to avoid stale elements.
2427 e_ofono_manager_clear_elements(void)
2429 e_ofono_elements_shutdown();
2430 e_ofono_elements_init();
2434 * Creates elements hash.
2436 * This has no init counter since its already guarded by other code.
2440 e_ofono_elements_init(void)
2442 EINA_SAFETY_ON_FALSE_RETURN(!elements);
2444 eina_hash_string_superfast_new
2445 (EINA_FREE_CB(_e_ofono_element_unregister_internal));
2449 e_ofono_elements_shutdown(void)
2451 EINA_SAFETY_ON_FALSE_RETURN(!!elements);
2452 eina_hash_free(elements);
2456 static inline Eina_Bool
2457 _e_ofono_element_is(const E_Ofono_Element *element, const char *interface)
2459 return element->interface == interface;
2463 e_ofono_element_is_manager(const E_Ofono_Element *element)
2465 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2466 return _e_ofono_element_is(element, e_ofono_iface_manager);
2470 e_ofono_element_is_modem(const E_Ofono_Element *element)
2472 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2473 return _e_ofono_element_is(element, e_ofono_iface_modem);
2477 e_ofono_element_is_netreg(const E_Ofono_Element *element)
2479 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2480 return _e_ofono_element_is(element, e_ofono_iface_netreg);