aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2023-02-02 12:14:11 +0100
committerAlexander Orzechowski <alex@ozal.ski>2023-02-28 14:44:02 +0000
commit35da9970019be6580394d5d6234b8ede0b2f0d5a (patch)
tree4bc97c7befa137c1722242125ece4aa132811c52
parent40117e1e0df79aaffd307a238fb973f0bf1edf78 (diff)
backend/drm: use libdisplay-info to parse EDID
-rw-r--r--.builds/alpine.yml1
-rw-r--r--.builds/archlinux.yml1
-rw-r--r--.builds/freebsd.yml1
-rw-r--r--README.md2
-rwxr-xr-xbackend/drm/gen_pnpids.sh7
-rw-r--r--backend/drm/meson.build10
-rw-r--r--backend/drm/util.c67
-rw-r--r--include/backend/drm/util.h2
8 files changed, 34 insertions, 57 deletions
diff --git a/.builds/alpine.yml b/.builds/alpine.yml
index a2c90953..7b8f7f3f 100644
--- a/.builds/alpine.yml
+++ b/.builds/alpine.yml
@@ -3,6 +3,7 @@ packages:
- eudev-dev
- ffmpeg-dev
- glslang
+ - libdisplay-info-dev
- libinput-dev
- libliftoff-dev
- libxkbcommon-dev
diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml
index f311bf74..26d4a163 100644
--- a/.builds/archlinux.yml
+++ b/.builds/archlinux.yml
@@ -3,6 +3,7 @@ packages:
- clang
- ffmpeg
- libinput
+ - libdisplay-info
- libliftoff
- libxkbcommon
- mesa
diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml
index 743dfb49..75a326f8 100644
--- a/.builds/freebsd.yml
+++ b/.builds/freebsd.yml
@@ -24,6 +24,7 @@ packages:
- x11/xcb-util-renderutil
- x11/xcb-util-wm
- x11-servers/xwayland-devel
+ - sysutils/libdisplay-info
- sysutils/seatd
- gmake
- hwdata
diff --git a/README.md b/README.md
index da2cbc92..603ee20c 100644
--- a/README.md
+++ b/README.md
@@ -52,6 +52,7 @@ Install dependencies:
* pixman
* [libseat] (optional, for the session)
* [hwdata] (optional, for the DRM backend)
+* [libdisplay-info] (optional, for the DRM backend)
* [libliftoff] (optional, for the DRM backend)
If you choose to enable X11 support:
@@ -81,5 +82,6 @@ See [CONTRIBUTING.md].
[wrapper libraries]: https://gitlab.freedesktop.org/wlroots/wlroots/-/wikis/Projects-which-use-wlroots#wrapper-libraries
[libseat]: https://git.sr.ht/~kennylevinsen/seatd
[hwdata]: https://github.com/vcrhonek/hwdata
+[libdisplay-info]: https://gitlab.freedesktop.org/emersion/libdisplay-info
[libliftoff]: https://gitlab.freedesktop.org/emersion/libliftoff
[CONTRIBUTING.md]: https://gitlab.freedesktop.org/wlroots/wlroots/-/blob/master/CONTRIBUTING.md
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) {
diff --git a/include/backend/drm/util.h b/include/backend/drm/util.h
index ba48fe6a..12eec35c 100644
--- a/include/backend/drm/util.h
+++ b/include/backend/drm/util.h
@@ -11,7 +11,7 @@ struct wlr_drm_connector;
int32_t calculate_refresh_rate(const drmModeModeInfo *mode);
enum wlr_output_mode_aspect_ratio get_picture_aspect_ratio(const drmModeModeInfo *mode);
// Returns manufacturer based on pnp id
-const char *get_pnp_manufacturer(uint16_t code);
+const char *get_pnp_manufacturer(const char code[static 3]);
// Populates the make/model/phys_{width,height} of output from the edid data
void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data);
const char *drm_connector_status_str(drmModeConnection status);