3
votes

I used to handle gpio in user space with /sys/class/gpio. Problem is that I need to use this gpio in a kernel driver. Due to the gpio request from the kernel driver, I cannot manipulate this gpio through /sys/class/gpio.

However I was able to use it through /dev/input/eventX after declaring my gpio as gpio keys in a device tree. Problem is that I can only get event with this interface (new status) but not initial one. So until the first event, I cannot know the current status of my gpio.

I tried to looking for over solution /sys/class/input/eventX and /sys/class/input/inputX without success.

More complete question available here : https://www.mail-archive.com/[email protected]/msg18588.html

Current dirty workaround that I used : Char device + ioctl

diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index 77d7b07..99df807 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -31,6 +31,16 @@
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
+#include <linux/cdev.h>
+#include <linux/uaccess.h>
+
+struct keys_dev {
+       struct cdev dev;
+       dev_t dev_no;
+       struct class *cl;
+};
+
+static struct keys_dev keys_inst;

 struct gpio_button_data {
        const struct gpio_keys_button *button;
@@ -55,6 +65,27 @@ struct gpio_keys_drvdata {
        struct gpio_button_data data[0];
 };

+
+#define KEYS_DEVICE_NAME "plug_status"
+#define GPIO_USB 1
+
+static long gpio_keys_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       int value = -1;
+       int err;
+
+       value = gpio_get_value (GPIO_USB);
+       value = !value;
+       err = copy_to_user((char*)arg, &value, sizeof(int));
+       return value;
+}
+
+static const struct file_operations gpio_keys_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = gpio_keys_ioctl,
+};
+
+
 /*
  * SYSFS interface for enabling/disabling keys and switches:
  *
@@ -851,11 +882,40 @@ static struct platform_driver gpio_keys_device_driver = {

 static int __init gpio_keys_init(void)
 {
+       int r;
+
+       r = alloc_chrdev_region(&keys_inst.dev_no , 0, 1, KEYS_DEVICE_NAME);
+       if (r < 0) {
+               printk(KERN_ERR "alloc_chrdev_region failed!\n");
+               return -ENOMEM;
+       }
+       keys_inst.cl = class_create(THIS_MODULE, KEYS_DEVICE_NAME);
+       if (keys_inst.cl == NULL) {
+               printk(KERN_ERR "Could not create class!\n");
+               return -ENOMEM;
+       }
+
+       if (device_create(keys_inst.cl, NULL, keys_inst.dev_no, NULL, KEYS_DEVICE_NAME) == NULL) {
+               printk(KERN_ERR "Could not create character device!\n");
+               return -ENOMEM;
+       }
+
+       cdev_init(&keys_inst.dev, &gpio_keys_fops );
+       r = cdev_add(&keys_inst.dev, keys_inst.dev_no, 1);
+       if (r < 0) {
+               printk(KERN_ERR "Could not add character device!\n");
+               return -ENOMEM;
+       }
+
        return platform_driver_register(&gpio_keys_device_driver);
 }

 static void __exit gpio_keys_exit(void)
 {
+
+       device_destroy(keys_inst.cl, keys_inst.dev_no);
+       class_destroy(keys_inst.cl);
+       unregister_chrdev_region(keys_inst.dev_no, 1);
        platform_driver_unregister(&gpio_keys_device_driver);
 }
1
It is not a bug or error of manipulation on export feature. this is completely normal. This is just because the gpio est already request by the kernel. I cannot use /sys/class/gpio. - ArthurLambert

1 Answers

0
votes

I read your other post as well. Not sure if this would work but perhaps you can dynamically load your gpio-keys.c driver as a loadable kernel module at run-time (via insmod or modprobe).

So, perhaps you can first boot into your system before loading your gpio-keys.ko into the kernel. So, at that point, you could first read your gpio to determine its inital value: cat /sys/class/gpio/gpio1/value. Then once determining that value, you can then insert your kernel module gpio-keys.ko into your kernel. Hopefully at that point, your gpio-keys become available and hence you could use them as interrupts to wake your board from suspend mode.