devicediscovery: add more sophisticated discovery
authorJohannes Zellner <johannes.zellner@nokia.com>
Fri, 25 May 2012 17:07:11 +0000 (10:07 -0700)
committerQt by Nokia <qt-info@nokia.com>
Sat, 26 May 2012 00:47:01 +0000 (02:47 +0200)
Detect devices based on bit testing through evdev ioctl api. As this is
for the udev replacement, the bit testing is done similar to what udev
does. The current keyboard detection is based on testing if the KEY_Q is
available. This might be adjusted in the future.

Change-Id: I3f4176681a351e33d90a1425f1afedc8ce3640b8
Reviewed-by: Girish Ramakrishnan <girish.1.ramakrishnan@nokia.com>
src/platformsupport/devicediscovery/qdevicediscovery_static.cpp

index 918ab87..bfb48d4 100644 (file)
 #include <QObject>
 #include <QHash>
 #include <QDir>
+#include <QtCore/private/qcore_unix_p.h>
+
+#include <linux/input.h>
+#include <fcntl.h>
 
 //#define QT_QPA_DEVICE_DISCOVERY_DEBUG
 
 #include <QtDebug>
 #endif
 
+#define LONG_BITS (sizeof(int) * 8 )
+#define LONG_FIELD_SIZE(bits) ((bits / LONG_BITS) + 1)
+
+static bool testBit(long bit, const long *field)
+{
+    return (field[bit / LONG_BITS] >> bit % LONG_BITS) & 1;
+}
+
 QT_BEGIN_NAMESPACE
 
 QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent)
@@ -65,7 +77,7 @@ QDeviceDiscovery::QDeviceDiscovery(QDeviceTypes types, QObject *parent) :
     m_types(types)
 {
 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
-    qWarning() << "New static DeviceDiscovery created for type" << types;
+    qWarning() << "New DeviceDiscovery created for type" << types;
 #endif
 }
 
@@ -82,19 +94,21 @@ QStringList QDeviceDiscovery::scanConnectedDevices()
     dir.setFilter(QDir::System);
 
     foreach (const QString &deviceFile, dir.entryList()) {
-        if (checkDeviceType(deviceFile))
-            devices << (dir.absolutePath() + QString::fromLatin1("/") + deviceFile);
+        QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile;
+        if (checkDeviceType(absoluteFilePath))
+            devices << absoluteFilePath;
     }
 
     // check for drm devices
     dir.setPath(QString::fromLatin1(QT_DRM_DEVICE_PATH));
     foreach (const QString &deviceFile, dir.entryList()) {
-        if (checkDeviceType(deviceFile))
-            devices << (dir.absolutePath() + QString::fromLatin1("/") + deviceFile);
+        QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile;
+        if (checkDeviceType(absoluteFilePath))
+            devices << absoluteFilePath;
     }
 
 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
-    qWarning() << "Static DeviceDiscovery found matching devices" << devices;
+    qWarning() << "DeviceDiscovery found matching devices" << devices;
 #endif
 
     return devices;
@@ -102,13 +116,63 @@ QStringList QDeviceDiscovery::scanConnectedDevices()
 
 bool QDeviceDiscovery::checkDeviceType(const QString &device)
 {
-    if ((m_types & (Device_Keyboard | Device_Mouse | Device_Touchpad | Device_Touchscreen)) && device.startsWith(QString::fromLatin1(QT_EVDEV_DEVICE_PREFIX)))
-       return true;
+    bool ret = false;
+    int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
+    if (!fd) {
+#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
+        qWarning() << "DeviceDiscovery cannot open device" << device;
+#endif
+        return false;
+    }
+
+    long bitsKey[LONG_FIELD_SIZE(KEY_CNT)];
+    if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey) >= 0 ) {
+        if (!ret && (m_types & Device_Keyboard)) {
+            if (testBit(KEY_Q, bitsKey)) {
+#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
+                qWarning() << "DeviceDiscovery found keyboard at" << device;
+#endif
+                ret = true;
+            }
+        }
+
+        if (!ret && (m_types & Device_Mouse)) {
+            long bitsRel[LONG_FIELD_SIZE(REL_CNT)];
+            if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel) >= 0 ) {
+                if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) {
+#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
+                    qWarning() << "DeviceDiscovery found mouse at" << device;
+#endif
+                    ret = true;
+                }
+            }
+        }
+
+        if (!ret && (m_types & (Device_Touchpad | Device_Touchscreen))) {
+            long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)];
+            if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs) >= 0 ) {
+                if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) {
+                    if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) {
+#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
+                        qWarning() << "DeviceDiscovery found touchpad at" << device;
+#endif
+                        ret = true;
+                    } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) {
+#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
+                        qWarning() << "DeviceDiscovery found touchscreen at" << device;
+#endif
+                        ret = true;
+                    }
+                }
+            }
+        }
+    }
 
-    if ((m_types & Device_DRM) && device.startsWith(QString::fromLatin1(QT_DRM_DEVICE_PREFIX)))
-        return true;
+    if (!ret && (m_types & Device_DRM) && device.contains(QString::fromLatin1(QT_DRM_DEVICE_PREFIX)))
+        ret = true;
 
-    return false;
+    QT_CLOSE(fd);
+    return ret;
 }
 
 QT_END_NAMESPACE