diff options
-rw-r--r-- | src/drmgamma.c | 131 | ||||
-rw-r--r-- | src/drmgamma.h | 69 |
2 files changed, 198 insertions, 2 deletions
diff --git a/src/drmgamma.c b/src/drmgamma.c index 0a8f72f..16a3006 100644 --- a/src/drmgamma.c +++ b/src/drmgamma.c @@ -21,6 +21,8 @@ #include <errno.h> #include <stdio.h> #include <fcntl.h> +#include <stdlib.h> +#include <string.h> @@ -56,7 +58,6 @@ size_t drm_card_count(void) if (access(buf, F_OK) < 0) return count; } - } /** @@ -70,9 +71,13 @@ int drm_card_open(size_t index, drm_card_t* restrict card) { char buf[DRM_DEV_NAME_MAX_LEN]; int old_errno; + size_t i, n; card->fd = -1; card->res = NULL; + card->connectors = NULL; + card->encoders = NULL; + card->connector_count = 0; sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, (int)index); card->fd = open(buf, O_RDWR | O_CLOEXEC); @@ -83,7 +88,30 @@ int drm_card_open(size_t index, drm_card_t* restrict card) if (card->res == NULL) goto fail; - card->crtc_count = (size_t)(card->res->count_crtcs); + card->crtc_count = (size_t)(card->res->count_crtcs); + card->connector_count = (size_t)(card->res->count_connectors); + n = card->connector_count; + + card->connectors = calloc(n, sizeof(drmModeConnector*)); + if (card->connectors == NULL) + goto fail; + card->encoders = calloc(n, sizeof(drmModeEncoder*)); + if (card->encoders == NULL) + goto fail; + + for (i = 0; i < n; i++) + { + card->connectors[i] = drmModeGetConnector(card->fd, card->res->connectors[i]); + if (card->connectors[i] == NULL) + goto fail; + + if (card->connectors[i]->encoder_id != 0) + { + card->encoders[i] = drmModeGetEncoder(card->fd, card->connectors[i]->encoder_id); + if (card->encoders[i] == NULL) + goto fail; + } + } return 0; fail: @@ -101,8 +129,107 @@ int drm_card_open(size_t index, drm_card_t* restrict card) */ void drm_card_close(drm_card_t* restrict card) { + size_t i, n = card->connector_count; + + if (card->encoders != NULL) + for (i = 0; i < n; i++) + if (card->encoders[i] != NULL) + drmModeFreeEncoder(card->encoders[i]); + free(card->encoders), card->encoders = NULL; + + if (card->connectors != NULL) + for (i = 0; i < n; i++) + if (card->connectors[i] != NULL) + drmModeFreeConnector(card->connectors[i]); + free(card->connectors), card->connectors = NULL; + if (card->res != NULL) drmModeFreeResources(card->res), card->res = NULL; if (card->fd != -1) close(card->fd), card->fd = -1; } + + +/** + * Acquire access to a CRT controller + * + * @param index The index of the CRT controller + * @param card The graphics card information + * @param crtc CRT controller information to fill in + * @return Zero on success, -1 on error + */ +int drm_crtc_open(size_t index, drm_card_t* restrict card, drm_crtc_t* restrict crtc) +{ + drmModePropertyRes* restrict prop; + drmModePropertyBlobRes* restrict blob; + size_t i; + + crtc->edid = NULL; + + crtc->id = card->res->crtcs[index]; + crtc->card = card; + + for (i = 0; i < card->connector_count; i++) + if (card->encoders[i] != NULL) + if (card->encoders[i]->crtc_id == crtc->id) + { + crtc->connector = card->connectors[i]; + crtc->encoder = card->encoders[i]; + } + + crtc->connected = crtc->connector->connection == DRM_MODE_CONNECTED; + + for (i = 0; i < crtc->connector->count_props; i++) + { + size_t j; + + prop = drmModeGetProperty(card->fd, crtc->connector->props[i]); + if (prop == NULL) + continue; + + if (strcmp(prop->name, "EDID")) + goto free_prop; + + + blob = drmModeGetPropertyBlob(card->fd, (uint32_t)(crtc->connector->prop_values[i])); + i = crtc->connector->count_props; + if ((blob == NULL) || (blob->data == NULL)) + goto free_blob; + + crtc->edid = malloc((blob->length * 2 + 1) * sizeof(char)); + if (crtc->edid == NULL) + { + drmModeFreePropertyBlob(blob); + drmModeFreeProperty(prop); + return -1; + } + for (j = 0; j < blob->length; j++) + { + unsigned char c = ((unsigned char*)(blob->data))[j]; + crtc->edid[j * 2 + 0] = "0123456789ABCDEF"[(c >> 4) & 15]; + crtc->edid[j * 2 + 1] = "0123456789ABCDEF"[(c >> 0) & 15]; + } + crtc->edid[blob->length * 2] = '\0'; + + free_blob: + if (blob != NULL) + drmModeFreePropertyBlob(blob); + + free_prop: + drmModeFreeProperty(prop); + } + + return 0; +} + + +/** + * Release access to a CRT controller + * + * @param crtc The CRT controller information to fill in + */ +void drm_crtc_close(drm_crtc_t* restrict crtc) +{ + free(crtc->edid), crtc->edid = NULL; +} + diff --git a/src/drmgamma.h b/src/drmgamma.h index 7044fd7..efc7ec2 100644 --- a/src/drmgamma.h +++ b/src/drmgamma.h @@ -44,8 +44,60 @@ typedef struct drm_card */ size_t crtc_count; + /** + * The available connectors + */ + drmModeConnector** restrict connectors; + + /** + * The available encoders + */ + drmModeEncoder** restrict encoders; + + /** + * The number of connectors and encoders + */ + size_t connector_count; + } drm_card_t; +/** + * CRT controller information + */ +typedef struct drm_crtc +{ + /** + * CRT controller identifier + */ + uint32_t id; + + /** + * The graphics card + */ + drm_card_t* restrict card; + + /** + * The CRT controller's connector + */ + drmModeConnector* restrict connector; + + /** + * The CRT controller's encoder + */ + drmModeEncoder* restrict encoder; + + /** + * Whether the connector is connected + */ + int connected; + + /** + * The CRT's EDID, hexadecimally encoded + */ + char* edid; + +} drm_crtc_t; + /** * Figure out how many graphics cards there are on the system @@ -70,6 +122,23 @@ int drm_card_open(size_t index, drm_card_t* restrict card); */ void drm_card_close(drm_card_t* restrict card); +/** + * Acquire access to a CRT controller + * + * @param index The index of the CRT controller + * @param card The graphics card information + * @param crtc CRT controller information to fill in + * @return Zero on success, -1 on error + */ +int drm_crtc_open(size_t index, drm_card_t* restrict card, drm_crtc_t* restrict crtc); + +/** + * Release access to a CRT controller + * + * @param crtc The CRT controller information to fill in + */ +void drm_crtc_close(drm_crtc_t* restrict crtc); + #endif |