summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-03-24 13:25:49 +0100
committerPeter Wu <peter@lekensteyn.nl>2014-03-24 13:25:49 +0100
commit0f78eb6ce67962a4147dce37cc4f8538d44b36d7 (patch)
treedb7b627eaa37e767e2a08aad19683fc79a6477e8 /hw
parent4215730f0ac21c625effe50ba14fbf050dc991a8 (diff)
downloadqemu-0f78eb6ce67962a4147dce37cc4f8538d44b36d7.tar.gz
unifying: implement BatteryStatus
Battery percentage is fuzzy... ok. Signed-off-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'hw')
-rw-r--r--hw/usb/hid-logitech-dj.c7
-rw-r--r--hw/usb/hid-logitech-dj.h22
-rw-r--r--hw/usb/hid-logitech-hidpp20.c47
3 files changed, 71 insertions, 5 deletions
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) {