From 4654f50e7b50aefe7b41c510c10a380afc54f871 Mon Sep 17 00:00:00 2001 From: Rexy712 Date: Fri, 27 Apr 2018 19:52:54 -0700 Subject: [PATCH] added sysfs functionality --- makefile | 4 ++ src/rex-edid.c | 156 +++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 149 insertions(+), 11 deletions(-) diff --git a/makefile b/makefile index 95c265f..0a712f4 100644 --- a/makefile +++ b/makefile @@ -65,6 +65,10 @@ $(OBJDIR): $(DEPDIR): $(call mkdir,"$@") +.PHONY: install +install: $(MAIN_EXECUTABLE) + install -m 755 "$(MAIN_EXECUTABLE)" /usr/bin/ + .PHONY: clean clean: $(call rmdir,"$(DEPDIR)") diff --git a/src/rex-edid.c b/src/rex-edid.c index 37fe296..0692259 100644 --- a/src/rex-edid.c +++ b/src/rex-edid.c @@ -21,6 +21,10 @@ #include #include #include +#include + +#define REX_EDID_VERSION_MAJ 0u +#define REX_EDID_VERSION_MIN 2u #define RANDR_MIN_VER_MAJ 1u #define RANDR_MIN_VER_MIN 3u @@ -74,7 +78,14 @@ _Noreturn void help(int ret){ printf("Usage: rex-edid [--help]\n"); printf("\n"); printf("Options:\n"); - printf("%-20s%s\n", "\t--help|-h", "show this help message"); + printf("\t--help|-h\n"); + printf("\t\tshow this help message\n"); + printf("\t--sysfs|-s\n"); + printf("\t\tget edid data and device names from sysfs\n"); + printf("\t\tNOT intended for use other than by udev rule\n"); + printf("\t--xrandr|-s\n"); + printf("\t\tget edid data and device names from X using randr extension\n"); + printf("\t\trequires randr version %u.%u or newer\n", RANDR_MIN_VER_MAJ, RANDR_MIN_VER_MIN); printf("\n"); printf("rex-edid Copyright (C) 2018 rexy712\n"); printf("This program comes with ABSOLUTELY NO WARRANTY; for details type refer to the LICENSE file.\n"); @@ -82,8 +93,16 @@ _Noreturn void help(int ret){ printf("under certain conditions; see the LICENSE file for details.\n"); exit(ret); } +_Noreturn void version(void){ + printf("rex-edid version %u.%u\n", REX_EDID_VERSION_MAJ, REX_EDID_VERSION_MIN); + printf("Copyright (C) 2018 rexy712\n"); + printf("This program comes with ABSOLUTELY NO WARRANTY; for details type refer to the LICENSE file.\n"); + printf("This is free software, and you are welcome to redistribute it\n"); + printf("under certain conditions; see the LICENSE file for details.\n"); + exit(0); +} -int main(int argc, char* argv[]){ +int rex_edid_xrandr(void){ xcb_connection_t* connection; /*connection to x server*/ xcb_window_t root; /*handle on root window of screen???*/ xcb_timestamp_t timestamp; /*timestamp of resource reply???*/ @@ -96,15 +115,6 @@ int main(int argc, char* argv[]){ xcb_randr_get_screen_resources_current_reply_t* randr_resources_reply; /*X server reply to our resource query*/ - for(i = 1;i < argc;++i){ - if(!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) - help(0); - else{ - fprintf(stderr, "Unrecognized option '%s'\n", argv[i]); - help(1); - } - } - /*initialize connection to x server*/ connection = xcb_connect(NULL, &screen_num); if(xcb_connection_has_error(connection)){ @@ -175,4 +185,128 @@ int main(int argc, char* argv[]){ free(randr_resources_reply); xcb_disconnect(connection); + return 0; +} + +/*get device name from DEVPATH environment variable and prepend '/sys' to it*/ +char* get_device_path(int* len){ + char* devpath; + int length; + char* tmp; + + /*udev stores the device location in sysfs in DEVPATH environment variable*/ + devpath = getenv("DEVPATH"); + if(!devpath) + return NULL; + length = strlen(devpath) + 5; + tmp = malloc(length); + if(!tmp) + return NULL; + tmp[length-1] = 0; + + snprintf(tmp, length, "/sys%s", devpath); + if(len) + *len = length-1; + return tmp; +} + +/*extract device name from the device path (the last part of the pathname)*/ +char* get_device_name(char* devpath, int strlength){ + int i; + for(i = strlength-1;i >= 0;--i){ + if(devpath[i] == '/'){ + if(i == strlength) + return NULL; + return &(devpath[i])+1; + } + } + return NULL; +} + +int rex_edid_sysfs(void){ + int devpath_len; /*length of device path name*/ + int devname_len; /*length of device name*/ + char* devpath; /*name of device path*/ + char* devname; /*name of the device*/ + DIR* dp; /*pointer to open device directory in sysfs*/ + struct dirent* dir; /*accessor to sysfs directory*/ + + /*set up device names*/ + devpath = get_device_path(&devpath_len); + if(!devpath){ + fprintf(stderr, "DEVPATH is empty!\n"); + return -3; + } + devname = get_device_name(devpath, devpath_len); + devname_len = strlen(devname); + + /*open directory*/ + dp = opendir(devpath); + if(!dp){ + fprintf(stderr, "Unable to open DEVPATH!\n"); + return -2; + } + + /*check all contents of device directory*/ + while((dir = readdir(dp))){ + if(!strncmp(dir->d_name, devname, devname_len)){ + int edid_len; /*length of full path to edid file*/ + char* edid_file; /*buffer for edid path name*/ + unsigned char c; /*place to store char from file*/ + + /*set up edid file path*/ + edid_len = strlen(dir->d_name)+1 + devpath_len + 6; + edid_file = malloc(edid_len); + snprintf(edid_file, edid_len, "%s/%s/edid", devpath, dir->d_name); + printf("%s:", dir->d_name + devname_len+1); + + /*read in edid data from file*/ + FILE* fd = fopen(edid_file, "r"); + if(!fd){ + fprintf(stderr, "Unable to open edid file\n"); + free(edid_file); + printf("\n"); + continue; + } + + c = fgetc(fd); + while(!feof(fd)){ + printf("%02x", c); + c = fgetc(fd); + } + + /*cleanup*/ + fclose(fd); + free(edid_file); + printf("\n"); + } + } + + closedir(dp); + free(devpath); + return 0; +} + +int main(int argc, char* argv[]){ + int i; + + if(argc == 1){ + help(1); + } + + for(i = 1;i < argc;++i){ + if(!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")){ + help(0); + }else if(!strcmp(argv[i], "--sysfs") || !strcmp(argv[i], "-s")){ + return rex_edid_sysfs(); + }else if(!strcmp(argv[i], "--xrandr") || !strcmp(argv[i], "-x")){ + return rex_edid_xrandr(); + }else if(!strcmp(argv[i], "--version")){ + version(); + }else{ + fprintf(stderr, "Unrecognized option '%s'\n", argv[i]); + help(1); + } + } + return 1; }