xref: /OK3568_Linux_fs/device/rockchip/common/data/kmsgrab.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 #include <errno.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <unistd.h>
7 #include <sys/ioctl.h>
8 #include <sys/mman.h>
9 
10 #include <xf86drm.h>
11 #include <xf86drmMode.h>
12 
map_fb(int fd,int handle,size_t size)13 static void *map_fb(int fd, int handle, size_t size) {
14 	struct drm_prime_handle arg;
15 	int ret;
16 	void *ptr;
17 
18 	memset(&arg, 0, sizeof(arg));
19 	arg.handle = handle;
20 
21 	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &arg);
22 	if (ret) {
23 		fprintf(stderr, "DRM_IOCTL_PRIME_HANDLE_TO_FD failed\n");
24 		return NULL;
25 	}
26 
27 	ptr = mmap(0, size, PROT_READ, MAP_SHARED, arg.fd, 0);
28 	if (ptr == MAP_FAILED) {
29 		fprintf(stderr, "mmap failed %s\n", strerror(errno));
30 		return NULL;
31 	}
32 
33 	return ptr;
34 }
35 
get_fb_dmafd(int fd,int handle)36 static int get_fb_dmafd(int fd, int handle)
37 {
38 	struct drm_prime_handle args;
39 	int ret;
40 
41 	memset(&args, 0, sizeof(args));
42 	args.fd = -1;
43 	args.handle = handle;
44 
45 	ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
46 	if (ret)
47 		return ret;
48 
49 	return args.fd;
50 }
51 
destroy_dumb(int fd,int handle)52 static void destroy_dumb(int fd, int handle) {
53 	struct drm_mode_destroy_dumb arg;
54 
55 	memset(&arg, 0, sizeof(arg));
56 	arg.handle = handle;
57 	drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
58 }
59 
dump_fb(int fd,int fb_id)60 static int dump_fb(int fd, int fb_id) {
61 	drmModeFBPtr fb = drmModeGetFB(fd, fb_id);
62 	size_t size;
63 	void *ptr;
64 	int dmafd;
65 
66 	if (!fb) {
67 		fprintf(stderr, "Failed to get framebuffer\n");
68 		return -1;
69 	}
70 
71 	size = fb->pitch * fb->height;
72 
73 	dmafd = get_fb_dmafd(fd, fb->handle);
74 
75 	fprintf(stderr, "fb handle=%d size=%dx%d(%d)\n",
76 		fb->handle, fb->width, fb->height, fb->pitch);
77 
78 	ptr = map_fb(fd, fb->handle, size);
79 	if (ptr) {
80 		fprintf(stderr, "first pixel: %x\n", *((int *)ptr));
81 		write(1, ptr, size);
82 		munmap(ptr, size);
83 		destroy_dumb(fd, fb->handle);
84 	}
85 
86 	close(dmafd);
87 	drmModeFreeFB(fb);
88 	return 0;
89 }
90 
get_crtc_fb(int fd,int crtc_id)91 static int get_crtc_fb(int fd, int crtc_id) {
92 	drmModeCrtcPtr crtc;
93 	int id;
94 
95 	crtc = drmModeGetCrtc(fd, crtc_id);
96 	if (!crtc) {
97 		fprintf(stderr, "Unknown CRTC %d\n", crtc_id);
98 		return -1;
99 	}
100 
101 	id = crtc->buffer_id;
102 
103 	drmModeFreeCrtc(crtc);
104 	return id;
105 }
106 
get_encoder_fb(int fd,int encoder_id)107 static int get_encoder_fb(int fd, int encoder_id) {
108 	drmModeEncoderPtr encoder;
109 	int id;
110 
111 	encoder = drmModeGetEncoder(fd, encoder_id);
112 	if (!encoder) {
113 		fprintf(stderr, "Unknown Encoder %d\n", encoder_id);
114 		return -1;
115 	}
116 
117 	id = get_crtc_fb(fd, encoder->crtc_id);
118 
119 	drmModeFreeEncoder(encoder);
120 	return id;
121 }
122 
get_connector_fb(int fd,int connector_id)123 static int get_connector_fb(int fd, int connector_id) {
124 	drmModeConnector *connector;
125 	int id;
126 
127 	connector = drmModeGetConnector(fd, connector_id);
128 	if (!connector) {
129 		fprintf(stderr, "Unknown Connector %d\n", connector_id);
130 		return -1;
131 	}
132 
133 	id = get_encoder_fb(fd, connector->encoder_id);
134 
135 	drmModeFreeConnector(connector);
136 	return id;
137 }
138 
get_plane_fb(int fd,int plane_id)139 static int get_plane_fb(int fd, int plane_id) {
140 	drmModePlanePtr plane;
141 	int id;
142 
143 	plane = drmModeGetPlane(fd, plane_id);
144 	if (!plane) {
145 		fprintf(stderr, "Unknown Plane %d\n", plane_id);
146 		return -1;
147 	}
148 
149 	id = plane->fb_id;
150 
151 	drmModeFreePlane(plane);
152 	return id;
153 }
154 
usage(const char * prog,int fd)155 static void usage(const char *prog, int fd) {
156 	drmModeCrtcPtr crtc;
157 	drmModeResPtr res;
158 	int i;
159 
160 	res = drmModeGetResources(fd);
161 
162 	fprintf(stderr, "Usage:\n");
163 	fprintf(stderr, "%s [--crtc|--connector|--plane|--fb] OBJ_ID > out\n",
164 		prog);
165 	fprintf(stderr, "Valid crtc:");
166 	for (i = 0; i < res->count_crtcs; i++) {
167 		crtc = drmModeGetCrtc(fd, res->crtcs[i]);
168 		if (crtc && crtc->mode_valid)
169 			fprintf(stderr, " %d", crtc->crtc_id);
170 		drmModeFreeCrtc(crtc);
171 	}
172 	fprintf(stderr, "\n");
173 
174 	drmModeFreeResources(res);
175 
176 	exit(-1);
177 }
178 
main(int argc,const char ** argv)179 int main(int argc, const char** argv) {
180 	int id, fd;
181 
182 	fd = open("/dev/dri/card0", O_RDWR);
183 	if (fd < 0) {
184 		fprintf(stderr, "drm open failed\n");
185 		return -1;
186 	}
187 	fcntl(fd, F_SETFD, FD_CLOEXEC);
188 
189 	// while (1) {
190 
191 	switch (argc) {
192 	case 3:
193 		id = atoi(argv[2]);
194 
195 		if (!strcmp(argv[1], "--crtc"))
196 			id = get_crtc_fb(fd, id);
197 		else if (!strcmp(argv[1], "--connector"))
198 			id = get_connector_fb(fd, id);
199 		else if (!strcmp(argv[1], "--plane"))
200 			id = get_plane_fb(fd, id);
201 		else if (strcmp(argv[1], "--fb"))
202 			usage(argv[0], fd);
203 
204 		break;
205 	case 2:
206 		id = atoi(argv[1]);
207 		if (id <= 0)
208 			usage(argv[0], fd);
209 
210 		break;
211 	default:
212 		usage(argv[0], fd);
213 	}
214 
215 	if (id <= 0) {
216 		fprintf(stderr, "Failed to get framebuffer id\n");
217 		return -1;
218 	}
219 
220 	dump_fb(fd, id);
221 
222 	// /* Add delay */ }
223 
224 	return 0;
225 }
226