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
19int 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
35int 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
61int 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
76void 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
84int 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
130out_vgem:
131	close(vgem_fd);
132out_ion:
133	ion_close_buffer_fd(&info);
134	printf("done.\n");
135	return ret;
136}
137