mouse baterry
This commit is contained in:
@@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace hidpp {
|
||||
|
||||
/// Battery state of a wireless Logitech device.
|
||||
struct BatteryStatus {
|
||||
enum class Level : uint8_t { UNKNOWN,
|
||||
CRITICAL,
|
||||
LOW,
|
||||
GOOD,
|
||||
FULL };
|
||||
|
||||
bool connected = false;
|
||||
int percentage = -1; // 0..100, or -1 when the device only reports a level
|
||||
Level level = Level::UNKNOWN;
|
||||
bool charging = false;
|
||||
bool externalPower = false;
|
||||
};
|
||||
|
||||
/// Reads the battery level of a Logitech HID++ 2.0 device.
|
||||
///
|
||||
/// Prefers the power_supply entry that hid-logitech-hidpp exports, and falls
|
||||
/// back to speaking HID++ 2.0 over /dev/hidraw* when that driver is not bound
|
||||
/// (the receiver then sits on hid-generic and exports no battery at all).
|
||||
///
|
||||
/// read() blocks on wireless round-trips that can take seconds when the device
|
||||
/// is asleep, so it must be called off the GTK main thread.
|
||||
class BatteryReader {
|
||||
public:
|
||||
explicit BatteryReader(std::string deviceName);
|
||||
~BatteryReader();
|
||||
|
||||
BatteryReader(const BatteryReader &) = delete;
|
||||
BatteryReader &operator=(const BatteryReader &) = delete;
|
||||
|
||||
BatteryStatus read();
|
||||
|
||||
private:
|
||||
/// A resolved HID++ endpoint: which hidraw node, which device slot on it,
|
||||
/// and the feature index the battery lives behind.
|
||||
struct Endpoint {
|
||||
int fd = -1;
|
||||
uint8_t deviceIndex = 0;
|
||||
uint8_t featureIdx = 0;
|
||||
uint16_t featureId = 0; // kFeatureUnifiedBattery or kFeatureBatteryStatus
|
||||
};
|
||||
|
||||
std::string deviceName;
|
||||
Endpoint endpoint{};
|
||||
|
||||
std::optional<BatteryStatus> readFromSysfs() const;
|
||||
std::optional<BatteryStatus> readFromHidpp();
|
||||
|
||||
/// Finds the hidraw node and device slot our device answers on. Expensive:
|
||||
/// only called on first use and after the cached endpoint stops replying.
|
||||
bool resolveEndpoint();
|
||||
void closeEndpoint();
|
||||
};
|
||||
|
||||
} // namespace hidpp
|
||||
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
|
||||
#include <condition_variable>
|
||||
#include <glibmm/dispatcher.h>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sigc++/sigc++.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "services/hidppBattery.hpp"
|
||||
|
||||
/// Polls the mouse battery once for the whole application.
|
||||
///
|
||||
/// The bar builds one window per monitor, so the widget cannot own the polling
|
||||
/// itself without every monitor opening its own HID++ session against the same
|
||||
/// receiver and competing for it. This service keeps a single worker thread and
|
||||
/// fans the result out to every widget through updated().
|
||||
class MouseBatteryService {
|
||||
public:
|
||||
static constexpr const char *kDeviceName = "MX Ergo S";
|
||||
|
||||
static std::shared_ptr<MouseBatteryService> getInstance();
|
||||
|
||||
~MouseBatteryService();
|
||||
|
||||
MouseBatteryService(const MouseBatteryService &) = delete;
|
||||
MouseBatteryService &operator=(const MouseBatteryService &) = delete;
|
||||
|
||||
/// Last reading. Safe to call from the main thread.
|
||||
hidpp::BatteryStatus getStatus() const;
|
||||
|
||||
/// Emitted on the main thread whenever a new reading lands.
|
||||
sigc::signal<void()> &updated() { return updatedSignal; }
|
||||
|
||||
/// Stops the worker thread; called from the application's shutdown handler
|
||||
/// so it cannot outlive the main loop the dispatcher posts to.
|
||||
void stop();
|
||||
|
||||
private:
|
||||
explicit MouseBatteryService(std::string deviceName);
|
||||
|
||||
void poll();
|
||||
|
||||
hidpp::BatteryReader reader;
|
||||
|
||||
Glib::Dispatcher dispatcher;
|
||||
sigc::signal<void()> updatedSignal;
|
||||
|
||||
std::thread worker;
|
||||
mutable std::mutex mutex;
|
||||
std::condition_variable wakeup;
|
||||
bool running = true;
|
||||
hidpp::BatteryStatus status{};
|
||||
|
||||
inline static std::shared_ptr<MouseBatteryService> instance = nullptr;
|
||||
};
|
||||
Reference in New Issue
Block a user