aboutsummaryrefslogtreecommitdiffstats
path: root/libgamma_unhex_edid.c
blob: 37c9681cee6b200adc51bd3589daf8498eae54e4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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;
}