Print log messages in case of wrong write access
[platform/core/system/peripheral-bus.git] / src / daemon / peripheral_bus_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 <gio/gio.h>
20 #include <poll.h>
21 #include <sys/time.h>
22 #include <libudev.h>
23
24 #include <peripheral_io.h>
25
26 #include "gpio.h"
27 #include "peripheral_bus.h"
28 #include "peripheral_bus_gdbus_gpio.h"
29 #include "peripheral_common.h"
30 #include "peripheral_bus_util.h"
31
32 static bool peripheral_bus_gpio_is_available(int pin, peripheral_bus_s *pb_data)
33 {
34         pb_board_dev_s *gpio = NULL;
35         pb_data_h handle;
36         GList *link;
37
38         RETV_IF(pb_data == NULL, false);
39         RETV_IF(pb_data->board == NULL, false);
40
41         gpio = peripheral_bus_board_find_device(PB_BOARD_DEV_GPIO, pb_data->board, pin);
42         if (gpio == NULL) {
43                 _E("Not supported GPIO pin : %d", pin);
44                 return false;
45         }
46
47         link = pb_data->gpio_list;
48         while (link) {
49                 handle = (pb_data_h)link->data;
50                 if (handle->dev.gpio.pin == pin) {
51                         _E("gpio %d is busy", pin);
52                         return false;
53                 }
54                 link = g_list_next(link);
55         }
56
57         return true;
58 }
59
60 static int gpio_wait_for_udev(int gpiopin)
61 {
62         #define GPIO_NAME_LEN 8
63         struct udev *udev;
64         struct udev_monitor *monitor;
65         struct udev_device *dev;
66         struct pollfd pfd;
67         char gpio_name[GPIO_NAME_LEN];
68         int ret = -EIO;
69
70         udev = udev_new();
71         if (!udev) {
72                 _E("Cannot create udev");
73                 return ret;
74         }
75
76         monitor = udev_monitor_new_from_netlink(udev, "udev");
77         if (!monitor) {
78                 _E("Cannot create udev monitor");
79                 udev_unref(udev);
80                 return ret;
81         }
82
83         ret = udev_monitor_filter_add_match_subsystem_devtype(monitor, "gpio", NULL);
84         if (ret < 0) {
85                 _E("Failed to add monitor filter");
86                 goto out;
87         }
88
89         ret = udev_monitor_enable_receiving(monitor);
90         if (ret < 0) {
91                 _E("Failed to enable udev receiving");
92                 goto out;
93         }
94
95         pfd.fd = udev_monitor_get_fd(monitor);
96         pfd.events = POLLIN;
97
98         snprintf(gpio_name, GPIO_NAME_LEN, "gpio%d", gpiopin);
99
100         for (int cnt = 0; cnt < 10; cnt++) {
101                 if (poll(&pfd, 1, 100) < 0) {
102                         _E("Failed to watch udev monitor");
103                         goto out;
104                 }
105
106                 dev = udev_monitor_receive_device(monitor);
107                 if (dev) {
108                         if (strcmp(udev_device_get_sysname(dev), gpio_name) == 0) {
109                                 _D("udev for %s is initialized", gpio_name);
110                                 ret = 0;
111                                 goto out;
112                         }
113                 }
114         }
115         _E("Time out");
116
117 out:
118         udev_monitor_unref(monitor);
119         udev_unref(udev);
120
121         return ret;
122 }
123
124
125 int peripheral_bus_gpio_open(gint pin, pb_data_h *handle, gpointer user_data)
126 {
127         peripheral_bus_s *pb_data = (peripheral_bus_s*)user_data;
128         pb_data_h gpio_handle;
129         int edge, direction;
130         int ret;
131
132         if (!peripheral_bus_gpio_is_available(pin, pb_data)) {
133                 _E("gpio %d is not available", pin);
134                 return PERIPHERAL_ERROR_RESOURCE_BUSY;
135         }
136
137         if ((ret = gpio_open(pin)) < 0) {
138                 _E("gpio_open error (%d)", ret);
139                 goto open_err;
140         }
141
142         if ((ret = gpio_get_edge_mode(pin, (gpio_edge_e*)&edge)) < 0) {
143                 _E("gpio_get_edge_mode error (%d)", ret);
144                 goto err;
145         }
146
147         if ((ret = gpio_get_direction(pin, (gpio_direction_e*)&direction)) < 0) {
148                 _E("gpio_get_direction error (%d)", ret);
149                 goto err;
150         }
151
152         gpio_handle = peripheral_bus_data_new(&pb_data->gpio_list);
153         if (!gpio_handle) {
154                 _E("peripheral_bus_data_new error");
155                 ret = PERIPHERAL_ERROR_UNKNOWN;
156                 goto err;
157         }
158
159         if (gpio_wait_for_udev(pin) < 0) {
160                 _E("device nodes are not writable");
161                 ret = PERIPHERAL_ERROR_UNKNOWN;
162                 goto err;
163         }
164
165         gpio_handle->type = PERIPHERAL_BUS_TYPE_GPIO;
166         gpio_handle->list = &pb_data->gpio_list;
167         gpio_handle->dev.gpio.pin = pin;
168         gpio_handle->dev.gpio.edge = edge;
169         gpio_handle->dev.gpio.direction = direction;
170         gpio_handle->dev.gpio.gpio_skeleton = pb_data->gpio_skeleton;
171
172         *handle = gpio_handle;
173
174         return PERIPHERAL_ERROR_NONE;
175
176 err:
177         gpio_close(pin);
178
179 open_err:
180         return ret;
181 }
182
183 int peripheral_bus_gpio_set_direction(pb_data_h handle, gint direction)
184 {
185         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
186         int ret;
187
188         gpio->direction = direction;
189
190         if ((ret = gpio_set_direction(gpio->pin, (gpio_direction_e)direction)) < 0) {
191                 _E("gpio_set_direction error (%d)", ret);
192                 return ret;
193         }
194
195         return PERIPHERAL_ERROR_NONE;
196 }
197
198 int peripheral_bus_gpio_get_direction(pb_data_h handle, gint *direction)
199 {
200         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
201         int ret;
202         gint value;
203
204         if ((ret = gpio_get_direction(gpio->pin, (gpio_direction_e*)direction)) < 0) {
205                 _E("gpio_get_direction error (%d)", ret);
206                 return ret;
207         }
208
209         if (*direction == GPIO_DIRECTION_OUT) {
210                 if ((ret = gpio_read(gpio->pin, &value)) < 0)
211                         return ret;
212                 /* Update direction state with the current value */
213                 *direction = GPIO_DIRECTION_OUT + value;
214         }
215
216         gpio->direction = *direction;
217
218         return PERIPHERAL_ERROR_NONE;
219 }
220
221 int peripheral_bus_gpio_set_edge(pb_data_h handle, gint edge)
222 {
223         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
224         int ret;
225
226         if ((ret = gpio_set_edge_mode(gpio->pin, (gpio_edge_e)edge)) < 0) {
227                 _E("gpio_set_edge_mode error (%d)", ret);
228                 return ret;
229         }
230
231         gpio->edge = edge;
232
233         return PERIPHERAL_ERROR_NONE;
234 }
235
236 int peripheral_bus_gpio_get_edge(pb_data_h handle, gint *edge)
237 {
238         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
239         int ret;
240
241         if ((ret = gpio_get_edge_mode(gpio->pin, (gpio_edge_e*)edge)) < 0) {
242                 _E("gpio_get_edge_mode error (%d)", ret);
243                 return ret;
244         }
245
246         gpio->edge = *edge;
247
248         return PERIPHERAL_ERROR_NONE;
249 }
250
251 int peripheral_bus_gpio_write(pb_data_h handle, gint value)
252 {
253         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
254         int ret;
255
256         /* Return error if direction of the pin is input mode */
257         if (gpio->direction == GPIO_DIRECTION_IN) {
258                 _E("The direction of the pin is INPUT mode, Cannot write");
259                 return PERIPHERAL_ERROR_INVALID_OPERATION;
260         }
261
262         if ((ret = gpio_write(gpio->pin, value)) < 0) {
263                 _E("gpio_write error (%d)", ret);
264                 return ret;
265         }
266         /* Update direction state along with the value */
267         gpio->direction = GPIO_DIRECTION_OUT + ((value > 0) ? 1 : 0);
268
269         return PERIPHERAL_ERROR_NONE;
270 }
271
272 int peripheral_bus_gpio_read(pb_data_h handle, gint *value)
273 {
274         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
275         int ret;
276
277         if ((ret = gpio_read(gpio->pin, value)) < 0) {
278                 _E("gpio_read error (%d)", ret);
279                 return ret;
280         }
281
282         return PERIPHERAL_ERROR_NONE;
283 }
284
285 static gboolean  peripheral_bus_gpio_cb(GIOChannel *io, GIOCondition condition, gpointer data)
286 {
287         peripheral_bus_gpio_s *gpio_data = (peripheral_bus_gpio_s *)data;
288         struct timeval time;
289         unsigned long long timestamp;
290         GIOStatus status;
291         gchar* strval;
292         int value;
293
294         if (!gpio_data->irq_en)
295                 return TRUE;
296
297         if (gpio_data->direction != PERIPHERAL_GPIO_DIRECTION_IN
298                 || gpio_data->edge == PERIPHERAL_GPIO_EDGE_NONE)
299                 return TRUE;
300
301         gettimeofday(&time, NULL);
302
303         g_io_channel_seek_position(io, 0, G_SEEK_SET, NULL);
304         status = g_io_channel_read_line(io, &strval, NULL, NULL, NULL);
305         if (status != G_IO_STATUS_NORMAL) {
306                 _E("Unable to read gpio value (%d)", status);
307                 return FALSE;
308         }
309         g_strstrip(strval);
310
311         _D("gpio = %d, data = %s", gpio_data->pin, strval);
312
313         if (g_ascii_strcasecmp(strval, "1") == 0)
314                 value = 1;
315         else if (g_ascii_strcasecmp(strval, "0") == 0)
316                 value = 0;
317         else {
318                 g_free(strval);
319                 _E("Error: gpio value is error");
320                 return FALSE;
321         }
322         g_free(strval);
323
324         if (gpio_data->edge == PERIPHERAL_GPIO_EDGE_RISING && value == 0)
325                 return TRUE;
326         else if (gpio_data->edge == PERIPHERAL_GPIO_EDGE_FALLING && value == 1)
327                 return TRUE;
328
329         timestamp = (unsigned long long)time.tv_sec * 1000000 + time.tv_usec;
330         peripheral_bus_emit_gpio_changed(gpio_data->gpio_skeleton, gpio_data->pin, value, timestamp);
331
332         return TRUE;
333 }
334
335 int peripheral_bus_gpio_register_irq(pb_data_h handle)
336 {
337         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
338         GIOStatus status;
339         gchar* strval;
340
341         if ((gpio->value_fd = gpio_open_isr(gpio->pin)) < 0)
342                 goto err_open_isr;
343
344         gpio->io = g_io_channel_unix_new(gpio->value_fd);
345         if (gpio->io == NULL) {
346                 _E("g_io_channel_unix_new error (%d)", gpio->value_fd);
347                 goto err_io_channel_new;
348         }
349
350         g_io_channel_seek_position(gpio->io, 0, G_SEEK_SET, NULL);
351         status = g_io_channel_read_line(gpio->io, &strval, NULL, NULL, NULL);
352         if (status != G_IO_STATUS_NORMAL) {
353                 _E("Unable to read gpio value (%d)", status);
354                 goto err_io_channel_read;
355         }
356         g_free(strval);
357
358         gpio->io_id = g_io_add_watch(gpio->io, G_IO_PRI, peripheral_bus_gpio_cb, gpio);
359         if (gpio->io_id == 0) {
360                 _E("g_io_add_watch error (%d)", gpio->io);
361                 goto err_io_add_watch;
362         }
363         g_io_channel_unref(gpio->io);
364         gpio->irq_en = 1;
365
366         return PERIPHERAL_ERROR_NONE;
367
368 err_io_add_watch:
369 err_io_channel_read:
370         g_io_channel_unref(gpio->io);
371         gpio->io_id = 0;
372 err_io_channel_new:
373         gpio_close_isr(gpio->value_fd);
374         gpio->io = 0;
375 err_open_isr:
376         gpio->value_fd = 0;
377
378         return PERIPHERAL_ERROR_UNKNOWN;
379 }
380
381 int peripheral_bus_gpio_unregister_irq(pb_data_h handle)
382 {
383         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
384
385         if (gpio->io) {
386                 gpio->irq_en = 0;
387                 g_source_remove(gpio->io_id);
388                 gpio->io_id = 0;
389                 g_io_channel_unref(gpio->io);
390                 gpio->io = 0;
391                 gpio_close_isr(gpio->value_fd);
392                 gpio->value_fd = 0;
393         }
394
395         return PERIPHERAL_ERROR_NONE;
396 }
397
398 int peripheral_bus_gpio_close(pb_data_h handle)
399 {
400         peripheral_bus_gpio_s *gpio = &handle->dev.gpio;
401         int ret = PERIPHERAL_ERROR_NONE;
402
403         if ((ret = gpio_close(gpio->pin)) < 0)
404                 return ret;
405
406         if (peripheral_bus_data_free(handle) < 0) {
407                 _E("Failed to free gpio data");
408                 ret = PERIPHERAL_ERROR_UNKNOWN;
409         }
410
411         return ret;;
412 }