backend-drm: let EDID parser return malloc'd strings

This will make adding libdisplay-info as another EDID parser easier,
because libdisplay-info always returns malloc'd strings.

To make things easier to extend as well, I introduce struct
drm_head_info. The libdisplay-info case will likely return more
information than this in the future.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
This commit is contained in:
Pekka Paalanen 2023-04-27 16:04:58 +03:00
parent fefdd577c8
commit dfdb1a71f8
2 changed files with 45 additions and 34 deletions

View file

@ -616,8 +616,6 @@ struct drm_head {
struct weston_head base;
struct drm_connector connector;
struct drm_edid edid;
struct backlight *backlight;
drmModeModeInfo inherited_mode; /**< Original mode on the connector */

View file

@ -34,6 +34,27 @@
#include "drm-internal.h"
#include "shared/weston-drm-fourcc.h"
#include "shared/xalloc.h"
struct drm_head_info {
char *make; /* The monitor make (PNP ID or company name). */
char *model; /* The monitor model (product name). */
char *serial_number;
/* The monitor supported EOTF modes, combination of
* enum weston_eotf_mode bits.
*/
uint32_t eotf_mask;
};
static void
drm_head_info_fini(struct drm_head_info *dhi)
{
free(dhi->make);
free(dhi->model);
free(dhi->serial_number);
*dhi = (struct drm_head_info){};
}
static const char *const aspect_ratio_as_string[] = {
[WESTON_MODE_PIC_AR_NONE] = "",
@ -302,27 +323,18 @@ edid_parse(struct drm_edid *edid, const uint8_t *data, size_t length)
*
* \param head The head whose \c drm_edid to fill in.
* \param props The DRM connector properties to get the EDID from.
* \param[out] make The monitor make (PNP ID).
* \param[out] model The monitor model (name).
* \param[out] serial_number The monitor serial number.
* \param[out] eotf_mask The monitor supported EOTF modes, combination of
* enum weston_eotf_mode bits.
* \param[out] dhi Receives information from EDID.
*
* Each of \c *make, \c *model and \c *serial_number are set only if the
* information is found in the EDID. The pointers they are set to must not
* be free()'d explicitly, instead they get implicitly freed when the
* \c drm_head is destroyed.
* \c *dhi must be drm_head_info_fini()'d by the caller.
*/
static void
find_and_parse_output_edid(struct drm_head *head,
drmModeObjectPropertiesPtr props,
const char **make,
const char **model,
const char **serial_number,
uint32_t *eotf_mask)
struct drm_head_info *dhi)
{
struct drm_device *device = head->connector.device;
drmModePropertyBlobPtr edid_blob = NULL;
struct drm_edid edid = {};
uint32_t blob_id;
int rc;
@ -337,21 +349,19 @@ find_and_parse_output_edid(struct drm_head *head,
if (!edid_blob)
return;
rc = edid_parse(&head->edid,
edid_blob->data,
edid_blob->length);
if (!rc) {
if (head->edid.pnp_id[0] != '\0')
*make = head->edid.pnp_id;
if (head->edid.monitor_name[0] != '\0')
*model = head->edid.monitor_name;
if (head->edid.serial_number[0] != '\0')
*serial_number = head->edid.serial_number;
rc = edid_parse(&edid, edid_blob->data, edid_blob->length);
if (rc == 0) {
if (edid.pnp_id[0] != '\0')
dhi->make = xstrdup(edid.pnp_id);
if (edid.monitor_name[0] != '\0')
dhi->model = xstrdup(edid.monitor_name);
if (edid.serial_number[0] != '\0')
dhi->serial_number = xstrdup(edid.serial_number);
}
drmModeFreePropertyBlob(edid_blob);
/* TODO: parse this from EDID */
*eotf_mask = WESTON_EOTF_MODE_ALL_MASK;
dhi->eotf_mask = WESTON_EOTF_MODE_ALL_MASK;
}
static void
@ -532,15 +542,16 @@ update_head_from_connector(struct drm_head *head)
struct drm_connector *connector = &head->connector;
drmModeObjectProperties *props = connector->props_drm;
drmModeConnector *conn = connector->conn;
const char *make = "unknown";
const char *model = "unknown";
const char *serial_number = "unknown";
uint32_t eotf_mask = WESTON_EOTF_MODE_SDR;
struct drm_head_info dhi = { .eotf_mask = WESTON_EOTF_MODE_SDR };
find_and_parse_output_edid(head, props, &make, &model, &serial_number, &eotf_mask);
weston_head_set_monitor_strings(&head->base, make, model, serial_number);
prune_eotf_modes_by_kms_support(head, &eotf_mask);
weston_head_set_supported_eotf_mask(&head->base, eotf_mask);
find_and_parse_output_edid(head, props, &dhi);
weston_head_set_monitor_strings(&head->base, dhi.make ?: "unknown",
dhi.model ?: "unknown",
dhi.serial_number ?: "unknown");
prune_eotf_modes_by_kms_support(head, &dhi.eotf_mask);
weston_head_set_supported_eotf_mask(&head->base, dhi.eotf_mask);
weston_head_set_non_desktop(&head->base,
check_non_desktop(connector, props));
weston_head_set_subpixel(&head->base,
@ -554,6 +565,8 @@ update_head_from_connector(struct drm_head *head)
/* Unknown connection status is assumed disconnected. */
weston_head_set_connection_status(&head->base,
conn->connection == DRM_MODE_CONNECTED);
drm_head_info_fini(&dhi);
}
/**