//=========================================================================// // // // PonyProg - Serial Device Programmer // // // // Copyright (C) 1997-2020 Claudio Lanconelli // // // // http://ponyprog.sourceforge.net // // // //-------------------------------------------------------------------------// // // // This program 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 version2 of // // the License, or (at your option) any later version. // // // // 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 (see LICENSE); if not, write to the // // Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // // // //=========================================================================// // Linux SysFS IO (useful on raspberry and embedded PC) #include "linuxsysfsint.h" #include "errcode.h" #include "e2cmdw.h" #include #include #include #include #define GPIO_OUT true #define GPIO_IN false #ifdef Q_OS_LINUX # include # include # include #endif LinuxSysFsInterface::LinuxSysFsInterface() { //qDebug() << "LinuxSysFsInterface::LinuxSysFsInterface()"; //DeInstall(); //old_portno = GetInstalled(); fd_ctrl = fd_clock = fd_datain = fd_dataout = -1; } LinuxSysFsInterface::~LinuxSysFsInterface() { Close(); } #ifdef Q_OS_LINUX #define SYSFS_GPIO_DIR "/sys/class/gpio" #define MAX_BUF 64 static int gpio_open(unsigned int gpio, bool out_dir) { // char buf[MAX_BUF]; QString buf; int rval; //trying with gpio command (you need wiringPi installed) buf.sprintf("export %u %s", gpio, out_dir ? "out" : "in"); // rval = system(buf.toLatin1().data()); rval = QProcess::execute("gpio", buf.split(" ")); if (rval != 0) { int fd; fd = open(SYSFS_GPIO_DIR "/export", O_WRONLY); if (fd < 0) { qWarning("Unable to open GPIO export interface: %s\n", strerror(errno)); rval = -1; } else { int ret, len; buf = QString::number(gpio); len = buf.length(); ret = write(fd, buf.toLatin1().data(), len); close(fd); rval = (ret == len) ? 0 : -1; } if (rval == 0) { buf.sprintf("%s/gpio%d/direction", SYSFS_GPIO_DIR, gpio); fd = open(buf.toLatin1().data(), O_WRONLY); if (fd < 0) { qWarning("Unable to open GPIO direction interface: %s\n", strerror(errno)); rval = -1; } else { int ret, len; if (out_dir) { buf = "out"; } else { buf = "in"; } len = buf.length(); ret = write(fd, buf.toLatin1().constData(), len); close(fd); rval = (ret == len) ? 0 : -1; } } } //open the value interace if (rval == 0) { int fd; buf.sprintf("%s/gpio%d/value", SYSFS_GPIO_DIR, gpio); fd = open(buf.toLatin1().data(), out_dir ? O_WRONLY : O_RDONLY); if (fd < 0) { qWarning("Unable to open GPIO set-value interface: %s\n", strerror(errno)); rval = -1; } else { rval = fd; } } qDebug() << "gpio_open(" << gpio << ", " << (out_dir ? "out" : "in") << ") rval = " << rval; return rval; } static int gpio_close(unsigned int gpio, int fd) { // char buf[MAX_BUF]; QString buf; int rval = 0; //close value interface if (fd > 0) { close(fd); } //trying with gpio command (you need wiringPi installed) buf.sprintf("unexport %u", gpio); // rval = system(buf.toLatin1().data()); rval = QProcess::execute("gpio", buf.split(" ")); if (rval != 0) { fd = open(SYSFS_GPIO_DIR "/unexport", O_WRONLY); if (fd < 0) { qWarning("Unable to open GPIO unexport interface: %s\n", strerror(errno)); rval = -1; } else { int ret, len; buf = QString().number(gpio); len = buf.length(); ret = write(fd, buf.toLatin1().data(), len); close(fd); rval = (ret == len) ? 0 : -1; } } qDebug() << "gpio_close(" << gpio << ") rval = " << rval; return rval; } #endif int LinuxSysFsInterface::SetPower(bool onoff) { qDebug() << "LinuxSysFsInterface::SetPower(" << onoff << ")"; return OK; } int LinuxSysFsInterface::InitPins(int idx) { if (pins.ctrl == 0 && pins.clock == 0 && pins.datain == 0 && pins.dataout == 0) { qWarning() << "LinuxSysFsInterface::InitPins() Unconfigured pins"; return E2ERR_OPENFAILED; } qDebug() << "LinuxSysFsInterface::InitPins Ctrl=" << pins.ctrl << ", Clock= " << pins.clock; qDebug() << "DataIn=" << pins.datain << ", DataOut=" << pins.dataout; #ifdef Q_OS_LINUX fd_ctrl = gpio_open(pins.ctrl, GPIO_OUT); fd_clock = gpio_open(pins.clock, GPIO_OUT); fd_datain = gpio_open(pins.datain, GPIO_IN); fd_dataout = gpio_open(pins.dataout, GPIO_OUT); if (fd_ctrl < 0 || fd_clock < 0 || fd_datain < 0 || fd_dataout < 0) { DeInitPins(); return E2ERR_OPENFAILED; } #endif return OK; } void LinuxSysFsInterface::DeInitPins() { #ifdef Q_OS_LINUX gpio_close(pins.ctrl, fd_ctrl); gpio_close(pins.clock, fd_clock); gpio_close(pins.datain, fd_datain); gpio_close(pins.dataout, fd_dataout); fd_ctrl = fd_clock = fd_datain = fd_dataout = -1; #endif } int LinuxSysFsInterface::Open(int port_no) { qDebug() << Q_FUNC_INFO << " (" << port_no << ") IN"; int ret_val = OK; if (GetInstalled() != port_no) { if ((ret_val = InitPins(port_no)) == OK) { Install(port_no); } } qDebug() << Q_FUNC_INFO << " = " << ret_val << " OUT"; return ret_val; } void LinuxSysFsInterface::Close() { qDebug() << Q_FUNC_INFO << " IN"; if (IsInstalled()) { SetPower(false); DeInitPins(); DeInstall(); } qDebug() << Q_FUNC_INFO << " OUT"; } // Per l'AVR e` la linea di RESET void LinuxSysFsInterface::SetControlLine(int res) { qDebug() << Q_FUNC_INFO << " (" << res << ") *** Inst=" << IsInstalled() << ", fd=" << fd_ctrl; if (IsInstalled()) { #ifdef Q_OS_LINUX if (cmdWin->GetPolarity() & RESETINV) { res = !res; } int ret; if (res) { ret = write(fd_ctrl, "1", 2); } else { ret = write(fd_ctrl, "0", 2); } if (ret != 2) { qWarning("LinuxSysFsInterface::SetControlLine() write failed (%d)\n", ret); exit(1); } #endif } } void LinuxSysFsInterface::SetDataOut(int sda) { qDebug() << Q_FUNC_INFO << "(" << sda << ") *** Inst=" << IsInstalled() << ", fd=" << fd_dataout; if (IsInstalled()) { #ifdef Q_OS_LINUX if ((cmdWin->GetPolarity() & DOUTINV)) { sda = !sda; } int ret; if (sda) { ret = write(fd_dataout, "1", 2); } else { ret = write(fd_dataout, "0", 2); } if (ret != 2) { qWarning("LinuxSysFsInterface::SetDataOut() write failed (%d)\n", ret); exit(1); } #endif } } void LinuxSysFsInterface::SetClock(int scl) { qDebug() << Q_FUNC_INFO << "(" << scl << ") *** Inst=" << IsInstalled() << ", fd=" << fd_clock; if (IsInstalled()) { #ifdef Q_OS_LINUX if ((cmdWin->GetPolarity() & CLOCKINV)) { scl = !scl; } int ret; if (scl) { ret = write(fd_clock, "1", 2); } else { ret = write(fd_clock, "0", 2); } if (ret != 2) { qWarning("LinuxSysFsInterface::SetClock() write failed (%d)\n", ret); exit(1); } #endif } } void LinuxSysFsInterface::SetClockData() { qDebug() << Q_FUNC_INFO << " *** Inst=" << IsInstalled(); if (IsInstalled()) { SetClock(1); SetDataOut(1); } } void LinuxSysFsInterface::ClearClockData() { qDebug() << Q_FUNC_INFO << " *** Inst=" << IsInstalled(); if (IsInstalled()) { SetClock(0); SetDataOut(0); } } int LinuxSysFsInterface::GetDataIn() { if (IsInstalled()) { unsigned int val = 0; #ifdef Q_OS_LINUX int ret; char ch; lseek(fd_datain, 0L, SEEK_SET); ret = read(fd_datain, &ch, 1); val = (ch == '0') ? 0 : 1; if (ret < 1) { qWarning("LinuxSysFsInterface::GetDataIn() read failed (%d)\n", ret); exit(1); } qDebug() << Q_FUNC_INFO << "=" << val << ", fd=" << fd_datain; if (cmdWin->GetPolarity() & DININV) { val = !val; } #endif return val; } else { return E2ERR_NOTINSTALLED; } } int LinuxSysFsInterface::GetClock() { return 1; } int LinuxSysFsInterface::IsClockDataUP() { qDebug() << Q_FUNC_INFO << " *** Inst=" << IsInstalled(); return GetDataIn(); } int LinuxSysFsInterface::IsClockDataDOWN() { qDebug() << Q_FUNC_INFO << " *** Inst=" << IsInstalled(); return !GetDataIn(); }