From 54e6c6b421c610586985c97c522d2e39aeb48d0d Mon Sep 17 00:00:00 2001 From: =?utf8?q?Michal=20Mal=C3=BD?= Date: Tue, 7 Jul 2015 01:27:54 +0200 Subject: [PATCH] Read devices directly from /dev/input --- deviceprober.cpp | 44 +++++++++++++++++++++++++++++++++----------- deviceprober.h | 12 +++++++++--- ffbdevice.cpp | 6 +++--- ffbdevice.h | 6 +++--- mainwindow.cpp | 11 +++++++---- mainwindow.h | 2 +- 6 files changed, 56 insertions(+), 25 deletions(-) diff --git a/deviceprober.cpp b/deviceprober.cpp index 3ead1ee..bbba7e8 100644 --- a/deviceprober.cpp +++ b/deviceprober.cpp @@ -7,7 +7,7 @@ #include #include -const QDir DeviceProber::s_deviceNodesByID("/dev/input/by-id"); +const QString DeviceProber::DEVICE_NODES_PATH("/dev/input"); const QString DeviceProber::res_ffbdeviceErrCap("FFB Device error"); DeviceProber::DeviceProber(QObject* parent) : @@ -15,23 +15,45 @@ DeviceProber::DeviceProber(QObject* parent) : { } -QStringList DeviceProber::listDevicesByID() +DeviceProber::DeviceList DeviceProber::listDevices() { - QStringList devices = DeviceProber::s_deviceNodesByID.entryList(QDir::NoDotAndDotDot); + DeviceProber::DeviceList list; + QDir devDir(DEVICE_NODES_PATH); + //QStringList devices = DeviceProber::s_deviceNodesPath.entryList(QDir::NoDotAndDotDot); + QStringList devices = devDir.entryList(QDir::System); - foreach (const QString s, devices) - qDebug() << s; + for (const QString& d : devices) { + int fd, ret; + char deviceName[64]; + DeviceInfo dinfo; + QString devicePath = devDir.absoluteFilePath(d); - return devices; + fd = open(devicePath.toLocal8Bit(), O_RDWR); + if (fd == -1) { + qDebug() << "Device" << d << "unaccessible" << strerror(errno); + continue; + } + + dinfo.path = devicePath; + ret = ioctl(fd, EVIOCGNAME(64), deviceName); + if (ret < 0) { + qDebug() << "Cannot get name of device" << d << strerror(errno); + dinfo.tag = QString("[%1]").arg(d); + } else + dinfo.tag = QString("%1 [%2]").arg(deviceName).arg(d); + + list.append(dinfo); + } + + return list; } -std::shared_ptr DeviceProber::openDeviceByID(const QString& id) +std::shared_ptr DeviceProber::openDevice(const QString& path) { - QString path = DeviceProber::s_deviceNodesByID.absoluteFilePath(id); /* Check if the device is already opened */ for (std::shared_ptr dev : m_openedDevices) { - if (QString::compare(id, dev->id()) == 0) { - qDebug() << "Device" << id << "already opened"; + if (QString::compare(path, dev->path()) == 0) { + qDebug() << "Device" << path << "already opened"; return dev; } } @@ -55,7 +77,7 @@ std::shared_ptr DeviceProber::openDeviceByID(const QString& id) return nullptr; } - std::shared_ptr device(new FFBDevice(fd, id, maxEffectCount)); + std::shared_ptr device(new FFBDevice(fd, path, maxEffectCount)); if (!device->queryDeviceCapabilities()) { QMessageBox::critical(nullptr, res_ffbdeviceErrCap, "Unable to query device capabilities."); return nullptr; diff --git a/deviceprober.h b/deviceprober.h index e39ab75..0314a7a 100644 --- a/deviceprober.h +++ b/deviceprober.h @@ -10,14 +10,20 @@ class DeviceProber : public QObject { Q_OBJECT public: + struct DeviceInfo { + QString path; + QString tag; + }; + typedef QList DeviceList; + explicit DeviceProber(QObject* parent = 0); - QStringList listDevicesByID(); - std::shared_ptr openDeviceByID(const QString& id); + DeviceList listDevices(); + std::shared_ptr openDevice(const QString& path); private: std::list> m_openedDevices; - static const QDir s_deviceNodesByID; + static const QString DEVICE_NODES_PATH; static const QString res_ffbdeviceErrCap; signals: diff --git a/ffbdevice.cpp b/ffbdevice.cpp index 57e5838..0588aaf 100644 --- a/ffbdevice.cpp +++ b/ffbdevice.cpp @@ -5,11 +5,11 @@ const quint8 FFBDevice::BITS_PER_LONG = sizeof(unsigned long) * 8; -FFBDevice::FFBDevice(const int fd, const QString& id, const int maxEffectCount, QObject* parent) : +FFBDevice::FFBDevice(const int fd, const QString& path, const int maxEffectCount, QObject* parent) : QObject(parent), c_fd(fd), - c_id(id), - c_maxEffectCount(maxEffectCount) + c_maxEffectCount(maxEffectCount), + c_path(path) { for (int i = 0; i < maxEffectCount; i++) m_effects.push_back(FFBEffectFactory::createEffect(FFBEffectTypes::NONE)); diff --git a/ffbdevice.h b/ffbdevice.h index bcf05b7..b1171b4 100644 --- a/ffbdevice.h +++ b/ffbdevice.h @@ -16,7 +16,7 @@ class FFBDevice : public QObject Q_OBJECT public: - explicit FFBDevice(const int fd, const QString& id, const int maxEffectCount, QObject* parent = 0); + explicit FFBDevice(const int fd, const QString& path, const int maxEffectCount, QObject* parent = 0); QStringList availableConditionSubtypesList() const; QStringList availableEffectsList() const; QStringList availableWaveformsList() const; @@ -30,8 +30,8 @@ public: FFBEffectTypes effectTypeByEffectIdx(const int idx) const; bool hasEffect(FFBEffectTypes id) const; bool hasPeriodicWaveform(PeriodicWaveforms id) const; - inline const QString& id() const { return c_id; } inline int maxEffectCount() const { return c_maxEffectCount; } + inline const QString& path() const { return c_path; } bool queryDeviceCapabilities(); bool removeAndEraseEffect(const int idx); bool startEffect(const int idx, FFBEffectTypes type, std::shared_ptr params); @@ -48,8 +48,8 @@ private: std::vector> m_effects; const int c_fd; - const QString c_id; const int c_maxEffectCount; + const QString c_path; static inline unsigned long longIdx(unsigned long bit) { return bit / BITS_PER_LONG; } static inline unsigned long offset(unsigned long bit) { return bit % BITS_PER_LONG; } diff --git a/mainwindow.cpp b/mainwindow.cpp index bff315c..dee56e5 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -33,7 +33,7 @@ MainWindow::MainWindow(std::shared_ptr prober, const QString& titl ui->ql_noChecksWarning->setHidden(true); fillDeviceList(); - connect(ui->cbox_devices, SIGNAL(activated(const QString&)), this, SLOT(onDeviceSelected(const QString&))); + connect(ui->cbox_devices, SIGNAL(activated(const int)), this, SLOT(onDeviceSelected(const int))); connect(ui->cbox_effectSlots, SIGNAL(activated(const int)), this, SLOT(onEffectSlotSelected(const int))); connect(ui->cbox_effectTypes, SIGNAL(activated(const int)), this, SLOT(onEffectTypeSelected(const int))); connect(ui->qpb_refreshDevices, SIGNAL(clicked()), this, SLOT(onRefreshDevicesClicked())); @@ -63,7 +63,9 @@ EffectSettings* MainWindow::effectSettingsByType(FFBEffectTypes type) void MainWindow::fillDeviceList() { ui->cbox_devices->clear(); - ui->cbox_devices->addItems(m_prober->listDevicesByID()); + + for (const DeviceProber::DeviceInfo& dinfo : m_prober->listDevices()) + ui->cbox_devices->addItem(dinfo.tag, dinfo.path); } void MainWindow::fillEffectSlotsList(const int idx) @@ -79,10 +81,11 @@ void MainWindow::fillEffectTypesList(const QStringList& list) ui->cbox_effectTypes->addItems(list); } -void MainWindow::onDeviceSelected(const QString& id) +void MainWindow::onDeviceSelected(const int idx) { + QString path = ui->cbox_devices->itemData(idx, Qt::UserRole).toString(); ui->cbox_effectSlots->clear(); - m_activeDevice = m_prober->openDeviceByID(id); + m_activeDevice = m_prober->openDevice(path); if (m_activeDevice == nullptr) return; diff --git a/mainwindow.h b/mainwindow.h index 33687ce..73fe41a 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -53,7 +53,7 @@ private: static const QString res_inputFormatErrCap; private slots: - void onDeviceSelected(const QString& id); + void onDeviceSelected(const int idx); void onEffectSlotSelected(const int idx); void onEffectTypeSelected(const int idx); void onRefreshDevicesClicked(); -- 2.43.5