ddc - work around some probe fails, missing timer handle, etc.

beating on ddc support to make it solid. dealing with some bad screens
that don't respond, a libddcutil that was doing a printf messing up
the message stream from e_system to e .... and more.
This commit is contained in:
Carsten Haitzler 2020-02-07 19:56:01 +00:00
parent d7325c3aad
commit fcacbe8a4f
4 changed files with 71 additions and 20 deletions

View File

@ -28,6 +28,7 @@ static Eina_Bool
_backlight_retry_timer_cb(void *data)
{
Backlight_Device *bd = data;
bd->retry_timer = NULL;
_backlight_devices_device_set(bd, bd->expected_val);
_backlight_devices_device_update(bd);
@ -48,7 +49,7 @@ _backlight_mismatch_retry(Backlight_Device *bd)
{ // try again
bd->retries++;
if (bd->retry_timer) ecore_timer_del(bd->retry_timer);
ecore_timer_add(0.1, _backlight_retry_timer_cb, bd);
bd->retry_timer = ecore_timer_add(0.1, _backlight_retry_timer_cb, bd);
} // or give up
else bd->retries = 0;
}
@ -84,6 +85,7 @@ _backlight_system_ddc_get_cb(void *data, const char *params)
if (!params) return;
if (sscanf(params, "%256s %i %i", edid, &id, &val) != 3) return;
if (!bd->edid) return;
if (!!strncmp(bd->edid, edid, strlen(edid))) return;
e_system_handler_del("ddc-val-get", _backlight_system_ddc_get_cb, bd);
if (val < 0) return; // get failed.... don't update
@ -215,6 +217,7 @@ static void
_backlight_devices_device_set(Backlight_Device *bd, double val)
{
bd->val = bd->expected_val = val;
bd->retries = 0;
#ifndef HAVE_WAYLAND_ONLY
if (!strcmp(bd->dev, "randr"))
{
@ -284,11 +287,13 @@ _backlight_devices_device_update(Backlight_Device *bd)
#endif
if (!strncmp(bd->dev, "ddc:", 4))
{
e_system_handler_del("ddc-val-get", _backlight_system_ddc_get_cb, bd);
e_system_handler_add("ddc-val-get", _backlight_system_ddc_get_cb, bd);
e_system_send("ddc-val-get", "%s %i", bd->dev + 4, 0x10); // backlight val in e_system_ddc.c
}
else
{
e_system_handler_del("bklight-val", _backlight_system_get_cb, bd);
e_system_handler_add("bklight-val", _backlight_system_get_cb, bd);
e_system_send("bklight-get", "%s", bd->dev);
}
@ -534,10 +539,12 @@ _backlight_devices_probe(Eina_Bool initial)
// ask enlightenment_system to list backlight devices. this is async so we have
// to respond to the device listing later
_devices_pending_ops++;
e_system_handler_del("bklight-list", _backlight_system_list_cb, NULL);
e_system_handler_add("bklight-list", _backlight_system_list_cb, NULL);
if (!initial) e_system_send("bklight-refresh", NULL);
e_system_send("bklight-list", NULL);
_devices_pending_ops++;
e_system_handler_del("ddc-list", _backlight_system_ddc_list_cb, NULL);
e_system_handler_add("ddc-list", _backlight_system_ddc_list_cb, NULL);
if (!initial) e_system_send("ddc-refresh", NULL);
e_system_send("ddc-list", NULL);

View File

@ -69,6 +69,7 @@ _system_message_read(void)
if (!data) return EINA_FALSE;
if (len < sizeof(Message_Head)) return EINA_FALSE;
head = (Message_Head *)bdata;
head->cmd[23] = 0;
if (len < (sizeof(Message_Head) + head->size)) return EINA_FALSE;
if (_handlers)
{

View File

@ -226,17 +226,24 @@ _ddc_clean(void)
static Eina_Bool
_ddc_probe(void)
{
Dev *d;
int i;
if (!ddc_lib) return EINA_FALSE;
eina_lock_take(&_devices_lock);
EINA_LIST_FREE(_devices, d)
{
free(d->edid);
free(d);
}
eina_lock_release(&_devices_lock);
_ddc_clean();
// the below can be quite sluggish, so we don't want to do this
// often, even though this is isolated in a worker thread. it will
// block the ddc worker thread while this is done.
if (ddc_func.ddca_get_display_info_list2(false, &ddc_dlist) != 0)
return EINA_FALSE;
if (!ddc_dlist) return EINA_FALSE;
if (ddc_func.ddca_get_display_info_list2(false, &ddc_dlist) != 0) goto err;
if (!ddc_dlist) goto err;
ddc_dh = calloc(ddc_dlist->ct, sizeof(DDCA_Display_Handle));
if (!ddc_dh)
{
@ -249,7 +256,6 @@ _ddc_probe(void)
DDCA_Display_Info *dinfo = &(ddc_dlist->info[i]);
DDCA_Display_Ref dref = dinfo->dref;
int j;
Dev *d;
if (ddc_func.ddca_open_display2(dref, false, &(ddc_dh[i])) != 0)
{
@ -261,22 +267,28 @@ _ddc_probe(void)
ddc_dh = NULL;
ddc_func.ddca_free_display_info_list(ddc_dlist);
ddc_dlist = NULL;
return EINA_FALSE;
goto err;
}
d = calloc(1, sizeof(Dev));
d->edid = malloc((128 * 2) + 1);
if (d->edid)
if (d)
{
for (j = 0; j < 128; j++)
snprintf(&(d->edid[j * 2]), 3, "%02x", dinfo->edid_bytes[j]);
d->edid[j * 2] = 0;
d->screen = i;
eina_lock_take(&_devices_lock);
_devices = eina_list_append(_devices, d);
eina_lock_release(&_devices_lock);
d->edid = malloc((128 * 2) + 1);
if (d->edid)
{
for (j = 0; j < 128; j++)
snprintf(&(d->edid[j * 2]), 3, "%02x", dinfo->edid_bytes[j]);
d->edid[j * 2] = 0;
d->screen = i;
eina_lock_take(&_devices_lock);
_devices = eina_list_append(_devices, d);
eina_lock_release(&_devices_lock);
}
else free(d);
}
}
return EINA_TRUE;
err:
return EINA_FALSE;
}
static Eina_Bool
@ -311,7 +323,7 @@ _req_alloc(const char *req, const char *params)
{
Req *r;
if (!params) return NULL;
if (!params) params = "";
r = calloc(1, sizeof(Req) + strlen(req) + 1 + strlen(params) + 1);
if (!r) return NULL;
r->req = ((char *)r) + sizeof(Req);
@ -522,8 +534,15 @@ _cb_worker(void *data EINA_UNUSED, Ecore_Thread *th)
}
else if (!strcmp(r->req, "refresh"))
{
_ddc_probe();
_do_list(th);
int i = 0;
for (i = 0; i < 10; i++)
{
if (_ddc_probe()) break;
usleep(10 * 1000);
}
if (i == 10)
fprintf(stderr, "DDC: PROBE FAILED.\n");
}
else if (!strcmp(r->req, "val-set"))
{

View File

@ -20,6 +20,28 @@ typedef struct
int size;
} Message_Head;
static int fd_null = -1, fd_supress = -1;
static void
_stdout_off(void)
{
fflush(stdout);
fd_supress = dup(1);
if (fd_null == -1) fd_null = open("/dev/null", O_WRONLY);
dup2(fd_null, 1);
}
static void
_stdout_on(void)
{
fflush(stdout);
dup2(fd_supress, 1);
close(fd_supress);
close(fd_null);
fd_supress = -1;
fd_null = -1;
}
static Eina_Bool
_cb_stdio_in_read(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
@ -81,6 +103,7 @@ done:
void
e_system_inout_init(void)
{
_stdout_off();
_cmd_handlers = eina_hash_string_superfast_new(free);
_fdh_in = ecore_main_fd_handler_add(0, ECORE_FD_READ,
_cb_stdio_in_read, NULL,
@ -94,6 +117,7 @@ e_system_inout_shutdown(void)
_fdh_in = NULL;
eina_hash_free(_cmd_handlers);
_cmd_handlers = NULL;
_stdout_on();
}
void
@ -151,7 +175,7 @@ e_system_inout_command_send(const char *cmd, const char *fmt, ...)
memcpy(head.cmd, cmd, len);
if (printed > 0) head.size = printed + 1;
else head.size = 0;
ret = write(1, &head, sizeof(head));
ret = write(fd_supress, &head, sizeof(head));
if (ret != sizeof(head))
{
ERR("Write of command failed at %lli\n", (long long)ret);
@ -159,7 +183,7 @@ e_system_inout_command_send(const char *cmd, const char *fmt, ...)
}
if ((buf) && (head.size > 0))
{
ret = write(1, buf, head.size);
ret = write(fd_supress, buf, head.size);
if (ret != (ssize_t)head.size)
{
ERR("Write of command buffer failed at %lli/%llu\n", (long long)ret, (unsigned long long)head.size);