From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 29EC92356B3; Mon, 31 Mar 2025 14:55:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1743432923; cv=none; b=dQZIT37zZEsgTtXf27L54Hu3pqjMiGbJeI72u/t197NWKPct82+dm/mOi4GhkaVP72V8PK3bPql2Qa9SMghcN046tC4OsjfR2OVbwsJa3DIZELb2JBI+WhQ+UcIFT6pzDEYoNAz+HDF5D2Jm0ihzfbUVkOTbuZelZBXr5ygZbCo= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1743432923; c=relaxed/simple; bh=+mvX5ZClEaPPTurFdhdHay7X2Gx4/MpbXaA0uzY6M5U=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=N082ISoJnjgIudAKiMEv+yc5OSeI23x4zK9vYBRKrAwkrH9rTsQVoLxK8/hiqXAxMsAkFGCiqEKm5sSszWeuM7c0vtR0iNkXf+miu9IMVfGykIJr0IdhSq6fATavH9EM4URFrYYIdcAESTyilolK7vH00WHtJfdM19dW5g9jJFM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cLUm+UO9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cLUm+UO9" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 1A021C4CEEF; Mon, 31 Mar 2025 14:55:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1743432922; bh=+mvX5ZClEaPPTurFdhdHay7X2Gx4/MpbXaA0uzY6M5U=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=cLUm+UO9esiSiS2LT/rklNX7OUP8DuRO7kMjgjnPH29s+g4h2OG41ogPtgTtt2sSU H+K7cL6lzIvEeb2iMWn7FCnC+yxKhqPQHFWHEL3kMifuImBQbi9vFzoWsfFE8iG3Lo k6nB/TVSTWeXmnoOW+p47flFe+zIWMbeaOB8QMzbjm6/amEpgNbVbBhW1lCQ1Sn5Yk wzDr4iS7HNoedZ+Y8QYX7jSZ0mWcCCQXnznYj59yQ4SyzAaHApG0iTUkD3Qgh/EGdc 9FznXhbsvuNEMWC9lxA6KnnKUp07wz3l7HbvLOtjoHS32wCHD1qIVWMIF9hbz7+XOr 3kfzObJFkkUSg== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: =?UTF-8?q?Tomasz=20Paku=C5=82a?= , Makarenko Oleg , =?UTF-8?q?Micha=C5=82=20Kope=C4=87?= , Paul Dino Jones , =?UTF-8?q?Crist=C3=B3ferson=20Bueno?= , Pablo Cisneros , Jiri Kosina , Sasha Levin , jikos@kernel.org, bentiss@kernel.org, linux-usb@vger.kernel.org, linux-input@vger.kernel.org Subject: [PATCH AUTOSEL 6.12 06/23] HID: pidff: Add MISSING_PBO quirk and its detection Date: Mon, 31 Mar 2025 10:54:52 -0400 Message-Id: <20250331145510.1705478-6-sashal@kernel.org> X-Mailer: git-send-email 2.39.5 In-Reply-To: <20250331145510.1705478-1-sashal@kernel.org> References: <20250331145510.1705478-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.12.21 Content-Transfer-Encoding: 8bit From: Tomasz Pakuła [ Upstream commit fc7c154e9bb3c2b98875cfc565406f4787e3b7a4 ] Some devices with only one axis are missing PARAMETER_BLOCK_OFFSET field for conditional effects. They can only have one axis, so we're limiting the max_axis when setting the report for those effects. Automatic detection ensures compatibility even if such device won't be explicitly defined in the kernel. Fixes initialization of VRS DirectForce PRO and possibly other devices. Changes in v6: - Fixed NULL pointer dereference. When PBO is missing, make sure not to set it anyway Co-developed-by: Makarenko Oleg Signed-off-by: Makarenko Oleg Signed-off-by: Tomasz Pakuła Reviewed-by: Michał Kopeć Reviewed-by: Paul Dino Jones Tested-by: Paul Dino Jones Tested-by: Cristóferson Bueno Tested-by: Pablo Cisneros Signed-off-by: Jiri Kosina Signed-off-by: Sasha Levin --- drivers/hid/usbhid/hid-pidff.c | 47 +++++++++++++++++++++------------- include/linux/hid.h | 1 + 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 929f5967e7cb1..503b22feacdbb 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -391,13 +391,19 @@ static int pidff_needs_set_periodic(struct ff_effect *effect, static void pidff_set_condition_report(struct pidff_device *pidff, struct ff_effect *effect) { - int i; + int i, max_axis; + + /* Devices missing Parameter Block Offset can only have one axis */ + max_axis = pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO ? 1 : 2; pidff->set_condition[PID_EFFECT_BLOCK_INDEX].value[0] = pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0]; - for (i = 0; i < 2; i++) { - pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; + for (i = 0; i < max_axis; i++) { + /* Omit Parameter Block Offset if missing */ + if (!(pidff->quirks & HID_PIDFF_QUIRK_MISSING_PBO)) + pidff->set_condition[PID_PARAM_BLOCK_OFFSET].value[0] = i; + pidff_set_signed(&pidff->set_condition[PID_CP_OFFSET], effect->u.condition[i].center); pidff_set_signed(&pidff->set_condition[PID_POS_COEFFICIENT], @@ -809,6 +815,11 @@ static int pidff_find_fields(struct pidff_usage *usage, const u8 *table, pr_debug("Setting MISSING_DELAY quirk\n"); return_value |= 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; + } else if (!found && strict) { pr_debug("failed to locate %d\n", k); return -1; @@ -1088,7 +1099,6 @@ static int pidff_find_effects(struct pidff_device *pidff, */ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) { - int envelope_ok = 0; int status = 0; /* Save info about the device not having the DELAY ffb field. */ @@ -1119,13 +1129,10 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) return -ENODEV; } - if (!PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) - envelope_ok = 1; - if (pidff_find_special_fields(pidff) || pidff_find_effects(pidff, dev)) return -ENODEV; - if (!envelope_ok) { + if (PIDFF_FIND_FIELDS(set_envelope, PID_SET_ENVELOPE, 1)) { if (test_and_clear_bit(FF_CONSTANT, dev->ffbit)) hid_warn(pidff->hid, "has constant effect but no envelope\n"); @@ -1150,16 +1157,20 @@ static int pidff_init_fields(struct pidff_device *pidff, struct input_dev *dev) 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)) && - PIDFF_FIND_FIELDS(set_condition, PID_SET_CONDITION, 1)) { - 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); + 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) { + 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) && diff --git a/include/linux/hid.h b/include/linux/hid.h index 42e4111f43e76..088c6688c3f98 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -1229,6 +1229,7 @@ int hid_pidff_init(struct hid_device *hid); /* HID PIDFF quirks */ #define HID_PIDFF_QUIRK_MISSING_DELAY BIT(0) +#define HID_PIDFF_QUIRK_MISSING_PBO BIT(1) #define dbg_hid(fmt, ...) pr_debug("%s: " fmt, __FILE__, ##__VA_ARGS__) -- 2.39.5