Module: xenomai-3
Branch: master
Commit: 15da7eeb46c9ff1a1bced18f4839cedafe05e907
URL:    
http://git.xenomai.org/?p=xenomai-3.git;a=commit;h=15da7eeb46c9ff1a1bced18f4839cedafe05e907

Author: Philippe Gerum <r...@xenomai.org>
Date:   Fri Feb 10 16:13:59 2017 +0100

drivers/gpio: do not require IRQEN for reading a pin

Reading a pin should only require to have set its direction to input
mode using the DIR_IN request, nothing beyond that.  IRQEN still
implicitly allows for reading a pin though.

---

 kernel/drivers/gpio/gpio-core.c |   29 ++++++++++++++++++++++++++---
 1 file changed, 26 insertions(+), 3 deletions(-)

diff --git a/kernel/drivers/gpio/gpio-core.c b/kernel/drivers/gpio/gpio-core.c
index c310a96..3acc555 100644
--- a/kernel/drivers/gpio/gpio-core.c
+++ b/kernel/drivers/gpio/gpio-core.c
@@ -34,7 +34,9 @@ struct rtdm_gpio_pin {
 };
 
 struct rtdm_gpio_chan {
-       bool requested;
+       int requested : 1,
+           has_direction : 1,
+           is_output : 1 ;
 };
 
 static int gpio_pin_interrupt(rtdm_irq_t *irqh)
@@ -77,6 +79,7 @@ static int request_gpio_irq(unsigned int gpio, struct 
rtdm_gpio_pin *pin,
                goto fail;
        }
 
+       chan->has_direction = true;
        gpio_export(gpio, true);
 
        rtdm_event_clear(&pin->event);
@@ -133,9 +136,15 @@ static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd,
                if (ret)
                        return ret;
                ret = gpio_direction_output(gpio, val);
+               if (ret == 0) {
+                       chan->has_direction = true;
+                       chan->is_output = true;
+               }
                break;
        case GPIO_RTIOC_DIR_IN:
                ret = gpio_direction_input(gpio);
+               if (ret == 0)
+                       chan->has_direction = true;
                break;
        case GPIO_RTIOC_IRQEN:
                if (chan->requested)
@@ -148,6 +157,7 @@ static int gpio_pin_ioctl_nrt(struct rtdm_fd *fd,
                break;
        case GPIO_RTIOC_IRQDIS:
                release_gpio_irq(gpio, pin, chan);
+               chan->requested = false;
                break;
        default:
                return -EINVAL;
@@ -167,9 +177,12 @@ static ssize_t gpio_pin_read_rt(struct rtdm_fd *fd,
        if (len < sizeof(value))
                return -EINVAL;
 
-       if (!chan->requested)
+       if (!chan->has_direction)
                return -EAGAIN;
 
+       if (chan->is_output)
+               return -EINVAL;
+
        pin = container_of(dev, struct rtdm_gpio_pin, dev);
 
        if (!(fd->oflags & O_NONBLOCK)) {
@@ -187,6 +200,7 @@ static ssize_t gpio_pin_read_rt(struct rtdm_fd *fd,
 static ssize_t gpio_pin_write_rt(struct rtdm_fd *fd,
                                 const void __user *buf, size_t len)
 {
+       struct rtdm_gpio_chan *chan = rtdm_fd_to_private(fd);
        struct rtdm_device *dev = rtdm_fd_device(fd);
        struct rtdm_gpio_pin *pin;
        int value, ret;
@@ -194,6 +208,12 @@ static ssize_t gpio_pin_write_rt(struct rtdm_fd *fd,
        if (len < sizeof(value))
                return -EINVAL;
 
+       if (!chan->has_direction)
+               return -EAGAIN;
+
+       if (!chan->is_output)
+               return -EINVAL;
+
        ret = rtdm_safe_copy_from_user(fd, &value, buf, sizeof(value));
        if (ret)
                return ret;
@@ -211,9 +231,12 @@ static int gpio_pin_select(struct rtdm_fd *fd, struct 
xnselector *selector,
        struct rtdm_device *dev = rtdm_fd_device(fd);
        struct rtdm_gpio_pin *pin;
 
-       if (!chan->requested)
+       if (!chan->has_direction)
                return -EAGAIN;
 
+       if (chan->is_output)
+               return -EINVAL;
+
        pin = container_of(dev, struct rtdm_gpio_pin, dev);
 
        return rtdm_event_select(&pin->event, selector, type, index);


_______________________________________________
Xenomai-git mailing list
Xenomai-git@xenomai.org
https://xenomai.org/mailman/listinfo/xenomai-git

Reply via email to