linux-input.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
To: linux-input@vger.kernel.org
Cc: "Emmanuel Gil Peyrot" <linkmauve@linkmauve.fr>,
	"Ash Logan" <ash@heyquark.com>,
	"Jonathan Neuschäfer" <j.ne@posteo.net>,
	"Jiri Kosina" <jikos@kernel.org>,
	"Benjamin Tissoires" <benjamin.tissoires@redhat.com>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 4/4] HID: wiiu-drc: Add battery reporting
Date: Mon,  3 May 2021 01:28:35 +0200	[thread overview]
Message-ID: <20210502232836.26134-5-linkmauve@linkmauve.fr> (raw)
In-Reply-To: <20210502232836.26134-1-linkmauve@linkmauve.fr>

On my DRC the values only go between 142 (battery LED blinking red
before shutdown) and 178 (charge LED stopping), it seems to be the same
on other units according to other testers.

A spinlock is used to avoid the battery level and status from being
reported unsynchronised.

Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
---
 drivers/hid/hid-wiiu-drc.c | 107 +++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/drivers/hid/hid-wiiu-drc.c b/drivers/hid/hid-wiiu-drc.c
index 80faaaad2bb5..119d55542e31 100644
--- a/drivers/hid/hid-wiiu-drc.c
+++ b/drivers/hid/hid-wiiu-drc.c
@@ -15,6 +15,8 @@
 #include <linux/device.h>
 #include <linux/hid.h>
 #include <linux/module.h>
+#include <linux/power_supply.h>
+#include <linux/spinlock.h>
 #include "hid-ids.h"
 
 #define DEVICE_NAME	"Nintendo Wii U gamepad"
@@ -69,6 +71,11 @@
 #define MAGNET_MIN	ACCEL_MIN
 #define MAGNET_MAX	ACCEL_MAX
 
+/* Battery constants */
+#define BATTERY_MIN	142
+#define BATTERY_MAX	178
+#define BATTERY_CAPACITY(val) ((val - BATTERY_MIN) * 100 / (BATTERY_MAX - BATTERY_MIN))
+
 /*
  * The device is setup with multiple input devices:
  * - A joypad with the buttons and sticks.
@@ -77,10 +84,17 @@
  */
 
 struct drc {
+	spinlock_t lock;
+
 	struct input_dev *joy_input_dev;
 	struct input_dev *touch_input_dev;
 	struct input_dev *accel_input_dev;
 	struct hid_device *hdev;
+	struct power_supply *battery;
+	struct power_supply_desc battery_desc;
+
+	u8 battery_energy;
+	int battery_status;
 };
 
 static int drc_raw_event(struct hid_device *hdev, struct hid_report *report,
@@ -89,6 +103,7 @@ static int drc_raw_event(struct hid_device *hdev, struct hid_report *report,
 	struct drc *drc = hid_get_drvdata(hdev);
 	int i, x, y, z, pressure, base;
 	u32 buttons;
+	unsigned long flags;
 
 	if (len != 128)
 		return 0;
@@ -206,6 +221,17 @@ static int drc_raw_event(struct hid_device *hdev, struct hid_report *report,
 	input_report_abs(drc->accel_input_dev, ABS_WHEEL, (int16_t)z);
 	input_sync(drc->accel_input_dev);
 
+	/* battery */
+	spin_lock_irqsave(&drc->lock, flags);
+	drc->battery_energy = data[5];
+	if (drc->battery_energy == BATTERY_MAX)
+		drc->battery_status = POWER_SUPPLY_STATUS_FULL;
+	else if ((data[4] & 0x40) != 0)
+		drc->battery_status = POWER_SUPPLY_STATUS_CHARGING;
+	else
+		drc->battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
+	spin_unlock_irqrestore(&drc->lock, flags);
+
 	/* let hidraw and hiddev handle the report */
 	return 0;
 }
@@ -309,10 +335,67 @@ static bool drc_setup_accel(struct drc *drc,
 	return true;
 }
 
+static enum power_supply_property drc_battery_props[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_CAPACITY,
+	POWER_SUPPLY_PROP_SCOPE,
+	POWER_SUPPLY_PROP_STATUS,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
+	POWER_SUPPLY_PROP_ENERGY_EMPTY,
+	POWER_SUPPLY_PROP_ENERGY_FULL,
+};
+
+static int drc_battery_get_property(struct power_supply *psy,
+				    enum power_supply_property psp,
+				    union power_supply_propval *val)
+{
+	struct drc *drc = power_supply_get_drvdata(psy);
+	unsigned long flags;
+	int ret = 0;
+	u8 battery_energy;
+	int battery_status;
+
+	spin_lock_irqsave(&drc->lock, flags);
+	battery_energy = drc->battery_energy;
+	battery_status = drc->battery_status;
+	spin_unlock_irqrestore(&drc->lock, flags);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = 1;
+		break;
+	case POWER_SUPPLY_PROP_SCOPE:
+		val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+		break;
+	case POWER_SUPPLY_PROP_CAPACITY:
+		val->intval = BATTERY_CAPACITY(battery_energy);
+		break;
+	case POWER_SUPPLY_PROP_STATUS:
+		val->intval = battery_status;
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+		val->intval = battery_energy;
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_EMPTY:
+		val->intval = BATTERY_MIN;
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_FULL:
+		val->intval = BATTERY_MAX;
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
 static bool drc_setup_joypad(struct drc *drc,
 		struct hid_device *hdev)
 {
 	struct input_dev *input_dev;
+	struct power_supply_config psy_cfg = { .drv_data = drc, };
+	int ret;
+	static uint8_t drc_num = 0;
 
 	input_dev = allocate_and_setup(hdev, DEVICE_NAME " Joypad");
 	if (!input_dev)
@@ -350,6 +433,30 @@ static bool drc_setup_joypad(struct drc *drc,
 
 	drc->joy_input_dev = input_dev;
 
+	drc->battery_desc.properties = drc_battery_props;
+	drc->battery_desc.num_properties = ARRAY_SIZE(drc_battery_props);
+	drc->battery_desc.get_property = drc_battery_get_property;
+	drc->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+	drc->battery_desc.use_for_apm = 0;
+
+	/*
+	 * TODO: It might be better to use the interface number as the drc_num,
+	 * but I don’t know how to fetch it from here.  In userland it is
+	 * /sys/devices/platform/latte/d140000.usb/usb3/3-1/3-1:1.?/bInterfaceNumber
+	 */
+	drc->battery_desc.name = devm_kasprintf(&hdev->dev, GFP_KERNEL, "wiiu-drc-%i-battery", drc_num++);
+	if (!drc->battery_desc.name)
+		return -ENOMEM;
+
+	drc->battery = devm_power_supply_register(&hdev->dev, &drc->battery_desc, &psy_cfg);
+	if (IS_ERR(drc->battery)) {
+		ret = PTR_ERR(drc->battery);
+		hid_err(hdev, "Unable to register battery device\n");
+		return ret;
+	}
+
+	power_supply_powers(drc->battery, &hdev->dev);
+
 	return true;
 }
 
-- 
2.31.1


  parent reply	other threads:[~2021-05-02 23:38 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-05-02 23:28 [PATCH 0/4] RFC: HID: wiiu-drc: Add a driver for the Wii U gamepad Emmanuel Gil Peyrot
2021-05-02 23:28 ` [PATCH 1/4] HID: wiiu-drc: Add a driver for this gamepad Emmanuel Gil Peyrot
2021-05-05 22:33   ` Jonathan Neuschäfer
2021-05-06 10:07     ` Emmanuel Gil Peyrot
2021-05-06 10:29       ` Jonathan Neuschäfer
2021-05-06 11:53   ` Barnabás Pőcze
2021-05-02 23:28 ` [PATCH 2/4] HID: wiiu-drc: Implement touch reports Emmanuel Gil Peyrot
2021-05-05 22:43   ` Jonathan Neuschäfer
2021-05-06 10:20     ` Emmanuel Gil Peyrot
2021-05-02 23:28 ` [PATCH 3/4] HID: wiiu-drc: Add accelerometer, gyroscope and magnetometer readings Emmanuel Gil Peyrot
2021-05-02 23:28 ` Emmanuel Gil Peyrot [this message]
2021-05-06 11:45   ` [PATCH 4/4] HID: wiiu-drc: Add battery reporting Barnabás Pőcze
2021-05-19  8:59 ` [PATCH v3 0/4] HID: wiiu-drc: Add a driver for the Wii U gamepad Emmanuel Gil Peyrot
2021-05-19  8:59   ` [PATCH v3 1/4] HID: wiiu-drc: Add a driver for this gamepad Emmanuel Gil Peyrot
2021-05-19  8:59   ` [PATCH v3 2/4] HID: wiiu-drc: Implement touch reports Emmanuel Gil Peyrot
2021-05-19  8:59   ` [PATCH v3 3/4] HID: wiiu-drc: Add accelerometer, gyroscope and magnetometer readings Emmanuel Gil Peyrot
2021-05-19  8:59   ` [PATCH v3 4/4] HID: wiiu-drc: Add battery reporting Emmanuel Gil Peyrot
2021-09-21 15:08   ` [PATCH v3 0/4] HID: wiiu-drc: Add a driver for the Wii U gamepad Emmanuel Gil Peyrot
2021-10-19  9:14     ` Jiri Kosina
2021-10-19  9:27       ` Emmanuel Gil Peyrot
2021-10-19  9:30         ` Jiri Kosina
2021-10-19  9:36           ` Emmanuel Gil Peyrot
2021-11-04 11:21           ` Emmanuel Gil Peyrot
2021-11-05 17:27             ` François-Xavier Carton
2021-10-19 23:59         ` François-Xavier Carton
2021-10-20  6:24           ` Emmanuel Gil Peyrot
2021-10-19 11:04   ` [PATCH v4 0/5] HID: nintendo: Add support " Emmanuel Gil Peyrot
2021-10-19 11:04     ` [PATCH v4 1/5] HID: nintendo: split switch support into its own file Emmanuel Gil Peyrot
2021-10-22  8:32       ` kernel test robot
2021-10-19 11:04     ` [PATCH v4 2/5] HID: nintendo: drc: add support for the Wii U gamepad Emmanuel Gil Peyrot
2021-11-05 20:55       ` kernel test robot
2021-10-19 11:04     ` [PATCH v4 3/5] HID: nintendo: drc: implement touch reports Emmanuel Gil Peyrot
2021-10-19 11:04     ` [PATCH v4 4/5] HID: nintendo: drc: add accelerometer, gyroscope and magnetometer readings Emmanuel Gil Peyrot
2021-10-19 11:04     ` [PATCH v4 5/5] HID: nintendo: drc: add battery reporting Emmanuel Gil Peyrot
2021-10-27  8:10     ` [PATCH v4 0/5] HID: nintendo: Add support for the Wii U gamepad Jiri Kosina
2021-10-27 10:10     ` [PATCH v5 " Emmanuel Gil Peyrot
2021-10-27 10:10       ` [PATCH v5 1/5] HID: nintendo: split switch support into its own file Emmanuel Gil Peyrot
2021-10-27 10:10       ` [PATCH v5 2/5] HID: nintendo: drc: add support for the Wii U gamepad Emmanuel Gil Peyrot
2021-10-27 10:10       ` [PATCH v5 3/5] HID: nintendo: drc: implement touch reports Emmanuel Gil Peyrot
2021-10-27 10:10       ` [PATCH v5 4/5] HID: nintendo: drc: add accelerometer, gyroscope and magnetometer readings Emmanuel Gil Peyrot
2021-10-27 10:10       ` [PATCH v5 5/5] HID: nintendo: drc: add battery reporting Emmanuel Gil Peyrot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210502232836.26134-5-linkmauve@linkmauve.fr \
    --to=linkmauve@linkmauve.fr \
    --cc=ash@heyquark.com \
    --cc=benjamin.tissoires@redhat.com \
    --cc=j.ne@posteo.net \
    --cc=jikos@kernel.org \
    --cc=linux-input@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).