mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-03-11 05:34:26 -04:00
backend/drm: use libdisplay-info to parse EDID
This commit is contained in:
parent
40117e1e0d
commit
35da997001
8 changed files with 34 additions and 57 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue