Solid

windevice.cpp
1/*
2 SPDX-FileCopyrightText: 2013 Patrick von Reth <vonreth@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
5*/
6
7#include "windevice.h"
8#include <solid/deviceinterface.h>
9
10#include "winbattery.h"
11#include "winblock.h"
12#include "wingenericinterface.h"
13#include "winopticaldisc.h"
14#include "winopticaldrive.h"
15#include "winprocessor.h"
16#include "winstorageaccess.h"
17#include "winstoragedrive.h"
18#include "winstoragevolume.h"
19
20#include <batclass.h>
21
22#if defined(__MINGW32__) && !defined(IOCTL_STORAGE_QUERY_PROPERTY)
23#include <winioctl_backport.h>
24#endif
25
26using namespace Solid::Backends::Win;
27
28WinDevice::WinDevice(const QString &udi)
29 : Device()
30 , m_udi(udi)
31 , m_type(Solid::DeviceInterface::Unknown)
32{
33 /*
34 /org/kde/solid/win/volume/disk #%1, partition #%2
35 /org/kde/solid/win/storage.cdrom/disk #%0
36 */
37 QStringList data = udi.split(QLatin1Char('/'));
38 QString parentName = data[6].split(QLatin1Char(','))[0].trimmed();
39 QString type = data[5];
40
41 if (type == QLatin1String("storage")) {
42 m_type = Solid::DeviceInterface::StorageDrive;
43 } else if (type == QLatin1String("volume")) {
44 m_type = Solid::DeviceInterface::StorageVolume;
45 } else if (type == QLatin1String("storage.cdrom")) {
46 m_type = Solid::DeviceInterface::OpticalDrive;
47 } else if (type == QLatin1String("volume.cdrom")) {
48 m_type = Solid::DeviceInterface::OpticalDisc;
49 } else if (type == QLatin1String("cpu")) {
50 m_type = Solid::DeviceInterface::Processor;
51 } else if (type == QLatin1String("power.battery")) {
52 m_type = Solid::DeviceInterface::Battery;
53 } else if (type == QLatin1String("volume.virtual")) {
54 m_type = Solid::DeviceInterface::StorageAccess;
55 }
56
57 switch (m_type) {
58 case Solid::DeviceInterface::StorageVolume: {
59 m_parentUdi = QLatin1String("/org/kde/solid/win/storage/") + parentName;
60 break;
61 }
62 case Solid::DeviceInterface::OpticalDisc: {
63 m_parentUdi = QLatin1String("/org/kde/solid/win/storage.cdrom/") + parentName;
64 break;
65 }
66 case Solid::DeviceInterface::StorageAccess: {
67 m_parentUdi = WinBlock::udiFromDriveLetter(WinBlock::resolveVirtualDrive(udi).mid(0, 2));
68 if (m_parentUdi.isEmpty()) {
69 m_parentUdi = QLatin1String("/org/kde/solid/win/") + type;
70 }
71 break;
72 }
73 default:
74 m_parentUdi = QLatin1String("/org/kde/solid/win/") + type;
75 }
76
77 switch (m_type) {
78 case Solid::DeviceInterface::Processor:
79 initCpuDevice();
80 break;
81 case Solid::DeviceInterface::Battery:
82 initBatteryDevice();
83 break;
84 default:
85 if (queryDeviceInterface(Solid::DeviceInterface::StorageAccess) || queryDeviceInterface(Solid::DeviceInterface::StorageDrive)) {
86 initStorageDevice();
87 } else {
88 qWarning() << "Unknown device" << udi;
89 }
90 }
91}
92
93void WinDevice::initStorageDevice()
94{
95 QString dev;
96 switch (m_type) {
97 case Solid::DeviceInterface::StorageAccess:
98 dev = WinBlock::driveLetterFromUdi(udi());
99 m_product = QStringLiteral("Virtual drive %1").arg(dev);
100 m_description = QStringLiteral("%1 (%2)").arg(dev, WinBlock::resolveVirtualDrive(udi()));
101 return;
102 case Solid::DeviceInterface::OpticalDrive:
103 dev = WinBlock::driveLetterFromUdi(udi());
104 break;
105 case Solid::DeviceInterface::StorageDrive:
106 dev = QStringLiteral("PhysicalDrive%1").arg(WinBlock(this).deviceMajor());
107 break;
108 default:
109 dev = WinBlock::driveLetterFromUdi(udi());
110 const QString label = WinStorageVolume(this).label();
111 if (!label.isEmpty()) {
112 m_description = QStringLiteral("%1 (%2)").arg(dev, label);
113 } else {
114 m_description = dev;
115 }
116 }
117
118 STORAGE_PROPERTY_QUERY query;
119 ZeroMemory(&query, sizeof(STORAGE_PROPERTY_QUERY));
120 query.PropertyId = StorageDeviceProperty;
121 query.QueryType = PropertyStandardQuery;
122
123 char buff[1024];
124 WinDeviceManager::getDeviceInfo<char, STORAGE_PROPERTY_QUERY>(dev, IOCTL_STORAGE_QUERY_PROPERTY, buff, 1024, &query);
125 STORAGE_DEVICE_DESCRIPTOR *info = ((STORAGE_DEVICE_DESCRIPTOR *)buff);
126 if (info->VendorIdOffset != 0) {
127 m_vendor = QString::fromLatin1(&buff[info->VendorIdOffset]).trimmed();
128 if (info->ProductIdOffset != 0) {
129 m_product = QString::fromLatin1(&buff[info->ProductIdOffset]).trimmed();
130 }
131 } else if (info->ProductIdOffset != 0) { // fallback doesn't work for all devices
132 QStringList tmp = QString::fromLatin1(&buff[info->ProductIdOffset]).trimmed().split(QLatin1Char(' '));
133 m_vendor = tmp.takeFirst();
134 m_product = tmp.join(QLatin1Char(' '));
135 }
136}
137
138void WinDevice::initBatteryDevice()
139{
140 WinBattery::Battery battery = WinBattery::batteryInfoFromUdi(m_udi);
141 BATTERY_QUERY_INFORMATION query;
142 ZeroMemory(&query, sizeof(query));
143 query.BatteryTag = battery.second;
144
145 DWORD size = 1024;
146 wchar_t buff[1024];
147
148 query.InformationLevel = BatteryDeviceName;
149 WinDeviceManager::getDeviceInfo<wchar_t, BATTERY_QUERY_INFORMATION>(battery.first, IOCTL_BATTERY_QUERY_INFORMATION, buff, size, &query);
150 m_product = QString::fromWCharArray(buff);
151
152 query.InformationLevel = BatteryManufactureName;
153 WinDeviceManager::getDeviceInfo<wchar_t, BATTERY_QUERY_INFORMATION>(battery.first, IOCTL_BATTERY_QUERY_INFORMATION, buff, size, &query);
154 m_vendor = QString::fromWCharArray(buff);
155
156 switch (WinBattery(this).technology()) {
157 case Solid::Battery::LithiumIon:
158 m_description = tr("Lithium Ion", "battery technology");
159 break;
160 case Solid::Battery::LeadAcid:
161 m_description = tr("Lead Acid", "battery technology");
162 break;
163 case Solid::Battery::NickelCadmium:
164 m_description = tr("Nickel Cadmium", "battery technology");
165 break;
166 case Solid::Battery::NickelMetalHydride:
167 m_description = tr("Nickel Metal Hydride", "battery technology");
168 break;
169 default:
170 m_description = tr("Unknown", "battery technology");
171 }
172}
173
174void WinDevice::initCpuDevice()
175{
176 WinProcessor cpu(this);
177 WinProcessor::ProcessorInfo info = WinProcessor::updateCache()[cpu.number()];
178 m_vendor = info.vendor;
179 m_product = info.produuct;
180 m_description = info.name;
181}
182
183QString WinDevice::udi() const
184{
185 return m_udi;
186}
187
188QString WinDevice::parentUdi() const
189{
190 return m_parentUdi;
191}
192
193QString WinDevice::vendor() const
194{
195 return m_vendor;
196}
197
198QString WinDevice::product() const
199{
200 return m_product;
201}
202
203QString WinDevice::description() const
204{
205 return m_description.isEmpty() ? m_product : m_description;
206}
207
208QString WinDevice::icon() const
209{
210 if (parentUdi().isEmpty()) {
211 return QLatin1String("computer");
212 }
213
214 QString icon;
215 switch (type()) {
216 case Solid::DeviceInterface::OpticalDrive:
217 icon = QLatin1String("drive-optical");
218 break;
219 case Solid::DeviceInterface::OpticalDisc: {
220 WinOpticalDisc disk(const_cast<WinDevice *>(this));
221 if (disk.availableContent() & Solid::OpticalDisc::Audio) {
222 icon = QLatin1String("media-optical-audio");
223 } else {
224 icon = QLatin1String("drive-optical");
225 }
226 break;
227 }
228 case Solid::DeviceInterface::StorageDrive:
229 case Solid::DeviceInterface::StorageVolume: {
230 WinStorageDrive storage(const_cast<WinDevice *>(this));
231 if (storage.bus() == Solid::StorageDrive::Usb) {
232 icon = QLatin1String("drive-removable-media-usb-pendrive");
233 } else {
234 icon = QLatin1String("drive-harddisk");
235 }
236 break;
237 }
238 case Solid::DeviceInterface::Processor:
239 icon = QLatin1String("cpu");
240 break;
241 case Solid::DeviceInterface::Battery:
242 icon = QLatin1String("battery");
243 break;
244 case Solid::DeviceInterface::StorageAccess:
245 icon = QLatin1String("drive-harddisk");
246 break;
247 default:
248 break;
249 }
250 return icon;
251}
252
253QStringList WinDevice::emblems() const
254{
255 QStringList icons;
256 switch (type()) {
257 case Solid::DeviceInterface::StorageAccess:
258 icons << QLatin1String("emblem-symbolic-link");
259 break;
260 default:
261 break;
262 }
263 return icons;
264}
265
266bool WinDevice::queryDeviceInterface(const Solid::DeviceInterface::Type &queryType) const
267{
268 if (queryType == Solid::DeviceInterface::GenericInterface) {
269 return true;
270 }
271
273 interfaceList << type();
274
275 switch (type()) {
276 case Solid::DeviceInterface::GenericInterface:
277 break;
278 case Solid::DeviceInterface::Block:
279 break;
280 case Solid::DeviceInterface::StorageAccess:
281 break;
282 case Solid::DeviceInterface::StorageDrive:
283 break;
284 case Solid::DeviceInterface::OpticalDrive:
285 interfaceList << Solid::DeviceInterface::Block << Solid::DeviceInterface::StorageDrive;
286 break;
287 case Solid::DeviceInterface::StorageVolume:
288 interfaceList << Solid::DeviceInterface::Block << Solid::DeviceInterface::StorageAccess;
289 break;
290 case Solid::DeviceInterface::OpticalDisc:
291 interfaceList << Solid::DeviceInterface::Block << Solid::DeviceInterface::StorageVolume << Solid::DeviceInterface::StorageAccess;
292 break;
293 case Solid::DeviceInterface::PortableMediaPlayer:
294 break;
295 case Solid::DeviceInterface::Unknown:
296 case Solid::DeviceInterface::Last:
297 default:
298 break;
299 }
300
301 if (interfaceList.size() == 0) {
302 qWarning() << "no interface found for type" << type();
303 }
304 return interfaceList.contains(queryType);
305}
306
307QObject *WinDevice::createDeviceInterface(const Solid::DeviceInterface::Type &type)
308{
309 if (!queryDeviceInterface(type)) {
310 return 0;
311 }
312 WinInterface *iface = 0;
313
314 switch (type) {
315 case Solid::DeviceInterface::GenericInterface:
316 iface = new WinGenericInterface(this);
317 break;
318 case Solid::DeviceInterface::Block:
319 iface = new WinBlock(this);
320 break;
321 case Solid::DeviceInterface::Processor:
322 iface = new WinProcessor(this);
323 break;
324 case Solid::DeviceInterface::StorageAccess:
325 iface = new WinStorageAccess(this);
326 break;
327 case Solid::DeviceInterface::StorageDrive:
328 iface = new WinStorageDrive(this);
329 break;
330 case Solid::DeviceInterface::OpticalDrive:
331 iface = new WinOpticalDrive(this);
332 break;
333 case Solid::DeviceInterface::StorageVolume:
334 iface = new WinStorageVolume(this);
335 break;
336 case Solid::DeviceInterface::OpticalDisc:
337 iface = new WinOpticalDisc(this);
338 break;
339 // case Solid::DeviceInterface::PortableMediaPlayer:
340 // iface = new PortableMediaPlayer(this);
341 // break;
342 case Solid::DeviceInterface::Battery:
343 iface = new WinBattery(this);
344 break;
345 case Solid::DeviceInterface::Unknown:
346 case Solid::DeviceInterface::Last:
347 break;
348 default:
349 break;
350 }
351
352 return iface;
353}
354
355Solid::DeviceInterface::Type WinDevice::type() const
356{
357 return m_type;
358}
359
360#include "moc_windevice.cpp"
Base class of all the device interfaces.
Type
This enum type defines the type of device interface that a Device can have.
This class allows applications to deal with devices available in the underlying system.
Type type(const QSqlDatabase &db)
std::optional< QSqlQuery > query(const QString &queryStatement)
QString label(StandardShortcut id)
bool contains(const AT &value) const const
qsizetype size() const const
value_type takeFirst()
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
QString fromWCharArray(const wchar_t *string, qsizetype size)
bool isEmpty() const const
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString trimmed() const const
QString join(QChar separator) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 17:03:23 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.