2 * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "peripheral_interface_gpio.h"
20 #define GPIO_INTERRUPTED_CALLBACK_UNSET 0
21 #define GPIO_INTERRUPTED_CALLBACK_SET 1
23 int peripheral_interface_gpio_set_initial_direction_into_handle(peripheral_gpio_h gpio)
25 static predefined_type_s types[2] = {
31 char gpio_buf[GPIO_BUFFER_MAX] = {0, };
33 int ret = read(gpio->fd_direction, &gpio_buf, GPIO_BUFFER_MAX);
34 CHECK_ERROR(ret <= 0);
36 for (index = 0; index < 2; index++) {
37 if (!strncmp(gpio_buf, types[index].type, types[index].len)) {
38 // PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGH and PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW : out type
39 gpio->direction = (peripheral_gpio_direction_e)index;
40 return PERIPHERAL_ERROR_NONE;
44 return PERIPHERAL_ERROR_IO_ERROR;
48 * [edge_mode] [direction]
50 * none -----------------> in, out (O)
52 * rising, falling, both ---------> in (O)
56 int peripheral_interface_gpio_set_direction(peripheral_gpio_h gpio, peripheral_gpio_direction_e direction)
58 RETV_IF(gpio->direction == direction, PERIPHERAL_ERROR_NONE);
59 RETV_IF(gpio->edge != PERIPHERAL_GPIO_EDGE_NONE, PERIPHERAL_ERROR_IO_ERROR);
61 static predefined_type_s types[3] = {
67 int ret = write(gpio->fd_direction, types[direction].type, types[direction].len);
68 CHECK_ERROR(ret != types[direction].len);
70 gpio->direction = direction;
72 return PERIPHERAL_ERROR_NONE;
75 int peripheral_interface_gpio_set_initial_edge_into_handle(peripheral_gpio_h gpio)
77 static predefined_type_s types[4] = {
85 char gpio_buf[GPIO_BUFFER_MAX] = {0, };
87 int ret = read(gpio->fd_edge, &gpio_buf, GPIO_BUFFER_MAX);
88 CHECK_ERROR(ret <= 0);
90 for (index = 0; index < 4; index++) {
91 if (!strncmp(gpio_buf, types[index].type, types[index].len)) {
92 gpio->edge = (peripheral_gpio_edge_e)index;
93 return PERIPHERAL_ERROR_NONE;
97 return PERIPHERAL_ERROR_IO_ERROR;
101 * [direction] [edge_mode]
103 * in ---------> none, rising, falling, both (O)
105 * out --------> none (O)
107 * -----> rising, falling, both (X)
109 int peripheral_interface_gpio_set_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_edge_e edge)
111 RETV_IF(gpio->edge == edge, PERIPHERAL_ERROR_NONE);
112 RETV_IF(gpio->direction != PERIPHERAL_GPIO_DIRECTION_IN, PERIPHERAL_ERROR_IO_ERROR);
114 static predefined_type_s types[4] = {
121 int ret = write(gpio->fd_edge, types[edge].type, types[edge].len);
122 CHECK_ERROR(ret != types[edge].len);
126 return PERIPHERAL_ERROR_NONE;
130 * [direction] [value]
132 * in ---------> write (X)
133 * out --------> write (O)
135 int peripheral_interface_gpio_write(peripheral_gpio_h gpio, uint32_t value)
137 RETV_IF(gpio->direction == PERIPHERAL_GPIO_DIRECTION_IN, PERIPHERAL_ERROR_IO_ERROR);
139 static predefined_type_s types[2] = {
144 int ret = write(gpio->fd_value, types[value].type, types[value].len);
145 CHECK_ERROR(ret != types[value].len);
147 return PERIPHERAL_ERROR_NONE;
151 * [direction] [value]
153 * in ---------> read (O)
154 * out --------> read (O)
156 int peripheral_interface_gpio_read(peripheral_gpio_h gpio, uint32_t *value)
160 char gpio_buf[GPIO_BUFFER_MAX] = {0, };
162 lseek(gpio->fd_value, 0, SEEK_SET);
163 ret = read(gpio->fd_value, &gpio_buf, length);
164 CHECK_ERROR(ret != length);
166 if (gpio_buf[0] == '0') {
168 } else if (gpio_buf[0] == '1') {
171 _E("Error: gpio value is error \n");
172 return PERIPHERAL_ERROR_IO_ERROR;
175 return PERIPHERAL_ERROR_NONE;
178 void peripheral_interface_gpio_close(peripheral_gpio_h gpio)
180 peripheral_interface_gpio_unset_interrupted_cb(gpio);
182 close(gpio->fd_direction);
183 close(gpio->fd_edge);
184 close(gpio->fd_value);
187 static gboolean __peripheral_interface_gpio_interrupted_cb_invoke(gpointer data)
189 peripheral_gpio_h gpio = (peripheral_gpio_h)data;
190 gpio->cb_info.cb(gpio, gpio->cb_info.error, NULL);
194 static gpointer __peripheral_interface_gpio_poll(void *data)
196 peripheral_gpio_h gpio = (peripheral_gpio_h)data;
200 struct pollfd poll_fd;
202 poll_fd.fd = gpio->fd_value;
203 poll_fd.events = POLLPRI;
207 while (g_atomic_int_get(&gpio->cb_info.status) == GPIO_INTERRUPTED_CALLBACK_SET) {
209 poll_state = poll(&poll_fd, 1, 3000);
214 if (poll_state < 0) {
216 gpio->cb_info.error = PERIPHERAL_ERROR_IO_ERROR;
217 g_idle_add_full(G_PRIORITY_HIGH_IDLE, __peripheral_interface_gpio_interrupted_cb_invoke, gpio, NULL);
221 if (poll_fd.revents & POLLPRI) {
222 ret = peripheral_interface_gpio_read(gpio, &value);
223 if (ret != PERIPHERAL_ERROR_NONE)
229 if (gpio->edge == PERIPHERAL_GPIO_EDGE_NONE)
232 if (gpio->edge == PERIPHERAL_GPIO_EDGE_RISING && value == 0)
235 if (gpio->edge == PERIPHERAL_GPIO_EDGE_FALLING && value == 1)
238 gpio->cb_info.error = PERIPHERAL_ERROR_NONE;
239 g_idle_add_full(G_PRIORITY_HIGH_IDLE, __peripheral_interface_gpio_interrupted_cb_invoke, gpio, NULL);
245 int peripheral_interface_gpio_set_interrupted_cb(peripheral_gpio_h gpio, peripheral_gpio_interrupted_cb callback, void *user_data)
247 RETV_IF(gpio->direction != PERIPHERAL_GPIO_DIRECTION_IN, PERIPHERAL_ERROR_IO_ERROR);
249 peripheral_interface_gpio_unset_interrupted_cb(gpio);
251 gpio->cb_info.cb = callback;
252 gpio->cb_info.user_data = user_data;
253 g_atomic_int_set(&gpio->cb_info.status, GPIO_INTERRUPTED_CALLBACK_SET);
254 gpio->cb_info.thread = g_thread_new(NULL, __peripheral_interface_gpio_poll, gpio);
256 return PERIPHERAL_ERROR_NONE;
259 int peripheral_interface_gpio_unset_interrupted_cb(peripheral_gpio_h gpio)
261 g_atomic_int_set(&gpio->cb_info.status, GPIO_INTERRUPTED_CALLBACK_UNSET);
263 if (gpio->cb_info.thread != NULL) {
264 g_thread_join(gpio->cb_info.thread);
265 gpio->cb_info.thread = NULL;
268 return PERIPHERAL_ERROR_NONE;