/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/ion.h>
#define ION_HEAP(bit) (1 << (bit))
enum ion_heap_ids {
INVALID_HEAP_ID = -1,
ION_CP_MM_HEAP_ID = 8,
ION_SECURE_HEAP_ID = 9,
ION_SECURE_DISPLAY_HEAP_ID = 10,
ION_CP_MFC_HEAP_ID = 12,
ION_CP_WB_HEAP_ID = 16, /* 8660 only */
ION_CAMERA_HEAP_ID = 20, /* 8660 only */
ION_SYSTEM_CONTIG_HEAP_ID = 21,
ION_ADSP_HEAP_ID = 22,
ION_PIL1_HEAP_ID = 23, /* Currently used for other PIL images */
ION_SF_HEAP_ID = 24,
ION_SYSTEM_HEAP_ID = 25,
ION_PIL2_HEAP_ID = 26, /* Currently used for modem firmware images */
ION_QSECOM_HEAP_ID = 27,
ION_AUDIO_HEAP_ID = 28,
ION_MM_FIRMWARE_HEAP_ID = 29,
ION_HEAP_ID_RESERVED = 31 /** Bit reserved for ION_FLAG_SECURE flag */
};
static unsigned int ion_type[] = {
ION_HEAP(ION_CP_MM_HEAP_ID),
ION_HEAP(ION_CP_MFC_HEAP_ID),
ION_HEAP(ION_SYSTEM_CONTIG_HEAP_ID),
ION_HEAP(ION_ADSP_HEAP_ID ),
ION_HEAP(ION_SF_HEAP_ID),
ION_HEAP(ION_SYSTEM_HEAP_ID),
ION_HEAP(ION_QSECOM_HEAP_ID),
ION_HEAP(ION_AUDIO_HEAP_ID),
};
#define NEW_ION
int ion_alloc(int fd, int len, int *hdl, unsigned int ion_type)
{
int ret;
struct ion_allocation_data req = {
.len = len,
#ifdef NEW_ION
.heap_id_mask = ion_type,
//.flags = ION_SECURE | ION_FORCE_CONTIGUOUS,
.flags = (1 << 0),
.flags = 0x0,
#else
.flags = ION_SECURE | ION_FORCE_CONTIGUOUS | ION_HEAP(ION_CP_MM_HEAP_ID),
#endif
.align = len,
};
ret = ioctl(fd, ION_IOC_ALLOC, &req);
if (ret) {
return ret;
}
*hdl = req.handle;
return 0;
}
int ion_free(int fd, int hdl)
{
int ret;
struct ion_handle_data req = {
.handle = hdl,
};
ret = ioctl(fd, ION_IOC_FREE, &req);
if (ret) {
return ret;
}
return 0;
}
int ion_map(int fd, int hdl)
{
int ret;
struct ion_fd_data req = {
.handle = hdl,
};
ret = ioctl(fd, ION_IOC_MAP, &req);
if (ret) {
return ret;
}
return req.fd;
}
int ion_fd;
int ion_handle;
int status[2];
int cmd = 0;
void *threadForIonFree01()
{
status[0] = 1;
while (cmd == 0) {
usleep(10);
}
if (cmd == -1)
goto failed;
usleep(50);
ion_free(ion_fd, ion_handle);
failed:
status[0] = 2;
return NULL;
}
void *threadForIonFree02()
{
status[1] = 1;
while (cmd == 0) {
usleep(10);
}
if(cmd == -1)
goto failed;
usleep(50);
ion_free(ion_fd, ion_handle);
failed:
status[1] = 2;
return NULL;
}
int main()
{
int ret, i, count;
pthread_t tid_free[2];
count = 0;
retry:
status[0] = 0;
status[1] = 0;
cmd = 0;
ion_fd = open("/dev/ion", O_RDONLY| O_SYNC, 0);
if (ion_fd < 0) {
return -1;
}
for (i=0; i < sizeof(ion_type)/sizeof(ion_type[0]); i++) {
ret = ion_alloc(ion_fd, 0x1000, &ion_handle, ion_type[i]);
if (ret == 0) {
break;
}
}
if (i == sizeof(ion_type)/sizeof(ion_type[0])) {
goto failed;
}
ret = pthread_create(&tid_free[0], NULL, threadForIonFree01, NULL);
if (ret != 0) {
goto failed;
}
ret = pthread_create(&tid_free[1], NULL, threadForIonFree02, NULL);
if (ret != 0) {
cmd = -1;
goto failed;
}
while (status[0] != 1 || status[1] != 1) {
usleep(50);
}
cmd = 1;
ret = ion_map(ion_fd, ion_handle);
while (status[0] != 2 || status[1] != 2) {
usleep(50);
}
failed:
ion_free(ion_fd,ion_handle);
close(ion_fd);
goto retry;
return 0;
}