[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [Gluon] b0234ea: Integrate libudev mechanism into the input subsyst
From:       Laszlo Papp <djszapi () archlinux ! us>
Date:       2010-11-08 17:35:13
Message-ID: 20101108173513.78D45A60A6 () git ! kde ! org
[Download RAW message or body]

commit b0234ea92e5ce54ea900c07a388b2b5735982203
branch master
Author: Laszlo Papp <djszapi@archlinux.us>
Date:   Mon Nov 8 19:31:06 2010 -0800

    Integrate libudev mechanism into the input subsystem and linker option.

diff --git a/input/CMakeLists.txt b/input/CMakeLists.txt
index 96e0a0e..48b71a9 100644
--- a/input/CMakeLists.txt
+++ b/input/CMakeLists.txt
@@ -158,7 +158,7 @@ if(GLUON_BUILD_ALL)
     add_dependencies(GluonInput GluonCore)
 endif()
 
-target_link_libraries(GluonInput ${GLUON_CORE_LIBS})
+target_link_libraries(GluonInput ${GLUON_CORE_LIBS} -ludev)
 
 set(GLUON_INPUT_LIBS
     GluonInput
diff --git a/input/linux/detectlinux.cpp b/input/linux/detectlinux.cpp
index c606388..4c2ab62 100644
--- a/input/linux/detectlinux.cpp
+++ b/input/linux/detectlinux.cpp
@@ -30,6 +30,8 @@
 #include <QtGui/QMessageBox>
 #include <QtCore/QDebug>
 
+#include <libudev.h>
+
 using namespace GluonInput;
 
 DetectLinux::DetectLinux( QObject* parent )
@@ -57,6 +59,15 @@ void DetectLinux::detectDevices()
     QString file;
     QFileInfoList inputFileInfoList;
     QList<struct input_id> processedInputs;
+    bool processed;
+
+    struct udev *udev;
+    struct udev_enumerate *enumerate;
+    struct udev_list_entry *devices;
+    struct udev_list_entry *dev_list_entry;
+    struct udev_device *dev;
+    struct udev_device *parent_dev;
+    struct input_id currentInputDeviceInfo;
 
     inputFileInfoList = event.entryInfoList( QDir::Files );
     foreach( QFileInfo inputFileInfo, inputFileInfoList )
@@ -111,6 +122,106 @@ void DetectLinux::detectDevices()
             detect->addInput( device );
         }
     }
+
+    /* Create the udev object */
+    udev = udev_new();
+    if (!udev)
+        qWarning() << "Cannot create udev" << endl;
+
+    /* Create a list of the devices in the 'hidraw' subsystem. */
+    enumerate = udev_enumerate_new(udev);
+    udev_enumerate_add_match_subsystem(enumerate, "input");
+    udev_enumerate_scan_devices(enumerate);
+    devices = udev_enumerate_get_list_entry(enumerate);
+    /* For each item enumerated, print out its information.
+     * udev_list_entry_foreach is a macro which expands to
+     * a loop. The loop will be executed for each member in
+     * devices, setting dev_list_entry to a list entry
+     * which contains the device's path in /sys.
+     */
+    udev_list_entry_foreach(dev_list_entry, devices) {
+        const char *path;
+
+        /* Get the filename of the /sys entry for the device
+           and create a udev_device object (dev) representing it */
+        path = udev_list_entry_get_name(dev_list_entry);
+        dev = udev_device_new_from_syspath(udev, path);
+
+        parent_dev = udev_device_get_parent_with_subsystem_devtype(dev, "input", 0);
+        if (parent_dev) {
+            udev_device_unref(parent_dev);
+            continue;
+        }
+
+        if (udev_device_get_sysattr_value(dev, "id/bustype"))
+            currentInputDeviceInfo.bustype = atoi(udev_device_get_sysattr_value(dev, \
"id/bustype")); +        if (udev_device_get_sysattr_value(dev, "id/vendor"))
+            currentInputDeviceInfo.vendor = \
atoi(udev_device_get_sysattr_value(dev,"id/vendor")); +        if \
(udev_device_get_sysattr_value(dev, "id/product")) +            \
currentInputDeviceInfo.product = atoi(udev_device_get_sysattr_value(dev, \
"id/product")); +        if (udev_device_get_sysattr_value(dev, "id/version"))
+            currentInputDeviceInfo.version = atoi(udev_device_get_sysattr_value(dev, \
"id/version")); +
+        /* The input device has been already processed, has read access
+         * credential
+         */
+        processed = false;
+        foreach(struct input_id inputID, processedInputs) {
+            if (inputID.bustype == currentInputDeviceInfo.bustype
+                    && inputID.vendor == currentInputDeviceInfo.vendor
+                    && inputID.product == currentInputDeviceInfo.product
+                    && inputID.version == currentInputDeviceInfo.version) {
+                processed = true;
+                break;
+            }
+        }
+
+        if (processed)
+            continue;
+
+        InputDevice *device = 0;
+        InputThread *thread = new InputThread(dev);
+        if (!thread->error()) {
+            switch (thread->deviceType()) {
+            case GluonInput::KeyboardDevice:
+                device = new Keyboard(thread);
+                detect->addKeyboard(static_cast<Keyboard *>(device));
+                break;
+
+            case GluonInput::MouseDevice:
+                device = new Mouse(thread);
+                detect->addMouse(static_cast<Mouse *>(device));
+                break;
+
+            case GluonInput::TouchpadDevice:
+                device = new Mouse(thread);
+                detect->addMouse(static_cast<Mouse *>(device));
+                break;
+
+            case GluonInput::JoystickDevice:
+                device = new Joystick(thread);
+                detect->addJoystick(static_cast<Joystick *>(device));
+                break;
+
+            case GluonInput::TouchDevice:
+                device = new Touch(thread);
+                detect->addTouch(static_cast<Touch *>(device));
+                break;
+
+            case GluonInput::UnknownDevice:
+                device = new InputDevice(thread);
+                detect->addUnknown(device);
+                break;
+            }
+
+            detect->addInput(device);
+        }
+    }
+
+    /* Free the enumerator object */
+    udev_enumerate_unref(enumerate);
+
+    udev_unref(udev);
 }
 
 void DetectLinux::setAllEnabled( bool enable )
diff --git a/input/linux/inputthread.cpp b/input/linux/inputthread.cpp
index 7b287c0..5ec84a5 100644
--- a/input/linux/inputthread.cpp
+++ b/input/linux/inputthread.cpp
@@ -28,6 +28,7 @@
 #include <QtCore/QDebug>
 #include <QtCore/QFile>
 #include <QtCore/QEvent>
+#include <QtCore/QStringList>
 
 #include <fcntl.h>
 #include <sys/stat.h>
@@ -52,6 +53,15 @@ InputThread::InputThread( const QString& devicePath, QObject* \
parent )  readInformation();
 }
 
+InputThread::InputThread(struct udev_device *dev, QObject *parent)
+    : QThread(parent)
+    , d(new InputThreadPrivate)
+{
+    d->m_udevDevice = dev;
+    readSystemFS();
+}
+
+
 InputThread::~InputThread()
 {
     closeDevice();
@@ -98,6 +108,131 @@ bool InputThread::openDevice( const QString& devicePath )
     return true;
 }
 
+int InputThread::readSystemFS()
+{
+
+    /* From here, we can call get_sysattr_value() for each file
+       in the device's /sys entry. The strings passed into these
+       functions (idProduct, idVendor, serial, etc.) correspond
+       directly to the files in the directory which represents
+       the USB device. Note that USB strings are Unicode, UCS2
+       encoded, but the strings returned from
+       udev_device_get_sysattr_value() are UTF-8 encoded. */
+    d->m_deviceName = \
QString::fromAscii(udev_device_get_sysattr_value(d->m_udevDevice, "name")); +
+    ///this next bit can be shared across platform
+    quint64 bit[EV_MAX][NBITS(KEY_MAX)];
+    int abs[5];
+    memset(bit, 0, sizeof(bit));
+
+    bool ok;
+    int k;
+    // qDebug() << udev_device_get_sysattr_value(d->m_udevDevice, "capabilities/ev") \
<< udev_device_get_sysattr_value(d->m_udevDevice, "name"); +    bit[0][0] = \
QString::fromAscii(udev_device_get_sysattr_value(d->m_udevDevice, \
"capabilities/ev")).toULong(&ok, 16); +
+    for (int i = 1; i < EV_MAX; ++i) {
+        if (test_bit(i, bit[0])) {
+            if (!i)
+                continue;
+            switch (i) {
+            case EV_KEY:
+            {
+                k = 0;
+                QStringList keySections = \
QString::fromAscii(udev_device_get_sysattr_value(d->m_udevDevice, \
"capabilities/key")).split(" "); +                for (QStringList::iterator istr = \
keySections.end(); istr != keySections.begin(); ++k) +                    bit[i][k] = \
(--istr)->toULongLong(&ok, 16); +
+                for (int j = 0; j < KEY_MAX; ++j) {
+                    if (test_bit(j, bit[i]))
+                        d->m_buttonCapabilities.append(j);
+                }
+            }
+            break;
+            case EV_REL:
+                {
+                    k = 0;
+                    QStringList relSections = \
QString::fromAscii(udev_device_get_sysattr_value(d->m_udevDevice, \
"capabilities/rel")).split(" "); +                    for (QStringList::iterator istr \
= relSections.end(); istr != relSections.begin(); ++k) +                        \
bit[i][k] = (--istr)->toULongLong(&ok, 16); +
+                    for (int j = 0; j < KEY_MAX; ++j) {
+                        if (test_bit(j, bit[i]))
+                            d->m_relAxisCapabilities.append(j);
+                    }
+                }
+                break;
+            case EV_ABS:
+                {
+                    for (int j = 0; j < ABS_MAX; ++j) {
+                        if (test_bit(j, bit[i])) {
+                            // Get abs value/limits
+                            k = 0;
+                            QStringList absSections = \
QString::fromAscii(udev_device_get_sysattr_value(d->m_udevDevice, \
"capabilities/abs")).split(" "); +                            for \
(QStringList::iterator istr = absSections.end(); istr != absSections.begin(); ++k) +  \
abs[k++] = (--istr)->toULongLong(&ok, 16); +
+                            AbsVal cabs(0, 0, 0, 0);
+                            for (int k = 0; k < 5; ++k) {
+                                if ((k < 3) || abs[k]) {
+                                    switch (k) {
+                                    case 0:
+                                        cabs.value = abs[k];
+                                        break;
+                                    case 1:
+                                        cabs.min = abs[k];
+                                        break;
+                                    case 2:
+                                        cabs.max = abs[k];
+                                        break;
+                                    case 3:
+                                        cabs.fuzz = abs[k];
+                                        break;
+                                    case 4:
+                                        cabs.flat = abs[k];
+                                        break;
+                                    }
+                                }
+                            }
+                            d->m_absAxisCapabilities.append(j);
+                            d->m_absAxisInfos.append(cabs);
+                        }
+                    }
+                }
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    //===============Find Force feedback ?? ===============
+
+    d->m_deviceType = GluonInput::UnknownDevice;
+
+    if (d->m_buttonCapabilities.contains(BTN_TOUCH)) {
+        d->m_deviceType  = GluonInput::TouchDevice;
+    }
+
+    if (d->m_buttonCapabilities.contains(BTN_STYLUS)
+            || d->m_buttonCapabilities.contains(ABS_PRESSURE)) {
+        d->m_deviceType  = GluonInput::MouseDevice;
+    }
+
+    if (d->m_buttonCapabilities.contains(BTN_TRIGGER)) {
+        d->m_deviceType  = GluonInput::JoystickDevice;
+    }
+
+    if (d->m_buttonCapabilities.contains(BTN_MOUSE)) {
+        d->m_deviceType  = GluonInput::MouseDevice;
+    }
+
+    if (d->m_buttonCapabilities.contains(KEY_ENTER))    {
+        d->m_deviceType  = GluonInput::KeyboardDevice;
+    }
+
+    return 0;
+}
+
 void InputThread::readInformation()
 {
     if( d->m_fd == -1 )
diff --git a/input/linux/inputthread.h b/input/linux/inputthread.h
index 1a52081..ecfa8e9 100644
--- a/input/linux/inputthread.h
+++ b/input/linux/inputthread.h
@@ -28,6 +28,8 @@
 #include <QtCore/QMap>
 #include <QtCore/QSharedData>
 
+#include <libudev.h>
+
 /**
  * \defgroup KCL KCL
  */
@@ -43,6 +45,7 @@ namespace GluonInput
 
         public:
             explicit InputThread( const QString& devicePath, QObject* parent = 0 );
+            explicit InputThread(udev_device *dev, QObject *parent = 0);
             ~InputThread();
             void run();
 
@@ -84,6 +87,7 @@ namespace GluonInput
             bool openDevice( const QString& devicePath );
             void closeDevice();
 
+            int readSystemFS();
             void readInformation();
 
             QSharedDataPointer<InputThreadPrivate> d;
diff --git a/input/linux/inputthreadprivate.h b/input/linux/inputthreadprivate.h
index 5f57692..57c81e8 100644
--- a/input/linux/inputthreadprivate.h
+++ b/input/linux/inputthreadprivate.h
@@ -28,6 +28,8 @@
 #include <QtCore/QMap>
 #include <QtCore/QString>
 
+#include <libudev.h>
+
 namespace GluonInput
 {
     class InputThreadPrivate : public QSharedData
@@ -39,6 +41,7 @@ namespace GluonInput
             int m_fd;
             struct input_id m_device_info;
             struct input_event m_currentEvent;
+            udev_device *m_udevDevice;
             QString m_devicePath;
 
             QString m_deviceName;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic