diff --git a/src/bin/e_backlight.c b/src/bin/e_backlight.c index 8eb8faeda..5dd1daea5 100644 --- a/src/bin/e_backlight.c +++ b/src/bin/e_backlight.c @@ -39,11 +39,34 @@ _backlight_system_get_cb(void *data, const char *params) } } +static void +_backlight_system_ddc_get_cb(void *data, const char *params) +{ + char edid[257]; + int id = -1, val = -1; + double fval; + Backlight_Device *bd = data; + + if (!params) return; + if (sscanf(params, "%256s %i %i", edid, &id, &val) != 3) return; + if (!!strncmp(bd->edid, edid, strlen(edid))) return; + e_system_handler_del("ddc-val-get", _backlight_system_ddc_get_cb, bd); + fval = (double)val / 100.0; + if (fabs(fval - bd->val) >= DBL_EPSILON) + { + bd->val = fval; + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); + } +} + static void _backlight_devices_clear(void) { + const char *s; Backlight_Device *bd; + EINA_LIST_FREE(bl_devs, s) + eina_stringshare_del(s); EINA_LIST_FREE(_devices, bd) { eina_stringshare_del(bd->dev); @@ -51,6 +74,7 @@ _backlight_devices_clear(void) eina_stringshare_del(bd->edid); if (bd->anim) ecore_animator_del(bd->anim); e_system_handler_del("bklight-val", _backlight_system_get_cb, bd); + e_system_handler_del("ddc-val-get", _backlight_system_ddc_get_cb, bd); free(bd); } } @@ -170,7 +194,8 @@ _backlight_devices_device_set(Backlight_Device *bd, double val) #endif if (!strncmp(bd->dev, "ddc:", 4)) { - // XXX: implement ddc support + e_system_send("ddc-val-set", "%s %i %i", bd->dev + 4, 0x10, (int)(bd->val * 100.0)); // backlight val in e_system_ddc.c + ecore_event_add(E_EVENT_BACKLIGHT_CHANGE, NULL, NULL, NULL); } else { @@ -221,7 +246,8 @@ _backlight_devices_device_update(Backlight_Device *bd) #endif if (!strncmp(bd->dev, "ddc:", 4)) { - // XXX: implement ddc support + 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 { @@ -262,6 +288,21 @@ _backlight_devices_screen_lid_get(void) return NULL; } +static E_Randr2_Screen * +_backlight_devices_screen_edid_get(const char *edid) +{ + Eina_List *l; + E_Randr2_Screen *sc; + + if (!e_randr2) return NULL; + EINA_LIST_FOREACH(e_randr2->screens, l, sc) + { + if (!sc->info.edid) continue; + if (!strncmp(sc->info.edid, edid, strlen(edid))) return sc; + } + return NULL; +} + static Backlight_Device * _backlight_devices_edid_find(const char *edid) { @@ -282,6 +323,7 @@ _backlight_devices_lid_register(const char *dev, Eina_Bool force) E_Randr2_Screen *sc = _backlight_devices_screen_lid_get(); Backlight_Device *bd; if (!sc) return; + if (!sc->info.edid) return; bd = _backlight_devices_edid_find(sc->info.edid); if (!bd) { @@ -302,23 +344,36 @@ _backlight_devices_lid_register(const char *dev, Eina_Bool force) eina_stringshare_replace(&(bd->dev), dev); } +static void +_backlight_devices_edid_register(const char *dev, const char *edid) +{ + E_Randr2_Screen *sc = _backlight_devices_screen_edid_get(edid); + Backlight_Device *bd; + if (!sc) return; + bd = _backlight_devices_edid_find(sc->info.edid); + if (!bd) + { + bd = calloc(1, sizeof(Backlight_Device)); + if (!bd) return; + bd->edid = eina_stringshare_add(sc->info.edid); + bd->output = eina_stringshare_add(sc->info.name); + _devices = eina_list_append(_devices, bd); + } + if (bd->dev) + { + if (!strcmp(bd->dev, "randr")) return; // randr devices win + } + eina_stringshare_replace(&(bd->dev), dev); +} + static void _backlight_system_list_cb(void *data EINA_UNUSED, const char *params) { // params "dev flag dev flag ..." - const char *p = params, *s; + const char *p = params; char dev[1024], flag, devnum = 0; e_system_handler_del("bklight-list", _backlight_system_list_cb, NULL); - EINA_LIST_FREE(bl_devs, s) - eina_stringshare_del(s); -#ifndef HAVE_WAYLAND_ONLY - if ((e_comp) && (e_comp->comp_type == E_PIXMAP_TYPE_X)) - { - if (ecore_x_randr_output_backlight_available()) - bl_devs = eina_list_append(bl_devs, eina_stringshare_add("randr")); - } -#endif while ((p) && (*p)) { if (sscanf(p, "%1023s", dev) == 1) @@ -364,7 +419,30 @@ _backlight_system_list_cb(void *data EINA_UNUSED, const char *params) } static void -_backlight_devices_probe(void) +_backlight_system_ddc_list_cb(void *data EINA_UNUSED, const char *params) +{ + const char *p = params; + char dev[257], buf[343]; + + e_system_handler_del("ddc-list", _backlight_system_ddc_list_cb, NULL); + while ((p) && (*p)) + { + if (sscanf(p, "%256s", dev) == 1) + { + p += strlen(dev); + snprintf(buf, sizeof(buf), "ddc:%s", dev); + bl_devs = eina_list_append + (bl_devs, eina_stringshare_add(buf)); + _backlight_devices_edid_register(buf, dev); + if (*p != ' ') break; + } + else break; + } + _backlight_devices_pending_done(); +} + +static void +_backlight_devices_probe(Eina_Bool initial) { _backlight_devices_clear(); #ifndef HAVE_WAYLAND_ONLY @@ -381,6 +459,7 @@ _backlight_devices_probe(void) Ecore_X_Randr_Output *out; int i, num = 0; + bl_devs = eina_list_append(bl_devs, eina_stringshare_add("randr")); out = ecore_x_randr_window_outputs_get(root, &num); if ((out) && (num > 0)) { @@ -417,8 +496,12 @@ _backlight_devices_probe(void) // to respond to the device listing later _devices_pending_ops++; e_system_handler_add("bklight-list", _backlight_system_list_cb, NULL); - e_system_send("bklight-refresh", NULL); + if (!initial) e_system_send("bklight-refresh", NULL); e_system_send("bklight-list", NULL); + _devices_pending_ops++; + 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); // XXXX: add ddc to e_syystem and query that too } @@ -444,7 +527,7 @@ static void _cb_job_zone_change(void *data EINA_UNUSED) { zone_change_job = NULL; - _backlight_devices_probe(); + _backlight_devices_probe(EINA_FALSE); e_backlight_update(); } @@ -460,7 +543,7 @@ EINTERN int e_backlight_init(void) { E_EVENT_BACKLIGHT_CHANGE = ecore_event_type_new(); - _backlight_devices_probe(); + _backlight_devices_probe(EINA_TRUE); #define H(ev, cb) \ handlers = eina_list_append(handlers, \ ecore_event_handler_add(ev, cb, NULL)); @@ -546,7 +629,6 @@ e_backlight_level_set(E_Zone *zone, double val, double tim) if (zone->bl_mode == E_BACKLIGHT_MODE_NORMAL) tim = 0.5; else if (tim < 0.0) tim = e_config->backlight.transition; - // XXX: store in bl device E_FREE_FUNC(bd->anim, ecore_animator_del); bd->anim = ecore_animator_timeline_add(tim, _bl_anim, bd); bd->from_val = bl_now; diff --git a/src/bin/e_system.c b/src/bin/e_system.c index 1bb07268a..a3731090c 100644 --- a/src/bin/e_system.c +++ b/src/bin/e_system.c @@ -107,7 +107,8 @@ _system_message_read(void) if (del_count > 0) { eina_hash_del(_handlers, head->cmd, plist); - eina_hash_add(_handlers, head->cmd, list); + if (list) + eina_hash_add(_handlers, head->cmd, list); } } buf2 = eina_binbuf_new(); diff --git a/src/bin/system/e_system.h b/src/bin/system/e_system.h index 5fc4b9639..be3ba4805 100644 --- a/src/bin/system/e_system.h +++ b/src/bin/system/e_system.h @@ -122,5 +122,8 @@ void e_system_l2ping_shutdown(void); void e_system_cpufreq_init(void); void e_system_cpufreq_shutdown(void); +void e_system_ddc_init(void); +void e_system_ddc_shutdown(void); + #endif diff --git a/src/bin/system/e_system_ddc.c b/src/bin/system/e_system_ddc.c new file mode 100644 index 000000000..7290b7a2d --- /dev/null +++ b/src/bin/system/e_system_ddc.c @@ -0,0 +1,598 @@ +#include "e_system.h" + +#include +#include + +typedef struct +{ + char *edid; + int screen; +} Dev; + +typedef struct +{ + char *req, *params; // don't free - part of alloc for req struct at offset +} Req; + +static Eina_Lock _devices_lock; +static Eina_List *_devices = NULL; +static Eina_List *_req = NULL; +static Eina_Semaphore _worker_sem; + +////////////////////////////////////////////////////////////////////////////// +// needed ddc types +#define DDCA_EDID_MFG_ID_FIELD_SIZE 4 +#define DDCA_EDID_MODEL_NAME_FIELD_SIZE 14 +#define DDCA_EDID_SN_ASCII_FIELD_SIZE 14 + +typedef int DDCA_Status; +typedef void * DDCA_Display_Ref; +typedef void * DDCA_Display_Handle; +typedef uint8_t DDCA_Vcp_Feature_Code; + +typedef enum +{ + DDCA_IO_I2C, + DDCA_IO_ADL, + DDCA_IO_USB +} DDCA_IO_Mode; + +typedef struct +{ + int iAdapterIndex; + int iDisplayIndex; +} DDCA_Adlno; + +typedef struct +{ + DDCA_IO_Mode io_mode; + union { + int i2c_busno; + DDCA_Adlno adlno; + int hiddev_devno; + } path; +} DDCA_IO_Path; + +typedef struct +{ + uint8_t major; + uint8_t minor; +} DDCA_MCCS_Version_Spec; + +typedef struct +{ + char marker[4]; + int dispno; + DDCA_IO_Path path; + int usb_bus; + int usb_device; + char mfg_id[DDCA_EDID_MFG_ID_FIELD_SIZE]; + char model_name[DDCA_EDID_MODEL_NAME_FIELD_SIZE]; + char sn[DDCA_EDID_SN_ASCII_FIELD_SIZE]; + uint16_t product_code; + uint8_t edid_bytes[128]; + DDCA_MCCS_Version_Spec vcp_version; + DDCA_Display_Ref dref; +} DDCA_Display_Info; + +typedef struct +{ + int ct; + DDCA_Display_Info info[]; +} DDCA_Display_Info_List; + +typedef struct +{ + uint8_t mh; + uint8_t ml; + uint8_t sh; + uint8_t sl; +} DDCA_Non_Table_Vcp_Value; + +////////////////////////////////////////////////////////////////////////////// +// ddc feature codes we plan to support +// 0x12 contrast (0->100, 75) +// 0x16 video gain r (0->100, 50) +// 0x18 video gain g (0->100, 50) +// 0x1a video gain b (0->100, 50) +// 0xaa screen rotation (read only) +// {0x01, "0 degrees"}, +// {0x02, "90 degrees"}, +// {0x03, "180 degrees"}, +// {0x04, "270 degrees"}, +// {0xff, "Display cannot supply orientation"}, +// 0x6c video black level r (0->255, 128) +// 0x6e video black level g (0->255, 128) +// 0x70 video black level b (0->255, 128) +// 0x6b backlight level w +// 0x6d backlight level r +// 0x6f backlight level g +// 0x71 backlight level b +// 0xd6 power mode (10x = on, 0x4 = off) +// {0x01, "DPM: On, DPMS: Off"}, +// {0x02, "DPM: Off, DPMS: Standby"}, +// {0x03, "DPM: Off, DPMS: Suspend"}, +// {0x04, "DPM: Off, DPMS: Off" }, +// 0xb6 display tech (readonly) (0x03 = LCD active matrix) +// {0x01, "CRT (shadow mask)"}, +// {0x02, "CRT (aperture grill)"}, +// {0x03, "LCD (active matrix)"}, // TFT in 2.0 +// {0x04, "LCos"}, +// {0x05, "Plasma"}, +// {0x06, "OLED"}, +// {0x07, "EL"}, +// {0x08, "Dynamic MEM"}, // MEM in 2.0 +// {0x09, "Static MEM"}, // not in 2.0 +// 0x62 speaker volume (0-100) +// 0x8d audio mute (1=mute, 2=unmute) +// 0xca OSD (1=disabled, 2=enabled) +// 0xda scan mode +// {0x00, "Normal operation"}, +// {0x01, "Underscan"}, +// {0x02, "Overscan"}, +// {0x03, "Widescreen" } +// 0xdb image mode +// {0x00, "No effect"}, +// {0x01, "Full mode"}, +// {0x02, "Zoom mode"}, +// {0x03, "Squeeze mode" }, +// {0x04, "Variable"}, +// 0x8d blank state (1=blank, 2 = unblack) +// 0x82 horiz mirror (0=normal, 1 = mirror) +// 0x84 vert mirror (0=normal, 1 = mirror) +// 0x63 speaker sel (0=front l/r, 1=side l/r, 2=rear l/r, 3=subwoofer) +// 0x86 scaling values +// {0x01, "No scaling"}, +// {0x02, "Max image, no aspect ration distortion"}, +// {0x03, "Max vertical image, no aspect ratio distortion"}, +// {0x04, "Max horizontal image, no aspect ratio distortion"}, +// {0x05, "Max vertical image with aspect ratio distortion"}, +// {0x06, "Max horizontal image with aspect ratio distortion"}, +// {0x07, "Linear expansion (compression) on horizontal axis"}, // Full mode +// {0x08, "Linear expansion (compression) on h and v axes"}, // Zoom mode +// {0x09, "Squeeze mode"}, +// {0x0a, "Non-linear expansion"}, // Variable +// 0x94 stereo mode +// {0x00, "Speaker off/Audio not supported"}, +// {0x01, "Mono"}, +// {0x02, "Stereo"}, +// {0x03, "Stereo expanded"}, +// {0x11, "SRS 2.0"}, +// {0x12, "SRS 2.1"}, +// {0x13, "SRS 3.1"}, +// {0x14, "SRS 4.1"}, +// {0x15, "SRS 5.1"}, +// {0x16, "SRS 6.1"}, +// {0x17, "SRS 7.1"}, +// {0x21, "Dolby 2.0"}, +// {0x22, "Dolby 2.1"}, +// {0x23, "Dolby 3.1"}, +// {0x24, "Dolby 4.1"}, +// {0x25, "Dolby 5.1"}, +// {0x26, "Dolby 6.1"}, +// {0x27, "Dolby 7.1"}, +// {0x31, "THX 2.0"}, +// {0x32, "THX 2.1"}, +// {0x33, "THX 3.1"}, +// {0x34, "THX 4.1"}, +// {0x35, "THX 5.1"}, +// {0x36, "THX 6.1"}, +// {0x37, "THX 7.1"}, + +////////////////////////////////////////////////////////////////////////////// + +// ddc lib handle and func symbols +static void *ddc_lib = NULL; +struct { + DDCA_Status (*ddca_get_display_info_list2) + (bool include_invalid_displays, DDCA_Display_Info_List **dlist_loc); + void (*ddca_free_display_info_list) + (DDCA_Display_Info_List *dlist); + DDCA_Status (*ddca_open_display2) + (DDCA_Display_Ref ddca_dref, bool wait, DDCA_Display_Handle *ddca_dh_loc); + DDCA_Status (*ddca_get_non_table_vcp_value) + (DDCA_Display_Handle ddca_dh, DDCA_Vcp_Feature_Code feature_code, DDCA_Non_Table_Vcp_Value *valrec); + DDCA_Status (*ddca_set_non_table_vcp_value) + (DDCA_Display_Handle ddca_dh, DDCA_Vcp_Feature_Code feature_code, uint8_t hi_byte, uint8_t lo_byte); + DDCA_Status (*ddca_close_display) + (DDCA_Display_Handle ddca_dh); +} ddc_func; + +static DDCA_Display_Info_List *ddc_dlist = NULL; +static DDCA_Display_Handle *ddc_dh = NULL; + +static void +_ddc_clean(void) +{ + int i; + + if (!ddc_lib) return; + if (ddc_dlist) + { + if (ddc_dh) + { + for (i = 0; i < ddc_dlist->ct; i++) + { + ddc_func.ddca_close_display(ddc_dh[i]); + } + free(ddc_dh); + ddc_dh = NULL; + } + ddc_func.ddca_free_display_info_list(ddc_dlist); + ddc_dlist = NULL; + } +} + +static Eina_Bool +_ddc_probe(void) +{ + int i; + + if (!ddc_lib) return EINA_FALSE; + _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; + ddc_dh = calloc(ddc_dlist->ct, sizeof(DDCA_Display_Handle)); + if (!ddc_dh) + { + ddc_func.ddca_free_display_info_list(ddc_dlist); + ddc_dlist = NULL; + free(ddc_dh); + } + for (i = 0; i < ddc_dlist->ct; i++) + { + 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) + { + for (i = i - 1; i >= 0; i--) + { + ddc_func.ddca_close_display(ddc_dh[i]); + } + free(ddc_dh); + ddc_dh = NULL; + ddc_func.ddca_free_display_info_list(ddc_dlist); + ddc_dlist = NULL; + return EINA_FALSE; + } + d = calloc(1, sizeof(Dev)); + 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); + } + } + return EINA_TRUE; +} + +static Eina_Bool +_ddc_init(void) +{ + ddc_lib = dlopen("libddcutil.so.2", RTLD_NOW | RTLD_LOCAL); + if (!ddc_lib) return EINA_FALSE; +#define SYM(_x) \ + do { \ + ddc_func._x = dlsym(ddc_lib, #_x); \ + if (!ddc_func._x) return EINA_FALSE; \ + } while (0) + SYM(ddca_get_display_info_list2); + SYM(ddca_free_display_info_list); + SYM(ddca_open_display2); + SYM(ddca_get_non_table_vcp_value); + SYM(ddca_set_non_table_vcp_value); + SYM(ddca_close_display); + + // brute force modprobe this as it likely is needed - probe will fail + // if this doesn't work or find devices anyway + system("modprobe i2c-dev"); + if (!_ddc_probe()) return EINA_FALSE; + + return EINA_TRUE; +} + +static Req * +_req_alloc(const char *req, const char *params) +{ + Req *r; + + if (!params) return NULL; + r = calloc(1, sizeof(Req) + strlen(req) + 1 + strlen(params) + 1); + if (!r) return NULL; + r->req = ((char *)r) + sizeof(Req); + strcpy(r->req, req); + r->params = r->req + strlen(r->req) + 1; + strcpy(r->params, params); + return r; +} + +static void +_request(const char *req, const char *params) +{ + Eina_List *l; + Req *r2, *r = _req_alloc(req, params); + if (!r) return; + + eina_lock_take(&_devices_lock); + EINA_LIST_FOREACH(_req, l, r2) + { + if (!strcmp(r2->req, r->req)) + { + if (!strcmp(req, "refresh")) + { + _req = eina_list_remove_list(_req, l); + free(r2); + break; + } + else if ((!strcmp(req, "val-set")) || + (!strcmp(req, "val-get"))) + { + if ((!strncmp(params, r2->params, 256)) && + (params[256] == ' ')) + { + const char *space = strchr(params + 256 + 1, ' '); + if (!strncmp(params, r2->params, (space - params))) + { + _req = eina_list_remove_list(_req, l); + free(r2); + break; + } + } + } + } + } + _req = eina_list_append(_req, r); + eina_semaphore_release(&_worker_sem, 1); + eina_lock_release(&_devices_lock); +} + +static void +_do_list(Ecore_Thread *th) +{ + Eina_List *l; + Dev *d; + Req *r; + Eina_Strbuf *sbuf; + + sbuf = eina_strbuf_new(); + if (sbuf) + { + eina_lock_take(&_devices_lock); + EINA_LIST_FOREACH(_devices, l, d) + { + eina_strbuf_append(sbuf, d->edid); + if (l->next) eina_strbuf_append(sbuf, " "); + } + eina_lock_release(&_devices_lock); + + r = _req_alloc("ddc-list", eina_strbuf_string_get(sbuf)); + if (r) ecore_thread_feedback(th, r); + eina_strbuf_free(sbuf); + } +} + +static Eina_Bool +_id_ok(int id) +{ + if (id == 0x10) return EINA_TRUE; // backlight allowed + return EINA_FALSE; +} + +static Dev * +_dev_find(const char *edid) +{ + Eina_List *l; + Dev *d; + + EINA_LIST_FOREACH(_devices, l, d) + { + if (!strcmp(d->edid, edid)) + { + return d; + } + } + return NULL; +} + +static void +_do_val_set(Ecore_Thread *th, const char *edid, int id, int val) +{ + Dev *d; + Req *r; + int screen; + char buf[512]; + + if (!ddc_lib) goto err; + if (!edid) goto err; + if (!_id_ok(id)) goto err; + if ((val < 0) || (val >= 65536)) goto err; + + eina_lock_take(&_devices_lock); + d = _dev_find(edid); + if (!d) + { + eina_lock_release(&_devices_lock); + goto err; + } + screen = d->screen; + eina_lock_release(&_devices_lock); + + if (ddc_func.ddca_set_non_table_vcp_value + (ddc_dh[screen], id, (val >> 8) & 0xff, val & 0xff) == 0) + { + snprintf(buf, sizeof(buf), "%s %i %i ok", edid, id, val); + } + else + { +err: + snprintf(buf, sizeof(buf), "%s %i %i err", edid, id, val); + } + r = _req_alloc("ddc-val-set", buf); + if (r) ecore_thread_feedback(th, r); +} + +static void +_do_val_get(Ecore_Thread *th, const char *edid, int id) +{ + Dev *d; + Req *r; + int screen, val; + char buf[512]; + DDCA_Non_Table_Vcp_Value valrec; + + if (!ddc_lib) goto err; + if (!edid) goto err; + if (!_id_ok(id)) goto err; + + eina_lock_take(&_devices_lock); + d = _dev_find(edid); + if (!d) + { + eina_lock_release(&_devices_lock); + goto err; + } + screen = d->screen; + eina_lock_release(&_devices_lock); + + if (ddc_func.ddca_get_non_table_vcp_value + (ddc_dh[screen], id, &valrec) == 0) + { + val = valrec.sl | (valrec.sh << 8); + snprintf(buf, sizeof(buf), "%s %i %i", edid, id, val); + } + else + { +err: + snprintf(buf, sizeof(buf), "%s %i -1", edid, id); + } + r = _req_alloc("ddc-val-get", buf); + if (r) ecore_thread_feedback(th, r); +} + +static void +_cb_worker(void *data EINA_UNUSED, Ecore_Thread *th) +{ + Req *r; + + _ddc_init(); + _do_list(th); + + for (;;) + { + // wait for requests + eina_semaphore_lock(&_worker_sem); + eina_lock_take(&_devices_lock); + if (_req) + { + r = _req->data; + if (r) + { + _req = eina_list_remove_list(_req, _req); + eina_lock_release(&_devices_lock); + if (!strcmp(r->req, "list")) + { + _do_list(th); + } + else if (!strcmp(r->req, "refresh")) + { + _ddc_probe(); + _do_list(th); + } + else if (!strcmp(r->req, "val-set")) + { + int id, val; + char edid[257]; + if (sscanf(r->params, "%256s %i %i", edid, &id, &val) == 3) + _do_val_set(th, edid, id, val); + } + else if (!strcmp(r->req, "val-get")) + { + int id; + char edid[257]; + if (sscanf(r->params, "%256s %i", edid, &id) == 2) + _do_val_get(th, edid, id); + } + free(r); + } + else eina_lock_release(&_devices_lock); + } + else eina_lock_release(&_devices_lock); + } +} + +static void +_cb_worker_message(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED, void *msg_data) +{ + Req *r = msg_data; + + if (!r) return; + e_system_inout_command_send(r->req, "%s", r->params); + free(r); +} + +static void +_cb_worker_end(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED) +{ +} + +static void +_cb_worker_cancel(void *data EINA_UNUSED, Ecore_Thread *th EINA_UNUSED) +{ +} + +static void +_cb_ddc_list(void *data EINA_UNUSED, const char *params) +{ + _request("list", params); +} + +static void +_cb_ddc_refresh(void *data EINA_UNUSED, const char *params) +{ + _request("refresh", params); +} + +static void +_cb_ddc_val_set(void *data EINA_UNUSED, const char *params) +{ + _request("val-set", params); +} + +static void +_cb_ddc_val_get(void *data EINA_UNUSED, const char *params) +{ + _request("val-get", params); +} + +void +e_system_ddc_init(void) +{ + eina_lock_new(&_devices_lock); + eina_semaphore_new(&_worker_sem, 0); + ecore_thread_feedback_run(_cb_worker, _cb_worker_message, + _cb_worker_end, _cb_worker_cancel, + NULL, EINA_TRUE); + e_system_inout_command_register("ddc-list", _cb_ddc_list, NULL); + e_system_inout_command_register("ddc-refresh", _cb_ddc_refresh, NULL); + e_system_inout_command_register("ddc-val-set", _cb_ddc_val_set, NULL); + e_system_inout_command_register("ddc-val-get", _cb_ddc_val_get, NULL); +} + +void +e_system_ddc_shutdown(void) +{ + // only shutdown things we really have to - no need to free mem etc. +} diff --git a/src/bin/system/e_system_main.c b/src/bin/system/e_system_main.c index de7873ade..fd7eb9d2c 100644 --- a/src/bin/system/e_system_main.c +++ b/src/bin/system/e_system_main.c @@ -287,6 +287,7 @@ main(int argc EINA_UNUSED, const char **argv EINA_UNUSED) e_system_inout_init(); e_system_backlight_init(); + e_system_ddc_init(); e_system_storage_init(); e_system_power_init(); e_system_rfkill_init(); @@ -302,6 +303,7 @@ main(int argc EINA_UNUSED, const char **argv EINA_UNUSED) e_system_rfkill_shutdown(); e_system_power_shutdown(); e_system_storage_shutdown(); + e_system_ddc_shutdown(); e_system_backlight_shutdown(); e_system_inout_shutdown(); diff --git a/src/bin/system/meson.build b/src/bin/system/meson.build index d570fa4d6..64683b96d 100644 --- a/src/bin/system/meson.build +++ b/src/bin/system/meson.build @@ -2,6 +2,7 @@ src = [ 'e_system_main.c', 'e_system_inout.c', 'e_system_backlight.c', + 'e_system_ddc.c', 'e_system_storage.c', 'e_system_power.c', 'e_system_rfkill.c',