static void printProperty(int fd, drmModePropertyRes* prop, uint64_t value) { fprintf(stdout, " Property: %i\n", prop->prop_id); fprintf(stdout, " Name: %s\n", prop->name); fprintf(stdout, " Flags: 0x%08x\n", prop->flags); fprintf(stdout, " Values: %d: %s\n", prop->count_values, getList64(prop->values, prop->count_values)); if (prop->flags & DRM_MODE_PROP_BLOB) { drmModePropertyBlobRes* blob; fprintf(stdout, " BLOB: "); blob = drmModeGetPropertyBlob(fd, value); if (!blob) { fprintf(stdout, "error getting blob %lu\n", value); } else { fprintf(stdout, "%d bytes, %08X...\n", blob->length, *(uint32_t *)blob->data); drmModeFreePropertyBlob(blob); } } else { int i; fprintf(stdout, " Enum: %lu\n", value); for (i = 0; i < prop->count_enums; i++) { fprintf(stdout, " %1s %4lld = %s\n", prop->enums[i].value == value ? "*" : "", prop->enums[i].value, prop->enums[i].name); } } fprintf(stdout, "\n"); }
static GBytes * read_output_edid (MetaMonitorManagerKms *manager_kms, MetaOutput *output) { MetaOutputKms *output_kms = output->driver_private; drmModePropertyBlobPtr edid_blob = NULL; if (output_kms->edid_blob_id == 0) return NULL; edid_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->edid_blob_id); if (!edid_blob) { meta_warning ("Failed to read EDID of output %s: %s\n", output->name, strerror(errno)); return NULL; } if (edid_blob->length > 0) return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length, (GDestroyNotify)drmModeFreePropertyBlob, edid_blob); else { drmModeFreePropertyBlob (edid_blob); return NULL; } }
static void output_destroy(xf86OutputPtr output) { struct output_private *priv = output->driver_private; if (priv->edid_blob) drmModeFreePropertyBlob(priv->edid_blob); drmModeFreeConnector(priv->drm_connector); free(priv); output->driver_private = NULL; }
static uint32_t blob_duplicate(int fd, uint32_t id_orig) { drmModePropertyBlobPtr orig = drmModeGetPropertyBlob(fd, id_orig); uint32_t id_new; igt_assert(orig); do_or_die(drmModeCreatePropertyBlob(fd, orig->data, orig->length, &id_new)); drmModeFreePropertyBlob(orig); return id_new; }
static gboolean output_get_tile_info (MetaMonitorManagerKms *manager_kms, MetaOutput *output) { MetaOutputKms *output_kms = output->driver_private; drmModePropertyBlobPtr tile_blob = NULL; int ret; if (output_kms->tile_blob_id == 0) return FALSE; tile_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->tile_blob_id); if (!tile_blob) { meta_warning ("Failed to read TILE of output %s: %s\n", output->name, strerror(errno)); return FALSE; } if (tile_blob->length > 0) { ret = sscanf ((char *)tile_blob->data, "%d:%d:%d:%d:%d:%d:%d:%d", &output->tile_info.group_id, &output->tile_info.flags, &output->tile_info.max_h_tiles, &output->tile_info.max_v_tiles, &output->tile_info.loc_h_tile, &output->tile_info.loc_v_tile, &output->tile_info.tile_w, &output->tile_info.tile_h); if (ret != 8) return FALSE; return TRUE; } else { drmModeFreePropertyBlob (tile_blob); return FALSE; } }
const std::string Property::to_str(uint64_t val) const { drmModePropertyPtr p = m_priv->drm_prop; string ret; if (p->flags & DRM_MODE_PROP_ENUM) { for (int i = 0; i < p->count_enums; i++) { if (p->enums[i].value == val) { ret += string("\"") + p->enums[i].name + "\""; break; } } ret += " (enum: " + to_string(val) + ")"; } else if (p->flags & DRM_MODE_PROP_RANGE) { ret += to_string(val); if (p->count_values == 2) ret += " [" + to_string(p->values[0]) + "-" + to_string(p->values[1]) + "]"; else ret += " <broken range>"; } else if (p->flags & DRM_MODE_PROP_BLOB) { ret += "Blob id: " + to_string(val); auto blob = drmModeGetPropertyBlob(card().fd(), (uint32_t) val); if (blob) { ret += " length: " + to_string(blob->length); drmModeFreePropertyBlob(blob); } } else { ret += to_string(val); } if (p->flags & DRM_MODE_PROP_PENDING) ret += " (pendig)"; if (p->flags & DRM_MODE_PROP_IMMUTABLE) ret += " (immutable)"; return ret; }
static void drmmode_output_destroy(xf86OutputPtr output) { drmmode_output_private_ptr drmmode_output = output->driver_private; int i; if (drmmode_output->edid_blob) drmModeFreePropertyBlob(drmmode_output->edid_blob); for (i = 0; i < drmmode_output->num_props; i++) { drmModeFreeProperty(drmmode_output->props[i].mode_prop); free(drmmode_output->props[i].atoms); } free(drmmode_output->props); drmModeFreeConnector(drmmode_output->mode_output); if (drmmode_output->private_data) { free(drmmode_output->private_data); drmmode_output->private_data = NULL; } if (drmmode_output->backlight_iface) drmmode_backlight_set(output, drmmode_output->backlight_active_level); free(drmmode_output); output->driver_private = NULL; }
/** * Get the extended display identification data for the monitor connected to a connector * * @param connection The identifier for the connection to the card * @param connector_index The index of the connector * @param edid Storage location for the EDID, it should be 128 bytes, * or 256 bytes if you are counting on the depricated EDID 2.0, * If hexadecimal, twice that + zero termiation. * @param size The size allocated to `edid` excluding your zero termination * @param hexadecimal Whether to convert to hexadecimal representation, this is preferable * @return The length of the found value, 0 if none, as if hex is false */ long blueshift_drm_get_edid(int connection, int connector_index, char* edid, long size, int hexadecimal) { card_connection* card = card_connections + connection; drmModeConnector* connector = *(card->connectors + connector_index); int fd = card->fd; long rc = 0; int prop_n = connector->count_props; int prop_i; for (prop_i = 0; prop_i < prop_n; prop_i++) { drmModePropertyRes* prop = drmModeGetProperty(fd, connector->props[prop_i]); if (!strcmp("EDID", prop->name)) { drmModePropertyBlobRes* blob = drmModeGetPropertyBlob(fd, (uint32_t)(connector->prop_values[prop_i])); if (hexadecimal) { uint32_t n = (uint32_t)size / 2; uint32_t i; rc += blob->length; if (n > blob->length) n = blob->length; for (i = 0; i < n ; i++) { *(edid + i * 2 + 0) = "0123456789abcdef"[(*((char*)(blob->data) + i) >> 4) & 15]; *(edid + i * 2 + 1) = "0123456789abcdef"[(*((char*)(blob->data) + i) >> 0) & 15]; } } else { uint32_t len = blob->length < size ? blob->length : (uint32_t)size; memcpy(edid, blob->data, (size_t)len * sizeof(char)); } drmModeFreePropertyBlob(blob); prop_i = prop_n; /* stop the for-loop */ }
/* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */ static void dump_blob(uint32_t blob_id) { uint32_t i; unsigned char *blob_data; drmModePropertyBlobPtr blob; blob = drmModeGetPropertyBlob(fd, blob_id); if (!blob) { printf("\n"); return; } blob_data = blob->data; for (i = 0; i < blob->length; i++) { if (i % 16 == 0) printf("\n\t\t\t"); printf("%.2hhx", blob_data[i]); } printf("\n"); drmModeFreePropertyBlob(blob); }
static DisplayModePtr output_get_modes(xf86OutputPtr output) { struct output_private *priv = output->driver_private; drmModeConnectorPtr drm_connector = priv->drm_connector; drmModeModeInfoPtr drm_mode = NULL; drmModePropertyPtr props = NULL; xf86MonPtr ddc_mon = NULL; DisplayModePtr modes = NULL, mode = NULL; int i; for (i = 0; i < drm_connector->count_props; i++) { props = drmModeGetProperty(priv->fd, drm_connector->props[i]); if (!props) continue; if (!(props->flags & DRM_MODE_PROP_BLOB)) goto out_free; if (!strcmp(props->name, "EDID")) { if (priv->edid_blob) drmModeFreePropertyBlob(priv->edid_blob); priv->edid_blob = drmModeGetPropertyBlob(priv->fd, drm_connector->prop_values[i]); } out_free: drmModeFreeProperty(props); } if (priv->edid_blob) { ddc_mon = xf86InterpretEDID(output->scrn->scrnIndex, priv->edid_blob->data); if (ddc_mon && priv->edid_blob->length > 128) ddc_mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA; } xf86OutputSetEDID(output, ddc_mon); for (i = 0; i < drm_connector->count_modes; i++) { drm_mode = &drm_connector->modes[i]; if (drm_mode) { mode = calloc(1, sizeof(DisplayModeRec)); if (!mode) continue; mode->Clock = drm_mode->clock; mode->HDisplay = drm_mode->hdisplay; mode->HSyncStart = drm_mode->hsync_start; mode->HSyncEnd = drm_mode->hsync_end; mode->HTotal = drm_mode->htotal; mode->VDisplay = drm_mode->vdisplay; mode->VSyncStart = drm_mode->vsync_start; mode->VSyncEnd = drm_mode->vsync_end; mode->VTotal = drm_mode->vtotal; mode->Flags = drm_mode->flags; mode->HSkew = drm_mode->hskew; mode->VScan = drm_mode->vscan; mode->VRefresh = xf86ModeVRefresh(mode); mode->Private = (void *)drm_mode; mode->type = 0; if (drm_mode->type & DRM_MODE_TYPE_PREFERRED) mode->type |= M_T_PREFERRED; if (drm_mode->type & DRM_MODE_TYPE_DRIVER) mode->type |= M_T_DRIVER; xf86SetModeDefaultName(mode); modes = xf86ModesAdd(modes, mode); xf86PrintModeline(0, mode); } } return modes; }
static DisplayModePtr drmmode_output_get_modes(xf86OutputPtr output) { drmmode_output_private_ptr drmmode_output = output->driver_private; drmModeConnectorPtr koutput = drmmode_output->mode_output; drmmode_ptr drmmode = drmmode_output->drmmode; int i; DisplayModePtr Modes = NULL, Mode; drmModePropertyPtr props; struct fixed_panel_lvds *p_lvds; drmModeModeInfo *mode_ptr; /* look for an EDID property */ for (i = 0; i < koutput->count_props; i++) { props = drmModeGetProperty(drmmode->fd, koutput->props[i]); if (!props) continue; if (!(props->flags & DRM_MODE_PROP_BLOB)) { drmModeFreeProperty(props); continue; } if (!strcmp(props->name, "EDID")) { drmModeFreePropertyBlob(drmmode_output->edid_blob); drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); } drmModeFreeProperty(props); } if (drmmode_output->edid_blob) xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data)); else xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL)); /* modes should already be available */ for (i = 0; i < koutput->count_modes; i++) { Mode = xnfalloc(sizeof(DisplayModeRec)); drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); Modes = xf86ModesAdd(Modes, Mode); } p_lvds = drmmode_output->private_data; /* * If the connector type is LVDS, we will traverse the kernel mode to * get the panel limit. * If it is incorrect, please fix me. */ if ((koutput->connector_type == DRM_MODE_CONNECTOR_LVDS) && p_lvds) { p_lvds->hdisplay = 0; p_lvds->vdisplay = 0; for (i = 0; i < koutput->count_modes; i++) { mode_ptr = &koutput->modes[i]; if ((mode_ptr->hdisplay >= p_lvds->hdisplay) && (mode_ptr->vdisplay >= p_lvds->vdisplay)) { p_lvds->hdisplay = mode_ptr->hdisplay; p_lvds->vdisplay = mode_ptr->vdisplay; } } if (!p_lvds->hdisplay || !p_lvds->vdisplay) xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, "Incorrect KMS mode.\n"); drmmode_output_lvds_edid(output, p_lvds); } return Modes; }