android: work around android's linux/input.h being retarded.
[profile/ivi/qtbase.git] / src / platformsupport / devicediscovery / qdevicediscovery_static.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdevicediscovery_p.h"
43
44 #include <QStringList>
45 #include <QCoreApplication>
46 #include <QObject>
47 #include <QHash>
48 #include <QDir>
49 #include <QtCore/private/qcore_unix_p.h>
50
51 #include <linux/input.h>
52 #include <fcntl.h>
53
54 /* android (and perhaps some other linux-derived stuff) don't define everything
55  * in linux/input.h, so we'll need to do that ourselves.
56  */
57 #ifndef KEY_CNT
58 #define KEY_CNT                 (KEY_MAX+1)
59 #endif
60 #ifndef REL_CNT
61 #define REL_CNT                 (REL_MAX+1)
62 #endif
63 #ifndef ABS_CNT
64 #define ABS_CNT                 (ABS_MAX+1)
65 #endif
66
67
68 //#define QT_QPA_DEVICE_DISCOVERY_DEBUG
69
70 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
71 #include <QtDebug>
72 #endif
73
74 #define LONG_BITS (sizeof(long) * 8 )
75 #define LONG_FIELD_SIZE(bits) ((bits / LONG_BITS) + 1)
76
77 static bool testBit(long bit, const long *field)
78 {
79     return (field[bit / LONG_BITS] >> bit % LONG_BITS) & 1;
80 }
81
82 QT_BEGIN_NAMESPACE
83
84 QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent)
85 {
86     return new QDeviceDiscovery(types, parent);
87 }
88
89 QDeviceDiscovery::QDeviceDiscovery(QDeviceTypes types, QObject *parent) :
90     QObject(parent),
91     m_types(types)
92 {
93 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
94     qWarning() << "New DeviceDiscovery created for type" << types;
95 #endif
96 }
97
98 QDeviceDiscovery::~QDeviceDiscovery()
99 {
100 }
101
102 QStringList QDeviceDiscovery::scanConnectedDevices()
103 {
104     QStringList devices;
105
106     // check for input devices
107     QDir dir(QString::fromLatin1(QT_EVDEV_DEVICE_PATH));
108     dir.setFilter(QDir::System);
109
110     foreach (const QString &deviceFile, dir.entryList()) {
111         QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile;
112         if (checkDeviceType(absoluteFilePath))
113             devices << absoluteFilePath;
114     }
115
116     // check for drm devices
117     dir.setPath(QString::fromLatin1(QT_DRM_DEVICE_PATH));
118     foreach (const QString &deviceFile, dir.entryList()) {
119         QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile;
120         if (checkDeviceType(absoluteFilePath))
121             devices << absoluteFilePath;
122     }
123
124 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
125     qWarning() << "DeviceDiscovery found matching devices" << devices;
126 #endif
127
128     return devices;
129 }
130
131 bool QDeviceDiscovery::checkDeviceType(const QString &device)
132 {
133     bool ret = false;
134     int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
135     if (!fd) {
136 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
137         qWarning() << "DeviceDiscovery cannot open device" << device;
138 #endif
139         return false;
140     }
141
142     long bitsKey[LONG_FIELD_SIZE(KEY_CNT)];
143     if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey) >= 0 ) {
144         if (!ret && (m_types & Device_Keyboard)) {
145             if (testBit(KEY_Q, bitsKey)) {
146 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
147                 qWarning() << "DeviceDiscovery found keyboard at" << device;
148 #endif
149                 ret = true;
150             }
151         }
152
153         if (!ret && (m_types & Device_Mouse)) {
154             long bitsRel[LONG_FIELD_SIZE(REL_CNT)];
155             if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel) >= 0 ) {
156                 if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) {
157 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
158                     qWarning() << "DeviceDiscovery found mouse at" << device;
159 #endif
160                     ret = true;
161                 }
162             }
163         }
164
165         if (!ret && (m_types & (Device_Touchpad | Device_Touchscreen))) {
166             long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)];
167             if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs) >= 0 ) {
168                 if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) {
169                     if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) {
170 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
171                         qWarning() << "DeviceDiscovery found touchpad at" << device;
172 #endif
173                         ret = true;
174                     } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) {
175 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
176                         qWarning() << "DeviceDiscovery found touchscreen at" << device;
177 #endif
178                         ret = true;
179                     } else if ((m_types & Device_Tablet) && (testBit(BTN_STYLUS, bitsKey) || testBit(BTN_TOOL_PEN, bitsKey))) {
180 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
181                         qWarning() << "DeviceDiscovery found tablet at" << device;
182 #endif
183                         ret = true;
184                     }
185                 }
186             }
187         }
188     }
189
190     if (!ret && (m_types & Device_DRM) && device.contains(QString::fromLatin1(QT_DRM_DEVICE_PREFIX)))
191         ret = true;
192
193     QT_CLOSE(fd);
194     return ret;
195 }
196
197 QT_END_NAMESPACE