Linux Input/HID development
 help / color / mirror / Atom feed
* [PATCH v2 06/17] HID: pidff: Better quirk assigment when searching for fields
From: Tomasz Pakuła @ 2025-08-13 20:09 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Assign quirks directly when they're discovered. Way easier to understand
without relying on return values.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 59 +++++++++++-----------------------
 1 file changed, 18 insertions(+), 41 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index cff79e76c211..c88442a087f1 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -943,7 +943,8 @@ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
  * Find fields from a report and fill a pidff_usage
  */
 static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
-			     struct hid_report *report, int count, int strict)
+			     struct hid_report *report, int count, int strict,
+			     u32 *quirks)
 {
 	if (!report) {
 		pr_debug("%s, null report\n", __func__);
@@ -951,7 +952,6 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
 	}
 
 	int i, j, k, found;
-	int return_value = 0;
 
 	for (k = 0; k < count; k++) {
 		found = 0;
@@ -979,17 +979,17 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
 		if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) {
 			pr_debug("Delay field not found, but that's OK\n");
 			pr_debug("Setting MISSING_DELAY quirk\n");
-			return_value |= HID_PIDFF_QUIRK_MISSING_DELAY;
+			*quirks |= HID_PIDFF_QUIRK_MISSING_DELAY;
 		} else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) {
 			pr_debug("PBO field not found, but that's OK\n");
 			pr_debug("Setting MISSING_PBO quirk\n");
-			return_value |= HID_PIDFF_QUIRK_MISSING_PBO;
+			*quirks |= HID_PIDFF_QUIRK_MISSING_PBO;
 		} else if (!found && strict) {
 			pr_debug("failed to locate %d\n", k);
 			return -1;
 		}
 	}
-	return return_value;
+	return 0;
 }
 
 /*
@@ -1258,26 +1258,17 @@ static int pidff_find_effects(struct pidff_device *pidff,
 #define PIDFF_FIND_FIELDS(name, report, strict) \
 	pidff_find_fields(pidff->name, pidff_ ## name, \
 		pidff->reports[report], \
-		ARRAY_SIZE(pidff_ ## name), strict)
+		ARRAY_SIZE(pidff_ ## name), strict, &pidff->quirks)
 
 /*
  * Fill and check the pidff_usages
  */
 static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
 {
-	int status = 0;
-
-	/* Save info about the device not having the DELAY ffb field. */
-	status = PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1);
-	if (status == -1) {
+	if (PIDFF_FIND_FIELDS(set_effect, PID_SET_EFFECT, 1)) {
 		hid_err(pidff->hid, "unknown set_effect report layout\n");
 		return -ENODEV;
 	}
-	pidff->quirks |= status;
-
-	if (status & HID_PIDFF_QUIRK_MISSING_DELAY)
-		hid_dbg(pidff->hid, "Adding MISSING_DELAY quirk\n");
-
 
 	PIDFF_FIND_FIELDS(block_load, PID_BLOCK_LOAD, 0);
 	if (!pidff->block_load[PID_EFFECT_BLOCK_INDEX].value) {
@@ -1311,39 +1302,25 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev)
 				 "has periodic effect but no envelope\n");
 	}
 
-	if (test_bit(FF_CONSTANT, dev->ffbit) &&
-	    PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1)) {
+	if (PIDFF_FIND_FIELDS(set_constant, PID_SET_CONSTANT, 1) &&
+	    test_and_clear_bit(FF_CONSTANT, dev->ffbit))
 		hid_warn(pidff->hid, "unknown constant effect layout\n");
-		clear_bit(FF_CONSTANT, dev->ffbit);
-	}
 
-	if (test_bit(FF_RAMP, dev->ffbit) &&
-	    PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1)) {
+	if (PIDFF_FIND_FIELDS(set_ramp, PID_SET_RAMP, 1) &&
+	    test_and_clear_bit(FF_RAMP, dev->ffbit))
 		hid_warn(pidff->hid, "unknown ramp effect layout\n");
-		clear_bit(FF_RAMP, dev->ffbit);
-	}
-
-	if (test_bit(FF_SPRING, dev->ffbit) ||
-	    test_bit(FF_DAMPER, dev->ffbit) ||
-	    test_bit(FF_FRICTION, dev->ffbit) ||
-	    test_bit(FF_INERTIA, dev->ffbit)) {
-		status = PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1);
 
-		if (status < 0) {
+	if (PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) {
+		if (test_and_clear_bit(FF_SPRING, dev->ffbit)   ||
+		    test_and_clear_bit(FF_DAMPER, dev->ffbit)   ||
+		    test_and_clear_bit(FF_FRICTION, dev->ffbit) ||
+		    test_and_clear_bit(FF_INERTIA, dev->ffbit))
 			hid_warn(pidff->hid, "unknown condition effect layout\n");
-			clear_bit(FF_SPRING, dev->ffbit);
-			clear_bit(FF_DAMPER, dev->ffbit);
-			clear_bit(FF_FRICTION, dev->ffbit);
-			clear_bit(FF_INERTIA, dev->ffbit);
-		}
-		pidff->quirks |= status;
 	}
 
-	if (test_bit(FF_PERIODIC, dev->ffbit) &&
-	    PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1)) {
+	if (PIDFF_FIND_FIELDS(set_periodic, PID_SET_PERIODIC, 1) &&
+	    test_and_clear_bit(FF_PERIODIC, dev->ffbit))
 		hid_warn(pidff->hid, "unknown periodic effect layout\n");
-		clear_bit(FF_PERIODIC, dev->ffbit);
-	}
 
 	PIDFF_FIND_FIELDS(pool, PID_POOL, 0);
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 07/17] HID: pidff: Simplify HID field/usage searching logic
From: Tomasz Pakuła @ 2025-08-13 20:09 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Some deduplication and splitting into separate functions. This is now
way easier to comprehend and parse mentally.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 105 +++++++++++++++++++--------------
 1 file changed, 62 insertions(+), 43 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index c88442a087f1..2e8eac944be0 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -939,6 +939,43 @@ static void pidff_set_autocenter(struct input_dev *dev, u16 magnitude)
 	pidff_autocenter(dev->ff->private, magnitude);
 }
 
+/*
+ * Find specific usage in a given hid_field
+ */
+static int pidff_find_usage(struct hid_field *fld, unsigned int usage_code)
+{
+	for (int i = 0; i < fld->maxusage; i++) {
+		if (fld->usage[i].hid == usage_code)
+			return i;
+	}
+	return -1;
+}
+
+/*
+ * Find hid_field with a specific usage. Return the usage index as well
+ */
+static int pidff_find_field_with_usage(int *usage_index,
+				       struct hid_report *report,
+				       unsigned int usage_code)
+{
+	for (int i = 0; i < report->maxfield; i++) {
+		struct hid_field *fld = report->field[i];
+
+		if (fld->maxusage != fld->report_count) {
+			pr_debug("maxusage and report_count do not match, skipping\n");
+			continue;
+		}
+
+		int index = pidff_find_usage(fld, usage_code);
+
+		if (index >= 0) {
+			*usage_index = index;
+			return i;
+		}
+	}
+	return -1;
+}
+
 /*
  * Find fields from a report and fill a pidff_usage
  */
@@ -946,46 +983,38 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table,
 			     struct hid_report *report, int count, int strict,
 			     u32 *quirks)
 {
+	const u8 block_offset = pidff_set_condition[PID_PARAM_BLOCK_OFFSET];
+	const u8 delay = pidff_set_effect[PID_START_DELAY];
+
 	if (!report) {
 		pr_debug("%s, null report\n", __func__);
 		return -1;
 	}
 
-	int i, j, k, found;
+	for (int i = 0; i < count; i++) {
+		int index;
+		int found = pidff_find_field_with_usage(&index, report,
+							HID_UP_PID | table[i]);
 
-	for (k = 0; k < count; k++) {
-		found = 0;
-		for (i = 0; i < report->maxfield; i++) {
-			if (report->field[i]->maxusage !=
-			    report->field[i]->report_count) {
-				pr_debug("maxusage and report_count do not match, skipping\n");
-				continue;
-			}
-			for (j = 0; j < report->field[i]->maxusage; j++) {
-				if (report->field[i]->usage[j].hid ==
-				    (HID_UP_PID | table[k])) {
-					pr_debug("found %d at %d->%d\n",
-						 k, i, j);
-					usage[k].field = report->field[i];
-					usage[k].value =
-						&report->field[i]->value[j];
-					found = 1;
-					break;
-				}
-			}
-			if (found)
-				break;
+		if (found >= 0) {
+			pr_debug("found %d at %d->%d\n", i, found, index);
+			usage[i].field = report->field[found];
+			usage[i].value = &report->field[found]->value[index];
+			continue;
 		}
-		if (!found && table[k] == pidff_set_effect[PID_START_DELAY]) {
+
+		if (table[i] == delay) {
 			pr_debug("Delay field not found, but that's OK\n");
 			pr_debug("Setting MISSING_DELAY quirk\n");
 			*quirks |= HID_PIDFF_QUIRK_MISSING_DELAY;
-		} else if (!found && table[k] == pidff_set_condition[PID_PARAM_BLOCK_OFFSET]) {
+
+		} else if (table[i] == block_offset) {
 			pr_debug("PBO field not found, but that's OK\n");
 			pr_debug("Setting MISSING_PBO quirk\n");
 			*quirks |= HID_PIDFF_QUIRK_MISSING_PBO;
-		} else if (!found && strict) {
-			pr_debug("failed to locate %d\n", k);
+
+		} else if (strict) {
+			pr_debug("failed to locate %d\n", i);
 			return -1;
 		}
 	}
@@ -1054,9 +1083,7 @@ static void pidff_find_reports(struct hid_device *hid, int report_type,
  */
 static int pidff_reports_ok(struct pidff_device *pidff)
 {
-	int i;
-
-	for (i = 0; i < PID_REQUIRED_REPORTS; i++) {
+	for (int i = 0; i < PID_REQUIRED_REPORTS; i++) {
 		if (!pidff->reports[i]) {
 			hid_dbg(pidff->hid, "%d missing\n", i);
 			return 0;
@@ -1077,9 +1104,7 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
 		return NULL;
 	}
 
-	int i;
-
-	for (i = 0; i < report->maxfield; i++) {
+	for (int i = 0; i < report->maxfield; i++) {
 		if (report->field[i]->logical == (HID_UP_PID | usage) &&
 		    report->field[i]->report_count > 0) {
 			if (!enforce_min ||
@@ -1099,18 +1124,12 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
 static int pidff_find_special_keys(int *keys, struct hid_field *fld,
 				   const u8 *usagetable, int count)
 {
-
-	int i, j;
 	int found = 0;
 
-	for (i = 0; i < count; i++) {
-		for (j = 0; j < fld->maxusage; j++) {
-			if (fld->usage[j].hid == (HID_UP_PID | usagetable[i])) {
-				keys[i] = j + 1;
-				found++;
-				break;
-			}
-		}
+	for (int i = 0; i < count; i++) {
+		keys[i] = pidff_find_usage(fld, HID_UP_PID | usagetable[i]) + 1;
+		if (keys[i])
+			found++;
 	}
 	return found;
 }
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 08/17] HID: pidff: Add support for AXES_ENABLE field
From: Tomasz Pakuła @ 2025-08-13 20:09 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

AXES_ENABLE can be used in place of DIRECTION_ENABLE to indicate, which
FFB-enabled axes will be affected by a given effect. EFFECT_DIRECTION
enables all and uses the first direction only while AXES_ENABLE is a
bitmask and bit indexes are the same as the defined GD usages in the
EFFECT_DIRECTION array. Each axis can have it's own direction in this
case.

Search for AXES_ENABLE, set AXES_ENABLE for all axes if DIRECTION_ENABLE
is not used.

Search for specific axes in the direction array. Save their indexes. This
let us know what axes are actually available on the device and which bit
in the AXES_ENABLE field corresponds to which axis.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 91 ++++++++++++++++++++++++++++++++--
 1 file changed, 87 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 2e8eac944be0..0f49d2836e9e 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -51,6 +51,7 @@ static const u8 pidff_reports[] = {
 
 /* PID special fields */
 #define PID_EFFECT_TYPE			0x25
+#define PID_AXES_ENABLE			0x55
 #define PID_DIRECTION			0x57
 #define PID_EFFECT_OPERATION_ARRAY	0x78
 #define PID_BLOCK_LOAD_STATUS		0x8b
@@ -150,6 +151,31 @@ static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
 /* Polar direction 90 degrees (East) */
 #define PIDFF_FIXED_WHEEL_DIRECTION	0x4000
 
+/* AXES_ENABLE and DIRECTION axes */
+enum pid_axes {
+	PID_AXIS_X,
+	PID_AXIS_Y,
+	PID_AXIS_Z,
+	PID_AXIS_RX,
+	PID_AXIS_RY,
+	PID_AXIS_RZ,
+	PID_AXIS_SLIDER,
+	PID_AXIS_DIAL,
+	PID_AXIS_WHEEL,
+	PID_AXES_COUNT,
+};
+static const u8 pidff_direction_axis[] = {
+	HID_USAGE & HID_GD_X,
+	HID_USAGE & HID_GD_Y,
+	HID_USAGE & HID_GD_Z,
+	HID_USAGE & HID_GD_RX,
+	HID_USAGE & HID_GD_RY,
+	HID_USAGE & HID_GD_RZ,
+	HID_USAGE & HID_GD_SLIDER,
+	HID_USAGE & HID_GD_DIAL,
+	HID_USAGE & HID_GD_WHEEL,
+};
+
 struct pidff_usage {
 	struct hid_field *field;
 	s32 *value;
@@ -184,6 +210,7 @@ struct pidff_device {
 	/* Special fields in set_effect */
 	struct hid_field *set_effect_type;
 	struct hid_field *effect_direction;
+	struct hid_field *axes_enable;
 
 	/* Special field in device_control */
 	struct hid_field *device_control;
@@ -198,11 +225,13 @@ struct pidff_device {
 	int type_id[ARRAY_SIZE(pidff_effect_types)];
 	int status_id[ARRAY_SIZE(pidff_block_load_status)];
 	int operation_id[ARRAY_SIZE(pidff_effect_operation_status)];
+	int direction_axis_id[ARRAY_SIZE(pidff_direction_axis)];
 
 	int pid_id[PID_EFFECTS_MAX];
 
 	u32 quirks;
 	u8 effect_count;
+	u8 axis_count;
 };
 
 static int pidff_is_effect_conditional(struct ff_effect *effect)
@@ -306,14 +335,37 @@ static void pidff_set_effect_direction(struct pidff_device *pidff,
 				       struct ff_effect *effect)
 {
 	u16 direction = effect->direction;
+	int direction_enable = 1;
 
 	/* Use fixed direction if needed */
 	if (pidff->quirks & HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION &&
 	    pidff_is_effect_conditional(effect))
 		direction = PIDFF_FIXED_WHEEL_DIRECTION;
 
+	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = direction_enable;
 	pidff->effect_direction->value[0] =
 		pidff_rescale(direction, U16_MAX, pidff->effect_direction);
+
+	if (direction_enable)
+		return;
+
+	/*
+	 * For use with improved FFB API
+	 * We want to read the selected axes and their direction from the effect
+	 * struct and only enable those. For now, enable all axes.
+	 *
+	 */
+	for (int i = 0; i < PID_AXES_COUNT; i++) {
+		/* HID index starts with 1 */
+		int index = pidff->direction_axis_id[i] - 1;
+
+		if (index < 0)
+			continue;
+
+		pidff->axes_enable->value[index] = 1;
+		pidff->effect_direction->value[index] = pidff_rescale(
+			direction, U16_MAX, pidff->effect_direction);
+	}
 }
 
 /*
@@ -411,7 +463,6 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
 			effect->trigger.interval);
 	pidff->set_effect[PID_GAIN].value[0] =
 		pidff->set_effect[PID_GAIN].field->logical_maximum;
-	pidff->set_effect[PID_DIRECTION_ENABLE].value[0] = 1;
 
 	pidff_set_effect_direction(pidff, effect);
 
@@ -1122,12 +1173,13 @@ static struct hid_field *pidff_find_special_field(struct hid_report *report,
  * Fill a pidff->*_id struct table
  */
 static int pidff_find_special_keys(int *keys, struct hid_field *fld,
-				   const u8 *usagetable, int count)
+				   const u8 *usagetable, int count,
+				   unsigned int usage_page)
 {
 	int found = 0;
 
 	for (int i = 0; i < count; i++) {
-		keys[i] = pidff_find_usage(fld, HID_UP_PID | usagetable[i]) + 1;
+		keys[i] = pidff_find_usage(fld, usage_page | usagetable[i]) + 1;
 		if (keys[i])
 			found++;
 	}
@@ -1136,7 +1188,11 @@ static int pidff_find_special_keys(int *keys, struct hid_field *fld,
 
 #define PIDFF_FIND_SPECIAL_KEYS(keys, field, name) \
 	pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
-		ARRAY_SIZE(pidff_ ## name))
+		ARRAY_SIZE(pidff_ ## name), HID_UP_PID)
+
+#define PIDFF_FIND_GENERAL_DESKTOP(keys, field, name) \
+	pidff_find_special_keys(pidff->keys, pidff->field, pidff_ ## name, \
+		ARRAY_SIZE(pidff_ ## name), HID_UP_GENDESK)
 
 /*
  * Find and check the special fields
@@ -1151,6 +1207,9 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
 	pidff->set_effect_type =
 		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
 					 PID_EFFECT_TYPE, 1);
+	pidff->axes_enable =
+		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
+					 PID_AXES_ENABLE, 0);
 	pidff->effect_direction =
 		pidff_find_special_field(pidff->reports[PID_SET_EFFECT],
 					 PID_DIRECTION, 0);
@@ -1216,6 +1275,30 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
 		return -1;
 	}
 
+	if (!pidff->axes_enable)
+		hid_info(pidff->hid, "axes enable field not found!\n");
+	else
+		hid_dbg(pidff->hid, "axes enable report count: %u\n",
+			pidff->axes_enable->report_count);
+
+	uint found = PIDFF_FIND_GENERAL_DESKTOP(direction_axis_id, axes_enable,
+						direction_axis);
+
+	pidff->axis_count = found;
+	hid_dbg(pidff->hid, "found direction axes: %u", found);
+
+	for (int i = 0; i < sizeof(pidff_direction_axis); i++) {
+		if (!pidff->direction_axis_id[i])
+			continue;
+
+		hid_dbg(pidff->hid, "axis %d, usage: 0x%04x, index: %d", i + 1,
+			pidff_direction_axis[i], pidff->direction_axis_id[i]);
+	}
+
+	if (pidff->axes_enable && found != pidff->axes_enable->report_count)
+		hid_warn(pidff->hid, "axes_enable: %u != direction axes: %u",
+			 pidff->axes_enable->report_count, found);
+
 	return 0;
 }
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 09/17] HID: pidff: Update debug messages
From: Tomasz Pakuła @ 2025-08-13 20:09 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>

Better indicate what operation is requested on a given effect (play or
stop). Previously, we only had the info about requesting playback but
this could be misleading when the looop count is 0.

Add debug print that shows what device control command was actually sent
to the device. Print out its hex hid usage.

Make field_index const to make sure it won't be changed by mistake later.
---
 drivers/hid/usbhid/hid-pidff.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 0f49d2836e9e..689419b20bf0 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -623,8 +623,7 @@ static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain)
  */
 static void pidff_set_device_control(struct pidff_device *pidff, int field)
 {
-	int i, index;
-	int field_index = pidff->control_id[field];
+	const int field_index = pidff->control_id[field];
 
 	if (field_index < 1)
 		return;
@@ -634,8 +633,9 @@ static void pidff_set_device_control(struct pidff_device *pidff, int field)
 		hid_dbg(pidff->hid, "DEVICE_CONTROL is a bitmask\n");
 
 		/* Clear current bitmask */
-		for (i = 0; i < ARRAY_SIZE(pidff_device_control); i++) {
-			index = pidff->control_id[i];
+		for (int i = 0; i < ARRAY_SIZE(pidff_device_control); i++) {
+			int index = pidff->control_id[i];
+
 			if (index < 1)
 				continue;
 
@@ -650,6 +650,8 @@ static void pidff_set_device_control(struct pidff_device *pidff, int field)
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_CONTROL], HID_REQ_SET_REPORT);
 	hid_hw_wait(pidff->hid);
+	hid_dbg(pidff->hid, "Device control command 0x%02x sent",
+		pidff_device_control[field]);
 }
 
 /*
@@ -751,6 +753,9 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
 {
 	pidff->effect_operation[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
 
+	hid_dbg(pidff->hid, "%s PID effect %d", n == 0 ? "stopping" : "playing",
+		pid_id);
+
 	if (n == 0) {
 		pidff->effect_operation_status->value[0] =
 			pidff->operation_id[PID_EFFECT_STOP];
@@ -772,6 +777,8 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
 {
 	struct pidff_device *pidff = dev->ff->private;
 
+	hid_dbg(pidff->hid, "requesting %s on FF effect %d",
+		value == 0 ? "stop" : "playback", effect_id);
 	pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
 	return 0;
 }
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 10/17] HID: pidff: Rework pidff_upload_effect
From: Tomasz Pakuła @ 2025-08-13 20:09 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

One of the more complicated functions. Expunge some of the logic to
separate functions (FF -> PID id conversion)

Add a macro for envelope check to make it more readable in the upload
function.

All this made it possible to to expunge common code from the big switch
statement and reduce the overall function size considerably. Now it can
fit on one screen.

Move the effect_cout logic from report functions to upload/erase
functions.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 243 ++++++++++++++++-----------------
 1 file changed, 115 insertions(+), 128 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 689419b20bf0..32d42792c95a 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -142,7 +142,7 @@ static const u8 pidff_effect_types[] = {
 #define PID_BLOCK_LOAD_SUCCESS	0
 #define PID_BLOCK_LOAD_FULL	1
 #define PID_BLOCK_LOAD_ERROR	2
-static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e};
+static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e };
 
 #define PID_EFFECT_START	0
 #define PID_EFFECT_STOP		1
@@ -242,6 +242,62 @@ static int pidff_is_effect_conditional(struct ff_effect *effect)
 	       effect->type == FF_FRICTION;
 }
 
+/*
+ * Get PID effect index from FF effect type.
+ * Return 0 if invalid.
+ */
+static int pidff_effect_ff_to_pid(struct ff_effect *effect)
+{
+	switch (effect->type) {
+	case FF_CONSTANT:
+		return PID_CONSTANT;
+	case FF_RAMP:
+		return PID_RAMP;
+	case FF_SPRING:
+		return PID_SPRING;
+	case FF_DAMPER:
+		return PID_DAMPER;
+	case FF_INERTIA:
+		return PID_INERTIA;
+	case FF_FRICTION:
+		return PID_FRICTION;
+	case FF_PERIODIC:
+		switch (effect->u.periodic.waveform) {
+		case FF_SQUARE:
+			return PID_SQUARE;
+		case FF_TRIANGLE:
+			return PID_TRIANGLE;
+		case FF_SINE:
+			return PID_SINE;
+		case FF_SAW_UP:
+			return PID_SAW_UP;
+		case FF_SAW_DOWN:
+			return PID_SAW_DOWN;
+		}
+	}
+	pr_err("invalid effect type\n");
+	return -EINVAL;
+}
+
+/*
+ * Get effect id in the device descriptor.
+ * Return 0 if invalid.
+ */
+static int pidff_get_effect_type_id(struct pidff_device *pidff,
+				    struct ff_effect *effect)
+{
+	int id = pidff_effect_ff_to_pid(effect);
+
+	if (id < 0)
+		return 0;
+
+	if (effect->type == FF_PERIODIC &&
+	    pidff->quirks & HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY)
+		id = PID_SINE;
+
+	return pidff->type_id[id];
+}
+
 /*
  * Clamp value for a given field
  */
@@ -387,12 +443,12 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
 			pidff->set_envelope[PID_FADE_LEVEL].field);
 
 	pidff_set_time(&pidff->set_envelope[PID_ATTACK_TIME],
-			envelope->attack_length);
+		       envelope->attack_length);
 	pidff_set_time(&pidff->set_envelope[PID_FADE_TIME],
-			envelope->fade_length);
+		       envelope->fade_length);
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -401,7 +457,7 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
 static int pidff_needs_set_envelope(struct ff_envelope *envelope,
 				    struct ff_envelope *old)
 {
-	bool needs_new_envelope;
+	int needs_new_envelope;
 
 	needs_new_envelope = envelope->attack_level  != 0 ||
 			     envelope->fade_level    != 0 ||
@@ -409,8 +465,7 @@ static int pidff_needs_set_envelope(struct ff_envelope *envelope,
 			     envelope->fade_length   != 0;
 
 	if (!needs_new_envelope)
-		return false;
-
+		return 0;
 	if (!old)
 		return needs_new_envelope;
 
@@ -423,8 +478,8 @@ static int pidff_needs_set_envelope(struct ff_envelope *envelope,
 /*
  * Send constant force report to the device
  */
-static void pidff_set_constant_force_report(struct pidff_device *pidff,
-					    struct ff_effect *effect)
+static void pidff_set_constant_report(struct pidff_device *pidff,
+				      struct ff_effect *effect)
 {
 	pidff->set_constant[PID_EFFECT_BLOCK_INDEX].value[0] =
 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
@@ -432,7 +487,7 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
 			 effect->u.constant.level);
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONSTANT],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -583,8 +638,8 @@ static int pidff_needs_set_condition(struct ff_effect *effect,
 /*
  * Send ramp force report to the device
  */
-static void pidff_set_ramp_force_report(struct pidff_device *pidff,
-					struct ff_effect *effect)
+static void pidff_set_ramp_report(struct pidff_device *pidff,
+				  struct ff_effect *effect)
 {
 	pidff->set_ramp[PID_EFFECT_BLOCK_INDEX].value[0] =
 		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
@@ -593,7 +648,7 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
 	pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
 			 effect->u.ramp.end_level);
 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_RAMP],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -703,9 +758,6 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
 {
 	int j;
 
-	if (!pidff->effect_count)
-		pidff_reset(pidff);
-
 	pidff->create_new_effect_type->value[0] = efnum;
 	hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
 			HID_REQ_SET_REPORT);
@@ -725,8 +777,6 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
 			hid_dbg(pidff->hid, "device reported free memory: %d bytes\n",
 				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value ?
 				 pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);
-
-			pidff->effect_count++;
 			return 0;
 		}
 		if (pidff->block_load_status->value[0] ==
@@ -767,7 +817,7 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
 	}
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -791,10 +841,7 @@ static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
 {
 	pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
 	hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_FREE],
-			HID_REQ_SET_REPORT);
-
-	if (pidff->effect_count > 0)
-		pidff->effect_count--;
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -816,139 +863,79 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
 	pidff_playback_pid(pidff, pid_id, 0);
 	pidff_erase_pid(pidff, pid_id);
 
+	if (pidff->effect_count > 0)
+		pidff->effect_count--;
+
+	hid_dbg(pidff->hid, "current effect count: %d", pidff->effect_count);
 	return 0;
 }
 
+#define PIDFF_SET_REPORT_IF_NEEDED(type, effect, old) \
+	({ if (!old || pidff_needs_set_## type(effect, old)) \
+		pidff_set_ ##type## _report(pidff, effect); })
+
+#define PIDFF_SET_ENVELOPE_IF_NEEDED(type, effect, old) \
+	({ if (pidff_needs_set_envelope(&effect->u.type.envelope, \
+	       old ? &old->u.type.envelope : NULL)) \
+		pidff_set_envelope_report(pidff, &effect->u.type.envelope); })
+
 /*
  * Effect upload handler
  */
-static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *effect,
+static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *new,
 			       struct ff_effect *old)
 {
 	struct pidff_device *pidff = dev->ff->private;
-	int type_id;
-	int error;
+	const int type_id = pidff_get_effect_type_id(pidff, new);
 
-	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
-	if (old) {
-		pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] =
-			pidff->pid_id[effect->id];
+	if (!type_id) {
+		hid_err(pidff->hid, "effect type not supported\n");
+		return -EINVAL;
 	}
 
-	switch (effect->type) {
+	if (!pidff->effect_count)
+		pidff_reset(pidff);
+
+	if (!old) {
+		int error = pidff_request_effect_upload(pidff, type_id);
+
+		if (error)
+			return error;
+
+		pidff->effect_count++;
+		hid_dbg(pidff->hid, "current effect count: %d", pidff->effect_count);
+		pidff->pid_id[new->id] =
+			pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
+	}
+
+	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] =
+		pidff->pid_id[new->id];
+
+	PIDFF_SET_REPORT_IF_NEEDED(effect, new, old);
+	switch (new->type) {
 	case FF_CONSTANT:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_CONSTANT]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_constant(effect, old))
-			pidff_set_constant_force_report(pidff, effect);
-		if (pidff_needs_set_envelope(&effect->u.constant.envelope,
-					old ? &old->u.constant.envelope : NULL))
-			pidff_set_envelope_report(pidff, &effect->u.constant.envelope);
+		PIDFF_SET_REPORT_IF_NEEDED(constant, new, old);
+		PIDFF_SET_ENVELOPE_IF_NEEDED(constant, new, old);
 		break;
 
 	case FF_PERIODIC:
-		if (!old) {
-			switch (effect->u.periodic.waveform) {
-			case FF_SQUARE:
-				type_id = PID_SQUARE;
-				break;
-			case FF_TRIANGLE:
-				type_id = PID_TRIANGLE;
-				break;
-			case FF_SINE:
-				type_id = PID_SINE;
-				break;
-			case FF_SAW_UP:
-				type_id = PID_SAW_UP;
-				break;
-			case FF_SAW_DOWN:
-				type_id = PID_SAW_DOWN;
-				break;
-			default:
-				hid_err(pidff->hid, "invalid waveform\n");
-				return -EINVAL;
-			}
-
-			if (pidff->quirks & HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY)
-				type_id = PID_SINE;
-
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[type_id]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_periodic(effect, old))
-			pidff_set_periodic_report(pidff, effect);
-		if (pidff_needs_set_envelope(&effect->u.periodic.envelope,
-					old ? &old->u.periodic.envelope : NULL))
-			pidff_set_envelope_report(pidff, &effect->u.periodic.envelope);
+		PIDFF_SET_REPORT_IF_NEEDED(periodic, new, old);
+		PIDFF_SET_ENVELOPE_IF_NEEDED(periodic, new, old);
 		break;
 
 	case FF_RAMP:
-		if (!old) {
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[PID_RAMP]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_ramp(effect, old))
-			pidff_set_ramp_force_report(pidff, effect);
-		if (pidff_needs_set_envelope(&effect->u.ramp.envelope,
-					old ? &old->u.ramp.envelope : NULL))
-			pidff_set_envelope_report(pidff, &effect->u.ramp.envelope);
+		PIDFF_SET_REPORT_IF_NEEDED(ramp, new, old);
+		PIDFF_SET_ENVELOPE_IF_NEEDED(ramp, new, old);
 		break;
 
 	case FF_SPRING:
 	case FF_DAMPER:
 	case FF_INERTIA:
 	case FF_FRICTION:
-		if (!old) {
-			switch (effect->type) {
-			case FF_SPRING:
-				type_id = PID_SPRING;
-				break;
-			case FF_DAMPER:
-				type_id = PID_DAMPER;
-				break;
-			case FF_INERTIA:
-				type_id = PID_INERTIA;
-				break;
-			case FF_FRICTION:
-				type_id = PID_FRICTION;
-				break;
-			}
-			error = pidff_request_effect_upload(pidff,
-					pidff->type_id[type_id]);
-			if (error)
-				return error;
-		}
-		if (!old || pidff_needs_set_effect(effect, old))
-			pidff_set_effect_report(pidff, effect);
-		if (!old || pidff_needs_set_condition(effect, old))
-			pidff_set_condition_report(pidff, effect);
+		PIDFF_SET_REPORT_IF_NEEDED(condition, new, old);
 		break;
-
-	default:
-		hid_err(pidff->hid, "invalid type\n");
-		return -EINVAL;
 	}
-
-	if (!old)
-		pidff->pid_id[effect->id] =
-		    pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
-
 	hid_dbg(pidff->hid, "uploaded\n");
-
 	return 0;
 }
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 11/17] HID: pidff: Separate check for infinite duration
From: Tomasz Pakuła @ 2025-08-13 20:09 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

It will be used in a few more places so this makes sure it will always
work the same.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 32d42792c95a..534fb28f6e55 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -242,6 +242,11 @@ static int pidff_is_effect_conditional(struct ff_effect *effect)
 	       effect->type == FF_FRICTION;
 }
 
+static int pidff_is_duration_infinite(u16 duration)
+{
+	return duration == FF_INFINITE || duration == PID_INFINITE;
+}
+
 /*
  * Get PID effect index from FF effect type.
  * Return 0 if invalid.
@@ -374,12 +379,8 @@ static void pidff_set_time(struct pidff_usage *usage, u16 time)
 
 static void pidff_set_duration(struct pidff_usage *usage, u16 duration)
 {
-	/* Infinite value conversion from Linux API -> PID */
-	if (duration == FF_INFINITE)
-		duration = PID_INFINITE;
-
 	/* PID defines INFINITE as the max possible value for duration field */
-	if (duration == PID_INFINITE) {
+	if (pidff_is_duration_infinite(duration)) {
 		usage->value[0] = (1U << usage->field->report_size) - 1;
 		return;
 	}
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 12/17] HID: pidff: PERMISSIVE_CONTROL quirk autodetection
From: Tomasz Pakuła @ 2025-08-13 20:10 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Fixes force feedback for devices built with MMOS firmware and many more
not yet detected devices.

Update quirks mask debug message to always contain all 32 bits of data.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 534fb28f6e55..3fd51ad5cf56 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -1210,8 +1210,16 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
 					 PID_DIRECTION, 0);
 	pidff->device_control =
 		pidff_find_special_field(pidff->reports[PID_DEVICE_CONTROL],
-			PID_DEVICE_CONTROL_ARRAY,
-			!(pidff->quirks & HID_PIDFF_QUIRK_PERMISSIVE_CONTROL));
+			PID_DEVICE_CONTROL_ARRAY, 1);
+
+	/* Detect and set permissive control quirk */
+	if (!pidff->device_control) {
+		pr_debug("Setting PERMISSIVE_CONTROL quirk\n");
+		pidff->quirks |= HID_PIDFF_QUIRK_PERMISSIVE_CONTROL;
+		pidff->device_control = pidff_find_special_field(
+			pidff->reports[PID_DEVICE_CONTROL],
+			PID_DEVICE_CONTROL_ARRAY, 0);
+	}
 
 	pidff->block_load_status =
 		pidff_find_special_field(pidff->reports[PID_BLOCK_LOAD],
@@ -1552,7 +1560,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
 	ff->playback = pidff_playback;
 
 	hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
-	hid_dbg(dev, "Active quirks mask: 0x%x\n", pidff->quirks);
+	hid_dbg(dev, "Active quirks mask: 0x%08x\n", pidff->quirks);
 
 	hid_device_io_stop(hid);
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 13/17] HID: pidff: Remove Anssi's email address from info msg
From: Tomasz Pakuła @ 2025-08-13 20:10 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Some users might try to contact him about issues and he's no longer
active when it comes to the driver development/fixes.

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 3fd51ad5cf56..ebebac5c4384 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -1559,7 +1559,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
 	ff->set_autocenter = pidff_set_autocenter;
 	ff->playback = pidff_playback;
 
-	hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula <anssi.hannula@gmail.com>\n");
+	hid_info(dev, "Force feedback for USB HID PID devices by Anssi Hannula\n");
 	hid_dbg(dev, "Active quirks mask: 0x%08x\n", pidff->quirks);
 
 	hid_device_io_stop(hid);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 14/17] HID: pidff: Define all cardinal directions
From: Tomasz Pakuła @ 2025-08-13 20:10 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Will be used by ff-effect based autocentering

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index ebebac5c4384..7f4c1186a44d 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -148,8 +148,12 @@ static const u8 pidff_block_load_status[] = { 0x8c, 0x8d, 0x8e };
 #define PID_EFFECT_STOP		1
 static const u8 pidff_effect_operation_status[] = { 0x79, 0x7b };
 
-/* Polar direction 90 degrees (East) */
-#define PIDFF_FIXED_WHEEL_DIRECTION	0x4000
+#define PID_DIRECTION_NORTH	0x0000
+#define PID_DIRECTION_EAST	0x4000
+#define PID_DIRECTION_SOUTH	0x8000
+#define PID_DIRECTION_WEST	0xc000
+
+#define PIDFF_FIXED_WHEEL_DIRECTION	PID_DIRECTION_EAST
 
 /* AXES_ENABLE and DIRECTION axes */
 enum pid_axes {
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 15/17] HID: pidff: clang-format pass
From: Tomasz Pakuła @ 2025-08-13 20:10 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 55 ++++++++++++++++------------------
 1 file changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 7f4c1186a44d..50a8924edfcc 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -9,12 +9,11 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include "hid-pidff.h"
+#include <linux/hid.h>
 #include <linux/input.h>
+#include <linux/minmax.h>
 #include <linux/slab.h>
 #include <linux/usb.h>
-#include <linux/hid.h>
-#include <linux/minmax.h>
-
 
 #define	PID_EFFECTS_MAX		64
 #define	PID_INFINITE		U16_MAX
@@ -321,7 +320,7 @@ static s32 pidff_clamp(s32 i, struct hid_field *field)
 static int pidff_rescale(int i, int max, struct hid_field *field)
 {
 	return i * (field->logical_maximum - field->logical_minimum) / max +
-		field->logical_minimum;
+	       field->logical_minimum;
 }
 
 /*
@@ -367,18 +366,18 @@ static void pidff_set_signed(struct pidff_usage *usage, s16 value)
 	else {
 		if (value < 0)
 			usage->value[0] =
-			    pidff_rescale(-value, -S16_MIN, usage->field);
+				pidff_rescale(-value, -S16_MIN, usage->field);
 		else
 			usage->value[0] =
-			    pidff_rescale(value, S16_MAX, usage->field);
+				pidff_rescale(value, S16_MAX, usage->field);
 	}
 	pr_debug("calculated from %d to %d\n", value, usage->value[0]);
 }
 
 static void pidff_set_time(struct pidff_usage *usage, u16 time)
 {
-	usage->value[0] = pidff_clamp(
-		pidff_rescale_time(time, usage->field), usage->field);
+	usage->value[0] = pidff_clamp(pidff_rescale_time(time, usage->field),
+				      usage->field);
 }
 
 static void pidff_set_duration(struct pidff_usage *usage, u16 duration)
@@ -516,11 +515,11 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
 		pidff->create_new_effect_type->value[0];
 
 	pidff_set_duration(&pidff->set_effect[PID_DURATION],
-		effect->replay.length);
+			   effect->replay.length);
 
 	pidff->set_effect[PID_TRIGGER_BUTTON].value[0] = effect->trigger.button;
 	pidff_set_time(&pidff->set_effect[PID_TRIGGER_REPEAT_INT],
-			effect->trigger.interval);
+		       effect->trigger.interval);
 	pidff->set_effect[PID_GAIN].value[0] =
 		pidff->set_effect[PID_GAIN].field->logical_maximum;
 
@@ -529,10 +528,10 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
 	/* Omit setting delay field if it's missing */
 	if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_DELAY))
 		pidff_set_time(&pidff->set_effect[PID_START_DELAY],
-				effect->replay.delay);
+			       effect->replay.delay);
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -562,10 +561,10 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
 			 effect->u.periodic.offset);
 	pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
 	pidff_set_time(&pidff->set_periodic[PID_PERIOD],
-			effect->u.periodic.period);
+		       effect->u.periodic.period);
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_PERIODIC],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -612,7 +611,7 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
 		pidff_set(&pidff->set_condition[PID_DEAD_BAND],
 			  effect->u.condition[i].deadband);
 		hid_hw_request(pidff->hid, pidff->reports[PID_SET_CONDITION],
-				HID_REQ_SET_REPORT);
+			       HID_REQ_SET_REPORT);
 	}
 }
 
@@ -675,7 +674,7 @@ static void pidff_set_gain_report(struct pidff_device *pidff, u16 gain)
 
 	pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
 	hid_hw_request(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -761,21 +760,19 @@ static void pidff_fetch_pool(struct pidff_device *pidff)
  */
 static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
 {
-	int j;
-
 	pidff->create_new_effect_type->value[0] = efnum;
 	hid_hw_request(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 	hid_dbg(pidff->hid, "create_new_effect sent, type: %d\n", efnum);
 
 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
 	pidff->block_load_status->value[0] = 0;
 	hid_hw_wait(pidff->hid);
 
-	for (j = 0; j < 60; j++) {
+	for (int i = 0; i < 60; i++) {
 		hid_dbg(pidff->hid, "pid_block_load requested\n");
 		hid_hw_request(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
-				HID_REQ_GET_REPORT);
+			       HID_REQ_GET_REPORT);
 		hid_hw_wait(pidff->hid);
 		if (pidff->block_load_status->value[0] ==
 		    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
@@ -857,8 +854,8 @@ static int pidff_erase_effect(struct input_dev *dev, int effect_id)
 	struct pidff_device *pidff = dev->ff->private;
 	int pid_id = pidff->pid_id[effect_id];
 
-	hid_dbg(pidff->hid, "starting to erase %d/%d\n",
-		effect_id, pidff->pid_id[effect_id]);
+	hid_dbg(pidff->hid, "starting to erase %d/%d\n", effect_id,
+		pidff->pid_id[effect_id]);
 
 	/*
 	 * Wait for the queue to clear. We do not want
@@ -978,7 +975,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
 		pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
 	hid_hw_request(pidff->hid, pidff->reports[PID_SET_EFFECT],
-			HID_REQ_SET_REPORT);
+		       HID_REQ_SET_REPORT);
 }
 
 /*
@@ -1269,7 +1266,7 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
 
 	if (PIDFF_FIND_SPECIAL_KEYS(status_id, block_load_status,
 				    block_load_status) !=
-			ARRAY_SIZE(pidff_block_load_status)) {
+	    ARRAY_SIZE(pidff_block_load_status)) {
 		hid_err(pidff->hid,
 			"block load status identifiers not found\n");
 		return -1;
@@ -1277,7 +1274,7 @@ static int pidff_find_special_fields(struct pidff_device *pidff)
 
 	if (PIDFF_FIND_SPECIAL_KEYS(operation_id, effect_operation_status,
 				    effect_operation_status) !=
-			ARRAY_SIZE(pidff_effect_operation_status)) {
+	    ARRAY_SIZE(pidff_effect_operation_status)) {
 		hid_err(pidff->hid, "effect operation identifiers not found\n");
 		return -1;
 	}
@@ -1482,8 +1479,8 @@ static int pidff_check_autocenter(struct pidff_device *pidff,
 int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
 {
 	struct pidff_device *pidff;
-	struct hid_input *hidinput = list_entry(hid->inputs.next,
-						struct hid_input, list);
+	struct hid_input *hidinput =
+		list_entry(hid->inputs.next, struct hid_input, list);
 	struct input_dev *dev = hidinput->input;
 	struct ff_device *ff;
 	int max_effects;
@@ -1570,7 +1567,7 @@ int hid_pidff_init_with_quirks(struct hid_device *hid, u32 initial_quirks)
 
 	return 0;
 
- fail:
+fail:
 	hid_device_io_stop(hid);
 
 	kfree(pidff);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 16/17] HID: universal-pidff: clang-format pass
From: Tomasz Pakuła @ 2025-08-13 20:10 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/hid-universal-pidff.c | 57 ++++++++++++++++---------------
 1 file changed, 29 insertions(+), 28 deletions(-)

diff --git a/drivers/hid/hid-universal-pidff.c b/drivers/hid/hid-universal-pidff.c
index 70fce0f88e82..549dac555d40 100644
--- a/drivers/hid/hid-universal-pidff.c
+++ b/drivers/hid/hid-universal-pidff.c
@@ -8,12 +8,12 @@
  * Copyright (c) 2024, 2025 Tomasz Pakuła
  */
 
+#include "hid-ids.h"
+#include "usbhid/hid-pidff.h"
 #include <linux/device.h>
 #include <linux/hid.h>
-#include <linux/module.h>
 #include <linux/input-event-codes.h>
-#include "hid-ids.h"
-#include "usbhid/hid-pidff.h"
+#include <linux/module.h>
 
 #define JOY_RANGE (BTN_DEAD - BTN_JOYSTICK + 1)
 
@@ -21,8 +21,10 @@
  * Map buttons manually to extend the default joystick button limit
  */
 static int universal_pidff_input_mapping(struct hid_device *hdev,
-	struct hid_input *hi, struct hid_field *field, struct hid_usage *usage,
-	unsigned long **bit, int *max)
+					 struct hid_input *hi,
+					 struct hid_field *field,
+					 struct hid_usage *usage,
+					 unsigned long **bit, int *max)
 {
 	if ((usage->hid & HID_USAGE_PAGE) != HID_UP_BUTTON)
 		return 0;
@@ -126,65 +128,64 @@ static int universal_pidff_input_configured(struct hid_device *hdev,
 		if (!test_bit(axis, input->absbit))
 			continue;
 
-		input_set_abs_params(input, axis,
-			input->absinfo[axis].minimum,
-			input->absinfo[axis].maximum,
-			axis == ABS_X ? 0 : 8, 0);
+		input_set_abs_params(input, axis, input->absinfo[axis].minimum,
+				     input->absinfo[axis].maximum,
+				     axis == ABS_X ? 0 : 8, 0);
 	}
 
 	/* Remove fuzz and deadzone from the second joystick axis */
 	if (hdev->vendor == USB_VENDOR_ID_FFBEAST &&
 	    hdev->product == USB_DEVICE_ID_FFBEAST_JOYSTICK)
 		input_set_abs_params(input, ABS_Y,
-			input->absinfo[ABS_Y].minimum,
-			input->absinfo[ABS_Y].maximum, 0, 0);
+				     input->absinfo[ABS_Y].minimum,
+				     input->absinfo[ABS_Y].maximum, 0, 0);
 
 	return 0;
 }
 
 static const struct hid_device_id universal_pidff_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R3_2),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R5_2),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R9_2),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R12_2),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_MOZA, USB_DEVICE_ID_MOZA_R16_R21_2),
-		.driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
+	  .driver_data = HID_PIDFF_QUIRK_FIX_CONDITIONAL_DIRECTION },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CAMMUS, USB_DEVICE_ID_CAMMUS_C12) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_VRS, USB_DEVICE_ID_VRS_DFP),
-		.driver_data = HID_PIDFF_QUIRK_PERMISSIVE_CONTROL },
+	  .driver_data = HID_PIDFF_QUIRK_PERMISSIVE_CONTROL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_JOYSTICK), },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_RUDDER), },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_FFBEAST, USB_DEVICE_ID_FFBEAST_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V10),
-		.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+	  .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12),
-		.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+	  .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE),
-		.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+	  .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_PXN_V12_LITE_2),
-		.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+	  .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LITE_STAR, USB_DEVICE_ID_LITE_STAR_GT987),
-		.driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
+	  .driver_data = HID_PIDFF_QUIRK_PERIODIC_SINE_ONLY },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_INVICTA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_FORTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_LA_PRIMA) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ASETEK, USB_DEVICE_ID_ASETEK_TONY_KANAAN) },
-	{ }
+	{}
 };
 MODULE_DEVICE_TABLE(hid, universal_pidff_devices);
 
-- 
2.50.1


^ permalink raw reply related

* [PATCH v2 17/17] HID: pidff: Reduce PID_EFFECT_OPERATION spam
From: Tomasz Pakuła @ 2025-08-13 20:10 UTC (permalink / raw)
  To: jikos, bentiss; +Cc: oleg, linux-input
In-Reply-To: <20250813201005.17819-1-tomasz.pakula.oficjalny@gmail.com>

Keep track of effect's loop_count to reduce the spam of ffb play
commands coming from some games. This should speed up normal magnitude
etc updates and slightly increase max possible FFB refresh rate.

Helps games like Dirt Rally 2.0, F1 2023, WRC from KT

Signed-off-by: Tomasz Pakuła <tomasz.pakula.oficjalny@gmail.com>
---
 drivers/hid/usbhid/hid-pidff.c | 36 ++++++++++++++++++++++++++--------
 1 file changed, 28 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c
index 50a8924edfcc..0342c0a3f476 100644
--- a/drivers/hid/usbhid/hid-pidff.c
+++ b/drivers/hid/usbhid/hid-pidff.c
@@ -184,6 +184,12 @@ struct pidff_usage {
 	s32 *value;
 };
 
+struct pidff_effect {
+	int pid_id;
+	int is_infinite;
+	unsigned int loop_count;
+};
+
 struct pidff_device {
 	struct hid_device *hid;
 
@@ -202,6 +208,8 @@ struct pidff_device {
 	struct pidff_usage effect_operation[ARRAY_SIZE(pidff_effect_operation)];
 	struct pidff_usage block_free[ARRAY_SIZE(pidff_block_free)];
 
+	struct pidff_effect effect[PID_EFFECTS_MAX];
+
 	/*
 	 * Special field is a field that is not composed of
 	 * usage<->value pairs that pidff_usage values are
@@ -230,8 +238,6 @@ struct pidff_device {
 	int operation_id[ARRAY_SIZE(pidff_effect_operation_status)];
 	int direction_axis_id[ARRAY_SIZE(pidff_direction_axis)];
 
-	int pid_id[PID_EFFECTS_MAX];
-
 	u32 quirks;
 	u8 effect_count;
 	u8 axis_count;
@@ -798,6 +804,12 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
 	return -EIO;
 }
 
+static int pidff_needs_playback(struct pidff_device *pidff, int effect_id, int n)
+{
+	return pidff->effect[effect_id].is_infinite ||
+	       pidff->effect[effect_id].loop_count != n;
+}
+
 /*
  * Play the effect with PID id n times
  */
@@ -829,9 +841,14 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
 {
 	struct pidff_device *pidff = dev->ff->private;
 
+	if (!pidff_needs_playback(pidff, effect_id, value))
+		return 0;
+
 	hid_dbg(pidff->hid, "requesting %s on FF effect %d",
 		value == 0 ? "stop" : "playback", effect_id);
-	pidff_playback_pid(pidff, pidff->pid_id[effect_id], value);
+
+	pidff->effect[effect_id].loop_count = value;
+	pidff_playback_pid(pidff, pidff->effect[effect_id].pid_id, value);
 	return 0;
 }
 
@@ -852,10 +869,9 @@ static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
 static int pidff_erase_effect(struct input_dev *dev, int effect_id)
 {
 	struct pidff_device *pidff = dev->ff->private;
-	int pid_id = pidff->pid_id[effect_id];
+	int pid_id = pidff->effect[effect_id].pid_id;
 
-	hid_dbg(pidff->hid, "starting to erase %d/%d\n", effect_id,
-		pidff->pid_id[effect_id]);
+	hid_dbg(pidff->hid, "starting to erase %d/%d\n", effect_id, pid_id);
 
 	/*
 	 * Wait for the queue to clear. We do not want
@@ -906,12 +922,16 @@ static int pidff_upload_effect(struct input_dev *dev, struct ff_effect *new,
 
 		pidff->effect_count++;
 		hid_dbg(pidff->hid, "current effect count: %d", pidff->effect_count);
-		pidff->pid_id[new->id] =
+		pidff->effect[new->id].loop_count = 0;
+		pidff->effect[new->id].pid_id =
 			pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0];
 	}
 
+	pidff->effect[new->id].is_infinite =
+		pidff_is_duration_infinite(new->replay.length);
+
 	pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] =
-		pidff->pid_id[new->id];
+		pidff->effect[new->id].pid_id;
 
 	PIDFF_SET_REPORT_IF_NEEDED(effect, new, old);
 	switch (new->type) {
-- 
2.50.1


^ permalink raw reply related

* Re: [PATCH 7/8] sound: dt-bindings: ti,omap-twl4030: convert to DT schema
From: Mark Brown @ 2025-08-13 20:29 UTC (permalink / raw)
  To: Jihed Chaibi
  Cc: linux-kernel, peter.ujfalusi, dmitry.torokhov, robh, krzk+dt,
	lgirdwood, tiwai, conor+dt, lee, ukleinek, gregkh, linux-input,
	devicetree, linux-pwm, linux-sound, linux-usb, shuah
In-Reply-To: <20250811224739.53869-8-jihed.chaibi.dev@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 599 bytes --]

On Tue, Aug 12, 2025 at 12:47:38AM +0200, Jihed Chaibi wrote:

> Convert the legacy TXT binding for the OMAP TWL4030 sound card
> to the modern YAML DT schema format. This adds formal validation
> and improves documentation.

Acked-by: Mark Brown <broonie@kernel.org>

Please submit patches using subject lines reflecting the style for the
subsystem, this makes it easier for people to identify relevant patches.
Look at what existing commits in the area you're changing are doing and
make sure your subject lines visually resemble what they're doing.
There's no need to resubmit to fix this alone.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply

* Re: (subset) [PATCH 00/21] treewide: remove unneeded 'fast_io' parameter in regmap_config
From: Mark Brown @ 2025-08-13 21:28 UTC (permalink / raw)
  To: linux-kernel, Wolfram Sang
  Cc: Adrian Hunter, Alexandre Belloni, Alexandre Torgue, Alim Akhtar,
	Andrea della Porta, Andreas Färber, Andrzej Hajda,
	Andy Shevchenko, Andy Yan, Avi Fishman, Bartosz Golaszewski,
	Benjamin Fair, Bjorn Andersson, Chen-Yu Tsai, Daniel Lezcano,
	David Airlie, David Lechner, Dmitry Torokhov, Drew Fustini,
	dri-devel, Fabio Estevam, Fabrice Gasnier, Fu Wei, Guo Ren,
	Hans Verkuil, Heiko Stübner, imx, Iwona Winiarska,
	Jaroslav Kysela, Jassi Brar, Jernej Skrabec, Jerome Brunet,
	Jonas Karlman, Jonathan Cameron, Kevin Hilman,
	Kishon Vijay Abraham I, Konrad Dybcio, Krzysztof Kozlowski,
	Laurent Pinchart, Lee Jones, Liam Girdwood, Linus Walleij,
	linux-actions, linux-amlogic, linux-arm-kernel, linux-arm-msm,
	linux-clk, linux-gpio, linux-iio, linux-input, linux-media,
	linux-mmc, linux-phy, linux-pm, linuxppc-dev, linux-pwm,
	linux-riscv, linux-rockchip, linux-rtc, linux-samsung-soc,
	linux-sound, linux-spi, linux-stm32, linux-sunxi, Liu Ying,
	Lukasz Luba, Maarten Lankhorst, Manivannan Sadhasivam,
	Martin Blumenstingl, Mauro Carvalho Chehab, Maxime Coquelin,
	Maxime Ripard, Michael Turquette, Miquel Raynal, Nancy Yuen,
	Neil Armstrong, Nicolin Chen, Nuno Sá, openbmc,
	Patrick Venture, Paul Walmsley, Pengutronix Kernel Team,
	Philipp Zabel, Piotr Wojtaszczyk, Rafael J. Wysocki, Robert Foss,
	Samuel Holland, Samuel Holland, Sandy Huang, Sascha Hauer,
	Shawn Guo, Shengjiu Wang, Simona Vetter, Stephen Boyd,
	Takashi Iwai, Tali Perry, Thomas Zimmermann, Tomer Maimon,
	Ulf Hansson, Uwe Kleine-König, Vasily Khoruzhick, Vinod Koul,
	Vladimir Zapolskiy, Xiubo Li, Yangtao Li, Zhang Rui
In-Reply-To: <20250813161517.4746-1-wsa+renesas@sang-engineering.com>

On Wed, 13 Aug 2025 18:14:46 +0200, Wolfram Sang wrote:
> While working on a driver using regmap with MMIO, I wondered if I need
> to set 'fast_io' in the config. Turned out I don't need to, so I added
> documentation for it with commit ffc72771ff6e ("regmap: Annotate that
> MMIO implies fast IO").
> 
> This series fixes the existing users in the tree which needlessly set
> the flag. They have been found using this coccinelle script:
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator.git for-next

Thanks!

[15/21] regulator: remove unneeded 'fast_io' parameter in regmap_config
        commit: 37533933bfe92cd5a99ef4743f31dac62ccc8de0

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


^ permalink raw reply

* Re: [PATCH 06/21] Input: remove unneeded 'fast_io' parameter in regmap_config
From: Dmitry Torokhov @ 2025-08-13 21:47 UTC (permalink / raw)
  To: Wolfram Sang
  Cc: linux-kernel, Mark Brown, Shawn Guo, Sascha Hauer,
	Pengutronix Kernel Team, Fabio Estevam, linux-input, imx,
	linux-arm-kernel
In-Reply-To: <20250813161517.4746-7-wsa+renesas@sang-engineering.com>

On Wed, Aug 13, 2025 at 06:14:52PM +0200, Wolfram Sang wrote:
> When using MMIO with regmap, fast_io is implied. No need to set it
> again.
> 
> Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com>

Applied, thank you.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v2 2/3] Input: aw86927 - add driver for Awinic AW86927
From: Griffin Kroah-Hartman @ 2025-08-14  7:43 UTC (permalink / raw)
  To: Dmitry Torokhov
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Konrad Dybcio, Luca Weiss, linux-input, devicetree, linux-kernel,
	linux-arm-msm
In-Reply-To: <vuv26omdn4a5jniv6znepcxel65buzymu6te2ys2dgtkttk6sg@edqm6xpddudn>

Hello Dmitry!

On 8/11/25 18:35, Dmitry Torokhov wrote:
> Hi Griffin,
> 
> On Mon, Aug 11, 2025 at 01:12:02PM +0200, Griffin Kroah-Hartman wrote:
(..)
>> +struct aw86927_sram_waveform_header {
>> +	uint8_t version;
>> +	struct {
>> +		__be16 start_address;
>> +		__be16 end_address;
>> +	} __packed waveform_address[1];
> 
> Why does this need to be an array? 

Great question, during development this was used to include multiple 
wave-forms, but it was decided that the feature was unnecessary as of 
now. I will remove the array for simplicity.

>> +static int aw86927_haptics_play(struct input_dev *dev, void *data, struct ff_effect *effect)
>> +{
>> +	struct aw86927_data *haptics = input_get_drvdata(dev);
>> +	int level;
>> +
>> +	level = effect->u.rumble.strong_magnitude;
>> +	if (!level)
>> +		level = effect->u.rumble.weak_magnitude;
>> +
>> +	/* If already running, don't restart playback */
> 
> Why not if effect parameters are changing? Also what if someone is
> issuing stop for already stopped effect?

It it's current state, the driver only has one level of vibration, 
therefore adjusting the effect does not matter as it is either vibrating 
or off.
For your second question I don't think I understand what you are asking. 
If someone gives magnitude 0 to a vibration that has ceased playback, 
the vibration has already stopped, so we don't need to stop it again.

>> +
>> +	haptics->regmap = devm_regmap_init_i2c(client, &aw86927_regmap_config);
>> +	if (IS_ERR(haptics->regmap))
>> +		return dev_err_probe(haptics->dev, PTR_ERR(haptics->regmap),
>> +					"Failed to allocate register map\n");
>> +
>> +	haptics->input_dev = devm_input_allocate_device(haptics->dev);
>> +	if (!haptics->input_dev)
>> +		return -ENOMEM;
>> +
>> +	haptics->reset_gpio = devm_gpiod_get(haptics->dev, "reset", GPIOD_OUT_HIGH);
>> +	if (IS_ERR(haptics->reset_gpio))
>> +		return dev_err_probe(haptics->dev, PTR_ERR(haptics->reset_gpio),
>> +				     "Failed to get reset gpio\n");
> 
> Is it mandatory to wire the reset pin? I see the chip supports software
> reset so maybe this can be optional?

In the datasheet, it is never explicitly mentioned that the pin is 
optional, and in the downstream driver it is mandatory.
If the reset pin is not found the probe will fail.

If somebody has a board with that use-case they can modify this driver 
easily.

>> +
>> +	/* Hardware reset */
>> +	aw86927_hw_reset(haptics);
>> +
>> +	/* Software reset */
>> +	err = regmap_write(haptics->regmap, AW86927_RSTCFG, AW86927_RSTCFG_SOFTRST);
>> +	if (err)
>> +		return dev_err_probe(haptics->dev, PTR_ERR(haptics->regmap),
>> +					"Failed Software reset\n");
> 
> Do you need to issue software reset together with hardware reset? Is
> one or the other not enough?

The datasheet does not mention whether one is enough, the downstream 
driver does it with both so I have assumed that this would be best 
practice with this chip.

>> +	err = devm_request_threaded_irq(haptics->dev, client->irq, NULL,
>> +					aw86927_irq, IRQF_ONESHOT, NULL, haptics);
> 
> Error handling? Also it looks like here it is safe to register the
> interrupt handler early since it does not actually do anything, but
> better to move it after the bulk of initialization in case it will get
> expanded.

I will fix the error handling :). If someone were to implement FIFO mode 
then this would be the correct placement of the initialization, so I 
think for now it would make sense to keep it here.

> 
> Thanks.
> 

Thank you for your comments!

^ permalink raw reply

* Re: [PATCH v2 1/3] dt-bindings: input: Add bindings for Awinic AW86927
From: Krzysztof Kozlowski @ 2025-08-14  8:58 UTC (permalink / raw)
  To: Griffin Kroah-Hartman
  Cc: Dmitry Torokhov, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Bjorn Andersson, Konrad Dybcio, Luca Weiss, linux-input,
	devicetree, linux-kernel, linux-arm-msm
In-Reply-To: <20250811-aw86927-v2-1-64be8f3da560@fairphone.com>

On Mon, Aug 11, 2025 at 01:12:01PM +0200, Griffin Kroah-Hartman wrote:
> Add bindings for the Awinic AW86927 haptic chip which can be found in
> smartphones.

Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>

If you are going to send new version, then also:

A nit, subject: drop second/last, redundant "bindings". The
"dt-bindings" prefix is already stating that these are bindings.
See also:
https://elixir.bootlin.com/linux/v6.7-rc8/source/Documentation/devicetree/bindings/submitting-patches.rst#L18

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2] HID: lg-g15 - Add support for Logitech G13.
From: Kate Hsuan @ 2025-08-14  9:09 UTC (permalink / raw)
  To: Leo L. Schwab
  Cc: Hans de Goede, Jiri Kosina, Benjamin Tissoires, linux-input,
	linux-kernel
In-Reply-To: <20250812065327.515098-2-ewhac@ewhac.org>

Hi Leo,

Thank you for your work.

On Tue, Aug 12, 2025 at 2:57 PM Leo L. Schwab <ewhac@ewhac.org> wrote:
>
> The Logitech G13 is a gaming keypad with general-purpose macro keys,
> four LED-backlit macro preset keys, five "menu" keys, backlight toggle
> key, an analog thumbstick, RGB LED backlight, and a monochrome LCD
> display.
>
> Supports input event generation for all keys and the thumbstick, and
> exposes all LEDs.
>
> Signed-off-by: Leo L. Schwab <ewhac@ewhac.org>
> ---
> Changes in v2:
>   - Add `#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED` bracket around new
>     code segment dependent on that feature (fixes test robot build
>     error).
>   - Use `guard(mutex)` construct in new code (existing code left
>     unmodified).
>   - Commit message revised.
>
>  drivers/hid/hid-ids.h    |   1 +
>  drivers/hid/hid-lg-g15.c | 440 +++++++++++++++++++++++++++++++++++++--
>  2 files changed, 420 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
> index 33cc5820f2be..7ed1e402b80a 100644
> --- a/drivers/hid/hid-ids.h
> +++ b/drivers/hid/hid-ids.h
> @@ -870,6 +870,7 @@
>  #define USB_DEVICE_ID_LOGITECH_DUAL_ACTION     0xc216
>  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2      0xc218
>  #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2    0xc219
> +#define USB_DEVICE_ID_LOGITECH_G13             0xc21c
>  #define USB_DEVICE_ID_LOGITECH_G15_LCD         0xc222
>  #define USB_DEVICE_ID_LOGITECH_G11             0xc225
>  #define USB_DEVICE_ID_LOGITECH_G15_V2_LCD      0xc227
> diff --git a/drivers/hid/hid-lg-g15.c b/drivers/hid/hid-lg-g15.c
> index f8605656257b..1749d0b43967 100644
> --- a/drivers/hid/hid-lg-g15.c
> +++ b/drivers/hid/hid-lg-g15.c
> @@ -26,7 +26,11 @@
>  #define LG_G510_FEATURE_BACKLIGHT_RGB  0x05
>  #define LG_G510_FEATURE_POWER_ON_RGB   0x06
>
> +#define LG_G13_FEATURE_M_KEYS_LEDS     0x05
> +#define LG_G13_FEATURE_BACKLIGHT_RGB   0x07
> +
>  enum lg_g15_model {
> +       LG_G13,
>         LG_G15,
>         LG_G15_V2,
>         LG_G510,
> @@ -45,6 +49,12 @@ enum lg_g15_led_type {
>         LG_G15_LED_MAX
>  };
>
> +struct g13_input_report {
> +       u8 report_id;   // 1
The comment should describe the reason of the settings in C comment
style, for exmple
 u8 report_id;   /* The report ID is always set to 1 */

> +       u8 joy_x, joy_y;
> +       u8 keybits[5];
> +};
> +
>  struct lg_g15_led {
>         union {
>                 struct led_classdev cdev;
> @@ -63,12 +73,174 @@ struct lg_g15_data {
>         struct mutex mutex;
>         struct work_struct work;
>         struct input_dev *input;
> +       struct input_dev *input_js; // joystick device for G13
The comment should in C comments, for example
 struct input_dev *input_js;  /*joystick device for G13*/

>         struct hid_device *hdev;
>         enum lg_g15_model model;
>         struct lg_g15_led leds[LG_G15_LED_MAX];
>         bool game_mode_enabled;
>  };
>
> +/********* G13 LED functions ***********/
> +/*
> + * G13 retains no state across power cycles, and always powers up with the backlight on,
> + * color #5AFF6E, all macro key LEDs off.
> + */
> +static int lg_g13_get_leds_state(struct lg_g15_data *g15)
> +{
> +       u8 * const tbuf = g15->transfer_buf;
> +       int ret, high;
> +
> +       /*  RGB backlight.  */
One white space is good.
/* RGB backlight. */
> +       ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_BACKLIGHT_RGB,
> +                                tbuf, 5,
> +                                HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
> +       if (ret != 5) {
> +               hid_err(g15->hdev, "Error getting backlight brightness: %d\n", ret);
> +               return (ret < 0) ? ret : -EIO;
> +       }
> +
> +       /*  Normalize RGB intensities against highest component.  */
Ditto and should be "the highest component".

> +       high = max3(tbuf[1], tbuf[2], tbuf[3]);
> +       if (high) {
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].red =
> +                       DIV_ROUND_CLOSEST(tbuf[1] * 255, high);
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].green =
> +                       DIV_ROUND_CLOSEST(tbuf[2] * 255, high);
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].blue =
> +                       DIV_ROUND_CLOSEST(tbuf[3] * 255, high);
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = high;
> +       } else {
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].red        = 255;
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].green      = 255;
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].blue       = 255;
> +               g15->leds[LG_G15_KBD_BRIGHTNESS].brightness = 0;

> +       }
> +
> +       /*  Macro LEDs.  */
Ditto.
> +       ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_M_KEYS_LEDS,
> +                                tbuf, 5,
> +                                HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
> +       if (ret != 5) {
> +               hid_err(g15->hdev, "Error getting macro LED brightness: %d\n", ret);
> +               return (ret < 0) ? ret : -EIO;
> +       }
> +
> +       for (int i = LG_G15_MACRO_PRESET1;  i < LG_G15_LED_MAX;  ++i)
> +               g15->leds[i].brightness = tbuf[1] & (1 << (i - LG_G15_MACRO_PRESET1));
> +
> +       return 0;
> +}
> +
> +/* Must be called with g15->mutex locked */
If guard() is called in lg_g13_kbd_led_write() and the comment can be dropped.
> +static int lg_g13_kbd_led_write(struct lg_g15_data *g15,
> +                               struct lg_g15_led *g15_led,
> +                               enum led_brightness brightness)
> +{
> +       struct mc_subled const * const subleds = g15_led->mcdev.subled_info;
> +       u8 * const tbuf = g15->transfer_buf;
> +       int ret;
> +
> +       led_mc_calc_color_components(&g15_led->mcdev, brightness);
> +
> +       tbuf[0] = 5;
> +       tbuf[1] = subleds[0].brightness;
> +       tbuf[2] = subleds[1].brightness;
> +       tbuf[3] = subleds[2].brightness;
> +       tbuf[4] = 0;
> +
> +       ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_BACKLIGHT_RGB,
> +                                tbuf, 5,
> +                                HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
> +       if (ret == 5) {
> +               g15_led->brightness = brightness;
> +               ret = 0;
> +       } else {
> +               hid_err(g15->hdev, "Error setting backlight brightness: %d\n", ret);
> +               ret = (ret < 0) ? ret : -EIO;
> +       }
> +
> +       return ret;
> +}
> +
> +static int lg_g13_kbd_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
> +{
> +       struct led_classdev_mc *mc = lcdev_to_mccdev(led_cdev);
> +       struct lg_g15_led *g15_led =
> +               container_of(mc, struct lg_g15_led, mcdev);
> +       struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
> +
> +       /* Ignore LED off on unregister / keyboard unplug */
> +       if (led_cdev->flags & LED_UNREGISTERING)
> +               return 0;
> +
> +       guard(mutex)(&g15->mutex);
guard() can be moved to lg_g13_kbd_led_write() to ensure the code is
protected by a mutex lock when lg_g13_kbd_led_write() is called.

> +       return lg_g13_kbd_led_write(g15, g15_led, brightness);
> +}
> +
> +static enum led_brightness lg_g13_kbd_led_get(struct led_classdev *led_cdev)
> +{
> +       struct led_classdev_mc const * const mc = lcdev_to_mccdev(led_cdev);
> +       struct lg_g15_led const *g15_led =
> +               container_of(mc, struct lg_g15_led, mcdev);
> +
> +       return g15_led->brightness;
> +}
> +
> +static int lg_g13_mkey_led_set(struct led_classdev *led_cdev, enum led_brightness brightness)
> +{
> +       struct lg_g15_led *g15_led =
> +               container_of(led_cdev, struct lg_g15_led, cdev);
> +       struct lg_g15_data *g15 = dev_get_drvdata(led_cdev->dev->parent);
> +       int i, ret;
> +       u8 * const tbuf = g15->transfer_buf;
> +       u8 val, mask = 0;
> +
> +       /* Ignore LED off on unregister / keyboard unplug */
> +       if (led_cdev->flags & LED_UNREGISTERING)
> +               return 0;
> +
> +       guard(mutex)(&g15->mutex);
> +
> +       for (i = LG_G15_MACRO_PRESET1;  i < LG_G15_LED_MAX;  ++i) {
> +               if (i == g15_led->led)
> +                       val = brightness;
> +               else
> +                       val = g15->leds[i].brightness;
> +
> +               if (val)
> +                       mask |= 1 << (i - LG_G15_MACRO_PRESET1);
> +       }
> +
> +       tbuf[0] = 5;
> +       tbuf[1] = mask;
> +       tbuf[2] =
> +       tbuf[3] =
> +       tbuf[4] = 0;
To increase the readability, it could be
       tbuf[2] = 0;
       tbuf[3] = 0;
       tbuf[4] = 0;

> +
> +       ret = hid_hw_raw_request(g15->hdev, LG_G13_FEATURE_M_KEYS_LEDS,
> +                                tbuf, 5,
> +                                HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
> +       if (ret != 5) {
> +               hid_err(g15->hdev, "Error setting LED brightness: %d\n", ret);
> +               return (ret < 0) ? ret : -EIO;
> +       }
> +
> +       g15_led->brightness = brightness;
> +       return 0;
> +}
> +
> +static enum led_brightness lg_g13_mkey_led_get(struct led_classdev *led_cdev)
> +{
> +       /*
> +        * G13 doesn't change macro key LEDs behind our back, so they're
> +        * whatever we last set them to.
> +        */
> +       struct lg_g15_led *g15_led =
> +               container_of(led_cdev, struct lg_g15_led, cdev);
> +
> +       return g15_led->brightness;
> +}
> +
>  /******** G15 and G15 v2 LED functions ********/
>
>  static int lg_g15_update_led_brightness(struct lg_g15_data *g15)
> @@ -390,6 +562,8 @@ static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
>         int ret;
>
>         switch (g15->model) {
> +       case LG_G13:
> +               return lg_g13_get_leds_state(g15);
>         case LG_G15:
>         case LG_G15_V2:
>                 return lg_g15_update_led_brightness(g15);
> @@ -417,6 +591,117 @@ static int lg_g15_get_initial_led_brightness(struct lg_g15_data *g15)
>
>  /******** Input functions ********/
>
> +/**
> + * g13_input_report.keybits[] is not 32-bit aligned, so we can't use the bitops macros.
> + *
> + * @ary: Pointer to array of u8s
> + * @b:   Bit index into ary, LSB first.  Not range checked.
Single white space is good.
@b: Bit index into ary, LSB first. Not range checked.

> + */
> +#define        TEST_BIT(ary, b)        ((1 << ((b) & 7)) & (ary)[(b) >> 3])
> +
> +/*  Table mapping keybits[] bit positions to event codes.  */
> +/*  Note: Indices are discontinuous to aid readability.  */
Signal white space is good.
/* Table mapping keybits[] bit positions to event codes. */
/* Note: Indices are discontinuous to aid readability. */

> +static const u16 g13_keys_for_bits[] = {
> +       /*  Main keypad - keys G1 - G22  */
Ditto.

> +       [0]     = KEY_MACRO1,
> +       [1]     = KEY_MACRO2,
> +       [2]     = KEY_MACRO3,
> +       [3]     = KEY_MACRO4,
> +       [4]     = KEY_MACRO5,
> +       [5]     = KEY_MACRO6,
> +       [6]     = KEY_MACRO7,
> +       [7]     = KEY_MACRO8,
> +       [8]     = KEY_MACRO9,
> +       [9]     = KEY_MACRO10,
> +       [10]    = KEY_MACRO11,
> +       [11]    = KEY_MACRO12,
> +       [12]    = KEY_MACRO13,
> +       [13]    = KEY_MACRO14,
> +       [14]    = KEY_MACRO15,
> +       [15]    = KEY_MACRO16,
> +       [16]    = KEY_MACRO17,
> +       [17]    = KEY_MACRO18,
> +       [18]    = KEY_MACRO19,
> +       [19]    = KEY_MACRO20,
> +       [20]    = KEY_MACRO21,
> +       [21]    = KEY_MACRO22,
> +
> +       /*  LCD menu buttons.  */
> +       [24]    = KEY_KBD_LCD_MENU5,    // "Next page" button
Use C-style comments
[24] = KEY_KBD_LCD_MENU5,    /* "Next page" button */
> +       [25]    = KEY_KBD_LCD_MENU1,    // Left-most
Ditto
> +       [26]    = KEY_KBD_LCD_MENU2,
> +       [27]    = KEY_KBD_LCD_MENU3,
> +       [28]    = KEY_KBD_LCD_MENU4,    // Right-most
Ditto
> +
> +       /*  Macro preset and record buttons; have red LEDs under them.  */
Single while space is good.
/* Macro preset and record buttons; have red LEDs under them. */

> +       [29]    = KEY_MACRO_PRESET1,
> +       [30]    = KEY_MACRO_PRESET2,
> +       [31]    = KEY_MACRO_PRESET3,
> +       [32]    = KEY_MACRO_RECORD_START,
> +
> +       /*  33-35 handled by joystick device.  */
Ditto.
> +
> +       /*  Backlight toggle.  */
Ditto.

> +       [37]    = KEY_LIGHTS_TOGGLE,
Replace the tab with a white space.


> +};
> +
> +static const u16 g13_keys_for_bits_js[] = {
> +       /*  Joystick buttons  */
> +       /*  These keybits are at bit indices 33, 34, and 35.  */
Single white space is good.

> +       BTN_BASE,       // Left side
Replace the C++ comments with the C comment format /* ... */. Please
check them and replace them with C-style comments
> +       BTN_BASE2,      // Bottom side
> +       BTN_THUMB,      // Stick depress
> +};
> +
> +static int lg_g13_event(struct lg_g15_data *g15, u8 const *data)
> +{
> +       struct g13_input_report const * const rep = (struct g13_input_report *) data;
> +       int i, val;
> +       bool hw_brightness_changed;
Remove unused variable.

> +
> +       /*
> +        * Main macropad and menu keys.
> +        * Emit key events defined for each bit position.
> +        */
> +       for (i = 0;  i < ARRAY_SIZE(g13_keys_for_bits);  ++i) {
> +               if (g13_keys_for_bits[i]) {
> +                       val = TEST_BIT(rep->keybits, i);
> +                       input_report_key(g15->input, g13_keys_for_bits[i], val);
> +               }
> +       }
> +       input_sync(g15->input);
> +
> +       /*
> +        * Joystick.
> +        * Emit button and deflection events.
> +        */
> +       for (i = 0;  i < ARRAY_SIZE(g13_keys_for_bits_js);  ++i) {
> +               if (g13_keys_for_bits_js[i]) {
> +                       val = TEST_BIT(rep->keybits, i + 33);
> +                       input_report_key(g15->input_js, g13_keys_for_bits_js[i], val);
> +               }
> +       }
> +       input_report_abs(g15->input_js, ABS_X, rep->joy_x);
> +       input_report_abs(g15->input_js, ABS_Y, rep->joy_y);
> +       input_sync(g15->input_js);
> +
> +#ifdef CONFIG_LEDS_BRIGHTNESS_HW_CHANGED


> +       /*
> +        * Bit 23 of keybits[] reports the current backlight on/off state.  If
> +        * it has changed from the last cached value, apply an update.
> +        */
> +       hw_brightness_changed =
> +               (!!TEST_BIT(rep->keybits, 23)) ^ (g15->leds[0].cdev.brightness_hw_changed > 0);
> +       if (hw_brightness_changed) {
> +               led_classdev_notify_brightness_hw_changed(
> +                       &g15->leds[0].cdev,
> +                       TEST_BIT(rep->keybits, 23) ? LED_FULL : LED_OFF);
> +       }
> +#endif
> +
> +       return 0;
> +}
> +
>  /* On the G15 Mark I Logitech has been quite creative with which bit is what */
>  static void lg_g15_handle_lcd_menu_keys(struct lg_g15_data *g15, u8 *data)
>  {
> @@ -572,6 +857,10 @@ static int lg_g15_raw_event(struct hid_device *hdev, struct hid_report *report,
>                 return 0;
>
>         switch (g15->model) {
> +       case LG_G13:
> +               if (data[0] == 0x01  &&  size == sizeof(struct g13_input_report))
Separate the variable and the operator with one white space.
 if (data[0] == 0x01 && size == sizeof(struct g13_input_report))

> +                       return lg_g13_event(g15, data);
> +               break;
>         case LG_G15:
>                 if (data[0] == 0x02 && size == 9)
>                         return lg_g15_event(g15, data);
> @@ -616,13 +905,22 @@ static void lg_g15_setup_led_rgb(struct lg_g15_data *g15, int index)
>  {
>         int i;
>         struct mc_subled *subled_info;
> -
> -       g15->leds[index].mcdev.led_cdev.brightness_set_blocking =
> -               lg_g510_kbd_led_set;
> -       g15->leds[index].mcdev.led_cdev.brightness_get =
> -               lg_g510_kbd_led_get;
> -       g15->leds[index].mcdev.led_cdev.max_brightness = 255;
> -       g15->leds[index].mcdev.num_colors = 3;
> +       struct lg_g15_led * const gled = &g15->leds[index];
> +
> +       if (g15->model == LG_G13) {
> +               gled->mcdev.led_cdev.brightness_set_blocking =
> +                       lg_g13_kbd_led_set;
> +               gled->mcdev.led_cdev.brightness_get =
> +                       lg_g13_kbd_led_get;
> +               gled->mcdev.led_cdev.flags = LED_BRIGHT_HW_CHANGED;
> +       } else {
> +               gled->mcdev.led_cdev.brightness_set_blocking =
> +                       lg_g510_kbd_led_set;
> +               gled->mcdev.led_cdev.brightness_get =
> +                       lg_g510_kbd_led_get;
> +       }
> +       gled->mcdev.led_cdev.max_brightness = 255;
> +       gled->mcdev.num_colors = 3;
>
>         subled_info = devm_kcalloc(&g15->hdev->dev, 3, sizeof(*subled_info), GFP_KERNEL);
>         if (!subled_info)
> @@ -632,20 +930,20 @@ static void lg_g15_setup_led_rgb(struct lg_g15_data *g15, int index)
>                 switch (i + 1) {
>                 case LED_COLOR_ID_RED:
>                         subled_info[i].color_index = LED_COLOR_ID_RED;
> -                       subled_info[i].intensity = g15->leds[index].red;
> +                       subled_info[i].intensity = gled->red;
>                         break;
>                 case LED_COLOR_ID_GREEN:
>                         subled_info[i].color_index = LED_COLOR_ID_GREEN;
> -                       subled_info[i].intensity = g15->leds[index].green;
> +                       subled_info[i].intensity = gled->green;
>                         break;
>                 case LED_COLOR_ID_BLUE:
>                         subled_info[i].color_index = LED_COLOR_ID_BLUE;
> -                       subled_info[i].intensity = g15->leds[index].blue;
> +                       subled_info[i].intensity = gled->blue;
>                         break;
>                 }
>                 subled_info[i].channel = i;
>         }
> -       g15->leds[index].mcdev.subled_info = subled_info;
> +       gled->mcdev.subled_info = subled_info;
>  }
>
>  static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
> @@ -656,6 +954,23 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
>         g15->leds[i].cdev.name = name;
>
>         switch (g15->model) {
> +       case LG_G13:
> +               if (i < LG_G15_BRIGHTNESS_MAX) {
> +                       /*  RGB backlight.  */
Use a single while space to separate /* , text and */.

> +                       lg_g15_setup_led_rgb(g15, i);
> +                       ret = devm_led_classdev_multicolor_register_ext(&g15->hdev->dev,
> +                                                                       &g15->leds[i].mcdev,
> +                                                                       NULL);
> +               } else {
> +                       /*  Macro keys  */
Ditto.

> +                       g15->leds[i].cdev.brightness_set_blocking = lg_g13_mkey_led_set;
> +                       g15->leds[i].cdev.brightness_get          = lg_g13_mkey_led_get;
> +                       g15->leds[i].cdev.max_brightness          = 1;
No need to align the variables. Keep using one while space.

> +
> +                       ret = devm_led_classdev_register(&g15->hdev->dev,
> +                                                        &g15->leds[i].cdev);
> +               }
> +               break;
>         case LG_G15:
>         case LG_G15_V2:
>                 g15->leds[i].cdev.brightness_get = lg_g15_led_get;
> @@ -702,27 +1017,60 @@ static int lg_g15_register_led(struct lg_g15_data *g15, int i, const char *name)
>  }
>
>  /* Common input device init code shared between keyboards and Z-10 speaker handling */
> -static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
> -                                 const char *name)
> +static void lg_g15_init_input_dev_core(struct hid_device *hdev,
> +                                      struct input_dev *input,
> +                                      char const *name)
static void lg_g15_init_input_dev_core(struct hid_device *hdev, struct
input_dev *input,
                                           char const *name)

>  {
> -       int i;
> -
> -       input->name = name;
> -       input->phys = hdev->phys;
> -       input->uniq = hdev->uniq;
> +       input->name       = name;
> +       input->phys       = hdev->phys;
> +       input->uniq       = hdev->uniq;
>         input->id.bustype = hdev->bus;
>         input->id.vendor  = hdev->vendor;
>         input->id.product = hdev->product;
>         input->id.version = hdev->version;
>         input->dev.parent = &hdev->dev;
> -       input->open = lg_g15_input_open;
> -       input->close = lg_g15_input_close;
> +       input->open       = lg_g15_input_open;
> +       input->close      = lg_g15_input_close;
Don't fix the style issue.

> +}
> +
> +static void lg_g15_init_input_dev(struct hid_device *hdev, struct input_dev *input,
> +                                 const char *name)
> +{
> +       int i;
> +
> +       lg_g15_init_input_dev_core(hdev, input, name);
>
>         /* Keys below the LCD, intended for controlling a menu on the LCD */
>         for (i = 0; i < 5; i++)
>                 input_set_capability(input, EV_KEY, KEY_KBD_LCD_MENU1 + i);
>  }
>
> +static void lg_g13_init_input_dev(struct hid_device *hdev,
> +                                 struct input_dev *input, const char *name,
> +                                 struct input_dev *input_js, const char *name_js)
> +{
> +       /*  Macropad.  */
> +       lg_g15_init_input_dev_core(hdev, input, name);
> +       for (int i = 0;  i < ARRAY_SIZE(g13_keys_for_bits);  ++i) {
> +               if (g13_keys_for_bits[i]) {
> +                       input_set_capability(input, EV_KEY, g13_keys_for_bits[i]);
> +               }
Remove the brackets for the "if" statement if only one line belongs to it.

> +       }
> +
> +       /*  OBTW, we're a joystick, too...  */
> +       lg_g15_init_input_dev_core(hdev, input_js, name_js);
> +       for (int i = 0;  i < ARRAY_SIZE(g13_keys_for_bits_js);  ++i) {
> +               if (g13_keys_for_bits_js[i]) {
> +                       input_set_capability(input_js, EV_KEY, g13_keys_for_bits_js[i]);
> +               }
Remove the brackets for the "if" statement if only one line belongs to it.

> +       }
> +
> +       input_set_capability(input_js, EV_ABS, ABS_X);
> +       input_set_abs_params(input_js, ABS_X, 0, 255, 0, 0);
> +       input_set_capability(input_js, EV_ABS, ABS_Y);
> +       input_set_abs_params(input_js, ABS_Y, 0, 255, 0, 0);
> +}
> +
>  static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  {
>         static const char * const led_names[] = {
> @@ -739,7 +1087,7 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>         unsigned int connect_mask = 0;
>         bool has_ff000000 = false;
>         struct lg_g15_data *g15;
> -       struct input_dev *input;
> +       struct input_dev *input, *input_js;
>         struct hid_report *rep;
>         int ret, i, gkeys = 0;
>
> @@ -778,6 +1126,21 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>         hid_set_drvdata(hdev, (void *)g15);
>
>         switch (g15->model) {
> +       case LG_G13:
> +               /*
> +                * Some usermode libraries tend to ignore devices that don't
> +                * "look like" a joystick.  Create additional input device
> +                * dedicated as joystick.
> +                */
Nit.
Improve the comment and describe the hardware and the variable
settings below in brief.
> +               input_js = devm_input_allocate_device(&hdev->dev);
> +               if (!input_js)
> +                       return -ENOMEM;
> +               g15->input_js = input_js;
> +               input_set_drvdata(input_js, hdev);
> +
> +               connect_mask = HID_CONNECT_HIDRAW;
> +               gkeys = 25;
> +               break;
>         case LG_G15:
>                 INIT_WORK(&g15->work, lg_g15_leds_changed_work);
>                 /*
> @@ -859,6 +1222,34 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>                         goto error_hw_stop;
>
>                 return 0; /* All done */
> +       } else if (g15->model == LG_G13) {
> +               static char const * const g13_led_names[] = {
> +                       /*  Backlight is shared between LCD and keys.  */
Replace double white space with single white space.

> +                       "g13:rgb:kbd_backlight",
> +                       NULL,   // Keep in sync with led_type enum
Replace the C++ comments with C comments.
> +                       "g13:red:macro_preset_1",
> +                       "g13:red:macro_preset_2",
> +                       "g13:red:macro_preset_3",
> +                       "g13:red:macro_record",
> +               };
> +               lg_g13_init_input_dev(hdev,
> +                                     input,    "Logitech G13 Gaming Keypad",
> +                                     input_js, "Logitech G13 Thumbstick");
No need to align the parameters in a function call.

> +               ret = input_register_device(input);
> +               if (ret)
> +                       goto error_hw_stop;
> +               ret = input_register_device(input_js);
> +               if (ret)
> +                       goto error_hw_stop;
> +
> +               for (i = 0;  i < ARRAY_SIZE(g13_led_names);  ++i) {
> +                       if (g13_led_names[i]) {
> +                               ret = lg_g15_register_led(g15, i, g13_led_names[i]);
> +                               if (ret)
> +                                       goto error_hw_stop;
> +                       }
> +               }
> +               return 0;
>         }
>
>         /* Setup and register input device */
> @@ -903,6 +1294,13 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
>  }
>
>  static const struct hid_device_id lg_g15_devices[] = {
> +       /*
> +        * The G13 is a macropad-only device with an LCD, LED backlighing,
> +        * and joystick.
> +        */
> +       { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
> +                        USB_DEVICE_ID_LOGITECH_G13),
> +               .driver_data = LG_G13 },
>         /* The G11 is a G15 without the LCD, treat it as a G15 */
>         { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
>                 USB_DEVICE_ID_LOGITECH_G11),
> --
> 2.50.1
>

Some style and comment style issues are pointed out, and I'll start to
test this work after I receive my G13.

-- 
BR,
Kate


^ permalink raw reply

* 答复: [External Mail]Re: [PATCH v2 2/2] HID: input: report battery status changes immediately
From: 卢国宏 @ 2025-08-14  9:30 UTC (permalink / raw)
  To: Jiri Kosina, José Expósito
  Cc: bentiss@kernel.org, linux-input@vger.kernel.org,
	linux-kernel@vger.kernel.org, Fei1 Jiang 蒋飞,
	tkjos@google.com
In-Reply-To: <6c923b9403bb45988f211cae45e4f748@xiaomi.com>


Hello, José and Jiri!
When will this HID patch be merged into the Linux mainline? We are looking forward to using this feature, so please help us push it forward! Thank you very much!

________________________________________
发件人: 卢国宏
发送时间: 2025年8月12日 8:44
收件人: Jiri Kosina; José Expósito
抄送: bentiss@kernel.org; linux-input@vger.kernel.org; linux-kernel@vger.kernel.org; Fei1 Jiang 蒋飞; 卢国宏
主题: 答复: [External Mail]Re: [PATCH v2 2/2] HID: input: report battery status changes immediately

Hello, Jiri!

Nowadays, there are more and more HID devices connected to Android and Linux devices. For example, we have already reached the third generation of controllers, a HID device. In each generation, we need to report the charging status of the controller, a HID device, to the Android phone. Only then can the phone know the charging status of the HID device. Based on this charging status, the phone can determine the PD fast charging logic and how to proceed. In addition to us, other mobile phone manufacturers, such as VIVO, have also made several generations of controllers. We also encountered this practical problem in the process of making the controller, so we raised this issue with you. Our solution is also based on the HID protocol. Thank you!


________________________________
发件人: Jiri Kosina <jikos@kernel.org>
发送时间: 2025年8月11日 19:48
收件人: José Expósito
抄送: bentiss@kernel.org; 卢国宏; linux-input@vger.kernel.org; linux-kernel@vger.kernel.org
主题: [External Mail]Re: [PATCH v2 2/2] HID: input: report battery status changes immediately

[外部邮件] 此邮件来源于小米公司外部,请谨慎处理。若对邮件安全性存疑,请将邮件转发给misec@xiaomi.com进行反馈

On Wed, 6 Aug 2025, José Expósito wrote:

> When the battery status changes, report the change immediately to user
> space.

Could you please make the changelog a little bit more elaborative, i.e.
why is it needed, what user-visible behavior change/improvement it brings,
etc.

I know it's in the e-mail thread, but at least some summary should go also
to the commit itself.

Thanks,

--
Jiri Kosina
SUSE Labs

#/******本邮件及其附件含有小米公司的保密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制、或散发)本邮件中的信息。如果您错收了本邮件,请您立即电话或邮件通知发件人并删除本邮件! This e-mail and its attachments contain confidential information from XIAOMI, which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction, or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this e-mail in error, please notify the sender by phone or email immediately and delete it!******/#

^ permalink raw reply

* [PATCH v3 1/2] HID: input: rename hidinput_set_battery_charge_status()
From: José Expósito @ 2025-08-14 10:39 UTC (permalink / raw)
  To: jikos
  Cc: bentiss, luguohong, linux-input, linux-kernel,
	José Expósito

In preparation for a patch fixing a bug affecting
hidinput_set_battery_charge_status(), rename the function to
hidinput_update_battery_charge_status() and move it up so it can be used
by hidinput_update_battery().

Refactor, no functional changes.

Tested-by: 卢国宏 <luguohong@xiaomi.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>

---

v3:

 - Improved commit message
 - Link to v2: https://lore.kernel.org/linux-input/20250806073944.5310-1-jose.exposito89@gmail.com/

v2:

 - Added Tested-by: 卢国宏 <luguohong@xiaomi.com>
 - Fixed compile warning:
   https://lore.kernel.org/linux-input/202508042305.PBym6Evd-lkp@intel.com/
 - Link to v1: https://lore.kernel.org/linux-input/20250804091215.6637-1-jose.exposito89@gmail.com/
---
 drivers/hid/hid-input-test.c | 10 +++++-----
 drivers/hid/hid-input.c      | 38 ++++++++++++++++++------------------
 2 files changed, 24 insertions(+), 24 deletions(-)

diff --git a/drivers/hid/hid-input-test.c b/drivers/hid/hid-input-test.c
index 77c2d45ac62a..6f5c71660d82 100644
--- a/drivers/hid/hid-input-test.c
+++ b/drivers/hid/hid-input-test.c
@@ -7,7 +7,7 @@
 
 #include <kunit/test.h>
 
-static void hid_test_input_set_battery_charge_status(struct kunit *test)
+static void hid_test_input_update_battery_charge_status(struct kunit *test)
 {
 	struct hid_device *dev;
 	bool handled;
@@ -15,15 +15,15 @@ static void hid_test_input_set_battery_charge_status(struct kunit *test)
 	dev = kunit_kzalloc(test, sizeof(*dev), GFP_KERNEL);
 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
 
-	handled = hidinput_set_battery_charge_status(dev, HID_DG_HEIGHT, 0);
+	handled = hidinput_update_battery_charge_status(dev, HID_DG_HEIGHT, 0);
 	KUNIT_EXPECT_FALSE(test, handled);
 	KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_UNKNOWN);
 
-	handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 0);
+	handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 0);
 	KUNIT_EXPECT_TRUE(test, handled);
 	KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_DISCHARGING);
 
-	handled = hidinput_set_battery_charge_status(dev, HID_BAT_CHARGING, 1);
+	handled = hidinput_update_battery_charge_status(dev, HID_BAT_CHARGING, 1);
 	KUNIT_EXPECT_TRUE(test, handled);
 	KUNIT_EXPECT_EQ(test, dev->battery_charge_status, POWER_SUPPLY_STATUS_CHARGING);
 }
@@ -63,7 +63,7 @@ static void hid_test_input_get_battery_property(struct kunit *test)
 }
 
 static struct kunit_case hid_input_tests[] = {
-	KUNIT_CASE(hid_test_input_set_battery_charge_status),
+	KUNIT_CASE(hid_test_input_update_battery_charge_status),
 	KUNIT_CASE(hid_test_input_get_battery_property),
 	{ }
 };
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index ff1784b5c2a4..262787e6eb20 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -595,6 +595,20 @@ static void hidinput_cleanup_battery(struct hid_device *dev)
 	dev->battery = NULL;
 }
 
+static bool hidinput_update_battery_charge_status(struct hid_device *dev,
+						  unsigned int usage, int value)
+{
+	switch (usage) {
+	case HID_BAT_CHARGING:
+		dev->battery_charge_status = value ?
+					     POWER_SUPPLY_STATUS_CHARGING :
+					     POWER_SUPPLY_STATUS_DISCHARGING;
+		return true;
+	}
+
+	return false;
+}
+
 static void hidinput_update_battery(struct hid_device *dev, int value)
 {
 	int capacity;
@@ -617,20 +631,6 @@ static void hidinput_update_battery(struct hid_device *dev, int value)
 		power_supply_changed(dev->battery);
 	}
 }
-
-static bool hidinput_set_battery_charge_status(struct hid_device *dev,
-					       unsigned int usage, int value)
-{
-	switch (usage) {
-	case HID_BAT_CHARGING:
-		dev->battery_charge_status = value ?
-					     POWER_SUPPLY_STATUS_CHARGING :
-					     POWER_SUPPLY_STATUS_DISCHARGING;
-		return true;
-	}
-
-	return false;
-}
 #else  /* !CONFIG_HID_BATTERY_STRENGTH */
 static int hidinput_setup_battery(struct hid_device *dev, unsigned report_type,
 				  struct hid_field *field, bool is_percentage)
@@ -642,14 +642,14 @@ static void hidinput_cleanup_battery(struct hid_device *dev)
 {
 }
 
-static void hidinput_update_battery(struct hid_device *dev, int value)
+static bool hidinput_update_battery_charge_status(struct hid_device *dev,
+						  unsigned int usage, int value)
 {
+	return false;
 }
 
-static bool hidinput_set_battery_charge_status(struct hid_device *dev,
-					       unsigned int usage, int value)
+static void hidinput_update_battery(struct hid_device *dev, int value)
 {
-	return false;
 }
 #endif	/* CONFIG_HID_BATTERY_STRENGTH */
 
@@ -1515,7 +1515,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
 		return;
 
 	if (usage->type == EV_PWR) {
-		bool handled = hidinput_set_battery_charge_status(hid, usage->hid, value);
+		bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value);
 
 		if (!handled)
 			hidinput_update_battery(hid, value);
-- 
2.50.1


^ permalink raw reply related

* [PATCH v3 2/2] HID: input: report battery status changes immediately
From: José Expósito @ 2025-08-14 10:39 UTC (permalink / raw)
  To: jikos
  Cc: bentiss, luguohong, linux-input, linux-kernel,
	José Expósito
In-Reply-To: <20250814103947.116139-1-jose.exposito89@gmail.com>

Previously, the battery status (charging/discharging) was not reported
immediately to user-space. 

For most input devices, this wasn't problematic because changing their
battery status requires connecting them to a different bus.
For example, a gamepad would report a discharging status while
connected via Bluetooth and a charging status while connected via USB.

However, certain devices are not connected or disconnected when their
battery status changes. For example, a phone battery changes its status
without connecting or disconnecting it.
In these cases, the battery status was not reported immediately to user
space.

Report battery status changes immediately to user space to support
these kinds of devices.

Fixes: a608dc1c0639 ("HID: input: map battery system charging")
Reported-by: 卢国宏 <luguohong@xiaomi.com>
Closes: https://lore.kernel.org/linux-input/aI49Im0sGb6fpgc8@fedora/T/
Tested-by: 卢国宏 <luguohong@xiaomi.com>
Signed-off-by: José Expósito <jose.exposito89@gmail.com>
---
 drivers/hid/hid-input.c | 23 ++++++++++-------------
 1 file changed, 10 insertions(+), 13 deletions(-)

diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 262787e6eb20..f45f856a127f 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -609,13 +609,19 @@ static bool hidinput_update_battery_charge_status(struct hid_device *dev,
 	return false;
 }
 
-static void hidinput_update_battery(struct hid_device *dev, int value)
+static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
+				    int value)
 {
 	int capacity;
 
 	if (!dev->battery)
 		return;
 
+	if (hidinput_update_battery_charge_status(dev, usage, value)) {
+		power_supply_changed(dev->battery);
+		return;
+	}
+
 	if (value == 0 || value < dev->battery_min || value > dev->battery_max)
 		return;
 
@@ -642,13 +648,8 @@ static void hidinput_cleanup_battery(struct hid_device *dev)
 {
 }
 
-static bool hidinput_update_battery_charge_status(struct hid_device *dev,
-						  unsigned int usage, int value)
-{
-	return false;
-}
-
-static void hidinput_update_battery(struct hid_device *dev, int value)
+static void hidinput_update_battery(struct hid_device *dev, unsigned int usage,
+				    int value)
 {
 }
 #endif	/* CONFIG_HID_BATTERY_STRENGTH */
@@ -1515,11 +1516,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
 		return;
 
 	if (usage->type == EV_PWR) {
-		bool handled = hidinput_update_battery_charge_status(hid, usage->hid, value);
-
-		if (!handled)
-			hidinput_update_battery(hid, value);
-
+		hidinput_update_battery(hid, usage->hid, value);
 		return;
 	}
 
-- 
2.50.1


^ permalink raw reply related

* Re: [PATCH v2 2/2] HID: input: report battery status changes immediately
From: José Expósito @ 2025-08-14 10:43 UTC (permalink / raw)
  To: Jiri Kosina; +Cc: bentiss, luguohong, linux-input, linux-kernel
In-Reply-To: <4q4qn3p8-6s3s-289n-44s2-43s76qrs2oo4@xreary.bet>

Hi Jiri,

On Mon, Aug 11, 2025 at 01:48:22PM +0200, Jiri Kosina wrote:
> On Wed, 6 Aug 2025, José Expósito wrote:
> 
> > When the battery status changes, report the change immediately to user
> > space.
> 
> Could you please make the changelog a little bit more elaborative, i.e. 
> why is it needed, what user-visible behavior change/improvement it brings, 
> etc.
> 
> I know it's in the e-mail thread, but at least some summary should go also 
> to the commit itself.

Thanks a lot for reviewing these patches.

I sent v3 with a more detailed description of the fix:
https://lore.kernel.org/linux-input/20250814103947.116139-1-jose.exposito89@gmail.com/

Jose

> Thanks,
> 
> -- 
> Jiri Kosina
> SUSE Labs
> 

^ permalink raw reply

* Re: (subset) [PATCH 00/21] treewide: remove unneeded 'fast_io' parameter in regmap_config
From: Mark Brown @ 2025-08-14 11:13 UTC (permalink / raw)
  To: linux-kernel, Wolfram Sang
  Cc: Adrian Hunter, Alexandre Belloni, Alexandre Torgue, Alim Akhtar,
	Andrea della Porta, Andreas Färber, Andrzej Hajda,
	Andy Shevchenko, Andy Yan, Avi Fishman, Bartosz Golaszewski,
	Benjamin Fair, Bjorn Andersson, Chen-Yu Tsai, Daniel Lezcano,
	David Airlie, David Lechner, Dmitry Torokhov, Drew Fustini,
	dri-devel, Fabio Estevam, Fabrice Gasnier, Fu Wei, Guo Ren,
	Hans Verkuil, Heiko Stübner, imx, Iwona Winiarska,
	Jaroslav Kysela, Jassi Brar, Jernej Skrabec, Jerome Brunet,
	Jonas Karlman, Jonathan Cameron, Kevin Hilman,
	Kishon Vijay Abraham I, Konrad Dybcio, Krzysztof Kozlowski,
	Laurent Pinchart, Lee Jones, Liam Girdwood, Linus Walleij,
	linux-actions, linux-amlogic, linux-arm-kernel, linux-arm-msm,
	linux-clk, linux-gpio, linux-iio, linux-input, linux-media,
	linux-mmc, linux-phy, linux-pm, linuxppc-dev, linux-pwm,
	linux-riscv, linux-rockchip, linux-rtc, linux-samsung-soc,
	linux-sound, linux-spi, linux-stm32, linux-sunxi, Liu Ying,
	Lukasz Luba, Maarten Lankhorst, Manivannan Sadhasivam,
	Martin Blumenstingl, Mauro Carvalho Chehab, Maxime Coquelin,
	Maxime Ripard, Michael Turquette, Miquel Raynal, Nancy Yuen,
	Neil Armstrong, Nicolin Chen, Nuno Sá, openbmc,
	Patrick Venture, Paul Walmsley, Pengutronix Kernel Team,
	Philipp Zabel, Piotr Wojtaszczyk, Rafael J. Wysocki, Robert Foss,
	Samuel Holland, Samuel Holland, Sandy Huang, Sascha Hauer,
	Shawn Guo, Shengjiu Wang, Simona Vetter, Stephen Boyd,
	Takashi Iwai, Tali Perry, Thomas Zimmermann, Tomer Maimon,
	Ulf Hansson, Uwe Kleine-König, Vasily Khoruzhick, Vinod Koul,
	Vladimir Zapolskiy, Xiubo Li, Yangtao Li, Zhang Rui
In-Reply-To: <20250813161517.4746-1-wsa+renesas@sang-engineering.com>

On Wed, 13 Aug 2025 18:14:46 +0200, Wolfram Sang wrote:
> While working on a driver using regmap with MMIO, I wondered if I need
> to set 'fast_io' in the config. Turned out I don't need to, so I added
> documentation for it with commit ffc72771ff6e ("regmap: Annotate that
> MMIO implies fast IO").
> 
> This series fixes the existing users in the tree which needlessly set
> the flag. They have been found using this coccinelle script:
> 
> [...]

Applied to

   https://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi.git for-next

Thanks!

[19/21] spi: remove unneeded 'fast_io' parameter in regmap_config
        commit: 48124569bbc6bfda1df3e9ee17b19d559f4b1aa3

All being well this means that it will be integrated into the linux-next
tree (usually sometime in the next 24 hours) and sent to Linus during
the next merge window (or sooner if it is a bug fix), however if
problems are discovered then the patch may be dropped or reverted.

You may get further e-mails resulting from automated or manual testing
and review of the tree, please engage with people reporting problems and
send followup patches addressing any issues that are reported if needed.

If any updates are required or you are submitting further changes they
should be sent as incremental updates against current git, existing
patches will not be replaced.

Please add any relevant lists and maintainers to the CCs when replying
to this mail.

Thanks,
Mark


^ permalink raw reply

* Re: [syzbot] [input?] [usb?] [io-uring?] INFO: task hung in io_wq_put_and_exit (5)
From: Aleksandr Nogikh @ 2025-08-14 12:04 UTC (permalink / raw)
  To: Jens Axboe
  Cc: syzbot, io-uring, linux-input, linux-kernel, linux-usb,
	syzkaller-bugs
In-Reply-To: <4a32f6c1-8d81-4a51-beed-caf8bc52fcc2@kernel.dk>

Hi Jens,

On Wed, Aug 13, 2025 at 4:32 PM Jens Axboe <axboe@kernel.dk> wrote:
>
> On Wed, Jul 23, 2025 at 8:44?AM syzbot <syzbot+e328767eafd849df0a78@syzkaller.appspotmail.com> wrote:
> >
> > Hello,
> >
> > syzbot found the following issue on:
> >
> > HEAD commit:    bf61759db409 Merge tag 'sched_ext-for-6.16-rc6-fixes' of g..
> > git tree:       upstream
> > console+strace: https://syzkaller.appspot.com/x/log.txt?x=12b877d4580000
> > kernel config:  https://syzkaller.appspot.com/x/.config?x=415e83411fefd73f
> > dashboard link: https://syzkaller.appspot.com/bug?extid=e328767eafd849df0a78
> > compiler:       gcc (Debian 12.2.0-14+deb12u1) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
> > syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=110b938c580000
> > C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=1622a38c580000
> >
> > Downloadable assets:
> > disk image: https://storage.googleapis.com/syzbot-assets/22c5f1286a72/disk-bf61759d.raw.xz
> > vmlinux: https://storage.googleapis.com/syzbot-assets/cc79af4d966c/vmlinux-bf61759d.xz
> > kernel image: https://storage.googleapis.com/syzbot-assets/b2e6d621f424/bzImage-bf61759d.xz
> >
> > The issue was bisected to:
> >
> > commit e5598d6ae62626d261b046a2f19347c38681ff51
> > Author: Pavel Begunkov <asml.silence@gmail.com>
> > Date:   Thu Aug 24 22:53:31 2023 +0000
> >
> >     io_uring: compact SQ/CQ heads/tails
> >
> > bisection log:  https://syzkaller.appspot.com/x/bisect.txt?x=12c92b82580000
> > final oops:     https://syzkaller.appspot.com/x/report.txt?x=11c92b82580000
> > console output: https://syzkaller.appspot.com/x/log.txt?x=16c92b82580000
> >
> > IMPORTANT: if you fix the issue, please add the following tag to the commit:
> > Reported-by: syzbot+e328767eafd849df0a78@syzkaller.appspotmail.com
> > Fixes: e5598d6ae626 ("io_uring: compact SQ/CQ heads/tails")
> >
> > INFO: task syz-executor971:5849 blocked for more than 143 seconds.
> >       Not tainted 6.16.0-rc6-syzkaller-00279-gbf61759db409 #0
> >       Blocked by coredump.
> > "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
> > task:syz-executor971 state:D stack:26488 pid:5849  tgid:5849  ppid:5844   task_flags:0x400148 flags:0x00024002
> > Call Trace:
> >  <TASK>
> >  context_switch kernel/sched/core.c:5397 [inline]
> >  __schedule+0x116a/0x5de0 kernel/sched/core.c:6786
> >  __schedule_loop kernel/sched/core.c:6864 [inline]
> >  schedule+0xe7/0x3a0 kernel/sched/core.c:6879
> >  schedule_timeout+0x257/0x290 kernel/time/sleep_timeout.c:75
> >  do_wait_for_common kernel/sched/completion.c:95 [inline]
> >  __wait_for_common+0x2ff/0x4e0 kernel/sched/completion.c:116
> >  io_wq_exit_workers io_uring/io-wq.c:1319 [inline]
> >  io_wq_put_and_exit+0x271/0x8d0 io_uring/io-wq.c:1347
> >  io_uring_clean_tctx+0x10d/0x190 io_uring/tctx.c:203
> >  io_uring_cancel_generic+0x69c/0x9a0 io_uring/io_uring.c:3212
> >  io_uring_files_cancel include/linux/io_uring.h:19 [inline]
> >  do_exit+0x2ce/0x2bd0 kernel/exit.c:911
> >  do_group_exit+0xd3/0x2a0 kernel/exit.c:1105
> >  __do_sys_exit_group kernel/exit.c:1116 [inline]
> >  __se_sys_exit_group kernel/exit.c:1114 [inline]
> >  __x64_sys_exit_group+0x3e/0x50 kernel/exit.c:1114
> >  x64_sys_call+0x1530/0x1730 arch/x86/include/generated/asm/syscalls_64.h:232
> >  do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
> >  do_syscall_64+0xcd/0x4c0 arch/x86/entry/syscall_64.c:94
> >  entry_SYSCALL_64_after_hwframe+0x77/0x7f
> > RIP: 0033:0x7f141ec08e39
> > RSP: 002b:00007ffcd1b0b6e8 EFLAGS: 00000246 ORIG_RAX: 00000000000000e7
> > RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f141ec08e39
> > RDX: 000000000000003c RSI: 00000000000000e7 RDI: 0000000000000000
> > RBP: 00007f141ec843b0 R08: ffffffffffffffb8 R09: 0000000000000000
> > R10: 000000000000000e R11: 0000000000000246 R12: 00007f141ec843b0
> > R13: 0000000000000000 R14: 00007f141ec880c0 R15: 00007f141ebd7020
> >  </TASK>
> > INFO: task syz-executor971:5850 blocked for more than 143 seconds.
> >       Not tainted 6.16.0-rc6-syzkaller-00279-gbf61759db409 #0
> >       Blocked by coredump.
>
> I took a look at this one, and it's simply waiting on nullb0 timeouts
> that it's flooded the queue with. Since it's flooding the nullb0 device
> which has been configured to time out IO, we'll have a lot of io-wq
> workers that are sitting blocked waiting on making progress. That can
> obviously take a long time, which then in turn triggers the io_uring
> cancelation/exit warning because of that. It all seems to be working as
> it should.
>
> I don't think there's a bug here because of that, the only thing that's
> "stuck" is because each timeout takes 30s to trigger and there are tons
> of them.
>
> #syz invalid

FWIW: if the bug is weird, but syzbot keeps on observing the crashes,
it's better to let it stay open than to close it with "syz invalid".
In this case, syzbot will just reopen the bug as "INFO: task hung in
io_wq_put_and_exit (6)", "INFO: task hung in io_wq_put_and_exit (7)",
and so on.

-- 
Aleksandr

>
> --
> Jens Axboe
>

^ permalink raw reply

* [dtor-input:next] BUILD SUCCESS WITH WARNING 9549ff7e584694f0605bc7955b90073041580b24
From: kernel test robot @ 2025-08-14 12:13 UTC (permalink / raw)
  To: Dmitry Torokhov; +Cc: linux-input

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/dtor/input.git next
branch HEAD: 9549ff7e584694f0605bc7955b90073041580b24  Input: remove unneeded 'fast_io' parameter in regmap_config

Warning (recently discovered and may have been fixed):

    https://lore.kernel.org/oe-kbuild-all/202508041754.ykl25o1q-lkp@intel.com

    drivers/input/touch-overlay.c: warning: EXPORT_SYMBOL() is used, but #include <linux/export.h> is missing

Warning ids grouped by kconfigs:

recent_errors
|-- alpha-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- alpha-allyesconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arc-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arc-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arc-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arm-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arm-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arm-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arm-randconfig-003-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- arm64-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- csky-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- csky-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- csky-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- hexagon-allmodconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- hexagon-allyesconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- hexagon-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- hexagon-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- i386-buildonly-randconfig-006-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- loongarch-allmodconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- loongarch-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- m68k-allmodconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- m68k-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- m68k-allyesconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- microblaze-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- microblaze-allyesconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- microblaze-defconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- mips-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- nios2-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- nios2-defconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- openrisc-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- parisc-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- parisc-defconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- parisc64-defconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- powerpc-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- powerpc-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- powerpc64-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- powerpc64-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- riscv-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- riscv-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- s390-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- s390-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- s390-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- sh-allnoconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- sh-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- sparc-defconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- um-allmodconfig
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- um-randconfig-001-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
|-- um-randconfig-002-20250814
|   `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing
`-- xtensa-randconfig-001-20250814
    `-- drivers-input-touch-overlay.c:warning:EXPORT_SYMBOL()-is-used-but-include-linux-export.h-is-missing

elapsed time: 853m

configs tested: 208
configs skipped: 4

tested configs:
alpha                             allnoconfig    gcc-15.1.0
alpha                            allyesconfig    clang-19
alpha                            allyesconfig    gcc-15.1.0
arc                              alldefconfig    clang-22
arc                              allmodconfig    clang-19
arc                               allnoconfig    gcc-15.1.0
arc                              allyesconfig    clang-19
arc                        nsimosci_defconfig    clang-22
arc                   randconfig-001-20250814    gcc-10.5.0
arc                   randconfig-001-20250814    gcc-12.5.0
arc                   randconfig-002-20250814    gcc-10.5.0
arc                   randconfig-002-20250814    gcc-13.4.0
arc                           tb10x_defconfig    clang-22
arm                              allmodconfig    clang-19
arm                               allnoconfig    clang-22
arm                              allyesconfig    clang-19
arm                       multi_v4t_defconfig    clang-22
arm                        mvebu_v7_defconfig    clang-22
arm                   randconfig-001-20250814    clang-22
arm                   randconfig-001-20250814    gcc-10.5.0
arm                   randconfig-002-20250814    clang-22
arm                   randconfig-002-20250814    gcc-10.5.0
arm                   randconfig-003-20250814    gcc-10.5.0
arm                   randconfig-004-20250814    gcc-10.5.0
arm                   randconfig-004-20250814    gcc-8.5.0
arm                         s3c6400_defconfig    clang-22
arm                        spear3xx_defconfig    clang-22
arm64                            allmodconfig    clang-19
arm64                             allnoconfig    gcc-15.1.0
arm64                 randconfig-001-20250814    clang-17
arm64                 randconfig-001-20250814    gcc-10.5.0
arm64                 randconfig-002-20250814    gcc-10.5.0
arm64                 randconfig-002-20250814    gcc-8.5.0
arm64                 randconfig-003-20250814    gcc-10.5.0
arm64                 randconfig-004-20250814    gcc-10.5.0
arm64                 randconfig-004-20250814    gcc-13.4.0
csky                              allnoconfig    gcc-15.1.0
csky                  randconfig-001-20250814    gcc-10.5.0
csky                  randconfig-001-20250814    gcc-15.1.0
csky                  randconfig-002-20250814    gcc-10.5.0
csky                  randconfig-002-20250814    gcc-15.1.0
hexagon                          allmodconfig    clang-17
hexagon                          allmodconfig    clang-19
hexagon                           allnoconfig    clang-22
hexagon                          allyesconfig    clang-19
hexagon                          allyesconfig    clang-22
hexagon               randconfig-001-20250814    clang-20
hexagon               randconfig-001-20250814    gcc-10.5.0
hexagon               randconfig-002-20250814    clang-22
hexagon               randconfig-002-20250814    gcc-10.5.0
i386                             allmodconfig    clang-20
i386                              allnoconfig    clang-20
i386                             allyesconfig    clang-20
i386        buildonly-randconfig-001-20250814    clang-20
i386        buildonly-randconfig-002-20250814    clang-20
i386        buildonly-randconfig-002-20250814    gcc-12
i386        buildonly-randconfig-003-20250814    clang-20
i386        buildonly-randconfig-003-20250814    gcc-12
i386        buildonly-randconfig-004-20250814    clang-20
i386        buildonly-randconfig-005-20250814    clang-20
i386        buildonly-randconfig-005-20250814    gcc-12
i386        buildonly-randconfig-006-20250814    clang-20
i386        buildonly-randconfig-006-20250814    gcc-12
i386                                defconfig    clang-20
i386                  randconfig-001-20250814    clang-20
i386                  randconfig-002-20250814    clang-20
i386                  randconfig-003-20250814    clang-20
i386                  randconfig-004-20250814    clang-20
i386                  randconfig-005-20250814    clang-20
i386                  randconfig-006-20250814    clang-20
i386                  randconfig-007-20250814    clang-20
i386                  randconfig-011-20250814    gcc-12
i386                  randconfig-012-20250814    gcc-12
i386                  randconfig-013-20250814    gcc-12
i386                  randconfig-014-20250814    gcc-12
i386                  randconfig-015-20250814    gcc-12
i386                  randconfig-016-20250814    gcc-12
i386                  randconfig-017-20250814    gcc-12
loongarch                        allmodconfig    clang-19
loongarch                         allnoconfig    clang-22
loongarch             randconfig-001-20250814    clang-22
loongarch             randconfig-001-20250814    gcc-10.5.0
loongarch             randconfig-002-20250814    gcc-10.5.0
loongarch             randconfig-002-20250814    gcc-15.1.0
m68k                             allmodconfig    clang-19
m68k                             allmodconfig    gcc-15.1.0
m68k                              allnoconfig    gcc-15.1.0
m68k                             allyesconfig    clang-19
m68k                             allyesconfig    gcc-15.1.0
microblaze                       allmodconfig    clang-19
microblaze                       allmodconfig    gcc-15.1.0
microblaze                        allnoconfig    gcc-15.1.0
microblaze                       allyesconfig    clang-19
microblaze                       allyesconfig    gcc-15.1.0
microblaze                          defconfig    gcc-15.1.0
mips                              allnoconfig    gcc-15.1.0
nios2                             allnoconfig    gcc-11.5.0
nios2                             allnoconfig    gcc-15.1.0
nios2                               defconfig    gcc-11.5.0
nios2                               defconfig    gcc-15.1.0
nios2                 randconfig-001-20250814    gcc-10.5.0
nios2                 randconfig-002-20250814    gcc-10.5.0
nios2                 randconfig-002-20250814    gcc-9.5.0
openrisc                          allnoconfig    clang-22
openrisc                          allnoconfig    gcc-15.1.0
openrisc                         allyesconfig    gcc-15.1.0
openrisc                            defconfig    gcc-12
parisc                           allmodconfig    gcc-15.1.0
parisc                            allnoconfig    clang-22
parisc                            allnoconfig    gcc-15.1.0
parisc                           allyesconfig    gcc-15.1.0
parisc                              defconfig    gcc-15.1.0
parisc                randconfig-001-20250814    gcc-10.5.0
parisc                randconfig-002-20250814    gcc-10.5.0
parisc                randconfig-002-20250814    gcc-13.4.0
parisc64                            defconfig    gcc-15.1.0
powerpc                          allmodconfig    gcc-15.1.0
powerpc                           allnoconfig    clang-22
powerpc                           allnoconfig    gcc-15.1.0
powerpc                          allyesconfig    gcc-15.1.0
powerpc                      ppc44x_defconfig    clang-22
powerpc               randconfig-001-20250814    gcc-10.5.0
powerpc               randconfig-001-20250814    gcc-8.5.0
powerpc               randconfig-002-20250814    gcc-10.5.0
powerpc               randconfig-002-20250814    gcc-8.5.0
powerpc               randconfig-003-20250814    gcc-10.5.0
powerpc64             randconfig-001-20250814    clang-22
powerpc64             randconfig-001-20250814    gcc-10.5.0
powerpc64             randconfig-002-20250814    clang-22
powerpc64             randconfig-002-20250814    gcc-10.5.0
powerpc64             randconfig-003-20250814    clang-22
powerpc64             randconfig-003-20250814    gcc-10.5.0
riscv                            allmodconfig    gcc-15.1.0
riscv                             allnoconfig    clang-22
riscv                             allnoconfig    gcc-15.1.0
riscv                            allyesconfig    gcc-15.1.0
riscv                               defconfig    gcc-12
riscv                 randconfig-001-20250814    clang-22
riscv                 randconfig-002-20250814    clang-22
s390                             allmodconfig    clang-18
s390                             allmodconfig    gcc-15.1.0
s390                              allnoconfig    clang-22
s390                             allyesconfig    gcc-15.1.0
s390                                defconfig    gcc-12
s390                  randconfig-001-20250814    clang-22
s390                  randconfig-002-20250814    clang-22
s390                  randconfig-002-20250814    gcc-8.5.0
sh                               allmodconfig    gcc-15.1.0
sh                                allnoconfig    gcc-15.1.0
sh                               allyesconfig    gcc-15.1.0
sh                                  defconfig    gcc-12
sh                    randconfig-001-20250814    clang-22
sh                    randconfig-001-20250814    gcc-9.5.0
sh                    randconfig-002-20250814    clang-22
sh                    randconfig-002-20250814    gcc-15.1.0
sparc                            allmodconfig    gcc-15.1.0
sparc                             allnoconfig    gcc-15.1.0
sparc                               defconfig    gcc-15.1.0
sparc                 randconfig-001-20250814    clang-22
sparc                 randconfig-001-20250814    gcc-14.3.0
sparc                 randconfig-002-20250814    clang-22
sparc                 randconfig-002-20250814    gcc-12.5.0
sparc64                             defconfig    gcc-12
sparc64               randconfig-001-20250814    clang-22
sparc64               randconfig-002-20250814    clang-22
sparc64               randconfig-002-20250814    gcc-8.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-22
um                               allyesconfig    clang-19
um                               allyesconfig    gcc-12
um                                  defconfig    gcc-12
um                             i386_defconfig    gcc-12
um                    randconfig-001-20250814    clang-22
um                    randconfig-002-20250814    clang-22
um                           x86_64_defconfig    gcc-12
x86_64                            allnoconfig    clang-20
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20250814    clang-20
x86_64      buildonly-randconfig-002-20250814    clang-20
x86_64      buildonly-randconfig-003-20250814    clang-20
x86_64      buildonly-randconfig-003-20250814    gcc-12
x86_64      buildonly-randconfig-004-20250814    clang-20
x86_64      buildonly-randconfig-005-20250814    clang-20
x86_64      buildonly-randconfig-005-20250814    gcc-12
x86_64      buildonly-randconfig-006-20250814    clang-20
x86_64      buildonly-randconfig-006-20250814    gcc-12
x86_64                              defconfig    clang-20
x86_64                                  kexec    clang-20
x86_64                randconfig-001-20250814    clang-20
x86_64                randconfig-002-20250814    clang-20
x86_64                randconfig-003-20250814    clang-20
x86_64                randconfig-004-20250814    gcc-12
x86_64                randconfig-005-20250814    clang-20
x86_64                randconfig-006-20250814    clang-20
x86_64                randconfig-007-20250814    gcc-12
x86_64                randconfig-008-20250814    clang-20
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-12
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-12
x86_64                           rhel-9.4-ltp    gcc-12
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    gcc-15.1.0
xtensa                randconfig-001-20250814    clang-22
xtensa                randconfig-001-20250814    gcc-8.5.0
xtensa                randconfig-002-20250814    clang-22
xtensa                randconfig-002-20250814    gcc-10.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox