Gpiopin.cpp

From RidgeRun Developer Connection
Jump to: navigation, search

gpioin.h

#ifndef GPIOPIN_H
#define GPIOPIN_H

#include <QObject>

class GpIoPin : public QObject{
        Q_OBJECT

        private:
                bool    _isOut;

                int             _ioFd;

                uint    _currentValue;
                uint    _pinNumber;

                int             exportPin();
                void    openFd();
                int             setDirection(bool out);

        public:
                explicit GpIoPin(uint pinNumber, bool isOut = true, QObject *parent = 0);
                ~GpIoPin();

                int     getValue(uint* value);

                int setEdge(char *edge);
                int setValue(uint value);

        signals:

        public slots:
};

#endif // GPIOPIN_H

gpioin.cpp

#include <fcntl.h>
#include <stdio.h>
#include <syslog.h>
#include <unistd.h>

#include "gpiopin.h"

#define MAX_BUF 64
#define SYSFS_GPIO_DIR "/sys/class/gpio"

void logError(QString methodName, int error){
        syslog(LOG_INFO, QString("gpio: %1 error: %2").arg(methodName.toLatin1().constData()).arg(error).toLatin1());
}

GpIoPin::GpIoPin(uint pinNumber, bool isOut, QObject *parent) : QObject(parent){
        _currentValue = 2;      // Make it out of range to force write if out pin
        _ioFd = -1;                                     // Make it invalid to force initial open
        _pinNumber = pinNumber;

        exportPin();
        setDirection(isOut);
}

GpIoPin::~GpIoPin(){
        if( 0 <= _ioFd ) close(_ioFd);
}

int GpIoPin::getValue(uint* value){
#ifdef __ARMEL__
        if( !_isOut ){
                if( 0 > _ioFd ) openFd();
                if( 0 > _ioFd ) return _ioFd;

                char ch;

                read(_ioFd, &ch, 1);

                if( ch != '0' ){
                        *value = 1;
                }else{
                        *value = 0;
                }

                _currentValue = *value;
        }
#endif

        return 0;
}

int GpIoPin::exportPin(){
#ifdef __ARMEL__
        int fd, len;
        char buf[MAX_BUF];

        fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY);
        if( fd < 0 ){
                logError("exportPin", fd);
                return fd;
        }

        len = qsnprintf(buf, sizeof(buf), "%d", _pinNumber);
        write(fd, buf, len);
        close(fd);
#endif

        return 0;
}

void GpIoPin::openFd(){
#ifdef __ARMEL__
        int len;
        char buf[MAX_BUF];

        len = qsnprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", _pinNumber);

        if( 0 <= _ioFd ) close(_ioFd );

        if( _isOut )
                _ioFd = open(buf, O_RDWR);
        else
                _ioFd = open(buf, O_RDONLY);

        if( 0 > _ioFd ){
                logError("openIoFd", _ioFd);
        }
#endif
}

int GpIoPin::setDirection(bool out){
#ifdef __ARMEL__
        int fd, len;
        char buf[MAX_BUF];

        len = qsnprintf(buf, sizeof(buf), SYSFS_GPIO_DIR  "/gpio%d/direction", _pinNumber);

        fd = open(buf, O_WRONLY);
        if( fd < 0 ){
                logError("setDirection", fd);
                return fd;
        }

        if( out ){
                write(fd, "out", 4);
        }else{
                write(fd, "in", 3);
        }

        close(fd);
#endif

        _isOut = out;

        return 0;
}

int GpIoPin::setEdge(char *edge){
#ifdef __ARMEL__
        int fd, len;
        char buf[MAX_BUF];

        len = qsnprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/edge", _pinNumber);

        fd = open(buf, O_WRONLY);
        if( fd < 0 ){
                logError("setEdge", fd);
                return fd;
        }

        write(fd, edge, strlen(edge) + 1);

        close(fd);
#endif

        return 0;
}

int GpIoPin::setValue(uint value){
#ifdef __ARMEL__
        if( _isOut && _currentValue != value ){
                if( 0 > _ioFd ) openFd();
                if( 0 > _ioFd ) return _ioFd;

                if( value ){
                        write(_ioFd, "1", 2);
                }else{
                        write(_ioFd, "0", 2);
                }

                _currentValue = value;
        }
#endif

        return 0;
}