libdrm全解析二十六 —— 源码全解析(23)

接前一篇文章:libdrm全解析二十五 —— 源码全解析(22)

本文参考以下博文:

DRM 驱动程序开发(VKMS)

特此致谢!

前一篇文章讲解完了drmModeGetResources函数,本篇文章继续讲解DRM一般流程的下一步。为了便于理解,再次贴出一般流程示例:

int main(int argc, char **argv)
{/* open the drm device */open("/dev/dri/card0");/* get crtc/encoder/connector id */drmModeGetResources(...);/* get connector for display mode */drmModeGetConnector(...);/* create a dumb-buffer */drmIoctl(DRM_IOCTL_MODE_CREATE_DUMB);/* bind the dumb-buffer to an FB object */drmModeAddFB(...);/* map the dumb buffer for userspace drawing */drmIoctl(DRM_IOCTL_MODE_MAP_DUMB);mmap(...);/* start display */drmModeSetCrtc(crtc_id, fb_id, connector_id, mode);
}

下一步是drmModeGetConnector()。

67. DRM_IOCTL_MODE_GETCONNECTOR

第67个宏是DRM_IOCTL_MODE_GETCONNECTOR,相应代码如下:

#define DRM_IOCTL_MODE_GETCONNECTOR	DRM_IOWR(0xA7, struct drm_mode_get_connector)

结合之前文章中的_IOWR(type,nr,size)的最终定义,得到如下代码:

#define DRM_IOCTL_MODE_GETCONNECTOR        ( ((3)  << 30) | (('d') << 8) | ((0xA7)   << 0) | ((sizeof(struct drm_mode_get_connector)) << 16) )


struct drm_mode_get_connector在同文件(include/drm/drm.h)中定义,代码如下:

/*** struct drm_mode_get_connector - Get connector metadata.** User-space can perform a GETCONNECTOR ioctl to retrieve information about a* connector. User-space is expected to retrieve encoders, modes and properties* by performing this ioctl at least twice: the first time to retrieve the* number of elements, the second time to retrieve the elements themselves.** To retrieve the number of elements, set @count_props and @count_encoders to* zero, set @count_modes to 1, and set @modes_ptr to a temporary struct* drm_mode_modeinfo element.** To retrieve the elements, allocate arrays for @encoders_ptr, @modes_ptr,* @props_ptr and @prop_values_ptr, then set @count_modes, @count_props and* @count_encoders to their capacity.** Performing the ioctl only twice may be racy: the number of elements may have* changed with a hotplug event in-between the two ioctls. User-space is* expected to retry the last ioctl until the number of elements stabilizes.* The kernel won't fill any array which doesn't have the expected length.** **Force-probing a connector**** If the @count_modes field is set to zero and the DRM client is the current* DRM master, the kernel will perform a forced probe on the connector to* refresh the connector status, modes and EDID. A forced-probe can be slow,* might cause flickering and the ioctl will block.** User-space needs to force-probe connectors to ensure their metadata is* up-to-date at startup and after receiving a hot-plug event. User-space* may perform a forced-probe when the user explicitly requests it. User-space* shouldn't perform a forced-probe in other situations.*/
struct drm_mode_get_connector {/** @encoders_ptr: Pointer to ``__u32`` array of object IDs. */__u64 encoders_ptr;/** @modes_ptr: Pointer to struct drm_mode_modeinfo array. */__u64 modes_ptr;/** @props_ptr: Pointer to ``__u32`` array of property IDs. */__u64 props_ptr;/** @prop_values_ptr: Pointer to ``__u64`` array of property values. */__u64 prop_values_ptr;/** @count_modes: Number of modes. */__u32 count_modes;/** @count_props: Number of properties. */__u32 count_props;/** @count_encoders: Number of encoders. */__u32 count_encoders;/** @encoder_id: Object ID of the current encoder. */__u32 encoder_id;/** @connector_id: Object ID of the connector. */__u32 connector_id;/*** @connector_type: Type of the connector.** See DRM_MODE_CONNECTOR_* defines.*/__u32 connector_type;/*** @connector_type_id: Type-specific connector number.** This is not an object ID. This is a per-type connector number. Each* (type, type_id) combination is unique across all connectors of a DRM* device.*/__u32 connector_type_id;/*** @connection: Status of the connector.** See enum drm_connector_status.*/__u32 connection;/** @mm_width: Width of the connected sink in millimeters. */__u32 mm_width;/** @mm_height: Height of the connected sink in millimeters. */__u32 mm_height;/*** @subpixel: Subpixel order of the connected sink.** See enum subpixel_order.*/__u32 subpixel;/** @pad: Padding, must be zero. */__u32 pad;
};

drm_mode_get_connector结构中各成员的意义代码注释描述得很清楚了,在此无需赘述。

DRM_IOCTL_MODE_GETCONNECTOR对应的Userspace API为:_drmModeGetConnector()。该函数在xf86drmMode.c中,代码如下:

/** Connector manipulation*/
static drmModeConnectorPtr
_drmModeGetConnector(int fd, uint32_t connector_id, int probe)
{struct drm_mode_get_connector conn, counts;drmModeConnectorPtr r = NULL;struct drm_mode_modeinfo stack_mode;memclear(conn);conn.connector_id = connector_id;if (!probe) {conn.count_modes = 1;conn.modes_ptr = VOID2U64(&stack_mode);}if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))return 0;retry:counts = conn;if (conn.count_props) {conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));if (!conn.props_ptr)goto err_allocs;conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));if (!conn.prop_values_ptr)goto err_allocs;}if (conn.count_modes) {conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));if (!conn.modes_ptr)goto err_allocs;} else {conn.count_modes = 1;conn.modes_ptr = VOID2U64(&stack_mode);}if (conn.count_encoders) {conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));if (!conn.encoders_ptr)goto err_allocs;}if (drmIoctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))goto err_allocs;/* The number of available connectors and etc may have changed with a* hotplug event in between the ioctls, in which case the field is* silently ignored by the kernel.*/if (counts.count_props < conn.count_props ||counts.count_modes < conn.count_modes ||counts.count_encoders < conn.count_encoders) {drmFree(U642VOID(conn.props_ptr));drmFree(U642VOID(conn.prop_values_ptr));if (U642VOID(conn.modes_ptr) != &stack_mode)drmFree(U642VOID(conn.modes_ptr));drmFree(U642VOID(conn.encoders_ptr));goto retry;}if(!(r = drmMalloc(sizeof(*r)))) {goto err_allocs;}r->connector_id = conn.connector_id;r->encoder_id = conn.encoder_id;r->connection   = conn.connection;r->mmWidth      = conn.mm_width;r->mmHeight     = conn.mm_height;/* convert subpixel from kernel to userspace */r->subpixel     = conn.subpixel + 1;r->count_modes  = conn.count_modes;r->count_props  = conn.count_props;r->props        = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));r->prop_values  = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));r->modes        = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));r->count_encoders = conn.count_encoders;r->encoders     = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));r->connector_type  = conn.connector_type;r->connector_type_id = conn.connector_type_id;if ((r->count_props && !r->props) ||(r->count_props && !r->prop_values) ||(r->count_modes && !r->modes) ||(r->count_encoders && !r->encoders)) {drmFree(r->props);drmFree(r->prop_values);drmFree(r->modes);drmFree(r->encoders);drmFree(r);r = 0;}err_allocs:drmFree(U642VOID(conn.prop_values_ptr));drmFree(U642VOID(conn.props_ptr));if (U642VOID(conn.modes_ptr) != &stack_mode)drmFree(U642VOID(conn.modes_ptr));drmFree(U642VOID(conn.encoders_ptr));return r;
}

函数的作用是获取Connector的当前状态信息。实际上,drmModeGetConnector函数就是_drmModeGetConnector函数的简单封装,如下所示:

drm_public drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
{return _drmModeGetConnector(fd, connector_id, 1);
}

对于_drmModeGetConnector函数的详细解析,将在下几篇文章中进行。


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部