2011/4/1 Mike Blumenkrantz <[email protected]>: > On Fri, 1 Apr 2011 22:19:19 +0200 > Leif Middelschulte <[email protected]> wrote: > >> Hello everyone, >> >> find attached a patch for EDID data extraction. My display's >> manufacturer didn't comply with the standard too much, so I can't test >> it entirely. But it should work. >> >> Review, comments and commit are welcome ;-) >> >> BR, >> >> Leif >> > Thanks for sending! I'll review it immediately! > > April fool's, it'll languish on the mailing list for months! :D Oh,
I forgot.... it's not april 1st anymore in .kr :-/ So then.. here you go > -- > Mike Blumenkrantz > Zentific: NULL pointer dereferences now 50% off! >
From a866c1f84c0ef44e85fc7c10abf7deff23e1fa08 Mon Sep 17 00:00:00 2001 From: Leif Middelschulte <[email protected]> Date: Fri, 1 Apr 2011 02:40:09 +0200 Subject: [PATCH] Added data extraction for raw EDID version >= 1.3 --- trunk/ecore/ChangeLog | 4 + trunk/ecore/src/lib/ecore_x/Ecore_X.h | 204 ++++++++ trunk/ecore/src/lib/ecore_x/xlib/Makefile.am | 1 + .../src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c | 486 ++++++++++++++++++++ 4 files changed, 695 insertions(+), 0 deletions(-) create mode 100644 trunk/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c diff --git a/trunk/ecore/ChangeLog b/trunk/ecore/ChangeLog index 31f5fe1..03479f3 100644 --- a/trunk/ecore/ChangeLog +++ b/trunk/ecore/ChangeLog @@ -113,3 +113,7 @@ * Add ecore_con_url_pipeline_set and ecore_con_url_pipeline_get for HTTP 1.1 pipelining support. + +2011-04-01 Leif Middelschulte + + * Add ecore_x_randr_edid_* data extraction and validation functions for EDID structures. diff --git a/trunk/ecore/src/lib/ecore_x/Ecore_X.h b/trunk/ecore/src/lib/ecore_x/Ecore_X.h index 0e21770..a9232fc 100644 --- a/trunk/ecore/src/lib/ecore_x/Ecore_X.h +++ b/trunk/ecore/src/lib/ecore_x/Ecore_X.h @@ -207,6 +207,35 @@ typedef enum _Ecore_X_Render_Subpixel_Order { ECORE_X_RENDER_SUBPIXEL_ORDER_NONE = 5 } Ecore_X_Render_Subpixel_Order; +typedef enum _Ecore_X_Randr_Edid_Display_Interface_Type { + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_UNDEFINED, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DVI, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_HDMI_A, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_HDMI_B, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_MDDI, + ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT +} Ecore_X_Randr_Edid_Display_Interface_Type; + +typedef enum _Ecore_X_Randr_Edid_Display_Colorscheme { + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_MONOCHROME_GRAYSCALE = 0x00, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB = 0x08, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_NON_RGB = 0x10, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_UNDEFINED = 0x18, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_4_4_4 = 0x444000, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_4_4 = 0x444, + ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_2_2 = 0x422 +} Ecore_X_Randr_Edid_Display_Colorscheme; + +typedef enum _Ecore_X_Randr_Edid_Aspect_Ratio { + ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3 = 0x0, + ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9 = 0x1, + ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10 = 0x2, + ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4 = 0x4, + ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9 = 0x8 +} Ecore_X_Randr_Edid_Aspect_Ratio; + +#define ECORE_X_RANDR_EDID_UNKNOWN_VALUE -1 + #define ECORE_X_SELECTION_TARGET_TARGETS "TARGETS" #define ECORE_X_SELECTION_TARGET_TEXT "TEXT" #define ECORE_X_SELECTION_TARGET_COMPOUND_TEXT "COMPOUND_TEXT" @@ -2668,6 +2697,181 @@ ecore_x_randr_output_crtc_set(Ecore_X_Window root, Ecore_X_Randr_Output output, const Ecore_X_Randr_Crtc crtc); +/* ecore_x_randr_12_edid.c */ + +/* + * @brief Validates the header from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if the header is valid. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_valid_header(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Checks whether a display's EDID has a valid checksum. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if the checksum is valid. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_info_has_valid_checksum(unsigned char *edid, long edid_length); + +/* + * @brief Get the encoded version from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded major and minor version encasuplated a single short. + */ +EAPI short ecore_x_randr_edid_version_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the encoded manufacturer from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded manufacturer identifier. + */ +EAPI const char *ecore_x_randr_edid_manufacturer_name_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the encoded name from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded manufacturer identifier. + */ +EAPI const char *ecore_x_randr_edid_display_name_get(unsigned char *edid, long edid_length); + +/* + * @brief Get the encoded ASCII from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded ASCII display identifier. + */ +EAPI const char *ecore_x_randr_edid_display_ascii_get(unsigned char *edid, long edid_length); + +/* + * @brief Get the encoded serial identifier from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded serial identifier. + */ +EAPI const char *ecore_x_randr_edid_display_serial_get(unsigned char *edid, long edid_length); + +/* + * @brief Get the encoded model number from raw EDID data. + * + * The manufacturer ID table is necessary for a useful description. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded model number. + */ +EAPI short ecore_x_randr_edid_model_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the manufacturer serial number from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The encoded serial manufacturer serial number. + */ +EAPI int ecore_x_randr_edid_manufacturer_serial_number_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the manufacturer model number from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The manufacturer's model number. + */ +EAPI short ecore_x_randr_edid_manufacturer_model_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Looks up the DPMS support from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if DPMS is supported in some way. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_available_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Looks up the DPMS Standby support from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if DPMS Standby is supported. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_standby_available_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Looks up the DPMS Suspend support from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if DPMS Suspend is supported. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_suspend_available_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Looks up the DPMS Off support from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if DPMS Off is supported. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_dpms_off_available_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the preferred aspect ratio from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The preferred aspect ratio. + */ +EAPI Ecore_X_Randr_Edid_Aspect_Ratio_Preferred ecore_x_randr_edid_display_aspect_ratio_preferred_get(unsigned char *edid, long edid_length); + +/* + * @brief Get the supported aspect ratios from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The supported aspect ratios. + */ +EAPI Ecore_X_Randr_Edid_Aspect_Ratio ecore_x_randr_edid_display_aspect_ratios_get(unsigned char *edid, long edid_length); + +/* + * @brief Get the supported colorschemes from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The supported colorschemes. + */ +EAPI Ecore_X_Randr_Edid_Display_Colorscheme ecore_x_randr_edid_display_colorscheme_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the display type from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return EINA_TRUE, if the display is a digital one. Else EINA_FALSE. + */ +EAPI Eina_Bool ecore_x_randr_edid_display_type_digital_get(unsigned char *edid, unsigned long edid_length); + +/* + * @brief Get the display interface type from raw EDID data. + * + * @param edid the edid structure + * @param edid_length length of the edid structure + * @return The interface type. + */ +EAPI Ecore_X_Randr_Edid_Display_Interface_Type ecore_x_randr_edid_display_interface_type_get(unsigned char *edid, unsigned long edid_length); + /* ecore_x_randr_13.c */ EAPI void ecore_x_randr_screen_backlight_level_set(Ecore_X_Window root, double level); diff --git a/trunk/ecore/src/lib/ecore_x/xlib/Makefile.am b/trunk/ecore/src/lib/ecore_x/xlib/Makefile.am index c75f4a5..71990ec 100644 --- a/trunk/ecore/src/lib/ecore_x/xlib/Makefile.am +++ b/trunk/ecore/src/lib/ecore_x/xlib/Makefile.am @@ -36,6 +36,7 @@ ecore_x_sync.c \ ecore_x_randr.c \ ecore_x_randr_11.c \ ecore_x_randr_12.c \ +ecore_x_randr_12_edid.c \ ecore_x_randr_13.c \ ecore_x_fixes.c \ ecore_x_damage.c \ diff --git a/trunk/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c b/trunk/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c new file mode 100644 index 0000000..85582dd --- /dev/null +++ b/trunk/ecore/src/lib/ecore_x/xlib/ecore_x_randr_12_edid.c @@ -0,0 +1,486 @@ +/* + * Copyright 2006-2009 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, and/or sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +/* Original Author: Adam Jackson <[email protected]> */ +/* Heavily modified by: Leif Middelschulte <[email protected]> */ + +#include "Ecore_X.h" + +/* TODO: + * - see other TODO's within this file. + */ + +#define ECORE_X_RANDR_EDID_VERSION_10 ((1 << 8) | 0) +#define ECORE_X_RANDR_EDID_VERSION_11 ((1 << 8) | 1) +#define ECORE_X_RANDR_EDID_VERSION_12 ((1 << 8) | 2) +#define ECORE_X_RANDR_EDID_VERSION_13 ((1 << 8) | 3) +#define ECORE_X_RANDR_EDID_VERSION_14 ((1 << 8) | 4) + +#define _ECORE_X_RANDR_EDID_OFFSET_MANUFACTURER 0x08 +#define _ECORE_X_RANDR_EDID_OFFSET_TYPE 0x14 +#define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR 0x12 +#define _ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR 0x13 +#define _ECORE_X_RANDR_EDID_OFFSET_DPMS 0x18 +#define _ECORE_X_RANDR_EDID_OFFSET_COLORSPACE 0x18 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK 0x36 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE 3 +#define _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT 5 +#define _ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO_PREFERRED 15 +#define _ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO 14 + +#define _ECORE_X_RANDR_EDID_MASK_DIGITAL 0x80 +#define _ECORE_X_RANDR_EDID_MASK_DIGITAL_INTERFACE 0x0f +#define _ECORE_X_RANDR_EDID_MASK_DIGITAL_TMDS_DFP_10 0x01 +#define _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_ANALOGOUS 0x18 +#define _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_444 0x10 +#define _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_422 0x08 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_PREFERRED 0xe0 +#define _ECORE_X_RANDR_EDID_MASK_DPMS 0xE0 +#define _ECORE_X_RANDR_EDID_MASK_DPMS_STANDBY 0x80 +#define _ECORE_X_RANDR_EDID_MASK_DPMS_SUSPEND 0x40 +#define _ECORE_X_RANDR_EDID_MASK_DPMS_OFF 0x20 +#define _ECORE_X_RANDR_EDID_MASK_INTERFACE_TYPE 0x0f +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_4_3 0x80 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_9 0x40 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_10 0x20 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_5_4 0x10 +#define _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_15_9 0x08 + +#define _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX 13 + +typedef enum _Ecore_X_Randr_Edid_Aspect_Ratio_Preferred { + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_4_3 = 0x00, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_9 = 0x01, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_10 = 0x02, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_5_4 = 0x03, + ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_15_9 = 0x04 +} Ecore_X_Randr_Edid_Aspect_Ratio_Preferred; + +/* Some convenience loops */ +#define _ECORE_X_RANDR_EDID_FOR_EACH_EXTENSION_BLOCK(edid, edid_length, extension_block_iter) \ + for (extension_block_iter = edid; extension_block_iter < (edid + edid_length); extension_block_iter += 128) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_CEA_BLOCK(edid, edid_length, cea_block_iter) \ + _ECORE_X_RANDR_EDID_FOR_EACH_EXTENSION_BLOCK(edid, edid_length, cea_block_iter) \ +if (cea_block_iter[0] == 0x02) + +/* The following macro is to be used with caution as it inherits another loop. + * Therefore using a 'break;' statement will lead to continuation in the + * inherent 'Extension block'-loop. + */ +#define _ECORE_X_RANDR_EDID_FOR_EACH_CEA_DETAILED_BLOCK(edid, edid_length, cea_block_iter, detailed_block_iter) \ + _ECORE_X_RANDR_EDID_FOR_EACH_CEA_BLOCK(edid, edid_length, cea_block_iter) \ +for (detailed_block_iter = cea_block_iter + cea_block_iter[2]; detailed_block_iter + 18 < cea_block_iter + 127; detailed_block_iter += 18) \ +if (detailed_block_iter[0]) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \ + for (block = edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK; block <= (edid + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK + (3*18)); block += 18) + +#define _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) \ + _ECORE_X_RANDR_EDID_FOR_EACH_DESCRIPTOR_BLOCK(edid, block) \ +if ((block[0] == 0) && (block[1] == 0)) + + EAPI Eina_Bool +ecore_x_randr_edid_has_valid_header(unsigned char *edid, unsigned long edid_length) +{ + Eina_Bool is_valid = EINA_FALSE; + + if (!edid) return EINA_FALSE; + + if (!memcmp(edid, "\x00\xFF\xFF\xFF\xFF\xFF\xFF\x00", 8)) + { + is_valid = EINA_TRUE; + } + + return is_valid; +} + + EAPI short +ecore_x_randr_edid_version_get(unsigned char *edid, unsigned long edid_length) +{ + short version; + version = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + + if (edid && ecore_x_randr_edid_has_valid_header(edid, edid_length)) + version = (edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MAJOR] << 8) | edid[_ECORE_X_RANDR_EDID_OFFSET_VERSION_MINOR]; + + return version; +} + + EAPI short +ecore_x_randr_edid_manufacturer_model_get(unsigned char *edid, unsigned long edid_length) +{ + short model = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + + if (edid && ecore_x_randr_edid_has_valid_header(edid, edid_length)) + model = (short)(edid[0x0A] + (edid[0x0B] << 8)); + + return model; +} + + EAPI int +ecore_x_randr_edid_manufacturer_serial_number_get(unsigned char *edid, unsigned long edid_length) +{ + int serial_number = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + + if (edid && ecore_x_randr_edid_has_valid_header(edid, edid_length)) + serial_number = (int)(edid[0x0C] + (edid[0x0D] << 8) + (edid[0x0E] << 16) + (edid[0x0F] << 24)); + + return serial_number; +} + + EAPI const char +*ecore_x_randr_edid_manufacturer_name_get(unsigned char *edid, unsigned long edid_length) +{ + unsigned char *x; + char *name = NULL; + + if (edid && ecore_x_randr_edid_has_valid_header(edid, edid_length)) + { + x = (edid + _ECORE_X_RANDR_EDID_OFFSET_MANUFACTURER); + + name = malloc(sizeof(char) * 4); + + name[0] = ((x[0] & 0x7C) >> 2) + '@'; + name[1] = ((x[0] & 0x03) << 3) + ((x[1] & 0xE0) >> 5) + '@'; + name[2] = (x[1] & 0x1F) + '@'; + name[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] = '\0'; + + /* + * if (isupper(name[0]) && isupper(name[1]) && isupper(name[2])) + * info->manufacturer_name_well_formed = EINA_TRUE; + */ + } + + return name; +} + + EAPI const char +*ecore_x_randr_edid_display_name_get(unsigned char *edid, long edid_length) +{ + unsigned char *block = NULL; + char *name = NULL; + const char *edid_name; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return NULL; + + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xFC) { + edid_name = (const char*)block + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + name = malloc(sizeof(*name) * _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + strncpy(name, edid_name, (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + return name; + } + } + return name; +} + + EAPI Ecore_X_Randr_Edid_Aspect_Ratio +ecore_x_randr_edid_display_aspect_ratio_preferred_get(unsigned char *edid, long edid_length) +{ + Ecore_X_Randr_Edid_Aspect_Ratio ret = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + Ecore_X_Randr_Edid_Aspect_Ratio_Preferred preferred_ratio; + unsigned char *block = NULL; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return ret; + + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if ((block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xFD) && (block[10] == 0x04)) + { + preferred_ratio = (Ecore_X_Randr_Edid_Aspect_Ratio_Preferred)((block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO_PREFERRED] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_PREFERRED) >> 5); + switch (preferred_ratio) + { + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_4_3: + ret = ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3; + break; + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_9: + ret = ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9; + break; + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_16_10: + ret = ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10; + break; + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_5_4: + ret = ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4; + break; + case ECORE_X_RANDR_EDID_ASPECT_RATIO_PREFERRED_15_9: + ret = ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9; + break; + default: + ret = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + } + } + return ret; + } + + return ret; +} + + EAPI Ecore_X_Randr_Edid_Aspect_Ratio +ecore_x_randr_edid_display_aspect_ratios_get(unsigned char *edid, long edid_length) +{ + Ecore_X_Randr_Edid_Aspect_Ratio ret = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + unsigned char *block = NULL; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return ret; + + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if ((block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xFD) && (block[10] == 0x04)) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_4_3) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_4_3; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_9) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_16_9; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_16_10) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_16_10; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_5_4) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_5_4; + if (block[_ECORE_X_RANDR_EDID_OFFSET_ASPECT_RATIO] & _ECORE_X_RANDR_EDID_MASK_ASPECT_RATIO_15_9) + ret |= ECORE_X_RANDR_EDID_ASPECT_RATIO_15_9; + } + } + + return ret; +} + + EAPI const char +*ecore_x_randr_edid_display_ascii_get(unsigned char *edid, long edid_length) +{ + unsigned char *block = NULL; + char *ascii = NULL; + const char *edid_ascii; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return ascii; + + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xFE) + { + edid_ascii = (const char*)block + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + /* + * TODO: Two of these in a row, in the third and fouth slots, + * seems to be specified by SPWG: http://www.spwg.org/ + */ + ascii = malloc(sizeof(*ascii) * _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + strncpy(ascii, edid_ascii, (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + return ascii; + } + } + + return ascii; +} + + EAPI const char +*ecore_x_randr_edid_display_serial_get(unsigned char *edid, long edid_length) +{ + unsigned char *block = NULL; + char *serial = NULL; + const char *edid_serial; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return serial; + + _ECORE_X_RANDR_EDID_FOR_EACH_NON_PIXEL_DESCRIPTOR_BLOCK(edid, block) + { + if (block[_ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_TYPE] == 0xFF) + { + edid_serial = (const char*)block + _ECORE_X_RANDR_EDID_OFFSET_DESCRIPTOR_BLOCK_CONTENT; + /* + * TODO: Two of these in a row, in the third and fouth slots, + * seems to be specified by SPWG: http://www.spwg.org/ + */ + serial = malloc(sizeof(*serial) * _ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX); + strncpy(serial, edid_serial, (_ECORE_X_RANDR_EDID_DISPLAY_DESCRIPTOR_BLOCK_CONTENT_LENGTH_MAX - 1)); + } + } + + return serial; +} + + EAPI Eina_Bool +ecore_x_randr_edid_info_has_valid_checksum(unsigned char *edid, long edid_length) +{ + unsigned char *cea_block_iter = NULL; + char sum; + int i; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + + /* Check the EDID block itself */ + for (i = 0, sum = 0; i < 128; i++) + sum += edid[i]; + if (sum) return EINA_FALSE; + + /* Check the cea extension blocks */ + _ECORE_X_RANDR_EDID_FOR_EACH_CEA_BLOCK(edid, edid_length, cea_block_iter) + { + for (i = 0, sum = 0; i < 128; i++) + sum += cea_block_iter[i]; + /* + * printf("Checksum: 0x%hx", x[0x7f]); + * printf(" (should be 0x%hx)\n", (char)(x[0x7f] - sum)); + */ + } + + if (sum) + return EINA_FALSE; + else + return EINA_TRUE; +} + + EAPI Eina_Bool +ecore_x_randr_edid_dpms_available_get(unsigned char *edid, unsigned long edid_length) +{ + Eina_Bool ret = EINA_FALSE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + + ret = (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS); + + return ret; +} + + EAPI Eina_Bool +ecore_x_randr_edid_dpms_standby_available_get(unsigned char *edid, unsigned long edid_length) +{ + Eina_Bool ret = EINA_FALSE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + + if (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS) + ret = (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS_STANDBY); + + return ret; +} + + EAPI Eina_Bool +ecore_x_randr_edid_dpms_suspend_available_get(unsigned char *edid, unsigned long edid_length) +{ + Eina_Bool ret = EINA_FALSE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + + if (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS) + ret = (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS_SUSPEND); + + return ret; +} + + EAPI Eina_Bool +ecore_x_randr_edid_dpms_off_available_get(unsigned char *edid, unsigned long edid_length) +{ + Eina_Bool ret = EINA_FALSE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return EINA_FALSE; + + if (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS) + ret = (edid[_ECORE_X_RANDR_EDID_OFFSET_DPMS] & _ECORE_X_RANDR_EDID_MASK_DPMS_OFF); + + return ret; +} + + EAPI Eina_Bool +ecore_x_randr_edid_display_type_digital_get(unsigned char *edid, unsigned long edid_length) +{ + Eina_Bool ret = EINA_FALSE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + if (version < ECORE_X_RANDR_EDID_VERSION_13) return ret; + + ret = (edid[_ECORE_X_RANDR_EDID_OFFSET_TYPE] & _ECORE_X_RANDR_EDID_MASK_DIGITAL); + + return ret; +} + + EAPI Ecore_X_Randr_Edid_Display_Colorscheme +ecore_x_randr_edid_display_colorscheme_get(unsigned char *edid, unsigned long edid_length) +{ + Ecore_X_Randr_Edid_Display_Colorscheme colorscheme = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + if (version < ECORE_X_RANDR_EDID_VERSION_13) return colorscheme; + + if (ecore_x_randr_edid_display_type_digital_get(edid, edid_length)) + { + colorscheme = ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_4_4_4; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_COLORSPACE] & _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_444) + colorscheme |= ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_4_4; + if (edid[_ECORE_X_RANDR_EDID_OFFSET_COLORSPACE] & _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_DIGITAL_YCRCB_422) + colorscheme |= ECORE_X_RANDR_EDID_DISPLAY_COLORSCHEME_COLOR_RGB_YCRCB_4_2_2; + } + else + { + colorscheme = edid[_ECORE_X_RANDR_EDID_OFFSET_COLORSPACE] & _ECORE_X_RANDR_EDID_MASK_COLORSCHEME_ANALOGOUS; + } + + return colorscheme; +} + + EAPI Ecore_X_Randr_Edid_Display_Interface_Type +ecore_x_randr_edid_display_interface_type_get(unsigned char *edid, unsigned long edid_length) +{ + Ecore_X_Randr_Edid_Display_Interface_Type type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + static short version; + + version = ecore_x_randr_edid_version_get(edid, edid_length); + + if (version < ECORE_X_RANDR_EDID_VERSION_13) return type; + + type = edid[_ECORE_X_RANDR_EDID_OFFSET_TYPE] & _ECORE_X_RANDR_EDID_MASK_INTERFACE_TYPE; + + if ((type < ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_UNDEFINED) || (type > ECORE_X_RANDR_EDID_DISPLAY_INTERFACE_DISPLAY_PORT)) + type = ECORE_X_RANDR_EDID_UNKNOWN_VALUE; + + return type; +} -- 1.7.1
------------------------------------------------------------------------------ Create and publish websites with WebMatrix Use the most popular FREE web apps or write code yourself; WebMatrix provides all the features you need to develop and publish your website. http://p.sf.net/sfu/ms-webmatrix-sf
_______________________________________________ enlightenment-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/enlightenment-devel
