From 0f78eb6ce67962a4147dce37cc4f8538d44b36d7 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Mon, 24 Mar 2014 13:25:49 +0100 Subject: unifying: implement BatteryStatus Battery percentage is fuzzy... ok. Signed-off-by: Peter Wu --- hw/usb/hid-logitech-dj.c | 7 +++++++ hw/usb/hid-logitech-dj.h | 22 +++++++++++++++----- hw/usb/hid-logitech-hidpp20.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) (limited to 'hw') diff --git a/hw/usb/hid-logitech-dj.c b/hw/usb/hid-logitech-dj.c index 59bdc7f65c..6097f16822 100644 --- a/hw/usb/hid-logitech-dj.c +++ b/hw/usb/hid-logitech-dj.c @@ -603,6 +603,9 @@ static void hidpp_init_device(USBLtunifyState *s, int device_index, int devtype) memcpy(hd->info.name, "M525", 4); hd->info.device_name = "WirelessMouse M525"; hd->report_interval = 8; + hd->battery.nlevels = 2; + hd->battery.level = 2; /* Full - 90 % */ + hd->battery.critical_perc = 2; break; case DEVTYPE_TOUCHPAD: /* TODO: perhaps "unpair" mouse and use this touchpad instead? */ @@ -613,6 +616,10 @@ static void hidpp_init_device(USBLtunifyState *s, int device_index, int devtype) memcpy(hd->info.name, "T650", 4); hd->info.device_name = "Rechargeable Touchpad T650"; hd->report_interval = 8; + hd->battery.nlevels = 4; + hd->battery.level = 3; /* Good - 50 % */ + hd->battery.flags = BAT_FLAG_RECHARGEABLE; + hd->battery.critical_perc = 10; break; } if (hd->info.protocol_version >= 0x0200) { diff --git a/hw/usb/hid-logitech-dj.h b/hw/usb/hid-logitech-dj.h index 6a29b6639e..785f0d5b56 100644 --- a/hw/usb/hid-logitech-dj.h +++ b/hw/usb/hid-logitech-dj.h @@ -220,11 +220,23 @@ typedef struct { /* TODO: status (device seen or not, encrypted link) */ struct { - uint8_t level; - enum { - BAT_STS_CHARGING, - /* TODO: charging, discharging, etc. */ - } status; + uint8_t nlevels; + uint8_t level; /* in range (1, nlevels) */ +#define BAT_FLAG_DISABLE_OSD (1 << 0) +#define BAT_FLAG_ENABLE_MILEAGE (1 << 1) +#define BAT_FLAG_RECHARGEABLE (1 << 2) + uint8_t flags; + uint8_t critical_perc; + +#define BAT_STS_DISCHARGING 0 +#define BAT_STS_RECHARGING 1 +#define BAT_STS_CHARGE_FINAL 2 +#define BAT_STS_CHARGE_COMPLETE 3 +#define BAT_STS_RECHARGING_SLOW 4 +#define BAT_STS_INVALID_BATTERY 5 +#define BAT_STS_THERMAL_ERROR 6 +#define BAT_STS_CHARGING_ERROR 7 + uint8_t status; } battery; uint8_t activity_counter; } LHidDevice; diff --git a/hw/usb/hid-logitech-hidpp20.c b/hw/usb/hid-logitech-hidpp20.c index 3c664cc089..026dd587be 100644 --- a/hw/usb/hid-logitech-hidpp20.c +++ b/hw/usb/hid-logitech-hidpp20.c @@ -186,11 +186,58 @@ static HIDPP20_FEATURE(feat_devicename) } } +static uint8_t calc_battery_percent(LHidDevice *hd, uint8_t level) +{ + uint8_t nlevels = hd->battery.nlevels; + + assert(nlevels >= 2); + assert(level >= 1 && level <= nlevels); + if (nlevels == 2) { + switch (level) { + case 2: return 90; + default: return 5; + } + } else if (nlevels < 10 || !(hd->battery.flags & BAT_FLAG_ENABLE_MILEAGE)) { + switch (4 * level / nlevels) { + case 4: return 90; + case 3: return 50; + case 2: return 20; + default: return 5; + } + } + + return 100 * level / nlevels; +} + +static HIDPP20_FEATURE(feat_batterystatus) +{ + switch (fn) { + case 0: /* BatteryLevel = GetBatteryLevelStatus() */ + params[0] = calc_battery_percent(hd, hd->battery.level); + if (hd->battery.level > 0 && hd->battery.status == BAT_STS_DISCHARGING) { + params[1] = calc_battery_percent(hd, hd->battery.level - 1); + } else { + params[1] = 0; + } + params[2] = hd->battery.status; + return 2; + case 1: /* LevelList[] = GetBatteryCapacity() */ + params[0] = hd->battery.nlevels; + params[1] = hd->battery.flags; + params[2] = params[3] = 0; /* TODO: nominal battery life */ + params[4] = hd->battery.critical_perc; + return 5; + default: + return -HIDPP20_ERR_CODE_INVALID_FUNCTION_ID; + } +} + /* root feature not included! */ static const HidppFeature features_m525[] = { { 0x0001, 0, feat_featureset }, { 0x0003, 0, feat_devicefwversion }, { 0x0005, 0, feat_devicename }, + { 0x1000, 0, feat_batterystatus }, }; void hidpp20_init_features(LHidDevice *hd) { -- cgit v1.2.1