summaryrefslogtreecommitdiffstats
path: root/core/modules/beamergui
diff options
context:
space:
mode:
authorSimon Rettberg2017-02-28 14:26:43 +0100
committerSimon Rettberg2017-02-28 14:26:43 +0100
commit2a004dfc0fdb15ad462b5b52f55b76a63cba9590 (patch)
tree65a404dadce7e34e5fee0c58dc9c546cbf4ead53 /core/modules/beamergui
parent[speedcheck] New module (diff)
downloadmltk-2a004dfc0fdb15ad462b5b52f55b76a63cba9590.tar.gz
mltk-2a004dfc0fdb15ad462b5b52f55b76a63cba9590.tar.xz
mltk-2a004dfc0fdb15ad462b5b52f55b76a63cba9590.zip
[beamergui] Use parse-edid to check if output matches specific device name
Diffstat (limited to 'core/modules/beamergui')
-rwxr-xr-xcore/modules/beamergui/data/opt/openslx/scripts/beamergui-mode_setter30
-rw-r--r--core/modules/beamergui/module.build3
-rw-r--r--core/modules/beamergui/source/parse-edid/LICENSE19
-rw-r--r--core/modules/beamergui/source/parse-edid/modes.h62
-rw-r--r--core/modules/beamergui/source/parse-edid/parse-edid.c368
5 files changed, 482 insertions, 0 deletions
diff --git a/core/modules/beamergui/data/opt/openslx/scripts/beamergui-mode_setter b/core/modules/beamergui/data/opt/openslx/scripts/beamergui-mode_setter
index b747d257..461152fa 100755
--- a/core/modules/beamergui/data/opt/openslx/scripts/beamergui-mode_setter
+++ b/core/modules/beamergui/data/opt/openslx/scripts/beamergui-mode_setter
@@ -25,6 +25,11 @@ MODES=("${MODES[@]}" "1280x1024 109.00 1280 1368 1496 1712 1024 1027 1034 1063
CONFIGFILE="/opt/openslx/beamergui/beamer.conf"
+# Hard-code a few models known to be problematic
+declare -a FORCE_BEAMER
+FORCE_BEAMER=("AT-HDVS-RX")
+
+
################################################################################
#DRIVER=$(lspci -nnk | grep -i vga -A3 | grep 'in use'| awk '{ print $NF }')
@@ -58,6 +63,31 @@ if [ ${#OUTPUTNAMES[@]} -eq 2 ]; then
MAYBEAMER=
SMALL=
for i in 0 1; do
+ # See if we hard-coded the device as a beamer
+ EDID=$(<<<$XRANDRV grep -Pzo "\n${OUTPUTNAMES[$i]}\N*connected\N*\n(\s+\N*\n)+" | grep -Eao '[0-9a-f]{32}' tmp | sed -r ':a;N;$!ba;s/[^0-9a-f]//gI;s/([0-9a-f]{2})/\\\\x\1/gI' | xargs printf | parse-edid)
+ MODEL_NAME=$(<<<$EDID awk '{if ($1 == "ModelName") { A=$2$3$4$5; print substr(A, 2, length(A) - 2)}}')
+ echo "'${OUTPUTNAMES[$i]}' is connected to device '$MODEL_NAME'"
+ # Have a name, do the checks
+ if [ -n "$MODEL_NAME" ]; then
+ FOUND=
+ # Try hard coded values from above
+ for model in "${FORCE_BEAMER[@]}"; do
+ if [ "x$model" = "x$MODEL_NAME" ]; then
+ FOUND=ya
+ break
+ fi
+ done
+ # Now try user supplied config
+ if [ -z "$FOUND" ] && grep -Fxq "${MODEL_NAME}=beamer" "$CONFIGFILE"; then
+ FOUND=ya
+ fi
+ # Set beamer if any match
+ if [ -n "$FOUND" ]; then
+ BEAMER=$i
+ continue
+ fi
+ fi
+ # Classic test by what X(randr) figured out
WIDTH=$(grep -E "^${OUTPUTNAMES[$i]}.*[0-9]+mm x [0-9]+mm" <<<"$XRANDR" | head -n 1 | grep -o -E ' [0-9]+mm x' | grep -o -E '[0-9]+')
if [ -z "$WIDTH" ] || [ "$WIDTH" -eq 0 ] || [ "$WIDTH" -gt 900 ]; then
echo "Screen $i is beamer, width is '$WIDTH'"
diff --git a/core/modules/beamergui/module.build b/core/modules/beamergui/module.build
index f920bb74..424c8bff 100644
--- a/core/modules/beamergui/module.build
+++ b/core/modules/beamergui/module.build
@@ -21,6 +21,9 @@ build() {
"$QMAKE" "$SRCDIR/src/beamergui.pro" -r -spec linux-g++ || perror "'qmake-qt4' failed (e.g. not installed)."
pinfo "Running make"
make || perror "'make' failed."
+
+ # Make read-edid
+ gcc -o "${MODULE_BUILD_DIR}/opt/openslx/bin/read-edid" "${MODULE_WORK_DIR}/source/parse-edid/parse-edid.c" || perror "Compiling parse-edid failed."
}
post_copy() {
:
diff --git a/core/modules/beamergui/source/parse-edid/LICENSE b/core/modules/beamergui/source/parse-edid/LICENSE
new file mode 100644
index 00000000..be945d3e
--- /dev/null
+++ b/core/modules/beamergui/source/parse-edid/LICENSE
@@ -0,0 +1,19 @@
+This is the parse-edid part from read-edid by Matthew Kern.
+Original license file from read-edid 3.0.2:
+
+ * This is an unofficial license. Let's call it BSD-like, with these terms:
+ * * You are free to use this software for any purpose. I cannot guarantee
+ * anything about this software or its fitness for any purpose. I will
+ * offer support for this software as long as I am capable of doing so,
+ * but this should not be interpreted as a support contract of any kind.
+ *
+ * * You are free to modify, distribute, etc. this code under the strict
+ * condition that you email me, Matthew Kern <pyrophobicman@gmail.com>, a
+ * brief message on what you're doing. Nothing will be rejected, this is
+ * simply to keep tabs on my work, and maybe we can share ideas on EDIDs.
+ *
+ * * (C)opyright 2008-2014 Matthew Kern
+ *
+ * Please see AUTHORS for a list of the people who made this software
+ * possible. All of the current code is a rewrite of my own work, but
+ * I am still indebted to those guys for a ton of the ideas.
diff --git a/core/modules/beamergui/source/parse-edid/modes.h b/core/modules/beamergui/source/parse-edid/modes.h
new file mode 100644
index 00000000..aef39b5c
--- /dev/null
+++ b/core/modules/beamergui/source/parse-edid/modes.h
@@ -0,0 +1,62 @@
+char ceamodes[61][128] = { //Guess who had to do these by hand... you're welcome.
+"",
+"25.200 640 656 752 800 480 490 492 525 -hsync -vsync",
+"27.027 720 736 798 858 480 489 495 525 -hsync -vsync",
+"27.027 720 736 798 858 480 489 495 525 -hsync -vsync",
+"74.250 1280 1390 1420 1650 720 725 730 750 +hsync +vsync",
+"74.250 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace",
+"27.027 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace",
+"27.027 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace",
+"27.027 1440 1478 1602 1716 240 244 247 262 -hsync -vsync",
+"27.027 1440 1478 1602 1716 240 244 247 262 -hsync -vsync",
+"54.054 2880 2956 3204 3432 480 484 487 525 -hsync -vsync interlace",
+"54.054 2880 2956 3204 3432 480 484 487 525 -hsync -vsync interlace",
+"54.054 2880 2956 3204 3432 240 244 247 262 -hsync -vsync",
+"54.054 2880 2956 3204 3432 240 244 247 262 -hsync -vsync",
+"54.054 1440 1472 1596 1716 480 489 495 525 -hsync -vsync",
+"54.054 1440 1472 1596 1716 480 489 495 525 -hsync -vsync",
+"148.500 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync",//16
+"27.000 720 732 796 864 576 581 586 625 -hsync -vsync",
+"27.000 720 732 796 864 576 581 586 625 -hsync -vsync",
+"74.250 1280 1720 1760 1980 720 725 730 750 +hsync +vsync",
+"74.250 1920 2448 2492 2640 1080 1082 1089 1125 +hsync +vsync interlace",
+"27.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace",
+"27.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace",
+"27.000 1440 1464 1590 1728 288 290 293 312 -hsync -vsync",
+"27.000 1440 1464 1590 1728 288 290 293 312 -hsync -vsync",
+"54.000 2880 2928 3180 3456 576 578 581 625 -hsync -vsync interlace",
+"54.000 2880 2928 3180 3456 576 578 581 625 -hsync -vsync interlace",
+"54.000 2880 2928 3180 3456 288 290 393 312 -hsync -vsync",
+"54.000 2880 2928 3180 3456 288 290 393 312 -hsync -vsync",
+"54.000 1440 1464 1592 1728 576 581 586 625 -hsync -vsync",
+"54.000 1440 1464 1592 1728 576 581 586 625 -hsync -vsync",
+"148.500 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync",
+"74.250 1920 2558 2602 2750 1080 1084 1089 1125 +hsync +vsync",//32
+"74.250 1920 2448 2492 2640 1080 1084 1089 1125 +hsync +vsync",
+"74.250 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync",
+"108.000 2880 2944 3192 3432 480 489 495 525 -hsync -vsync",
+"108.000 2880 2944 3192 3432 480 489 495 525 -hsync -vsync",
+"108.000 2880 2928 3184 3456 576 581 586 625 -hsync -vsync",
+"108.000 2880 2928 3184 3456 576 581 586 625 -hsync -vsync",
+"72.000 1920 1952 2120 2304 1080 1103 1108 1250 +hsync +vsync interlace",
+"148.500 1920 2448 2492 2640 1080 1082 1087 1125 +hsync +vsync interlace",
+"148.500 1280 1720 1760 1980 720 725 730 750 +hsync +vsync",
+"54.000 720 732 796 864 576 581 586 625 -hsync -vsync",
+"54.000 720 732 796 864 576 581 586 625 -hsync -vsync",
+"54.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace",
+"54.000 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace",
+"148.500 1920 2008 2052 2200 1080 1082 1087 1125 +hsync +vsync interlace",
+"148.500 1280 1390 1430 1650 720 725 730 750 +hsync +vsync",
+"54.000 720 736 798 858 480 489 495 525 -hsync -vsync", //48
+"54.000 720 736 798 858 480 489 495 525 -hsync -vsync",
+"54.000 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace",
+"54.000 1440 1478 1602 1716 480 484 487 525 -hsync -vsync interlace",
+"108.00 720 732 796 864 576 581 586 625 -hsync -vsync",
+"108.00 720 732 796 864 576 581 586 625 -hsync -vsync",
+"108.00 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace",
+"108.00 1440 1464 1590 1728 576 578 581 625 -hsync -vsync interlace",
+"108.108 720 736 798 858 480 489 495 525 -hsync -vsync",
+"108.108 720 736 798 858 480 489 495 525 -hsync -vsync",
+"108.108 1440 1478 1602 1716 480 484 587 525 -hsync -vsync interlace",
+"108.108 1440 1478 1602 1716 480 484 587 525 -hsync -vsync interlace",
+};
diff --git a/core/modules/beamergui/source/parse-edid/parse-edid.c b/core/modules/beamergui/source/parse-edid/parse-edid.c
new file mode 100644
index 00000000..5005af8c
--- /dev/null
+++ b/core/modules/beamergui/source/parse-edid/parse-edid.c
@@ -0,0 +1,368 @@
+/* Complete parse-edid rewrite. Using some unix-specific stuff - I don't care about dos
+ *
+ * Hope it works :P
+ *
+ *
+ * (C)opyright 2008-2014 Matthew Kern
+ * Full license terms in file LICENSE
+ * */
+
+#include <stdio.h> //for the *printf's et al.
+
+#include <unistd.h> //read, and because it's nice to have
+#include <stdlib.h> //exit, and because it's nice to have
+
+#include "modes.h"
+
+typedef unsigned char byte;
+
+byte edid[128]; //edid itself
+byte extb[128]; //extension block. Hope there's only 1, for now.
+
+char modearray[128][128];
+int native;
+int currentmode;
+
+static void die(char *msg) {
+ fprintf(stderr, "%s", msg);
+ exit(1);
+}
+
+static void warn(char *msg) {
+ fprintf(stderr, "WARNING: ");
+ fprintf(stderr, "%s", msg);
+ fprintf(stderr, "Trying to continue...\n");
+}
+
+static void diewemail(char *msg) {
+ fprintf(stderr, "%s", msg);
+ fprintf(stderr, "Something strange happened. Please contact the author,\nMatthew Kern at <pyrophobicman@gmail.com>\n");
+ exit(1);
+}
+
+int parseedid() {
+ int i;
+ int j;
+ byte sum = 0;
+ char modelname[13];
+ //int ptm;
+ int compsync = 0;
+ int hres;
+ int vres;
+
+ //check the checksum
+ for (i = 0; i<128; i++) {
+ sum += edid[i];
+ }
+ if (sum)
+ warn("Checksum failed\n");
+ else
+ fprintf(stderr, "Checksum Correct\n\n");
+
+ //check header
+ for (i = 0; i < 8; i++) {
+ if (!(((i == 0 || i == 7) && edid[i] == 0x00) || (edid[i] == 0xff))) //0x00 0xff 0xff 0xff 0xff 0xff 0x00
+ diewemail("Header incorrect. Probably not an edid\n");
+ }
+
+ //Make a monitor section...
+ printf("Section \"Monitor\"\n");
+
+ //Product Identification
+ /* Model Name: Only thing I do out of order of edid, to comply with X standards... */
+ for (i = 0x36; i < 0x7E; i += 0x12) { //read through descriptor blocks...
+ if (edid[i] == 0x00) { //not a timing descriptor
+ if (edid[i+3] == 0xfc) { //Model Name tag
+ for (j = 0; j < 13; j++) {
+ if (edid[i+5+j] == 0x0a)
+ modelname[j] = 0x00;
+ else
+ modelname[j] = edid[i+5+j];
+ }
+ }
+ }
+ }
+ printf("\tIdentifier \"%s\"\n\tModelName \"%s\"\n", modelname, modelname);
+
+ /* Vendor Name: 3 characters, standardized by microsoft, somewhere.
+ * bytes 8 and 9: f e d c b a 9 8 7 6 5 4 3 2 1 0
+ * Character 1 is e d c b a
+ * Character 2 is 9 8 7 6 5
+ * Character 3 is 4 3 2 1 0
+ * Those values start at 0 (0x00 is 'A', 0x01 is 'B', 0x19 is 'Z', etc.)
+ */
+ printf("\tVendorName \"%c%c%c\"\n", (edid[8] >> 2 & 0x1f) + 'A' - 1, (((edid[8] & 0x3) << 3) | ((edid[9] & 0xe0) >> 5)) + 'A' - 1, (edid[9] & 0x1f) + 'A' - 1 );
+
+ /* Skip Product ID and Serial Number. */
+ /* Week and Year: not required, but do it for fun. */
+ if (edid[0x10] <= 54)
+ printf("\t# Monitor Manufactured week %i of %i\n", (int)(edid[0x10]), ((int)(edid[0x11])) + 1990);
+ else if (edid[0x10] != 0xff)
+ printf("\t# Monitor Manufactured in %i\n", ((int)(edid[0x11])) + 1990);
+ else if (edid[0x10] == 0xff)
+ printf("\t# Monitor Model Year: %i\n", ((int)(edid[0x11])) + 1990);
+
+ //Edid Version
+ printf("\t# EDID version %i.%i\n", (int)(edid[0x12]), (int)(edid[0x13]));
+
+ //Basic Display Parameter
+ /* Digital or not? */
+ if (edid[0x14] & 0x80)
+ printf("\t# Digital Display\n");
+ else {
+ printf("\t# Analog Display\n");
+ if (edid[0x14] & 0x02) //sync on green.
+ printf("\tOption \"SyncOnGreen\" \"true\"\n");
+ if (edid[0x14] & 0x04)
+ compsync = 1; //Composite sync. Save for modelines.
+ }
+ /* Ignore video input definitions, because X doesn't care. */
+
+ /* Size parameters: H and V, in centimeters. Projectors put 0 here.
+ * DiplaySize is in millimeters, so multiply by 10
+ * If 0x16 is 0, but not 0x15, you really should do aspect ratio... */
+ if (edid[0x15] && edid[0x16])
+ printf("\tDisplaySize %i %i\n", ((int)(edid[0x15])) * 10, ((int)(edid[0x16])) * 10);
+ else
+ printf("\t# Display Physical Size not given. Normal for projectors.\n");
+
+ /* Gamma. Divide by 100, add 1. Defaults to 1, so if 0, it'll be 1 anyway. */
+ if (edid[0x17] != 0xff)
+ printf("\tGamma %.2f\n", (float)((((float)edid[0x17]) / 100) + 1));
+
+ /* DPMS. Simple yes or no. */
+ printf("\tOption \"DPMS\" \"%s\"\n", (edid[0x18] & 0xE0) ? "true" : "false");
+
+ /* Preferred timing mode. This has no meaning, really. The first mode given is preferred. */
+ //ptm = ((edid[0x18] & 0x02) ? 1 : 0);
+ //printf("\t# preferred timing mode %sfound\n", ptm ? "" : "not ");
+
+ /* GTF. Not sure what it means to X, so ignore it (for now) */
+
+ /* ignore chroma stuff as well. */
+
+ //Monitor Limits... okay, another one out of order with the EDID...
+
+ for (i = 0x36; i < 0x7E; i += 0x12) { //read through descriptor blocks...
+ if (edid[i] == 0x00) { //not a timing descriptor
+ if (edid[i+3] == 0xfd) { //monitor limits tag
+ printf("\tHorizsync %i-%i\n", (int)edid[i+7] + (((edid[i+4] & 0x0c) & 0x04) ? 255 : 0), (int)edid[i+8] + ((edid[i+4] & 0x08) ? 255 : 0));
+ printf("\tVertRefresh %i-%i\n", (int)edid[i+5] + (((edid[i+4] & 0x03) & 0x01) ? 255 : 0), (int)edid[i+6] + ((edid[i+4] & 0x02) ? 255 : 0));
+ printf("\t# Maximum pixel clock is %iMHz\n", (int)edid[i+9] * 10);
+ }
+ }
+ }
+
+ //I can ignore predefined modes - X knows these already.
+
+ int hactive, vactive, pixclk, hsyncoff, hsyncwidth, hblank, vsyncoff, vsyncwidth, vblank;
+ //Parse for Detailed Timing Descriptors...
+ for (i = 0x36; i < 0x7E; i += 0x12) { //read through descriptor blocks...
+ if ((edid[i] != 0x00) && (edid[i+1] != 0x00)) { //a dtd
+ hactive = edid[i+2] + ((edid[i+4] & 0xf0) << 4);
+ hblank = edid[i+3] + ((edid[i+4] & 0x0f) << 8);
+ vactive = edid[i+5] + ((edid[i+7] & 0xf0) << 4);
+ vblank = edid[i+6] + ((edid[i+7] & 0x0f) << 8);
+
+ //printf("\tModeline \t\"%dx%d\" ", hactive, vactive);
+
+ pixclk = (edid[i+1] << 8) | (edid[i]);
+
+ sprintf(modearray[currentmode], "%.2f ", (double)pixclk / 100.0);
+
+ //I'm using Fremlin's nomenclature...
+ //sync offset = front porch
+ //sync width = sync pulse width
+
+ hsyncoff = edid[i+8] | ((edid[i+11] & 0xC0) << 2);
+ hsyncwidth = edid[i+9] | ((edid[i+11] & 0x30) << 4);
+ vsyncoff = ((edid[i+10] & 0xf0) >> 4) | ((edid[i+11] & 0x0C) << 2);
+ vsyncwidth = (edid[i+10] & 0x0f) | ((edid[i+11] & 0x03) << 4);
+
+
+ sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], hactive, hactive+hsyncoff, hactive+hsyncoff+hsyncwidth, hactive+hblank);
+ sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], vactive, vactive+vsyncoff, vactive+vsyncoff+vsyncwidth, vactive+vblank);
+
+ if ( (edid[i+17]&0x80) || ((edid[i+17]&0x18) == 0x18) ) {
+ sprintf(modearray[currentmode], "%s%shsync %svsync %s", modearray[currentmode], ((edid[i+17]&0x10) && edid[i+17]&0x02) ? "+": "-", ((edid[i+17]&0x10) && edid[i+17]&0x04) ? "+": "-", (edid[i+17]&0x80) ? "interlace": "");
+ //hehe... there's been at least 2 bugs in the old parse-edid the whole time - somebody caught the htimings one, and I just caught two problems right here - lack of checking for analog sync and getting hsync and vsync backwards... yes, vsync and hsync have been flipped this whole time. Glad I'm rewriting
+ //printf("%s\n", modearray[currentmode]);
+ currentmode++;
+
+ }
+ //printf("\tEndmode\n");
+ }
+ }
+
+ //Standard Timings - put these after dtd's, because this way preferred is up top.
+ /* I started doing this, but I think it's unnecessary. Think not? you do it. I'll comment what you're missing.*/
+ int refresh;
+ for (i = 0x26; i < 0x36; i += 0x2) { //read through list of resolutions...
+ if (!(edid[i] == 1 && edid[i+1] == 1)) { //skip if it's "blank"
+ hres = (((int)edid[i]) + 31) * 8;
+ switch ((edid[i+1] & 0xC0) >> 6) {
+ case 0: vres = (hres * 10) / 16; //16:10 aspect ratio
+ break;
+ case 1: vres = (hres * 3) / 4; //4:3
+ break;
+ case 2: vres = (hres * 4) / 5; //5:4
+ break;
+ case 3: vres = (hres * 9) / 16; //16:9
+ break;
+ default: diewemail("The impossible has happened.\n");
+ }
+ refresh = (edid[i+1] & 0x3F) + 60;
+ printf("\t#Not giving standard mode: ");
+ printf("%ix%i, %iHz\n", hres, vres, refresh);
+ /*
+ printf("\tMode\t\"%ix%i\"\n", hres, vres);
+ printf("\t\tDotClock\t%.6f\n", (float)((hres * vres) * (((edid[i+1] & 0x3f) + 60)) / 1000000)); //(pixels/screen) * (screen/sec) / a million = megapixels/sec, aka dot clock in mHz
+ printf("\t\tHTimings\t\n");*/
+ }
+ }
+}
+
+int parseextb() {
+ int i, curloc, j;
+ //char nativename[64];
+ byte sum =0;
+ printf("\n\t#Extension block found. Parsing...\n");
+ /*
+ for (i = 0; i < 128; i++)
+ printf("byte %xh is 0x%x\n", i, extb[i]);
+ */
+ //printf("Tag: %x\n", extb[0]);
+
+ for (i=0;i<128;i++) {
+ sum +=extb[i];
+ }
+ if (sum != 0x00) {
+ die("Extension block checksum failed\n");
+ }
+ if (extb[0] != 0x02)
+ diewemail("I only know about extension blocks of type 02h. PLEASE email me!\n");
+ curloc = extb[2];
+ if (curloc == 0) {
+ printf("#No data in the extension block\n");
+ return 0;
+ }
+
+ //printf("There are %i bytes of data block\n", curloc - 4);
+
+ //see CEA tables 28-30
+ if (curloc > 4) {
+ if ((extb[4] & 0xE0) != 0x40) { //if the first one is not a video one
+ printf("extb[4]: 0x%x (0x%x)\n", extb[4], extb[4]&0xE0);
+ diewemail("Hmm, you have data blocks, but not video ones... weird\n");
+
+ }
+
+ for (i=0;i<(extb[4]&0x1F);i++) {
+ if ((extb[5+i]&0x7f) > 59) {
+ printf("#WARNING: I may have missed a mode (CEA mode %i)\n", extb[5+i]&0x7f);
+ if (native==-1)
+ printf("#DOUBLE WARNING: It's your first mode, too, so this may actually be important.\n");
+ }
+ else {
+ if (native==-1)
+ native = currentmode;
+ sprintf(modearray[currentmode], "%s", ceamodes[extb[5+i]&0x7F]);
+ currentmode++;
+ }
+ }
+
+ }
+
+ //starting 18-byte DTD's.
+
+
+ //Copypaste the DTD stuff from above.
+ int hactive, vactive, pixclk, hsyncoff, hsyncwidth, hblank, vsyncoff, vsyncwidth, vblank;
+ //Parse for Detailed Timing Descriptors...
+ for (i = curloc; i < curloc+(18*4); i += 0x12) { //read through descriptor blocks...
+ if ((extb[i] != 0x00) && (extb[i+1] != 0x00)) { //a dtd
+ hactive = extb[i+2] + ((extb[i+4] & 0xf0) << 4);
+ hblank = extb[i+3] + ((extb[i+4] & 0x0f) << 8);
+ vactive = extb[i+5] + ((extb[i+7] & 0xf0) << 4);
+ vblank = extb[i+6] + ((extb[i+7] & 0x0f) << 8);
+
+ //printf("\tModeline \t\"%dx%d\" ", hactive, vactive);
+
+ if (i == curloc && (extb[3]&0x0F) > 0) {
+ native = currentmode;
+ //sprintf(nativename, "%dx%d", hactive, vactive);
+ }
+
+ pixclk = (extb[i+1] << 8) | (extb[i]);
+
+ sprintf(modearray[currentmode], "%.2f ", (double)pixclk / 100.0);
+
+ //I'm using Fremlin's nomenclature...
+ //sync offset = front porch
+ //sync width = sync pulse width
+
+ hsyncoff = extb[i+8] | ((extb[i+11] & 0xC0) << 2);
+ hsyncwidth = extb[i+9] | ((extb[i+11] & 0x30) << 4);
+ vsyncoff = ((extb[i+10] & 0xf0) >> 4) | ((extb[i+11] & 0x0C) << 2);
+ vsyncwidth = (extb[i+10] & 0x0f) | ((extb[i+11] & 0x03) << 4);
+
+
+ sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], hactive, hactive+hsyncoff, hactive+hsyncoff+hsyncwidth, hactive+hblank);
+ sprintf(modearray[currentmode], "%s%u %u %u %u ", modearray[currentmode], vactive, vactive+vsyncoff, vactive+vsyncoff+vsyncwidth, vactive+vblank);
+
+
+ if ( (extb[i+17]&0x80) || ((extb[i+17]&0x18) == 0x18) ) {
+ sprintf(modearray[currentmode], "%s%shsync %svsync %s", modearray[currentmode], ((extb[i+17]&0x10) && extb[i+17]&0x02) ? "+": "-", ((extb[i+17]&0x10) && extb[i+17]&0x04) ? "+": "-", (extb[i+17]&0x80) ? "interlace": "");
+ //hehe... there's been at least 2 bugs in the old parse-edid the whole time - somebody caught the htimings one, and I just caught two problems right here - lack of checking for analog sync and getting hsync and vsync backwards... yes, vsync and hsync have been flipped this whole time. Glad I'm rewriting
+
+ }
+ //printf("\n");
+ currentmode++;
+ }
+ }
+
+}
+
+int dofooter() {
+ int i;
+ if (native != -1)
+ printf("\tModeline \t\"Mode %i\" %s\n", native, modearray[native]);
+ for (i=0;i<currentmode;i++) {
+ if (i != native)
+ printf("\tModeline \t\"Mode %i\" %s\n", i, modearray[i]);
+ }
+
+ if (native != -1)
+ printf("\tOption \"PreferredMode\" \"Mode %i\"\n", native); //half a chance of giving us the native default... The preferred mode is already in front.
+ printf("EndSection\n");
+}
+
+
+int main() {
+ int infd = 0;
+ int i;
+ int extblock = 0;
+
+ native = -1;
+ currentmode = 0;
+
+ if (read(infd, &edid, 128) != 128)
+ die("Partial Read... Try again\n");
+#ifdef EBUG
+ for (i = 0; i<128; i++)
+ printf("byte %i: %x\n", i, edid[i]);
+#endif
+ if (edid[126] == 0x01) {
+ if (read(infd, &extb, 128) != 128)
+ die("Partial Read... Try again\n");
+ extblock = 1;
+ }
+ else if (edid[126] > 0x01)
+ diewemail("You seem to have too many extension blocks. Will not continue to parse\n");
+
+ parseedid();
+ if (extblock)
+ parseextb();
+ dofooter();
+ return 0;
+}