diff options
author | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2021-05-11 14:27:05 +0200 |
---|---|---|
committer | Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> | 2022-09-12 20:57:24 +0200 |
commit | bfb241618d7932118f6461789d4d750fab6c9663 (patch) | |
tree | 6f4b246c1a79f65baeb40bdc54ea84b80cfb6e41 | |
parent | 0a33b35bc9e700ed8764c7b8c4b8fda7c8fce44e (diff) | |
download | hardware_replicant_libsamsung-ipc-patches-todo/sysfs-gpio-driver.tar.gz hardware_replicant_libsamsung-ipc-patches-todo/sysfs-gpio-driver.tar.bz2 hardware_replicant_libsamsung-ipc-patches-todo/sysfs-gpio-driver.zip |
Add sysfs gpio driverpatches-todo/sysfs-gpio-driver
Signed-off-by: Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
-rw-r--r-- | samsung-ipc/Makefile.am | 1 | ||||
-rw-r--r-- | samsung-ipc/drivers/Makefile.am | 6 | ||||
-rw-r--r-- | samsung-ipc/drivers/drivers.c | 47 | ||||
-rw-r--r-- | samsung-ipc/drivers/drivers.h | 44 | ||||
-rw-r--r-- | samsung-ipc/drivers/gpios/Makefile.am | 6 | ||||
-rw-r--r-- | samsung-ipc/drivers/gpios/gpios.c | 97 | ||||
-rw-r--r-- | samsung-ipc/drivers/gpios/gpios.h | 33 | ||||
-rw-r--r-- | samsung-ipc/drivers/gpios/sysfs/sysfs.c | 166 | ||||
-rw-r--r-- | samsung-ipc/drivers/gpios/sysfs/sysfs.h | 33 | ||||
-rw-r--r-- | samsung-ipc/ipc.c | 3 |
10 files changed, 436 insertions, 0 deletions
diff --git a/samsung-ipc/Makefile.am b/samsung-ipc/Makefile.am index 47484e5..dfbdf3d 100644 --- a/samsung-ipc/Makefile.am +++ b/samsung-ipc/Makefile.am @@ -40,6 +40,7 @@ libsamsung_ipc_la_SOURCES = \ $(NULL) include devices/Makefile.am +include drivers/Makefile.am include modems/Makefile.am include partitions/Makefile.am diff --git a/samsung-ipc/drivers/Makefile.am b/samsung-ipc/drivers/Makefile.am new file mode 100644 index 0000000..eee626e --- /dev/null +++ b/samsung-ipc/drivers/Makefile.am @@ -0,0 +1,6 @@ +libsamsung_ipc_la_SOURCES += \ + drivers/drivers.c \ + drivers/drivers.h \ + $(NULL) + +include drivers/gpios/Makefile.am diff --git a/samsung-ipc/drivers/drivers.c b/samsung-ipc/drivers/drivers.c new file mode 100644 index 0000000..f0d476e --- /dev/null +++ b/samsung-ipc/drivers/drivers.c @@ -0,0 +1,47 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stddef.h> + +#include <samsung-ipc.h> + +int drivers_probe(struct ipc_client *client, struct ipc_device_desc *ipc_device) +{ + if (client == NULL) + return -1; + + if (ipc_device == NULL){ + ipc_client_log(client, + "%s failed: ipc_device is NULL", __func__); + return -1; + } + + // TODO: replace with for loop that iterates over the drivers and pass + // to each probe() all the other drivers name somehow. + // If a better driver is available, the probe will exit in favor of the + // better driver. If the better driver fails it'll fallback to the older + // driver somehow. + // -EPROBE_DEFER could somehow be used for that. For instance: + // if better driver => defer + // then called again => return, don't init + probe_gpios(client, ipc_device); + + return 0; +} diff --git a/samsung-ipc/drivers/drivers.h b/samsung-ipc/drivers/drivers.h new file mode 100644 index 0000000..a82e4ee --- /dev/null +++ b/samsung-ipc/drivers/drivers.h @@ -0,0 +1,44 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __DRIVERS_H__ +#define __DRIVERS_H__ + +#include <samsung-ipc.h> + +#include "devices/ipc_devices.h" +#include "drivers/gpios/gpios.h" + +struct driver { + /* The name should be unique */ + char *name; + /* TODO: + * - Handle its internal state by passing stuff + * - Pass it the infos it needs to decide if it needs to load or not + */ + int (*probe)(struct ipc_client *client, + struct ipc_device_desc *ipc_device, + /* TODO: make it opaque */ + struct gpio_driver_ops **gpio_driver_ops); +}; + +/* TODO */ +int drivers_probe(struct ipc_client *client, struct ipc_device_desc *ipc_device); + +#endif /* __DRIVERS_H__ */ diff --git a/samsung-ipc/drivers/gpios/Makefile.am b/samsung-ipc/drivers/gpios/Makefile.am new file mode 100644 index 0000000..986a83f --- /dev/null +++ b/samsung-ipc/drivers/gpios/Makefile.am @@ -0,0 +1,6 @@ +libsamsung_ipc_la_SOURCES += \ + drivers/gpios/gpios.c \ + drivers/gpios/gpios.h \ + drivers/gpios/sysfs/sysfs.c \ + drivers/gpios/sysfs/sysfs.h \ + $(NULL) diff --git a/samsung-ipc/drivers/gpios/gpios.c b/samsung-ipc/drivers/gpios/gpios.c new file mode 100644 index 0000000..b025258 --- /dev/null +++ b/samsung-ipc/drivers/gpios/gpios.c @@ -0,0 +1,97 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdbool.h> +#include <stddef.h> + +#include <samsung-ipc.h> + +#include "devices/ipc_devices.h" +#include "drivers/gpios/sysfs/sysfs.h" + +#include "gpios.h" + +struct gpio_driver_ops *driver_ops; + +int gpio_export(struct ipc_client *client, unsigned gpio, bool direction) +{ + if (client == NULL) + return -1; + + if (!driver_ops) { + ipc_client_log(client, + "%s failed: driver_ops is NULL", __func__); + return -1; + } + + return driver_ops->export(client, gpio, direction); +} + +int gpio_get_value(struct ipc_client *client, unsigned gpio) +{ + if (client == NULL) + return -1; + + if (!driver_ops) { + ipc_client_log(client, + "%s failed: driver_ops is NULL", __func__); + return -1; + } + + return driver_ops->get_value(client, gpio); +} + +int gpio_set_value(struct ipc_client *client, unsigned gpio, bool value) +{ + if (client == NULL) + return -1; + + if (!driver_ops) { + ipc_client_log(client, + "%s failed: driver_ops is NULL", __func__); + return -1; + } + + return driver_ops->set_value(client, gpio, value); +} + +int probe_gpios(struct ipc_client *client, struct ipc_device_desc *ipc_device) +{ + if (client == NULL) + return -1; + + if (ipc_device == NULL){ + ipc_client_log(client, + "%s failed: ipc_device is NULL", __func__); + return -1; + } + + // TODO: replace with for loop that iterates over the drivers and pass + // to each probe() all the other drivers name somehow. + // If a better driver is available, the probe will exit in favor of the + // better driver. If the better driver fails it'll fallback to the older + // driver somehow. + // -EPROBE_DEFER could somehow be used for that. For instance: + // if better driver => defer + // then called again => return, don't init + // To do that a list of pointers in an elf section should be enough + probe_sysfs_gpio(client, ipc_device, &driver_ops); + + return 0; +} diff --git a/samsung-ipc/drivers/gpios/gpios.h b/samsung-ipc/drivers/gpios/gpios.h new file mode 100644 index 0000000..af31d2e --- /dev/null +++ b/samsung-ipc/drivers/gpios/gpios.h @@ -0,0 +1,33 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __GPIOS_H__ +#define __GPIOS_H__ + +#include "devices/ipc_devices.h" + +struct gpio_driver_ops { + int (*export)(struct ipc_client *client, unsigned gpio, bool direction); + int (*get_value)(struct ipc_client *client, unsigned gpio); + int (*set_value)(struct ipc_client *client, unsigned gpio, bool value); +}; + +int probe_gpios(struct ipc_client *client, struct ipc_device_desc *ipc_device); + +#endif /* __GPIOS_H__ */ diff --git a/samsung-ipc/drivers/gpios/sysfs/sysfs.c b/samsung-ipc/drivers/gpios/sysfs/sysfs.c new file mode 100644 index 0000000..609f276 --- /dev/null +++ b/samsung-ipc/drivers/gpios/sysfs/sysfs.c @@ -0,0 +1,166 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#define _GNU_SOURCE + +#include <errno.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include <samsung-ipc.h> + +#include "drivers/drivers.h" +#include "drivers/gpios/gpios.h" + +int sysfs_gpio_export(struct ipc_client *client, unsigned gpio, bool direction) +{ + char* sysfs_gpio_direction_path; + int rc = 0; + + rc = asprintf(&sysfs_gpio_direction_path, + "/sys/class/gpio/gpio%d/direction", gpio); + + if (rc == -1) { + ipc_client_log(client, + "%s: asprintf failed with error %d", + __func__, rc); + return -1; + } + + rc = sysfs_value_write("/sys/class/gpio/export", gpio); + if (rc == -1) { + ipc_client_log(client, + "%s: sysfs_value_write failed: " + "writing %d to %s failed with error %d", + __func__, gpio, "/sys/class/gpio/export", rc); + goto error; + } + + rc = sysfs_value_write(sysfs_gpio_direction_path, direction); + if (rc == -1) { + ipc_client_log(client, + "%s: sysfs_value_write failed: " + "writing %d to %s failed with error %d", + __func__, direction, sysfs_gpio_direction_path, + rc); + goto error; + } + +error: + free(sysfs_gpio_direction_path); + + return rc; +} + +int sysfs_gpio_get_value(struct ipc_client *client, unsigned gpio) +{ + char* sysfs_gpio_value_path; + int rc = 0; + + rc = asprintf(&sysfs_gpio_value_path, + "/sys/class/gpio/gpio%d/export", gpio); + if (rc == -1) { + ipc_client_log(client, + "%s: asprintf failed with error %d", + __func__, rc); + return -1; + } + + rc = sysfs_value_read(sysfs_gpio_value_path); + if (rc == -1) { + ipc_client_log(client, + "%s: sysfs_value_read failed: " + "reading from %s failed with error %d", + __func__, sysfs_gpio_value_path, + rc); + } + + free(sysfs_gpio_value_path); + + return rc; +} + +int sysfs_gpio_set_value(struct ipc_client *client, unsigned gpio, bool value) +{ + char* sysfs_gpio_value_path; + int rc = 0; + + rc = asprintf(&sysfs_gpio_value_path, + "/sys/class/gpio/gpio%d/export", gpio); + if (rc == -1) { + ipc_client_log(client, + "%s: asprintf failed with error %d", + __func__, rc); + return -1; + } + + rc = sysfs_value_write(sysfs_gpio_value_path, value); + if (rc == -1) { + ipc_client_log(client, + "%s: sysfs_value_write failed: " + "writing %d to %s failed with error %d", + __func__, value, sysfs_gpio_value_path, + rc); + goto error; + } + +error: + free(sysfs_gpio_value_path); + + return rc; +} + +struct gpio_driver_ops sysfs_gpio_ops = { + .export = sysfs_gpio_export, + .get_value = sysfs_gpio_get_value, + .set_value = sysfs_gpio_set_value, +}; + +int probe_sysfs_gpio(struct ipc_client *client, + struct ipc_device_desc *ipc_device, + struct gpio_driver_ops **gpio_driver_ops) +{ + int rc; + + /* TODO: + * - look at the other drivers and return -EPROBE_DEFER when + * another better driver will be tried and upron re-call + * bail out with an informative print message. + */ + + rc = access("/sys/class/gpio/export", W_OK); + if (rc == -1) { + rc = errno; + ipc_client_log(client, + "%s: testing %s access failed with error %d", + __func__, "/sys/class/gpio/export", rc); + return -rc; + } + + *gpio_driver_ops = &sysfs_gpio_ops; + + return 0; +} + +struct driver sysfs_driver = { + .name = "sysfs", + .probe = probe_sysfs_gpio, +}; diff --git a/samsung-ipc/drivers/gpios/sysfs/sysfs.h b/samsung-ipc/drivers/gpios/sysfs/sysfs.h new file mode 100644 index 0000000..f43fc38 --- /dev/null +++ b/samsung-ipc/drivers/gpios/sysfs/sysfs.h @@ -0,0 +1,33 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2021 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __SYSFS_GPIOS_H__ +#define __SYSFS_GPIOS_H__ + +#include "drivers/gpios/gpios.h" + +int sysfs_gpio_export(struct ipc_client *client, unsigned gpio, bool direction); +int sysfs_gpio_get_value(struct ipc_client *client, unsigned gpio); +int sysfs_gpio_set_value(struct ipc_client *client, unsigned gpio, bool value); + +int probe_sysfs_gpio(struct ipc_client *client, + struct ipc_device_desc *ipc_device, + struct gpio_driver_ops **gpio_driver_ops); + +#endif /* __SYSFS_GPIOS_H__ */ diff --git a/samsung-ipc/ipc.c b/samsung-ipc/ipc.c index c116fbb..4fe333c 100644 --- a/samsung-ipc/ipc.c +++ b/samsung-ipc/ipc.c @@ -40,6 +40,7 @@ #include "ipc.h" #include "devices/ipc_devices.h" +#include "drivers/drivers.h" int ipc_device_detect(void) { @@ -224,6 +225,8 @@ static struct ipc_client *ipc_transport_client_create(int type) sizeof(struct ipc_client_handlers)); } + drivers_probe(client, &ipc_devices[device_index]); + goto complete; error: |