0

所以我有一个 QT 项目,我想在其中检查是否连接了键盘。如果它未连接,我希望在程序运行期间连接它时仍能使用它。我环顾四周,发现了一些可能合适的库,但我不确定它们是否能做我想做的事。有问题的库:libinputlibusbSolid使用 KDE。我的问题是,这些库中的一个会做我想做的事情,还是完全不同?如果它是上述库之一,那么任何示例都会有所帮助,因为我真的无法从文档中得到任何东西。我可能还应该提到我使用的是 linux,或者更准确地说是 openSUSE Leap 15.2

4

1 回答 1

1

好吧,事实证明它并没有我想象的那么复杂,而且我谈到的库都不需要。这是我的解决方案,以防将来有人正在寻找类似的东西。

扫描仪.h

#ifndef SCANNER_H
#define SCANNER_H

#include <QObject>
#include <QThread>
#include <QTimer>
#include <QDebug>
#include <QString>
#include <QFile>
#include <QSocketNotifier>

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>

class Scanner : public QThread
{
    Q_OBJECT

public:
    static Scanner* getInstance(void);
    int saveInCorrectFormat(int code);

protected:
    void run() override;

signals:
    void ChipScanned(QString rfid);

private slots:
    void handleNotification(int socket);
    void checkScannerData();

private:
    Scanner(QObject *parent = 0);
    ~Scanner();

    void initScanner(void);

    static Scanner* sInstance;
    QString defaultPath = "/dev/input/event2";
    QString rfid;
    QTimer* sCheckScanner;
    QFile *sScannerFile;
    QSocketNotifier *sNotifier;
    int fd;
    bool notificationEnabled;
    struct input_event event;
    int RFID[10];
    int i = 0;
    int buffer = 0;
};

#endif // SCANNER_H

扫描仪.cpp

#include "scanner.h"

Scanner* Scanner::sInstance = new Scanner();

Scanner* Scanner::getInstance(void){
    return sInstance;
}

Scanner::Scanner(QObject *parent) : QThread(parent){
    moveToThread(this);
    start();
}

Scanner::~Scanner(){

}

void Scanner::run(){
    initScanner();
    QThread::exec();
}

/**
 * @brief Scanner::initScanner
 * initialize the timer to check up on the keyboard event file
 */
void Scanner::initScanner(void){
    notificationEnabled = false;
    sScannerFile = new QFile(defaultPath);

    sCheckScanner = new QTimer(this);
    sCheckScanner->setInterval(100);
    sCheckScanner->setSingleShot(false);
    connect(sCheckScanner, SIGNAL(timeout()), this, SLOT(checkScannerData()));
    sCheckScanner->start();
}

/**
 * @brief Scanner::checkScannerData
 * check if the keyboard is connected or not
 * if it is connected, activate event handling
 */
void Scanner::checkScannerData(){
    if(sScannerFile->exists()){
        if(notificationEnabled){
            return;
        }

        fd = open(defaultPath.toUtf8().data(), O_RDONLY | O_NONBLOCK);
        if(-1 != fd){
            sNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
            connect(sNotifier, SIGNAL(activated(int)), this, SLOT(handleNotification(int)));
            qDebug() << "Scanner connected";
            notificationEnabled = true;
        }
    }else{
        if(notificationEnabled){
            sNotifier->setEnabled(false);
            disconnect(sNotifier, SIGNAL(activated(int)), this, SLOT(handleNotification(int)));
            delete sNotifier;
            close(fd);
            qDebug() << "Scanner disconnect";
            notificationEnabled = false;
        }
    }
}

/**
 * @brief Scanner::handleNotification
 * check if the keyboard is still connected or if the event was the disconnect
 * if still connected than read the data and save it
 * @param socket
 */
void Scanner::handleNotification(int socket){
    if(!sScannerFile->exists()){
        if(notificationEnabled){
            sNotifier->setEnabled(false);
            disconnect(sNotifier, SIGNAL(activated(int)), this, SLOT(handleNotification(int)));
            delete sNotifier;
            close(fd);
            qDebug() << "Scanner disconnect";
            notificationEnabled = false;
        }
        return;
    }

    if(read(fd, &event, sizeof(event)) == sizeof(event)){
        if(event.type != EV_SYN){
            if(event.value == 1 && event.code != 28){
                RFID[i] = saveInCorrectFormat(event.code);
                rfid.append(QString("%1").arg(saveInCorrectFormat(event.code)));
                i++;
            }
        }
    }

    if(rfid.size() == 10){
        buffer++;
        if(buffer == 10){
            emit ChipScanned(rfid);
            qDebug() << rfid;
            i = 0;
            buffer = 0;
            rfid.clear();
        }
    }
}

/**
 * @brief Scanner::saveInCorrectFormat
 * correct the raw data in the it's right format
 * @param code
 * current data to convert
 * @return
 * converted data
 */
int Scanner::saveInCorrectFormat(int code){
    switch(code){
    case 11:
        return 0;
    case 28:
        return -1;
    default:
        return code-1;
    }
}

一些额外的信息:我的设备并不是真正的键盘,但输入的处理就像是键盘一样,这就是为什么我必须对原始数据进行一些调整才能达到预期的格式。其他任何人很可能不需要这些调整,例如读取数据后int saveInCorrectFormat的条件。if我相信这段代码是相当通用的,这意味着defaultPath在读取原始数据的同时进行一些调整并可能使其也可以用于其他设备。

于 2021-08-02T13:00:01.407 回答