* Re: [PATCH v4 27/28] gcc-sdm845: Add general purpose clock ops
From: Uwe Kleine-König @ 2024-09-10 9:59 UTC (permalink / raw)
To: Dzmitry Sankouski
Cc: dmitry.baryshkov, Sebastian Reichel, Bjorn Andersson,
Michael Turquette, Stephen Boyd, Neil Armstrong, Jessica Zhang,
Sam Ravnborg, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
David Airlie, Daniel Vetter, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Lee Jones, Dmitry Torokhov, Pavel Machek,
Liam Girdwood, Mark Brown, Krzysztof Kozlowski, Konrad Dybcio,
Chanwoo Choi, linux-pm, linux-kernel, linux-arm-msm, linux-clk,
dri-devel, devicetree, linux-input, linux-leds, linux-pwm,
linux-samsung-soc
In-Reply-To: <20240719-starqltechn_integration_upstream-v4-27-a7f644821941@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1149 bytes --]
Hello,
On Fri, Jul 19, 2024 at 03:55:04PM +0300, Dzmitry Sankouski wrote:
> SDM845 has "General Purpose" clocks that can be muxed to
> SoC pins to clock various external devices.
> Those clocks may be used as e.g. PWM sources for external peripherals.
>
> GPCLK can in theory have arbitrary value depending on the use case, so
> the concept of frequency tables, used in rcg2 clock driver, is not
> efficient, because it allows only defined frequencies.
>
> Introduce clk_rcg2_gp_ops, which automatically calculate clock
> mnd values for arbitrary clock rate.
>
> Signed-off-by: Dzmitry Sankouski <dsankouski@gmail.com>
> ---
> drivers/clk/qcom/clk-rcg.h | 1 +
> drivers/clk/qcom/clk-rcg2.c | 162 ++++++++++++++++++++++++++++++++++++++++--
> drivers/clk/qcom/gcc-sdm845.c | 19 ++---
> drivers/pwm/pwm-clk.c | 5 ++
I don't understand why a change to some qcom clk implementation detail
needs a change to drivers/pwm/pwm-clk.c in the same commit. I guess if
the change to drivers/pwm/pwm-clk.c is needed it should better go into a
separate patch with an appropriate commit log?!
Best regards
Uwe
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* [PATCH 3/3] Input: i8042 - add TUXEDO Stellaris 15 Slim Gen6 AMD to i8042 quirk table
From: Werner Sembach @ 2024-09-10 9:40 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Werner Sembach, linux-input, linux-kernel
In-Reply-To: <20240910094008.1601230-1-wse@tuxedocomputers.com>
The Gen6 devices have the same problem and the same Solution as the Gen5
ones.
Some TongFang barebones have touchpad and/or keyboard issues after
suspend, fixable with nomux + reset + noloop + nopnp. Luckily, none of
them have an external PS/2 port so this can safely be set for all of
them.
I'm not entirely sure if every device listed really needs all four quirks,
but after testing and production use, no negative effects could be
observed when setting all four.
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Cc: stable@vger.kernel.org
---
drivers/input/serio/i8042-acpipnpio.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index d16072b82d957..34d1f07ea4c30 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1150,6 +1150,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GMxHGxx"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
/*
* A lot of modern Clevo barebones have touchpad and/or keyboard issues
* after suspend fixable with nomux + reset + noloop + nopnp. Luckily,
--
2.34.1
^ permalink raw reply related
* [PATCH 2/3] Input: i8042 - Add another board name for TUXEDO Stellaris Gen5 AMD line
From: Werner Sembach @ 2024-09-10 9:40 UTC (permalink / raw)
To: Dmitry Torokhov; +Cc: Werner Sembach, linux-input, linux-kernel
In-Reply-To: <20240910094008.1601230-1-wse@tuxedocomputers.com>
There might be devices out in the wild where the board name is GMxXGxx
instead of GMxXGxX.
Adding both to be on the safe side.
Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
Cc: stable@vger.kernel.org
---
drivers/input/serio/i8042-acpipnpio.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/input/serio/i8042-acpipnpio.h b/drivers/input/serio/i8042-acpipnpio.h
index 1d73391f127bc..d16072b82d957 100644
--- a/drivers/input/serio/i8042-acpipnpio.h
+++ b/drivers/input/serio/i8042-acpipnpio.h
@@ -1136,6 +1136,13 @@ static const struct dmi_system_id i8042_dmi_quirk_table[] __initconst = {
.driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
},
+ {
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "GMxXGxx"),
+ },
+ .driver_data = (void *)(SERIO_QUIRK_NOMUX | SERIO_QUIRK_RESET_ALWAYS |
+ SERIO_QUIRK_NOLOOP | SERIO_QUIRK_NOPNP)
+ },
{
.matches = {
DMI_MATCH(DMI_BOARD_NAME, "GMxXGxX"),
--
2.34.1
^ permalink raw reply related
* [PATCH -next] Input: matrix_keypad: Remove duplicated include in matrix_keypad.c
From: Yang Li @ 2024-09-10 1:01 UTC (permalink / raw)
To: dmitry.torokhov; +Cc: linux-input, linux-kernel, Yang Li, Abaci Robot
The header files consumer.h is included twice in matrix_keypad.c,
so one inclusion of each can be removed.
Reported-by: Abaci Robot <abaci@linux.alibaba.com>
Closes: https://bugzilla.openanolis.cn/show_bug.cgi?id=10823
Signed-off-by: Yang Li <yang.lee@linux.alibaba.com>
---
drivers/input/keyboard/matrix_keypad.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c
index 3c38bae576ed..4cfdac922022 100644
--- a/drivers/input/keyboard/matrix_keypad.c
+++ b/drivers/input/keyboard/matrix_keypad.c
@@ -17,7 +17,6 @@
#include <linux/jiffies.h>
#include <linux/module.h>
#include <linux/gpio.h>
-#include <linux/gpio/consumer.h>
#include <linux/input/matrix_keypad.h>
#include <linux/slab.h>
#include <linux/of.h>
--
2.32.0.3.g01195cf9f
^ permalink raw reply related
* Re: [PATCH 1/2] HID: wacom: Support sequence numbers smaller than 16-bit
From: Jiri Kosina @ 2024-09-09 20:40 UTC (permalink / raw)
To: Gerecke, Jason
Cc: linux-input, Benjamin Tissoires, Ping Cheng, Joshua Dickens,
Jason Gerecke, Joshua Dickens
In-Reply-To: <20240909203208.47339-1-jason.gerecke@wacom.com>
On Mon, 9 Sep 2024, Gerecke, Jason wrote:
> From: Jason Gerecke <jason.gerecke@wacom.com>
>
> The current dropped packet reporting assumes that all sequence numbers
> are 16 bits in length. This results in misleading "Dropped" messages if
> the hardware uses fewer bits. For example, if a tablet uses only 8 bits
> to store its sequence number, once it rolls over from 255 -> 0, the
> driver will still be expecting a packet "256". This patch adjusts the
> logic to reset the next expected packet to logical_minimum whenever
> it overflows beyond logical_maximum.
>
> Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
> Tested-by: Joshua Dickens <joshua.dickens@wacom.com>
> Fixes: 6d09085b38e5 ("HID: wacom: Adding Support for new usages")
Hi Jason,
thanks for both fixes.
Looking at them, it seems like it'd normally be 6.11 material, but given
- how far we currently are in a 6.11 development cycle
- how long this issue has been present in the code
- the fact that it actually does change the event processing behavior
I have to ask you for a judgement -- would you like to absolutely see
these in 6.11 as last-minute fixes, or do you consider this to be 6.12
material?
Thanks,
--
Jiri Kosina
SUSE Labs
^ permalink raw reply
* [PATCH] HID: i2c-hid: ensure various commands do not interfere with each other
From: Dmitry Torokhov @ 2024-09-09 20:37 UTC (permalink / raw)
To: Jiri Kosina, . Benjamin Tissoires
Cc: Douglas Anderson, Hans de Goede, Kenny Levinsen, linux-input,
linux-kernel
i2c-hid uses 2 shared buffers: command and "raw" input buffer for
sending requests to peripherals and read data from peripherals when
executing variety of commands. Such commands include reading of HID
registers, requesting particular power mode, getting and setting
reports and so on. Because all such requests use the same 2 buffers
they should not execute simultaneously.
Fix this by introducing "cmd_lock" mutex and acquire it whenever
we needs to access ihid->cmdbuf or idid->rawbuf.
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
---
drivers/hid/i2c-hid/i2c-hid-core.c | 42 +++++++++++++++++++-----------
1 file changed, 27 insertions(+), 15 deletions(-)
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 632eaf9e11a6..2f8a9d3f1e86 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -105,6 +105,7 @@ struct i2c_hid {
wait_queue_head_t wait; /* For waiting the interrupt */
+ struct mutex cmd_lock; /* protects cmdbuf and rawbuf */
struct mutex reset_lock;
struct i2chid_ops *ops;
@@ -220,6 +221,8 @@ static int i2c_hid_xfer(struct i2c_hid *ihid,
static int i2c_hid_read_register(struct i2c_hid *ihid, __le16 reg,
void *buf, size_t len)
{
+ guard(mutex)(&ihid->cmd_lock);
+
*(__le16 *)ihid->cmdbuf = reg;
return i2c_hid_xfer(ihid, ihid->cmdbuf, sizeof(__le16), buf, len);
@@ -252,6 +255,8 @@ static int i2c_hid_get_report(struct i2c_hid *ihid,
i2c_hid_dbg(ihid, "%s\n", __func__);
+ guard(mutex)(&ihid->cmd_lock);
+
/* Command register goes first */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
length += sizeof(__le16);
@@ -342,6 +347,8 @@ static int i2c_hid_set_or_send_report(struct i2c_hid *ihid,
if (!do_set && le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0)
return -ENOSYS;
+ guard(mutex)(&ihid->cmd_lock);
+
if (do_set) {
/* Command register goes first */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
@@ -384,6 +391,8 @@ static int i2c_hid_set_power_command(struct i2c_hid *ihid, int power_state)
{
size_t length;
+ guard(mutex)(&ihid->cmd_lock);
+
/* SET_POWER uses command register */
*(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
length = sizeof(__le16);
@@ -440,25 +449,27 @@ static int i2c_hid_start_hwreset(struct i2c_hid *ihid)
if (ret)
return ret;
- /* Prepare reset command. Command register goes first. */
- *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
- length += sizeof(__le16);
- /* Next is RESET command itself */
- length += i2c_hid_encode_command(ihid->cmdbuf + length,
- I2C_HID_OPCODE_RESET, 0, 0);
+ scoped_guard(mutex, &ihid->cmd_lock) {
+ /* Prepare reset command. Command register goes first. */
+ *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister;
+ length += sizeof(__le16);
+ /* Next is RESET command itself */
+ length += i2c_hid_encode_command(ihid->cmdbuf + length,
+ I2C_HID_OPCODE_RESET, 0, 0);
- set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
+ set_bit(I2C_HID_RESET_PENDING, &ihid->flags);
- ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
- if (ret) {
- dev_err(&ihid->client->dev,
- "failed to reset device: %d\n", ret);
- goto err_clear_reset;
- }
+ ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0);
+ if (ret) {
+ dev_err(&ihid->client->dev,
+ "failed to reset device: %d\n", ret);
+ break;
+ }
- return 0;
+ return 0;
+ }
-err_clear_reset:
+ /* Clean up if sending reset command failed */
clear_bit(I2C_HID_RESET_PENDING, &ihid->flags);
i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP);
return ret;
@@ -1200,6 +1211,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops,
ihid->is_panel_follower = drm_is_panel_follower(&client->dev);
init_waitqueue_head(&ihid->wait);
+ mutex_init(&ihid->cmd_lock);
mutex_init(&ihid->reset_lock);
INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work);
--
2.46.0.598.g6f2099f65c-goog
--
Dmitry
^ permalink raw reply related
* [PATCH 2/2] HID: wacom: Do not warn about dropped packets for first packet
From: Gerecke, Jason @ 2024-09-09 20:32 UTC (permalink / raw)
To: linux-input, Benjamin Tissoires, Jiri Kosina
Cc: Ping Cheng, Joshua Dickens, Jason Gerecke, Joshua Dickens
In-Reply-To: <20240909203208.47339-1-jason.gerecke@wacom.com>
From: Jason Gerecke <jason.gerecke@wacom.com>
The driver currently assumes that the first sequence number it will see
is going to be 0. This is not a realiable assumption and can break if,
for example, the tablet has already been running for some time prior to
the kernel driver connecting to the device. This commit initializes the
expected sequence number to -1 and will only print the "Dropped" warning
the it has been updated to a non-negative value.
Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Tested-by: Joshua Dickens <joshua.dickens@wacom.com>
Fixes: 6d09085b38e5 ("HID: wacom: Adding Support for new usages")
---
drivers/hid/wacom_wac.c | 6 +++++-
drivers/hid/wacom_wac.h | 2 +-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index cef08737a6240..59a13ad9371cd 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2388,6 +2388,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev,
wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS3, 0);
features->quirks &= ~WACOM_QUIRK_PEN_BUTTON3;
break;
+ case WACOM_HID_WD_SEQUENCENUMBER:
+ wacom_wac->hid_data.sequence_number = -1;
+ break;
}
}
@@ -2512,7 +2515,8 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
wacom_wac->hid_data.barrelswitch3 = value;
return;
case WACOM_HID_WD_SEQUENCENUMBER:
- if (wacom_wac->hid_data.sequence_number != value) {
+ if (wacom_wac->hid_data.sequence_number != value &&
+ wacom_wac->hid_data.sequence_number >= 0) {
int sequence_size = field->logical_maximum - field->logical_minimum + 1;
int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
hid_warn(hdev, "Dropped %d packets", drop_count);
diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h
index 55e0c7a9fdcb4..c8803d5c6a71e 100644
--- a/drivers/hid/wacom_wac.h
+++ b/drivers/hid/wacom_wac.h
@@ -326,7 +326,7 @@ struct hid_data {
int bat_connected;
int ps_connected;
bool pad_input_event_flag;
- unsigned short sequence_number;
+ int sequence_number;
ktime_t time_delayed;
};
--
2.46.0
^ permalink raw reply related
* [PATCH 1/2] HID: wacom: Support sequence numbers smaller than 16-bit
From: Gerecke, Jason @ 2024-09-09 20:32 UTC (permalink / raw)
To: linux-input, Benjamin Tissoires, Jiri Kosina
Cc: Ping Cheng, Joshua Dickens, Jason Gerecke, Joshua Dickens
From: Jason Gerecke <jason.gerecke@wacom.com>
The current dropped packet reporting assumes that all sequence numbers
are 16 bits in length. This results in misleading "Dropped" messages if
the hardware uses fewer bits. For example, if a tablet uses only 8 bits
to store its sequence number, once it rolls over from 255 -> 0, the
driver will still be expecting a packet "256". This patch adjusts the
logic to reset the next expected packet to logical_minimum whenever
it overflows beyond logical_maximum.
Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
Tested-by: Joshua Dickens <joshua.dickens@wacom.com>
Fixes: 6d09085b38e5 ("HID: wacom: Adding Support for new usages")
---
drivers/hid/wacom_wac.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c
index 74258a78d0408..cef08737a6240 100644
--- a/drivers/hid/wacom_wac.c
+++ b/drivers/hid/wacom_wac.c
@@ -2512,9 +2512,14 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field
wacom_wac->hid_data.barrelswitch3 = value;
return;
case WACOM_HID_WD_SEQUENCENUMBER:
- if (wacom_wac->hid_data.sequence_number != value)
- hid_warn(hdev, "Dropped %hu packets", (unsigned short)(value - wacom_wac->hid_data.sequence_number));
+ if (wacom_wac->hid_data.sequence_number != value) {
+ int sequence_size = field->logical_maximum - field->logical_minimum + 1;
+ int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size;
+ hid_warn(hdev, "Dropped %d packets", drop_count);
+ }
wacom_wac->hid_data.sequence_number = value + 1;
+ if (wacom_wac->hid_data.sequence_number > field->logical_maximum)
+ wacom_wac->hid_data.sequence_number = field->logical_minimum;
return;
}
--
2.46.0
^ permalink raw reply related
* Re: [PATCH v2 0/3] iio: Introduce and use aligned_s64 type
From: Jonathan Cameron @ 2024-09-09 19:01 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Uwe Kleine-König, Jonathan Cameron, Srinivas Pandruvada,
Basavaraj Natikar, linux-input, linux-iio, linux-kernel,
Jiri Kosina, Lars-Peter Clausen, Lorenzo Bianconi
In-Reply-To: <Zt695hJRwiT2RSJT@smile.fi.intel.com>
On Mon, 9 Sep 2024 12:20:38 +0300
Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> On Sat, Sep 07, 2024 at 04:37:52PM +0100, Jonathan Cameron wrote:
> > On Tue, 3 Sep 2024 20:59:03 +0300
> > Andy Shevchenko <andriy.shevchenko@linux.intel.com> wrote:
> >
> > > Instead of having open coded idea of aligned member, use
> > > a newly defined type like it's done in, e.g., u64 case.
> > > Update a few IIO drivers to show how to use it.
> > >
> > > v2 (took only one year from v1, not bad!):
> > :)
> >
> > Applied with that tweak for patch 2 that you called out.
>
> Please, also do
> s/__aligned_s64/aligned_s64/
> in the commit message there.
done I think
>
> > Will probably be next cycle though before these go upstream
> > (so think of this as queuing them up very early for 6.13 :)
>
> Sure, thanks!
>
^ permalink raw reply
* [PATCH v4 RESEND] HID: corsair-void: Add Corsair Void headset family driver
From: Stuart Hayhurst @ 2024-09-09 18:49 UTC (permalink / raw)
To: linux-input
Cc: Stuart Hayhurst, Jiri Kosina, Benjamin Tissoires,
Christophe JAILLET, linux-kernel
Introduce a driver for the Corsair Void family of headsets, supporting:
- Battery reporting (power_supply)
- Sidetone setting support
- Physical microphone location reporting
- Headset and receiver firmware version reporting
- Built-in alert triggering
- USB wireless_status
Tested with a Void Pro Wireless, Void Elite Wireless and a Void Elite Wired
Signed-off-by: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
---
Just a couple questions about the sysfs attributes:
- Should the sysfs documentation use the implementation date (current), or the date it was submitted?
- Are the attribute names correct? I guessed reasonable names, but if there's a convention I'll correct them
- For cases where the wireless headset is disconnected, `microphone_up` returns -ENODEV
- Should it be left like that, or deregister the attributes when the headset disconnects?
v3 -> v4:
- Added missing <linux/device.h> include
- Added missing newline, fix indent
- Use hid_hw_raw_request return code directly for wireless sidetone
- Use battery status enum for remaining values
- Use of devm_kasprintf() to create battery string
- Moved corsair_void_request_status error reporting to callers
- Simplified corsair_void_request_status
- Removed battery_struct_size, use sizeof(*battery_data) instead
- Removed unnecessary curly brackets in send_alert_store
v2 -> v3:
- Use __free(kfree) helper to free allocations
- Combined similar condition checks
- Check power_supply was created successfully before saving it
- Removed explicit initialisation of return value in corsair_void_probe
- Use preferred syntax for drvdata's struct allocation size
- Removed named success exit point from driver probe
- Removed unused driver probe exit point
v1 -> v2:
- Added a module author email address
- Removed unused variable (psy_cfg)
- Corrected status request buffer size from 12 bytes to 2 bytes
- Use enums for battery status
- Use kmalloc instead of kzalloc where applicable
- Use __le16 type for cpu_to_le16
- Use DEVICE_ATTR_RO and DEVICE_ATTR_WO to create attributes
- Simplified corsair_void_set_sidetone_wired
- Cleaned up patch description
.../ABI/testing/sysfs-driver-hid-corsair-void | 38 +
drivers/hid/Kconfig | 10 +
drivers/hid/Makefile | 1 +
drivers/hid/hid-corsair-void.c | 829 ++++++++++++++++++
4 files changed, 878 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-driver-hid-corsair-void
create mode 100644 drivers/hid/hid-corsair-void.c
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-corsair-void b/Documentation/ABI/testing/sysfs-driver-hid-corsair-void
new file mode 100644
index 000000000000..f933ba15dd6d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-hid-corsair-void
@@ -0,0 +1,38 @@
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/fw_version_headset
+Date: January 2024
+KernelVersion: 6.12
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) The firmware version of the headset
+ * Returns -ENODATA if no version was reported
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/fw_version_receiver
+Date: January 2024
+KernelVersion: 6.12
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) The firmware version of the receiver
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/microphone_up
+Date: July 2023
+KernelVersion: 6.12
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) Get the physical position of the microphone
+ * 1 -> Microphone up
+ * 0 -> Microphone down
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/send_alert
+Date: July 2023
+KernelVersion: 6.12
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (W) Play a built-in notification from the headset (0 / 1)
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/set_sidetone
+Date: December 2023
+KernelVersion: 6.12
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (W) Set the sidetone volume (0 - sidetone_max)
+
+What: /sys/bus/hid/drivers/hid-corsair-void/<dev>/sidetone_max
+Date: July 2024
+KernelVersion: 6.12
+Contact: Stuart Hayhurst <stuart.a.hayhurst@gmail.com>
+Description: (R) Report the maximum sidetone volume
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
index 08446c89eff6..7dcf911f3367 100644
--- a/drivers/hid/Kconfig
+++ b/drivers/hid/Kconfig
@@ -221,6 +221,16 @@ config HID_CORSAIR
- Vengeance K90
- Scimitar PRO RGB
+config HID_CORSAIR_VOID
+ tristate "Corsair Void headsets"
+ depends on USB_HID
+ select POWER_SUPPLY
+ help
+ Support for Corsair Void headsets.
+
+ Supported devices:
+ - Corsair Void headsets
+
config HID_COUGAR
tristate "Cougar devices"
help
diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
index e40f1ddebbb7..037d7e3b6c3e 100644
--- a/drivers/hid/Makefile
+++ b/drivers/hid/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_HID_CHERRY) += hid-cherry.o
obj-$(CONFIG_HID_CHICONY) += hid-chicony.o
obj-$(CONFIG_HID_CMEDIA) += hid-cmedia.o
obj-$(CONFIG_HID_CORSAIR) += hid-corsair.o
+obj-$(CONFIG_HID_CORSAIR_VOID) += hid-corsair-void.o
obj-$(CONFIG_HID_COUGAR) += hid-cougar.o
obj-$(CONFIG_HID_CP2112) += hid-cp2112.o
obj-$(CONFIG_HID_CYPRESS) += hid-cypress.o
diff --git a/drivers/hid/hid-corsair-void.c b/drivers/hid/hid-corsair-void.c
new file mode 100644
index 000000000000..6ece56b850fc
--- /dev/null
+++ b/drivers/hid/hid-corsair-void.c
@@ -0,0 +1,829 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * HID driver for Corsair Void headsets
+ *
+ * Copyright (C) 2023-2024 Stuart Hayhurst
+ */
+
+/* -------------------------------------------------------------------------- */
+/* Receiver report information: (ID 100) */
+/* -------------------------------------------------------------------------- */
+/*
+ * When queried, the receiver reponds with 5 bytes to describe the battery
+ * The power button, mute button and moving the mic also trigger this report
+ * This includes power button + mic + connection + battery status and capacity
+ * The information below may not be perfect, it's been gathered through guesses
+ *
+ * 0: REPORT ID
+ * 100 for the battery packet
+ *
+ * 1: POWER BUTTON + (?)
+ * Largest bit is 1 when power button pressed
+ *
+ * 2: BATTERY CAPACITY + MIC STATUS
+ * Battery capacity:
+ * Seems to report ~54 higher than reality when charging
+ * Capped at 100, charging or not
+ * Microphone status:
+ * Largest bit is set to 1 when the mic is physically up
+ * No bits change when the mic is muted, only when physically moved
+ * This report is sent every time the mic is moved, no polling required
+ *
+ * 3: CONNECTION STATUS
+ * 16: Wired headset
+ * 38: Initialising
+ * 49: Lost connection
+ * 51: Disconnected, searching
+ * 52: Disconnected, not searching
+ * 177: Normal
+ *
+ * 4: BATTERY STATUS
+ * 0: Disconnected
+ * 1: Normal
+ * 2: Low
+ * 3: Critical - sent during shutdown
+ * 4: Fully charged
+ * 5: Charging
+ */
+/* -------------------------------------------------------------------------- */
+
+/* -------------------------------------------------------------------------- */
+/* Receiver report information: (ID 102) */
+/* -------------------------------------------------------------------------- */
+/*
+ * When queried, the recevier responds with 4 bytes to describe the firmware
+ * The first 2 bytes are for the receiver, the second 2 are the headset
+ * The headset firmware version will be 0 if no headset is connected
+ *
+ * 0: Recevier firmware major version
+ * Major version of the receiver's firmware
+ *
+ * 1: Recevier firmware minor version
+ * Minor version of the receiver's firmware
+ *
+ * 2: Headset firmware major version
+ * Major version of the headset's firmware
+ *
+ * 3: Headset firmware minor version
+ * Minor version of the headset's firmware
+ */
+/* -------------------------------------------------------------------------- */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/cleanup.h>
+#include <linux/device.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
+#include <linux/usb.h>
+#include <linux/workqueue.h>
+#include <asm/byteorder.h>
+
+#include "hid-ids.h"
+
+#define CORSAIR_VOID_DEVICE(id, type) { HID_USB_DEVICE(USB_VENDOR_ID_CORSAIR, (id)), \
+ .driver_data = (type) }
+#define CORSAIR_VOID_WIRELESS_DEVICE(id) CORSAIR_VOID_DEVICE((id), CORSAIR_VOID_WIRELESS)
+#define CORSAIR_VOID_WIRED_DEVICE(id) CORSAIR_VOID_DEVICE((id), CORSAIR_VOID_WIRED)
+
+#define CORSAIR_VOID_STATUS_REQUEST_ID 0xC9
+#define CORSAIR_VOID_NOTIF_REQUEST_ID 0xCA
+#define CORSAIR_VOID_SIDETONE_REQUEST_ID 0xFF
+#define CORSAIR_VOID_STATUS_REPORT_ID 0x64
+#define CORSAIR_VOID_FIRMWARE_REPORT_ID 0x66
+
+#define CORSAIR_VOID_USB_SIDETONE_REQUEST 0x1
+#define CORSAIR_VOID_USB_SIDETONE_REQUEST_TYPE 0x21
+#define CORSAIR_VOID_USB_SIDETONE_VALUE 0x200
+#define CORSAIR_VOID_USB_SIDETONE_INDEX 0xB00
+
+#define CORSAIR_VOID_MIC_MASK GENMASK(7, 7)
+#define CORSAIR_VOID_CAPACITY_MASK GENMASK(6, 0)
+
+#define CORSAIR_VOID_WIRELESS_CONNECTED 177
+
+#define CORSAIR_VOID_SIDETONE_MAX_WIRELESS 55
+#define CORSAIR_VOID_SIDETONE_MAX_WIRED 4096
+
+enum {
+ CORSAIR_VOID_WIRELESS,
+ CORSAIR_VOID_WIRED,
+};
+
+enum {
+ CORSAIR_VOID_BATTERY_NORMAL = 1,
+ CORSAIR_VOID_BATTERY_LOW = 2,
+ CORSAIR_VOID_BATTERY_CRITICAL = 3,
+ CORSAIR_VOID_BATTERY_CHARGED = 4,
+ CORSAIR_VOID_BATTERY_CHARGING = 5,
+};
+
+static enum power_supply_property corsair_void_battery_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
+ POWER_SUPPLY_PROP_SCOPE,
+ POWER_SUPPLY_PROP_MODEL_NAME,
+ POWER_SUPPLY_PROP_MANUFACTURER,
+};
+
+struct corsair_void_battery_data {
+ int status;
+ bool present;
+ int capacity;
+ int capacity_level;
+};
+
+struct corsair_void_drvdata {
+ struct hid_device *hid_dev;
+ struct device *dev;
+
+ char *name;
+ bool is_wired;
+ unsigned int sidetone_max;
+
+ struct corsair_void_battery_data battery_data;
+ bool mic_up;
+ bool connected;
+ int fw_receiver_major;
+ int fw_receiver_minor;
+ int fw_headset_major;
+ int fw_headset_minor;
+
+ struct power_supply *battery;
+ struct power_supply_desc battery_desc;
+ struct mutex battery_mutex;
+
+ struct delayed_work delayed_status_work;
+ struct delayed_work delayed_firmware_work;
+ struct work_struct battery_remove_work;
+ struct work_struct battery_add_work;
+};
+
+/*
+ * Functions to process receiver data
+*/
+
+static void corsair_void_set_wireless_status(struct corsair_void_drvdata *drvdata)
+{
+ struct usb_interface *usb_if = to_usb_interface(drvdata->dev->parent);
+
+ if (drvdata->is_wired)
+ return;
+
+ usb_set_wireless_status(usb_if, drvdata->connected ?
+ USB_WIRELESS_STATUS_CONNECTED :
+ USB_WIRELESS_STATUS_DISCONNECTED);
+}
+
+static void corsair_void_set_unknown_batt(struct corsair_void_drvdata *drvdata)
+{
+ struct corsair_void_battery_data *battery_data = &drvdata->battery_data;
+
+ battery_data->status = POWER_SUPPLY_STATUS_UNKNOWN;
+ battery_data->present = false;
+ battery_data->capacity = 0;
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
+}
+
+/* Reset data that may change between wireless connections */
+static void corsair_void_set_unknown_wireless_data(struct corsair_void_drvdata *drvdata)
+{
+ /* Only 0 out headset, receiver is always known if relevant */
+ drvdata->fw_headset_major = 0;
+ drvdata->fw_headset_minor = 0;
+
+ drvdata->connected = false;
+ drvdata->mic_up = false;
+
+ corsair_void_set_wireless_status(drvdata);
+}
+
+static void corsair_void_process_receiver(struct corsair_void_drvdata *drvdata,
+ int raw_battery_capacity,
+ int raw_connection_status,
+ int raw_battery_status)
+{
+ struct corsair_void_battery_data *battery_data = &drvdata->battery_data;
+ struct corsair_void_battery_data orig_battery_data;
+
+ /* Save initial battery data, to compare later */
+ orig_battery_data = *battery_data;
+
+ /* Headset not connected, or it's wired */
+ if (raw_connection_status != CORSAIR_VOID_WIRELESS_CONNECTED)
+ goto unknown_battery;
+
+ /* Battery information unavailable */
+ if (raw_battery_status == 0)
+ goto unknown_battery;
+
+ /* Battery must be connected then */
+ battery_data->present = true;
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+
+ /* Set battery status */
+ switch (raw_battery_status) {
+ case CORSAIR_VOID_BATTERY_NORMAL:
+ case CORSAIR_VOID_BATTERY_LOW:
+ case CORSAIR_VOID_BATTERY_CRITICAL:
+ battery_data->status = POWER_SUPPLY_STATUS_DISCHARGING;
+ if (raw_battery_status == CORSAIR_VOID_BATTERY_LOW)
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (raw_battery_status == CORSAIR_VOID_BATTERY_CRITICAL)
+ battery_data->capacity_level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+
+ break;
+ case CORSAIR_VOID_BATTERY_CHARGED:
+ battery_data->status = POWER_SUPPLY_STATUS_FULL;
+ break;
+ case CORSAIR_VOID_BATTERY_CHARGING:
+ battery_data->status = POWER_SUPPLY_STATUS_CHARGING;
+ break;
+ default:
+ hid_warn(drvdata->hid_dev, "unknown battery status '%d'",
+ raw_battery_status);
+ goto unknown_battery;
+ break;
+ }
+
+ battery_data->capacity = raw_battery_capacity;
+ corsair_void_set_wireless_status(drvdata);
+
+ goto success;
+unknown_battery:
+ corsair_void_set_unknown_batt(drvdata);
+success:
+
+ /* Inform power supply if battery values changed */
+ if (memcmp(&orig_battery_data, battery_data, sizeof(*battery_data))) {
+ scoped_guard(mutex, &drvdata->battery_mutex) {
+ if (drvdata->battery) {
+ power_supply_changed(drvdata->battery);
+ }
+ }
+ }
+}
+
+/*
+ * Functions to report stored data
+*/
+
+static int corsair_void_battery_get_property(struct power_supply *psy,
+ enum power_supply_property prop,
+ union power_supply_propval *val)
+{
+ struct corsair_void_drvdata *drvdata = power_supply_get_drvdata(psy);
+
+ switch (prop) {
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
+ case POWER_SUPPLY_PROP_MODEL_NAME:
+ if (!strncmp(drvdata->hid_dev->name, "Corsair ", 8))
+ val->strval = drvdata->hid_dev->name + 8;
+ else
+ val->strval = drvdata->hid_dev->name;
+ break;
+ case POWER_SUPPLY_PROP_MANUFACTURER:
+ val->strval = "Corsair";
+ break;
+ case POWER_SUPPLY_PROP_STATUS:
+ val->intval = drvdata->battery_data.status;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = drvdata->battery_data.present;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ val->intval = drvdata->battery_data.capacity;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ val->intval = drvdata->battery_data.capacity_level;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static ssize_t microphone_up_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (!drvdata->connected)
+ return -ENODEV;
+
+ return sysfs_emit(buf, "%d\n", drvdata->mic_up);
+}
+
+static ssize_t fw_version_receiver_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata->fw_receiver_major == 0 && drvdata->fw_receiver_minor == 0)
+ return -ENODATA;
+
+ return sysfs_emit(buf, "%d.%02d\n", drvdata->fw_receiver_major,
+ drvdata->fw_receiver_minor);
+}
+
+
+static ssize_t fw_version_headset_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ if (drvdata->fw_headset_major == 0 && drvdata->fw_headset_minor == 0)
+ return -ENODATA;
+
+ return sysfs_emit(buf, "%d.%02d\n", drvdata->fw_headset_major,
+ drvdata->fw_headset_minor);
+}
+
+static ssize_t sidetone_max_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", drvdata->sidetone_max);
+}
+
+/*
+ * Functions to send data to headset
+*/
+
+static ssize_t send_alert_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+ struct hid_device *hid_dev = drvdata->hid_dev;
+ unsigned char alert_id;
+ unsigned char *send_buf __free(kfree) = NULL;
+ int ret;
+
+ if (!drvdata->connected || drvdata->is_wired)
+ return -ENODEV;
+
+ /* Only accept 0 or 1 for alert ID */
+ if (kstrtou8(buf, 10, &alert_id) || alert_id >= 2)
+ return -EINVAL;
+
+ send_buf = kmalloc(3, GFP_KERNEL);
+ if (!send_buf)
+ return -ENOMEM;
+
+ /* Packet format to send alert with ID alert_id */
+ send_buf[0] = CORSAIR_VOID_NOTIF_REQUEST_ID;
+ send_buf[1] = 0x02;
+ send_buf[2] = alert_id;
+
+ ret = hid_hw_raw_request(hid_dev, CORSAIR_VOID_NOTIF_REQUEST_ID,
+ send_buf, 3, HID_OUTPUT_REPORT,
+ HID_REQ_SET_REPORT);
+ if (ret < 0)
+ hid_warn(hid_dev, "failed to send alert request (reason: %d)",
+ ret);
+ else
+ ret = count;
+
+ return ret;
+}
+
+static int corsair_void_set_sidetone_wired(struct device *dev, const char *buf,
+ unsigned int sidetone)
+{
+ struct usb_interface *usb_if = to_usb_interface(dev->parent);
+ struct usb_device *usb_dev = interface_to_usbdev(usb_if);
+
+ /* Packet format to set sidetone for wired headsets */
+ __le16 sidetone_le = cpu_to_le16(sidetone);
+
+ return usb_control_msg_send(usb_dev, 0,
+ CORSAIR_VOID_USB_SIDETONE_REQUEST,
+ CORSAIR_VOID_USB_SIDETONE_REQUEST_TYPE,
+ CORSAIR_VOID_USB_SIDETONE_VALUE,
+ CORSAIR_VOID_USB_SIDETONE_INDEX,
+ &sidetone_le, 2, USB_CTRL_SET_TIMEOUT,
+ GFP_KERNEL);
+}
+
+static int corsair_void_set_sidetone_wireless(struct device *dev,
+ const char *buf,
+ unsigned char sidetone)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+ struct hid_device *hid_dev = drvdata->hid_dev;
+ unsigned char *send_buf __free(kfree) = NULL;
+
+ send_buf = kmalloc(12, GFP_KERNEL);
+ if (!send_buf)
+ return -ENOMEM;
+
+ /* Packet format to set sidetone for wireless headsets */
+ send_buf[0] = CORSAIR_VOID_SIDETONE_REQUEST_ID;
+ send_buf[1] = 0x0B;
+ send_buf[2] = 0x00;
+ send_buf[3] = 0xFF;
+ send_buf[4] = 0x04;
+ send_buf[5] = 0x0E;
+ send_buf[6] = 0xFF;
+ send_buf[7] = 0x05;
+ send_buf[8] = 0x01;
+ send_buf[9] = 0x04;
+ send_buf[10] = 0x00;
+ send_buf[11] = sidetone + 200;
+
+ return hid_hw_raw_request(hid_dev, CORSAIR_VOID_SIDETONE_REQUEST_ID,
+ send_buf, 12, HID_FEATURE_REPORT,
+ HID_REQ_SET_REPORT);
+}
+
+static ssize_t set_sidetone_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct corsair_void_drvdata *drvdata = dev_get_drvdata(dev);
+ struct hid_device *hid_dev = drvdata->hid_dev;
+ unsigned int sidetone;
+ int ret;
+
+ if (!drvdata->connected)
+ return -ENODEV;
+
+ /* sidetone must be between 0 and drvdata->sidetone_max inclusive */
+ if (kstrtouint(buf, 10, &sidetone) || sidetone > drvdata->sidetone_max)
+ return -EINVAL;
+
+ if (drvdata->is_wired)
+ ret = corsair_void_set_sidetone_wired(dev, buf, sidetone);
+ else
+ ret = corsair_void_set_sidetone_wireless(dev, buf, sidetone);
+
+ if (ret < 0)
+ hid_warn(hid_dev, "failed to send sidetone (reason: %d)", ret);
+ else
+ ret = count;
+
+ return ret;
+}
+
+static int corsair_void_request_status(struct hid_device *hid_dev, int id)
+{
+ unsigned char *send_buf __free(kfree) = NULL;
+
+ send_buf = kmalloc(2, GFP_KERNEL);
+ if (!send_buf)
+ return -ENOMEM;
+
+ /* Packet format to request data item (status / firmware) refresh */
+ send_buf[0] = CORSAIR_VOID_STATUS_REQUEST_ID;
+ send_buf[1] = id;
+
+ /* Send request for data refresh */
+ return hid_hw_raw_request(hid_dev, CORSAIR_VOID_STATUS_REQUEST_ID,
+ send_buf, 2, HID_OUTPUT_REPORT,
+ HID_REQ_SET_REPORT);
+}
+
+/*
+ * Headset connect / disconnect handlers and work handlers
+*/
+
+static void corsair_void_status_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+ struct delayed_work *delayed_work;
+ int battery_ret;
+
+ delayed_work = container_of(work, struct delayed_work, work);
+ drvdata = container_of(delayed_work, struct corsair_void_drvdata,
+ delayed_status_work);
+
+ battery_ret = corsair_void_request_status(drvdata->hid_dev,
+ CORSAIR_VOID_STATUS_REPORT_ID);
+ if (battery_ret < 0) {
+ hid_warn(drvdata->hid_dev,
+ "failed to request battery (reason: %d)", battery_ret);
+ }
+}
+
+static void corsair_void_firmware_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+ struct delayed_work *delayed_work;
+ int firmware_ret;
+
+ delayed_work = container_of(work, struct delayed_work, work);
+ drvdata = container_of(delayed_work, struct corsair_void_drvdata,
+ delayed_firmware_work);
+
+ firmware_ret = corsair_void_request_status(drvdata->hid_dev,
+ CORSAIR_VOID_FIRMWARE_REPORT_ID);
+ if (firmware_ret < 0) {
+ hid_warn(drvdata->hid_dev,
+ "failed to request firmware (reason: %d)", firmware_ret);
+ }
+
+}
+
+static void corsair_void_battery_remove_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+
+ drvdata = container_of(work, struct corsair_void_drvdata,
+ battery_remove_work);
+ scoped_guard(mutex, &drvdata->battery_mutex) {
+ if (drvdata->battery) {
+ power_supply_unregister(drvdata->battery);
+ drvdata->battery = NULL;
+ }
+ }
+}
+
+static void corsair_void_battery_add_work_handler(struct work_struct *work)
+{
+ struct corsair_void_drvdata *drvdata;
+ struct power_supply_config psy_cfg;
+ struct power_supply *new_supply;
+
+ drvdata = container_of(work, struct corsair_void_drvdata,
+ battery_add_work);
+ guard(mutex)(&drvdata->battery_mutex);
+ if (drvdata->battery)
+ return;
+
+ psy_cfg.drv_data = drvdata;
+ new_supply = power_supply_register(drvdata->dev,
+ &drvdata->battery_desc,
+ &psy_cfg);
+
+ if (IS_ERR(new_supply)) {
+ hid_err(drvdata->hid_dev,
+ "failed to register battery '%s' (reason: %ld)\n",
+ drvdata->battery_desc.name,
+ PTR_ERR(new_supply));
+ return;
+ }
+
+ if (power_supply_powers(new_supply, drvdata->dev)) {
+ power_supply_unregister(new_supply);
+ return;
+ }
+
+ drvdata->battery = new_supply;
+}
+
+static void corsair_void_headset_connected(struct corsair_void_drvdata *drvdata)
+{
+ schedule_work(&drvdata->battery_add_work);
+ schedule_delayed_work(&drvdata->delayed_firmware_work,
+ msecs_to_jiffies(100));
+}
+
+static void corsair_void_headset_disconnected(struct corsair_void_drvdata *drvdata)
+{
+ schedule_work(&drvdata->battery_remove_work);
+
+ corsair_void_set_unknown_wireless_data(drvdata);
+ corsair_void_set_unknown_batt(drvdata);
+}
+
+/*
+ * Driver setup, probing and HID event handling
+*/
+
+static DEVICE_ATTR_RO(fw_version_receiver);
+static DEVICE_ATTR_RO(fw_version_headset);
+static DEVICE_ATTR_RO(microphone_up);
+static DEVICE_ATTR_RO(sidetone_max);
+
+static DEVICE_ATTR_WO(send_alert);
+static DEVICE_ATTR_WO(set_sidetone);
+
+static struct attribute *corsair_void_attrs[] = {
+ &dev_attr_fw_version_receiver.attr,
+ &dev_attr_fw_version_headset.attr,
+ &dev_attr_microphone_up.attr,
+ &dev_attr_send_alert.attr,
+ &dev_attr_set_sidetone.attr,
+ &dev_attr_sidetone_max.attr,
+ NULL,
+};
+
+static const struct attribute_group corsair_void_attr_group = {
+ .attrs = corsair_void_attrs,
+};
+
+static int corsair_void_probe(struct hid_device *hid_dev,
+ const struct hid_device_id *hid_id)
+{
+ int ret;
+ struct corsair_void_drvdata *drvdata;
+ char *name;
+
+ if (!hid_is_usb(hid_dev))
+ return -EINVAL;
+
+ drvdata = devm_kzalloc(&hid_dev->dev, sizeof(*drvdata),
+ GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ hid_set_drvdata(hid_dev, drvdata);
+ dev_set_drvdata(&hid_dev->dev, drvdata);
+
+ drvdata->dev = &hid_dev->dev;
+ drvdata->hid_dev = hid_dev;
+ drvdata->is_wired = hid_id->driver_data == CORSAIR_VOID_WIRED;
+
+ drvdata->sidetone_max = CORSAIR_VOID_SIDETONE_MAX_WIRELESS;
+ if (drvdata->is_wired)
+ drvdata->sidetone_max = CORSAIR_VOID_SIDETONE_MAX_WIRED;
+
+ /* Set initial values for no wireless headset attached */
+ /* If a headset is attached, it'll be prompted later */
+ corsair_void_set_unknown_wireless_data(drvdata);
+ corsair_void_set_unknown_batt(drvdata);
+
+ /* Receiver version won't be reset after init */
+ /* Headset version already set via set_unknown_wireless_data */
+ drvdata->fw_receiver_major = 0;
+ drvdata->fw_receiver_minor = 0;
+
+ ret = hid_parse(hid_dev);
+ if (ret) {
+ hid_err(hid_dev, "parse failed (reason: %d)\n", ret);
+ return ret;
+ }
+
+ name = devm_kasprintf(drvdata->dev, GFP_KERNEL,
+ "corsair-void-%d-battery", hid_dev->id);
+ if (!name)
+ return -ENOMEM;
+
+ drvdata->battery_desc.name = name;
+ drvdata->battery_desc.type = POWER_SUPPLY_TYPE_BATTERY;
+ drvdata->battery_desc.properties = corsair_void_battery_props;
+ drvdata->battery_desc.num_properties = ARRAY_SIZE(corsair_void_battery_props);
+ drvdata->battery_desc.get_property = corsair_void_battery_get_property;
+
+ drvdata->battery = NULL;
+ INIT_WORK(&drvdata->battery_remove_work,
+ corsair_void_battery_remove_work_handler);
+ INIT_WORK(&drvdata->battery_add_work,
+ corsair_void_battery_add_work_handler);
+ ret = devm_mutex_init(drvdata->dev, &drvdata->battery_mutex);
+ if (ret)
+ return ret;
+
+ ret = sysfs_create_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
+ if (ret)
+ return ret;
+
+ /* Any failures after here will need to call hid_hw_stop */
+ ret = hid_hw_start(hid_dev, HID_CONNECT_DEFAULT);
+ if (ret) {
+ hid_err(hid_dev, "hid_hw_start failed (reason: %d)\n", ret);
+ goto failed_after_sysfs;
+ }
+
+ /* Refresh battery data, in case wireless headset is already connected */
+ INIT_DELAYED_WORK(&drvdata->delayed_status_work,
+ corsair_void_status_work_handler);
+ schedule_delayed_work(&drvdata->delayed_status_work,
+ msecs_to_jiffies(100));
+
+ /* Refresh firmware versions */
+ INIT_DELAYED_WORK(&drvdata->delayed_firmware_work,
+ corsair_void_firmware_work_handler);
+ schedule_delayed_work(&drvdata->delayed_firmware_work,
+ msecs_to_jiffies(100));
+
+ return 0;
+
+failed_after_sysfs:
+ sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
+ return ret;
+}
+
+static void corsair_void_remove(struct hid_device *hid_dev)
+{
+ struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev);
+
+ hid_hw_stop(hid_dev);
+ cancel_work_sync(&drvdata->battery_remove_work);
+ cancel_work_sync(&drvdata->battery_add_work);
+ if (drvdata->battery)
+ power_supply_unregister(drvdata->battery);
+
+ cancel_delayed_work_sync(&drvdata->delayed_firmware_work);
+ sysfs_remove_group(&hid_dev->dev.kobj, &corsair_void_attr_group);
+}
+
+static int corsair_void_raw_event(struct hid_device *hid_dev,
+ struct hid_report *hid_report,
+ u8 *data, int size)
+{
+ struct corsair_void_drvdata *drvdata = hid_get_drvdata(hid_dev);
+ bool was_connected = drvdata->connected;
+
+ /* Description of packets are documented at the top of this file */
+ if (hid_report->id == CORSAIR_VOID_STATUS_REPORT_ID) {
+ drvdata->mic_up = FIELD_GET(CORSAIR_VOID_MIC_MASK, data[2]);
+ drvdata->connected = (data[3] == CORSAIR_VOID_WIRELESS_CONNECTED) ||
+ drvdata->is_wired;
+
+ corsair_void_process_receiver(drvdata,
+ FIELD_GET(CORSAIR_VOID_CAPACITY_MASK, data[2]),
+ data[3], data[4]);
+ } else if (hid_report->id == CORSAIR_VOID_FIRMWARE_REPORT_ID) {
+ drvdata->fw_receiver_major = data[1];
+ drvdata->fw_receiver_minor = data[2];
+ drvdata->fw_headset_major = data[3];
+ drvdata->fw_headset_minor = data[4];
+ }
+
+ /* Handle wireless headset connect / disconnect */
+ if ((was_connected != drvdata->connected) && !drvdata->is_wired) {
+ if (drvdata->connected)
+ corsair_void_headset_connected(drvdata);
+ else
+ corsair_void_headset_disconnected(drvdata);
+ }
+
+ return 0;
+}
+
+static const struct hid_device_id corsair_void_devices[] = {
+ /* Corsair Void Wireless */
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a0c),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a2b),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x1b23),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x1b25),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x1b27),
+
+ /* Corsair Void USB */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a0f),
+ CORSAIR_VOID_WIRED_DEVICE(0x1b1c),
+ CORSAIR_VOID_WIRED_DEVICE(0x1b29),
+ CORSAIR_VOID_WIRED_DEVICE(0x1b2a),
+
+ /* Corsair Void Surround */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a30),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a31),
+
+ /* Corsair Void Pro Wireless */
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a14),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a16),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a1a),
+
+ /* Corsair Void Pro USB */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a17),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a1d),
+
+ /* Corsair Void Pro Surround */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a18),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a1e),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a1f),
+
+ /* Corsair Void Elite Wireless */
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a51),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a55),
+ CORSAIR_VOID_WIRELESS_DEVICE(0x0a75),
+
+ /* Corsair Void Elite USB */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a52),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a56),
+
+ /* Corsair Void Elite Surround */
+ CORSAIR_VOID_WIRED_DEVICE(0x0a53),
+ CORSAIR_VOID_WIRED_DEVICE(0x0a57),
+
+ {}
+};
+
+MODULE_DEVICE_TABLE(hid, corsair_void_devices);
+
+static struct hid_driver corsair_void_driver = {
+ .name = "hid-corsair-void",
+ .id_table = corsair_void_devices,
+ .probe = corsair_void_probe,
+ .remove = corsair_void_remove,
+ .raw_event = corsair_void_raw_event,
+};
+
+module_hid_driver(corsair_void_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Stuart Hayhurst <stuart.a.hayhurst@gmail.com>");
+MODULE_DESCRIPTION("HID driver for Corsair Void headsets");
--
2.45.2
^ permalink raw reply related
* Re: [PATCH -next v2 10/15] hwmon: (corsair-cpro) Use devm_hid_hw_start_and_open in ccp_probe()
From: Marius Zachmann @ 2024-09-09 18:05 UTC (permalink / raw)
To: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, linux,
wilken.gottwalt, jonas, mezin.alexander, Li Zetao
Cc: lizetao1, linux-input, linux-i2c, linux-hwmon
In-Reply-To: <20240909012313.500341-11-lizetao1@huawei.com>
On 09.09.24 at 03:23:08 MESZ, Li Zetao wrote
> Currently, the corsair-cpro module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the out_hw_close and hid_hw_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Marius Zachmann <mail@mariuszachmann.de>
^ permalink raw reply
* Re: [PATCH -next v2 13/15] hwmon: (nzxt-kraken2) Use devm_hid_hw_start_and_open in kraken2_probe()
From: Jonas Malaco @ 2024-09-09 18:23 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, linux, mail,
wilken.gottwalt, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-14-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:11AM GMT, Li Zetao wrote:
> Currently, the nzxt-kraken2 module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Further optimization, use devm_hwmon_device_register_with_info to replace
> hwmon_device_register_with_info, the remote operation can be completely
> deleted, and the kraken2_priv_data no longer needs to hold hwmon device.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Jonas Malaco <jonas@protocubo.io>
^ permalink raw reply
* Re: [PATCH] dt-binding: touchscreen: fix x-plat-ohm missing type definition
From: Krzysztof Kozlowski @ 2024-09-09 17:47 UTC (permalink / raw)
To: Sayyad Abid
Cc: devicetree, Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Marek Vasut, Michael Welling, linux-input,
linux-kernel
In-Reply-To: <CACVUEB=UBQ=qnEGHodXjYNcMicOW6dGb1Z-V1CPkBV15+OdmwA@mail.gmail.com>
On 09/09/2024 14:48, Sayyad Abid wrote:
> On Mon, Sep 9, 2024 at 1:36 PM Sayyad Abid <sayyad.abid16@gmail.com> wrote:
>>
>> On Mon, Sep 9, 2024 at 1:21 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>>
>>> On 09/09/2024 09:48, Sayyad Abid wrote:
>>>> On Mon, Sep 9, 2024 at 12:02 PM Krzysztof Kozlowski <krzk@kernel.org> wrote:
>>>>>
>>>>> On Sun, Sep 08, 2024 at 08:47:43PM +0530, Sayyad Abid wrote:
>>>>>> This patch fixes the issue with x-plat-ohm missing a type definition.
>>>>>> The patch adds the fix for this issue by adding value of this property
>>>>>
>>>>> You repeated twice the same while it is unclear why this is missing.
>>>> I must have overlooked it, my bad.
>>>
>>> Keep discussion public.
>> I am away form my desktop and trying to reply with Gmail's client,
>> I use mutt otherwise hence the trouble. I hit 'reply' instead of 'reply all'.
>>>
>>>>>
>>>>> Also:
>>>>> Please do not use "This commit/patch/change", but imperative mood. See
>>>>> longer explanation here:
>>>>> https://elixir.bootlin.com/linux/v5.17.1/source/Documentation/process/submitting-patches.rst#L95
>>>> Okay, I'll refer to this article for any further patches. Thank you!
>>>>>
>>>>>
>>>>>> should be a 32-bit unsigned integer.
>>>>>>
>>>>>> Signed-off-by: Sayyad Abid <sayyad.abid16@gmail.com>
>>>>>>
>>>>>> ---
>>>>>> .../devicetree/bindings/input/touchscreen/ti,tsc2005.yaml | 2 ++
>>>>>> 1 file changed, 2 insertions(+)
>>>>>>
>>>>>> diff --git a/Documentation/devicetree/bindings/input/touchscreen/ti,tsc2005.yaml b/Documentation/devicetree/bindings/input/touchscreen/ti,tsc2005.yaml
>>>>>> index 7187c390b2f5..98ff65cf9f9f 100644
>>>>>> --- a/Documentation/devicetree/bindings/input/touchscreen/ti,tsc2005.yaml
>>>>>> +++ b/Documentation/devicetree/bindings/input/touchscreen/ti,tsc2005.yaml
>>>>>> @@ -38,6 +38,8 @@ properties:
>>>>>>
>>>>>> ti,x-plate-ohms:
>>>>>> description: resistance of the touchscreen's X plates in ohm (defaults to 280)
>>>>>
>>>>>> + $ref: /schemas/types.yaml#/definitions/uint32
>>>>>
>>>>> $ref should not be needed, so what is exactly missing? Provide some
>>>>> sort of proof that you are fixing real issue.
>>>> I ran dt_bindings_check on the file which resulted in a warning
>>>> "x-plate-ohm : missing type definition", to resolve this warning I
>>>> looked at the other yaml files in the ti,txc2005.yaml directory
>>>> (/Documentation/devicetree/bindings/input/touchscreen/), Where I found
>>>> out that one of the TI's touchscreen (ti,am3359) binding used $ref
>>>> property for the similar "x-plate-resistance" property.
>>>>
>>>> Adding the $ref resolved the warnings.
>>>
>>> You run some older dtschema.
>> I'll update this and check again.
> So I did a full clean clone of the kernel repo and followed the
> dtschema installation
> as mentioned in the Linux Kernel Documentation.
> Running the dt_binding_check resulted in the same warning.
The dtschema change fixing this ("schemas: property-units: Exclude some
non-conforming properties") is not yet in a released version, so I
suggest do nothing or try the latest dtschema from master. But in any
case this change does not look good. ohms should not have a ref, so even
if this warning is legitimate, the fix should be probably different.
Best regards,
Krzysztof
^ permalink raw reply
* Re: [PATCH -next v2 14/15] hwmon: (nzxt-kraken3) Use devm_hid_hw_start_and_open in kraken3_probe()
From: Aleksa Savic @ 2024-09-09 17:44 UTC (permalink / raw)
To: Li Zetao
Cc: savicaleksa83, linux-input, linux-i2c, linux-hwmon, jikos,
bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, me, jdelvare, linux, mail, wilken.gottwalt,
jonas, mezin.alexander
In-Reply-To: <20240909012313.500341-15-lizetao1@huawei.com>
On 2024-09-09 03:23:12 GMT+02:00, Li Zetao wrote:
> Currently, the nzxt-kraken2 module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
> ---
The commit message references the nzxt-kraken2 module, instead
of nzxt-kraken3 which it touches. Other than that,
Reviewed-by: Aleksa Savic <savicaleksa83@gmail.com>
^ permalink raw reply
* Re: [PATCH -next v2 12/15] hwmon: (gigabyte_waterforce) Use devm_hid_hw_start_and_open in waterforce_probe()
From: Aleksa Savic @ 2024-09-09 17:37 UTC (permalink / raw)
To: Li Zetao
Cc: savicaleksa83, linux-input, linux-i2c, linux-hwmon, bentiss,
michael.zaidman, gupt21, djogorchock, roderick.colenbrander, me,
jdelvare, mail, wilken.gottwalt, jonas, mezin.alexander, jikos,
linux
In-Reply-To: <20240909012313.500341-13-lizetao1@huawei.com>
On 2024-09-09 03:23:10 GMT+02:00, Li Zetao wrote:
> Currently, the waterforce module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Reviewed-by: Aleksa Savic <savicaleksa83@gmail.com>
^ permalink raw reply
* Re: [PATCH -next v2 09/15] hwmon: Use devm_hid_hw_start_and_open in rog_ryujin_probe()
From: Aleksa Savic @ 2024-09-09 17:32 UTC (permalink / raw)
To: Li Zetao, jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, me, jdelvare, linux, mail, wilken.gottwalt,
jonas, mezin.alexander
Cc: savicaleksa83, linux-input, linux-i2c, linux-hwmon
In-Reply-To: <20240909012313.500341-10-lizetao1@huawei.com>
On 2024-09-09 03:23:07 GMT+02:00, Li Zetao wrote:
> Currently, the rog_ryujin module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Further optimization, use devm_hwmon_device_register_with_info to replace
> hwmon_device_register_with_info, the remote operation can be completely
> deleted, and the rog_ryujin_data structure no longer needs to hold
> hwmon device.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Reviewed-by: Aleksa Savic <savicaleksa83@gmail.com>
^ permalink raw reply
* Re: [PATCH -next v2 08/15] hwmon: (aquacomputer_d5next) Use devm_hid_hw_start_and_open in aqc_probe()
From: Aleksa Savic @ 2024-09-09 17:29 UTC (permalink / raw)
To: Li Zetao, jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, me, jdelvare, linux, mail, wilken.gottwalt,
jonas, mezin.alexander
Cc: savicaleksa83, linux-input, linux-i2c, linux-hwmon
In-Reply-To: <20240909012313.500341-9-lizetao1@huawei.com>
On 2024-09-09 03:23:06 GMT+02:00, Li Zetao wrote:
> Currently, the aquacomputer_d5next module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Reviewed-by: Aleksa Savic <savicaleksa83@gmail.com>
^ permalink raw reply
* Re: [PATCH -next v2 15/15] hwmon: (nzxt-smart2) Use devm_hid_hw_start_and_open in nzxt_smart2_hid_probe()
From: Guenter Roeck @ 2024-09-09 17:01 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-16-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:13AM +0800, Li Zetao wrote:
> Currently, the nzxt-smart2 module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the out_hw_close and out_hw_stop
> lables, and directly return the error code when an error occurs.
>
> Further optimization, use devm_hwmon_device_register_with_info to replace
> hwmon_device_register_with_info, the remote operation can be completely
> deleted, and the drvdata no longer needs to hold hwmon device
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
^ permalink raw reply
* Re: [PATCH -next v2 14/15] hwmon: (nzxt-kraken3) Use devm_hid_hw_start_and_open in kraken3_probe()
From: Guenter Roeck @ 2024-09-09 17:01 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-15-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:12AM +0800, Li Zetao wrote:
> Currently, the nzxt-kraken2 module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
^ permalink raw reply
* Re: [PATCH -next v2 13/15] hwmon: (nzxt-kraken2) Use devm_hid_hw_start_and_open in kraken2_probe()
From: Guenter Roeck @ 2024-09-09 17:00 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-14-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:11AM +0800, Li Zetao wrote:
> Currently, the nzxt-kraken2 module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Further optimization, use devm_hwmon_device_register_with_info to replace
> hwmon_device_register_with_info, the remote operation can be completely
> deleted, and the kraken2_priv_data no longer needs to hold hwmon device.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
^ permalink raw reply
* Re: [PATCH -next v2 12/15] hwmon: (gigabyte_waterforce) Use devm_hid_hw_start_and_open in waterforce_probe()
From: Guenter Roeck @ 2024-09-09 17:00 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-13-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:10AM +0800, Li Zetao wrote:
> Currently, the waterforce module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
^ permalink raw reply
* Re: [PATCH -next v2 11/15] hwmon: (corsair-psu) Use devm_hid_hw_start_and_open in corsairpsu_probe()
From: Guenter Roeck @ 2024-09-09 17:00 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-12-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:09AM +0800, Li Zetao wrote:
> Currently, the corsair-psu module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Reviewed-by: Wilken Gottwalt <wilken.gottwalt@posteo.net>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
^ permalink raw reply
* Re: [PATCH -next v2 10/15] hwmon: (corsair-cpro) Use devm_hid_hw_start_and_open in ccp_probe()
From: Guenter Roeck @ 2024-09-09 16:59 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-11-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:08AM +0800, Li Zetao wrote:
> Currently, the corsair-cpro module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the out_hw_close and hid_hw_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> v1 -> v2: Adjust commit information
> v1:
> https://lore.kernel.org/all/20240904123607.3407364-15-lizetao1@huawei.com/
>
> drivers/hwmon/corsair-cpro.c | 24 +++++-------------------
> 1 file changed, 5 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/hwmon/corsair-cpro.c b/drivers/hwmon/corsair-cpro.c
> index e1a7f7aa7f80..7bba30840f32 100644
> --- a/drivers/hwmon/corsair-cpro.c
> +++ b/drivers/hwmon/corsair-cpro.c
> @@ -601,14 +601,10 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
> if (ret)
> return ret;
>
> - ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
> + ret = devm_hid_hw_start_and_open(hdev, HID_CONNECT_HIDRAW);
> if (ret)
> return ret;
>
> - ret = hid_hw_open(hdev);
> - if (ret)
> - goto out_hw_stop;
> -
> ccp->hdev = hdev;
> hid_set_drvdata(hdev, ccp);
>
> @@ -621,28 +617,20 @@ static int ccp_probe(struct hid_device *hdev, const struct hid_device_id *id)
> /* temp and fan connection status only updates when device is powered on */
> ret = get_temp_cnct(ccp);
> if (ret)
> - goto out_hw_close;
> + return ret;
>
> ret = get_fan_cnct(ccp);
> if (ret)
> - goto out_hw_close;
> + return ret;
>
> ccp_debugfs_init(ccp);
>
> ccp->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "corsaircpro",
> ccp, &ccp_chip_info, NULL);
> - if (IS_ERR(ccp->hwmon_dev)) {
> - ret = PTR_ERR(ccp->hwmon_dev);
> - goto out_hw_close;
> - }
> + if (IS_ERR(ccp->hwmon_dev))
> + return PTR_ERR(ccp->hwmon_dev);
>
> return 0;
> -
> -out_hw_close:
> - hid_hw_close(hdev);
> -out_hw_stop:
> - hid_hw_stop(hdev);
> - return ret;
> }
>
> static void ccp_remove(struct hid_device *hdev)
> @@ -651,8 +639,6 @@ static void ccp_remove(struct hid_device *hdev)
>
> debugfs_remove_recursive(ccp->debugfs);
> hwmon_device_unregister(ccp->hwmon_dev);
> - hid_hw_close(hdev);
> - hid_hw_stop(hdev);
> }
>
> static const struct hid_device_id ccp_devices[] = {
> --
> 2.34.1
>
>
^ permalink raw reply
* Re: [PATCH -next v2 09/15] hwmon: Use devm_hid_hw_start_and_open in rog_ryujin_probe()
From: Guenter Roeck @ 2024-09-09 16:59 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-10-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:07AM +0800, Li Zetao wrote:
> Currently, the rog_ryujin module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Further optimization, use devm_hwmon_device_register_with_info to replace
> hwmon_device_register_with_info, the remote operation can be completely
> deleted, and the rog_ryujin_data structure no longer needs to hold
> hwmon device.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Subject should include 'asus_rog_ryujin'. Other than that,
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> v1 -> v2:
> 1) Further optimize using devm_hwmon_device_register_with_info
> and remove the .remove operation
> 2) Adjust commit information
> v1:
> https://lore.kernel.org/all/20240904123607.3407364-14-lizetao1@huawei.com/
>
> drivers/hwmon/asus_rog_ryujin.c | 47 +++++----------------------------
> 1 file changed, 7 insertions(+), 40 deletions(-)
>
> diff --git a/drivers/hwmon/asus_rog_ryujin.c b/drivers/hwmon/asus_rog_ryujin.c
> index f8b20346a995..ef0d9b72a824 100644
> --- a/drivers/hwmon/asus_rog_ryujin.c
> +++ b/drivers/hwmon/asus_rog_ryujin.c
> @@ -80,7 +80,6 @@ static const char *const rog_ryujin_speed_label[] = {
>
> struct rog_ryujin_data {
> struct hid_device *hdev;
> - struct device *hwmon_dev;
> /* For locking access to buffer */
> struct mutex buffer_lock;
> /* For queueing multiple readers */
> @@ -497,6 +496,7 @@ static int rog_ryujin_raw_event(struct hid_device *hdev, struct hid_report *repo
> static int rog_ryujin_probe(struct hid_device *hdev, const struct hid_device_id *id)
> {
> struct rog_ryujin_data *priv;
> + struct device *hwmon_dev;
> int ret;
>
> priv = devm_kzalloc(&hdev->dev, sizeof(*priv), GFP_KERNEL);
> @@ -520,23 +520,13 @@ static int rog_ryujin_probe(struct hid_device *hdev, const struct hid_device_id
> }
>
> /* Enable hidraw so existing user-space tools can continue to work */
> - ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
> - if (ret) {
> - hid_err(hdev, "hid hw start failed with %d\n", ret);
> + ret = devm_hid_hw_start_and_open(hdev, HID_CONNECT_HIDRAW);
> + if (ret)
> return ret;
> - }
> -
> - ret = hid_hw_open(hdev);
> - if (ret) {
> - hid_err(hdev, "hid hw open failed with %d\n", ret);
> - goto fail_and_stop;
> - }
>
> priv->buffer = devm_kzalloc(&hdev->dev, MAX_REPORT_LENGTH, GFP_KERNEL);
> - if (!priv->buffer) {
> - ret = -ENOMEM;
> - goto fail_and_close;
> - }
> + if (!priv->buffer)
> + return -ENOMEM;
>
> mutex_init(&priv->status_report_request_mutex);
> mutex_init(&priv->buffer_lock);
> @@ -548,31 +538,9 @@ static int rog_ryujin_probe(struct hid_device *hdev, const struct hid_device_id
> init_completion(&priv->cooler_duty_set);
> init_completion(&priv->controller_duty_set);
>
> - priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, "rog_ryujin",
> + hwmon_dev = devm_hwmon_device_register_with_info(&hdev->dev, "rog_ryujin",
> priv, &rog_ryujin_chip_info, NULL);
> - if (IS_ERR(priv->hwmon_dev)) {
> - ret = PTR_ERR(priv->hwmon_dev);
> - hid_err(hdev, "hwmon registration failed with %d\n", ret);
> - goto fail_and_close;
> - }
> -
> - return 0;
> -
> -fail_and_close:
> - hid_hw_close(hdev);
> -fail_and_stop:
> - hid_hw_stop(hdev);
> - return ret;
> -}
> -
> -static void rog_ryujin_remove(struct hid_device *hdev)
> -{
> - struct rog_ryujin_data *priv = hid_get_drvdata(hdev);
> -
> - hwmon_device_unregister(priv->hwmon_dev);
> -
> - hid_hw_close(hdev);
> - hid_hw_stop(hdev);
> + return PTR_ERR_OR_ZERO(hwmon_dev);
> }
>
> static const struct hid_device_id rog_ryujin_table[] = {
> @@ -586,7 +554,6 @@ static struct hid_driver rog_ryujin_driver = {
> .name = "rog_ryujin",
> .id_table = rog_ryujin_table,
> .probe = rog_ryujin_probe,
> - .remove = rog_ryujin_remove,
> .raw_event = rog_ryujin_raw_event,
> };
>
> --
> 2.34.1
>
>
^ permalink raw reply
* Re: [PATCH -next v2 08/15] hwmon: (aquacomputer_d5next) Use devm_hid_hw_start_and_open in aqc_probe()
From: Guenter Roeck @ 2024-09-09 16:57 UTC (permalink / raw)
To: Li Zetao
Cc: jikos, bentiss, michael.zaidman, gupt21, djogorchock,
roderick.colenbrander, savicaleksa83, me, jdelvare, mail,
wilken.gottwalt, jonas, mezin.alexander, linux-input, linux-i2c,
linux-hwmon
In-Reply-To: <20240909012313.500341-9-lizetao1@huawei.com>
On Mon, Sep 09, 2024 at 09:23:06AM +0800, Li Zetao wrote:
> Currently, the aquacomputer_d5next module needs to maintain hid resources
> by itself. Use devm_hid_hw_start_and_open helper to ensure that hid
> resources are consistent with the device life cycle, and release
> hid resources before device is released. At the same time, it can avoid
> the goto-release encoding, drop the fail_and_close and fail_and_stop
> lables, and directly return the error code when an error occurs.
>
> Signed-off-by: Li Zetao <lizetao1@huawei.com>
Acked-by: Guenter Roeck <linux@roeck-us.net>
> ---
> v1 -> v2: Adjust commit information
> v1:
> https://lore.kernel.org/all/20240904123607.3407364-13-lizetao1@huawei.com/
>
> drivers/hwmon/aquacomputer_d5next.c | 39 +++++++----------------------
> 1 file changed, 9 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/hwmon/aquacomputer_d5next.c b/drivers/hwmon/aquacomputer_d5next.c
> index 8e55cd2f46f5..9b66ff0fe6e1 100644
> --- a/drivers/hwmon/aquacomputer_d5next.c
> +++ b/drivers/hwmon/aquacomputer_d5next.c
> @@ -1556,14 +1556,10 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
> if (ret)
> return ret;
>
> - ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW);
> + ret = devm_hid_hw_start_and_open(hdev, HID_CONNECT_HIDRAW);
> if (ret)
> return ret;
>
> - ret = hid_hw_open(hdev);
> - if (ret)
> - goto fail_and_stop;
> -
> switch (hdev->product) {
> case USB_PRODUCT_ID_AQUAERO:
> /*
> @@ -1577,10 +1573,8 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
> * they present. The two other devices have the type of the second element in
> * their respective collections set to 1, while the real device has it set to 0.
> */
> - if (hdev->collection[1].type != 0) {
> - ret = -ENODEV;
> - goto fail_and_close;
> - }
> + if (hdev->collection[1].type != 0)
> + return -ENODEV;
>
> priv->kind = aquaero;
>
> @@ -1740,10 +1734,8 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
> * Choose the right Leakshield device, because
> * the other one acts as a keyboard
> */
> - if (hdev->type != 2) {
> - ret = -ENODEV;
> - goto fail_and_close;
> - }
> + if (hdev->type != 2)
> + return -ENODEV;
>
> priv->kind = leakshield;
>
> @@ -1865,30 +1857,20 @@ static int aqc_probe(struct hid_device *hdev, const struct hid_device_id *id)
> priv->name = aqc_device_names[priv->kind];
>
> priv->buffer = devm_kzalloc(&hdev->dev, priv->buffer_size, GFP_KERNEL);
> - if (!priv->buffer) {
> - ret = -ENOMEM;
> - goto fail_and_close;
> - }
> + if (!priv->buffer)
> + return -ENOMEM;
>
> mutex_init(&priv->mutex);
>
> priv->hwmon_dev = hwmon_device_register_with_info(&hdev->dev, priv->name, priv,
> &aqc_chip_info, NULL);
>
> - if (IS_ERR(priv->hwmon_dev)) {
> - ret = PTR_ERR(priv->hwmon_dev);
> - goto fail_and_close;
> - }
> + if (IS_ERR(priv->hwmon_dev))
> + return PTR_ERR(priv->hwmon_dev);
>
> aqc_debugfs_init(priv);
>
> return 0;
> -
> -fail_and_close:
> - hid_hw_close(hdev);
> -fail_and_stop:
> - hid_hw_stop(hdev);
> - return ret;
> }
>
> static void aqc_remove(struct hid_device *hdev)
> @@ -1897,9 +1879,6 @@ static void aqc_remove(struct hid_device *hdev)
>
> debugfs_remove_recursive(priv->debugfs);
> hwmon_device_unregister(priv->hwmon_dev);
> -
> - hid_hw_close(hdev);
> - hid_hw_stop(hdev);
> }
>
> static const struct hid_device_id aqc_table[] = {
> --
> 2.34.1
>
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox