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