Line | Source | Count |
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | | - |
7 | | - |
8 | | - |
9 | | - |
10 | | - |
11 | | - |
12 | | - |
13 | | - |
14 | | - |
15 | | - |
16 | | - |
17 | | - |
18 | | - |
19 | | - |
20 | | - |
21 | | - |
22 | | - |
23 | | - |
24 | | - |
25 | | - |
26 | | - |
27 | | - |
28 | | - |
29 | | - |
30 | | - |
31 | | - |
32 | | - |
33 | | - |
34 | | - |
35 | | - |
36 | | - |
37 | | - |
38 | | - |
39 | | - |
40 | #include "qdevicediscovery_udev_p.h" | - |
41 | | - |
42 | #include <QStringList> | - |
43 | #include <QCoreApplication> | - |
44 | #include <QObject> | - |
45 | #include <QHash> | - |
46 | #include <QSocketNotifier> | - |
47 | #include <QLoggingCategory> | - |
48 | | - |
49 | #include <linux/input.h> | - |
50 | | - |
51 | QT_BEGIN_NAMESPACE | - |
52 | | - |
53 | Q_LOGGING_CATEGORY(lcDD, "qt.qpa.input") never executed: return category; | 0 |
54 | | - |
55 | QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent) | - |
56 | { | - |
57 | qCDebug(lcDD) << "udev device discovery for type" << types; never executed: QMessageLogger(__FILE__, 57, __PRETTY_FUNCTION__, lcDD().categoryName()).debug() << "udev device discovery for type" << types; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
58 | | - |
59 | QDeviceDiscovery *helper = 0; | - |
60 | struct udev *udev; | - |
61 | | - |
62 | udev = udev_new(); | - |
63 | if (udev) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
64 | helper = new QDeviceDiscoveryUDev(types, udev, parent); | - |
65 | } else { never executed: end of block | 0 |
66 | qWarning("Failed to get udev library context"); | - |
67 | } never executed: end of block | 0 |
68 | | - |
69 | return helper; never executed: return helper; | 0 |
70 | } | - |
71 | | - |
72 | QDeviceDiscoveryUDev::QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev, QObject *parent) : | - |
73 | QDeviceDiscovery(types, parent), | - |
74 | m_udev(udev), m_udevMonitor(0), m_udevMonitorFileDescriptor(-1), m_udevSocketNotifier(0) | - |
75 | { | - |
76 | if (!m_udev)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
77 | return; never executed: return; | 0 |
78 | | - |
79 | m_udevMonitor = udev_monitor_new_from_netlink(m_udev, "udev"); | - |
80 | if (!m_udevMonitor) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
81 | qWarning("Unable to create an udev monitor. No devices can be detected."); | - |
82 | return; never executed: return; | 0 |
83 | } | - |
84 | | - |
85 | udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitor, "input", 0); | - |
86 | udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitor, "drm", 0); | - |
87 | udev_monitor_enable_receiving(m_udevMonitor); | - |
88 | m_udevMonitorFileDescriptor = udev_monitor_get_fd(m_udevMonitor); | - |
89 | | - |
90 | m_udevSocketNotifier = new QSocketNotifier(m_udevMonitorFileDescriptor, QSocketNotifier::Read, this); | - |
91 | connect(m_udevSocketNotifier, SIGNAL(activated(int)), this, SLOT(handleUDevNotification())); | - |
92 | } never executed: end of block | 0 |
93 | | - |
94 | QDeviceDiscoveryUDev::~QDeviceDiscoveryUDev() | - |
95 | { | - |
96 | if (m_udevMonitor)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
97 | udev_monitor_unref(m_udevMonitor); never executed: udev_monitor_unref(m_udevMonitor); | 0 |
98 | | - |
99 | if (m_udev)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
100 | udev_unref(m_udev); never executed: udev_unref(m_udev); | 0 |
101 | } never executed: end of block | 0 |
102 | | - |
103 | QStringList QDeviceDiscoveryUDev::scanConnectedDevices() | - |
104 | { | - |
105 | QStringList devices; | - |
106 | | - |
107 | if (!m_udev)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
108 | return devices; never executed: return devices; | 0 |
109 | | - |
110 | udev_enumerate *ue = udev_enumerate_new(m_udev); | - |
111 | udev_enumerate_add_match_subsystem(ue, "input"); | - |
112 | udev_enumerate_add_match_subsystem(ue, "drm"); | - |
113 | | - |
114 | if (m_types & Device_Mouse)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
115 | udev_enumerate_add_match_property(ue, "ID_INPUT_MOUSE", "1"); never executed: udev_enumerate_add_match_property(ue, "ID_INPUT_MOUSE", "1"); | 0 |
116 | if (m_types & Device_Touchpad)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
117 | udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHPAD", "1"); never executed: udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHPAD", "1"); | 0 |
118 | if (m_types & Device_Touchscreen)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
119 | udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHSCREEN", "1"); never executed: udev_enumerate_add_match_property(ue, "ID_INPUT_TOUCHSCREEN", "1"); | 0 |
120 | if (m_types & Device_Keyboard) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
121 | udev_enumerate_add_match_property(ue, "ID_INPUT_KEYBOARD", "1"); | - |
122 | udev_enumerate_add_match_property(ue, "ID_INPUT_KEY", "1"); | - |
123 | } never executed: end of block | 0 |
124 | if (m_types & Device_Tablet)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
125 | udev_enumerate_add_match_property(ue, "ID_INPUT_TABLET", "1"); never executed: udev_enumerate_add_match_property(ue, "ID_INPUT_TABLET", "1"); | 0 |
126 | if (m_types & Device_Joystick)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
127 | udev_enumerate_add_match_property(ue, "ID_INPUT_JOYSTICK", "1"); never executed: udev_enumerate_add_match_property(ue, "ID_INPUT_JOYSTICK", "1"); | 0 |
128 | | - |
129 | if (udev_enumerate_scan_devices(ue) != 0) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
130 | qWarning("Failed to scan devices"); | - |
131 | return devices; never executed: return devices; | 0 |
132 | } | - |
133 | | - |
134 | udev_list_entry *entry; | - |
135 | udev_list_entry_foreach (entry, udev_enumerate_get_list_entry(ue)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
136 | const char *syspath = udev_list_entry_get_name(entry); | - |
137 | udev_device *udevice = udev_device_new_from_syspath(m_udev, syspath); | - |
138 | QString candidate = QString::fromUtf8(udev_device_get_devnode(udevice)); | - |
139 | if ((m_types & Device_InputMask) && candidate.startsWith(QLatin1String(QT_EVDEV_DEVICE)))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
140 | devices << candidate; never executed: devices << candidate; | 0 |
141 | if ((m_types & Device_VideoMask) && candidate.startsWith(QLatin1String(QT_DRM_DEVICE))) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
142 | if (m_types & Device_DRM_PrimaryGPU) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
143 | udev_device *pci = udev_device_get_parent_with_subsystem_devtype(udevice, "pci", 0); | - |
144 | if (pci) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
145 | if (qstrcmp(udev_device_get_sysattr_value(pci, "boot_vga"), "1") == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
146 | devices << candidate; never executed: devices << candidate; | 0 |
147 | } never executed: end of block | 0 |
148 | } else never executed: end of block | 0 |
149 | devices << candidate; never executed: devices << candidate; | 0 |
150 | } | - |
151 | | - |
152 | udev_device_unref(udevice); | - |
153 | } never executed: end of block | 0 |
154 | udev_enumerate_unref(ue); | - |
155 | | - |
156 | qCDebug(lcDD) << "Found matching devices" << devices; never executed: QMessageLogger(__FILE__, 156, __PRETTY_FUNCTION__, lcDD().categoryName()).debug() << "Found matching devices" << devices; TRUE | never evaluated | FALSE | never evaluated |
| 0 |
157 | | - |
158 | return devices; never executed: return devices; | 0 |
159 | } | - |
160 | | - |
161 | void QDeviceDiscoveryUDev::handleUDevNotification() | - |
162 | { | - |
163 | if (!m_udevMonitor)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
164 | return; never executed: return; | 0 |
165 | | - |
166 | struct udev_device *dev; | - |
167 | QString devNode; | - |
168 | | - |
169 | dev = udev_monitor_receive_device(m_udevMonitor); | - |
170 | if (!dev)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
171 | goto cleanup; never executed: goto cleanup; | 0 |
172 | | - |
173 | const char *action; | - |
174 | action = udev_device_get_action(dev); | - |
175 | if (!action)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
176 | goto cleanup; never executed: goto cleanup; | 0 |
177 | | - |
178 | const char *str; | - |
179 | str = udev_device_get_devnode(dev); | - |
180 | if (!str)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
181 | goto cleanup; never executed: goto cleanup; | 0 |
182 | | - |
183 | const char *subsystem; | - |
184 | devNode = QString::fromUtf8(str); | - |
185 | if (devNode.startsWith(QLatin1String(QT_EVDEV_DEVICE)))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
186 | subsystem = "input"; never executed: subsystem = "input"; | 0 |
187 | else if (devNode.startsWith(QLatin1String(QT_DRM_DEVICE)))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
188 | subsystem = "drm"; never executed: subsystem = "drm"; | 0 |
189 | else goto cleanup; never executed: goto cleanup; | 0 |
190 | | - |
191 | | - |
192 | if (!checkDeviceType(dev)) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
193 | | - |
194 | struct udev_device *parent_dev = udev_device_get_parent_with_subsystem_devtype(dev, subsystem, 0); | - |
195 | if (!parent_dev)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
196 | goto cleanup; never executed: goto cleanup; | 0 |
197 | | - |
198 | if (!checkDeviceType(parent_dev))TRUE | never evaluated | FALSE | never evaluated |
| 0 |
199 | goto cleanup; never executed: goto cleanup; | 0 |
200 | } never executed: end of block | 0 |
201 | | - |
202 | if (qstrcmp(action, "add") == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
203 | emit deviceDetected(devNode); never executed: deviceDetected(devNode); | 0 |
204 | | - |
205 | if (qstrcmp(action, "remove") == 0)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
206 | emit deviceRemoved(devNode); never executed: deviceRemoved(devNode); | 0 |
207 | | - |
208 | cleanup: code before this statement never executed: cleanup: | 0 |
209 | udev_device_unref(dev); | - |
210 | } never executed: end of block | 0 |
211 | | - |
212 | bool QDeviceDiscoveryUDev::checkDeviceType(udev_device *dev) | - |
213 | { | - |
214 | if (!dev)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
215 | return false; never executed: return false; | 0 |
216 | | - |
217 | if ((m_types & Device_Keyboard) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"), "1") == 0 )) {TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
218 | const QString capabilities_key = QString::fromUtf8(udev_device_get_sysattr_value(dev, "capabilities/key")); | - |
219 | const auto val = capabilities_key.splitRef(QLatin1Char(' '), QString::SkipEmptyParts); | - |
220 | if (!val.isEmpty()) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
221 | bool ok; | - |
222 | unsigned long long keys = val.last().toULongLong(&ok, 16); | - |
223 | if (ok) {TRUE | never evaluated | FALSE | never evaluated |
| 0 |
224 | | - |
225 | bool test = (keys >> KEY_Q) & 1; | - |
226 | if (test)TRUE | never evaluated | FALSE | never evaluated |
| 0 |
227 | return true; never executed: return true; | 0 |
228 | } never executed: end of block | 0 |
229 | } never executed: end of block | 0 |
230 | } never executed: end of block | 0 |
231 | | - |
232 | if ((m_types & Device_Keyboard) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEY"), "1") == 0 ))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
233 | return true; never executed: return true; | 0 |
234 | | - |
235 | if ((m_types & Device_Mouse) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_MOUSE"), "1") == 0))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
236 | return true; never executed: return true; | 0 |
237 | | - |
238 | if ((m_types & Device_Touchpad) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"), "1") == 0))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
239 | return true; never executed: return true; | 0 |
240 | | - |
241 | if ((m_types & Device_Touchscreen) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"), "1") == 0))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
242 | return true; never executed: return true; | 0 |
243 | | - |
244 | if ((m_types & Device_Tablet) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TABLET"), "1") == 0))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
245 | return true; never executed: return true; | 0 |
246 | | - |
247 | if ((m_types & Device_Joystick) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"), "1") == 0))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
248 | return true; never executed: return true; | 0 |
249 | | - |
250 | if ((m_types & Device_DRM) && (qstrcmp(udev_device_get_subsystem(dev), "drm") == 0))TRUE | never evaluated | FALSE | never evaluated |
TRUE | never evaluated | FALSE | never evaluated |
| 0 |
251 | return true; never executed: return true; | 0 |
252 | | - |
253 | return false; never executed: return false; | 0 |
254 | } | - |
255 | | - |
256 | QT_END_NAMESPACE | - |
| | |