1 #include <errno.h>
2 #include <fcntl.h>
3 #include <stdio.h>
4 #include <stdint.h>
5 #include <string.h>
6 #include <unistd.h>
7 
8 #include <sys/ioctl.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 
12 #include <linux/dma-buf.h>
13 
14 #include <drm/drm.h>
15 
16 #include "ion.h"
17 #include "ionutils.h"
18 
check_vgem(int fd)19 int check_vgem(int fd)
20 {
21 	drm_version_t version = { 0 };
22 	char name[5];
23 	int ret;
24 
25 	version.name_len = 4;
26 	version.name = name;
27 
28 	ret = ioctl(fd, DRM_IOCTL_VERSION, &version);
29 	if (ret)
30 		return 1;
31 
32 	return strcmp(name, "vgem");
33 }
34 
open_vgem(void)35 int open_vgem(void)
36 {
37 	int i, fd;
38 	const char *drmstr = "/dev/dri/card";
39 
40 	fd = -1;
41 	for (i = 0; i < 16; i++) {
42 		char name[80];
43 
44 		sprintf(name, "%s%u", drmstr, i);
45 
46 		fd = open(name, O_RDWR);
47 		if (fd < 0)
48 			continue;
49 
50 		if (check_vgem(fd)) {
51 			close(fd);
52 			continue;
53 		} else {
54 			break;
55 		}
56 
57 	}
58 	return fd;
59 }
60 
import_vgem_fd(int vgem_fd,int dma_buf_fd,uint32_t * handle)61 int import_vgem_fd(int vgem_fd, int dma_buf_fd, uint32_t *handle)
62 {
63 	struct drm_prime_handle import_handle = { 0 };
64 	int ret;
65 
66 	import_handle.fd = dma_buf_fd;
67 	import_handle.flags = 0;
68 	import_handle.handle = 0;
69 
70 	ret = ioctl(vgem_fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &import_handle);
71 	if (ret == 0)
72 		*handle = import_handle.handle;
73 	return ret;
74 }
75 
close_handle(int vgem_fd,uint32_t handle)76 void close_handle(int vgem_fd, uint32_t handle)
77 {
78 	struct drm_gem_close close = { 0 };
79 
80 	close.handle = handle;
81 	ioctl(vgem_fd, DRM_IOCTL_GEM_CLOSE, &close);
82 }
83 
main()84 int main()
85 {
86 	int ret, vgem_fd;
87 	struct ion_buffer_info info;
88 	uint32_t handle = 0;
89 	struct dma_buf_sync sync = { 0 };
90 
91 	info.heap_type = ION_HEAP_TYPE_SYSTEM;
92 	info.heap_size = 4096;
93 	info.flag_type = ION_FLAG_CACHED;
94 
95 	ret = ion_export_buffer_fd(&info);
96 	if (ret < 0) {
97 		printf("ion buffer alloc failed\n");
98 		return -1;
99 	}
100 
101 	vgem_fd = open_vgem();
102 	if (vgem_fd < 0) {
103 		ret = vgem_fd;
104 		printf("Failed to open vgem\n");
105 		goto out_ion;
106 	}
107 
108 	ret = import_vgem_fd(vgem_fd, info.buffd, &handle);
109 
110 	if (ret < 0) {
111 		printf("Failed to import buffer\n");
112 		goto out_vgem;
113 	}
114 
115 	sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
116 	ret = ioctl(info.buffd, DMA_BUF_IOCTL_SYNC, &sync);
117 	if (ret)
118 		printf("sync start failed %d\n", errno);
119 
120 	memset(info.buffer, 0xff, 4096);
121 
122 	sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
123 	ret = ioctl(info.buffd, DMA_BUF_IOCTL_SYNC, &sync);
124 	if (ret)
125 		printf("sync end failed %d\n", errno);
126 
127 	close_handle(vgem_fd, handle);
128 	ret = 0;
129 
130 out_vgem:
131 	close(vgem_fd);
132 out_ion:
133 	ion_close_buffer_fd(&info);
134 	printf("done.\n");
135 	return ret;
136 }
137