1 /*
2  *   Copyright 2020 Google, Inc
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  */
16 
17 #include <BufferAllocator/BufferAllocatorWrapper.h>
18 #include <errno.h>
19 #include <ion/ion.h>
20 #include <stdbool.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <sys/mman.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26 
27 typedef struct {
28     int a;
29     int b;
30 } custom_callback_data;
31 
legacy_ion_custom_callback(int ion_fd,int dma_buf_fd,void * legacy_ion_custom_data)32 int legacy_ion_custom_callback(int ion_fd, int dma_buf_fd,
33                                 void *legacy_ion_custom_data) {
34     int ret = 0;
35     custom_callback_data *data;
36     (void) dma_buf_fd;
37     if (!ion_is_legacy(ion_fd)) {
38         perror("error in legacy ion custom callback");
39         ret = errno;
40     } else {
41         printf("in custom legacy ion cpu sync callback\n");
42         if (legacy_ion_custom_data) {
43             data = (custom_callback_data *) legacy_ion_custom_data;
44             printf("custom data was supplied to ion cpu sync callback: a = %d, b = %d\n",
45                    data->a, data->b);
46         }
47     }
48 
49     return ret;
50 }
51 
libdmabufheaptest(bool use_custom_callback,void * legacy_ion_custom_data)52 void libdmabufheaptest(bool use_custom_callback, void *legacy_ion_custom_data) {
53     const size_t len = 1024 * 1024;
54     int fd = -1, ret = 0;
55     size_t i = 0;
56     unsigned char* ptr = NULL;
57 
58     BufferAllocator* bufferAllocator = CreateDmabufHeapBufferAllocator();
59     if (!bufferAllocator) {
60         printf("unable to get allocator\n");
61         return;
62     }
63 
64     /*
65      * Legacy ion devices may have hardcoded heap IDs that do not
66      * match the ion UAPI header. Map heap name 'system' to a heap mask
67      * of all 1s so that these devices will allocate from the first
68      * available heap when asked to allocate from a heap of name 'system'.
69      */
70     ret = MapDmabufHeapNameToIonHeap(bufferAllocator, kDmabufSystemHeapName,
71                                      "" /* no mapping for non-legacy */,
72                                      0 /* no mapping for non-legacy ion */,
73                                      ~0 /* legacy ion heap mask */, 0 /* legacy ion heap flag */);
74     if (ret < 0) {
75         printf("MapDmabufHeapNameToIonHeap failed: %d\n", ret);
76         return;
77     }
78 
79     /*
80      * Test the DmabufHeapAllocSystem() APIs.
81      */
82     fd = DmabufHeapAllocSystem(bufferAllocator, true /* cpu_access */, len, 0, 0);
83     if (fd < 0) {
84         printf("DmabufHeapAllocSystem() failed: %d cpu_access: true\n", fd);
85         return;
86     }
87     close(fd);
88 
89     fd = DmabufHeapAllocSystem(bufferAllocator, false /* cpu_access */, len, 0, 0);
90     if (fd < 0) {
91         printf("DmabufHeapAllocSystem() failed: %d cpu_access: false\n", fd);
92         return;
93     }
94     close(fd);
95 
96     fd = DmabufHeapAlloc(bufferAllocator, kDmabufSystemHeapName, len, 0, 0);
97     if (fd < 0) {
98         printf("Alloc failed: %d\n", fd);
99         return;
100     }
101 
102     ptr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
103     if (ptr == MAP_FAILED) {
104         perror("mmap failed\n");
105         return;
106     }
107 
108     ret = DmabufHeapCpuSyncStart(bufferAllocator, fd, kSyncReadWrite,
109                                  use_custom_callback ? legacy_ion_custom_callback : NULL,
110                                  legacy_ion_custom_data);
111     if (ret) {
112         printf("DmabufHeapCpuSyncStart failed: %d\n", ret);
113         return;
114     }
115 
116     for (i = 0; i < len; i++) {
117         ptr[i] = (unsigned char)i;
118     }
119     for (i = 0; i < len; i++) {
120         if (ptr[i] != (unsigned char)i) {
121             printf("%s failed wrote %zu read %d from mapped "
122                    "memory\n",
123                    __func__, i, ptr[i]);
124             return;
125         }
126     }
127 
128     ret = DmabufHeapCpuSyncEnd(bufferAllocator, fd, kSyncReadWrite,
129                                use_custom_callback ? legacy_ion_custom_callback : NULL,
130                                legacy_ion_custom_data);
131     if (ret) {
132         printf("DmabufHeapCpuSyncEnd failed: %d\n", ret);
133         return;
134     }
135 
136     munmap(ptr, len);
137     close(fd);
138 
139     FreeDmabufHeapBufferAllocator(bufferAllocator);
140     printf("PASSED\n");
141 }
142 
main(int argc,char * argv[])143 int main(int argc, char* argv[]) {
144     (void)argc;
145     (void)argv;
146 
147     if (CheckIonSupport())
148         printf("ION support detected\n");
149     else
150         printf("No ION support detected\n");
151 
152     custom_callback_data data = {.a = 1, .b = 2};
153     printf("*****running with custom legacy ion cpu sync callback, with custom data****\n");
154     libdmabufheaptest(true, &data);
155     printf("*****running with custom legacy ion cpu sync callback, without custom data****\n");
156     libdmabufheaptest(true, NULL);
157     printf("****running without custom legacy ion cpu sync callback, with custom data****\n");
158     libdmabufheaptest(false, &data);
159     printf("****running without custom legacy ion cpu sync callback, without custom data****\n");
160     libdmabufheaptest(false, NULL);
161     return 0;
162 }
163