1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the plugins of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
40 ****************************************************************************/
42 #include "qdevicediscovery_p.h"
44 #include <QStringList>
45 #include <QCoreApplication>
49 #include <QtCore/private/qcore_unix_p.h>
51 #include <linux/input.h>
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.
58 #define KEY_CNT (KEY_MAX+1)
61 #define REL_CNT (REL_MAX+1)
64 #define ABS_CNT (ABS_MAX+1)
68 //#define QT_QPA_DEVICE_DISCOVERY_DEBUG
70 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
74 #define LONG_BITS (sizeof(long) * 8 )
75 #define LONG_FIELD_SIZE(bits) ((bits / LONG_BITS) + 1)
77 static bool testBit(long bit, const long *field)
79 return (field[bit / LONG_BITS] >> bit % LONG_BITS) & 1;
84 QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent)
86 return new QDeviceDiscovery(types, parent);
89 QDeviceDiscovery::QDeviceDiscovery(QDeviceTypes types, QObject *parent) :
93 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
94 qWarning() << "New DeviceDiscovery created for type" << types;
98 QDeviceDiscovery::~QDeviceDiscovery()
102 QStringList QDeviceDiscovery::scanConnectedDevices()
106 // check for input devices
107 QDir dir(QString::fromLatin1(QT_EVDEV_DEVICE_PATH));
108 dir.setFilter(QDir::System);
110 foreach (const QString &deviceFile, dir.entryList()) {
111 QString absoluteFilePath = dir.absolutePath() + QString::fromLatin1("/") + deviceFile;
112 if (checkDeviceType(absoluteFilePath))
113 devices << absoluteFilePath;
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;
124 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
125 qWarning() << "DeviceDiscovery found matching devices" << devices;
131 bool QDeviceDiscovery::checkDeviceType(const QString &device)
134 int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
136 #ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG
137 qWarning() << "DeviceDiscovery cannot open device" << device;
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;
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;
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;
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;
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;
190 if (!ret && (m_types & Device_DRM) && device.contains(QString::fromLatin1(QT_DRM_DEVICE_PREFIX)))