aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2021-05-11 14:27:05 +0200
committerDenis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>2022-09-12 20:57:24 +0200
commitbfb241618d7932118f6461789d4d750fab6c9663 (patch)
tree6f4b246c1a79f65baeb40bdc54ea84b80cfb6e41
parent0a33b35bc9e700ed8764c7b8c4b8fda7c8fce44e (diff)
downloadhardware_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.am1
-rw-r--r--samsung-ipc/drivers/Makefile.am6
-rw-r--r--samsung-ipc/drivers/drivers.c47
-rw-r--r--samsung-ipc/drivers/drivers.h44
-rw-r--r--samsung-ipc/drivers/gpios/Makefile.am6
-rw-r--r--samsung-ipc/drivers/gpios/gpios.c97
-rw-r--r--samsung-ipc/drivers/gpios/gpios.h33
-rw-r--r--samsung-ipc/drivers/gpios/sysfs/sysfs.c166
-rw-r--r--samsung-ipc/drivers/gpios/sysfs/sysfs.h33
-rw-r--r--samsung-ipc/ipc.c3
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: