7#include "windevicemanager_p.h"
11#include <devpropdef.h>
14using namespace Solid::Backends::Win;
18WinBattery::WinBattery(WinDevice *device)
19 : WinInterface(device)
20 , m_state(Solid::
Battery::NoCharge)
23 connect(SolidWinEventFilter::instance(), SIGNAL(powerChanged()),
this, SLOT(powerChanged()));
31int WinBattery::chargePercent()
const
36int WinBattery::capacity()
const
41int WinBattery::cycleCount()
const
46bool WinBattery::isRechargeable()
const
48 return m_rechargeable;
51bool WinBattery::isPowerSupply()
const
53 return m_isPowerSupply;
64 HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
66 if (INVALID_HANDLE_VALUE != hdev) {
68 for (
int idev = 0; idev < 100; idev++) {
69 SP_DEVICE_INTERFACE_DATA did;
70 ZeroMemory(&did,
sizeof(did));
71 did.cbSize =
sizeof(did);
73 if (SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVCLASS_BATTERY, idev, &did)) {
76 SetupDiGetDeviceInterfaceDetailW(hdev, &did, 0, 0, &cbRequired, 0);
77 if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
78 char *buffer =
new char[cbRequired];
79 SP_DEVICE_INTERFACE_DETAIL_DATA *pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA *)buffer;
80 ZeroMemory(pdidd, cbRequired);
81 pdidd->cbSize =
sizeof(*pdidd);
82 if (SetupDiGetDeviceInterfaceDetail(hdev, &did, pdidd, cbRequired, &cbRequired, 0)) {
84 ulong tag = WinDeviceManager::getDeviceInfo<ulong>(path, IOCTL_BATTERY_QUERY_TAG);
87 m_udiToGDI[udi] =
Battery(path, tag);
94 SetupDiDestroyDeviceInfoList(hdev);
99const WinBattery::Battery WinBattery::batteryInfoFromUdi(
const QString &udi)
101 return m_udiToGDI[udi];
104void WinBattery::powerChanged()
106 const int old_charge = m_charge;
107 const int old_capacity = m_capacity;
108 const int old_cyleCount = m_cycleCount;
110 const bool old_isPowerSupply = m_isPowerSupply;
111 const double old_energy = m_energy;
112 const double old_energyFull = m_energyFull;
113 const double old_energyFullDesign = m_energyFullDesign;
114 const double old_energyRate = m_energyRate;
115 const double old_voltage = m_voltage;
117 BATTERY_WAIT_STATUS batteryStatusQuery;
118 ZeroMemory(&batteryStatusQuery,
sizeof(batteryStatusQuery));
119 Battery b = m_udiToGDI[m_device->udi()];
120 batteryStatusQuery.BatteryTag = b.second;
121 BATTERY_STATUS
status = WinDeviceManager::getDeviceInfo<BATTERY_STATUS, BATTERY_WAIT_STATUS>(b.first, IOCTL_BATTERY_QUERY_STATUS, &batteryStatusQuery);
123 BATTERY_QUERY_INFORMATION batteryInformationQuery;
124 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
125 batteryInformationQuery.BatteryTag = b.second;
126 batteryInformationQuery.InformationLevel = BatteryInformation;
127 BATTERY_INFORMATION info =
128 WinDeviceManager::getDeviceInfo<BATTERY_INFORMATION, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, &batteryInformationQuery);
131 updateBatteryTemp(b);
132 updateTimeToEmpty(b);
134 m_isPowerSupply = !(
status.PowerState & BATTERY_POWER_ON_LINE);
139 m_technology = Solid::Battery::LithiumIon;
141 m_technology = Solid::Battery::LeadAcid;
143 m_technology = Solid::Battery::NickelCadmium;
145 m_technology = Solid::Battery::NickelMetalHydride;
147 m_technology = Solid::Battery::UnknownTechnology;
150 m_energy =
status.Capacity / 1000.0;
151 m_energyFull = info.FullChargedCapacity / 1000.0;
152 m_energyFullDesign = info.DesignedCapacity / 1000.0;
153 m_energyRate =
status.Rate / 1000.0;
154 m_voltage =
status.Voltage / 1000.0;
156 if (info.FullChargedCapacity != 0) {
157 m_charge = (float)
status.Capacity / info.FullChargedCapacity * 100.0;
160 if (info.DesignedCapacity != 0) {
161 m_capacity = (float)info.FullChargedCapacity / info.DesignedCapacity * 100.0;
164 if (info.CycleCount != 0) {
165 m_cycleCount = info.CycleCount;
168 if (
status.PowerState == 0) {
169 m_state = Solid::Battery::NoCharge;
170 }
else if (
status.PowerState & BATTERY_CHARGING) {
171 m_state = Solid::Battery::Charging;
172 }
else if (
status.PowerState & BATTERY_DISCHARGING) {
173 m_state = Solid::Battery::Discharging;
180 if (info.Capabilities & BATTERY_SYSTEM_BATTERY) {
181 m_type = Solid::Battery::PrimaryBattery;
183 m_type = Solid::Battery::UnknownBattery;
186 m_rechargeable = info.Technology == 1;
188 if (m_charge != old_charge) {
189 Q_EMIT chargePercentChanged(m_charge, m_device->udi());
192 if (m_capacity != old_capacity) {
193 Q_EMIT capacityChanged(m_capacity, m_device->udi());
196 if (m_cycleCount != old_cyleCount) {
197 Q_EMIT cycleCountChanged(m_cycleCount, m_device->udi());
200 if (old_state != m_state) {
201 Q_EMIT chargeStateChanged(m_state, m_device->udi());
204 if (old_isPowerSupply != m_isPowerSupply) {
205 Q_EMIT powerSupplyStateChanged(m_isPowerSupply, m_device->udi());
208 if (old_energy != m_energy) {
209 Q_EMIT energyChanged(m_energy, m_device->udi());
212 if (old_energyFull != m_energyFull) {
213 Q_EMIT energyFullChanged(m_energyFull, m_device->udi());
216 if (old_energyFullDesign != m_energyFullDesign) {
217 Q_EMIT energyFullDesignChanged(m_energyFullDesign, m_device->udi());
220 if (old_energyRate != m_energyRate) {
221 Q_EMIT energyRateChanged(m_energyRate, m_device->udi());
224 if (old_voltage != m_voltage) {
225 Q_EMIT voltageChanged(m_voltage, m_device->udi());
229void WinBattery::initSerial(
const Battery &b)
231 wchar_t buffer[1024];
232 BATTERY_QUERY_INFORMATION batteryInformationQuery;
233 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
234 batteryInformationQuery.BatteryTag = b.second;
235 batteryInformationQuery.InformationLevel = BatterySerialNumber;
236 WinDeviceManager::getDeviceInfo<wchar_t, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, buffer, 1024, &batteryInformationQuery);
241void WinBattery::updateTimeToEmpty(
const WinBattery::Battery &b)
243 BATTERY_QUERY_INFORMATION batteryInformationQuery;
244 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
245 batteryInformationQuery.BatteryTag = b.second;
246 batteryInformationQuery.InformationLevel = BatteryEstimatedTime;
247 ulong time = WinDeviceManager::getDeviceInfo<ulong, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, &batteryInformationQuery);
249 if (time == BATTERY_UNKNOWN_TIME) {
253 if (time != m_timeUntilEmpty) {
254 m_timeUntilEmpty = time;
255 Q_EMIT timeToEmptyChanged(time, m_device->udi());
259void WinBattery::updateBatteryTemp(
const WinBattery::Battery &b)
261 BATTERY_QUERY_INFORMATION batteryInformationQuery;
262 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
263 batteryInformationQuery.BatteryTag = b.second;
264 batteryInformationQuery.InformationLevel = BatteryTemperature;
265 ulong batteryTemp = WinDeviceManager::getDeviceInfo<ulong, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, &batteryInformationQuery);
267 if (batteryTemp != m_temperature) {
268 m_temperature = batteryTemp;
269 Q_EMIT temperatureChanged(batteryTemp, m_device->udi());
278double WinBattery::energy()
const
283double WinBattery::energyFull()
const
288double WinBattery::energyFullDesign()
const
290 return m_energyFullDesign;
293double WinBattery::energyRate()
const
298double WinBattery::voltage()
const
303bool WinBattery::isPresent()
const
308qlonglong WinBattery::timeToEmpty()
const
310 return m_timeUntilEmpty;
313qlonglong WinBattery::timeToFull()
const
318double WinBattery::temperature()
const
320 return m_temperature;
323qlonglong WinBattery::remainingTime()
const
325 return m_timeUntilEmpty;
328QString WinBattery::serial()
const
333#include "moc_winbattery.cpp"
This device interface is available on batteries.
BatteryType
This enum type defines the type of the device holding the battery.
Technology
Technology used in the battery.
ChargeState
This enum type defines charge state of a battery.
Q_SCRIPTABLE CaptureState status()
QString path(const QString &relativePath)
QString fromUtf8(QByteArrayView str)
QString fromWCharArray(const wchar_t *string, qsizetype size)
QString number(double n, char format, int precision)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)