是不是缺少了IOCTL设置
时间: 2024-03-28 16:41:42 浏览: 88
是的,您说得对。在使用select函数接收vblank信号之前,还需要使用ioctl函数向DRM设备注册vblank事件并启用它。以下是一个示例代码,演示如何注册vblank事件并使用select函数接收它:
```c
#include <stdio.h>
#include <fcntl.h>
#include <sys/select.h>
#include <drm/drm.h>
#include <drm/drm_mode.h>
int main(void)
{
int fd = open("/dev/dri/card0", O_RDWR);
if (fd < 0) {
perror("open");
return -1;
}
// 获取设备信息
struct drm_mode_card_res res;
if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res) < 0) {
perror("DRM_IOCTL_MODE_GETRESOURCES");
return -1;
}
// 注册vblank事件
struct drm_mode_crtc crtc;
crtc.crtc_id = res.crtcs[0];
if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc) < 0) {
perror("DRM_IOCTL_MODE_GETCRTC");
return -1;
}
struct drm_event_vblank vbl;
vbl.request.type = DRM_EVENT_VBLANK;
vbl.request.sequence = 0;
vbl.request.signal = (unsigned long)&vbl;
vbl.request.tv_sec = 0;
vbl.request.tv_usec = 0;
vbl.crtc_id = crtc.crtc_id;
if (ioctl(fd, DRM_IOCTL_MODE_SETEVENT, &vbl.request) < 0) {
perror("DRM_IOCTL_MODE_SETEVENT");
return -1;
}
// 启用vblank事件
uint32_t flags = DRM_MODE_PAGE_FLIP_EVENT | DRM_MODE_ATOMIC_NONBLOCK;
if (drmModePageFlip(fd, crtc.crtc_id, 0, flags, NULL) < 0) {
perror("drmModePageFlip");
return -1;
}
// 等待vblank事件
fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
while (1) {
int ret = select(fd + 1, &fds, NULL, NULL, NULL);
if (ret < 0) {
perror("select");
break;
}
if (FD_ISSET(fd, &fds)) {
ret = read(fd, &vbl, sizeof(vbl));
if (ret < 0) {
perror("read");
break;
}
printf("Received vblank event for crtc %d, sequence %u.\n",
vbl.crtc_id, vbl.sequence);
}
}
close(fd);
return 0;
}
```
在此示例中,我们使用DRM_IOCTL_MODE_GETRESOURCES ioctl函数获取设备信息,并使用DRM_IOCTL_MODE_GETCRTC ioctl函数获取第一个crtc的信息。然后,我们使用DRM_IOCTL_MODE_SETEVENT ioctl函数注册vblank事件,并使用drmModePageFlip函数启用它。最后,我们使用select函数等待vblank事件并处理它。请注意,此示例代码仅适用于具有单个crtc的系统,如果您的系统有多个crtc,则需要相应地调整代码。
阅读全文