1 #include "e_connman_private.h"
5 static Eina_Hash *elements = NULL;
7 typedef struct _E_Connman_Array E_Connman_Array;
8 typedef struct _E_Connman_Element_Pending E_Connman_Element_Pending;
9 typedef struct _E_Connman_Element_Call_Data E_Connman_Element_Call_Data;
10 typedef struct _E_Connman_Element_Property E_Connman_Element_Property;
11 typedef struct _E_Connman_Element_Listener E_Connman_Element_Listener;
12 typedef struct _E_Connman_Element_Dict_Entry E_Connman_Element_Dict_Entry;
14 struct _E_Connman_Array
20 struct _E_Connman_Element_Pending
23 DBusPendingCall *pending;
25 E_DBus_Method_Return_Cb user_cb;
29 struct _E_Connman_Element_Call_Data
31 E_Connman_Element *element;
32 E_DBus_Method_Return_Cb cb;
33 E_Connman_Element_Pending *pending;
37 struct _E_Connman_Element_Property
50 E_Connman_Array *array;
54 struct _E_Connman_Element_Dict_Entry
68 struct _E_Connman_Element_Listener
71 void (*cb)(void *data, const E_Connman_Element *element);
73 void (*free_data)(void *data);
77 _e_connman_element_event_no_free(void *data __UNUSED__, void *ev)
79 E_Connman_Element *element = ev;
80 e_connman_element_unref(element);
84 e_connman_element_event_add(int event_type, E_Connman_Element *element)
86 e_connman_element_ref(element);
88 (event_type, element, _e_connman_element_event_no_free, element);
92 e_connman_element_call_dispatch_and_free(void *d, DBusMessage *msg, DBusError *err)
94 E_Connman_Element_Call_Data *data = d;
95 E_Connman_Element_Pending *pending;
97 pending = data->pending;
98 pending->pending = NULL;
101 data->cb(data->element, msg, err);
103 if (pending->user_cb)
104 pending->user_cb(pending->user_data, msg, err);
106 pending->data = NULL;
107 *data->p_list = eina_inlist_remove(*data->p_list, EINA_INLIST_GET(pending));
113 e_connman_element_pending_cancel_and_free(Eina_Inlist **pending)
117 E_Connman_Element_Pending *p = (E_Connman_Element_Pending *)*pending;
120 dbus_pending_call_cancel(p->pending);
122 dbus_error_init(&err);
123 dbus_set_error(&err, "Canceled", "Pending method call was canceled.");
124 e_connman_element_call_dispatch_and_free(p->data, NULL, &err);
125 dbus_error_free(&err);
130 e_connman_element_listener_add(E_Connman_Element *element, void (*cb)(void *data, const E_Connman_Element *element), const void *data, void (*free_data)(void *data))
132 E_Connman_Element_Listener *l;
133 EINA_SAFETY_ON_FALSE_GOTO(element, error);
134 EINA_SAFETY_ON_FALSE_GOTO(cb, error);
136 l = malloc(sizeof(*l));
139 ERR("could not allocate E_Connman_Element_Listener");
144 l->data = (void *)data;
145 l->free_data = free_data;
147 element->_listeners = eina_inlist_append
148 (element->_listeners, EINA_INLIST_GET(l));
154 free_data((void *)data);
158 e_connman_element_listener_del(E_Connman_Element *element, void (*cb)(void *data, const E_Connman_Element *element), const void *data)
160 E_Connman_Element_Listener *l;
162 EINA_SAFETY_ON_NULL_RETURN(element);
163 EINA_SAFETY_ON_NULL_RETURN(cb);
165 EINA_INLIST_FOREACH(element->_listeners, l)
166 if ((l->cb == cb) && (l->data == data))
168 element->_listeners = eina_inlist_remove
169 (element->_listeners, EINA_INLIST_GET(l));
171 l->free_data(l->data);
179 _e_connman_element_listeners_call_do(E_Connman_Element *element)
181 E_Connman_Element_Listener *l, **shadow;
182 unsigned int i, count;
184 /* NB: iterate on a copy in order to allow listeners to be deleted
185 * from callbacks. number of listeners should be small, so the
186 * following should do fine.
188 count = eina_inlist_count(element->_listeners);
192 shadow = alloca(sizeof(*shadow) * count);
197 EINA_INLIST_FOREACH(element->_listeners, l)
200 for (i = 0; i < count; i++)
201 shadow[i]->cb(shadow[i]->data, element);
204 e_connman_element_event_add(E_CONNMAN_EVENT_ELEMENT_UPDATED, element);
208 _e_connman_element_listeners_call_idler(void *data)
210 E_Connman_Element *element = data;
211 _e_connman_element_listeners_call_do(element);
212 element->_idler.changed = NULL;
213 return ECORE_CALLBACK_CANCEL;
217 _e_connman_element_listeners_call(E_Connman_Element *element)
219 if (element->_idler.changed)
222 element->_idler.changed = ecore_idler_add
223 (_e_connman_element_listeners_call_idler, element);
226 /***********************************************************************
228 ***********************************************************************/
231 _e_connman_element_dict_entry_free(E_Connman_Element_Dict_Entry *entry)
235 case DBUS_TYPE_BOOLEAN:
237 case DBUS_TYPE_UINT16:
238 case DBUS_TYPE_UINT32:
241 case DBUS_TYPE_OBJECT_PATH:
242 eina_stringshare_del(entry->value.path);
245 case DBUS_TYPE_STRING:
246 eina_stringshare_del(entry->value.str);
250 ERR("don't know how to free dict entry '%s' of type %c (%d)",
251 entry->name, entry->type, entry->type);
254 eina_stringshare_del(entry->name);
258 static E_Connman_Element_Dict_Entry *
259 _e_connman_element_dict_entry_new(DBusMessageIter *itr)
261 E_Connman_Element_Dict_Entry *entry;
262 DBusMessageIter e_itr, v_itr;
264 const char *key = NULL;
267 dbus_message_iter_recurse(itr, &e_itr);
269 t = dbus_message_iter_get_arg_type(&e_itr);
270 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
272 ERR("invalid format for dict entry. first type not a string: %c (%d)",
277 dbus_message_iter_get_basic(&e_itr, &key);
280 ERR("invalid format for dict entry. no key.");
284 dbus_message_iter_next(&e_itr);
285 t = dbus_message_iter_get_arg_type(&e_itr);
286 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
288 ERR("invalid format for dict entry '%s'. "
289 "second type not a variant: %c (%d)",
294 dbus_message_iter_recurse(&e_itr, &v_itr);
296 t = dbus_message_iter_get_arg_type(&v_itr);
297 if ((t == DBUS_TYPE_INVALID) || (t == DBUS_TYPE_ARRAY))
299 ERR("invalid type for dict value for entry '%s': %c (%d)",
304 entry = calloc(1, sizeof(*entry));
307 ERR("could not allocate memory for dict entry.");
311 dbus_message_iter_get_basic(&v_itr, &value);
314 case DBUS_TYPE_BOOLEAN:
315 entry->value.boolean = (Eina_Bool)(long)value;
319 entry->value.byte = (unsigned char)(long)value;
322 case DBUS_TYPE_UINT16:
323 entry->value.u16 = (unsigned short)(long)value;
326 case DBUS_TYPE_UINT32:
327 entry->value.u32 = (unsigned int)(long)value;
330 case DBUS_TYPE_STRING:
331 entry->value.str = eina_stringshare_add(value);
334 case DBUS_TYPE_OBJECT_PATH:
335 entry->value.path = eina_stringshare_add(value);
339 ERR("don't know how to create dict entry '%s' for of type %c (%d)",
345 entry->name = eina_stringshare_add(key);
350 static E_Connman_Element_Dict_Entry *
351 _e_connman_element_array_dict_find_stringshared(const E_Connman_Array *array, const char *key)
353 E_Connman_Element_Dict_Entry *entry;
354 Eina_Array_Iterator iterator;
357 EINA_ARRAY_ITER_NEXT(array->array, i, entry, iterator)
358 if (entry->name == key)
365 _e_connman_element_array_free(E_Connman_Array *array, E_Connman_Array *new __UNUSED__)
367 Eina_Array_Iterator iterator;
376 case DBUS_TYPE_BOOLEAN:
378 case DBUS_TYPE_UINT16:
379 case DBUS_TYPE_UINT32:
382 case DBUS_TYPE_STRING:
383 case DBUS_TYPE_OBJECT_PATH:
384 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
385 eina_stringshare_del(item);
388 case DBUS_TYPE_DICT_ENTRY:
389 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
390 _e_connman_element_dict_entry_free(item);
394 ERR("don't know how to free array of values of type %c (%d)",
395 array->type, array->type);
398 eina_array_free(array->array);
403 _e_connman_element_property_value_free(E_Connman_Element_Property *property)
405 switch (property->type)
410 case DBUS_TYPE_BOOLEAN:
412 case DBUS_TYPE_UINT16:
413 case DBUS_TYPE_UINT32:
416 case DBUS_TYPE_STRING:
417 eina_stringshare_del(property->value.str);
420 case DBUS_TYPE_OBJECT_PATH:
421 eina_stringshare_del(property->value.path);
424 case DBUS_TYPE_ARRAY:
425 _e_connman_element_array_free(property->value.array, NULL);
429 ERR("don't know how to free value of property type %c (%d)",
430 property->type, property->type);
435 _e_connman_element_get_interface(const char *key)
437 const char *interface = NULL, *tail;
446 if (strcmp(tail, "rofiles") == 0)
447 interface = e_connman_iface_profile;
452 if (strcmp(tail, "ervices") == 0)
453 interface = e_connman_iface_service;
458 if (strcmp(tail, "echnologies") == 0)
459 interface = e_connman_iface_technology;
468 ERR("failed to find interface for property \"%s\"", key);
474 _e_connman_element_item_register(const char *key, const char *item)
476 E_Connman_Element *element;
477 const char *interface;
479 interface = _e_connman_element_get_interface(key);
483 element = e_connman_element_register(item, interface);
484 if ((element) && (!e_connman_element_properties_sync(element)))
485 WRN("could not get properties of %s", element->path);
488 /* Match 2 arrays to find which are new and which are old elements
489 * For new elements, register them under prop_name property
490 * For old elements, unregister them, sending proper DEL event
493 _e_connman_element_array_match(E_Connman_Array *old, E_Connman_Array *new, const char *prop_name)
495 Eina_List *deleted = NULL;
496 Eina_Array_Iterator iter_old, iter_new;
497 unsigned int i_old = 0, i_new = 0;
498 void *item_old, *item_new;
505 if (old->type != DBUS_TYPE_OBJECT_PATH)
508 if ((!new) || (!new->array) || eina_array_count_get(new->array) == 0)
510 if ((!old) || (!old->array) || eina_array_count_get(old->array) == 0)
516 iter_old = old->array->data;
517 goto out_remove_remaining;
521 iter_new = new->array->data;
522 item_new = *iter_new;
523 EINA_ARRAY_ITER_NEXT(old->array, i_old, item_old, iter_old)
525 if (item_old == item_new)
528 if (i_new >= eina_array_count_get(new->array))
535 item_new = *iter_new;
539 deleted = eina_list_append(deleted, item_old);
543 for(; i_new < eina_array_count_get(new->array); iter_new++, i_new++)
545 Eina_Bool found = EINA_FALSE;
546 item_new = *iter_new;
550 EINA_LIST_FOREACH(deleted, l, data)
552 if (data == item_new)
554 deleted = eina_list_remove_list(deleted, l);
561 _e_connman_element_item_register(prop_name, item_new);
562 DBG("Add element %s\n", (const char *)item_new);
566 /* everybody after i_old on old->array + everybody from deleted list
569 EINA_LIST_FREE(deleted, data)
571 E_Connman_Element *e = e_connman_element_get(data);
573 e_connman_element_unregister(e);
575 DBG("Delete element %s\n", (const char *)data);
578 out_remove_remaining:
579 for(; i_old < eina_array_count_get(old->array); iter_old++, i_old++)
581 E_Connman_Element *e;
582 item_old = *iter_old;
586 e = e_connman_element_get(item_old);
588 e_connman_element_unregister(e);
590 DBG("Delete element %s\n", (const char *)item_old);
595 _e_connman_element_property_update(E_Connman_Element_Property *property, int type, void *data)
597 Eina_Bool changed = EINA_FALSE;
599 if ((type == DBUS_TYPE_STRING || type == DBUS_TYPE_OBJECT_PATH) && data)
600 data = (char *)eina_stringshare_add(data);
602 if (property->type != type)
605 DBG("property type changed from '%c' to '%c'",
606 property->type, type);
608 _e_connman_element_property_value_free(property);
609 memset(&property->value, 0, sizeof(property->value));
610 property->type = type;
616 case DBUS_TYPE_BOOLEAN:
617 if (changed || property->value.boolean != (Eina_Bool)(long)data)
619 property->value.boolean = (Eina_Bool)(long)data;
626 if (changed || property->value.byte != (unsigned char)(long)data)
628 property->value.byte = (unsigned char)(long)data;
634 case DBUS_TYPE_UINT16:
635 if (changed || property->value.u16 != (unsigned short)(long)data)
637 property->value.u16 = (unsigned short)(long)data;
643 case DBUS_TYPE_UINT32:
644 if (changed || property->value.u32 != (unsigned int)(long)data)
646 property->value.u32 = (unsigned int)(long)data;
652 case DBUS_TYPE_STRING:
655 property->value.str = data;
659 if (property->value.str)
660 eina_stringshare_del(property->value.str);
662 if (property->value.str != data)
664 property->value.str = data;
671 case DBUS_TYPE_OBJECT_PATH:
674 property->value.path = data;
678 if (property->value.path)
679 eina_stringshare_del(property->value.path);
681 if (property->value.path != data)
683 property->value.path = data;
690 case DBUS_TYPE_ARRAY:
692 if (property->value.array)
694 _e_connman_element_array_match(property->value.array, data, property->name);
695 _e_connman_element_array_free(property->value.array, data);
698 property->value.array = data;
703 ERR("don't know how to update property type %c (%d)", type, type);
709 static E_Connman_Element_Property *
710 _e_connman_element_property_new(const char *name, int type, void *data)
712 E_Connman_Element_Property *property;
714 property = calloc(1, sizeof(*property));
717 eina_stringshare_del(name);
718 ERR("could not allocate property: %s", strerror(errno));
722 property->name = name;
723 _e_connman_element_property_update(property, type, data);
728 _e_connman_element_property_free(E_Connman_Element_Property *property)
730 _e_connman_element_property_value_free(property);
731 eina_stringshare_del(property->name);
735 /***********************************************************************
737 ***********************************************************************/
739 e_connman_element_bytes_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count)
741 Eina_Array_Iterator iterator;
742 E_Connman_Array *array;
743 unsigned char *ret, *p;
747 EINA_SAFETY_ON_NULL_RETURN_VAL(element, NULL);
748 EINA_SAFETY_ON_NULL_RETURN_VAL(property, NULL);
749 EINA_SAFETY_ON_NULL_RETURN_VAL(count, NULL);
753 if (!e_connman_element_property_get_stringshared
754 (element, property, NULL, &array))
757 if ((!array) || (!(array->array)))
760 *count = eina_array_count_get(array->array);
761 ret = malloc(*count * sizeof(unsigned char));
764 ERR("could not allocate return array of %d bytes: %s",
765 *count, strerror(errno));
771 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
773 *p = (unsigned char)(long)item;
780 e_connman_element_objects_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count, E_Connman_Element ***p_elements)
782 E_Connman_Element **ret, **p;
783 Eina_Array_Iterator iterator;
784 E_Connman_Array *array;
789 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
790 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
791 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
792 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
797 if (!e_connman_element_property_get_stringshared
798 (element, property, &type, &array))
801 if (type != DBUS_TYPE_ARRAY)
803 ERR("property %s is not an array!", property);
807 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
810 if (array->type != DBUS_TYPE_OBJECT_PATH)
812 ERR("property %s is not an array of object paths!", property);
816 *count = eina_array_count_get(array->array);
817 ret = malloc(*count * sizeof(E_Connman_Element *));
820 ERR("could not allocate return array of %d elements: %s",
821 *count, strerror(errno));
828 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
830 E_Connman_Element *e = e_connman_element_get(item);
842 /* strings are just pointers (references), no strdup or stringshare_add/ref */
844 e_connman_element_strings_array_get_stringshared(const E_Connman_Element *element, const char *property, unsigned int *count, const char ***strings)
846 const char **ret, **p;
847 Eina_Array_Iterator iterator;
848 E_Connman_Array *array;
853 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
854 EINA_SAFETY_ON_NULL_RETURN_VAL(property, EINA_FALSE);
855 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
856 EINA_SAFETY_ON_NULL_RETURN_VAL(strings, EINA_FALSE);
861 if (!e_connman_element_property_get_stringshared
862 (element, property, &type, &array))
865 if (type != DBUS_TYPE_ARRAY)
867 ERR("property %s is not an array!", property);
871 if ((!array) || (!array->array) || (array->type == DBUS_TYPE_INVALID))
874 if (array->type != DBUS_TYPE_STRING)
876 ERR("property %s is not an array of strings!", property);
880 *count = eina_array_count_get(array->array);
881 ret = malloc(*count * sizeof(char *));
884 ERR("could not allocate return array of %d strings: %s",
885 *count, strerror(errno));
892 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
906 _e_connman_element_array_print(FILE *fp, E_Connman_Array *array)
908 Eina_Array_Iterator iterator;
917 case DBUS_TYPE_OBJECT_PATH:
918 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
919 fprintf(fp, "\"%s\", ", (const char *)item);
922 case DBUS_TYPE_STRING:
923 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
924 fprintf(fp, "\"%s\", ", (const char *)item);
928 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
929 fprintf(fp, "%#02hhx (\"%c\"), ", (unsigned char)(long)item,
930 (unsigned char)(long)item);
933 case DBUS_TYPE_UINT16:
934 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
935 fprintf(fp, "%#04hx (%hu), ", (unsigned short)(long)item,
936 (unsigned short)(long)item);
939 case DBUS_TYPE_UINT32:
940 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
941 fprintf(fp, "%#08x (%u), ", (unsigned int)(long)item,
942 (unsigned int)(long)item);
945 case DBUS_TYPE_DICT_ENTRY:
947 EINA_ARRAY_ITER_NEXT(array->array, i, item, iterator)
949 E_Connman_Element_Dict_Entry *entry = item;
950 fprintf(fp, "%s: ", entry->name);
953 case DBUS_TYPE_OBJECT_PATH:
954 fprintf(fp, "\"%s\", ", entry->value.path);
957 case DBUS_TYPE_STRING:
958 fprintf(fp, "\"%s\", ", entry->value.str);
962 fprintf(fp, "%#02hhx (\"%c\"), ",
963 entry->value.byte, entry->value.byte);
966 case DBUS_TYPE_UINT16:
967 fprintf(fp, "%#04hx (%hu), ",
968 entry->value.u16, entry->value.u16);
971 case DBUS_TYPE_UINT32:
972 fprintf(fp, "%#08x (%u), ",
973 entry->value.u32, entry->value.u32);
977 fprintf(fp, "<UNKNOWN TYPE '%c'>", entry->type);
984 fprintf(fp, "<UNKNOWN ARRAY TYPE '%c'>", array->type);
989 * Print element to file descriptor.
992 e_connman_element_print(FILE *fp, const E_Connman_Element *element)
994 const E_Connman_Element_Property *p;
996 EINA_SAFETY_ON_NULL_RETURN(fp);
999 fputs("Error: no element to print\n", fp);
1004 "Element %p: %s [%s]\n"
1006 element, element->path, element->interface);
1008 EINA_INLIST_FOREACH(element->props, p)
1010 fprintf(fp, "\t\t%s (%c) = ", p->name, p->type);
1014 case DBUS_TYPE_STRING:
1015 fprintf(fp, "\"%s\"", p->value.str);
1018 case DBUS_TYPE_OBJECT_PATH:
1019 fprintf(fp, "\"%s\"", p->value.path);
1022 case DBUS_TYPE_BOOLEAN:
1023 fprintf(fp, "%hhu", p->value.boolean);
1026 case DBUS_TYPE_BYTE:
1027 fprintf(fp, "%#02hhx (%d), ", p->value.byte, p->value.byte);
1030 case DBUS_TYPE_UINT16:
1031 fprintf(fp, "%hu", p->value.u16);
1034 case DBUS_TYPE_UINT32:
1035 fprintf(fp, "%u", p->value.u32);
1038 case DBUS_TYPE_ARRAY:
1039 _e_connman_element_array_print(fp, p->value.array);
1043 fputs("don't know how to print type", fp);
1050 static E_Connman_Element *
1051 e_connman_element_new(const char *path, const char *interface)
1053 E_Connman_Element *element;
1055 element = calloc(1, sizeof(*element));
1058 ERR("could not allocate element: %s", strerror(errno));
1062 element->path = eina_stringshare_add(path);
1063 element->interface = eina_stringshare_ref(interface);
1064 element->_references = 1;
1070 e_connman_element_extra_properties_free(E_Connman_Element *element)
1072 while (element->props)
1074 E_Connman_Element_Property *prop;
1075 prop = (E_Connman_Element_Property *)element->props;
1076 element->props = element->props->next;
1077 _e_connman_element_property_free(prop);
1082 e_connman_element_free(E_Connman_Element *element)
1084 if (element->_idler.changed)
1085 ecore_idler_del(element->_idler.changed);
1087 while (element->_listeners)
1089 E_Connman_Element_Listener *l = (void *)element->_listeners;
1090 element->_listeners = eina_inlist_remove
1091 (element->_listeners, element->_listeners);
1094 l->free_data(l->data);
1099 e_connman_element_pending_cancel_and_free(&element->_pending.properties_get);
1100 e_connman_element_pending_cancel_and_free(&element->_pending.property_set);
1101 e_connman_element_pending_cancel_and_free(&element->_pending.agent_register);
1102 e_connman_element_pending_cancel_and_free(&element->_pending.agent_unregister);
1103 e_connman_element_pending_cancel_and_free(&element->_pending.request_scan);
1104 e_connman_element_pending_cancel_and_free(&element->_pending.technology_enable);
1105 e_connman_element_pending_cancel_and_free(&element->_pending.technology_disable);
1106 e_connman_element_pending_cancel_and_free(&element->_pending.profile_remove);
1107 e_connman_element_pending_cancel_and_free(&element->_pending.service_connect);
1108 e_connman_element_pending_cancel_and_free(&element->_pending.service_disconnect);
1109 e_connman_element_pending_cancel_and_free(&element->_pending.service_remove);
1110 e_connman_element_pending_cancel_and_free(&element->_pending.service_move_before);
1111 e_connman_element_pending_cancel_and_free(&element->_pending.service_move_after);
1112 e_connman_element_pending_cancel_and_free(&element->_pending.service_clear_property);
1114 e_connman_element_extra_properties_free(element);
1115 eina_stringshare_del(element->interface);
1116 eina_stringshare_del(element->path);
1121 * Add reference to element.
1124 e_connman_element_ref(E_Connman_Element *element)
1126 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1127 return ++element->_references;
1131 * Remove reference from element.
1133 * If reference count drops to 0 element will be freed.
1136 e_connman_element_unref(E_Connman_Element *element)
1139 EINA_SAFETY_ON_NULL_RETURN_VAL(element, 0);
1141 i = --element->_references;
1143 e_connman_element_free(element);
1145 ERR("element %p references %d < 0", element, i);
1151 * Send message with callbacks set to work with connman elements.
1153 * If this call fails (returns @c EINA_FALSE), pending callbacks will not be called,
1154 * not even with error messages.
1156 * @return @c EINA_TRUE on success, @c EINA_FALSE on failure.
1159 e_connman_element_message_send(E_Connman_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, DBusMessage *msg, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1161 E_Connman_Element_Call_Data *data;
1162 E_Connman_Element_Pending *p;
1164 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1165 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1166 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1167 EINA_SAFETY_ON_NULL_RETURN_VAL(msg, EINA_FALSE);
1169 data = malloc(sizeof(*data));
1172 ERR("could not alloc e_connman_element_call_data: %s",
1174 dbus_message_unref(msg);
1178 p = malloc(sizeof(*p));
1181 ERR("could not alloc E_Connman_Element_Pending: %s",
1184 dbus_message_unref(msg);
1188 data->element = element;
1191 data->p_list = pending;
1192 p->user_cb = user_cb;
1193 p->user_data = (void *)user_data;
1195 p->pending = e_dbus_message_send
1196 (e_connman_conn, msg, e_connman_element_call_dispatch_and_free, -1, data);
1197 dbus_message_unref(msg);
1201 *pending = eina_inlist_append(*pending, EINA_INLIST_GET(p));
1205 ERR("failed to call %s (obj=%s, path=%s, iface=%s)",
1206 method_name, e_connman_system_bus_name_get(),
1207 element->path, element->interface);
1214 e_connman_element_call_full(E_Connman_Element *element, const char *method_name, E_DBus_Method_Return_Cb cb, Eina_Inlist **pending, E_DBus_Method_Return_Cb user_cb, const void *user_data)
1218 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1219 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1220 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1222 msg = dbus_message_new_method_call
1223 (e_connman_system_bus_name_get(), element->path, element->interface,
1226 return e_connman_element_message_send
1227 (element, method_name, cb, msg, pending, user_cb, user_data);
1231 _e_connman_element_property_value_add(E_Connman_Element *element, const char *name, int type, void *value)
1233 E_Connman_Element_Property *p;
1235 name = eina_stringshare_add(name);
1236 EINA_INLIST_FOREACH(element->props, p)
1238 if (p->name == name)
1240 eina_stringshare_del(name);
1241 return _e_connman_element_property_update(p, type, value);
1245 p = _e_connman_element_property_new(name, type, value);
1248 ERR("could not create property %s (%c)", name, type);
1252 element->props = eina_inlist_append(element->props, EINA_INLIST_GET(p));
1256 static E_Connman_Array *
1257 _e_connman_element_iter_get_array(DBusMessageIter *itr, const char *key)
1259 E_Connman_Array *array;
1260 DBusMessageIter e_itr;
1262 array = malloc(sizeof(E_Connman_Array));
1265 ERR("could not create new e_connman array.");
1269 array->array = eina_array_new(16);
1270 if (!(array->array))
1272 ERR("could not create new eina array.");
1277 dbus_message_iter_recurse(itr, &e_itr);
1278 array->type = dbus_message_iter_get_arg_type(&e_itr);
1279 if (array->type == DBUS_TYPE_INVALID)
1281 DBG("array %s is of type 'invalid' (empty?)", key);
1282 eina_array_free(array->array);
1289 switch (array->type)
1291 case DBUS_TYPE_OBJECT_PATH:
1295 dbus_message_iter_get_basic(&e_itr, &path);
1296 path = eina_stringshare_add(path);
1297 eina_array_push(array->array, path);
1298 _e_connman_element_item_register(key, path);
1302 case DBUS_TYPE_STRING:
1306 dbus_message_iter_get_basic(&e_itr, &str);
1307 str = eina_stringshare_add(str);
1308 eina_array_push(array->array, str);
1312 case DBUS_TYPE_BYTE:
1315 dbus_message_iter_get_basic(&e_itr, &byte);
1316 eina_array_push(array->array, (void *)(long)byte);
1320 case DBUS_TYPE_DICT_ENTRY:
1322 E_Connman_Element_Dict_Entry *entry;
1323 entry = _e_connman_element_dict_entry_new(&e_itr);
1325 eina_array_push(array->array, entry);
1330 ERR("don't know how to build array '%s' of type %c (%d)",
1331 key, array->type, array->type);
1332 eina_array_free(array->array);
1337 while (dbus_message_iter_next(&e_itr));
1342 _e_connman_element_get_properties_callback(void *user_data, DBusMessage *msg, DBusError *err)
1344 E_Connman_Element *element = user_data;
1345 DBusMessageIter itr, s_itr;
1348 DBG("get_properties msg=%p", msg);
1350 if (!_dbus_callback_check_and_init(msg, &itr, err))
1353 t = dbus_message_iter_get_arg_type(&itr);
1354 if (!_dbus_iter_type_check(t, DBUS_TYPE_ARRAY))
1358 dbus_message_iter_recurse(&itr, &s_itr);
1361 DBusMessageIter e_itr, v_itr;
1366 t = dbus_message_iter_get_arg_type(&s_itr);
1367 if (!_dbus_iter_type_check(t, DBUS_TYPE_DICT_ENTRY))
1370 dbus_message_iter_recurse(&s_itr, &e_itr);
1372 t = dbus_message_iter_get_arg_type(&e_itr);
1373 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
1376 dbus_message_iter_get_basic(&e_itr, &key);
1377 dbus_message_iter_next(&e_itr);
1378 t = dbus_message_iter_get_arg_type(&e_itr);
1379 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
1382 dbus_message_iter_recurse(&e_itr, &v_itr);
1383 t = dbus_message_iter_get_arg_type(&v_itr);
1384 if (t == DBUS_TYPE_ARRAY)
1386 value = _e_connman_element_iter_get_array(&v_itr, key);
1388 else if (t != DBUS_TYPE_INVALID)
1390 dbus_message_iter_get_basic(&v_itr, &value);
1394 ERR("property has invalid type %s", key);
1398 r = _e_connman_element_property_value_add(element, key, t, value);
1401 ERR("failed to add property value %s (%c)", key, t);
1405 INF("property value changed %s (%c)", key, t);
1409 while (dbus_message_iter_next(&s_itr));
1412 _e_connman_element_listeners_call(element);
1416 * Sync element properties with server.
1418 * Call method GetProperties() at the given element on server in order to sync
1421 * @param element to call method on server.
1422 * @param cb function to call when server replies or some error happens.
1423 * @param data data to give to cb when it is called.
1425 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1428 e_connman_element_sync_properties_full(E_Connman_Element *element, E_DBus_Method_Return_Cb cb, const void *data)
1430 const char name[] = "GetProperties";
1432 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1433 return e_connman_element_call_full
1434 (element, name, _e_connman_element_get_properties_callback,
1435 &element->_pending.properties_get, cb, data);
1439 * Sync element properties with server, simple version.
1441 * Call method GetProperties() at the given element on server in order to sync
1442 * them. This is the simple version and there is no check of server reply
1445 * @param element to call method on server.
1447 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1450 e_connman_element_properties_sync(E_Connman_Element *element)
1452 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1453 return e_connman_element_sync_properties_full(element, NULL, NULL);
1457 * Call method SetProperty(prop, {key: value}) at the given element on server.
1459 * This is a server call, not local, so it may fail and in that case
1460 * no property is updated locally. If the value was set the event
1461 * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
1463 * @param element to call method on server.
1464 * @param prop property name.
1465 * @param key dict key name.
1466 * @param type DBus type to use for value.
1467 * @param value pointer to value, just like regular DBus, see
1468 * dbus_message_iter_append_basic().
1469 * @param cb function to call when server replies or some error happens.
1470 * @param data data to give to cb when it is called.
1472 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1475 e_connman_element_property_dict_set_full(E_Connman_Element *element, const char *prop, const char *key, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
1477 const char name[] = "SetProperty";
1479 DBusMessageIter itr, variant, dict, entry;
1482 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1483 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1485 msg = dbus_message_new_method_call
1486 (e_connman_system_bus_name_get(), element->path, element->interface, name);
1491 dbus_message_iter_init_append(msg, &itr);
1492 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1494 if ((size_t)snprintf(typestr, sizeof(typestr),
1495 (DBUS_TYPE_ARRAY_AS_STRING
1496 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1497 DBUS_TYPE_STRING_AS_STRING
1499 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1500 type) >= sizeof(typestr))
1502 ERR("sizeof(typestr) is too small!");
1506 dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &variant);
1508 snprintf(typestr, sizeof(typestr),
1509 (DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
1510 DBUS_TYPE_STRING_AS_STRING
1512 DBUS_DICT_ENTRY_END_CHAR_AS_STRING),
1515 dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, typestr, &dict);
1516 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry);
1518 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
1520 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1521 dbus_message_iter_append_basic(&entry, type, &value);
1523 dbus_message_iter_append_basic(&entry, type, value);
1525 dbus_message_iter_close_container(&dict, &entry);
1526 dbus_message_iter_close_container(&variant, &dict);
1527 dbus_message_iter_close_container(&itr, &variant);
1529 return e_connman_element_message_send
1530 (element, name, NULL, msg, &element->_pending.property_set, cb, data);
1534 * Call method SetProperty(prop, value) at the given element on server.
1536 * This is a server call, not local, so it may fail and in that case
1537 * no property is updated locally. If the value was set the event
1538 * E_CONNMAN_EVENT_ELEMENT_UPDATED will be added to main loop.
1540 * @param element to call method on server.
1541 * @param prop property name.
1542 * @param type DBus type to use for value.
1543 * @param value pointer to value, just like regular DBus, see
1544 * dbus_message_iter_append_basic().
1545 * @param cb function to call when server replies or some error happens.
1546 * @param data data to give to cb when it is called.
1548 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1551 e_connman_element_property_set_full(E_Connman_Element *element, const char *prop, int type, const void *value, E_DBus_Method_Return_Cb cb, const void *data)
1553 const char name[] = "SetProperty";
1557 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1558 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1560 msg = dbus_message_new_method_call
1561 (e_connman_system_bus_name_get(), element->path, element->interface, name);
1566 DBusMessageIter itr, v;
1567 dbus_message_iter_init_append(msg, &itr);
1568 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &prop);
1572 dbus_message_iter_open_container(&itr, DBUS_TYPE_VARIANT, typestr, &v);
1573 if ((type == DBUS_TYPE_STRING) || (type == DBUS_TYPE_OBJECT_PATH))
1575 dbus_message_iter_append_basic(&v, type, &value);
1577 else if (type == DBUS_TYPE_BOOLEAN)
1579 unsigned int b = *(char *)value;
1580 dbus_message_iter_append_basic(&v, type, &b);
1584 dbus_message_iter_append_basic(&v, type, value);
1587 dbus_message_iter_close_container(&itr, &v);
1589 return e_connman_element_message_send
1590 (element, name, NULL, msg, &element->_pending.property_set, cb, data);
1594 * Call method SetProperty(prop, value) at the given element on server.
1596 * This is the simple version and there is no check of server reply
1599 * @param element to call method on server.
1600 * @param prop property name.
1601 * @param type DBus type to use for value.
1602 * @param value pointer to value, just like regular DBus, see
1603 * dbus_message_iter_append_basic().
1605 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1608 e_connman_element_property_set(E_Connman_Element *element, const char *prop, int type, const void *value)
1610 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1611 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
1612 return e_connman_element_property_set_full
1613 (element, prop, type, value, NULL, NULL);
1617 e_connman_element_call_with_path(E_Connman_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)
1619 DBusMessageIter itr;
1622 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1623 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1624 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1625 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1627 msg = dbus_message_new_method_call
1628 (e_connman_system_bus_name_get(), element->path, element->interface,
1634 dbus_message_iter_init_append(msg, &itr);
1635 dbus_message_iter_append_basic(&itr, DBUS_TYPE_OBJECT_PATH, &string);
1637 return e_connman_element_message_send
1638 (element, method_name, cb, msg, pending, user_cb, user_data);
1642 e_connman_element_call_with_string(E_Connman_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)
1644 DBusMessageIter itr;
1647 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1648 EINA_SAFETY_ON_NULL_RETURN_VAL(method_name, EINA_FALSE);
1649 EINA_SAFETY_ON_NULL_RETURN_VAL(string, EINA_FALSE);
1650 EINA_SAFETY_ON_NULL_RETURN_VAL(pending, EINA_FALSE);
1652 msg = dbus_message_new_method_call
1653 (e_connman_system_bus_name_get(), element->path, element->interface,
1659 dbus_message_iter_init_append(msg, &itr);
1660 dbus_message_iter_append_basic(&itr, DBUS_TYPE_STRING, &string);
1662 return e_connman_element_message_send
1663 (element, method_name, cb, msg, pending, user_cb, user_data);
1667 * Get property type.
1669 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1670 * values shall be considered invalid.
1672 * @param element which element to get the property
1673 * @param name property name, must be previously stringshared
1674 * @param type will contain the value type.
1676 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1679 e_connman_element_property_type_get_stringshared(const E_Connman_Element *element, const char *name, int *type)
1681 const E_Connman_Element_Property *p;
1683 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1684 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1685 EINA_SAFETY_ON_NULL_RETURN_VAL(type, EINA_FALSE);
1687 EINA_INLIST_FOREACH(element->props, p)
1689 if (p->name == name)
1696 WRN("element %s (%p) has no property with name \"%s\".",
1697 element->path, element, name);
1702 * Get property type.
1704 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1705 * values shall be considered invalid.
1707 * @param element which element to get the property
1708 * @param name property name
1709 * @param type will contain the value type.
1711 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1714 e_connman_element_property_type_get(const E_Connman_Element *element, const char *name, int *type)
1717 name = eina_stringshare_add(name);
1718 ret = e_connman_element_property_type_get_stringshared(element, name, type);
1719 eina_stringshare_del(name);
1724 e_connman_element_list_properties(const E_Connman_Element *element, Eina_Bool (*cb)(void *data, const E_Connman_Element *element, const char *name, int type, const void *value), const void *data)
1726 const E_Connman_Element_Property *p;
1728 EINA_SAFETY_ON_NULL_RETURN(element);
1729 EINA_SAFETY_ON_NULL_RETURN(cb);
1731 EINA_INLIST_FOREACH(element->props, p)
1733 const void *value = NULL;
1737 case DBUS_TYPE_STRING:
1738 value = &p->value.str;
1741 case DBUS_TYPE_OBJECT_PATH:
1742 value = &p->value.path;
1745 case DBUS_TYPE_BOOLEAN:
1746 value = (void *)&p->value.boolean;
1749 case DBUS_TYPE_UINT16:
1750 value = &p->value.u16;
1753 case DBUS_TYPE_UINT32:
1754 value = &p->value.u32;
1758 ERR("unsupported type %c", p->type);
1761 if (!cb((void *)data, element, p->name, p->type, value))
1767 * Get dict value given its key inside a dict property.
1769 * This will look into properties for one of type dict that contains
1770 * the given key, to find the property. If no property is found then
1771 * @c EINA_FALSE is returned.
1773 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1774 * values shall be considered invalid.
1776 * @param element which element to get the property
1777 * @param dict_name property name, must be previously stringshared
1778 * @param key key inside dict, must be previously stringshared
1779 * @param type if provided it will contain the value type.
1780 * @param value where to store the property value, must be a pointer to the
1781 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1783 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1786 e_connman_element_property_dict_get_stringshared(const E_Connman_Element *element, const char *dict_name, const char *key, int *type, void *value)
1788 const E_Connman_Element_Property *p;
1790 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1791 EINA_SAFETY_ON_NULL_RETURN_VAL(dict_name, EINA_FALSE);
1792 EINA_SAFETY_ON_NULL_RETURN_VAL(key, EINA_FALSE);
1793 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1795 EINA_INLIST_FOREACH(element->props, p)
1797 E_Connman_Element_Dict_Entry *entry;
1798 E_Connman_Array *array;
1800 if (p->name != dict_name)
1803 if (p->type != DBUS_TYPE_ARRAY)
1805 WRN("element %s (%p) has property \"%s\" is not an array: %c (%d)",
1806 element->path, element, dict_name, p->type, p->type);
1810 array = p->value.array;
1811 if ((!array) || (array->type != DBUS_TYPE_DICT_ENTRY))
1813 int t = array ? array->type : DBUS_TYPE_INVALID;
1814 WRN("element %s (%p) has property \"%s\" is not a dict: %c (%d)",
1815 element->path, element, dict_name, t, t);
1819 entry = _e_connman_element_array_dict_find_stringshared(array, key);
1822 WRN("element %s (%p) has no dict property with name \"%s\" with "
1824 element->path, element, dict_name, key);
1829 *type = entry->type;
1831 switch (entry->type)
1833 case DBUS_TYPE_BOOLEAN:
1834 *(Eina_Bool *)value = entry->value.boolean;
1837 case DBUS_TYPE_BYTE:
1838 *(unsigned char *)value = entry->value.byte;
1841 case DBUS_TYPE_UINT16:
1842 *(unsigned short *)value = entry->value.u16;
1845 case DBUS_TYPE_UINT32:
1846 *(unsigned int *)value = entry->value.u32;
1849 case DBUS_TYPE_STRING:
1850 *(const char **)value = entry->value.str;
1853 case DBUS_TYPE_OBJECT_PATH:
1854 *(const char **)value = entry->value.path;
1858 ERR("don't know how to get property %s, key %s type %c (%d)",
1859 dict_name, key, entry->type, entry->type);
1864 WRN("element %s (%p) has no property with name \"%s\".",
1865 element->path, element, dict_name);
1870 * Get property value given its name.
1872 * This will look into properties, to find the property.
1873 * If no property is found then @c EINA_FALSE is returned.
1875 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1876 * values shall be considered invalid.
1878 * @param element which element to get the property
1879 * @param name property name, must be previously stringshared
1880 * @param type if provided it will contain the value type.
1881 * @param value where to store the property value, must be a pointer to the
1882 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1884 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1887 e_connman_element_property_get_stringshared(const E_Connman_Element *element, const char *name, int *type, void *value)
1889 const E_Connman_Element_Property *p;
1891 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
1892 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
1893 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
1895 EINA_INLIST_FOREACH(element->props, p)
1897 if (p->name != name)
1905 case DBUS_TYPE_BOOLEAN:
1906 *(Eina_Bool *)value = p->value.boolean;
1909 case DBUS_TYPE_BYTE:
1910 *(unsigned char *)value = p->value.byte;
1913 case DBUS_TYPE_UINT16:
1914 *(unsigned short *)value = p->value.u16;
1917 case DBUS_TYPE_UINT32:
1918 *(unsigned int *)value = p->value.u32;
1921 case DBUS_TYPE_STRING:
1922 *(const char **)value = p->value.str;
1925 case DBUS_TYPE_OBJECT_PATH:
1926 *(const char **)value = p->value.path;
1929 case DBUS_TYPE_ARRAY:
1930 *(E_Connman_Array **)value = p->value.array;
1934 ERR("don't know how to get property type %c (%d)",
1940 WRN("element %s (%p) has no property with name \"%s\".",
1941 element->path, element, name);
1946 * Get property value given its name.
1948 * This will look into properties, to find the property.
1949 * If no property is found then @c EINA_FALSE is returned.
1951 * If @c EINA_FALSE is returned, then this call failed and parameter-returned
1952 * values shall be considered invalid.
1954 * @param element which element to get the property
1955 * @param name property name
1956 * @param type if provided it will contain the value type.
1957 * @param value where to store the property value, must be a pointer to the
1958 * exact type, (Eina_Bool *) for booleans, (char **) for strings, and so on.
1960 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
1963 e_connman_element_property_get(const E_Connman_Element *element, const char *name, int *type, void *value)
1966 name = eina_stringshare_add(name);
1967 ret = e_connman_element_property_get_stringshared
1968 (element, name, type, value);
1969 eina_stringshare_del(name);
1973 struct e_connman_elements_for_each_data
1975 Eina_Hash_Foreach cb;
1980 _e_connman_elements_for_each(Eina_Hash *hash __UNUSED__, const char *key, void *data, void *fdata)
1982 struct e_connman_elements_for_each_data *each_data = fdata;
1984 each_data->cb(elements, key, data, each_data->data);
1989 * Call the given function for each existing element.
1991 * @param cb function to call for each element. It will get as parameters,
1992 * in order: the element pointer and the given @a user_data.
1993 * @param user_data data to give to @a cb for each element.
1996 e_connman_elements_for_each(Eina_Hash_Foreach cb, const void *user_data)
1998 struct e_connman_elements_for_each_data data = {cb, (void *)user_data};
2000 EINA_SAFETY_ON_NULL_RETURN(cb);
2002 eina_hash_foreach(elements, (Eina_Hash_Foreach)_e_connman_elements_for_each,
2007 _e_connman_elements_get_allocate(unsigned int *count, E_Connman_Element ***p_elements)
2009 *count = eina_hash_population(elements);
2016 *p_elements = malloc(*count * sizeof(E_Connman_Element *));
2019 ERR("could not allocate return array of %d elements: %s",
2020 *count, strerror(errno));
2029 _e_connman_elements_get_all(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *data, void *fdata)
2031 E_Connman_Element *element = data;
2032 E_Connman_Element ***p_ret = fdata;
2040 * Get all known elements.
2042 * No reference is added to these elements, since there are no threads
2043 * in the system, you are free to add references yourself right after
2044 * the return of this call without race condition, elements by the
2045 * system (ie: elementRemoved signal)could only be touched on the next
2046 * main loop iteration.
2048 * @param count return the number of elements in array.
2049 * @param p_elements array with all elements, these are not referenced
2050 * and in no particular order, just set if return is @c EINA_TRUE.
2052 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2055 e_connman_elements_get_all(unsigned int *count, E_Connman_Element ***p_elements)
2057 E_Connman_Element **p;
2059 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2060 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2062 if (!_e_connman_elements_get_allocate(count, p_elements))
2066 eina_hash_foreach(elements, (Eina_Hash_Foreach)_e_connman_elements_get_all,
2071 struct e_connman_elements_get_all_str_data
2073 E_Connman_Element **elements;
2079 _e_connman_elements_get_all_type(Eina_Hash *hash __UNUSED__, const char *key __UNUSED__, void *e, void *user_data)
2081 struct e_connman_elements_get_all_str_data *data = user_data;
2082 E_Connman_Element *element = e;
2084 if ((data->str) && (element->interface != data->str))
2087 data->elements[data->count] = element;
2093 * Get all known elements of type.
2095 * No reference is added to these elements, since there are no threads
2096 * in the system, you are free to add references yourself right after
2097 * the return of this call without race condition, elements by the
2098 * system (ie: ElementRemoved signal) could only be touched on the next
2099 * main loop iteration.
2101 * @param type type to filter, or NULL to get all.
2102 * @param count return the number of elements in array.
2103 * @param p_elements array with all elements, these are not referenced
2104 * and in no particular order, just set if return is @c EINA_TRUE.
2106 * @return @c EINA_TRUE on success, @c EINA_FALSE otherwise.
2108 * @see e_connman_elements_get_all()
2111 e_connman_elements_get_all_type(const char *type, unsigned int *count, E_Connman_Element ***p_elements)
2113 struct e_connman_elements_get_all_str_data data;
2115 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
2116 EINA_SAFETY_ON_NULL_RETURN_VAL(p_elements, EINA_FALSE);
2118 if (!_e_connman_elements_get_allocate(count, p_elements))
2121 data.elements = *p_elements;
2123 data.str = eina_stringshare_add(type);
2124 eina_hash_foreach(elements,
2125 (Eina_Hash_Foreach)_e_connman_elements_get_all_type,
2128 eina_stringshare_del(data.str);
2129 *count = data.count;
2134 * Get the element registered at given path.
2136 * @param path the path to query for registered object.
2138 * @return element pointer if found, NULL otherwise. No references are added.
2141 e_connman_element_get(const char *path)
2143 E_Connman_Element *element;
2145 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2146 element = eina_hash_find(elements, path);
2152 _e_connman_element_property_changed_callback(void *data, DBusMessage *msg)
2154 E_Connman_Element *element = (E_Connman_Element *)data;
2155 DBusMessageIter itr, v_itr;
2156 int t, r, changed = 0;
2157 const char *name = NULL;
2160 DBG("Property changed in element %s", element->path);
2162 if (!_dbus_callback_check_and_init(msg, &itr, NULL))
2165 t = dbus_message_iter_get_arg_type(&itr);
2166 if (!_dbus_iter_type_check(t, DBUS_TYPE_STRING))
2168 ERR("missing name in property changed signal");
2172 dbus_message_iter_get_basic(&itr, &name);
2174 dbus_message_iter_next(&itr);
2175 t = dbus_message_iter_get_arg_type(&itr);
2176 if (!_dbus_iter_type_check(t, DBUS_TYPE_VARIANT))
2178 ERR("missing value in property changed signal");
2182 dbus_message_iter_recurse(&itr, &v_itr);
2183 t = dbus_message_iter_get_arg_type(&v_itr);
2185 if (t == DBUS_TYPE_ARRAY)
2187 value = _e_connman_element_iter_get_array(&v_itr, name);
2189 else if (t != DBUS_TYPE_INVALID)
2191 dbus_message_iter_get_basic(&v_itr, &value);
2195 ERR("property has invalid type %s", name);
2199 r = _e_connman_element_property_value_add(element, name, t, value);
2202 ERR("failed to add property value %s (%c)", name, t);
2206 INF("property value changed %s (%c)", name, t);
2211 _e_connman_element_listeners_call(element);
2215 * Register the given path, possible creating and element and return it.
2217 * This will check if path is already registered, in that case the
2218 * exiting element is returned. If it was not registered yet, a new
2219 * element is created, registered and returned.
2221 * This call will not add extra references to the object.
2223 * @param path the path to register the element
2225 * @return the registered object, no references are added.
2228 e_connman_element_register(const char *path, const char *interface)
2230 E_Connman_Element *element;
2232 EINA_SAFETY_ON_NULL_RETURN_VAL(path, NULL);
2233 EINA_SAFETY_ON_NULL_RETURN_VAL(interface, NULL);
2235 element = eina_hash_find(elements, path);
2239 element = e_connman_element_new(path, interface);
2243 if (!eina_hash_add(elements, element->path, element))
2245 ERR("could not add element %s to hash, delete it.", path);
2246 e_connman_element_free(element);
2250 element->signal_handler =
2251 e_dbus_signal_handler_add
2252 (e_connman_conn, e_connman_system_bus_name_get(),
2253 element->path, element->interface, "PropertyChanged",
2254 _e_connman_element_property_changed_callback, element);
2256 e_connman_element_event_add(E_CONNMAN_EVENT_ELEMENT_ADD, element);
2262 _e_connman_element_event_unregister_and_free(void *data __UNUSED__, void *ev)
2264 E_Connman_Element *element = ev;
2265 e_connman_element_unref(element);
2269 _e_connman_element_unregister_internal(E_Connman_Element *element)
2271 if (element->signal_handler)
2273 e_dbus_signal_handler_del(e_connman_conn, element->signal_handler);
2274 element->signal_handler = NULL;
2277 ecore_event_add(E_CONNMAN_EVENT_ELEMENT_DEL, element,
2278 _e_connman_element_event_unregister_and_free, NULL);
2282 * Forget about the given element.
2284 * This will remove the element from the pool of known objects, then
2285 * add an E_CONNMAN_EVENT_ELEMENT_DEL and after that will unreference it,
2286 * possible freeing it.
2288 * @param element element to forget about. Its reference will be removed.
2291 e_connman_element_unregister(E_Connman_Element *element)
2297 eina_hash_del_by_key(elements, element->path);
2301 * Remove all known elements.
2303 * This will remove all known elements but will NOT add any
2304 * E_CONNMAN_EVENT_ELEMENT_DEL to main loop.
2306 * This is just useful to make sure next e_connman_manager_sync_elements()
2307 * will not leave any stale elements. This is unlikely to happen, as
2308 * E_Connman is supposed to catch all required events to avoid stale elements.
2311 e_connman_manager_clear_elements(void)
2313 e_connman_elements_shutdown();
2314 e_connman_elements_init();
2318 * Creates elements hash.
2320 * This has no init counter since its already guarded by other code.
2324 e_connman_elements_init(void)
2326 EINA_SAFETY_ON_FALSE_RETURN(!elements);
2328 eina_hash_string_superfast_new(EINA_FREE_CB
2329 (_e_connman_element_unregister_internal));
2333 e_connman_elements_shutdown(void)
2335 EINA_SAFETY_ON_FALSE_RETURN(!!elements);
2336 eina_hash_free(elements);
2340 static inline Eina_Bool
2341 _e_connman_element_is(const E_Connman_Element *element, const char *interface)
2343 return element->interface == interface;
2347 e_connman_element_is_manager(const E_Connman_Element *element)
2349 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2350 return _e_connman_element_is(element, e_connman_iface_manager);
2354 e_connman_element_is_profile(const E_Connman_Element *element)
2356 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2357 return _e_connman_element_is(element, e_connman_iface_profile);
2361 e_connman_element_is_service(const E_Connman_Element *element)
2363 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2364 return _e_connman_element_is(element, e_connman_iface_service);
2368 e_connman_element_is_technology(const E_Connman_Element *element)
2370 EINA_SAFETY_ON_NULL_RETURN_VAL(element, EINA_FALSE);
2371 return _e_connman_element_is(element, e_connman_iface_technology);