raster pushed a commit to branch master.

http://git.enlightenment.org/core/enlightenment.git/commit/?id=f9607a90840682983fa046f5bb62bb98e33d5805

commit f9607a90840682983fa046f5bb62bb98e33d5805
Author: Carsten Haitzler (Rasterman) <ras...@rasterman.com>
Date:   Tue Apr 6 19:25:28 2021 +0100

    mod bz5 - fix hw that comes with bt rfkill on and bz adapters empty
    
    so - it seems on some hardware and./or os combinations the list of bt
    adapters is empty from bluez5 entirely if the adapter is rfkilled off.
    this means e doesnt see it at all - has no idea it's there. bz doesnt
    expose it. without that we can't turn it on even. so - if our bt
    adapter list is empty, then assume this is an error and manually list
    rfkillable devines and forcibly unblock them ot make them appear in
    bulez5... not so much a bug fix as a system brokenness workaround with
    bz5 just ignoring rfkill bnlocked devices and not even telling us
    about them.
    
    @fix
---
 src/bin/system/e_system_rfkill.c | 104 ++++++++++++++++++++++++++++-----------
 src/modules/bluez5/e_mod_main.c  |  62 +++++++++++++++++++++++
 2 files changed, 138 insertions(+), 28 deletions(-)

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))
+               {
+                  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)
                {
-                  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);
+                  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))
+               {
+                  if (!strcmp(a->dev, dev))
+                    {
+                       a->id = id;
+                       // wait for exit to spawn rfkill again...
+                       break;
+                    }
+               }
+             else
                {
-                  a->id = id;
-                  // wait for exit to spawn rfkill again...
-                  break;
+                  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)
      {

-- 


Reply via email to