aboutsummaryrefslogtreecommitdiffstats
path: root/libgamma_unhex_edid.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgamma_unhex_edid.c')
-rw-r--r--libgamma_unhex_edid.c55
1 files changed, 55 insertions, 0 deletions
diff --git a/libgamma_unhex_edid.c b/libgamma_unhex_edid.c
new file mode 100644
index 0000000..37c9681
--- /dev/null
+++ b/libgamma_unhex_edid.c
@@ -0,0 +1,55 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+/**
+ * Convert an hexadecimal representation of an EDID to a raw representation
+ *
+ * @param edid The EDID in hexadecimal representation
+ * @return The EDID in raw representation, it will be half the length
+ * of `edid` (the input value); `NULL` on allocation error or
+ * if the EDID is malformated, `errno` will be set accordingly
+ */
+unsigned char *
+libgamma_unhex_edid(const char *restrict edid)
+{
+ unsigned char *restrict out;
+ size_t i, n = strlen(edid);
+ char a, b;
+
+ /* Check that the length of the strings is even,
+ * otherwise it cannot represent bytes */
+ if (n & 1) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Allocate memory area for output octet array */
+ n /= 2 * sizeof(unsigned char);
+ out = malloc(n);
+ if (!out)
+ return NULL;
+
+ /* Convert to raw octet array */
+ for (i = 0; i < n; i++) {
+ /* Get the next character pair that, it represents an octet. */
+ a = edid[i * 2 + 0];
+ b = edid[i * 2 + 1];
+
+ /* Verify that the input is in hexadecimal */
+ if (!isxdigit(a) || !isxdigit(b)) {
+ free(out);
+ errno = EINVAL;
+ return NULL;
+ }
+
+ /* Convert each chararacter to raw format */
+ a = (char)((a & 15) + (a > '9' ? 9 : 0));
+ b = (char)((b & 15) + (b > '9' ? 9 : 0));
+
+ /* Combine the two characters into one octet */
+ out[i] = (unsigned char)((a << 4) | b);
+ }
+
+ return out;
+}