mirror of
https://github.com/ElvishArtisan/rivendell.git
synced 2025-04-07 01:13:50 +02:00
* Added an 'RDMatrix::KernelGpio' element to the 'RDMatrix::Type enum. * Implemented a Kernel GPIO switcher driver in 'ripcd/kernelgpio.cpp' and 'ripcd/kernelgpio.h'.
218 lines
4.0 KiB
C++
218 lines
4.0 KiB
C++
// rdkernelgpio.cpp
|
|
//
|
|
// Control Class for the Linux SysFS GPIO Interface
|
|
//
|
|
// (C) Copyright 2017 Fred Gleason <fredg@paravelsystems.com>
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU Library General Public License
|
|
// version 2 as published by the Free Software Foundation.
|
|
//
|
|
// This program 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 this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//
|
|
|
|
#include "rdkernelgpio.h"
|
|
|
|
RDKernelGpio::RDKernelGpio(QObject *parent)
|
|
: QObject(parent)
|
|
{
|
|
gpio_poll_timer=new QTimer(this);
|
|
connect(gpio_poll_timer,SIGNAL(timeout()),this,SLOT(pollData()));
|
|
}
|
|
|
|
|
|
RDKernelGpio::~RDKernelGpio()
|
|
{
|
|
for(unsigned i=0;i<gpio_gpios.size();i++) {
|
|
removeGpio(gpio_gpios[i]);
|
|
}
|
|
delete gpio_poll_timer;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::addGpio(int gpio)
|
|
{
|
|
FILE *f=NULL;
|
|
|
|
for(unsigned i=0;i<gpio_gpios.size();i++) {
|
|
if(gpio==gpio_gpios[i]) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if((f=OpenNode("export","w"))==NULL) {
|
|
return false;
|
|
}
|
|
fprintf(f,"%u",gpio);
|
|
fclose(f);
|
|
gpio_gpios.push_back(gpio);
|
|
gpio_states.push_back(value(gpio));
|
|
|
|
if(gpio_gpios.size()==1) {
|
|
gpio_poll_timer->start(KERNELGPIO_POLL_INTERVAL);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::removeGpio(int gpio)
|
|
{
|
|
FILE *f=NULL;
|
|
|
|
if((f=OpenNode("unexport","w"))==NULL) {
|
|
return false;
|
|
}
|
|
fprintf(f,"%u",gpio);
|
|
fclose(f);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
RDKernelGpio::Direction RDKernelGpio::direction(int gpio,bool *ok) const
|
|
{
|
|
RDKernelGpio::Direction ret=RDKernelGpio::In;
|
|
FILE *f=NULL;
|
|
char str[255];
|
|
|
|
if((f=OpenNode("direction","r",gpio))!=NULL) {
|
|
fscanf(f,"%s",str);
|
|
if(QString(str)=="out") {
|
|
ret=RDKernelGpio::Out;
|
|
}
|
|
fclose(f);
|
|
if(ok!=NULL) {
|
|
*ok=true;
|
|
}
|
|
}
|
|
else {
|
|
if(ok!=NULL) {
|
|
*ok=false;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::setDirection(int gpio,RDKernelGpio::Direction dir) const
|
|
{
|
|
FILE *f=NULL;
|
|
|
|
if((f=OpenNode("direction","w",gpio))!=NULL) {
|
|
switch(dir) {
|
|
case RDKernelGpio::In:
|
|
fprintf(f,"in");
|
|
break;
|
|
|
|
case RDKernelGpio::Out:
|
|
fprintf(f,"out");
|
|
break;
|
|
}
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::activeLow(int gpio,bool *ok) const
|
|
{
|
|
unsigned ret=false;
|
|
FILE *f=NULL;
|
|
|
|
if((f=OpenNode("active_low","r",gpio))!=NULL) {
|
|
fscanf(f,"%u",&ret);
|
|
fclose(f);
|
|
if(ok!=NULL) {
|
|
*ok=true;
|
|
}
|
|
}
|
|
else {
|
|
if(ok!=NULL) {
|
|
*ok=false;
|
|
}
|
|
}
|
|
|
|
return (bool)ret;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::setActiveLow(int gpio,bool state) const
|
|
{
|
|
FILE *f=NULL;
|
|
|
|
if((f=OpenNode("active_low","w",gpio))!=NULL) {
|
|
fprintf(f,"%u",state);
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::value(int gpio,bool *ok) const
|
|
{
|
|
unsigned ret=false;
|
|
FILE *f=NULL;
|
|
|
|
if((f=OpenNode("value","r",gpio))!=NULL) {
|
|
fscanf(f,"%u",&ret);
|
|
fclose(f);
|
|
if(ok!=NULL) {
|
|
*ok=true;
|
|
}
|
|
}
|
|
else {
|
|
if(ok!=NULL) {
|
|
*ok=false;
|
|
}
|
|
}
|
|
|
|
return (bool)ret;
|
|
}
|
|
|
|
|
|
bool RDKernelGpio::setValue(int gpio,bool state) const
|
|
{
|
|
FILE *f=NULL;
|
|
|
|
if((f=OpenNode("value","w",gpio))!=NULL) {
|
|
fprintf(f,"%u",state);
|
|
fclose(f);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void RDKernelGpio::pollData()
|
|
{
|
|
bool state=false;
|
|
|
|
for(unsigned i=0;i<gpio_gpios.size();i++) {
|
|
if((state=value(gpio_gpios[i]))!=gpio_states[i]) {
|
|
gpio_states[i]=state;
|
|
emit valueChanged(gpio_gpios[i],state);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FILE *RDKernelGpio::OpenNode(const QString &name,const char *mode,int gpio) const
|
|
{
|
|
if(gpio<0) {
|
|
return fopen((KERNELGPIO_SYS_FILE+"/"+name),mode);
|
|
}
|
|
return fopen((KERNELGPIO_SYS_FILE+QString().sprintf("/gpio%d/",gpio)+name),
|
|
mode);
|
|
}
|