ENDIF()
SET(SOURCES src/peripheral_gpio.c
+ src/peripheral_gpio_legacy_api.c
src/peripheral_i2c.c
src/peripheral_pwm.c
src/peripheral_adc.c
return -1;
}
+static inline void cleanup_fd(int *fd) {
+ close_fd(*fd);
+ *fd = -1;
+}
+
#define PERIPHERAL_FEATURE_UNKNOWN -1
#define PERIPHERAL_FEATURE_FALSE 0
#define PERIPHERAL_FEATURE_TRUE 1
#include <unistd.h>
#include "peripheral_io.h"
+#include "peripheral_gpio_legacy_api.h"
#include "common.h"
#include "log.h"
FEATURE("http://tizen.org/feature/peripheral_io.gpio")
-/* Path format for device file */
-#define DEV_PATH_BASE(pin, file) ("/sys/class/gpio/gpio" pin "/" file)
-/* direction is the longest file name of all accesses in the device directory.
- The other are: edge and value.
- */
-#define DEV_PATH_FMT_MAX_SIZE sizeof(DEV_PATH_BASE(MAX_d_FMT, "direction"))
-#define DEV_PATH_FMT(file) DEV_PATH_BASE("%d", file)
-
-/* Format for gpio name */
-#define GPIO_NAME_BASE "gpio"
-#define GPIO_NAME_FMT_MAX_SIZE sizeof(GPIO_NAME_BASE MAX_d_FMT)
-#define GPIO_NAME_FMT (GPIO_NAME_BASE "%d")
-
#define GPIO_STRUCTURE_VERMAGIC 13712
#define GPIO_CALLBACK_STRUCTURE_VERMAGIC 14469
#define GPIO_INTERRUPTED_CALLBACK_CHECK_SET_INTERVAL_MILISECONDS 3000
-#define GPIO_BUFFER_MAX 64
-
typedef struct _peripheral_gpio_interrupted_cb_info_s {
// vermagic value is used to verify structure inside csapi
// do not move it and value field to different place inside structure
// otherwise update csapi accordingly
int vermagic;
interrupted_cb_info_s cb_info;
- int pin;
- int fd_direction;
- int fd_edge;
- int fd_value;
+ struct gpio_legacy_data legacy_data;
peripheral_gpio_direction_e direction;
peripheral_gpio_edge_e edge;
};
-#define GPIO_BASE "gpio"
-
-typedef struct FilterData {
- char gpio_name[GPIO_NAME_FMT_MAX_SIZE];
-} FilterData;
-
-static bool __filter_device(struct udev_device *device, void *data)
-{
- FilterData *filter = data;
-
- if (strcmp(udev_device_get_sysname(device), filter->gpio_name) == 0) {
- _D("udev for %s is initialized", filter->gpio_name);
- return true;
- }
- return false;
-}
-
-static int peripheral_gpio_export(int pin)
-{
- RETVM_IF(pin < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid gpio pin");
-
- int ret;
- struct udev *udev = NULL;
- struct udev_monitor *monitor = NULL;
-
- ret = peripheral_create_udev_monitor(&udev, &monitor, "gpio");
- if (ret != 0) {
- _E("Failed to create udev monitor");
- ret = PERIPHERAL_ERROR_IO_ERROR;
- goto out;
- };
-
- ret = peripheral_write_pin_to_file("/sys/class/gpio/export", pin);
- if (ret != 0) {
- /* If export fails with EBUSY, then it means
- this pin has been already exported.
- That's fine for us.
- */
- if (ret != EBUSY) {
- _E("gpio: export pin %d: failed with error %d", pin, ret);
- goto out;
- }
- }
-
- FilterData filter;
- snprintf(filter.gpio_name, sizeof filter.gpio_name, GPIO_NAME_FMT, pin);
-
- ret = peripheral_wait_for_udev(monitor, __filter_device, &filter);
- if (ret < 0) {
- _E("device nodes are not writable");
- ret = PERIPHERAL_ERROR_IO_ERROR;
- goto out;
- }
-
-out:
- udev_monitor_unref(monitor);
- udev_unref(udev);
-
- return ret;
-}
-
-static int peripheral_gpio_lock_export(void)
-{
- return peripheral_lock("/sys/class/gpio/export");
-}
-
-static inline int cleanup_handle(peripheral_gpio_h handle) {
- if (handle == NULL)
- return PERIPHERAL_ERROR_NONE;
-
- __attribute__ ((cleanup(peripheral_unlockp))) int lock = peripheral_gpio_lock_export();
- int pin = handle->pin;
-
- close_fd(handle->fd_edge);
- close_fd(handle->fd_value);
- close_fd(handle->fd_direction); /* this also closes pin flock() */
- free(handle);
-
- if (pin < 0)
- return PERIPHERAL_ERROR_NONE;
-
- int ret = peripheral_write_pin_to_file("/sys/class/gpio/unexport", pin);
- if (ret != 0) {
- _E("gpio: unexport pin %d: failed with error %d", pin, ret);
- return PERIPHERAL_ERROR_IO_ERROR;
- }
-
- return PERIPHERAL_ERROR_NONE;
-}
-
-static inline void cleanup_handlep(peripheral_gpio_h *handle) {
- cleanup_handle(*handle);
-}
-
-static int peripheral_gpio_set_initial_direction_into_handle(peripheral_gpio_h gpio)
-{
- static predefined_type_s types[2] = {
- {"in", 2},
- {"out", 3},
- };
-
- char gpio_buf[GPIO_BUFFER_MAX] = {0, };
-
- int ret = read(gpio->fd_direction, &gpio_buf, sizeof gpio_buf);
- CHECK_ERROR(ret <= 0);
-
- for (size_t index = 0; index < ARRAY_SIZE(types); index++) {
- if (strncmp(gpio_buf, types[index].type, types[index].len))
- continue;
-
- // PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGH and PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW : out type
- gpio->direction = (peripheral_gpio_direction_e)index;
-
- /*
- * Also write to direction for the very first time after boot
- * to ensure that the pin is fully initialized.
- * Without this, writing to 'edge' is not possible.
- */
- ret = write(gpio->fd_direction, types[index].type, types[index].len);
- CHECK_ERROR(ret != types[index].len);
-
- return PERIPHERAL_ERROR_NONE;
- }
-
- return PERIPHERAL_ERROR_IO_ERROR;
-}
-
-static int peripheral_gpio_set_initial_edge_into_handle(peripheral_gpio_h gpio)
-{
- static const predefined_type_s types[4] = {
- {"none", 4},
- {"rising", 6},
- {"falling", 7},
- {"both", 4}
- };
-
- char gpio_buf[GPIO_BUFFER_MAX] = {0, };
-
- int ret = read(gpio->fd_edge, &gpio_buf, sizeof gpio_buf);
- CHECK_ERROR(ret <= 0);
-
- for (size_t index = 0; index < ARRAY_SIZE(types); index++) {
- if (strncmp(gpio_buf, types[index].type, types[index].len))
- continue;
-
- gpio->edge = (peripheral_gpio_edge_e)index;
- return PERIPHERAL_ERROR_NONE;
- }
-
- return PERIPHERAL_ERROR_IO_ERROR;
+static inline void free_gpio(peripheral_gpio_h *handle) {
+ /* NB: This is, on purpose, *not* peripheral_gpio_close.
+ * This is because this function is only used as a cleanup function in peripheral_gpio_open,
+ * where most of the structure is not initialized yet and we just want to free the memory. */
+ free(*handle);
+ *handle = NULL;
}
/**
RETVM_IF(gpio_pin < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid gpio pin number");
/* Initialize */
- __attribute__ ((cleanup(cleanup_handlep))) peripheral_gpio_h handle = (peripheral_gpio_h)calloc(1, sizeof *handle);
+ __attribute__ ((cleanup(free_gpio))) peripheral_gpio_h handle = (peripheral_gpio_h)calloc(1, sizeof *handle);
if (handle == NULL) {
_E("Failed to allocate peripheral_gpio_h");
return PERIPHERAL_ERROR_OUT_OF_MEMORY;
// set gpio_s_vermagic and callback vermagic so csapi can verify structure
handle->vermagic = GPIO_STRUCTURE_VERMAGIC;
handle->cb_info.vermagic = GPIO_CALLBACK_STRUCTURE_VERMAGIC;
- handle->fd_direction = -1;
- handle->fd_edge = -1;
- handle->fd_value = -1;
- handle->pin = -1;
-
- __attribute__ ((cleanup(peripheral_unlockp))) int lock = peripheral_gpio_lock_export();
- RETVM_IF(lock == -1, PERIPHERAL_ERROR_IO_ERROR, "Failed to lock 'export'");
- ret = peripheral_gpio_export(gpio_pin);
- RETVM_IF(ret != 0, PERIPHERAL_ERROR_IO_ERROR, "Failed to export the gpio pin, ret : %d", ret);
-
- handle->pin = gpio_pin;
-
- /* space for /sys/class/gpio/gpio%d/direction,
- which is larger than /sys/class/gpio/gpio%d/edge and /sys/class/gpio/gpio%d/value
- */
- char path[DEV_PATH_FMT_MAX_SIZE] = {0, };
- snprintf(path, sizeof path, DEV_PATH_FMT("direction"), handle->pin);
- handle->fd_direction = open(path, O_RDWR | O_CLOEXEC);
- CHECK_ERROR(handle->fd_direction < 0);
+ handle->cb_info.thread = NULL;
- TRY_FLOCK(ret, handle->fd_direction, LOCK_EX | LOCK_NB, "gpio pin %d", gpio_pin);
+ ret = gpio_legacy_open(&handle->legacy_data, gpio_pin, &handle->direction, &handle->edge);
CHECK_ERROR(ret != PERIPHERAL_ERROR_NONE);
- snprintf(path, sizeof path, DEV_PATH_FMT("edge"), handle->pin);
- handle->fd_edge = open(path, O_RDWR | O_CLOEXEC);
- CHECK_ERROR(handle->fd_edge < 0);
-
- snprintf(path, sizeof path, DEV_PATH_FMT("value"), handle->pin);
- handle->fd_value = open(path, O_RDWR | O_CLOEXEC);
- CHECK_ERROR(handle->fd_value < 0);
-
- lock = peripheral_unlock(lock);
-
- ret = peripheral_gpio_set_initial_direction_into_handle(handle);
- if (ret != PERIPHERAL_ERROR_NONE) {
- _E("Failed to peripheral_gpio_set_initial_direction_into_handle()");
- return ret;
- }
-
- ret = peripheral_gpio_set_initial_edge_into_handle(handle);
- if (ret != PERIPHERAL_ERROR_NONE) {
- _E("Failed to peripheral_gpio_set_initial_edge_into_handle()");
- return ret;
- }
-
- handle->cb_info.thread = NULL;
*gpio = handle;
handle = NULL;
peripheral_gpio_unset_interrupted_cb(gpio);
- cleanup_handlep(&gpio);
+ int ret = gpio_legacy_cleanup(&gpio->legacy_data);
- return PERIPHERAL_ERROR_NONE;
+ free(gpio);
+
+ return ret;
}
/**
RETVM_IF(gpio->cb_info.status != GPIO_INTERRUPTED_CALLBACK_UNSET, PERIPHERAL_ERROR_IO_ERROR,
"Can't change direction to OUT while 'interrupted_cb' is set");
- static const predefined_type_s types[3] = {
- {"in", 2},
- {"high", 4},
- {"low", 3}
- };
-
- int ret = write(gpio->fd_direction, types[direction].type, types[direction].len);
- CHECK_ERROR(ret != types[direction].len);
+ int ret = gpio_legacy_set_direction(&gpio->legacy_data, direction);
+ if (ret != PERIPHERAL_ERROR_NONE)
+ return ret;
gpio->direction = direction;
-
return PERIPHERAL_ERROR_NONE;
}
RETV_IF(gpio->edge == edge, PERIPHERAL_ERROR_NONE);
RETV_IF(gpio->direction != PERIPHERAL_GPIO_DIRECTION_IN, PERIPHERAL_ERROR_IO_ERROR);
- static const predefined_type_s types[4] = {
- {"none", 4},
- {"rising", 6},
- {"falling", 7},
- {"both", 4}
- };
-
- int ret = write(gpio->fd_edge, types[edge].type, types[edge].len);
- CHECK_ERROR(ret != types[edge].len);
+ int ret = gpio_legacy_set_edge_mode(&gpio->legacy_data, edge);
+ if (ret != PERIPHERAL_ERROR_NONE)
+ return ret;
gpio->edge = edge;
-
return PERIPHERAL_ERROR_NONE;
}
struct pollfd poll_fd;
- poll_fd.fd = gpio->fd_value;
+ poll_fd.fd = gpio_legacy_get_poll_fd(&gpio->legacy_data);
poll_fd.events = POLLPRI;
uint32_t value;
* in ---------> read (O)
* out --------> read (O)
*/
- int ret;
- int length = 1;
- char gpio_buf[GPIO_BUFFER_MAX] = {0, };
-
- ret = pread(gpio->fd_value, &gpio_buf, length, 0);
- CHECK_ERROR(ret != length);
-
- if (gpio_buf[0] == '0') {
- *value = 0;
- } else if (gpio_buf[0] == '1') {
- *value = 1;
- } else {
- _E("Error: gpio value is error \n");
- return PERIPHERAL_ERROR_IO_ERROR;
- }
- return PERIPHERAL_ERROR_NONE;
+ return gpio_legacy_read(&gpio->legacy_data, value);
}
/**
*/
RETV_IF(gpio->direction == PERIPHERAL_GPIO_DIRECTION_IN, PERIPHERAL_ERROR_IO_ERROR);
- static const predefined_type_s types[2] = {
- {"0", 1},
- {"1", 1}
- };
-
- int ret = write(gpio->fd_value, types[value].type, types[value].len);
- CHECK_ERROR(ret != types[value].len);
-
- return PERIPHERAL_ERROR_NONE;
+ return gpio_legacy_write(&gpio->legacy_data, value);
}
--- /dev/null
+/*
+ * Copyright (c) 2016-2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <glib.h>
+#include <libudev.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/file.h>
+#include <unistd.h>
+
+#include "peripheral_io.h"
+#include "peripheral_gpio_legacy_api.h"
+#include "common.h"
+#include "log.h"
+
+/* Path format for device file */
+#define DEV_PATH_BASE(pin, file) ("/sys/class/gpio/gpio" pin "/" file)
+/* direction is the longest file name of all accesses in the device directory.
+ The other are: edge and value.
+ */
+#define DEV_PATH_FMT_MAX_SIZE sizeof(DEV_PATH_BASE(MAX_d_FMT, "direction"))
+#define DEV_PATH_FMT(file) DEV_PATH_BASE("%d", file)
+
+/* Format for gpio name */
+#define GPIO_NAME_BASE "gpio"
+#define GPIO_NAME_FMT_MAX_SIZE sizeof(GPIO_NAME_BASE MAX_d_FMT)
+#define GPIO_NAME_FMT (GPIO_NAME_BASE "%d")
+
+#define GPIO_BUFFER_MAX 64
+
+#define GPIO_BASE "gpio"
+
+typedef struct FilterData {
+ char gpio_name[GPIO_NAME_FMT_MAX_SIZE];
+} FilterData;
+
+static bool __filter_device(struct udev_device *device, void *data)
+{
+ assert(device);
+ assert(data);
+
+ FilterData *filter = data;
+
+ if (strcmp(udev_device_get_sysname(device), filter->gpio_name) == 0) {
+ _D("udev for %s is initialized", filter->gpio_name);
+ return true;
+ }
+ return false;
+}
+
+static int gpio_legacy_export(int pin)
+{
+ RETVM_IF(pin < 0, PERIPHERAL_ERROR_INVALID_PARAMETER, "Invalid gpio pin");
+
+ int ret;
+ struct udev *udev = NULL;
+ struct udev_monitor *monitor = NULL;
+
+ ret = peripheral_create_udev_monitor(&udev, &monitor, "gpio");
+ if (ret != 0) {
+ _E("Failed to create udev monitor");
+ ret = PERIPHERAL_ERROR_IO_ERROR;
+ goto out;
+ };
+
+ ret = peripheral_write_pin_to_file("/sys/class/gpio/export", pin);
+ if (ret != 0) {
+ /* If export fails with EBUSY, then it means
+ this pin has been already exported.
+ That's fine for us.
+ */
+ if (ret != EBUSY) {
+ _E("gpio: export pin %d: failed with error %d", pin, ret);
+ goto out;
+ }
+ }
+
+ FilterData filter;
+ snprintf(filter.gpio_name, sizeof filter.gpio_name, GPIO_NAME_FMT, pin);
+
+ ret = peripheral_wait_for_udev(monitor, __filter_device, &filter);
+ if (ret < 0) {
+ _E("device nodes are not writable");
+ ret = PERIPHERAL_ERROR_IO_ERROR;
+ goto out;
+ }
+
+out:
+ udev_monitor_unref(monitor);
+ udev_unref(udev);
+
+ return ret;
+}
+
+static int gpio_legacy_lock_export(void)
+{
+ return peripheral_lock("/sys/class/gpio/export");
+}
+
+int gpio_legacy_cleanup(struct gpio_legacy_data *ldata)
+{
+ assert(ldata);
+
+ __attribute__ ((cleanup(peripheral_unlockp))) int lock = gpio_legacy_lock_export();
+ int pin = ldata->pin;
+
+ close_fd(ldata->fd_edge);
+ close_fd(ldata->fd_value);
+ close_fd(ldata->fd_direction); /* this also closes pin flock() */
+
+ if (pin < 0)
+ return PERIPHERAL_ERROR_NONE;
+
+ int ret = peripheral_write_pin_to_file("/sys/class/gpio/unexport", pin);
+ if (ret != 0) {
+ _E("gpio: unexport pin %d: failed with error %d", pin, ret);
+ return PERIPHERAL_ERROR_IO_ERROR;
+ }
+
+ return PERIPHERAL_ERROR_NONE;
+}
+
+static int gpio_legacy_set_initial_direction_into_handle(int fd_direction, peripheral_gpio_direction_e *direction_out)
+{
+ assert(direction_out);
+
+ static predefined_type_s types[2] = {
+ {"in", 2},
+ {"out", 3},
+ };
+
+ char gpio_buf[GPIO_BUFFER_MAX] = {0, };
+
+ int ret = read(fd_direction, &gpio_buf, sizeof gpio_buf);
+ CHECK_ERROR(ret <= 0);
+
+ for (size_t index = 0; index < ARRAY_SIZE(types); index++) {
+ if (strncmp(gpio_buf, types[index].type, types[index].len))
+ continue;
+
+ // PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_HIGH and PERIPHERAL_GPIO_DIRECTION_OUT_INITIALLY_LOW : out type
+ *direction_out = (peripheral_gpio_direction_e)index;
+
+ /*
+ * Also write to direction for the very first time after boot
+ * to ensure that the pin is fully initialized.
+ * Without this, writing to 'edge' is not possible.
+ */
+ ret = write(fd_direction, types[index].type, types[index].len);
+ CHECK_ERROR(ret != types[index].len);
+
+ return PERIPHERAL_ERROR_NONE;
+ }
+
+ return PERIPHERAL_ERROR_IO_ERROR;
+}
+
+static int gpio_legacy_set_initial_edge_into_handle(int fd_edge, peripheral_gpio_edge_e *edge_out)
+{
+ assert(edge_out);
+
+ static const predefined_type_s types[4] = {
+ {"none", 4},
+ {"rising", 6},
+ {"falling", 7},
+ {"both", 4}
+ };
+
+ char gpio_buf[GPIO_BUFFER_MAX] = {0, };
+
+ int ret = read(fd_edge, &gpio_buf, sizeof gpio_buf);
+ CHECK_ERROR(ret <= 0);
+
+ for (size_t index = 0; index < ARRAY_SIZE(types); index++) {
+ if (strncmp(gpio_buf, types[index].type, types[index].len))
+ continue;
+
+ *edge_out = (peripheral_gpio_edge_e)index;
+ return PERIPHERAL_ERROR_NONE;
+ }
+
+ return PERIPHERAL_ERROR_IO_ERROR;
+}
+
+int gpio_legacy_open(struct gpio_legacy_data *ldata, int gpio_pin, peripheral_gpio_direction_e *direction_out, peripheral_gpio_edge_e *edge_out)
+{
+ assert(ldata);
+ assert(direction_out);
+ assert(edge_out);
+
+ int ret = PERIPHERAL_ERROR_NONE;
+
+ __attribute__((cleanup(cleanup_fd))) int fd_direction = -1;
+ __attribute__((cleanup(cleanup_fd))) int fd_edge = -1;
+ __attribute__((cleanup(cleanup_fd))) int fd_value = -1;
+
+ __attribute__ ((cleanup(peripheral_unlockp))) int lock = gpio_legacy_lock_export();
+ RETVM_IF(lock == -1, PERIPHERAL_ERROR_IO_ERROR, "Failed to lock 'export'");
+
+ ret = gpio_legacy_export(gpio_pin);
+ RETVM_IF(ret != 0, PERIPHERAL_ERROR_IO_ERROR, "Failed to export the gpio pin, ret : %d", ret);
+
+ /* space for /sys/class/gpio/gpio%d/direction,
+ which is larger than /sys/class/gpio/gpio%d/edge and /sys/class/gpio/gpio%d/value
+ */
+ char path[DEV_PATH_FMT_MAX_SIZE] = {0, };
+ snprintf(path, sizeof path, DEV_PATH_FMT("direction"), gpio_pin);
+ fd_direction = open(path, O_RDWR | O_CLOEXEC);
+ CHECK_ERROR(fd_direction < 0);
+
+ TRY_FLOCK(ret, fd_direction, LOCK_EX | LOCK_NB, "gpio pin %d", gpio_pin);
+ CHECK_ERROR(ret != PERIPHERAL_ERROR_NONE);
+
+ snprintf(path, sizeof path, DEV_PATH_FMT("edge"), gpio_pin);
+ fd_edge = open(path, O_RDWR | O_CLOEXEC);
+ CHECK_ERROR(fd_edge < 0);
+
+ snprintf(path, sizeof path, DEV_PATH_FMT("value"), gpio_pin);
+ fd_value = open(path, O_RDWR | O_CLOEXEC);
+ CHECK_ERROR(fd_value < 0);
+
+ lock = peripheral_unlock(lock);
+
+ ret = gpio_legacy_set_initial_direction_into_handle(fd_direction, direction_out);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("Failed to gpio_legacy_set_initial_direction_into_data()");
+ return ret;
+ }
+
+ ret = gpio_legacy_set_initial_edge_into_handle(fd_edge, edge_out);
+ if (ret != PERIPHERAL_ERROR_NONE) {
+ _E("Failed to gpio_legacy_set_initial_edge_into_data()");
+ return ret;
+ }
+
+ ldata->fd_direction = fd_direction;
+ ldata->fd_edge = fd_edge;
+ ldata->fd_value = fd_value;
+ ldata->pin = gpio_pin;
+
+ fd_direction = -1;
+ fd_edge = -1;
+ fd_value = -1;
+
+ return PERIPHERAL_ERROR_NONE;
+}
+
+int gpio_legacy_set_direction(struct gpio_legacy_data *ldata, peripheral_gpio_direction_e direction)
+{
+ assert(ldata);
+
+ static const predefined_type_s types[3] = {
+ {"in", 2},
+ {"high", 4},
+ {"low", 3}
+ };
+
+ int ret = write(ldata->fd_direction, types[direction].type, types[direction].len);
+ CHECK_ERROR(ret != types[direction].len);
+
+ return PERIPHERAL_ERROR_NONE;
+}
+
+int gpio_legacy_set_edge_mode(struct gpio_legacy_data *ldata, peripheral_gpio_edge_e edge)
+{
+ assert(ldata);
+
+ static const predefined_type_s types[4] = {
+ {"none", 4},
+ {"rising", 6},
+ {"falling", 7},
+ {"both", 4}
+ };
+
+ int ret = write(ldata->fd_edge, types[edge].type, types[edge].len);
+ CHECK_ERROR(ret != types[edge].len);
+
+ return PERIPHERAL_ERROR_NONE;
+}
+
+int gpio_legacy_read(struct gpio_legacy_data *ldata, uint32_t *value)
+{
+ assert(ldata);
+ assert(value);
+
+ int ret;
+ int length = 1;
+ char gpio_buf[GPIO_BUFFER_MAX] = {0, };
+
+ ret = pread(ldata->fd_value, &gpio_buf, length, 0);
+ CHECK_ERROR(ret != length);
+
+ if (gpio_buf[0] == '0') {
+ *value = 0;
+ } else if (gpio_buf[0] == '1') {
+ *value = 1;
+ } else {
+ _E("Error: gpio value is error \n");
+ return PERIPHERAL_ERROR_IO_ERROR;
+ }
+
+ return PERIPHERAL_ERROR_NONE;
+}
+
+int gpio_legacy_write(struct gpio_legacy_data *ldata, uint32_t value)
+{
+ assert(ldata);
+
+ static const predefined_type_s types[2] = {
+ {"0", 1},
+ {"1", 1}
+ };
+
+ int ret = write(ldata->fd_value, types[value].type, types[value].len);
+ CHECK_ERROR(ret != types[value].len);
+
+ return PERIPHERAL_ERROR_NONE;
+}
+
+int gpio_legacy_get_poll_fd(struct gpio_legacy_data *ldata)
+{
+ assert(ldata);
+
+ return ldata->fd_value;
+}
--- /dev/null
+/*
+ * Copyright (c) 2016-2021 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "peripheral_io.h"
+
+/* NB: This struct should really be an opaque one, i.e. should be defined
+ * in the corresponding .c file instead and should be only used elsewhere
+ * via the functions defined below. Alas, in _peripheral_gpio_s, we want
+ * to have an instance of this struct as a field. If this struct were opaque,
+ * we could only put an ugly pointer there. */
+struct gpio_legacy_data {
+ int pin;
+ int fd_direction;
+ int fd_edge;
+ int fd_value;
+};
+
+int gpio_legacy_open(struct gpio_legacy_data *ldata, int gpio_pin, peripheral_gpio_direction_e *direction_out, peripheral_gpio_edge_e *edge_out);
+int gpio_legacy_read(struct gpio_legacy_data *ldata, uint32_t *value);
+int gpio_legacy_write(struct gpio_legacy_data *ldata, uint32_t value);
+int gpio_legacy_set_direction(struct gpio_legacy_data *ldata, peripheral_gpio_direction_e direction);
+int gpio_legacy_set_edge_mode(struct gpio_legacy_data *ldata, peripheral_gpio_edge_e edge);
+int gpio_legacy_cleanup(struct gpio_legacy_data *ldata);
+int gpio_legacy_get_poll_fd(struct gpio_legacy_data *ldata);