#include "peripheral_interface_gpio.h"
#include "peripheral_interface_common.h"
-static int __gpio_wait_for_udev(int pin)
+static int __gpio_create_udev_monitor(struct udev **udev, struct udev_monitor **monitor)
{
- struct udev *udev;
- struct udev_monitor *monitor;
- struct udev_device *dev;
- struct pollfd pfd;
- char gpio_name[MAX_BUF_LEN];
+ struct udev *_udev = NULL;
+ struct udev_monitor *_monitor = NULL;
int ret = -EIO;
- udev = udev_new();
- if (!udev) {
+ _udev = udev_new();
+ if (!_udev) {
_E("Cannot create udev");
- return ret;
+ goto error;
}
- monitor = udev_monitor_new_from_netlink(udev, "udev");
- if (!monitor) {
+ _monitor = udev_monitor_new_from_netlink(_udev, "udev");
+ if (!_monitor) {
_E("Cannot create udev monitor");
- udev_unref(udev);
- return ret;
+ goto error;
}
- ret = udev_monitor_filter_add_match_subsystem_devtype(monitor, "gpio", NULL);
+ ret = udev_monitor_filter_add_match_subsystem_devtype(_monitor, "gpio", NULL);
if (ret < 0) {
_E("Failed to add monitor filter");
- goto out;
+ goto error;
}
- ret = udev_monitor_enable_receiving(monitor);
+ ret = udev_monitor_enable_receiving(_monitor);
if (ret < 0) {
_E("Failed to enable udev receiving");
- goto out;
+ goto error;
}
+ *udev = _udev;
+ *monitor = _monitor;
+
+ return 0;
+
+error:
+ udev_monitor_unref(_monitor);
+ udev_unref(_udev);
+ return ret;
+}
+
+static int __gpio_wait_for_udev(struct udev_monitor *monitor, int pin)
+{
+ struct udev_device *dev;
+ struct pollfd pfd;
+ char gpio_name[MAX_BUF_LEN];
+
pfd.fd = udev_monitor_get_fd(monitor);
pfd.events = POLLIN;
snprintf(gpio_name, MAX_BUF_LEN, "gpio%d", pin);
for (int cnt = 0; cnt < 10; cnt++) {
+ _D("poll iteration");
if (poll(&pfd, 1, 100) < 0) {
_E("Failed to watch udev monitor");
- goto out;
+ return -EIO;
}
dev = udev_monitor_receive_device(monitor);
if (dev) {
if (strcmp(udev_device_get_sysname(dev), gpio_name) == 0) {
_D("udev for %s is initialized", gpio_name);
- ret = 0;
- goto out;
+ udev_device_unref(dev);
+ return 0;
}
+ udev_device_unref(dev);
}
}
_E("Time out");
-out:
- udev_monitor_unref(monitor);
- udev_unref(udev);
-
- return ret;
+ return 0;
}
int peripheral_interface_gpio_export(int pin)
RETVM_IF(pin < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid gpio pin");
int ret;
- int fd;
+ int fd = -1;
int length;
char buf[MAX_BUF_LEN] = {0, };
+ struct udev *udev = NULL;
+ struct udev_monitor *monitor = NULL;
+
+ ret = __gpio_create_udev_monitor(&udev, &monitor);
+ if (ret != 0) {
+ _E("Failed to create udev monitor");
+ goto out;
+ };
fd = open("/sys/class/gpio/export", O_WRONLY);
- IF_ERROR_RETURN(fd < 0);
+ if (fd < 0) {
+ _E("open() failed: %m");
+ ret = PERIPHERAL_ERROR_IO_ERROR;
+ goto out;
+ }
length = snprintf(buf, MAX_BUF_LEN, "%d", pin);
ret = write(fd, buf, length);
- IF_ERROR_RETURN(ret != length, close(fd));
+ if (ret != length) {
+ _E("write() failed: %m");
+ ret = PERIPHERAL_ERROR_IO_ERROR;
+ goto out;
+ }
ret = close(fd);
- IF_ERROR_RETURN(ret != 0);
+ if (ret != 0) {
+ _E("close() failed: %m");
+ ret = PERIPHERAL_ERROR_IO_ERROR;
+ goto out;
+ }
- ret = __gpio_wait_for_udev(pin);
+ ret = __gpio_wait_for_udev(monitor, pin);
if (ret < 0) {
_E("device nodes are not writable");
- return PERIPHERAL_ERROR_IO_ERROR;
+ ret = PERIPHERAL_ERROR_IO_ERROR;
+ goto out;
}
- return PERIPHERAL_ERROR_NONE;
+out:
+ if (fd != -1)
+ close(fd);
+
+ udev_monitor_unref(monitor);
+ udev_unref(udev);
+
+ return ret;
}
int peripheral_interface_gpio_unexport(int pin)