1 #include "e.h"
2 #include "e_mod_main.h"
3 
4 #include "E_Connman.h"
5 
6 E_Module *connman_mod = NULL;
7 static char tmpbuf[4096]; /* general purpose buffer, just use immediately */
8 
9 const char _e_connman_name[] = "connman";
10 const char _e_connman_Name[] = N_("Connection Manager");
11 int _e_connman_log_dom = -1;
12 
13 const char *
e_connman_theme_path(void)14 e_connman_theme_path(void)
15 {
16 #define TF "/e-module-connman.edj"
17    size_t dirlen;
18 
19    dirlen = strlen(connman_mod->dir);
20    if (dirlen >= sizeof(tmpbuf) - sizeof(TF))
21      return NULL;
22 
23    memcpy(tmpbuf, connman_mod->dir, dirlen);
24    memcpy(tmpbuf + dirlen, TF, sizeof(TF));
25 
26    return tmpbuf;
27 #undef TF
28 }
29 
30 static Evas_Object *
_econnman_service_new_icon(struct Connman_Service * cs,Evas * evas)31 _econnman_service_new_icon(struct Connman_Service *cs, Evas *evas)
32 {
33    const char *type = econnman_service_type_to_str(cs->type);
34    Edje_Message_Int_Set *msg;
35    Evas_Object *icon;
36    char buf[128];
37 
38    snprintf(buf, sizeof(buf), "e/modules/connman/icon/%s", type);
39    icon = edje_object_add(evas);
40    e_theme_edje_object_set(icon, "base/theme/modules/connman", buf);
41 
42    msg = malloc(sizeof(*msg) + sizeof(int));
43    msg->count = 2;
44    msg->val[0] = cs->state;
45    msg->val[1] = cs->strength;
46 
47    edje_object_message_send(icon, EDJE_MESSAGE_INT_SET, 1, msg);
48    free(msg);
49 
50    return icon;
51 }
52 
53 static Evas_Object *
_econnman_service_new_end(struct Connman_Service * cs,Evas * evas)54 _econnman_service_new_end(struct Connman_Service *cs, Evas *evas)
55 {
56    Eina_Iterator *iter;
57    Evas_Object *end;
58    void *security;
59    char buf[128];
60 
61    end = edje_object_add(evas);
62    e_theme_edje_object_set(end, "base/theme/modules/connman",
63                            "e/modules/connman/end");
64 
65    if (!cs->security)
66      return end;
67 
68    iter = eina_array_iterator_new(cs->security);
69    while (eina_iterator_next(iter, &security))
70      {
71         snprintf(buf, sizeof(buf), "e,security,%s", (const char *)security);
72         edje_object_signal_emit(end, buf, "e");
73      }
74    eina_iterator_free(iter);
75 
76    return end;
77 }
78 
79 static void
_econnman_disconnect_cb(void * data,const char * error)80 _econnman_disconnect_cb(void *data, const char *error)
81 {
82    const char *path = data;
83 
84    if (error == NULL)
85      return;
86 
87    ERR("Could not disconnect %s: %s", path, error);
88 }
89 
90 static void
_econnman_connect_cb(void * data,const char * error)91 _econnman_connect_cb(void *data, const char *error)
92 {
93    const char *path = data;
94 
95    if (error == NULL)
96      return;
97 
98    ERR("Could not connect %s: %s", path, error);
99 }
100 
101 static void
_econnman_popup_selected_cb(void * data)102 _econnman_popup_selected_cb(void *data)
103 {
104    E_Connman_Instance *inst = data;
105    const char *path;
106    struct Connman_Service *cs;
107 
108    path = e_widget_ilist_selected_value_get(inst->ui.popup.list);
109    if (path == NULL)
110      return;
111 
112    cs = econnman_manager_find_service(inst->ctxt->cm, path);
113    if (!cs)
114      return;
115 
116    switch (cs->state)
117      {
118       case CONNMAN_STATE_READY:
119       case CONNMAN_STATE_ONLINE:
120          INF("Disconnect %s", path);
121          econnman_service_disconnect(cs, _econnman_disconnect_cb,
122                                      (void *) path);
123          break;
124       default:
125          INF("Connect %s", path);
126          econnman_service_connect(cs, _econnman_connect_cb, (void *) path);
127          break;
128      }
129 }
130 
131 static void
_econnman_popup_update(struct Connman_Manager * cm,E_Connman_Instance * inst)132 _econnman_popup_update(struct Connman_Manager *cm, E_Connman_Instance *inst)
133 {
134    Evas_Object *list = inst->ui.popup.list;
135    Evas_Object *powered = inst->ui.popup.powered;
136    Evas *evas = evas_object_evas_get(list);
137    struct Connman_Service *cs;
138    const char *hidden = "«hidden»";
139 
140    EINA_SAFETY_ON_NULL_RETURN(cm);
141 
142    e_widget_ilist_freeze(list);
143    e_widget_ilist_clear(list);
144 
145    EINA_INLIST_FOREACH(cm->services, cs)
146      {
147         Evas_Object *icon = _econnman_service_new_icon(cs, evas);
148         Evas_Object *end = _econnman_service_new_end(cs, evas);
149         e_widget_ilist_append_full(list, icon, end, cs->name ?: hidden,
150                                    _econnman_popup_selected_cb,
151                                    inst, cs->path);
152      }
153 
154    e_widget_ilist_thaw(list);
155    e_widget_ilist_go(list);
156 
157    if (inst->ctxt)
158      {
159         inst->ctxt->powered = cm->powered;
160      }
161    e_widget_check_checked_set(powered, cm->powered);
162 }
163 
164 void
econnman_mod_services_changed(struct Connman_Manager * cm)165 econnman_mod_services_changed(struct Connman_Manager *cm)
166 {
167    E_Connman_Module_Context *ctxt = connman_mod->data;
168    const Eina_List *l;
169    E_Connman_Instance *inst;
170 
171    EINA_LIST_FOREACH(ctxt->instances, l, inst)
172      {
173         if (!inst->popup)
174           continue;
175 
176         _econnman_popup_update(cm, inst);
177      }
178 }
179 
180 static void
_econnman_app_launch(E_Connman_Instance * inst)181 _econnman_app_launch(E_Connman_Instance *inst)
182 {
183    Efreet_Desktop *desktop;
184    E_Zone *zone;
185 
186    desktop = efreet_util_desktop_file_id_find("econnman.desktop");
187    if (!desktop)
188      {
189         e_util_dialog_internal
190           (_("Missing Application"),
191           _("This module wants to execute an external application "
192             "EConnMan that does not exist.<ps/>"
193             "Please install <b>EConnMan</b> application."));
194         return;
195      }
196 
197    zone = e_gadcon_client_zone_get(inst->gcc);
198    if (!zone)
199      zone = e_zone_current_get();
200 
201    e_exec(zone, desktop, NULL, NULL, "econnman/app");
202    efreet_desktop_free(desktop);
203 }
204 
205 static void
_econnman_configure_cb(void * data,void * data2 EINA_UNUSED)206 _econnman_configure_cb(void *data, void *data2 EINA_UNUSED)
207 {
208    E_Connman_Instance *inst = data;
209    econnman_popup_del(inst);
210    _econnman_app_launch(inst);
211 }
212 
213 static void
_econnman_powered_changed(void * data,Evas_Object * obj EINA_UNUSED,void * info EINA_UNUSED)214 _econnman_powered_changed(void *data, Evas_Object *obj EINA_UNUSED, void *info EINA_UNUSED)
215 {
216    E_Connman_Instance *inst = data;
217    E_Connman_Module_Context *ctxt = inst->ctxt;
218 
219    if (!ctxt) return;
220    if (!ctxt->cm) return;
221    econnman_powered_set(ctxt->cm, ctxt->powered);
222 }
223 
224 static void
_e_connman_widget_size_set(E_Connman_Instance * inst,Evas_Object * widget,Evas_Coord percent_w,Evas_Coord percent_h,Evas_Coord min_w,Evas_Coord min_h,Evas_Coord max_w,Evas_Coord max_h)225 _e_connman_widget_size_set(E_Connman_Instance *inst, Evas_Object *widget, Evas_Coord percent_w, Evas_Coord percent_h, Evas_Coord min_w, Evas_Coord min_h, Evas_Coord max_w, Evas_Coord max_h)
226 {
227    Evas_Coord w, h, zw, zh;
228    E_Zone *zone;
229 
230    zone = e_gadcon_client_zone_get(inst->gcc);
231    e_zone_useful_geometry_get(zone, NULL, NULL, &zw, &zh);
232 
233    w = zw * percent_w / 100.0;
234    h = zh * percent_h / 100.0;
235 
236    if (w < min_w)
237      w = min_w;
238    else if (w > max_w)
239      w = max_w;
240    if (h < min_h)
241      h = min_h;
242    else if (h > max_h)
243      h = max_h;
244 
245    e_widget_size_min_set(widget, w, h);
246 }
247 
248 static void
_econnman_popup_del_cb(void * obj)249 _econnman_popup_del_cb(void *obj)
250 {
251    econnman_popup_del(e_object_data_get(obj));
252 }
253 
254 static void
_econnman_popup_del(void * data,Evas_Object * obj EINA_UNUSED)255 _econnman_popup_del(void *data, Evas_Object *obj EINA_UNUSED)
256 {
257    E_Connman_Instance *inst = data;
258 
259    E_FREE_FUNC(inst->popup, e_object_del);
260 }
261 
262 static void
_econnman_popup_new(E_Connman_Instance * inst)263 _econnman_popup_new(E_Connman_Instance *inst)
264 {
265    E_Connman_Module_Context *ctxt = inst->ctxt;
266    Evas_Object *list, *bt, *ck;
267    Evas *evas;
268 
269    EINA_SAFETY_ON_FALSE_RETURN(inst->popup == NULL);
270 
271    if (!ctxt->cm)
272      return;
273 
274    inst->popup = e_gadcon_popup_new(inst->gcc, 0);
275    evas = e_comp->evas;
276 
277    list = e_widget_list_add(evas, 0, 0);
278    inst->ui.popup.list = e_widget_ilist_add(evas, 24, 24, NULL);
279    e_widget_size_min_set(inst->ui.popup.list, 60, 100);
280    e_widget_list_object_append(list, inst->ui.popup.list, 1, 1, 0.5);
281 
282    ck = e_widget_check_add(evas, _("Wifi On"), &(ctxt->powered));
283    inst->ui.popup.powered = ck;
284    e_widget_list_object_append(list, ck, 1, 0, 0.5);
285    evas_object_smart_callback_add(ck, "changed",
286                                   _econnman_powered_changed, inst);
287 
288    _econnman_popup_update(ctxt->cm, inst);
289 
290    if (efreet_util_desktop_file_id_find("econnman.desktop"))
291      {
292         bt = e_widget_button_add(evas, _("Configure"), NULL,
293                                  _econnman_configure_cb, inst, NULL);
294         e_widget_list_object_append(list, bt, 1, 0, 0.5);
295      }
296 
297    /* 30,40 % -- min vga, max uvga */
298    _e_connman_widget_size_set(inst, list, 10, 30, 192, 192, 384, 384);
299    e_gadcon_popup_content_set(inst->popup, list);
300    e_comp_object_util_autoclose(inst->popup->comp_object, _econnman_popup_del, NULL, inst);
301    e_gadcon_popup_show(inst->popup);
302    e_object_data_set(E_OBJECT(inst->popup), inst);
303    E_OBJECT_DEL_SET(inst->popup, _econnman_popup_del_cb);
304 }
305 
306 void
econnman_popup_del(E_Connman_Instance * inst)307 econnman_popup_del(E_Connman_Instance *inst)
308 {
309    E_FREE_FUNC(inst->popup, e_object_del);
310    inst->ui.popup.powered = inst->ui.popup.list = NULL;
311 }
312 
313 static void
_econnman_mod_manager_update_inst(E_Connman_Module_Context * ctxt EINA_UNUSED,E_Connman_Instance * inst,enum Connman_State state,enum Connman_Service_Type type)314 _econnman_mod_manager_update_inst(E_Connman_Module_Context *ctxt EINA_UNUSED,
315                                   E_Connman_Instance *inst,
316                                   enum Connman_State state,
317                                   enum Connman_Service_Type type)
318 {
319    Evas_Object *o = inst->ui.gadget;
320    Edje_Message_Int_Set *msg;
321    const char *typestr;
322    char buf[128];
323 
324    msg = malloc(sizeof(*msg) + sizeof(int));
325    msg->count = 2;
326    msg->val[0] = state;
327    /* FIXME check if it's possible to receive strength as props of cm */
328    if (type == -1)
329        msg->val[1] = 0;
330    else
331        msg->val[1] = 100;
332 
333    edje_object_message_send(o, EDJE_MESSAGE_INT_SET, 1, msg);
334    free(msg);
335 
336    typestr = econnman_service_type_to_str(type);
337    snprintf(buf, sizeof(buf), "e,changed,technology,%s", typestr);
338    edje_object_signal_emit(o, buf, "e");
339 
340    DBG("state=%d type=%d", state, type);
341 }
342 
_econnman_manager_service_type_get(struct Connman_Manager * cm)343 static enum Connman_Service_Type _econnman_manager_service_type_get(
344                                                    struct Connman_Manager *cm)
345 {
346    DBG("cm->services=%p", cm->services);
347 
348    if ((cm->services) && ((cm->state == CONNMAN_STATE_ONLINE) ||
349                           (cm->state == CONNMAN_STATE_READY)))
350      /* FIXME would be nice to represent "configuring state".
351         theme already supports it */
352      /*                 (cm->state == CONNMAN_STATE_ASSOCIATION) ||
353                           (cm->state == CONNMAN_STATE_CONFIGURATION))) */
354      {
355         struct Connman_Service *cs = EINA_INLIST_CONTAINER_GET(cm->services,
356                                                       struct Connman_Service);
357         return cs->type;
358      }
359    return CONNMAN_SERVICE_TYPE_NONE;
360 }
361 
362 void
econnman_mod_manager_update(struct Connman_Manager * cm)363 econnman_mod_manager_update(struct Connman_Manager *cm)
364 {
365    enum Connman_Service_Type type;
366    E_Connman_Module_Context *ctxt = connman_mod->data;
367    E_Connman_Instance *inst;
368    Eina_List *l;
369 
370    EINA_SAFETY_ON_NULL_RETURN(cm);
371 
372    type = _econnman_manager_service_type_get(cm);
373    EINA_LIST_FOREACH(ctxt->instances, l, inst)
374      _econnman_mod_manager_update_inst(ctxt, inst, cm->state, type);
375 }
376 
377 static void
_econnman_gadget_setup(E_Connman_Instance * inst)378 _econnman_gadget_setup(E_Connman_Instance *inst)
379 {
380    E_Connman_Module_Context *ctxt = inst->ctxt;
381    Evas_Object *o = inst->ui.gadget;
382 
383    DBG("has_manager=%d", ctxt->cm != NULL);
384 
385    if (!ctxt->cm)
386      {
387         edje_object_signal_emit(o, "e,unavailable", "e");
388         edje_object_signal_emit(o, "e,changed,connected,no", "e");
389      }
390    else
391      edje_object_signal_emit(o, "e,available", "e");
392 
393    return;
394 }
395 
396 void
econnman_mod_manager_inout(struct Connman_Manager * cm)397 econnman_mod_manager_inout(struct Connman_Manager *cm)
398 {
399    E_Connman_Module_Context *ctxt = connman_mod->data;
400    const Eina_List *l;
401    E_Connman_Instance *inst;
402 
403    DBG("Manager %s", cm ? "in" : "out");
404    ctxt->cm = cm;
405 
406    EINA_LIST_FOREACH(ctxt->instances, l, inst)
407      _econnman_gadget_setup(inst);
408 
409    if (ctxt->cm)
410      econnman_mod_manager_update(cm);
411 }
412 
413 static void
_econnman_menu_cb_configure(void * data,E_Menu * menu EINA_UNUSED,E_Menu_Item * mi EINA_UNUSED)414 _econnman_menu_cb_configure(void *data, E_Menu *menu EINA_UNUSED,
415                             E_Menu_Item *mi EINA_UNUSED)
416 {
417    E_Connman_Instance *inst = data;
418    _econnman_app_launch(inst);
419 }
420 
421 static void
_econnman_menu_new(E_Connman_Instance * inst,Evas_Event_Mouse_Down * ev)422 _econnman_menu_new(E_Connman_Instance *inst, Evas_Event_Mouse_Down *ev)
423 {
424    E_Menu *m;
425    E_Menu_Item *mi;
426    int x, y;
427 
428    m = e_menu_new();
429    mi = e_menu_item_new(m);
430    e_menu_item_label_set(mi, _("Settings"));
431    e_util_menu_item_theme_icon_set(mi, "configure");
432    e_menu_item_callback_set(mi, _econnman_menu_cb_configure, inst);
433 
434    m = e_gadcon_client_util_menu_items_append(inst->gcc, m, 0);
435    e_gadcon_canvas_zone_geometry_get(inst->gcc->gadcon, &x, &y, NULL, NULL);
436    e_menu_activate_mouse(m,
437                          e_zone_current_get(),
438                          x + ev->output.x, y + ev->output.y, 1, 1,
439                          E_MENU_POP_DIRECTION_DOWN, ev->timestamp);
440 }
441 
442 static void
_econnman_cb_mouse_down(void * data,Evas * evas EINA_UNUSED,Evas_Object * obj EINA_UNUSED,void * event)443 _econnman_cb_mouse_down(void *data, Evas *evas EINA_UNUSED,
444                         Evas_Object *obj EINA_UNUSED, void *event)
445 {
446    E_Connman_Instance *inst = data;
447    Evas_Event_Mouse_Down *ev = event;
448 
449    if (!inst)
450      return;
451 
452    if (ev->button == 1)
453      {
454         if (!inst->popup)
455           _econnman_popup_new(inst);
456      }
457    else if (ev->button == 3)
458      _econnman_menu_new(inst, ev);
459 }
460 
461 /* Gadcon Api Functions */
462 
463 static E_Gadcon_Client *
_gc_init(E_Gadcon * gc,const char * name,const char * id,const char * style)464 _gc_init(E_Gadcon *gc, const char *name, const char *id, const char *style)
465 {
466    E_Connman_Instance *inst;
467    E_Connman_Module_Context *ctxt;
468    enum Connman_Service_Type type;
469 
470    if (!connman_mod)
471      return NULL;
472 
473    ctxt = connman_mod->data;
474 
475    inst = E_NEW(E_Connman_Instance, 1);
476    inst->ctxt = ctxt;
477    inst->ui.gadget = edje_object_add(gc->evas);
478    e_theme_edje_object_set(inst->ui.gadget, "base/theme/modules/connman",
479                            "e/modules/connman/main");
480 
481    inst->gcc = e_gadcon_client_new(gc, name, id, style, inst->ui.gadget);
482    inst->gcc->data = inst;
483 
484    evas_object_event_callback_add
485      (inst->ui.gadget, EVAS_CALLBACK_MOUSE_DOWN, _econnman_cb_mouse_down, inst);
486 
487    _econnman_gadget_setup(inst);
488 
489    if (ctxt->cm)
490      {
491         /* Update main icon with the current state */
492         type = _econnman_manager_service_type_get(ctxt->cm);
493         _econnman_mod_manager_update_inst(ctxt, inst, ctxt->cm->state, type);
494      }
495    ctxt->instances = eina_list_append(ctxt->instances, inst);
496 
497    return inst->gcc;
498 }
499 
500 static void
_gc_shutdown(E_Gadcon_Client * gcc)501 _gc_shutdown(E_Gadcon_Client *gcc)
502 {
503    E_Connman_Module_Context *ctxt;
504    E_Connman_Instance *inst;
505 
506    if (!connman_mod)
507      return;
508 
509    ctxt = connman_mod->data;
510    if (!ctxt)
511      return;
512 
513    inst = gcc->data;
514    if (!inst)
515      return;
516 
517    if (inst->popup)
518      econnman_popup_del(inst);
519 
520    evas_object_del(inst->ui.gadget);
521 
522    ctxt->instances = eina_list_remove(ctxt->instances, inst);
523 
524    E_FREE(inst);
525 }
526 
527 static void
_gc_orient(E_Gadcon_Client * gcc,E_Gadcon_Orient orient EINA_UNUSED)528 _gc_orient(E_Gadcon_Client *gcc, E_Gadcon_Orient orient EINA_UNUSED)
529 {
530    e_gadcon_client_aspect_set(gcc, 16, 16);
531    e_gadcon_client_min_size_set(gcc, 16, 16);
532 }
533 
534 static const char *
_gc_label(const E_Gadcon_Client_Class * client_class EINA_UNUSED)535 _gc_label(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
536 {
537    return _(_e_connman_Name);
538 }
539 
540 static Evas_Object *
_gc_icon(const E_Gadcon_Client_Class * client_class EINA_UNUSED,Evas * evas)541 _gc_icon(const E_Gadcon_Client_Class *client_class EINA_UNUSED, Evas *evas)
542 {
543    Evas_Object *o;
544 
545    o = edje_object_add(evas);
546    edje_object_file_set(o, e_connman_theme_path(), "icon");
547    return o;
548 }
549 
550 static const char *
_gc_id_new(const E_Gadcon_Client_Class * client_class EINA_UNUSED)551 _gc_id_new(const E_Gadcon_Client_Class *client_class EINA_UNUSED)
552 {
553    E_Connman_Module_Context *ctxt;
554    Eina_List *instances;
555 
556    if (!connman_mod)
557      return NULL;
558 
559    ctxt = connman_mod->data;
560    if (!ctxt)
561      return NULL;
562 
563    instances = ctxt->instances;
564    snprintf(tmpbuf, sizeof(tmpbuf), "connman.%d", eina_list_count(instances));
565    return tmpbuf;
566 }
567 
568 static const E_Gadcon_Client_Class _gc_class =
569 {
570    GADCON_CLIENT_CLASS_VERSION, _e_connman_name,
571    {
572       _gc_init, _gc_shutdown, _gc_orient, _gc_label, _gc_icon, _gc_id_new, NULL,
573       e_gadcon_site_is_not_toolbar
574    },
575    E_GADCON_CLIENT_STYLE_PLAIN
576 };
577 
578 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, _e_connman_Name };
579 
580 static E_Config_Dialog *
_econnman_config(Evas_Object * parent EINA_UNUSED,const char * params EINA_UNUSED)581 _econnman_config(Evas_Object *parent EINA_UNUSED, const char *params EINA_UNUSED)
582 {
583    E_Connman_Module_Context *ctxt;
584 
585    if (!connman_mod)
586      return NULL;
587 
588    ctxt = connman_mod->data;
589    if (!ctxt)
590      return NULL;
591 
592    if (!ctxt->conf_dialog)
593      ctxt->conf_dialog = e_connman_config_dialog_new(NULL, ctxt);
594 
595    return ctxt->conf_dialog;
596 }
597 
598 static const char _reg_cat[] = "extensions";
599 static const char _reg_item[] = "extensions/connman";
600 
601 static void
_econnman_configure_registry_register(void)602 _econnman_configure_registry_register(void)
603 {
604    e_configure_registry_category_add(_reg_cat, 90, _("Extensions"), NULL,
605                                      "preferences-extensions");
606    e_configure_registry_item_add(_reg_item, 110, _(_e_connman_Name), NULL,
607                                  e_connman_theme_path(),
608                                  _econnman_config);
609 }
610 
611 static void
_econnman_configure_registry_unregister(void)612 _econnman_configure_registry_unregister(void)
613 {
614    e_configure_registry_item_del(_reg_item);
615    e_configure_registry_category_del(_reg_cat);
616 }
617 
618 E_API void *
e_modapi_init(E_Module * m)619 e_modapi_init(E_Module *m)
620 {
621    E_Connman_Module_Context *ctxt;
622    Eldbus_Connection *c;
623 
624    if (_e_connman_log_dom < 0)
625      {
626         _e_connman_log_dom = eina_log_domain_register("econnman",
627                                                       EINA_COLOR_ORANGE);
628         if (_e_connman_log_dom < 0)
629           {
630              EINA_LOG_CRIT("could not register logging domain econnman");
631              goto error_log_domain;
632           }
633      }
634 
635    ctxt = E_NEW(E_Connman_Module_Context, 1);
636    if (!ctxt)
637      goto error_connman_context;
638    c = eldbus_connection_get(ELDBUS_CONNECTION_TYPE_SYSTEM);
639    if (!c)
640      goto error_dbus_bus_get;
641    if (!e_connman_system_init(c))
642      goto error_connman_system_init;
643 
644    ctxt->conf_dialog = NULL;
645    connman_mod = m;
646 
647    _econnman_configure_registry_register();
648    e_gadcon_provider_register(&_gc_class);
649 
650    return ctxt;
651 
652 error_connman_system_init:
653    eldbus_connection_unref(c);
654 error_dbus_bus_get:
655    E_FREE(ctxt);
656 error_connman_context:
657    eina_log_domain_unregister(_e_connman_log_dom);
658 error_log_domain:
659    _e_connman_log_dom = -1;
660    return NULL;
661 }
662 
663 static void
_econnman_instances_free(E_Connman_Module_Context * ctxt)664 _econnman_instances_free(E_Connman_Module_Context *ctxt)
665 {
666    while (ctxt->instances)
667      {
668         E_Connman_Instance *inst = ctxt->instances->data;
669         ctxt->instances = eina_list_remove_list(ctxt->instances,
670                                                 ctxt->instances);
671         e_object_del(E_OBJECT(inst->gcc));
672      }
673 }
674 
675 E_API int
e_modapi_shutdown(E_Module * m)676 e_modapi_shutdown(E_Module *m)
677 {
678    E_Connman_Module_Context *ctxt;
679 
680    ctxt = m->data;
681    if (!ctxt)
682      return 0;
683 
684    e_connman_system_shutdown();
685 
686    _econnman_instances_free(ctxt);
687    _econnman_configure_registry_unregister();
688    e_gadcon_provider_unregister(&_gc_class);
689 
690    E_FREE(ctxt);
691    connman_mod = NULL;
692 
693    eina_log_domain_unregister(_e_connman_log_dom);
694    _e_connman_log_dom = -1;
695 
696    return 1;
697 }
698 
699 E_API int
e_modapi_save(E_Module * m)700 e_modapi_save(E_Module *m)
701 {
702    E_Connman_Module_Context *ctxt;
703 
704    ctxt = m->data;
705    if (!ctxt)
706      return 0;
707    return 1;
708 }
709