7#include "windevicemanager_p.h"
11#include <devpropdef.h>
14using namespace Solid::Backends::Win;
18WinBattery::WinBattery(WinDevice *device)
19 : WinInterface(device)
23 connect(SolidWinEventFilter::instance(), SIGNAL(powerChanged()),
this, SLOT(powerChanged()));
31int WinBattery::chargePercent()
const
36int WinBattery::capacity()
const
41bool WinBattery::isRechargeable()
const
43 return m_rechargeable;
46bool WinBattery::isPowerSupply()
const
48 return m_isPowerSupply;
59 HDEVINFO hdev = SetupDiGetClassDevs(&GUID_DEVCLASS_BATTERY, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
61 if (INVALID_HANDLE_VALUE != hdev) {
63 for (
int idev = 0; idev < 100; idev++) {
64 SP_DEVICE_INTERFACE_DATA did;
65 ZeroMemory(&did,
sizeof(did));
66 did.cbSize =
sizeof(did);
68 if (SetupDiEnumDeviceInterfaces(hdev, 0, &GUID_DEVCLASS_BATTERY, idev, &did)) {
71 SetupDiGetDeviceInterfaceDetailW(hdev, &did, 0, 0, &cbRequired, 0);
72 if (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
73 char *buffer =
new char[cbRequired];
74 SP_DEVICE_INTERFACE_DETAIL_DATA *pdidd = (SP_DEVICE_INTERFACE_DETAIL_DATA *)buffer;
75 ZeroMemory(pdidd, cbRequired);
76 pdidd->cbSize =
sizeof(*pdidd);
77 if (SetupDiGetDeviceInterfaceDetail(hdev, &did, pdidd, cbRequired, &cbRequired, 0)) {
79 ulong tag = WinDeviceManager::getDeviceInfo<ulong>(path, IOCTL_BATTERY_QUERY_TAG);
82 m_udiToGDI[udi] =
Battery(path, tag);
89 SetupDiDestroyDeviceInfoList(hdev);
94const WinBattery::Battery WinBattery::batteryInfoFromUdi(
const QString &udi)
96 return m_udiToGDI[udi];
99void WinBattery::powerChanged()
101 const int old_charge = m_charge;
102 const int old_capacity = m_capacity;
104 const bool old_isPowerSupply = m_isPowerSupply;
105 const double old_energy = m_energy;
106 const double old_energyFull = m_energyFull;
107 const double old_energyFullDesign = m_energyFullDesign;
108 const double old_energyRate = m_energyRate;
109 const double old_voltage = m_voltage;
111 BATTERY_WAIT_STATUS batteryStatusQuery;
112 ZeroMemory(&batteryStatusQuery,
sizeof(batteryStatusQuery));
113 Battery b = m_udiToGDI[m_device->udi()];
114 batteryStatusQuery.BatteryTag = b.second;
115 BATTERY_STATUS
status = WinDeviceManager::getDeviceInfo<BATTERY_STATUS, BATTERY_WAIT_STATUS>(b.first, IOCTL_BATTERY_QUERY_STATUS, &batteryStatusQuery);
117 BATTERY_QUERY_INFORMATION batteryInformationQuery;
118 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
119 batteryInformationQuery.BatteryTag = b.second;
120 batteryInformationQuery.InformationLevel = BatteryInformation;
121 BATTERY_INFORMATION info =
122 WinDeviceManager::getDeviceInfo<BATTERY_INFORMATION, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, &batteryInformationQuery);
125 updateBatteryTemp(b);
126 updateTimeToEmpty(b);
128 m_isPowerSupply = !(
status.PowerState & BATTERY_POWER_ON_LINE);
132 if (tech ==
"LION" || tech ==
"LI-I") {
133 m_technology = Solid::Battery::LithiumIon;
134 }
else if (tech ==
"PBAC") {
135 m_technology = Solid::Battery::LeadAcid;
136 }
else if (tech ==
"NICD") {
137 m_technology = Solid::Battery::NickelCadmium;
138 }
else if (tech ==
"NIMH") {
139 m_technology = Solid::Battery::NickelMetalHydride;
141 m_technology = Solid::Battery::UnknownTechnology;
144 m_energy =
status.Capacity / 1000.0;
145 m_energyFull = info.FullChargedCapacity / 1000.0;
146 m_energyFullDesign = info.DesignedCapacity / 1000.0;
147 m_energyRate =
status.Rate / 1000.0;
148 m_voltage =
status.Voltage / 1000.0;
150 if (info.FullChargedCapacity != 0) {
151 m_charge = (float)
status.Capacity / info.FullChargedCapacity * 100.0;
154 if (info.DesignedCapacity != 0) {
155 m_capacity = (float)info.FullChargedCapacity / info.DesignedCapacity * 100.0;
158 if (
status.PowerState == 0) {
159 m_state = Solid::Battery::NoCharge;
160 }
else if (
status.PowerState & BATTERY_CHARGING) {
161 m_state = Solid::Battery::Charging;
162 }
else if (
status.PowerState & BATTERY_DISCHARGING) {
163 m_state = Solid::Battery::Discharging;
170 if (info.Capabilities & BATTERY_SYSTEM_BATTERY) {
171 m_type = Solid::Battery::PrimaryBattery;
173 m_type = Solid::Battery::UnknownBattery;
176 m_rechargeable = info.Technology == 1;
178 if (m_charge != old_charge) {
179 Q_EMIT chargePercentChanged(m_charge, m_device->udi());
182 if (m_capacity != old_capacity) {
183 Q_EMIT capacityChanged(m_capacity, m_device->udi());
186 if (old_state != m_state) {
187 Q_EMIT chargeStateChanged(m_state, m_device->udi());
190 if (old_isPowerSupply != m_isPowerSupply) {
191 Q_EMIT powerSupplyStateChanged(m_isPowerSupply, m_device->udi());
194 if (old_energy != m_energy) {
195 Q_EMIT energyChanged(m_energy, m_device->udi());
198 if (old_energyFull != m_energyFull) {
199 Q_EMIT energyFullChanged(m_energyFull, m_device->udi());
202 if (old_energyFullDesign != m_energyFullDesign) {
203 Q_EMIT energyFullDesignChanged(m_energyFullDesign, m_device->udi());
206 if (old_energyRate != m_energyRate) {
207 Q_EMIT energyRateChanged(m_energyRate, m_device->udi());
210 if (old_voltage != m_voltage) {
211 Q_EMIT voltageChanged(m_voltage, m_device->udi());
215void WinBattery::initSerial(
const Battery &b)
217 wchar_t buffer[1024];
218 BATTERY_QUERY_INFORMATION batteryInformationQuery;
219 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
220 batteryInformationQuery.BatteryTag = b.second;
221 batteryInformationQuery.InformationLevel = BatterySerialNumber;
222 WinDeviceManager::getDeviceInfo<wchar_t, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, buffer, 1024, &batteryInformationQuery);
227void WinBattery::updateTimeToEmpty(
const WinBattery::Battery &b)
229 BATTERY_QUERY_INFORMATION batteryInformationQuery;
230 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
231 batteryInformationQuery.BatteryTag = b.second;
232 batteryInformationQuery.InformationLevel = BatteryEstimatedTime;
233 ulong time = WinDeviceManager::getDeviceInfo<ulong, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, &batteryInformationQuery);
235 if (time == BATTERY_UNKNOWN_TIME) {
239 if (time != m_timeUntilEmpty) {
240 m_timeUntilEmpty = time;
241 Q_EMIT timeToEmptyChanged(time, m_device->udi());
245void WinBattery::updateBatteryTemp(
const WinBattery::Battery &b)
247 BATTERY_QUERY_INFORMATION batteryInformationQuery;
248 ZeroMemory(&batteryInformationQuery,
sizeof(batteryInformationQuery));
249 batteryInformationQuery.BatteryTag = b.second;
250 batteryInformationQuery.InformationLevel = BatteryTemperature;
251 ulong batteryTemp = WinDeviceManager::getDeviceInfo<ulong, BATTERY_QUERY_INFORMATION>(b.first, IOCTL_BATTERY_QUERY_INFORMATION, &batteryInformationQuery);
253 if (batteryTemp != m_temperature) {
254 m_temperature = batteryTemp;
255 Q_EMIT temperatureChanged(batteryTemp, m_device->udi());
264double WinBattery::energy()
const
269double WinBattery::energyFull()
const
274double WinBattery::energyFullDesign()
const
276 return m_energyFullDesign;
279double WinBattery::energyRate()
const
284double WinBattery::voltage()
const
289bool WinBattery::isPresent()
const
294qlonglong WinBattery::timeToEmpty()
const
296 return m_timeUntilEmpty;
299qlonglong WinBattery::timeToFull()
const
304double WinBattery::temperature()
const
306 return m_temperature;
309qlonglong WinBattery::remainingTime()
const
311 return m_timeUntilEmpty;
314QString WinBattery::serial()
const
319#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)
The single responsibility of this class is to create arguments valid for logind Inhibit call.
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)