ion.c revision f0a54c17d894391a69bfa6c11b474c5b851b762e
1/*
2 *  ion.c
3 *
4 * Memory Allocator functions for ion
5 *
6 *   Copyright 2011 Google, Inc
7 *
8 *  Licensed under the Apache License, Version 2.0 (the "License");
9 *  you may not use this file except in compliance with the License.
10 *  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *  Unless required by applicable law or agreed to in writing, software
15 *  distributed under the License is distributed on an "AS IS" BASIS,
16 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 *  See the License for the specific language governing permissions and
18 *  limitations under the License.
19 */
20#define LOG_TAG "ion"
21
22#include <cutils/log.h>
23#include <errno.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <sys/ioctl.h>
27#include <sys/mman.h>
28#include <sys/types.h>
29
30#include <linux/ion.h>
31#include <ion/ion.h>
32
33int ion_open()
34{
35    int fd = open("/dev/ion", O_RDWR);
36    if (fd < 0)
37        ALOGE("open /dev/ion failed!\n");
38    return fd;
39}
40
41int ion_close(int fd)
42{
43    int ret = close(fd);
44    if (ret < 0)
45        return -errno;
46    return ret;
47}
48
49static int ion_ioctl(int fd, int req, void *arg)
50{
51    int ret = ioctl(fd, req, arg);
52    if (ret < 0) {
53        ALOGE("ioctl %x failed with code %d: %s\n", req,
54              ret, strerror(errno));
55        return -errno;
56    }
57    return ret;
58}
59
60int ion_alloc(int fd, size_t len, size_t align, unsigned int heap_mask,
61              unsigned int flags, ion_user_handle_t *handle)
62{
63    int ret;
64    struct ion_allocation_data data = {
65        .len = len,
66        .align = align,
67        .heap_id_mask = heap_mask,
68        .flags = flags,
69    };
70
71    if (handle == NULL)
72        return -EINVAL;
73
74    ret = ion_ioctl(fd, ION_IOC_ALLOC, &data);
75    if (ret < 0)
76        return ret;
77    *handle = data.handle;
78    return ret;
79}
80
81int ion_free(int fd, ion_user_handle_t handle)
82{
83    struct ion_handle_data data = {
84        .handle = handle,
85    };
86    return ion_ioctl(fd, ION_IOC_FREE, &data);
87}
88
89int ion_map(int fd, ion_user_handle_t handle, size_t length, int prot,
90            int flags, off_t offset, unsigned char **ptr, int *map_fd)
91{
92    int ret;
93    struct ion_fd_data data = {
94        .handle = handle,
95    };
96
97    if (map_fd == NULL)
98        return -EINVAL;
99    if (ptr == NULL)
100        return -EINVAL;
101
102    ret = ion_ioctl(fd, ION_IOC_MAP, &data);
103    if (ret < 0)
104        return ret;
105    *map_fd = data.fd;
106    if (*map_fd < 0) {
107        ALOGE("map ioctl returned negative fd\n");
108        return -EINVAL;
109    }
110    *ptr = mmap(NULL, length, prot, flags, *map_fd, offset);
111    if (*ptr == MAP_FAILED) {
112        ALOGE("mmap failed: %s\n", strerror(errno));
113        return -errno;
114    }
115    return ret;
116}
117
118int ion_share(int fd, ion_user_handle_t handle, int *share_fd)
119{
120    int ret;
121    struct ion_fd_data data = {
122        .handle = handle,
123    };
124
125    if (share_fd == NULL)
126        return -EINVAL;
127
128    ret = ion_ioctl(fd, ION_IOC_SHARE, &data);
129    if (ret < 0)
130        return ret;
131    *share_fd = data.fd;
132    if (*share_fd < 0) {
133        ALOGE("share ioctl returned negative fd\n");
134        return -EINVAL;
135    }
136    return ret;
137}
138
139int ion_alloc_fd(int fd, size_t len, size_t align, unsigned int heap_mask,
140                 unsigned int flags, int *handle_fd) {
141    ion_user_handle_t handle;
142    int ret;
143
144    ret = ion_alloc(fd, len, align, heap_mask, flags, &handle);
145    if (ret < 0)
146        return ret;
147    ret = ion_share(fd, handle, handle_fd);
148    ion_free(fd, handle);
149    return ret;
150}
151
152int ion_import(int fd, int share_fd, ion_user_handle_t *handle)
153{
154    int ret;
155    struct ion_fd_data data = {
156        .fd = share_fd,
157    };
158
159    if (handle == NULL)
160        return -EINVAL;
161
162    ret = ion_ioctl(fd, ION_IOC_IMPORT, &data);
163    if (ret < 0)
164        return ret;
165    *handle = data.handle;
166    return ret;
167}
168
169int ion_sync_fd(int fd, int handle_fd)
170{
171    struct ion_fd_data data = {
172        .fd = handle_fd,
173    };
174    return ion_ioctl(fd, ION_IOC_SYNC, &data);
175}
176