#include <fcntl.h>
#include <unistd.h>
-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) :
{
}
-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<FFBDevice> DeviceProber::openDeviceByID(const QString& id)
+std::shared_ptr<FFBDevice> DeviceProber::openDevice(const QString& path)
{
- QString path = DeviceProber::s_deviceNodesByID.absoluteFilePath(id);
/* Check if the device is already opened */
for (std::shared_ptr<FFBDevice> 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;
}
}
return nullptr;
}
- std::shared_ptr<FFBDevice> device(new FFBDevice(fd, id, maxEffectCount));
+ std::shared_ptr<FFBDevice> device(new FFBDevice(fd, path, maxEffectCount));
if (!device->queryDeviceCapabilities()) {
QMessageBox::critical(nullptr, res_ffbdeviceErrCap, "Unable to query device capabilities.");
return nullptr;
{
Q_OBJECT
public:
+ struct DeviceInfo {
+ QString path;
+ QString tag;
+ };
+ typedef QList<DeviceInfo> DeviceList;
+
explicit DeviceProber(QObject* parent = 0);
- QStringList listDevicesByID();
- std::shared_ptr<FFBDevice> openDeviceByID(const QString& id);
+ DeviceList listDevices();
+ std::shared_ptr<FFBDevice> openDevice(const QString& path);
private:
std::list<std::shared_ptr<FFBDevice>> m_openedDevices;
- static const QDir s_deviceNodesByID;
+ static const QString DEVICE_NODES_PATH;
static const QString res_ffbdeviceErrCap;
signals:
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));
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;
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<FFBEffectParameters> params);
std::vector<std::shared_ptr<FFBEffect>> 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; }
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()));
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)
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;
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();