#include "atb_system.h" #include "ATBHMIconfig.h" #include #include #include #include #include #include #include #include ATB_system::ATB_system(ATBHMIconfig *config, QObject *parent) : QObject(parent) { this->config = config; this->tf_gpio = nullptr; #if defined (ARCH_PTU2) if (config->hasFeatureTF()) init_touch_feedback(); #elif defined (ARCH_PTU4) if (config->hasFeatureTF()) init_touch_feedback(); #endif } ATB_system::~ATB_system() { if (config->hasFeatureTF()) { delete(this->tf_gpio_outstream); delete(this->tf_gpio); } } void ATB_system::executeSystemCommand(quint16 cmd, QByteArray data) { Q_UNUSED(data); switch (cmd) { case SYS_COMMAND_SLEEP: qDebug() << "ATB_system::executeSystemCommand(): " << cmd; dbus_permitSuspend(); break; case SYS_COMMAND_DIMLOW: if (config->hasFeatureDBusDisplayControl()) { dbus_DimControlStart(); } else { this->DimLow(); } break; case SYS_COMMAND_DIMHIGH: if (config->hasFeatureDBusDisplayControl()) { dbus_DimHighPermanent(); } else { this->DimHigh(); } break; case SYS_COMMAND_BEEP: if (config->hasFeatureTF()) this->Beep(); break; case SYS_COMMAND_MACHINE_NUMBER: // deprecated and not used // setMachineNumber(data); break; case SYS_COMMAND_LED_CONTROL: this->privateConfigLED(data); break; case SYS_COMMAND_HALT: this->halt(); break; case SYS_COMMAND_REBOOT: this->reboot(); break; default: qDebug() << "ATB_system::executeSystemCommand(): unknown command: " << cmd; break; } } /***************************************************************************** * stubs for display control * * this methodes should later be scriptable an call corresponding methodes * in DisplayControl via DBus. */ void ATB_system::DimLow() { return; } void ATB_system::DimHigh() { //if (config->hasFeatureDC()) // this->dc->DimHigh(); } //void ATB_system::Dim(quint8 value) { if (config->hasFeatureDC()) this->dc->Dim((uchar)value); } void ATB_system::DimStart() { return; } void ATB_system::DimStop() { return; } /***************************************************************************** */ void ATB_system::Beep() { qDebug() << "ATB_system::Beep(): now i should make a beep!"; #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QTimer::singleShot (BEEPTIMEOUT, this, SLOT(BeepStop()) ); *(this->tf_gpio_outstream) << config->getTouchFeedbackOnValue(); this->tf_gpio_outstream->flush(); #endif } void ATB_system::BeepStop() { #if defined (ARCH_PTU2) || defined (ARCH_PTU4) *(this->tf_gpio_outstream) << config->getTouchFeedbackOffValue(); this->tf_gpio_outstream->flush(); #endif } int ATB_system::init_touch_feedback() { #if defined (ARCH_PTU2) QString GPIODirName("/sys/class/gpio/"); QString directionFileName; QString valueFileName; // # echo 129 > /sys/class/gpio/export QFile file("/sys/class/gpio/export"); file.open(QIODevice::WriteOnly | QIODevice::Text); QTextStream out(&file); out << config->getTouchFeedbackGPIO(); file.close(); // check, if gpio-dir was created GPIODirName.append("gpio"); GPIODirName.append(config->getTouchFeedbackGPIO()); QFileInfo fileinfo1(GPIODirName); if (! fileinfo1.isDir() ) { qDebug() << "ATB_system::init_touch_feedback(): \"" << GPIODirName << "\" is not a directory"; config->unsetFeatureTF(); return -1; } directionFileName = GPIODirName + "/direction"; QFileInfo fileinfo2(directionFileName); if (! fileinfo2.isWritable() ) { qDebug() << "ATB_system::init_touch_feedback(): \"" << directionFileName << "\" is not writable"; config->unsetFeatureTF(); return -1; } // # echo out > /sys/class/gpio/gpio129/direction QFile directionfile(directionFileName); directionfile.open(QIODevice::ReadWrite | QIODevice::Text); QTextStream out2(&directionfile); out2 << "out"; out2.flush(); // re-read 'direction' for confirmation // -> the following is disabled because this sometimes failed //QTextStream in(&directionfile); //QString line = in.readLine(); //if (line != "out") { // qDebug() << "ATB_system::init_touch_feedback(): re-read directionfile failed"; // config->unsetFeatureTF(); // return -1; //} directionfile.close(); // open gpio file valueFileName = GPIODirName + "/value"; this->tf_gpio = new QFile(valueFileName); this->tf_gpio->open(QIODevice::WriteOnly); this->tf_gpio_outstream = new QTextStream(this->tf_gpio); qDebug() << "ATB_system::init_touch_feedback(): GPIODirName = \"" << GPIODirName << "\""; qDebug() << "ATB_system::init_touch_feedback(): valueFileName = \"" << valueFileName << "\""; #elif defined (ARCH_PTU4) QString sysfs_buzzer("/sys/class/leds/Buzzer/brightness"); this->tf_gpio = new QFile(sysfs_buzzer); tf_gpio->open(QIODevice::WriteOnly); this->tf_gpio_outstream = new QTextStream(this->tf_gpio); #endif return 1; } /******************************************************************************** * set date/time * * Datestring format: YYYY-MM-DD hh:mm[:ss] * This is a format that is accepted both by busybox-date (e.g. PTU2) and by * coreutils-date. * * example: * /bin/date -s "2015-08-05 17:55:00" * */ void ATB_system::setDateTime(const QString & dateTimeString) { QString datetimeCMD = "/bin/date -s " + dateTimeString; #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QProcess::startDetached(datetimeCMD); // the following does not work on PTU2: //QProcess::startDetached ("/sbin/hwclock -w"); #endif } /******************************************************************************** * static functions to write single values to files. * * Used e.g. to store some machine specific settings like customer number or machine * number in filesystem. * * This data should be updated rarely and the calling function must keep this in mind! * * Note: QFile::open() creates a file, if it is not existing. */ quint8 ATB_system::setPSAConfigInt(const QString &filename, quint16 iValue) { return setPSAConfigString(filename, QString::number(iValue)); } quint8 ATB_system::setPSAConfigString(const QString & filename, const QString & sValue) { #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QFile file(filename); #else QFile file(QDir::homePath() + filename); #endif if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "ATB_system::setPSAConfigString() cannot open file: " << filename; qDebug() << " file.errorString() = " << file.errorString(); return 0; } qDebug() << "ATB_system::setPSAConfigString() write file: " << filename; QTextStream out(&file); out << sValue; out.flush(); file.close(); return 1; } quint16 ATB_system::readPSAConfigInt(const QString & filename) { bool ok; quint16 result = (quint16)readPSAConfigString(filename).toInt(&ok); if (!ok) { result = 0; } return result; } QString ATB_system::readPSAConfigString(const QString & filename) { #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QFileInfo fileinfo(filename); #else QFileInfo fileinfo(QDir::homePath() + filename); #endif if (! fileinfo.isReadable() ) { qDebug() << "ATB_system::readPSAConfigString(): \"" << filename << "\" is not readable"; return 0; } #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QFile file(filename); #else QFile file(QDir::homePath() + filename); #endif if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "ATB_system::readPSAConfigString() cannot open file: " << filename; return 0; } QTextStream in(&file); QString stringValue = in.readLine(100); qDebug() << "ATB_system::readPSAConfigString() stringValue = " << stringValue; file.close(); return stringValue; } /******************************************************************************** * LED control interface * */ void ATB_system::onConfigLED(LED_NAME LED, LED_TRIGGER trigger, quint16 delayOn, quint16 delayOff) { QString LEDPath = "/sys/class/leds/"; QString LEDName = ""; QString LEDtrigger = ""; // DEBUG // //////// switch (LED) { #if defined (ARCH_PTU2) case ATB_LED1: LEDName.append("atb_led1"); break; case ATB_LED2: LEDName.append("atb_led2"); break; case ATB_LED3: LEDName.append("atb_led3"); break; case ATB_LED4: LEDName.append("atb_led4"); break; #elif defined (ARCH_PTU4) case ATB_LED1: LEDName.append("D504"); break; case ATB_LED2: LEDName.append("D503"); break; case ATB_LED3: LEDName.append("D502"); break; case ATB_LED4: LEDName.append("D501"); break; #endif default: return; } switch (trigger) { case LED_TRIGGER_NONE: LEDtrigger.append("none"); break; case LED_TRIGGER_TIMER: LEDtrigger.append("timer"); break; #if defined (ARCH_PTU2) case LED_TRIGGER_DEFAULT_ON: LEDtrigger.append("default-on"); break; #elif defined (ARCH_PTU4) /* note: ptu4 leds currently do not support 'default-on' trigger * workaround is to set delay_off to '0' */ case LED_TRIGGER_DEFAULT_ON: LEDtrigger.append("timer"); trigger = LED_TRIGGER_TIMER; delayOn = 1; delayOff = 0; break; #endif default: return; } QString filename = LEDPath + LEDName + "/trigger"; // set trigger this->privateSetLEDTrigger(filename, LEDtrigger); // set delays for trigger 'timer' if (trigger == LED_TRIGGER_TIMER) { // set delay on if (delayOn != 0) { filename = LEDPath + LEDName + "/delay_on"; this->privateSetLEDDelayOn(filename, QString::number(delayOn)); } // set delay off if (delayOff != 0) { filename = LEDPath + LEDName + "/delay_off"; this->privateSetLEDDelayOn(filename, QString::number(delayOff)); } } return; } /***************************************************************************** * wrapper function for LED control. * * TODO: Test, check: plausibillity, cmd.lenght(), type casts to LED_NAME, LED_TRIGGER */ void ATB_system::privateConfigLED(const QByteArray & cmd) { quint16 delayOn = (quint8)cmd.at(3) + ((quint16)(cmd.at(2) << 8)); quint16 delayOff = (quint8)cmd.at(5) + ((quint16)(cmd.at(4) << 8)); this->onConfigLED((LED_NAME)cmd.at(0), (LED_TRIGGER)cmd.at(1), delayOn, delayOff); } void ATB_system::privateSetLEDTrigger(const QString & led, const QString & trigger) { #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QFile file(led); #else QFile file(QDir::homePath() + led); #endif if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "ATB_system::onConfigLED() cannot open file: " << led; qDebug() << " file.errorString() = " << file.errorString(); return; } qDebug() << "ATB_system::onConfigLED() write file: " << led; QTextStream out(&file); out << trigger; out.flush(); file.close(); } void ATB_system::privateSetLEDDelayOn(const QString & led, const QString & delayOn) { #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QFile file(led); #else QFile file(QDir::homePath() + led); #endif if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "ATB_system::onConfigLED() cannot open file: " << led; qDebug() << " file.errorString() = " << file.errorString(); return; } qDebug() << "ATB_system::onConfigLED() write file: " << led; QTextStream out(&file); out << delayOn; out.flush(); file.close(); } void ATB_system::privateSetLEDDelayOff(const QString & led, const QString & delayOff) { #if defined (ARCH_PTU2) || defined (ARCH_PTU4) QFile file(led); #else QFile file(QDir::homePath() + led); #endif if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "ATB_system::onConfigLED() cannot open file: " << led; qDebug() << " file.errorString() = " << file.errorString(); return; } qDebug() << "ATB_system::onConfigLED() write file: " << led; QTextStream out(&file); out << delayOff; out.flush(); file.close(); } /***************************************************************************** * functions for switching blink button on/off * This is only available on PTU4 */ void ATB_system::switchBlinkButtonOn() { this->privateSwitchBlinkButton(true); } void ATB_system::switchBlinkButtonOff() { this->privateSwitchBlinkButton(false); } void ATB_system::privateSwitchBlinkButton(bool on) { #if defined (ARCH_PTU2) #elif defined (ARCH_PTU4) QString BlinkLED("/sys/class/leds/TIMER_RESET/brightness"); QFile file(BlinkLED); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { qDebug() << "ATB_system::privateSwitchBlinkButton() cannot open file: " << BlinkLED; qDebug() << " file.errorString() = " << file.errorString(); return; } QTextStream out(&file); if (on) { out << "0"; } else { out << "1"; } out.flush(); file.close(); #else Q_UNUSED(on) #endif } /***************************************************************************** * halt system. * */ void ATB_system::halt() { QProcess::startDetached("/sbin/halt"); } /***************************************************************************** * reboot system. * */ void ATB_system::reboot() { QProcess::startDetached("/sbin/reboot"); } /***************************************************************************** * functions for wake vmc * This is only available on PTU4 */ void ATB_system::onWakeVMC() { #if defined (ARCH_PTU2) #elif defined (ARCH_PTU4) if (config->hasFeatureDBusSuspendControl()) { this->dbus_wakeSystem(); } #endif } /***************************************************************************** * get event device name by a type: * * e.g. type is TOUCHSCREEN: * getEventDeviceName(TOUCHSCREEN) returns "/dev/input/event0" * */ QString ATB_system::getEventDeviceName(DEVICE_TYPE type) { QString procDevices = "/proc/bus/input/devices"; QFile inFile(procDevices); if (!inFile.open(QFile::ReadOnly)) { qCritical() << "ATB_system::getEventDeviceName() ERROR open()" << procDevices; return ""; } QTextStream textInStream(&inFile); QString line; QString N_RegExp; QString DeviceTypeName; int lineCounter = 0; bool typeFound = false; QString H_RegExp = "^H: Handlers"; // H: Handlers=kbd event2 QString eventDeviceName = ""; QString eventPart; QStringList devNames; QString DeviceNamePattern; //PTU4 Touchscreen N: Name="atmel_mxt_ts T100 touchscreen" //PTU4 GPIO kys N: Name="gpio_keys.6" //RFID Reader, Stronglink SL040 N: Name="StrongLink USB CardReader" //2D Scanner, Datalogig DSE0420 N: Name="Datalogic ADC Inc. Handheld Barcode Scanner" VID: 05f9, PID:4005 //2D Scanner, Datalogig DSM0400 N: Name="Datalogic Handheld Barcode Scanner" VID: 05f9, PID:4005 //2D Scanner, Honeywell N56000 N: Name="Honeywell Imaging & Mobility N5600" //2D Scanner, Newland FM3080 N: Name="Newland Auto-ID NLS-FM3080V2-20 USB POS KBW" VID: 1eab, PID:0022 //2D Scanner, Opticon MDI-4000 N: Name="Opticon Opticon USB Barcode Reader" //USB Mouse N: Name="Logitech USB-PS/2 Optical Mouse" /* Datalogic DSE0420 I: Bus=0003 Vendor=05f9 Product=4005 Version=0110 N: Name="Datalogic ADC Inc. Handheld Barcode Scanner" P: Phys=usb-700000.ehci-2.3/input2 S: Sysfs=/devices/ahb.0/700000.ehci/usb1/1-2/1-2.3/1-2.3:1.2/input/input14 U: Uniq=S/N G16C15795 H: Handlers=kbd event3 B: PROP=0 B: EV=120013 B: KEY=10000 7 ff9f207a c14057ff febeffdf ffefffff ffffffff fffffffe B: MSC=10 B: LED=1f */ /* Datalogic DSM04XX I: Bus=0003 Vendor=05f9 Product=4005 Version=0110 N: Name="Datalogic Handheld Barcode Scanner" P: Phys=usb-700000.ehci-2.3/input0 S: Sysfs=/devices/ahb.0/700000.ehci/usb1/1-2/1-2.3/1-2.3:1.0/input/input15 U: Uniq=S/N G21FA0180 H: Handlers=kbd event3 B: PROP=0 B: EV=120013 B: KEY=e080ffdf 1cfffff ffffffff fffffffe B: MSC=10 B: LED=1f */ /* I: Bus=0003 Vendor=1eab Product=0022 Version=0110 N: Name="Newland Auto-ID NLS-FM3080V2-20 USB POS KBW" P: Phys=usb-700000.ehci-2.2/input0 S: Sysfs=/devices/ahb.0/700000.ehci/usb1/1-2/1-2.2/1-2.2:1.0/input/input6 U: Uniq=FM3080V2-20-BH00017 H: Handlers=kbd event2 B: PROP=0 B: EV=120013 B: KEY=10000 7 ff9f207a c14057ff febeffdf ffefffff ffffffff fffffffe B: MSC=10 B: LED=1f */ switch (type) { case EVENT_DEVICE_BARCODEREADER: N_RegExp = "^N: Name=.+(Barcode|Honeywell Imaging|Newland Auto).+"; DeviceTypeName = "1D/2D-Scanner"; DeviceNamePattern = "event"; break; case EVENT_DEVICE_TOUCHSCREEN: N_RegExp = "^N: Name=.+touch.+"; DeviceTypeName = "Touchscreen"; DeviceNamePattern = "event"; break; case EVENT_DEVICE_GPIO_KEYBOARD: N_RegExp = "^N: Name=.+gpio.+"; DeviceTypeName = "gpio-keys"; DeviceNamePattern = "event"; break; case EVENT_DEVICE_KEYBOARD: N_RegExp = "^N: Name=.+touch.+"; DeviceTypeName = "keyboard"; DeviceNamePattern = "event"; break; case EVENT_DEVICE_RFIDREADER: N_RegExp = "^N: Name=.+Card.+"; DeviceTypeName = "card reader"; DeviceNamePattern = "event"; break; case EVENT_DEVICE_USBMOUSE: N_RegExp = "^N: Name=.+USB.+Mouse.+"; DeviceTypeName = "USB Mouse"; DeviceNamePattern = "mouse"; break; } qDebug() << "ATB_system::getEventDeviceName() N_RegExp = " << N_RegExp; do { line = textInStream.readLine(); // DEBUG //qDebug() << " " << line; // find "N:"-line: if (line.contains(QRegExp(N_RegExp))) { typeFound = true; lineCounter = 0; qDebug() << "ATB_system::getEventDeviceName() found N_RegExp = " << N_RegExp; } if (typeFound) { // found "N:"-line, now search for "H:"-line; // the corresponding "H:"-line should be within the next 7 following text lines. // example lines: // - "H: Handlers=event0 mouse0" -> for touchscreen on PTU4 // - "H: Handlers=event3 mouse1" -> for USB mouse on PTU4 lineCounter++; if ( (lineCounter<=7) && (line.contains(QRegExp(H_RegExp))) ) { eventPart = line.split("=", QString::SkipEmptyParts).takeLast(); devNames = eventPart.split(" ", QString::SkipEmptyParts); for (int i=0; i