6c64b9805ec257765addcc79585c09dda89e09f1
[platform/core/api/peripheral-io.git] / src / peripheral_gpio.c
1 /*
2  * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd.
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 <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <assert.h>
21
22 #include "peripheral_io.h"
23 #include "peripheral_gdbus_gpio.h"
24 #include "peripheral_common.h"
25 #include "peripheral_internal.h"
26 #include "peripheral_io_gdbus.h"
27
28 typedef struct {
29         int pin;
30         gpio_isr_cb callback;
31         void *user_data;
32 } gpio_isr_data_s;
33
34 static GList *gpio_isr_list = NULL;
35
36 int peripheral_gpio_isr_callback(int pin)
37 {
38         GList *link;
39         gpio_isr_data_s *isr_data;
40
41         link = gpio_isr_list;
42         while (link) {
43                 isr_data = (gpio_isr_data_s*)link->data;
44
45                 if (isr_data->pin == pin) {
46                         if (isr_data->callback)
47                                 isr_data->callback(isr_data->user_data);
48                         return PERIPHERAL_ERROR_NONE;
49                 }
50                 link = g_list_next(link);
51         }
52
53         return PERIPHERAL_ERROR_NONE;
54 }
55
56 int peripheral_gpio_isr_set(int pin, gpio_isr_cb callback, void *user_data)
57 {
58         GList *link;
59         gpio_isr_data_s *isr_data = NULL;
60
61         link = gpio_isr_list;
62         while (link) {
63                 gpio_isr_data_s *tmp;
64                 tmp = (gpio_isr_data_s*)link->data;
65                 if (tmp->pin == pin) {
66                         isr_data = tmp;
67                         break;
68                 }
69                 link = g_list_next(link);
70         }
71
72         if (isr_data == NULL) {
73                 isr_data = (gpio_isr_data_s*)calloc(1, sizeof(gpio_isr_data_s));
74                 if (isr_data == NULL) {
75                         _E("failed to allocate gpio_isr_data_s");
76                         return PERIPHERAL_ERROR_OUT_OF_MEMORY;
77                 }
78
79                 gpio_isr_list = g_list_append(gpio_isr_list, isr_data);
80         }
81
82         isr_data->pin = pin;
83         isr_data->callback = callback;
84         isr_data->user_data = user_data;
85
86         return PERIPHERAL_ERROR_NONE;
87 }
88
89 int peripheral_gpio_isr_unset(int pin)
90 {
91         GList *link;
92         gpio_isr_data_s *isr_data;
93
94         link = gpio_isr_list;
95         while (link) {
96                 isr_data = (gpio_isr_data_s*)link->data;
97
98                 if (isr_data->pin == pin) {
99                         gpio_isr_list = g_list_remove_link(gpio_isr_list, link);
100                         free(link->data);
101                         g_list_free(link);
102                         break;
103                 }
104                 link = g_list_next(link);
105         }
106
107         return PERIPHERAL_ERROR_NONE;
108 }
109
110 /**
111  * @brief Initializes(export) gpio pin and creates gpio handle.
112  */
113 int peripheral_gpio_open(int gpio_pin, peripheral_gpio_h *gpio)
114 {
115         int ret = PERIPHERAL_ERROR_NONE;
116         peripheral_gpio_h handle;
117
118         RETVM_IF(gpio_pin < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid gpio pin number");
119
120         /* Initialize */
121         handle = (peripheral_gpio_h)calloc(1, sizeof(struct _peripheral_gpio_s));
122
123         if (handle == NULL) {
124                 _E("Failed to allocate peripheral_gpio_h");
125                 return PERIPHERAL_ERROR_OUT_OF_MEMORY;
126         }
127         handle->pin = gpio_pin;
128
129         gpio_proxy_init();
130
131         ret = peripheral_gdbus_gpio_open(handle);
132
133         if (ret != PERIPHERAL_ERROR_NONE) {
134                 _E("Failed to open the gpio pin, ret : %d", ret);
135                 free(handle);
136                 handle = NULL;
137         }
138
139         *gpio = handle;
140
141         return ret;
142 }
143
144 /**
145  * @brief Closes the gpio_context.
146  * @brief Releases the gpio handle and finalize(unexport) the gpio pin.
147  */
148 int peripheral_gpio_close(peripheral_gpio_h gpio)
149 {
150         int ret = PERIPHERAL_ERROR_NONE;
151
152         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
153
154         /* call gpio_close */
155         ret = peripheral_gdbus_gpio_close(gpio);
156         if (ret != PERIPHERAL_ERROR_NONE)
157                 _E("Failed to close the gpio pin, ret : %d", ret);
158         gpio_proxy_deinit();
159
160         free(gpio);
161         gpio = NULL;
162
163         return ret;
164 }
165
166 /**
167  * @brief Gets direction of the gpio.
168  */
169 int peripheral_gpio_get_direction(peripheral_gpio_h gpio, peripheral_gpio_direction_e *direction)
170 {
171         int ret = PERIPHERAL_ERROR_NONE;
172
173         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
174
175         ret = peripheral_gdbus_gpio_get_direction(gpio, direction);
176         if (ret != PERIPHERAL_ERROR_NONE)
177                 _E("Failed to get direction of the gpio pin, ret : %d", ret);
178
179         return ret;
180 }
181
182
183 /**
184  * @brief Sets direction of the gpio pin.
185  */
186 int peripheral_gpio_set_direction(peripheral_gpio_h gpio, peripheral_gpio_direction_e direction)
187 {
188         int ret = PERIPHERAL_ERROR_NONE;
189
190         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
191         RETVM_IF(direction > PERIPHERAL_GPIO_DIRECTION_OUT_HIGH, PERIPHERAL_ERROR_INVALID_PARAMETER,
192                 "Invalid direction input");
193
194         /* call gpio_set_direction */
195         ret = peripheral_gdbus_gpio_set_direction(gpio, direction);
196         if (ret != PERIPHERAL_ERROR_NONE)
197                 _E("Failed to set gpio direction, ret : %d", ret);
198
199         return ret;
200 }
201
202 /**
203  * @brief Reads value of the gpio.
204  */
205 int peripheral_gpio_read(peripheral_gpio_h gpio, int *value)
206 {
207         int ret = PERIPHERAL_ERROR_NONE;
208
209         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
210
211         /* call gpio_read */
212         ret = peripheral_gdbus_gpio_read(gpio, value);
213         if (ret != PERIPHERAL_ERROR_NONE)
214                 _E("Failed to read value of the gpio pin, ret : %d", ret);
215
216         return ret;
217 }
218
219 /**
220  * @brief Writes value to the gpio.
221  */
222 int peripheral_gpio_write(peripheral_gpio_h gpio, int value)
223 {
224         int ret = PERIPHERAL_ERROR_NONE;
225
226         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
227
228         /* call gpio_write */
229         ret = peripheral_gdbus_gpio_write(gpio, value);
230         if (ret != PERIPHERAL_ERROR_NONE)
231                 _E("Failed to write to the gpio pin, ret : %d", ret);
232
233         return ret;
234 }
235
236 /**
237  * @brief Gets the edge mode of the gpio.
238  */
239 int peripheral_gpio_get_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_edge_e *edge)
240 {
241         int ret = PERIPHERAL_ERROR_NONE;
242
243         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
244
245         ret = peripheral_gdbus_gpio_get_edge_mode(gpio, edge);
246         if (ret != PERIPHERAL_ERROR_NONE)
247                 _E("Failed to get edge mode of the gpio pin, ret : %d", ret);
248
249         return ret;
250 }
251
252 /**
253  * @brief Sets the edge mode of the gpio pin.
254  */
255 int peripheral_gpio_set_edge_mode(peripheral_gpio_h gpio, peripheral_gpio_edge_e edge)
256 {
257         int ret = PERIPHERAL_ERROR_NONE;
258
259         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
260         RETVM_IF(edge > PERIPHERAL_GPIO_EDGE_BOTH, PERIPHERAL_ERROR_INVALID_PARAMETER,
261                 "Invalid edge input");
262
263         /* call gpio_set_edge_mode */
264         ret = peripheral_gdbus_gpio_set_edge_mode(gpio, edge);
265         if (ret != PERIPHERAL_ERROR_NONE)
266                 _E("Failed to set edge mode of the gpio pin, ret : %d", ret);
267
268         return ret;
269 }
270
271 /**
272  * @brief Registers a callback function to be invoked when the gpio interrupt is triggered.
273  */
274 int peripheral_gpio_register_cb(peripheral_gpio_h gpio, gpio_isr_cb callback, void *user_data)
275 {
276         int ret = PERIPHERAL_ERROR_NONE;
277
278         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
279
280         ret = peripheral_gdbus_gpio_register_cb(gpio, callback, user_data);
281         if (ret != PERIPHERAL_ERROR_NONE) {
282                 _E("Failed to register cb, ret : %d", ret);
283                 return ret;
284         }
285
286         /* set isr */
287         ret = peripheral_gpio_isr_set(gpio->pin, callback, user_data);
288         if (ret != PERIPHERAL_ERROR_NONE)
289                 _E("Failed to register gpio isr, ret : %d", ret);
290
291         return ret;
292 }
293
294 /**
295  * @brief Unregisters the callback function for the gpio handler.
296  */
297 int peripheral_gpio_unregister_cb(peripheral_gpio_h gpio)
298 {
299         int ret = PERIPHERAL_ERROR_NONE;
300
301         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
302
303         ret = peripheral_gdbus_gpio_unregister_cb(gpio);
304         if (ret != PERIPHERAL_ERROR_NONE) {
305                 _E("Failed to unregister gpio isr, ret : %d", ret);
306                 return ret;
307         }
308
309         /* clean up isr */
310         ret = peripheral_gpio_isr_unset(gpio->pin);
311
312         return ret;
313 }
314
315 /**
316  * @brief Gets pin number of the gpio handle.
317  */
318 int peripheral_gpio_get_pin(peripheral_gpio_h gpio, int *gpio_pin)
319 {
320         RETVM_IF(gpio == NULL, PERIPHERAL_ERROR_INVALID_PARAMETER, "gpio handle is NULL");
321
322         *gpio_pin = gpio->pin;
323
324         return PERIPHERAL_ERROR_NONE;
325 }