diff options
Diffstat (limited to 'backend')
-rwxr-xr-x | backend/drm/gen_pnpids.sh | 7 | ||||
-rw-r--r-- | backend/drm/meson.build | 10 | ||||
-rw-r--r-- | backend/drm/util.c | 67 |
3 files changed, 28 insertions, 56 deletions
diff --git a/backend/drm/gen_pnpids.sh b/backend/drm/gen_pnpids.sh index 80e5542d..5a9547ae 100755 --- a/backend/drm/gen_pnpids.sh +++ b/backend/drm/gen_pnpids.sh @@ -13,12 +13,11 @@ gen_pnps() } cat << EOF -#include <stdint.h> -#include <stddef.h> #include "backend/drm/util.h" + #define PNP_ID(a, b, c) ((a & 0x1f) << 10) | ((b & 0x1f) << 5) | (c & 0x1f) -const char *get_pnp_manufacturer(uint16_t code) { - switch (code) { +const char *get_pnp_manufacturer(const char code[static 3]) { + switch (PNP_ID(code[0], code[1], code[2])) { $(gen_pnps) } return NULL; diff --git a/backend/drm/meson.build b/backend/drm/meson.build index 3fb011c1..824134fe 100644 --- a/backend/drm/meson.build +++ b/backend/drm/meson.build @@ -5,6 +5,13 @@ hwdata = dependency( not_found_message: 'Required for the DRM backend.', ) +libdisplay_info = dependency( + 'libdisplay-info', + required: 'drm' in backends, + fallback: 'libdisplay-info', + not_found_message: 'Required for the DRM backend.', +) + libliftoff = dependency( 'libliftoff', version: '>=0.4.0', @@ -12,7 +19,7 @@ libliftoff = dependency( required: false, ) -if not (hwdata.found() and features['session']) +if not (hwdata.found() and libdisplay_info.found() and features['session']) subdir_done() endif @@ -45,4 +52,5 @@ endif features += { 'drm-backend': true } internal_features += { 'libliftoff': libliftoff.found() } +wlr_deps += libdisplay_info wlr_deps += libliftoff diff --git a/backend/drm/util.c b/backend/drm/util.c index adb9306e..d4ece1f9 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -3,6 +3,8 @@ #include <drm_fourcc.h> #include <drm_mode.h> #include <drm.h> +#include <libdisplay-info/edid.h> +#include <libdisplay-info/info.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -48,9 +50,6 @@ enum wlr_output_mode_aspect_ratio get_picture_aspect_ratio(const drmModeModeInfo } } -/* See https://en.wikipedia.org/wiki/Extended_Display_Identification_Data for layout of EDID data. - * We don't parse the EDID properly. We just expect to receive valid data. - */ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) { struct wlr_output *output = &conn->output; @@ -61,62 +60,28 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data) output->model = NULL; output->serial = NULL; - if (!data || len < 128) { + struct di_info *info = di_info_parse_edid(data, len); + if (info == NULL) { + wlr_log(WLR_ERROR, "Failed to parse EDID"); return; } - uint16_t id = (data[8] << 8) | data[9]; - const char *manu = get_pnp_manufacturer(id); - char pnp_id[4]; + const struct di_edid *edid = di_info_get_edid(info); + const struct di_edid_vendor_product *vendor_product = di_edid_get_vendor_product(edid); + char pnp_id[] = { + vendor_product->manufacturer[0], + vendor_product->manufacturer[1], + vendor_product->manufacturer[2], + '\0', + }; + const char *manu = get_pnp_manufacturer(vendor_product->manufacturer); if (!manu) { - // The ASCII 3-letter manufacturer PnP ID is encoded in 5-bit codes - pnp_id[0] = ((id >> 10) & 0x1F) + '@'; - pnp_id[1] = ((id >> 5) & 0x1F) + '@'; - pnp_id[2] = ((id >> 0) & 0x1F) + '@'; - pnp_id[3] = '\0'; manu = pnp_id; } output->make = strdup(manu); - uint16_t model = data[10] | (data[11] << 8); - char model_str[32]; - snprintf(model_str, sizeof(model_str), "0x%04" PRIX16, model); - - uint32_t serial = data[12] | (data[13] << 8) | (data[14] << 8) | (data[15] << 8); - char serial_str[32]; - if (serial != 0) { - snprintf(serial_str, sizeof(serial_str), "0x%08" PRIX32, serial); - } else { - serial_str[0] = '\0'; - } - - for (size_t i = 72; i <= 108; i += 18) { - uint16_t flag = (data[i] << 8) | data[i + 1]; - if (flag == 0 && data[i + 3] == 0xFC) { - snprintf(model_str, sizeof(model_str), "%.13s", &data[i + 5]); - - // Monitor names are terminated by newline if they're too short - char *nl = strchr(model_str, '\n'); - if (nl) { - *nl = '\0'; - } - } else if (flag == 0 && data[i + 3] == 0xFF) { - snprintf(serial_str, sizeof(serial_str), "%.13s", &data[i + 5]); - - // Monitor serial numbers are terminated by newline if they're too - // short - char* nl = strchr(serial_str, '\n'); - - if (nl) { - *nl = '\0'; - } - } - } - - output->model = strdup(model_str); - if (serial_str[0] != '\0') { - output->serial = strdup(serial_str); - } + output->model = di_info_get_model(info); + output->serial = di_info_get_serial(info); } const char *drm_connector_status_str(drmModeConnection status) { |