Add evdev based generic linux keyboard plugin
authorJohannes Zellner <johannes.zellner@nokia.com>
Fri, 10 Feb 2012 10:47:32 +0000 (11:47 +0100)
committerQt by Nokia <qt-info@nokia.com>
Sat, 11 Feb 2012 00:19:49 +0000 (01:19 +0100)
This introduces a udev based evdev keyboard plugin. It contains a
default US keyboard map to fit the QKey enumeration.
Most of the udev related code was developed by ICS.
Major parts of the keyboard handler itself is reused from Qt 4 codebase.

Change-Id: I383d05eecfde1c8916b0007dd101bfcb66711968
Reviewed-by: Laszlo Agocs <laszlo.p.agocs@nokia.com>
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
src/plugins/generic/evdevkeyboard/evdevkeyboard.pro [new file with mode: 0644]
src/plugins/generic/evdevkeyboard/main.cpp [new file with mode: 0644]
src/plugins/generic/evdevkeyboard/qevdevkeyboard_defaultmap.h [new file with mode: 0644]
src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp [new file with mode: 0644]
src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h [new file with mode: 0644]
src/plugins/generic/evdevkeyboard/qevdevkeyboardmanager.cpp [new file with mode: 0644]
src/plugins/generic/evdevkeyboard/qevdevkeyboardmanager.h [new file with mode: 0644]
src/plugins/generic/generic.pro

diff --git a/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro b/src/plugins/generic/evdevkeyboard/evdevkeyboard.pro
new file mode 100644 (file)
index 0000000..243cd0c
--- /dev/null
@@ -0,0 +1,19 @@
+TARGET = qevdevkeyboardplugin
+load(qt_plugin)
+
+DESTDIR = $$QT.gui.plugins/generic
+target.path = $$[QT_INSTALL_PLUGINS]/generic
+INSTALLS += target
+
+HEADERS = \
+    qevdevkeybaord_defaultmap.h \
+    qevdevkeyboardhandler.h \
+    qevdevkeyboardmanager.h
+
+QT += core-private
+
+LIBS += -ludev
+
+SOURCES = main.cpp \
+    qevdevkeyboardhandler.cpp \
+    qevdevkeyboardmanager.cpp
diff --git a/src/plugins/generic/evdevkeyboard/main.cpp b/src/plugins/generic/evdevkeyboard/main.cpp
new file mode 100644 (file)
index 0000000..c3cc9f6
--- /dev/null
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qgenericplugin_qpa.h>
+#include "qevdevkeyboardmanager.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEvdevKeyboardPlugin : public QGenericPlugin
+{
+public:
+    QEvdevKeyboardPlugin();
+
+    QStringList keys() const;
+    QObject* create(const QString &key, const QString &specification);
+};
+
+QEvdevKeyboardPlugin::QEvdevKeyboardPlugin()
+    : QGenericPlugin()
+{
+}
+
+QStringList QEvdevKeyboardPlugin::keys() const
+{
+    return (QStringList()
+            << QLatin1String("EvdevKeyboard"));
+}
+
+QObject* QEvdevKeyboardPlugin::create(const QString &key,
+                                                 const QString &specification)
+{
+    if (!key.compare(QLatin1String("EvdevKeyboard"), Qt::CaseInsensitive))
+        return new QEvdevKeyboardManager(key, specification);
+    return 0;
+}
+
+Q_EXPORT_PLUGIN2(qevdevkeyboarplugin, QEvdevKeyboardPlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboard_defaultmap.h b/src/plugins/generic/evdevkeyboard/qevdevkeyboard_defaultmap.h
new file mode 100644 (file)
index 0000000..49b07ef
--- /dev/null
@@ -0,0 +1,787 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVDEVKEYBOARDHANDLER_DEFAULTMAP_H
+#define QEVDEVKEYBOARDHANDLER_DEFAULTMAP_H
+
+// no QT_BEGIN_NAMESPACE, since we include it internally...
+
+const QEvdevKeyboardMap::Mapping QEvdevKeyboardHandler::s_keymap_default[] = {
+    {   1, 0xffff, 0x01000000, 0x00, 0x00, 0x0000 },
+    {   2, 0x0031, 0x00000031, 0x00, 0x00, 0x0000 },
+    {   2, 0x0021, 0x00000021, 0x01, 0x00, 0x0000 },
+    {   3, 0x0032, 0x00000032, 0x00, 0x00, 0x0000 },
+    {   3, 0x0040, 0x00000040, 0x01, 0x00, 0x0000 },
+    {   3, 0x0040, 0x00000040, 0x02, 0x00, 0x0000 },
+    {   4, 0x0033, 0x00000033, 0x00, 0x00, 0x0000 },
+    {   4, 0x0023, 0x00000023, 0x01, 0x00, 0x0000 },
+    {   4, 0xffff, 0x01000000, 0x04, 0x00, 0x0000 },
+    {   5, 0x0034, 0x00000034, 0x00, 0x00, 0x0000 },
+    {   5, 0x0024, 0x00000024, 0x01, 0x00, 0x0000 },
+    {   5, 0x0024, 0x00000024, 0x02, 0x00, 0x0000 },
+    {   5, 0x005c, 0x0400005c, 0x04, 0x00, 0x0000 },
+    {   6, 0x0035, 0x00000035, 0x00, 0x00, 0x0000 },
+    {   6, 0x0025, 0x00000025, 0x01, 0x00, 0x0000 },
+    {   6, 0x005d, 0x0400005d, 0x04, 0x00, 0x0000 },
+    {   7, 0x0036, 0x00000036, 0x00, 0x00, 0x0000 },
+    {   7, 0x005e, 0x0000005e, 0x01, 0x00, 0x0000 },
+    {   7, 0x005e, 0x01001252, 0x02, 0x01, 0x0000 },
+    {   7, 0x005e, 0x0400005e, 0x04, 0x00, 0x0000 },
+    {   8, 0x0037, 0x00000037, 0x00, 0x00, 0x0000 },
+    {   8, 0x0026, 0x00000026, 0x01, 0x00, 0x0000 },
+    {   8, 0x007b, 0x0000007b, 0x02, 0x00, 0x0000 },
+    {   8, 0x005f, 0x0400005f, 0x04, 0x00, 0x0000 },
+    {   9, 0x0038, 0x00000038, 0x00, 0x00, 0x0000 },
+    {   9, 0x002a, 0x0000002a, 0x01, 0x00, 0x0000 },
+    {   9, 0x005b, 0x0000005b, 0x02, 0x00, 0x0000 },
+    {   9, 0xffff, 0x01000003, 0x04, 0x00, 0x0000 },
+    {  10, 0x0039, 0x00000039, 0x00, 0x00, 0x0000 },
+    {  10, 0x0028, 0x00000028, 0x01, 0x00, 0x0000 },
+    {  10, 0x005d, 0x0000005d, 0x02, 0x00, 0x0000 },
+    {  11, 0x0030, 0x00000030, 0x00, 0x00, 0x0000 },
+    {  11, 0x0029, 0x00000029, 0x01, 0x00, 0x0000 },
+    {  11, 0x007d, 0x0000007d, 0x02, 0x00, 0x0000 },
+    {  12, 0x002d, 0x0000002d, 0x00, 0x00, 0x0000 },
+    {  12, 0x005f, 0x0000005f, 0x01, 0x00, 0x0000 },
+    {  12, 0x005c, 0x0000005c, 0x02, 0x00, 0x0000 },
+    {  12, 0x005f, 0x0400005f, 0x04, 0x00, 0x0000 },
+    {  12, 0x005f, 0x0400005f, 0x05, 0x00, 0x0000 },
+    {  13, 0x003d, 0x0000003d, 0x00, 0x00, 0x0000 },
+    {  13, 0x002b, 0x0000002b, 0x01, 0x00, 0x0000 },
+    {  14, 0xffff, 0x01000003, 0x00, 0x00, 0x0000 },
+    {  14, 0xffff, 0x01000000, 0x0c, 0x08, 0x0300 },
+    {  15, 0xffff, 0x01000001, 0x00, 0x00, 0x0000 },
+    {  16, 0x0071, 0x00000051, 0x00, 0x00, 0x0000 },
+    {  16, 0x0051, 0x00000051, 0x01, 0x00, 0x0000 },
+    {  16, 0x0071, 0x00000051, 0x02, 0x00, 0x0000 },
+    {  16, 0x0051, 0x00000051, 0x03, 0x00, 0x0000 },
+    {  16, 0x0071, 0x04000051, 0x04, 0x00, 0x0000 },
+    {  16, 0x0071, 0x04000051, 0x05, 0x00, 0x0000 },
+    {  16, 0x0071, 0x04000051, 0x06, 0x00, 0x0000 },
+    {  16, 0x0071, 0x04000051, 0x07, 0x00, 0x0000 },
+    {  16, 0x0071, 0x08000051, 0x08, 0x00, 0x0000 },
+    {  16, 0x0071, 0x08000051, 0x09, 0x00, 0x0000 },
+    {  16, 0x0071, 0x08000051, 0x0a, 0x00, 0x0000 },
+    {  16, 0x0071, 0x08000051, 0x0b, 0x00, 0x0000 },
+    {  16, 0x0071, 0x0c000051, 0x0c, 0x00, 0x0000 },
+    {  16, 0x0071, 0x0c000051, 0x0d, 0x00, 0x0000 },
+    {  16, 0x0071, 0x0c000051, 0x0e, 0x00, 0x0000 },
+    {  16, 0x0071, 0x0c000051, 0x0f, 0x00, 0x0000 },
+    {  17, 0x0077, 0x00000057, 0x00, 0x00, 0x0000 },
+    {  17, 0x0057, 0x00000057, 0x01, 0x00, 0x0000 },
+    {  17, 0x0077, 0x00000057, 0x02, 0x00, 0x0000 },
+    {  17, 0x0057, 0x00000057, 0x03, 0x00, 0x0000 },
+    {  17, 0x0077, 0x04000057, 0x04, 0x00, 0x0000 },
+    {  17, 0x0077, 0x04000057, 0x05, 0x00, 0x0000 },
+    {  17, 0x0077, 0x04000057, 0x06, 0x00, 0x0000 },
+    {  17, 0x0077, 0x04000057, 0x07, 0x00, 0x0000 },
+    {  17, 0x0077, 0x08000057, 0x08, 0x00, 0x0000 },
+    {  17, 0x0077, 0x08000057, 0x09, 0x00, 0x0000 },
+    {  17, 0x0077, 0x08000057, 0x0a, 0x00, 0x0000 },
+    {  17, 0x0077, 0x08000057, 0x0b, 0x00, 0x0000 },
+    {  17, 0x0077, 0x0c000057, 0x0c, 0x00, 0x0000 },
+    {  17, 0x0077, 0x0c000057, 0x0d, 0x00, 0x0000 },
+    {  17, 0x0077, 0x0c000057, 0x0e, 0x00, 0x0000 },
+    {  17, 0x0077, 0x0c000057, 0x0f, 0x00, 0x0000 },
+    {  18, 0x0065, 0x00000045, 0x00, 0x00, 0x0000 },
+    {  18, 0x0045, 0x00000045, 0x01, 0x00, 0x0000 },
+    {  18, 0x0065, 0x00000045, 0x02, 0x00, 0x0000 },
+    {  18, 0x0045, 0x00000045, 0x03, 0x00, 0x0000 },
+    {  18, 0x0065, 0x04000045, 0x04, 0x00, 0x0000 },
+    {  18, 0x0065, 0x04000045, 0x05, 0x00, 0x0000 },
+    {  18, 0x0065, 0x04000045, 0x06, 0x00, 0x0000 },
+    {  18, 0x0065, 0x04000045, 0x07, 0x00, 0x0000 },
+    {  18, 0x0065, 0x08000045, 0x08, 0x00, 0x0000 },
+    {  18, 0x0065, 0x08000045, 0x09, 0x00, 0x0000 },
+    {  18, 0x0065, 0x08000045, 0x0a, 0x00, 0x0000 },
+    {  18, 0x0065, 0x08000045, 0x0b, 0x00, 0x0000 },
+    {  18, 0x0065, 0x0c000045, 0x0c, 0x00, 0x0000 },
+    {  18, 0x0065, 0x0c000045, 0x0d, 0x00, 0x0000 },
+    {  18, 0x0065, 0x0c000045, 0x0e, 0x00, 0x0000 },
+    {  18, 0x0065, 0x0c000045, 0x0f, 0x00, 0x0000 },
+    {  19, 0x0072, 0x00000052, 0x00, 0x00, 0x0000 },
+    {  19, 0x0052, 0x00000052, 0x01, 0x00, 0x0000 },
+    {  19, 0x0072, 0x00000052, 0x02, 0x00, 0x0000 },
+    {  19, 0x0052, 0x00000052, 0x03, 0x00, 0x0000 },
+    {  19, 0x0072, 0x04000052, 0x04, 0x00, 0x0000 },
+    {  19, 0x0072, 0x04000052, 0x05, 0x00, 0x0000 },
+    {  19, 0x0072, 0x04000052, 0x06, 0x00, 0x0000 },
+    {  19, 0x0072, 0x04000052, 0x07, 0x00, 0x0000 },
+    {  19, 0x0072, 0x08000052, 0x08, 0x00, 0x0000 },
+    {  19, 0x0072, 0x08000052, 0x09, 0x00, 0x0000 },
+    {  19, 0x0072, 0x08000052, 0x0a, 0x00, 0x0000 },
+    {  19, 0x0072, 0x08000052, 0x0b, 0x00, 0x0000 },
+    {  19, 0x0072, 0x0c000052, 0x0c, 0x00, 0x0000 },
+    {  19, 0x0072, 0x0c000052, 0x0d, 0x00, 0x0000 },
+    {  19, 0x0072, 0x0c000052, 0x0e, 0x00, 0x0000 },
+    {  19, 0x0072, 0x0c000052, 0x0f, 0x00, 0x0000 },
+    {  20, 0x0074, 0x00000054, 0x00, 0x00, 0x0000 },
+    {  20, 0x0054, 0x00000054, 0x01, 0x00, 0x0000 },
+    {  20, 0x0074, 0x00000054, 0x02, 0x00, 0x0000 },
+    {  20, 0x0054, 0x00000054, 0x03, 0x00, 0x0000 },
+    {  20, 0x0074, 0x04000054, 0x04, 0x00, 0x0000 },
+    {  20, 0x0074, 0x04000054, 0x05, 0x00, 0x0000 },
+    {  20, 0x0074, 0x04000054, 0x06, 0x00, 0x0000 },
+    {  20, 0x0074, 0x04000054, 0x07, 0x00, 0x0000 },
+    {  20, 0x0074, 0x08000054, 0x08, 0x00, 0x0000 },
+    {  20, 0x0074, 0x08000054, 0x09, 0x00, 0x0000 },
+    {  20, 0x0074, 0x08000054, 0x0a, 0x00, 0x0000 },
+    {  20, 0x0074, 0x08000054, 0x0b, 0x00, 0x0000 },
+    {  20, 0x0074, 0x0c000054, 0x0c, 0x00, 0x0000 },
+    {  20, 0x0074, 0x0c000054, 0x0d, 0x00, 0x0000 },
+    {  20, 0x0074, 0x0c000054, 0x0e, 0x00, 0x0000 },
+    {  20, 0x0074, 0x0c000054, 0x0f, 0x00, 0x0000 },
+    {  21, 0x0079, 0x00000059, 0x00, 0x00, 0x0000 },
+    {  21, 0x0059, 0x00000059, 0x01, 0x00, 0x0000 },
+    {  21, 0x0079, 0x00000059, 0x02, 0x00, 0x0000 },
+    {  21, 0x0059, 0x00000059, 0x03, 0x00, 0x0000 },
+    {  21, 0x0079, 0x04000059, 0x04, 0x00, 0x0000 },
+    {  21, 0x0079, 0x04000059, 0x05, 0x00, 0x0000 },
+    {  21, 0x0079, 0x04000059, 0x06, 0x00, 0x0000 },
+    {  21, 0x0079, 0x04000059, 0x07, 0x00, 0x0000 },
+    {  21, 0x0079, 0x08000059, 0x08, 0x00, 0x0000 },
+    {  21, 0x0079, 0x08000059, 0x09, 0x00, 0x0000 },
+    {  21, 0x0079, 0x08000059, 0x0a, 0x00, 0x0000 },
+    {  21, 0x0079, 0x08000059, 0x0b, 0x00, 0x0000 },
+    {  21, 0x0079, 0x0c000059, 0x0c, 0x00, 0x0000 },
+    {  21, 0x0079, 0x0c000059, 0x0d, 0x00, 0x0000 },
+    {  21, 0x0079, 0x0c000059, 0x0e, 0x00, 0x0000 },
+    {  21, 0x0079, 0x0c000059, 0x0f, 0x00, 0x0000 },
+    {  22, 0x0075, 0x00000055, 0x00, 0x00, 0x0000 },
+    {  22, 0x0055, 0x00000055, 0x01, 0x00, 0x0000 },
+    {  22, 0x0075, 0x00000055, 0x02, 0x00, 0x0000 },
+    {  22, 0x0055, 0x00000055, 0x03, 0x00, 0x0000 },
+    {  22, 0x0075, 0x04000055, 0x04, 0x00, 0x0000 },
+    {  22, 0x0075, 0x04000055, 0x05, 0x00, 0x0000 },
+    {  22, 0x0075, 0x04000055, 0x06, 0x00, 0x0000 },
+    {  22, 0x0075, 0x04000055, 0x07, 0x00, 0x0000 },
+    {  22, 0x0075, 0x08000055, 0x08, 0x00, 0x0000 },
+    {  22, 0x0075, 0x08000055, 0x09, 0x00, 0x0000 },
+    {  22, 0x0075, 0x08000055, 0x0a, 0x00, 0x0000 },
+    {  22, 0x0075, 0x08000055, 0x0b, 0x00, 0x0000 },
+    {  22, 0x0075, 0x0c000055, 0x0c, 0x00, 0x0000 },
+    {  22, 0x0075, 0x0c000055, 0x0d, 0x00, 0x0000 },
+    {  22, 0x0075, 0x0c000055, 0x0e, 0x00, 0x0000 },
+    {  22, 0x0075, 0x0c000055, 0x0f, 0x00, 0x0000 },
+    {  23, 0x0069, 0x00000049, 0x00, 0x00, 0x0000 },
+    {  23, 0x0049, 0x00000049, 0x01, 0x00, 0x0000 },
+    {  23, 0x0069, 0x00000049, 0x02, 0x00, 0x0000 },
+    {  23, 0x0049, 0x00000049, 0x03, 0x00, 0x0000 },
+    {  23, 0x0069, 0x04000049, 0x04, 0x00, 0x0000 },
+    {  23, 0x0069, 0x04000049, 0x05, 0x00, 0x0000 },
+    {  23, 0x0069, 0x04000049, 0x06, 0x00, 0x0000 },
+    {  23, 0x0069, 0x04000049, 0x07, 0x00, 0x0000 },
+    {  23, 0x0069, 0x08000049, 0x08, 0x00, 0x0000 },
+    {  23, 0x0069, 0x08000049, 0x09, 0x00, 0x0000 },
+    {  23, 0x0069, 0x08000049, 0x0a, 0x00, 0x0000 },
+    {  23, 0x0069, 0x08000049, 0x0b, 0x00, 0x0000 },
+    {  23, 0x0069, 0x0c000049, 0x0c, 0x00, 0x0000 },
+    {  23, 0x0069, 0x0c000049, 0x0d, 0x00, 0x0000 },
+    {  23, 0x0069, 0x0c000049, 0x0e, 0x00, 0x0000 },
+    {  23, 0x0069, 0x0c000049, 0x0f, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0000004f, 0x00, 0x00, 0x0000 },
+    {  24, 0x004f, 0x0000004f, 0x01, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0000004f, 0x02, 0x00, 0x0000 },
+    {  24, 0x004f, 0x0000004f, 0x03, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0400004f, 0x04, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0400004f, 0x05, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0400004f, 0x06, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0400004f, 0x07, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0800004f, 0x08, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0800004f, 0x09, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0800004f, 0x0a, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0800004f, 0x0b, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0c00004f, 0x0c, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0c00004f, 0x0d, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0c00004f, 0x0e, 0x00, 0x0000 },
+    {  24, 0x006f, 0x0c00004f, 0x0f, 0x00, 0x0000 },
+    {  25, 0x0070, 0x00000050, 0x00, 0x00, 0x0000 },
+    {  25, 0x0050, 0x00000050, 0x01, 0x00, 0x0000 },
+    {  25, 0x0070, 0x00000050, 0x02, 0x00, 0x0000 },
+    {  25, 0x0050, 0x00000050, 0x03, 0x00, 0x0000 },
+    {  25, 0x0070, 0x04000050, 0x04, 0x00, 0x0000 },
+    {  25, 0x0070, 0x04000050, 0x05, 0x00, 0x0000 },
+    {  25, 0x0070, 0x04000050, 0x06, 0x00, 0x0000 },
+    {  25, 0x0070, 0x04000050, 0x07, 0x00, 0x0000 },
+    {  25, 0x0070, 0x08000050, 0x08, 0x00, 0x0000 },
+    {  25, 0x0070, 0x08000050, 0x09, 0x00, 0x0000 },
+    {  25, 0x0070, 0x08000050, 0x0a, 0x00, 0x0000 },
+    {  25, 0x0070, 0x08000050, 0x0b, 0x00, 0x0000 },
+    {  25, 0x0070, 0x0c000050, 0x0c, 0x00, 0x0000 },
+    {  25, 0x0070, 0x0c000050, 0x0d, 0x00, 0x0000 },
+    {  25, 0x0070, 0x0c000050, 0x0e, 0x00, 0x0000 },
+    {  25, 0x0070, 0x0c000050, 0x0f, 0x00, 0x0000 },
+    {  26, 0x005b, 0x0000005b, 0x00, 0x00, 0x0000 },
+    {  26, 0x007b, 0x0000007b, 0x01, 0x00, 0x0000 },
+    {  26, 0xffff, 0x01000000, 0x04, 0x00, 0x0000 },
+    {  27, 0x005d, 0x0000005d, 0x00, 0x00, 0x0000 },
+    {  27, 0x007d, 0x0000007d, 0x01, 0x00, 0x0000 },
+    {  27, 0x007e, 0x0000007e, 0x02, 0x00, 0x0000 },
+    {  27, 0x005d, 0x0400005d, 0x04, 0x00, 0x0000 },
+    {  28, 0xffff, 0x01000004, 0x00, 0x00, 0x0000 },
+    {  28, 0x006d, 0x0c00004d, 0x08, 0x00, 0x0000 },
+    {  29, 0xffff, 0x01000021, 0x00, 0x04, 0x0004 },
+    {  30, 0x0061, 0x00000041, 0x00, 0x00, 0x0000 },
+    {  30, 0x0041, 0x00000041, 0x01, 0x00, 0x0000 },
+    {  30, 0x0061, 0x00000041, 0x02, 0x00, 0x0000 },
+    {  30, 0x0041, 0x00000041, 0x03, 0x00, 0x0000 },
+    {  30, 0x0061, 0x04000041, 0x04, 0x00, 0x0000 },
+    {  30, 0x0061, 0x04000041, 0x05, 0x00, 0x0000 },
+    {  30, 0x0061, 0x04000041, 0x06, 0x00, 0x0000 },
+    {  30, 0x0061, 0x04000041, 0x07, 0x00, 0x0000 },
+    {  30, 0x0061, 0x08000041, 0x08, 0x00, 0x0000 },
+    {  30, 0x0061, 0x08000041, 0x09, 0x00, 0x0000 },
+    {  30, 0x0061, 0x08000041, 0x0a, 0x00, 0x0000 },
+    {  30, 0x0061, 0x08000041, 0x0b, 0x00, 0x0000 },
+    {  30, 0x0061, 0x0c000041, 0x0c, 0x00, 0x0000 },
+    {  30, 0x0061, 0x0c000041, 0x0d, 0x00, 0x0000 },
+    {  30, 0x0061, 0x0c000041, 0x0e, 0x00, 0x0000 },
+    {  30, 0x0061, 0x0c000041, 0x0f, 0x00, 0x0000 },
+    {  31, 0x0073, 0x00000053, 0x00, 0x00, 0x0000 },
+    {  31, 0x0053, 0x00000053, 0x01, 0x00, 0x0000 },
+    {  31, 0x0073, 0x00000053, 0x02, 0x00, 0x0000 },
+    {  31, 0x0053, 0x00000053, 0x03, 0x00, 0x0000 },
+    {  31, 0x0073, 0x04000053, 0x04, 0x00, 0x0000 },
+    {  31, 0x0073, 0x04000053, 0x05, 0x00, 0x0000 },
+    {  31, 0x0073, 0x04000053, 0x06, 0x00, 0x0000 },
+    {  31, 0x0073, 0x04000053, 0x07, 0x00, 0x0000 },
+    {  31, 0x0073, 0x08000053, 0x08, 0x00, 0x0000 },
+    {  31, 0x0073, 0x08000053, 0x09, 0x00, 0x0000 },
+    {  31, 0x0073, 0x08000053, 0x0a, 0x00, 0x0000 },
+    {  31, 0x0073, 0x08000053, 0x0b, 0x00, 0x0000 },
+    {  31, 0x0073, 0x0c000053, 0x0c, 0x00, 0x0000 },
+    {  31, 0x0073, 0x0c000053, 0x0d, 0x00, 0x0000 },
+    {  31, 0x0073, 0x0c000053, 0x0e, 0x00, 0x0000 },
+    {  31, 0x0073, 0x0c000053, 0x0f, 0x00, 0x0000 },
+    {  32, 0x0064, 0x00000044, 0x00, 0x00, 0x0000 },
+    {  32, 0x0044, 0x00000044, 0x01, 0x00, 0x0000 },
+    {  32, 0x0064, 0x00000044, 0x02, 0x00, 0x0000 },
+    {  32, 0x0044, 0x00000044, 0x03, 0x00, 0x0000 },
+    {  32, 0x0064, 0x04000044, 0x04, 0x00, 0x0000 },
+    {  32, 0x0064, 0x04000044, 0x05, 0x00, 0x0000 },
+    {  32, 0x0064, 0x04000044, 0x06, 0x00, 0x0000 },
+    {  32, 0x0064, 0x04000044, 0x07, 0x00, 0x0000 },
+    {  32, 0x0064, 0x08000044, 0x08, 0x00, 0x0000 },
+    {  32, 0x0064, 0x08000044, 0x09, 0x00, 0x0000 },
+    {  32, 0x0064, 0x08000044, 0x0a, 0x00, 0x0000 },
+    {  32, 0x0064, 0x08000044, 0x0b, 0x00, 0x0000 },
+    {  32, 0x0064, 0x0c000044, 0x0c, 0x00, 0x0000 },
+    {  32, 0x0064, 0x0c000044, 0x0d, 0x00, 0x0000 },
+    {  32, 0x0064, 0x0c000044, 0x0e, 0x00, 0x0000 },
+    {  32, 0x0064, 0x0c000044, 0x0f, 0x00, 0x0000 },
+    {  33, 0x0066, 0x00000046, 0x00, 0x00, 0x0000 },
+    {  33, 0x0046, 0x00000046, 0x01, 0x00, 0x0000 },
+    {  33, 0x0066, 0x00000046, 0x02, 0x00, 0x0000 },
+    {  33, 0x0046, 0x00000046, 0x03, 0x00, 0x0000 },
+    {  33, 0x0066, 0x04000046, 0x04, 0x00, 0x0000 },
+    {  33, 0x0066, 0x04000046, 0x05, 0x00, 0x0000 },
+    {  33, 0x0066, 0x04000046, 0x06, 0x00, 0x0000 },
+    {  33, 0x0066, 0x04000046, 0x07, 0x00, 0x0000 },
+    {  33, 0x0066, 0x08000046, 0x08, 0x00, 0x0000 },
+    {  33, 0x0066, 0x08000046, 0x09, 0x00, 0x0000 },
+    {  33, 0x0066, 0x08000046, 0x0a, 0x00, 0x0000 },
+    {  33, 0x0066, 0x08000046, 0x0b, 0x00, 0x0000 },
+    {  33, 0x0066, 0x0c000046, 0x0c, 0x00, 0x0000 },
+    {  33, 0x0066, 0x0c000046, 0x0d, 0x00, 0x0000 },
+    {  33, 0x0066, 0x0c000046, 0x0e, 0x00, 0x0000 },
+    {  33, 0x0066, 0x0c000046, 0x0f, 0x00, 0x0000 },
+    {  34, 0x0067, 0x00000047, 0x00, 0x00, 0x0000 },
+    {  34, 0x0047, 0x00000047, 0x01, 0x00, 0x0000 },
+    {  34, 0x0067, 0x00000047, 0x02, 0x00, 0x0000 },
+    {  34, 0x0047, 0x00000047, 0x03, 0x00, 0x0000 },
+    {  34, 0x0067, 0x04000047, 0x04, 0x00, 0x0000 },
+    {  34, 0x0067, 0x04000047, 0x05, 0x00, 0x0000 },
+    {  34, 0x0067, 0x04000047, 0x06, 0x00, 0x0000 },
+    {  34, 0x0067, 0x04000047, 0x07, 0x00, 0x0000 },
+    {  34, 0x0067, 0x08000047, 0x08, 0x00, 0x0000 },
+    {  34, 0x0067, 0x08000047, 0x09, 0x00, 0x0000 },
+    {  34, 0x0067, 0x08000047, 0x0a, 0x00, 0x0000 },
+    {  34, 0x0067, 0x08000047, 0x0b, 0x00, 0x0000 },
+    {  34, 0x0067, 0x0c000047, 0x0c, 0x00, 0x0000 },
+    {  34, 0x0067, 0x0c000047, 0x0d, 0x00, 0x0000 },
+    {  34, 0x0067, 0x0c000047, 0x0e, 0x00, 0x0000 },
+    {  34, 0x0067, 0x0c000047, 0x0f, 0x00, 0x0000 },
+    {  35, 0x0068, 0x00000048, 0x00, 0x00, 0x0000 },
+    {  35, 0x0048, 0x00000048, 0x01, 0x00, 0x0000 },
+    {  35, 0x0068, 0x00000048, 0x02, 0x00, 0x0000 },
+    {  35, 0x0048, 0x00000048, 0x03, 0x00, 0x0000 },
+    {  35, 0x0068, 0x04000048, 0x04, 0x00, 0x0000 },
+    {  35, 0x0068, 0x04000048, 0x05, 0x00, 0x0000 },
+    {  35, 0x0068, 0x04000048, 0x06, 0x00, 0x0000 },
+    {  35, 0x0068, 0x04000048, 0x07, 0x00, 0x0000 },
+    {  35, 0x0068, 0x08000048, 0x08, 0x00, 0x0000 },
+    {  35, 0x0068, 0x08000048, 0x09, 0x00, 0x0000 },
+    {  35, 0x0068, 0x08000048, 0x0a, 0x00, 0x0000 },
+    {  35, 0x0068, 0x08000048, 0x0b, 0x00, 0x0000 },
+    {  35, 0x0068, 0x0c000048, 0x0c, 0x00, 0x0000 },
+    {  35, 0x0068, 0x0c000048, 0x0d, 0x00, 0x0000 },
+    {  35, 0x0068, 0x0c000048, 0x0e, 0x00, 0x0000 },
+    {  35, 0x0068, 0x0c000048, 0x0f, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0000004a, 0x00, 0x00, 0x0000 },
+    {  36, 0x004a, 0x0000004a, 0x01, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0000004a, 0x02, 0x00, 0x0000 },
+    {  36, 0x004a, 0x0000004a, 0x03, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0400004a, 0x04, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0400004a, 0x05, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0400004a, 0x06, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0400004a, 0x07, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0800004a, 0x08, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0800004a, 0x09, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0800004a, 0x0a, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0800004a, 0x0b, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0c00004a, 0x0c, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0c00004a, 0x0d, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0c00004a, 0x0e, 0x00, 0x0000 },
+    {  36, 0x006a, 0x0c00004a, 0x0f, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0000004b, 0x00, 0x00, 0x0000 },
+    {  37, 0x004b, 0x0000004b, 0x01, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0000004b, 0x02, 0x00, 0x0000 },
+    {  37, 0x004b, 0x0000004b, 0x03, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0400004b, 0x04, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0400004b, 0x05, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0400004b, 0x06, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0400004b, 0x07, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0800004b, 0x08, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0800004b, 0x09, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0800004b, 0x0a, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0800004b, 0x0b, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0c00004b, 0x0c, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0c00004b, 0x0d, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0c00004b, 0x0e, 0x00, 0x0000 },
+    {  37, 0x006b, 0x0c00004b, 0x0f, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0000004c, 0x00, 0x00, 0x0000 },
+    {  38, 0x004c, 0x0000004c, 0x01, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0000004c, 0x02, 0x00, 0x0000 },
+    {  38, 0x004c, 0x0000004c, 0x03, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0400004c, 0x04, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0400004c, 0x05, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0400004c, 0x06, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0400004c, 0x07, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0800004c, 0x08, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0800004c, 0x09, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0800004c, 0x0a, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0800004c, 0x0b, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0c00004c, 0x0c, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0c00004c, 0x0d, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0c00004c, 0x0e, 0x00, 0x0000 },
+    {  38, 0x006c, 0x0c00004c, 0x0f, 0x00, 0x0000 },
+    {  39, 0x003b, 0x0000003b, 0x00, 0x00, 0x0000 },
+    {  39, 0x003a, 0x0000003a, 0x01, 0x00, 0x0000 },
+    {  40, 0x0027, 0x00000027, 0x00, 0x00, 0x0000 },
+    {  40, 0x0022, 0x00000022, 0x01, 0x00, 0x0000 },
+    {  40, 0x0027, 0x01001251, 0x02, 0x01, 0x0000 },
+    {  40, 0x0022, 0x01001257, 0x03, 0x01, 0x0000 },
+    {  40, 0x0067, 0x04000047, 0x04, 0x00, 0x0000 },
+    {  41, 0x0060, 0x00000060, 0x00, 0x00, 0x0000 },
+    {  41, 0x007e, 0x0000007e, 0x01, 0x00, 0x0000 },
+    {  41, 0x0060, 0x01001250, 0x02, 0x01, 0x0000 },
+    {  41, 0x007e, 0x01001253, 0x03, 0x01, 0x0000 },
+    {  42, 0xffff, 0x01000020, 0x00, 0x04, 0x0001 },
+    {  43, 0x005c, 0x0000005c, 0x00, 0x00, 0x0000 },
+    {  43, 0x007c, 0x0000007c, 0x01, 0x00, 0x0000 },
+    {  43, 0x005c, 0x0400005c, 0x04, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0000005a, 0x00, 0x00, 0x0000 },
+    {  44, 0x005a, 0x0000005a, 0x01, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0000005a, 0x02, 0x00, 0x0000 },
+    {  44, 0x005a, 0x0000005a, 0x03, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0400005a, 0x04, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0400005a, 0x05, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0400005a, 0x06, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0400005a, 0x07, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0800005a, 0x08, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0800005a, 0x09, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0800005a, 0x0a, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0800005a, 0x0b, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0c00005a, 0x0c, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0c00005a, 0x0d, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0c00005a, 0x0e, 0x00, 0x0000 },
+    {  44, 0x007a, 0x0c00005a, 0x0f, 0x00, 0x0000 },
+    {  45, 0x0078, 0x00000058, 0x00, 0x00, 0x0000 },
+    {  45, 0x0058, 0x00000058, 0x01, 0x00, 0x0000 },
+    {  45, 0x0078, 0x00000058, 0x02, 0x00, 0x0000 },
+    {  45, 0x0058, 0x00000058, 0x03, 0x00, 0x0000 },
+    {  45, 0x0078, 0x04000058, 0x04, 0x00, 0x0000 },
+    {  45, 0x0078, 0x04000058, 0x05, 0x00, 0x0000 },
+    {  45, 0x0078, 0x04000058, 0x06, 0x00, 0x0000 },
+    {  45, 0x0078, 0x04000058, 0x07, 0x00, 0x0000 },
+    {  45, 0x0078, 0x08000058, 0x08, 0x00, 0x0000 },
+    {  45, 0x0078, 0x08000058, 0x09, 0x00, 0x0000 },
+    {  45, 0x0078, 0x08000058, 0x0a, 0x00, 0x0000 },
+    {  45, 0x0078, 0x08000058, 0x0b, 0x00, 0x0000 },
+    {  45, 0x0078, 0x0c000058, 0x0c, 0x00, 0x0000 },
+    {  45, 0x0078, 0x0c000058, 0x0d, 0x00, 0x0000 },
+    {  45, 0x0078, 0x0c000058, 0x0e, 0x00, 0x0000 },
+    {  45, 0x0078, 0x0c000058, 0x0f, 0x00, 0x0000 },
+    {  46, 0x0063, 0x00000043, 0x00, 0x00, 0x0000 },
+    {  46, 0x0043, 0x00000043, 0x01, 0x00, 0x0000 },
+    {  46, 0x0063, 0x00000043, 0x02, 0x00, 0x0000 },
+    {  46, 0x0043, 0x00000043, 0x03, 0x00, 0x0000 },
+    {  46, 0x0063, 0x04000043, 0x04, 0x00, 0x0000 },
+    {  46, 0x0063, 0x04000043, 0x05, 0x00, 0x0000 },
+    {  46, 0x0063, 0x04000043, 0x06, 0x00, 0x0000 },
+    {  46, 0x0063, 0x04000043, 0x07, 0x00, 0x0000 },
+    {  46, 0x0063, 0x08000043, 0x08, 0x00, 0x0000 },
+    {  46, 0x0063, 0x08000043, 0x09, 0x00, 0x0000 },
+    {  46, 0x0063, 0x08000043, 0x0a, 0x00, 0x0000 },
+    {  46, 0x0063, 0x08000043, 0x0b, 0x00, 0x0000 },
+    {  46, 0x0063, 0x0c000043, 0x0c, 0x00, 0x0000 },
+    {  46, 0x0063, 0x0c000043, 0x0d, 0x00, 0x0000 },
+    {  46, 0x0063, 0x0c000043, 0x0e, 0x00, 0x0000 },
+    {  46, 0x0063, 0x0c000043, 0x0f, 0x00, 0x0000 },
+    {  47, 0x0076, 0x00000056, 0x00, 0x00, 0x0000 },
+    {  47, 0x0056, 0x00000056, 0x01, 0x00, 0x0000 },
+    {  47, 0x0076, 0x00000056, 0x02, 0x00, 0x0000 },
+    {  47, 0x0056, 0x00000056, 0x03, 0x00, 0x0000 },
+    {  47, 0x0076, 0x04000056, 0x04, 0x00, 0x0000 },
+    {  47, 0x0076, 0x04000056, 0x05, 0x00, 0x0000 },
+    {  47, 0x0076, 0x04000056, 0x06, 0x00, 0x0000 },
+    {  47, 0x0076, 0x04000056, 0x07, 0x00, 0x0000 },
+    {  47, 0x0076, 0x08000056, 0x08, 0x00, 0x0000 },
+    {  47, 0x0076, 0x08000056, 0x09, 0x00, 0x0000 },
+    {  47, 0x0076, 0x08000056, 0x0a, 0x00, 0x0000 },
+    {  47, 0x0076, 0x08000056, 0x0b, 0x00, 0x0000 },
+    {  47, 0x0076, 0x0c000056, 0x0c, 0x00, 0x0000 },
+    {  47, 0x0076, 0x0c000056, 0x0d, 0x00, 0x0000 },
+    {  47, 0x0076, 0x0c000056, 0x0e, 0x00, 0x0000 },
+    {  47, 0x0076, 0x0c000056, 0x0f, 0x00, 0x0000 },
+    {  48, 0x0062, 0x00000042, 0x00, 0x00, 0x0000 },
+    {  48, 0x0042, 0x00000042, 0x01, 0x00, 0x0000 },
+    {  48, 0x0062, 0x00000042, 0x02, 0x00, 0x0000 },
+    {  48, 0x0042, 0x00000042, 0x03, 0x00, 0x0000 },
+    {  48, 0x0062, 0x04000042, 0x04, 0x00, 0x0000 },
+    {  48, 0x0062, 0x04000042, 0x05, 0x00, 0x0000 },
+    {  48, 0x0062, 0x04000042, 0x06, 0x00, 0x0000 },
+    {  48, 0x0062, 0x04000042, 0x07, 0x00, 0x0000 },
+    {  48, 0x0062, 0x08000042, 0x08, 0x00, 0x0000 },
+    {  48, 0x0062, 0x08000042, 0x09, 0x00, 0x0000 },
+    {  48, 0x0062, 0x08000042, 0x0a, 0x00, 0x0000 },
+    {  48, 0x0062, 0x08000042, 0x0b, 0x00, 0x0000 },
+    {  48, 0x0062, 0x0c000042, 0x0c, 0x00, 0x0000 },
+    {  48, 0x0062, 0x0c000042, 0x0d, 0x00, 0x0000 },
+    {  48, 0x0062, 0x0c000042, 0x0e, 0x00, 0x0000 },
+    {  48, 0x0062, 0x0c000042, 0x0f, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0000004e, 0x00, 0x00, 0x0000 },
+    {  49, 0x004e, 0x0000004e, 0x01, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0000004e, 0x02, 0x00, 0x0000 },
+    {  49, 0x004e, 0x0000004e, 0x03, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0400004e, 0x04, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0400004e, 0x05, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0400004e, 0x06, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0400004e, 0x07, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0800004e, 0x08, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0800004e, 0x09, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0800004e, 0x0a, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0800004e, 0x0b, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0c00004e, 0x0c, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0c00004e, 0x0d, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0c00004e, 0x0e, 0x00, 0x0000 },
+    {  49, 0x006e, 0x0c00004e, 0x0f, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0000004d, 0x00, 0x00, 0x0000 },
+    {  50, 0x004d, 0x0000004d, 0x01, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0000004d, 0x02, 0x00, 0x0000 },
+    {  50, 0x004d, 0x0000004d, 0x03, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0400004d, 0x04, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0400004d, 0x05, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0400004d, 0x06, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0400004d, 0x07, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0800004d, 0x08, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0800004d, 0x09, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0800004d, 0x0a, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0800004d, 0x0b, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0c00004d, 0x0c, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0c00004d, 0x0d, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0c00004d, 0x0e, 0x00, 0x0000 },
+    {  50, 0x006d, 0x0c00004d, 0x0f, 0x00, 0x0000 },
+    {  51, 0x002c, 0x0000002c, 0x00, 0x00, 0x0000 },
+    {  51, 0x003c, 0x0000003c, 0x01, 0x00, 0x0000 },
+    {  51, 0x002c, 0x0100125b, 0x02, 0x01, 0x0000 },
+    {  52, 0x002e, 0x0000002e, 0x00, 0x00, 0x0000 },
+    {  52, 0x003e, 0x0000003e, 0x01, 0x00, 0x0000 },
+    {  52, 0xffff, 0x01001120, 0x02, 0x00, 0x0000 },
+    {  53, 0x002f, 0x0000002f, 0x00, 0x00, 0x0000 },
+    {  53, 0x003f, 0x0000003f, 0x01, 0x00, 0x0000 },
+    {  53, 0xffff, 0x01000003, 0x04, 0x00, 0x0000 },
+    {  54, 0xffff, 0x01000020, 0x00, 0x04, 0x0001 },
+    {  55, 0x002a, 0x2000002a, 0x00, 0x00, 0x0000 },
+    {  56, 0xffff, 0x01000023, 0x00, 0x04, 0x0008 },
+    {  57, 0x0020, 0x00000020, 0x00, 0x00, 0x0000 },
+    {  58, 0xffff, 0x01000024, 0x00, 0x00, 0x0000 },
+    {  59, 0xffff, 0x01000030, 0x00, 0x00, 0x0000 },
+    {  59, 0xffff, 0x0100003c, 0x01, 0x00, 0x0000 },
+    {  59, 0xffff, 0x01000048, 0x04, 0x00, 0x0000 },
+    {  59, 0xffff, 0x01000000, 0x0c, 0x08, 0x0100 },
+    {  60, 0xffff, 0x01000031, 0x00, 0x00, 0x0000 },
+    {  60, 0xffff, 0x0100003d, 0x01, 0x00, 0x0000 },
+    {  60, 0xffff, 0x01000049, 0x04, 0x00, 0x0000 },
+    {  60, 0xffff, 0x01000000, 0x0c, 0x08, 0x0101 },
+    {  61, 0xffff, 0x01000032, 0x00, 0x00, 0x0000 },
+    {  61, 0xffff, 0x0100003e, 0x01, 0x00, 0x0000 },
+    {  61, 0xffff, 0x0100004a, 0x04, 0x00, 0x0000 },
+    {  61, 0xffff, 0x01000000, 0x0c, 0x08, 0x0102 },
+    {  62, 0xffff, 0x01000033, 0x00, 0x00, 0x0000 },
+    {  62, 0xffff, 0x0100003f, 0x01, 0x00, 0x0000 },
+    {  62, 0xffff, 0x0100004b, 0x04, 0x00, 0x0000 },
+    {  62, 0xffff, 0x01000000, 0x0c, 0x08, 0x0103 },
+    {  63, 0xffff, 0x01000034, 0x00, 0x00, 0x0000 },
+    {  63, 0xffff, 0x01000040, 0x01, 0x00, 0x0000 },
+    {  63, 0xffff, 0x0100004c, 0x04, 0x00, 0x0000 },
+    {  63, 0xffff, 0x01000000, 0x0c, 0x08, 0x0104 },
+    {  64, 0xffff, 0x01000035, 0x00, 0x00, 0x0000 },
+    {  64, 0xffff, 0x01000041, 0x01, 0x00, 0x0000 },
+    {  64, 0xffff, 0x0100004d, 0x04, 0x00, 0x0000 },
+    {  64, 0xffff, 0x01000000, 0x0c, 0x08, 0x0105 },
+    {  65, 0xffff, 0x01000036, 0x00, 0x00, 0x0000 },
+    {  65, 0xffff, 0x01000042, 0x01, 0x00, 0x0000 },
+    {  65, 0xffff, 0x0100004e, 0x04, 0x00, 0x0000 },
+    {  65, 0xffff, 0x01000000, 0x0c, 0x08, 0x0106 },
+    {  66, 0xffff, 0x01000037, 0x00, 0x00, 0x0000 },
+    {  66, 0xffff, 0x01000043, 0x01, 0x00, 0x0000 },
+    {  66, 0xffff, 0x0100004f, 0x04, 0x00, 0x0000 },
+    {  66, 0xffff, 0x01000000, 0x0c, 0x08, 0x0107 },
+    {  67, 0xffff, 0x01000038, 0x00, 0x00, 0x0000 },
+    {  67, 0xffff, 0x01000044, 0x01, 0x00, 0x0000 },
+    {  67, 0xffff, 0x01000050, 0x04, 0x00, 0x0000 },
+    {  67, 0xffff, 0x01000000, 0x0c, 0x08, 0x0108 },
+    {  68, 0xffff, 0x01000039, 0x00, 0x00, 0x0000 },
+    {  68, 0xffff, 0x01000045, 0x01, 0x00, 0x0000 },
+    {  68, 0xffff, 0x01000051, 0x04, 0x00, 0x0000 },
+    {  68, 0xffff, 0x01000000, 0x0c, 0x08, 0x0109 },
+    {  69, 0xffff, 0x01000025, 0x00, 0x00, 0x0000 },
+    {  70, 0xffff, 0x01000026, 0x00, 0x00, 0x0000 },
+    {  70, 0xffff, 0x01000026, 0x08, 0x00, 0x0000 },
+    {  71, 0x0037, 0x20000037, 0x00, 0x00, 0x0000 },
+    {  72, 0x0038, 0x20000038, 0x00, 0x00, 0x0000 },
+    {  73, 0x0039, 0x20000039, 0x00, 0x00, 0x0000 },
+    {  74, 0x002d, 0x2000002d, 0x00, 0x00, 0x0000 },
+    {  75, 0x0034, 0x20000034, 0x00, 0x00, 0x0000 },
+    {  76, 0x0035, 0x20000035, 0x00, 0x00, 0x0000 },
+    {  77, 0x0036, 0x20000036, 0x00, 0x00, 0x0000 },
+    {  78, 0x002b, 0x2000002b, 0x00, 0x00, 0x0000 },
+    {  79, 0x0031, 0x20000031, 0x00, 0x00, 0x0000 },
+    {  80, 0x0032, 0x20000032, 0x00, 0x00, 0x0000 },
+    {  81, 0x0033, 0x20000033, 0x00, 0x00, 0x0000 },
+    {  82, 0x0030, 0x20000030, 0x00, 0x00, 0x0000 },
+    {  83, 0x002e, 0x2000002e, 0x00, 0x00, 0x0000 },
+    {  83, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
+    {  83, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+    {  86, 0x003c, 0x0000003c, 0x00, 0x00, 0x0000 },
+    {  86, 0x003e, 0x0000003e, 0x01, 0x00, 0x0000 },
+    {  86, 0x007c, 0x0000007c, 0x02, 0x00, 0x0000 },
+    {  87, 0xffff, 0x0100003a, 0x00, 0x00, 0x0000 },
+    {  87, 0xffff, 0x01000046, 0x01, 0x00, 0x0000 },
+    {  87, 0xffff, 0x01000052, 0x04, 0x00, 0x0000 },
+    {  87, 0xffff, 0x01000000, 0x0c, 0x08, 0x010a },
+    {  88, 0xffff, 0x0100003b, 0x00, 0x00, 0x0000 },
+    {  88, 0xffff, 0x01000047, 0x01, 0x00, 0x0000 },
+    {  88, 0xffff, 0x01000000, 0x0c, 0x08, 0x010b },
+    {  96, 0xffff, 0x21000005, 0x00, 0x00, 0x0000 },
+    {  97, 0xffff, 0x01000021, 0x00, 0x04, 0x0004 },
+    {  98, 0x002f, 0x2000002f, 0x00, 0x00, 0x0000 },
+    {  99, 0x005c, 0x0400005c, 0x00, 0x00, 0x0000 },
+    { 100, 0xffff, 0x01001103, 0x00, 0x04, 0x0002 },
+    { 102, 0xffff, 0x01000010, 0x00, 0x00, 0x0000 },
+    { 103, 0xffff, 0x01000013, 0x00, 0x00, 0x0000 },
+    { 104, 0xffff, 0x01000016, 0x00, 0x00, 0x0000 },
+    { 105, 0xffff, 0x01000012, 0x00, 0x00, 0x0000 },
+    { 105, 0xffff, 0x01000000, 0x0c, 0x08, 0x0180 },
+    { 106, 0xffff, 0x01000014, 0x00, 0x00, 0x0000 },
+    { 106, 0xffff, 0x01000000, 0x0c, 0x08, 0x0181 },
+    { 107, 0xffff, 0x01000011, 0x00, 0x00, 0x0000 },
+    { 108, 0xffff, 0x01000015, 0x00, 0x00, 0x0000 },
+    { 109, 0xffff, 0x01000017, 0x00, 0x00, 0x0000 },
+    { 110, 0xffff, 0x01000006, 0x00, 0x00, 0x0000 },
+    { 111, 0xffff, 0x01000007, 0x00, 0x00, 0x0000 },
+    { 111, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
+    { 111, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+    { 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 },
+};
+
+const QEvdevKeyboardMap::Composing QEvdevKeyboardHandler::s_keycompose_default[] = {
+    { 0x0060, 0x0041, 0x00c0 },
+    { 0x0060, 0x0061, 0x00e0 },
+    { 0x0027, 0x0041, 0x00c1 },
+    { 0x0027, 0x0061, 0x00e1 },
+    { 0x005e, 0x0041, 0x00c2 },
+    { 0x005e, 0x0061, 0x00e2 },
+    { 0x007e, 0x0041, 0x00c3 },
+    { 0x007e, 0x0061, 0x00e3 },
+    { 0x0022, 0x0041, 0x00c4 },
+    { 0x0022, 0x0061, 0x00e4 },
+    { 0x002d, 0x0061, 0x00aa },
+    { 0x002d, 0x0041, 0x00aa },
+    { 0x004f, 0x0041, 0x00c5 },
+    { 0x006f, 0x0061, 0x00e5 },
+    { 0x0030, 0x0041, 0x00c5 },
+    { 0x0030, 0x0061, 0x00e5 },
+    { 0x0041, 0x0041, 0x00c5 },
+    { 0x0061, 0x0061, 0x00e5 },
+    { 0x00b0, 0x0041, 0x00c5 },
+    { 0x00b0, 0x0061, 0x00e5 },
+    { 0x0041, 0x0045, 0x00c6 },
+    { 0x0061, 0x0065, 0x00e6 },
+    { 0x002c, 0x0043, 0x00c7 },
+    { 0x002c, 0x0063, 0x00e7 },
+    { 0x005e, 0x0043, 0x00c7 },
+    { 0x005e, 0x0063, 0x00e7 },
+    { 0x0060, 0x0045, 0x00c8 },
+    { 0x0060, 0x0065, 0x00e8 },
+    { 0x0027, 0x0045, 0x00c9 },
+    { 0x0027, 0x0065, 0x00e9 },
+    { 0x005e, 0x0045, 0x00ca },
+    { 0x005e, 0x0065, 0x00ea },
+    { 0x0022, 0x0045, 0x00cb },
+    { 0x0022, 0x0065, 0x00eb },
+    { 0x0060, 0x0049, 0x00cc },
+    { 0x0060, 0x0069, 0x00ec },
+    { 0x0027, 0x0049, 0x00cd },
+    { 0x0027, 0x0069, 0x00ed },
+    { 0x005e, 0x0049, 0x00ce },
+    { 0x005e, 0x0069, 0x00ee },
+    { 0x0022, 0x0049, 0x00cf },
+    { 0x0022, 0x0069, 0x00ef },
+    { 0x002d, 0x0044, 0x00d0 },
+    { 0x002d, 0x0064, 0x00f0 },
+    { 0x005e, 0x0044, 0x00d0 },
+    { 0x005e, 0x0064, 0x00f0 },
+    { 0x007e, 0x004e, 0x00d1 },
+    { 0x007e, 0x006e, 0x00f1 },
+    { 0x005e, 0x004e, 0x00d1 },
+    { 0x005e, 0x006e, 0x00f1 },
+    { 0x0060, 0x004f, 0x00d2 },
+    { 0x0060, 0x006f, 0x00f2 },
+    { 0x0027, 0x004f, 0x00d3 },
+    { 0x0027, 0x006f, 0x00f3 },
+    { 0x005e, 0x004f, 0x00d4 },
+    { 0x005e, 0x006f, 0x00f4 },
+    { 0x007e, 0x004f, 0x00d5 },
+    { 0x007e, 0x006f, 0x00f5 },
+    { 0x0022, 0x004f, 0x00d6 },
+    { 0x0022, 0x006f, 0x00f6 },
+    { 0x002f, 0x004f, 0x00d8 },
+    { 0x002f, 0x006f, 0x00f8 },
+    { 0x002d, 0x006f, 0x00ba },
+    { 0x002d, 0x004f, 0x00ba },
+    { 0x0060, 0x0055, 0x00d9 },
+    { 0x0060, 0x0075, 0x00f9 },
+    { 0x0027, 0x0055, 0x00da },
+    { 0x0027, 0x0075, 0x00fa },
+    { 0x005e, 0x0055, 0x00db },
+    { 0x005e, 0x0075, 0x00fb },
+    { 0x0022, 0x0055, 0x00dc },
+    { 0x0022, 0x0075, 0x00fc },
+    { 0x0027, 0x0059, 0x00dd },
+    { 0x0027, 0x0079, 0x00fd },
+    { 0x0054, 0x0048, 0x00de },
+    { 0x0074, 0x0068, 0x00fe },
+    { 0x0073, 0x0073, 0x00df },
+    { 0x0022, 0x0079, 0x00ff },
+    { 0x0073, 0x007a, 0x00df },
+    { 0x006e, 0x006e, 0x00f1 },
+    { 0x006e, 0x0068, 0x00f1 },
+    { 0x004e, 0x0059, 0x00d1 },
+    { 0x004e, 0x004e, 0x00d1 },
+    { 0x004e, 0x0048, 0x00d1 },
+    { 0x004e, 0x0079, 0x00d1 },
+    { 0x004e, 0x006e, 0x00d1 },
+    { 0x004e, 0x0068, 0x00d1 },
+    { 0x002d, 0x004c, 0x00a3 },
+    { 0x003c, 0x003c, 0x00ab },
+    { 0x003e, 0x003e, 0x00bb },
+    { 0x003f, 0x003f, 0x00bf },
+    { 0x005e, 0x003f, 0x00bf },
+    { 0x0021, 0x0021, 0x00a1 },
+    { 0x005e, 0x0021, 0x00a1 },
+    { 0x005e, 0x0031, 0x00b9 },
+    { 0x005e, 0x0032, 0x00b2 },
+    { 0x005e, 0x0033, 0x00b3 },
+    { 0x002b, 0x002d, 0x00b1 },
+    { 0x0063, 0x003d, 0x00a2 },
+    { 0x0063, 0x002f, 0x00a2 },
+    { 0x002f, 0x0063, 0x00a2 },
+    { 0x002d, 0x0063, 0x00a2 },
+    { 0x002d, 0x0043, 0x00a2 },
+    { 0x004c, 0x003d, 0x00a3 },
+    { 0x002d, 0x004c, 0x00a3 },
+    { 0x002d, 0x006c, 0x00a3 },
+    { 0x005e, 0x002a, 0x00d7 },
+    { 0x005e, 0x0078, 0x00d7 },
+    { 0x0078, 0x0078, 0x00d7 },
+    { 0x005e, 0x002e, 0x00b7 },
+    { 0x002e, 0x002e, 0x00b7 },
+    { 0x005e, 0x002f, 0x00f7 },
+    { 0x005e, 0x003a, 0x00f7 },
+    { 0x002d, 0x003a, 0x00f7 },
+    { 0x003a, 0x002d, 0x00f7 },
+    { 0x0059, 0x003d, 0x00a5 },
+    { 0x002d, 0x0059, 0x00a5 },
+    { 0x002d, 0x006c, 0x00a5 },
+    { 0x0028, 0x0063, 0x00a9 },
+    { 0x0022, 0x0063, 0x00a9 },
+    { 0x002d, 0x0061, 0x00aa },
+    { 0x002d, 0x0041, 0x00aa },
+    { 0x002d, 0x006f, 0x00ba },
+    { 0x002d, 0x004f, 0x00ba },
+    { 0x0028, 0x0072, 0x00ae },
+    { 0x0022, 0x0072, 0x00ae },
+    { 0x006d, 0x0075, 0x00b5 },
+    { 0x0031, 0x0034, 0x0152 },
+    { 0x0031, 0x0032, 0x0153 },
+    { 0x0033, 0x0034, 0x0178 },
+    { 0x0065, 0x003d, 0x20ac },
+    { 0x002d, 0x0065, 0x20ac },
+    { 0x002d, 0x0045, 0x20ac },
+    { 0x0076, 0x0053, 0x0160 },
+    { 0x005e, 0x0053, 0x0160 },
+    { 0x0076, 0x0073, 0x0161 },
+    { 0x005e, 0x0073, 0x0161 },
+    { 0x0076, 0x005a, 0x017d },
+    { 0x005e, 0x005a, 0x017d },
+    { 0x0076, 0x007a, 0x017e },
+    { 0x005e, 0x007a, 0x017e },
+    { 0x004f, 0x0045, 0x0152 },
+    { 0x004f, 0x0065, 0x0152 },
+    { 0x006f, 0x0065, 0x0153 },
+    { 0x0022, 0x0059, 0x0178 },
+    { 0x0069, 0x006a, 0x00ff },
+    { 0x0049, 0x004a, 0x0178 },
+};
+
+#endif // QEVDEVKEYBOARDHANDLER_DEFAULTMAP_H
diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.cpp
new file mode 100644 (file)
index 0000000..f9237e3
--- /dev/null
@@ -0,0 +1,490 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevdevkeyboardhandler.h"
+
+#include <qplatformdefs.h>
+
+#include <QSocketNotifier>
+#include <QStringList>
+#include <QWindowSystemInterface>
+#include <QCoreApplication>
+#include <private/qcore_unix_p.h>
+
+#include <linux/input.h>
+
+//#define QT_QPA_KEYMAP_DEBUG
+
+#ifdef QT_QPA_KEYMAP_DEBUG
+#include <qdebug.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// simple builtin US keymap
+#include "qevdevkeyboard_defaultmap.h"
+
+QEvdevKeyboardHandler::QEvdevKeyboardHandler(int deviceDescriptor, const QString &device, bool disableZap, bool enableCompose, const QString &keymapFile)
+    : m_fd(deviceDescriptor), m_device(device),
+      m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
+      m_no_zap(disableZap), m_do_compose(enableCompose),
+      m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
+{
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Create keyboard handler with for device" << device;
+#endif
+
+    setObjectName(QLatin1String("LinuxInput Keyboard Handler"));
+
+    memset(m_locks, 0, sizeof(m_locks));
+
+    if (keymapFile.isEmpty() || !loadKeymap(keymapFile))
+        unloadKeymap();
+
+    // socket notifier for events on the keyboard device
+    QSocketNotifier *notifier;
+    notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+    connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
+}
+
+QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
+{
+    unloadKeymap();
+
+    if (m_fd >= 0)
+        qt_safe_close(m_fd);
+}
+
+QEvdevKeyboardHandler *QEvdevKeyboardHandler::createLinuxInputKeyboardHandler(const QString &key, const QString &specification)
+{
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Try to create keyboard handler with" << key << specification;
+#else
+    Q_UNUSED(key)
+#endif
+
+    QString keymapFile;
+    QString device = "/dev/input/event0";
+    int repeatDelay = 400;
+    int repeatRate = 80;
+    bool disableZap = false;
+    bool enableCompose = false;
+
+    QStringList args = specification.split(QLatin1Char(':'));
+    foreach (const QString &arg, args) {
+        if (arg.startsWith(QLatin1String("keymap=")))
+            keymapFile = arg.mid(7);
+        else if (arg == QLatin1String("disable-zap"))
+            disableZap = true;
+        else if (arg == QLatin1String("enable-compose"))
+            enableCompose = true;
+        else if (arg.startsWith(QLatin1String("repeat-delay=")))
+            repeatDelay = arg.mid(13).toInt();
+        else if (arg.startsWith(QLatin1String("repeat-rate=")))
+            repeatRate = arg.mid(12).toInt();
+        else if (arg.startsWith(QLatin1String("/dev/")))
+            device = arg;
+    }
+
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Opening keyboard at" << device;
+#endif
+
+    int fd;
+    fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDWR, 0);
+    if (fd >= 0) {
+        if (repeatDelay > 0 && repeatRate > 0) {
+            int kbdrep[2] = { repeatDelay, repeatRate };
+            ::ioctl(fd, EVIOCSREP, kbdrep);
+        }
+
+        return new QEvdevKeyboardHandler(fd, device, disableZap, enableCompose, keymapFile);
+    } else {
+        qWarning("Cannot open keyboard input device '%s': %s", qPrintable(device), strerror(errno));
+        return 0;
+    }
+}
+
+void QEvdevKeyboardHandler::switchLed(int led, bool state)
+{
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "switchLed" << led << state;
+#endif
+
+    struct ::input_event led_ie;
+    ::gettimeofday(&led_ie.time, 0);
+    led_ie.type = EV_LED;
+    led_ie.code = led;
+    led_ie.value = state;
+
+    qt_safe_write(m_fd, &led_ie, sizeof(led_ie));
+}
+
+void QEvdevKeyboardHandler::readKeycode()
+{
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Read new keycode on" << m_device;
+#endif
+
+    struct ::input_event buffer[32];
+    int n = 0;
+
+    forever {
+        n = qt_safe_read(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
+
+        if (n == 0) {
+            qWarning("Got EOF from the input device.");
+            return;
+        } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+           qWarning("Could not read from input device: %s", strerror(errno));
+            return;
+        } else if (n % sizeof(buffer[0]) == 0) {
+            break;
+        }
+    }
+
+    n /= sizeof(buffer[0]);
+
+    for (int i = 0; i < n; ++i) {
+        if (buffer[i].type != EV_KEY)
+            continue;
+
+        quint16 code = buffer[i].code;
+        qint32 value = buffer[i].value;
+
+        QEvdevKeyboardHandler::KeycodeAction ka;
+        ka = processKeycode(code, value != 0, value == 2);
+
+        switch (ka) {
+        case QEvdevKeyboardHandler::CapsLockOn:
+        case QEvdevKeyboardHandler::CapsLockOff:
+            switchLed(LED_CAPSL, ka == QEvdevKeyboardHandler::CapsLockOn);
+            break;
+
+        case QEvdevKeyboardHandler::NumLockOn:
+        case QEvdevKeyboardHandler::NumLockOff:
+            switchLed(LED_NUML, ka == QEvdevKeyboardHandler::NumLockOn);
+            break;
+
+        case QEvdevKeyboardHandler::ScrollLockOn:
+        case QEvdevKeyboardHandler::ScrollLockOff:
+            switchLed(LED_SCROLLL, ka == QEvdevKeyboardHandler::ScrollLockOn);
+            break;
+
+        default:
+            // ignore console switching and reboot
+            break;
+        }
+    }
+}
+
+void QEvdevKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat)
+{
+    QWindowSystemInterface::handleKeyEvent(0, ( isPress ? QEvent::KeyPress : QEvent::KeyRelease ), keycode, modifiers, QString( unicode ), autoRepeat );
+}
+
+QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat)
+{
+    KeycodeAction result = None;
+    bool first_press = pressed && !autorepeat;
+
+    const QEvdevKeyboardMap::Mapping *map_plain = 0;
+    const QEvdevKeyboardMap::Mapping *map_withmod = 0;
+
+    // get a specific and plain mapping for the keycode and the current modifiers
+    for (int i = 0; i < m_keymap_size && !(map_plain && map_withmod); ++i) {
+        const QEvdevKeyboardMap::Mapping *m = m_keymap + i;
+        if (m->keycode == keycode) {
+            if (m->modifiers == 0)
+                map_plain = m;
+
+            quint8 testmods = m_modifiers;
+            if (m_locks[0] /*CapsLock*/ && (m->flags & QEvdevKeyboardMap::IsLetter))
+                testmods ^= QEvdevKeyboardMap::ModShift;
+            if (m->modifiers == testmods)
+                map_withmod = m;
+        }
+    }
+
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning("Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d  |  plain=%d, withmod=%d, size=%d", \
+             keycode, m_modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, \
+             map_plain ? map_plain - m_keymap : -1, \
+             map_withmod ? map_withmod - m_keymap : -1, \
+             m_keymap_size);
+#endif
+
+    const QEvdevKeyboardMap::Mapping *it = map_withmod ? map_withmod : map_plain;
+
+    if (!it) {
+#ifdef QT_QPA_KEYMAP_DEBUG
+        // we couldn't even find a plain mapping
+        qWarning("Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, m_modifiers);
+#endif
+        return result;
+    }
+
+    bool skip = false;
+    quint16 unicode = it->unicode;
+    quint32 qtcode = it->qtcode;
+
+    if ((it->flags & QEvdevKeyboardMap::IsModifier) && it->special) {
+        // this is a modifier, i.e. Shift, Alt, ...
+        if (pressed)
+            m_modifiers |= quint8(it->special);
+        else
+            m_modifiers &= ~quint8(it->special);
+    } else if (qtcode >= Qt::Key_CapsLock && qtcode <= Qt::Key_ScrollLock) {
+        // (Caps|Num|Scroll)Lock
+        if (first_press) {
+            quint8 &lock = m_locks[qtcode - Qt::Key_CapsLock];
+            lock ^= 1;
+
+            switch (qtcode) {
+            case Qt::Key_CapsLock  : result = lock ? CapsLockOn : CapsLockOff; m_modifiers ^= QEvdevKeyboardMap::ModShift; break;
+            case Qt::Key_NumLock   : result = lock ? NumLockOn : NumLockOff; break;
+            case Qt::Key_ScrollLock: result = lock ? ScrollLockOn : ScrollLockOff; break;
+            default                : break;
+            }
+        }
+    } else if ((it->flags & QEvdevKeyboardMap::IsSystem) && it->special && first_press) {
+        switch (it->special) {
+        case QEvdevKeyboardMap::SystemReboot:
+            result = Reboot;
+            break;
+
+        case QEvdevKeyboardMap::SystemZap:
+            if (!m_no_zap)
+                qApp->quit();
+            break;
+
+        case QEvdevKeyboardMap::SystemConsolePrevious:
+            result = PreviousConsole;
+            break;
+
+        case QEvdevKeyboardMap::SystemConsoleNext:
+            result = NextConsole;
+            break;
+
+        default:
+            if (it->special >= QEvdevKeyboardMap::SystemConsoleFirst &&
+                it->special <= QEvdevKeyboardMap::SystemConsoleLast) {
+                result = KeycodeAction(SwitchConsoleFirst + ((it->special & QEvdevKeyboardMap::SystemConsoleMask) & SwitchConsoleMask));
+            }
+            break;
+        }
+
+        skip = true; // no need to tell Qt about it
+    } else if ((qtcode == Qt::Key_Multi_key) && m_do_compose) {
+        // the Compose key was pressed
+        if (first_press)
+            m_composing = 2;
+        skip = true;
+    } else if ((it->flags & QEvdevKeyboardMap::IsDead) && m_do_compose) {
+        // a Dead key was pressed
+        if (first_press && m_composing == 1 && m_dead_unicode == unicode) { // twice
+            m_composing = 0;
+            qtcode = Qt::Key_unknown; // otherwise it would be Qt::Key_Dead...
+        } else if (first_press && unicode != 0xffff) {
+            m_dead_unicode = unicode;
+            m_composing = 1;
+            skip = true;
+        } else {
+            skip = true;
+        }
+    }
+
+    if (!skip) {
+        // a normal key was pressed
+        const int modmask = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier;
+
+        // we couldn't find a specific mapping for the current modifiers,
+        // or that mapping didn't have special modifiers:
+        // so just report the plain mapping with additional modifiers.
+        if ((it == map_plain && it != map_withmod) ||
+            (map_withmod && !(map_withmod->qtcode & modmask))) {
+            qtcode |= QEvdevKeyboardHandler::toQtModifiers(m_modifiers);
+        }
+
+        if (m_composing == 2 && first_press && !(it->flags & QEvdevKeyboardMap::IsModifier)) {
+            // the last key press was the Compose key
+            if (unicode != 0xffff) {
+                int idx = 0;
+                // check if this code is in the compose table at all
+                for ( ; idx < m_keycompose_size; ++idx) {
+                    if (m_keycompose[idx].first == unicode)
+                        break;
+                }
+                if (idx < m_keycompose_size) {
+                    // found it -> simulate a Dead key press
+                    m_dead_unicode = unicode;
+                    unicode = 0xffff;
+                    m_composing = 1;
+                    skip = true;
+                } else {
+                    m_composing = 0;
+                }
+            } else {
+                m_composing = 0;
+            }
+        } else if (m_composing == 1 && first_press && !(it->flags & QEvdevKeyboardMap::IsModifier)) {
+            // the last key press was a Dead key
+            bool valid = false;
+            if (unicode != 0xffff) {
+                int idx = 0;
+                // check if this code is in the compose table at all
+                for ( ; idx < m_keycompose_size; ++idx) {
+                    if (m_keycompose[idx].first == m_dead_unicode && m_keycompose[idx].second == unicode)
+                        break;
+                }
+                if (idx < m_keycompose_size) {
+                    quint16 composed = m_keycompose[idx].result;
+                    if (composed != 0xffff) {
+                        unicode = composed;
+                        qtcode = Qt::Key_unknown;
+                        valid = true;
+                    }
+                }
+            }
+            if (!valid) {
+                unicode = m_dead_unicode;
+                qtcode = Qt::Key_unknown;
+            }
+            m_composing = 0;
+        }
+
+        if (!skip) {
+#ifdef QT_QPA_KEYMAP_DEBUG
+            qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask));
+#endif
+
+            // send the result to the server
+            processKeyEvent(unicode, qtcode & ~modmask, Qt::KeyboardModifiers(qtcode & modmask), pressed, autorepeat);
+        }
+    }
+    return result;
+}
+
+void QEvdevKeyboardHandler::unloadKeymap()
+{
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Unload current keymap and restore built-in";
+#endif
+
+    if (m_keymap && m_keymap != s_keymap_default)
+        delete [] m_keymap;
+    if (m_keycompose && m_keycompose != s_keycompose_default)
+        delete [] m_keycompose;
+
+    m_keymap = s_keymap_default;
+    m_keymap_size = sizeof(s_keymap_default) / sizeof(s_keymap_default[0]);
+    m_keycompose = s_keycompose_default;
+    m_keycompose_size = sizeof(s_keycompose_default) / sizeof(s_keycompose_default[0]);
+
+    // reset state, so we could switch keymaps at runtime
+    m_modifiers = 0;
+    memset(m_locks, 0, sizeof(m_locks));
+    m_composing = 0;
+    m_dead_unicode = 0xffff;
+}
+
+bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
+{
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Load keymap" << file;
+#endif
+
+    QFile f(file);
+
+    if (!f.open(QIODevice::ReadOnly)) {
+        qWarning("Could not open keymap file '%s'", qPrintable(file));
+        return false;
+    }
+
+    // .qmap files have a very simple structure:
+    // quint32 magic           (QKeyboard::FileMagic)
+    // quint32 version         (1)
+    // quint32 keymap_size     (# of struct QKeyboard::Mappings)
+    // quint32 keycompose_size (# of struct QKeyboard::Composings)
+    // all QKeyboard::Mappings via QDataStream::operator(<<|>>)
+    // all QKeyboard::Composings via QDataStream::operator(<<|>>)
+
+    quint32 qmap_magic, qmap_version, qmap_keymap_size, qmap_keycompose_size;
+
+    QDataStream ds(&f);
+
+    ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
+
+    if (ds.status() != QDataStream::Ok || qmap_magic != QEvdevKeyboardMap::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
+        qWarning("'%s' is ot a valid.qmap keymap file.", qPrintable(file));
+        return false;
+    }
+
+    QEvdevKeyboardMap::Mapping *qmap_keymap = new QEvdevKeyboardMap::Mapping[qmap_keymap_size];
+    QEvdevKeyboardMap::Composing *qmap_keycompose = qmap_keycompose_size ? new QEvdevKeyboardMap::Composing[qmap_keycompose_size] : 0;
+
+    for (quint32 i = 0; i < qmap_keymap_size; ++i)
+        ds >> qmap_keymap[i];
+    for (quint32 i = 0; i < qmap_keycompose_size; ++i)
+        ds >> qmap_keycompose[i];
+
+    if (ds.status() != QDataStream::Ok) {
+        delete [] qmap_keymap;
+        delete [] qmap_keycompose;
+
+        qWarning("Keymap file '%s' can not be loaded.", qPrintable(file));
+        return false;
+    }
+
+    // unload currently active and clear state
+    unloadKeymap();
+
+    m_keymap = qmap_keymap;
+    m_keymap_size = qmap_keymap_size;
+    m_keycompose = qmap_keycompose;
+    m_keycompose_size = qmap_keycompose_size;
+
+    m_do_compose = true;
+
+    return true;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h b/src/plugins/generic/evdevkeyboard/qevdevkeyboardhandler.h
new file mode 100644 (file)
index 0000000..76b5c57
--- /dev/null
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVDEVKEYBOARDHANDLER_H
+#define QEVDEVKEYBOARDHANDLER_H
+
+#include <qobject.h>
+#include <QTimer>
+#include <QDataStream>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+namespace QEvdevKeyboardMap {
+    const quint32 FileMagic = 0x514d4150; // 'QMAP'
+
+    struct Mapping {
+        quint16 keycode;
+        quint16 unicode;
+        quint32 qtcode;
+        quint8 modifiers;
+        quint8 flags;
+        quint16 special;
+
+    };
+
+    enum Flags {
+        IsDead     = 0x01,
+        IsLetter   = 0x02,
+        IsModifier = 0x04,
+        IsSystem   = 0x08
+    };
+
+    enum System {
+        SystemConsoleFirst    = 0x0100,
+        SystemConsoleMask     = 0x007f,
+        SystemConsoleLast     = 0x017f,
+        SystemConsolePrevious = 0x0180,
+        SystemConsoleNext     = 0x0181,
+        SystemReboot          = 0x0200,
+        SystemZap             = 0x0300
+    };
+
+    struct Composing {
+        quint16 first;
+        quint16 second;
+        quint16 result;
+    };
+
+    enum Modifiers {
+        ModPlain   = 0x00,
+        ModShift   = 0x01,
+        ModAltGr   = 0x02,
+        ModControl = 0x04,
+        ModAlt     = 0x08,
+        ModShiftL  = 0x10,
+        ModShiftR  = 0x20,
+        ModCtrlL   = 0x40,
+        ModCtrlR   = 0x80
+        // ModCapsShift = 0x100, // not supported!
+    };
+}
+
+inline QDataStream &operator>>(QDataStream &ds, QEvdevKeyboardMap::Mapping &m)
+{
+    return ds >> m.keycode >> m.unicode >> m.qtcode >> m.modifiers >> m.flags >> m.special;
+}
+
+inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Mapping &m)
+{
+    return ds << m.keycode << m.unicode << m.qtcode << m.modifiers << m.flags << m.special;
+}
+
+inline QDataStream &operator>>(QDataStream &ds, QEvdevKeyboardMap::Composing &c)
+{
+    return ds >> c.first >> c.second >> c.result;
+}
+
+inline QDataStream &operator<<(QDataStream &ds, const QEvdevKeyboardMap::Composing &c)
+{
+    return ds << c.first << c.second << c.result;
+}
+
+
+class QEvdevKeyboardHandler : public QObject
+{
+    Q_OBJECT
+public:
+    QEvdevKeyboardHandler(int deviceDescriptor, const QString &device, bool disableZap, bool enableCompose, const QString &keymapFile);
+    ~QEvdevKeyboardHandler();
+
+    enum KeycodeAction {
+        None               = 0,
+
+        CapsLockOff        = 0x01000000,
+        CapsLockOn         = 0x01000001,
+        NumLockOff         = 0x02000000,
+        NumLockOn          = 0x02000001,
+        ScrollLockOff      = 0x03000000,
+        ScrollLockOn       = 0x03000001,
+
+        Reboot             = 0x04000000,
+
+        PreviousConsole    = 0x05000000,
+        NextConsole        = 0x05000001,
+        SwitchConsoleFirst = 0x06000000,
+        SwitchConsoleLast  = 0x0600007f,
+        SwitchConsoleMask  = 0x0000007f
+    };
+
+    static QEvdevKeyboardHandler *createLinuxInputKeyboardHandler(const QString &key, const QString &specification);
+
+    static Qt::KeyboardModifiers toQtModifiers(quint8 mod)
+    {
+        Qt::KeyboardModifiers qtmod = Qt::NoModifier;
+
+        if (mod & (QEvdevKeyboardMap::ModShift | QEvdevKeyboardMap::ModShiftL | QEvdevKeyboardMap::ModShiftR))
+            qtmod |= Qt::ShiftModifier;
+        if (mod & (QEvdevKeyboardMap::ModControl | QEvdevKeyboardMap::ModCtrlL | QEvdevKeyboardMap::ModCtrlR))
+            qtmod |= Qt::ControlModifier;
+        if (mod & QEvdevKeyboardMap::ModAlt)
+            qtmod |= Qt::AltModifier;
+
+        return qtmod;
+    }
+
+private slots:
+    void readKeycode();
+    KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat);
+
+private:
+    void unloadKeymap();
+    bool loadKeymap(const QString &file);
+    void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat);
+    void switchLed(int, bool);
+
+    int m_fd;
+    QString m_device;
+
+    // keymap handling
+    quint8 m_modifiers;
+    quint8 m_locks[3];
+    int m_composing;
+    quint16 m_dead_unicode;
+
+    bool m_no_zap;
+    bool m_do_compose;
+
+    const QEvdevKeyboardMap::Mapping *m_keymap;
+    int m_keymap_size;
+    const QEvdevKeyboardMap::Composing *m_keycompose;
+    int m_keycompose_size;
+
+    static const QEvdevKeyboardMap::Mapping s_keymap_default[];
+    static const QEvdevKeyboardMap::Composing s_keycompose_default[];
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QEVDEVKEYBOARDHANDLER_H
diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/plugins/generic/evdevkeyboard/qevdevkeyboardmanager.cpp
new file mode 100644 (file)
index 0000000..8769b70
--- /dev/null
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevdevkeyboardmanager.h"
+
+#include <QStringList>
+#include <QDebug>
+#include <QCoreApplication>
+
+#include <linux/input.h>
+#include <linux/kd.h>
+
+//#define QT_QPA_KEYMAP_DEBUG
+
+QT_BEGIN_NAMESPACE
+
+QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &specification)
+    : m_udev(0), m_udevMonitor(0), m_udevMonitorFileDescriptor(-1), m_udevSocketNotifier(0)
+{
+    Q_UNUSED(key);
+
+    bool useUDev = false;
+    QStringList args = specification.split(QLatin1Char(':'));
+    QStringList devices;
+
+    foreach (const QString &arg, args) {
+        if (arg.startsWith("udev") && !arg.contains("no")) {
+            useUDev = true;
+        } else if (arg.startsWith("/dev/")) {
+            // if device is specified try to use it
+            devices.append(arg);
+            args.removeAll(arg);
+        }
+    }
+
+    m_spec = args.join(":");
+
+    // add all keyboards for devices specified in the argument list
+    foreach (const QString &device, devices)
+        addKeyboard(device);
+
+    // no udev and no devices specified, try a fallback
+    if (!useUDev && devices.isEmpty()) {
+        addKeyboard();
+        return;
+    }
+
+    m_udev = udev_new();
+    if (!m_udev) {
+        qWarning() << "Failed to read udev configuration. Try to open a keyboard without it";
+        addKeyboard();
+    } else {
+        // Look for already attached devices:
+        parseConnectedDevices();
+        // Watch for device add/remove
+        startWatching();
+    }
+}
+
+QEvdevKeyboardManager::~QEvdevKeyboardManager()
+{
+    // cleanup udev related resources
+    stopWatching();
+    if (m_udev)
+        udev_unref(m_udev);
+
+    // cleanup all resources of connected keyboards
+    qDeleteAll(m_keyboards);
+    m_keyboards.clear();
+}
+
+void QEvdevKeyboardManager::addKeyboard(const QString &devnode)
+{
+    QString specification = m_spec;
+    QString deviceString = devnode;
+
+    if (!deviceString.isEmpty()) {
+        specification.append(":");
+        specification.append(deviceString);
+    } else {
+        deviceString = "default";
+    }
+
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Adding keyboard at" << deviceString;
+#endif
+
+    QEvdevKeyboardHandler *keyboard;
+    keyboard = QEvdevKeyboardHandler::createLinuxInputKeyboardHandler("EvdevKeyboard", specification);
+    if (keyboard)
+        m_keyboards.insert(deviceString, keyboard);
+    else
+        qWarning() << "Failed to open keyboard";
+}
+
+void QEvdevKeyboardManager::removeKeyboard(const QString &devnode)
+{
+    if (m_keyboards.contains(devnode)) {
+#ifdef QT_QPA_KEYMAP_DEBUG
+    qWarning() << "Removing keyboard at" << devnode;
+#endif
+        QEvdevKeyboardHandler *keyboard = m_keyboards.value(devnode);
+        m_keyboards.remove(devnode);
+        delete keyboard;
+    }
+}
+
+void QEvdevKeyboardManager::startWatching()
+{
+    m_udevMonitor = udev_monitor_new_from_netlink(m_udev, "udev");
+    if (!m_udevMonitor) {
+#ifdef QT_QPA_KEYMAP_DEBUG
+        qWarning("Unable to create an Udev monitor. No devices can be detected.");
+#endif
+        return;
+    }
+
+    udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitor, "input", NULL);
+    udev_monitor_enable_receiving(m_udevMonitor);
+    m_udevMonitorFileDescriptor = udev_monitor_get_fd(m_udevMonitor);
+
+    m_udevSocketNotifier = new QSocketNotifier(m_udevMonitorFileDescriptor, QSocketNotifier::Read, this);
+    connect(m_udevSocketNotifier, SIGNAL(activated(int)), this, SLOT(deviceDetected()));
+}
+
+void QEvdevKeyboardManager::stopWatching()
+{
+    if (m_udevSocketNotifier)
+        delete m_udevSocketNotifier;
+
+    if (m_udevMonitor)
+        udev_monitor_unref(m_udevMonitor);
+
+    m_udevSocketNotifier = 0;
+    m_udevMonitor = 0;
+    m_udevMonitorFileDescriptor = 0;
+}
+
+void QEvdevKeyboardManager::deviceDetected()
+{
+    if (!m_udevMonitor)
+        return;
+
+    struct udev_device *dev;
+    dev = udev_monitor_receive_device(m_udevMonitor);
+    if (!dev)
+        return;
+
+    if (qstrcmp(udev_device_get_action(dev), "add") == 0) {
+        checkDevice(dev);
+    } else {
+        // We can't determine what the device was, so we handle false positives outside of this class
+        QString str = udev_device_get_devnode(dev);
+        if (!str.isEmpty())
+            removeKeyboard(str);
+    }
+
+    udev_device_unref(dev);
+}
+
+void QEvdevKeyboardManager::parseConnectedDevices()
+{
+    struct udev_enumerate *enumerate;
+    struct udev_list_entry *devices;
+    struct udev_list_entry *dev_list_entry;
+    struct udev_device *dev;
+    const char *str;
+
+    enumerate = udev_enumerate_new(m_udev);
+    udev_enumerate_add_match_subsystem(enumerate, "input");
+    udev_enumerate_scan_devices(enumerate);
+    devices = udev_enumerate_get_list_entry(enumerate);
+
+    udev_list_entry_foreach(dev_list_entry, devices) {
+        str = udev_list_entry_get_name(dev_list_entry);
+        dev = udev_device_new_from_syspath(m_udev, str);
+        checkDevice(dev);
+    }
+
+    udev_enumerate_unref(enumerate);
+}
+
+void QEvdevKeyboardManager::checkDevice(udev_device *dev)
+{
+    const char *str;
+    QString devnode;
+
+    str = udev_device_get_devnode(dev);
+    if (!str)
+        return;
+
+    devnode = str;
+
+    dev = udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL);
+    if (!dev)
+        return;
+
+    str = udev_device_get_sysattr_value(dev, "capabilities/key");
+    QStringList val = QString(str).split(' ', QString::SkipEmptyParts);
+
+    bool ok;
+    unsigned long long keys = val.last().toULongLong(&ok, 16);
+    if (!ok)
+        return;
+
+    // Tests if the letter Q is valid for the device.  We may want to alter this test, but it seems mostly reliable.
+    bool test = (keys >> KEY_Q) & 1;
+    if (test) {
+        addKeyboard(devnode);
+        return;
+    }
+}
diff --git a/src/plugins/generic/evdevkeyboard/qevdevkeyboardmanager.h b/src/plugins/generic/evdevkeyboard/qevdevkeyboardmanager.h
new file mode 100644 (file)
index 0000000..11892d1
--- /dev/null
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVDEVKEYBOARDMANAGER_H
+#define QEVDEVKEYBOARDMANAGER_H
+
+#include "qevdevkeyboardhandler.h"
+
+#include <QObject>
+#include <QHash>
+#include <QSocketNotifier>
+
+#include <libudev.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QEvdevKeyboardManager : public QObject
+{
+    Q_OBJECT
+public:
+    explicit QEvdevKeyboardManager(const QString &key, const QString &specification);
+    ~QEvdevKeyboardManager();
+
+private slots:
+    void deviceDetected();
+
+private:
+    void startWatching();
+    void stopWatching();
+    void parseConnectedDevices();
+    void checkDevice(struct udev_device *dev);
+
+    void addKeyboard(const QString &devnode = QString());
+    void removeKeyboard(const QString &devnode);
+
+    QString m_spec;
+    QHash<QString,QEvdevKeyboardHandler*> m_keyboards;
+
+    struct udev *m_udev;
+    struct udev_monitor *m_udevMonitor;
+    int m_udevMonitorFileDescriptor;
+    QSocketNotifier *m_udevSocketNotifier;
+};
+
+#endif // QEVDEVKEYBOARDMANAGER_H
index c4c3f92..06bc009 100644 (file)
@@ -4,6 +4,6 @@ linux-g++-maemo: SUBDIRS += meego
 
 contains(QT_CONFIG, evdev) {
     contains(QT_CONFIG, libudev) {
-        SUBDIRS += evdevmouse evdevtouch
+        SUBDIRS += evdevmouse evdevtouch evdevkeyboard
     }
 }