Input: wacom - enhance Wireless Receiver battery reporting
authorBenjamin Tissoires <benjamin.tissoires@redhat.com>
Sat, 26 Jul 2014 00:29:48 +0000 (17:29 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 26 Jul 2014 01:55:53 +0000 (18:55 -0700)
- Reports the current status of the battery (discharging, charging, full).
- Also notify the upower daemon when there is a change in the battery
  value.
- keep the battery value as a percentage, not the raw value
- add WACOM_QUIRK_BATTERY to easily add a battery to a device (required
  for Bluetooth devices)

Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Acked-by: Przemo Firszt <przemo@firszt.eu>
Acked-by: Ping Cheng <pingc@wacom.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/hid/wacom.h
drivers/hid/wacom_sys.c
drivers/hid/wacom_wac.c
drivers/hid/wacom_wac.h

index a678f827e39ecb6a55421de4178bc532ed7033af..98cb93f16ba47c88ad2b38995c51526f380ca36c 100644 (file)
@@ -128,6 +128,13 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac)
        schedule_work(&wacom->work);
 }
 
+static inline void wacom_notify_battery(struct wacom_wac *wacom_wac)
+{
+       struct wacom *wacom = container_of(wacom_wac, struct wacom, wacom_wac);
+
+       power_supply_changed(&wacom->battery);
+}
+
 extern const struct hid_device_id wacom_ids[];
 
 void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len);
index f1c6d3dae248dc1aa2862480704404a3859dd621..f8744c4d3b18c27ba91296cf2bbe9d28eea21d5f 100644 (file)
@@ -769,6 +769,7 @@ static void wacom_destroy_leds(struct wacom *wacom)
 }
 
 static enum power_supply_property wacom_battery_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_SCOPE,
        POWER_SUPPLY_PROP_CAPACITY
 };
@@ -786,7 +787,16 @@ static int wacom_battery_get_property(struct power_supply *psy,
                        break;
                case POWER_SUPPLY_PROP_CAPACITY:
                        val->intval =
-                               wacom->wacom_wac.battery_capacity * 100 / 31;
+                               wacom->wacom_wac.battery_capacity;
+                       break;
+               case POWER_SUPPLY_PROP_STATUS:
+                       if (wacom->wacom_wac.bat_charging)
+                               val->intval = POWER_SUPPLY_STATUS_CHARGING;
+                       else if (wacom->wacom_wac.battery_capacity == 100 &&
+                                   wacom->wacom_wac.ps_connected)
+                               val->intval = POWER_SUPPLY_STATUS_FULL;
+                       else
+                               val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
                        break;
                default:
                        ret = -EINVAL;
@@ -800,7 +810,7 @@ static int wacom_initialize_battery(struct wacom *wacom)
 {
        int error = 0;
 
-       if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR) {
+       if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) {
                wacom->battery.properties = wacom_battery_props;
                wacom->battery.num_properties = ARRAY_SIZE(wacom_battery_props);
                wacom->battery.get_property = wacom_battery_get_property;
@@ -821,8 +831,8 @@ static int wacom_initialize_battery(struct wacom *wacom)
 
 static void wacom_destroy_battery(struct wacom *wacom)
 {
-       if (wacom->wacom_wac.features.quirks & WACOM_QUIRK_MONITOR &&
-           wacom->battery.dev) {
+       if ((wacom->wacom_wac.features.quirks & WACOM_QUIRK_BATTERY) &&
+            wacom->battery.dev) {
                power_supply_unregister(&wacom->battery);
                wacom->battery.dev = NULL;
        }
@@ -947,6 +957,7 @@ static void wacom_wireless_work(struct work_struct *work)
 
        if (wacom_wac->pid == 0) {
                hid_info(wacom->hdev, "wireless tablet disconnected\n");
+               wacom_wac1->shared->type = 0;
        } else {
                const struct hid_device_id *id = wacom_ids;
 
index 2f3a3a77d0c638213f8936e3435027ad30c1c588..cfd2ae13c2877049daeffd40d93fd5092a063d3a 100644 (file)
@@ -1365,7 +1365,7 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
 
        connected = data[1] & 0x01;
        if (connected) {
-               int pid, battery;
+               int pid, battery, ps_connected;
 
                if ((wacom->shared->type == INTUOSHT) &&
                                wacom->shared->touch_max) {
@@ -1375,17 +1375,29 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len)
                }
 
                pid = get_unaligned_be16(&data[6]);
-               battery = data[5] & 0x3f;
+               battery = (data[5] & 0x3f) * 100 / 31;
+               ps_connected = !!(data[5] & 0x80);
                if (wacom->pid != pid) {
                        wacom->pid = pid;
                        wacom_schedule_work(wacom);
                }
-               wacom->battery_capacity = battery;
+
+               if (wacom->shared->type &&
+                   (battery != wacom->battery_capacity ||
+                    ps_connected != wacom->ps_connected)) {
+                       wacom->battery_capacity = battery;
+                       wacom->ps_connected = ps_connected;
+                       wacom->bat_charging = ps_connected &&
+                                               wacom->battery_capacity < 100;
+                       wacom_notify_battery(wacom);
+               }
        } else if (wacom->pid != 0) {
                /* disconnected while previously connected */
                wacom->pid = 0;
                wacom_schedule_work(wacom);
                wacom->battery_capacity = 0;
+               wacom->bat_charging = 0;
+               wacom->ps_connected = 0;
        }
 
        return 0;
@@ -1558,8 +1570,10 @@ void wacom_setup_device_quirks(struct wacom_features *features)
                features->quirks |= WACOM_QUIRK_NO_INPUT;
 
                /* must be monitor interface if no device_type set */
-               if (!features->device_type)
+               if (!features->device_type) {
                        features->quirks |= WACOM_QUIRK_MONITOR;
+                       features->quirks |= WACOM_QUIRK_BATTERY;
+               }
        }
 }
 
index 4c592475b23704c79c7c09baa063ac4685520878..8a042ac0114ef7ba41bf59c1e22cb374c3534a19 100644 (file)
@@ -68,6 +68,7 @@
 #define WACOM_QUIRK_BBTOUCH_LOWRES     0x0002
 #define WACOM_QUIRK_NO_INPUT           0x0004
 #define WACOM_QUIRK_MONITOR            0x0008
+#define WACOM_QUIRK_BATTERY            0x0010
 
 enum {
        PENPARTNER = 0,
@@ -164,6 +165,8 @@ struct wacom_wac {
        int pid;
        int battery_capacity;
        int num_contacts_left;
+       int bat_charging;
+       int ps_connected;
 };
 
 #endif