diff --git a/src/bin/system/e_system_rfkill.c b/src/bin/system/e_system_rfkill.c index 9bdf8fbb7..23206ea2d 100644 --- a/src/bin/system/e_system_rfkill.c +++ b/src/bin/system/e_system_rfkill.c @@ -1,12 +1,20 @@ #include "e_system.h" +typedef enum +{ + RFKILL_BLOCK, + RFKILL_UNBLOCK, + RFKILL_LIST, +} RFKill_Action; + typedef struct { char *dev; Ecore_Event_Handler *handle_del, *handle_data; Ecore_Exe *exe; int id; - Eina_Bool block : 1; + RFKill_Action act; + Eina_Strbuf *list_ret; Eina_Bool doit : 1; } Action; @@ -21,7 +29,8 @@ _rfkill_dev_verify(const char *dev) ((*s >= 'A') && (*s <= 'Z')) || ((*s >= '0') && (*s <= '9')) || (*s == '-') || (*s == '+') || (*s == ',') || (*s == '.') || - (*s == '/') || (*s == ':') || (*s == '=') || (*s == '@'))) + (*s == '/') || (*s == ':') || (*s == '=') || (*s == '@') || + (*s == '_'))) return EINA_FALSE; } return EINA_TRUE; @@ -34,6 +43,7 @@ _rfkill_action_free(Action *a) // if (a->exe) ecore_exe_free(a->exe); if (a->handle_del) ecore_event_handler_del(a->handle_del); if (a->handle_data) ecore_event_handler_del(a->handle_data); + if (a->list_ret) eina_strbuf_free(a->list_ret); free(a->dev); free(a); } @@ -48,10 +58,10 @@ _cb_rfkill_exe_del(void *data, int ev_type EINA_UNUSED, void *event) { if (a->doit) { - if (a->block) + if (a->act == RFKILL_BLOCK) e_system_inout_command_send("rfkill-block", "%i %s", ev->exit_code, a->dev); - else + else if (a->act == RFKILL_UNBLOCK) e_system_inout_command_send("rfkill-unblock", "%i %s", ev->exit_code, a->dev); _rfkill_action_free(a); @@ -63,31 +73,52 @@ _cb_rfkill_exe_del(void *data, int ev_type EINA_UNUSED, void *event) // a->exe can stay - exe's are auto-freed by ecore on exit // ecore_exe_free(a->exe); a->exe = NULL; - if (snprintf(cmd, sizeof(cmd), "rfkill %s %i", - a->block ? "block" : "unblock", a->id) < - (int)(sizeof(cmd) - 1)) + if ((a->act == RFKILL_BLOCK) || (a->act == RFKILL_UNBLOCK)) { - a->doit = EINA_TRUE; - a->exe = ecore_exe_pipe_run(cmd, - ECORE_EXE_NOT_LEADER | - ECORE_EXE_TERM_WITH_PARENT | - ECORE_EXE_PIPE_READ | - ECORE_EXE_PIPE_WRITE | - ECORE_EXE_PIPE_READ_LINE_BUFFERED, NULL); - if (!a->exe) _rfkill_action_free(a); + if (snprintf(cmd, sizeof(cmd), "rfkill %s %i", + (a->act == RFKILL_BLOCK) ? "block" : "unblock", + a->id) < (int)(sizeof(cmd) - 1)) + { + a->doit = EINA_TRUE; + a->exe = ecore_exe_pipe_run(cmd, + ECORE_EXE_NOT_LEADER | + ECORE_EXE_TERM_WITH_PARENT | + ECORE_EXE_PIPE_READ | + ECORE_EXE_PIPE_WRITE | + ECORE_EXE_PIPE_READ_LINE_BUFFERED, NULL); + if (!a->exe) _rfkill_action_free(a); + } + } + else if (a->act == RFKILL_LIST) + { + e_system_inout_command_send("rfkill-list", "-"); + _rfkill_action_free(a); } else _rfkill_action_free(a); } } else { - if (a->block) + if (a->act == RFKILL_BLOCK) e_system_inout_command_send("rfkill-block", "%i %s", 123, a->dev); - else + else if (a->act == RFKILL_UNBLOCK) e_system_inout_command_send("rfkill-unblock", "%i %s", 123, a->dev); - _rfkill_action_free(a); + else if (a->act == RFKILL_LIST) + { + if (a->list_ret) + { + const char *s = eina_strbuf_string_get(a->list_ret); + if (s) + e_system_inout_command_send("rfkill-list", "%s", s); + else + e_system_inout_command_send("rfkill-list", "-"); + } + else + e_system_inout_command_send("rfkill-list", "-"); + _rfkill_action_free(a); + } } return EINA_TRUE; } @@ -104,16 +135,26 @@ _cb_rfkill_exe_data(void *data, int ev_type EINA_UNUSED, void *event) for (i = 0; ev->lines[i].line; i++) { int id; - char dev[1024]; + char dev[1024], type[1024]; id = -1; - if (sscanf(ev->lines[i].line, "%i: %1023[^:] %*s", &id, dev) == 2) + if (sscanf(ev->lines[i].line, "%i: %1023[^:]: %1023[^\n]", &id, dev, type) == 3) { - if (!strcmp(a->dev, dev)) + if ((a->act == RFKILL_BLOCK) || (a->act == RFKILL_UNBLOCK)) { - a->id = id; - // wait for exit to spawn rfkill again... - break; + if (!strcmp(a->dev, dev)) + { + a->id = id; + // wait for exit to spawn rfkill again... + break; + } + } + else + { + if (!a->list_ret) a->list_ret = eina_strbuf_new(); + if (a->list_ret) + eina_strbuf_append_printf(a->list_ret, "%s\t%s\n", + dev, type); } } } @@ -121,14 +162,14 @@ _cb_rfkill_exe_data(void *data, int ev_type EINA_UNUSED, void *event) } static void -_rfkill_do(Eina_Bool block, const char *dev) +_rfkill_do(RFKill_Action act, const char *dev) { Action *a = calloc(1, sizeof(Action)); if (!a) return; a->dev = strdup(dev); if (!a->dev) goto err; a->id = -1; - a->block = block; + a->act = act; a->handle_del = ecore_event_handler_add(ECORE_EXE_EVENT_DEL, _cb_rfkill_exe_del, a); a->handle_data = ecore_event_handler_add(ECORE_EXE_EVENT_DATA, @@ -152,14 +193,20 @@ static void _cb_rfkill_block(void *data EINA_UNUSED, const char *params) { if (!_rfkill_dev_verify(params)) return; - _rfkill_do(EINA_TRUE, params); + _rfkill_do(RFKILL_BLOCK, params); } static void _cb_rfkill_unblock(void *data EINA_UNUSED, const char *params) { if (!_rfkill_dev_verify(params)) return; - _rfkill_do(EINA_FALSE, params); + _rfkill_do(RFKILL_UNBLOCK, params); +} + +static void +_cb_rfkill_list(void *data EINA_UNUSED, const char *params EINA_UNUSED) +{ + _rfkill_do(RFKILL_LIST, ""); } void @@ -167,6 +214,7 @@ e_system_rfkill_init(void) { e_system_inout_command_register("rfkill-block", _cb_rfkill_block, NULL); e_system_inout_command_register("rfkill-unblock", _cb_rfkill_unblock, NULL); + e_system_inout_command_register("rfkill-list", _cb_rfkill_list, NULL); } void diff --git a/src/modules/bluez5/e_mod_main.c b/src/modules/bluez5/e_mod_main.c index bcac3ec9c..ed9a6efed 100644 --- a/src/modules/bluez5/e_mod_main.c +++ b/src/modules/bluez5/e_mod_main.c @@ -9,6 +9,8 @@ static E_Config_DD *conf_device_edd = NULL; static E_Config_DD *conf_edd = NULL; Config *ebluez5_config = NULL; +static Ecore_Timer *zero_adapters_check_timer = NULL; + E_API E_Module_Api e_modapi = {E_MODULE_API_VERSION, "Bluez5"}; static void @@ -210,6 +212,48 @@ _cb_rfkill_unblock(void *datam EINA_UNUSED, const char *params) "users and groups there to be sure.")); } +static void +_cb_rfkill_list(void *datam EINA_UNUSED, const char *params) +{ + if ((!params) || (!strcmp(params, "-"))) return; + // params is: + // hci0\tBluetooth\n + // phy0\tWireless LAN\n + // ... + // we got a list of possible rf-killable devices and this list callback + // will only have happened if we requested a list which we only do if + // tjhe list of adapters is empty still 5 seconds after init - something + // possibly wrong with them being blocked and thbus bluez not even listing + // them, so unblock them to get them listed + char **lines = eina_str_split(params, "\n", 0); + if (lines) + { + int i = 0; + char *line = lines[i]; + + while (line) + { + char **fields = eina_str_split(line, "\t", 0); + if (fields) + { + if ((fields[0]) && (fields[1])) + { + if (!strcasecmp(fields[1], "bluetooth")) + { + ebluez5_rfkill_unblock(fields[0]); + } + } + free(fields[0]); + free(fields); + } + i++; + line = lines[i]; + } + free(lines[0]); + free(lines); + } +} + void ebluez5_rfkill_unblock(const char *name) { @@ -329,6 +373,15 @@ ebluez5_device_prop_unlock_set(const char *address, Eina_Bool enable) } } +static Eina_Bool +_cb_zero_adapters_check(void *data EINA_UNUSED) +{ + zero_adapters_check_timer = NULL; + if (!ebluez5_popup_adapters_get()) + e_system_send("rfkill-list", "-"); + return EINA_FALSE; +} + ///////////////////////////////////////////////////////////////////////////// /* Module Functions */ @@ -364,6 +417,7 @@ e_modapi_init(E_Module *m) E_CONFIG_LIST(D, T, devices, conf_device_edd); e_system_handler_add("rfkill-unblock", _cb_rfkill_unblock, NULL); + e_system_handler_add("rfkill-list", _cb_rfkill_list, NULL); ebluez5_config = e_config_domain_load("module.ebluez5", conf_edd); if (!ebluez5_config) ebluez5_config = E_NEW(Config, 1); @@ -373,6 +427,8 @@ e_modapi_init(E_Module *m) e_gadcon_provider_register(&_gc_class); + zero_adapters_check_timer = ecore_timer_add(5.0, _cb_zero_adapters_check, NULL); + return m; } @@ -382,6 +438,12 @@ e_modapi_shutdown(E_Module *m EINA_UNUSED) Config_Adapter *ad; Config_Device *dev; + if (zero_adapters_check_timer) + { + ecore_timer_del(zero_adapters_check_timer); + zero_adapters_check_timer = NULL; + } + e_system_handler_del("rfkill-list", _cb_rfkill_list, NULL); e_system_handler_del("rfkill-unblock", _cb_rfkill_unblock, NULL); EINA_LIST_FREE(ebluez5_config->adapters, ad) {