diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c index 808cabed44..4c3fbaaa64 100644 --- a/hw/xfree86/ddc/interpret_edid.c +++ b/hw/xfree86/ddc/interpret_edid.c @@ -28,6 +28,10 @@ #include #endif +#include +#include +#include + #include "misc.h" #include "xf86.h" #include "xf86_OSproc.h" @@ -164,15 +168,18 @@ encode_aspect_ratio(xf86MonPtr m) } } -xf86MonPtr -xf86InterpretEDID(int scrnIndex, Uchar * block) +static xf86MonPtr parseEDID(int scrnIndex, uint8_t *block, size_t size, bool copy) { - xf86MonPtr m; + xf86MonPtr m = calloc(1, sizeof(xf86Monitor) + (copy ? size : 0)); + if (!m) + return NULL; + + /* make a copy of the EDID block for later reference */ + if (copy) { + memcpy(&(m[1]), block, size); + block = (uint8_t*)&m[1]; + } - if (!block) - return NULL; - if (!(m = XNFcallocarray(1, sizeof(xf86Monitor)))) - return NULL; m->scrnIndex = scrnIndex; m->rawData = block; @@ -191,6 +198,11 @@ xf86InterpretEDID(int scrnIndex, Uchar * block) handle_edid_quirks(m); encode_aspect_ratio(m); + if (size > 128) + m->flags |= EDID_COMPLETE_RAWDATA; + + /* possibly add more extended parsing here, eg. HDR information */ + return m; error: @@ -198,6 +210,24 @@ xf86InterpretEDID(int scrnIndex, Uchar * block) return NULL; } +/* new entry point, should be used whenever possible */ +xf86MonPtr xf86ParseEDID(ScrnInfoPtr pScrn, uint8_t *block, size_t size) +{ + if (!pScrn || !block || !size) + return NULL; + + return parseEDID(pScrn->scrnIndex, block, size, true); +} + +/* old entry point, deprecated but still needed for backwards compat */ +xf86MonPtr xf86InterpretEDID(int scrnIndex, uint8_t *block) +{ + if (!block) + return NULL; + + return parseEDID(scrnIndex, block, EDID1_LEN, false); +} + static int get_cea_detail_timing(Uchar * blk, xf86MonPtr mon, struct detailed_monitor_section *det_mon) diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h index c750441fcb..17fc38ea5e 100644 --- a/hw/xfree86/ddc/xf86DDC.h +++ b/hw/xfree86/ddc/xf86DDC.h @@ -42,4 +42,17 @@ extern _X_EXPORT xf86MonPtr xf86InterpretEEDID(int screenIndex, Uchar * block); extern _X_EXPORT Bool xf86SetDDCproperties(ScrnInfoPtr pScreen, xf86MonPtr DDC); +/* + * parse EDID block and return a newly allocated xf86Monitor + * + * the data block will be copied into the structure (actually right after the struct) + * and thus automatically be freed when the returned struct is freed. + * + * @param screenIndex index of the screen, will be recorded in the xf86Monitor + * @param block the EDID block to parse + * @param size size of the EDID block (128 or larger for extended types) + * @return newly allocated xf86MonRec or NULL on failure + */ +_X_EXPORT xf86MonPtr xf86ParseEDID(ScrnInfoPtr pScreen, uint8_t *block, size_t size); + #endif