2022-08-31 12:16:36 +02:00
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "bits.h"
|
|
|
|
#include "displayid.h"
|
|
|
|
|
2022-09-02 08:47:38 +02:00
|
|
|
/**
|
|
|
|
* The size of the mandatory fields in a DisplayID section.
|
|
|
|
*/
|
|
|
|
#define DISPLAYID_MIN_SIZE 5
|
|
|
|
/**
|
|
|
|
* The maximum size of a DisplayID section.
|
|
|
|
*/
|
|
|
|
#define DISPLAYID_MAX_SIZE 256
|
|
|
|
|
2022-09-02 09:35:50 +02:00
|
|
|
static void
|
|
|
|
add_failure(struct di_displayid *displayid, const char fmt[], ...)
|
|
|
|
{
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
_di_logger_va_add_failure(displayid->logger, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
}
|
|
|
|
|
2022-09-02 09:15:53 +02:00
|
|
|
static bool
|
|
|
|
validate_checksum(const uint8_t *data, size_t size)
|
|
|
|
{
|
|
|
|
uint8_t sum = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < size; i++) {
|
|
|
|
sum += data[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
return sum == 0;
|
|
|
|
}
|
|
|
|
|
2022-08-31 12:16:36 +02:00
|
|
|
bool
|
|
|
|
_di_displayid_parse(struct di_displayid *displayid, const uint8_t *data,
|
|
|
|
size_t size, struct di_logger *logger)
|
|
|
|
{
|
2022-09-02 08:47:38 +02:00
|
|
|
size_t section_size;
|
2022-09-02 09:03:34 +02:00
|
|
|
uint8_t product_type;
|
2022-09-02 08:47:38 +02:00
|
|
|
|
2022-08-31 12:16:36 +02:00
|
|
|
if (size < 5) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-09-02 09:35:50 +02:00
|
|
|
displayid->logger = logger;
|
|
|
|
|
2022-08-31 12:16:36 +02:00
|
|
|
displayid->version = get_bit_range(data[0x00], 7, 4);
|
|
|
|
displayid->revision = get_bit_range(data[0x00], 3, 0);
|
|
|
|
if (displayid->version == 0 || displayid->version > 1) {
|
|
|
|
errno = ENOTSUP;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-09-02 08:47:38 +02:00
|
|
|
section_size = (size_t) data[0x01] + DISPLAYID_MIN_SIZE;
|
|
|
|
if (section_size > DISPLAYID_MAX_SIZE || section_size > size) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-09-02 09:15:53 +02:00
|
|
|
if (!validate_checksum(data, section_size)) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-09-02 09:03:34 +02:00
|
|
|
product_type = data[0x02];
|
|
|
|
switch (product_type) {
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_EXTENSION:
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_TEST:
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_DISPLAY_PANEL:
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_STANDALONE_DISPLAY:
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_TV_RECEIVER:
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_REPEATER:
|
|
|
|
case DI_DISPLAYID_PRODUCT_TYPE_DIRECT_DRIVE:
|
|
|
|
displayid->product_type = product_type;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
errno = EINVAL;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-09-02 09:35:50 +02:00
|
|
|
displayid->logger = NULL;
|
2022-08-31 12:16:36 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
di_displayid_get_version(const struct di_displayid *displayid)
|
|
|
|
{
|
|
|
|
return displayid->version;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
di_displayid_get_revision(const struct di_displayid *displayid)
|
|
|
|
{
|
|
|
|
return displayid->revision;
|
|
|
|
}
|
2022-09-02 09:03:34 +02:00
|
|
|
|
|
|
|
enum di_displayid_product_type
|
|
|
|
di_displayid_get_product_type(const struct di_displayid *displayid)
|
|
|
|
{
|
|
|
|
return displayid->product_type;
|
|
|
|
}
|