From nobody Sat Oct 4 08:03:31 2025 Received: from mail-il1-f201.google.com (mail-il1-f201.google.com [209.85.166.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 363BC25A333 for ; Mon, 18 Aug 2025 23:10:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558636; cv=none; b=SCQC+zE24HZWfWRTrsxyqqZScwk8N8FWK7DXAfkdYMis1CqSlPv/soTX3IjkEU16MVna1fGrpByOoR2FZtjO/emj1BIpmUoOxZRqJ/RF9tHCYoWIs87pC3SYi3+K51ZrAtFj/FWTRHScIpw3t2VJGRWACIGz+lSPLba1CgAsFWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558636; c=relaxed/simple; bh=fmhEJJJB/E1FFPI5LjG9ozybSomAbkYBLER6Pk9jyms=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=bHJRBBgMoqH9Hl0/TkFV8alIq6uDKKjjmJOxYxWvkfim8dtcp60Uqr9wy3gRLxKA+M/IuDkIbOxQ/VcJAmrxwF1QWdWIYDiIIATAb9poNk9M/tzRy1GVPm6gSiS1Dc8/OX4+fvmuRFcmNB0e1USjOBT09D+WJsdtE3VVnmxxNv8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=H6pnQoVB; arc=none smtp.client-ip=209.85.166.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="H6pnQoVB" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3e580be9806so36300635ab.1 for ; Mon, 18 Aug 2025 16:10:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558634; x=1756163434; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=H0QevRU85Pi+9axz8eFxpRKcQRe8ukOlLHQx9hBgz38=; b=H6pnQoVBSjnxDHOw8nUX5IrGcTb67khWH+mXN0py21h+cRLyrLx//f4BOCbEj00O5g 7tHDfWumzYoT6SYRxw75nATdGvB5jnY/2YR9UY4ofnYDcdkzeXwrDEOJX7KXCFQps+Ds 9GkTxwcDlwdNFQSZaRjFL+FYaO9sTq133m3KmgOolIjCqFmFTdKGUsjK1D+6VKz1FjSA UELLJNDzOd3Jf2Wp3y9H5prYCVNHlIC8v8C9iXfvoI8i0Iaa8nCvZlGs1IDR57ommzpn KTyD+2Dot2X1GZr0K78chufYGyigTTOGekN8qYMXmI0NwBpMm8gvufYXsxkL7PAeomfo Y+TA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558634; x=1756163434; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=H0QevRU85Pi+9axz8eFxpRKcQRe8ukOlLHQx9hBgz38=; b=KbZTi5qgHe0asRxgpsEYuOlHQUIxE5vm2VY4mS3j1Mum+HOxSQpijIdqspc/akJRpp 2Bgj1czQAaUNZeaDEo9HpfMN3r+tD1fdNWbt9ky4L4J8NIz0Wfulg94TxrEm2vHSfY5E hXy/vF+5X4q39pF+RTeNu7pXyeoZ0Ds3+B6J/RiSUEjt6KXwZEhb4xXF4R44bojQnz8N /nJIcfLLP3ddreRihp0JUhVwywGXfyChtgleUWoIs1CfjYua/cTLYNITp08pk3wy+9Z4 FFjdDNhLnDMtG3kun1+rKkEEQwWqPd/omVInHeZIeonC5nE5Tp/Y+BoQy1wpaTX2e1X+ 7t6Q== X-Forwarded-Encrypted: i=1; AJvYcCUkbDL3VgQ3vz6YcXXmUuzrF4TrhAc7+fnZzVA1zE3qYkUU47N1ck51ZbjRvRdV25i2k3C57eNE0XxS+2c=@vger.kernel.org X-Gm-Message-State: AOJu0YxkOiiS6Tn7k5tTeIxjtgvCnQGh7V4NnonrH2skL2ylvF0cwA3y 5vcM65fCEF4FiDGBLahmM2IRLj526/4uKlma5b4Rjctpjv4zvsBk4ojkGWMxVY39VVng9aaCeZv OWVEkgD5PoQ== X-Google-Smtp-Source: AGHT+IFCfiADlQxcsJnYSe59mlfocD3gP94iu57cJNx0vOjYhVOrRJWHhrHJK//rZTjPILcmNtM8bbwrPkcR X-Received: from jabc24.prod.google.com ([2002:a05:6638:c218:b0:50a:68a6:1578]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:1a26:b0:3e3:cc1b:2b5e with SMTP id e9e14a558f8ab-3e676627764mr9826585ab.15.1755558634367; Mon, 18 Aug 2025 16:10:34 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:42 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-1-e4f9ab0add84@google.com> Subject: [PATCH v3 01/11] HID: add haptics page defines From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Introduce haptic usages as defined in HID Usage Tables specification. Add HID units for newton and gram. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- include/linux/hid.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/linux/hid.h b/include/linux/hid.h index 568a9d8c749bc5547ff78d5abe6db7bce2f62d2b..344ab0e40f29afe55575e5a7544= 496b7bb48a266 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -156,6 +156,7 @@ struct hid_item { #define HID_UP_TELEPHONY 0x000b0000 #define HID_UP_CONSUMER 0x000c0000 #define HID_UP_DIGITIZER 0x000d0000 +#define HID_UP_HAPTIC 0x000e0000 #define HID_UP_PID 0x000f0000 #define HID_UP_BATTERY 0x00850000 #define HID_UP_CAMERA 0x00900000 @@ -316,6 +317,28 @@ struct hid_item { #define HID_DG_TOOLSERIALNUMBER 0x000d005b #define HID_DG_LATENCYMODE 0x000d0060 =20 +#define HID_HP_SIMPLECONTROLLER 0x000e0001 +#define HID_HP_WAVEFORMLIST 0x000e0010 +#define HID_HP_DURATIONLIST 0x000e0011 +#define HID_HP_AUTOTRIGGER 0x000e0020 +#define HID_HP_MANUALTRIGGER 0x000e0021 +#define HID_HP_AUTOTRIGGERASSOCIATEDCONTROL 0x000e0022 +#define HID_HP_INTENSITY 0x000e0023 +#define HID_HP_REPEATCOUNT 0x000e0024 +#define HID_HP_RETRIGGERPERIOD 0x000e0025 +#define HID_HP_WAVEFORMVENDORPAGE 0x000e0026 +#define HID_HP_WAVEFORMVENDORID 0x000e0027 +#define HID_HP_WAVEFORMCUTOFFTIME 0x000e0028 +#define HID_HP_WAVEFORMNONE 0x000e1001 +#define HID_HP_WAVEFORMSTOP 0x000e1002 +#define HID_HP_WAVEFORMCLICK 0x000e1003 +#define HID_HP_WAVEFORMBUZZCONTINUOUS 0x000e1004 +#define HID_HP_WAVEFORMRUMBLECONTINUOUS 0x000e1005 +#define HID_HP_WAVEFORMPRESS 0x000e1006 +#define HID_HP_WAVEFORMRELEASE 0x000e1007 +#define HID_HP_VENDORWAVEFORMMIN 0x000e2001 +#define HID_HP_VENDORWAVEFORMMAX 0x000e2fff + #define HID_BAT_ABSOLUTESTATEOFCHARGE 0x00850065 #define HID_BAT_CHARGING 0x00850044 =20 @@ -423,6 +446,12 @@ struct hid_item { #define HID_REPORT_PROTOCOL 1 #define HID_BOOT_PROTOCOL 0 =20 +/* + * HID units + */ +#define HID_UNIT_GRAM 0x0101 +#define HID_UNIT_NEWTON 0xe111 + /* * This is the global environment of the parser. This information is * persistent for main-items. The global environment can be saved and --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E48A2765D7 for ; Mon, 18 Aug 2025 23:10:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558648; cv=none; b=QtrABxZ4YcjwLTQFmhRfTxVvhjt+PS74AOAiTx9sFk03VjecO6qBy9Msi2XUhxNsfK56Mm6DgbOHLbnX8cjxDQ4hNXib/g6bRAbaS3dfd77KHfGvXFsB17983B7XrEYgntIUTqNmiqZmsHQYK4v9LlVhLdubt4nw1ApKiFCCyFI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558648; c=relaxed/simple; bh=pm1W0YfpOpWRiFbJt4o4DwVnxjqV5znVwyUekdvRLXU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=aa1Tt/G+/K29s+/cGcVhIfWECd/ODoHcQOQEapvDhuRiinkJya/EwDpJQg6XVkHiXDy26In8fqV1YkNukTFC2p64Rx/1q4Rwph5IyyMx3EEhMNvUyQXf19B/P9jW9gAbmlnK92ItBuv05UIAHTFRx6lrjIDT8ZYjELipIuFMCbs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=obh3M1he; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="obh3M1he" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-88432da036bso550086839f.1 for ; Mon, 18 Aug 2025 16:10:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558645; x=1756163445; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=weSzBVnDQwjDP7j2MvS38YwDqh+Hi+XeLH59AMJj2cU=; b=obh3M1he/uBiWescp4u2j2cnFx0V6CQ8VIFWaPfcNxgQckqYIwj0JkLktkp7fiihcr n+DUjQ6KtEIEC3O7KDhFwyvSpVYVDQkVqN4Wfe2x0vQCHOXFReh1cvrQ+/JCj1HYKf8j x2GuAZVDk7OgFg4Ggpi+dFCrkvnzjk776urDjUauwlgAe18wsPEwHnN2o56NB5X1X7yW TQJr3kPzKZUwyYwISj9eSi8VYdhffgTUGQEHa+ueSHA9YQkouUOoRonZAV33tKvZMOxM CI3ANjSPTZ2kir5KKfdFkaHKrTyQRHPUrF982KyBNdJHC0asiR6QXhEOLNWaOkKqShYs ozMQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558645; x=1756163445; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=weSzBVnDQwjDP7j2MvS38YwDqh+Hi+XeLH59AMJj2cU=; b=UmOYSpyXO0mI9AiT8SXw+IxAIIJZLU5joUXmO1h2dr4ju3qL4n3c8TlhVmAQsE4ohI qXQLQb36Vs9bR9p7h114yZyNPSRJxvZ6luyy0Xj65EtdaXO//4FfAWCmy0xHXk++ZqRQ 6ReB0R5vE/HicAeeE4TvfkIxSL4+YWZVDFLKS52K2NCgquAnbMXiFbYSSY73pFNjIL3n EqTjhHd7BjAJDpC1LZM2uXBKcTVkDdI8Jka+bOg/MbFWpSoDq3cgS9xeF71X7jXR9kMn HTBvfQRzTUrvArwAWOtq997/wb3qcetR3uOa6ZfPShgIwg7mIQzUD9PJBpDSfW5rERZR bU/g== X-Forwarded-Encrypted: i=1; AJvYcCX/9T/uPa7NhFenyL8rw6ICh8e4hHRL89SUAAo+Ax9LV6GKgGD/LYyK5DbL0yYMpsEO2iDHGMoreRsqSCA=@vger.kernel.org X-Gm-Message-State: AOJu0YzrfpJM3SiTO1hvmieSgwr2R2TSSteY314prK3Wqb/MGtyA9hGM gaytasgTZWV04pJrlzyyCiWp8iSwSjT1TZ3Mjgo7Q447A0EhJlhXG4AkV6fwraT6Q7BZLCE8xqT N7C5B/Jd73w== X-Google-Smtp-Source: AGHT+IEaW72/Pb59rNZtAEgraB28P029G7O5swShzAoxNgLe6iTZBLDO7jtuVyNiADWynNE2azecOrk3BnJX X-Received: from iobbe15.prod.google.com ([2002:a05:6602:378f:b0:884:3f50:a648]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:2dd4:b0:884:315d:e433 with SMTP id ca18e2360f4ac-88467f6312fmr87282339f.12.1755558635646; Mon, 18 Aug 2025 16:10:35 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:43 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-2-e4f9ab0add84@google.com> Subject: [PATCH v3 02/11] Input: add FF_HAPTIC effect type From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak FF_HAPTIC effect type can be used to trigger haptic feedback with HID simple haptic usages. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose Acked-by: Dmitry Torokhov --- include/uapi/linux/input.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index 2557eb7b056178b2b8be98d9cea855eba1bd5aaf..a440fafaa018947f4d9ca0a15af= 2b4c6bd0ae6a0 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -428,6 +428,24 @@ struct ff_rumble_effect { __u16 weak_magnitude; }; =20 +/** + * struct ff_haptic_effect + * @hid_usage: hid_usage according to Haptics page (WAVEFORM_CLICK, etc.) + * @vendor_id: the waveform vendor ID if hid_usage is in the vendor-define= d range + * @vendor_waveform_page: the vendor waveform page if hid_usage is in the = vendor-defined range + * @intensity: strength of the effect as percentage + * @repeat_count: number of times to retrigger effect + * @retrigger_period: time before effect is retriggered (in ms) + */ +struct ff_haptic_effect { + __u16 hid_usage; + __u16 vendor_id; + __u8 vendor_waveform_page; + __u16 intensity; + __u16 repeat_count; + __u16 retrigger_period; +}; + /** * struct ff_effect - defines force feedback effect * @type: type of the effect (FF_CONSTANT, FF_PERIODIC, FF_RAMP, FF_SPRING, @@ -464,6 +482,7 @@ struct ff_effect { struct ff_periodic_effect periodic; struct ff_condition_effect condition[2]; /* One for each axis */ struct ff_rumble_effect rumble; + struct ff_haptic_effect haptic; } u; }; =20 @@ -471,6 +490,7 @@ struct ff_effect { * Force feedback effect types */ =20 +#define FF_HAPTIC 0x4f #define FF_RUMBLE 0x50 #define FF_PERIODIC 0x51 #define FF_CONSTANT 0x52 @@ -480,7 +500,7 @@ struct ff_effect { #define FF_INERTIA 0x56 #define FF_RAMP 0x57 =20 -#define FF_EFFECT_MIN FF_RUMBLE +#define FF_EFFECT_MIN FF_HAPTIC #define FF_EFFECT_MAX FF_RAMP =20 /* --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f74.google.com (mail-io1-f74.google.com [209.85.166.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 826E227F16F for ; Mon, 18 Aug 2025 23:10:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558646; cv=none; b=ABIc8UY8CzywlT5SFTR7FU7ejACdzL0if86+hjIlcSfkgnkKb8X4Ywu3gYN86pi0n5Rr3PRcWLDGsug4zgdeXsWqGTNxjv3tFVNBGyOKqRxYRy6N4h3oxbuSrDYgkHtxZrHjsxs3YgcoJkRJEkR6chTRQCub2e25qvVLZqQdiso= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558646; c=relaxed/simple; bh=jKW22Y1YSZCMJKYVPMb/MDnG5XPEPaPhSJ4Fk8StOYY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=rslKHWkB6ZYy76cOETzYFBtEZcFBGyu1GUqV3j5wfCE94iUqRwLDH8l/MtWnFT7OmI5Cr7kzH6LkfKvX0pYuOFspRX0zZWLKhHqaysAz6I84ZLXBLe/ov0JC+xt0fLfFIdu4P7kLwkjoXqSzdQMrlBQWUZAj7SbxlB+uT5azpNs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=O6Fl9WCa; arc=none smtp.client-ip=209.85.166.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="O6Fl9WCa" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88432cccc80so471571739f.0 for ; Mon, 18 Aug 2025 16:10:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558643; x=1756163443; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=sQOdy+KlWKxwsTUwWnTs614rgt1w5bSixUfa+zzu7Sc=; b=O6Fl9WCa2uWL0n6ouYPaq6gu3HAxYLjMedmyqpH3tT/9V/xlYIjRBdTAO2En/+gAic c+NGc75y6YFMotMnfMkMsDpyvFkDBLPfBnri/Pq/nJlFhqt6AsFh+nyPPF4/pRohBaB4 ABwgoO5rVdR323AZYgsqBkefXaqLs+RUcVHP2DRIey+2Ek4tsVhy+rxgb6nUOBgG4y1v uAflzBtQ5PrciZAV8H9lYSqIwpsH5VJn7M4la4kfU7f3fRM3nyDEcrhcyYYlDGwmdjX8 zkt7rZsS4oD6N7Lhb7WJMz7Kwa/QiEJq0CS1H9ZulI3+Q4lmYGn6stBSoXxPcQ25LOlg X68w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558643; x=1756163443; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=sQOdy+KlWKxwsTUwWnTs614rgt1w5bSixUfa+zzu7Sc=; b=FMzWeH6Lt4bBMqoRpAX9OadYmqamMjKPn01wp5w3/L9r+HMxd/DQLxSdQCGVWfWmFF 934kSpEdShT7/vSI5A1kNz7AKWiKMK8s1qZy+NbE/bKBCSEIU/1MbNj7cHVOPbQ+/5A6 LmkjgmLClbXxWuHcfGy5Jfm0fTphZpnGax4rOLN0cYUhEPU4p+gKXfLsufgdpQYGYjnD e/GiCIjrcTap34kumeXVETB6mvSrJl+p8PGNUviT1U7zGUIBiKDttXZMnkKlCHpJmJxN DmkRIyIKnvHHK3LMQ36oUTtQeeAsOPt3FkvZq61U/ywgd/YwTCyFDB+qY39/lIsBHfre +fDQ== X-Forwarded-Encrypted: i=1; AJvYcCUgP4bt/7e5XjedS1qeqUd3VOO58jjdjImrm7z0Lg7qUgiiQb5OuGM6zstJRrBLMe16gtHzhx/vTnFxNIM=@vger.kernel.org X-Gm-Message-State: AOJu0YxesQgHMRzDWvz9RqKVW5G/GDhHwRjAGQ7QkY0js4iS7ltzDJRw 06tdElz+5wTlORwO4DTirB33cjoFokdzzhFhcaXFvuRyX0PkkafAeYgXHPiruPF0lSiOritexTb /YEIbehxTtw== X-Google-Smtp-Source: AGHT+IENXK2kuyir4ub8DtPGQzHQsMDEtGHtPbYUJO4YqIMU/DCj3/jGIUSc7sqfu0LqU2QJCqI05UDl8KNS X-Received: from jabkw19.prod.google.com ([2002:a05:6638:9313:b0:501:eef5:7b8e]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:340e:b0:87c:1cc3:c0fa with SMTP id ca18e2360f4ac-88467dc9d94mr94914139f.0.1755558636882; Mon, 18 Aug 2025 16:10:36 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:44 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-3-e4f9ab0add84@google.com> Subject: [PATCH v3 03/11] Input: add INPUT_PROP_HAPTIC_TOUCHPAD From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak INPUT_PROP_HAPTIC_TOUCHPAD property is to be set for a device with simple haptic capabilities. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose Acked-by: Dmitry Torokhov Reviewed-by: Randy Dunlap --- Documentation/input/event-codes.rst | 14 ++++++++++++++ include/uapi/linux/input-event-codes.h | 1 + 2 files changed, 15 insertions(+) diff --git a/Documentation/input/event-codes.rst b/Documentation/input/even= t-codes.rst index b4557462edd7b3fef9e9cd6c2c3cb2d05bb531ab..1ead9bb8d9c6451a81426665baa= b643f9e50216a 100644 --- a/Documentation/input/event-codes.rst +++ b/Documentation/input/event-codes.rst @@ -400,6 +400,20 @@ can report through the rotational axes (absolute and/o= r relative rx, ry, rz). All other axes retain their meaning. A device must not mix regular directional axes and accelerometer axes on the same event node. =20 +INPUT_PROP_HAPTIC_TOUCHPAD +-------------------------- + +The INPUT_PROP_HAPTIC_TOUCHPAD property indicates that device: +- supports simple haptic auto and manual triggering +- can differentiate between at least 5 fingers +- uses correct resolution for the X/Y (units and value) +- reports correct force per touch, and correct units for them (newtons or = grams) +- follows the MT protocol type B + +Summing up, such devices follow the MS spec for input devices in +Win8 and Win8.1, and in addition support the Simple haptic controller HID = table, +and report correct units for the pressure. + Guidelines =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D =20 diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/in= put-event-codes.h index 3b2524e4b667d1e7cc02ff5cb674e7c2ac069a66..efe8c36d4ee9a938ffb1b0dd0dd= d0ec6a3fcb8fe 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -27,6 +27,7 @@ #define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ #define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ #define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ +#define INPUT_PROP_HAPTIC_TOUCHPAD 0x07 /* is a haptic touchpad */ =20 #define INPUT_PROP_MAX 0x1f #define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f74.google.com (mail-io1-f74.google.com [209.85.166.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 148D927A46E for ; Mon, 18 Aug 2025 23:10:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558640; cv=none; b=EVpfN7D4jyfMadhqVnFC+iq5uGA06NAYMiM0ps/FXIVEd1sRQn9BB66pqiZvDINbIous9RWR5nUzEgz9WA5kLgz6agxHoNRko6REMK71L7JciPA1SzZez9vskYaTsRNV+3ERAeIJb2ii7+pviIFU2q2VsGCLoIW9o3cg4D3tFv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558640; c=relaxed/simple; bh=7TrDKAAZtsRGZI6gBph3Bshg7JPs1/WJmYhCqBgo+SQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ui1iNZtQLq7Kn6ZDIVtHvD5WOdRcz1kOxol6BaHDlnAcdGP3ziTbvp3+kLckiCZBecumZvOXLvU0yGwYtI0QDW3T20gUyHZWrptWegLFU+uM9V4Vo+ezgWTD8RQaBDL4VHK4PtN1OM3maH7ms+tMwVFfKjK+ADNqorLwW1UvPDQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=ltaHO5Fa; arc=none smtp.client-ip=209.85.166.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="ltaHO5Fa" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88432dc61d9so1255306139f.1 for ; Mon, 18 Aug 2025 16:10:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558638; x=1756163438; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=K8bS//tJvRP9+OItmvzAW0lhRS/UPeeXHlsLDZL+8Ak=; b=ltaHO5FahoHrE7cTOJeS85EEJMlT9LFsRaygxYgaX0KJWiTuZbJKNLNYMXhgo3czEP /aPl+Ks9RAL+E5RStuHtMGCPi5JEWx+fWIfTXDCwPZDAKzhwb6DUpShsAeh6BXGPcLkb s5k2aLWEhZ1K2uupp4UmADhSe3JVzsSRQTzAhbuVYCliO9vTpWqiR/xbmxLmN7f4Pbaq lf/Uld4EM13XE67IVQDNKvawevMRekLwmXgAS37Tcry40t8Z6FCtEUKPBn1KAFCLYwrt EfucZnddOK21Uiii+BwmGfd2I5gP69eBOtCEPJMJy1d5lxtDSvJkhEeOMHs/TdrfqKz+ BbpA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558638; x=1756163438; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=K8bS//tJvRP9+OItmvzAW0lhRS/UPeeXHlsLDZL+8Ak=; b=uPE3aOA0QYQMTWs7TQc3UQnXHXw4xZSESG8YdgXP8PA0KaN5VVDMHvmkyUbRvSLhWZ MyH1fPnpg0P7KGovEhKoj8PCnG2y8GwK1asOPAd7EN7P8Zue1UwQ7KcC7brN174+tyRB gd3A/pUncheUIu9/Pfc2PO7iC80hApc6U1n6FB/JSROVBkxGp9Y1nBZaBVmZ9EBVd4aC mLQEtjPfz9OApUVfYPMc+nb/uWXAU0GcZKCr0H4qAeiOvP6Up0WiJu6OH0Xk3m0oY2CK 0kIolKCvyQnccWe7+qWZOVkEH/41Ut0tlQJcG+0pmFG4iblgt1kYckHU7hnR9CNsor2E ONFA== X-Forwarded-Encrypted: i=1; AJvYcCWZyhfr+bENHbVTRJdxZWnniAYdqdxbwSN+WwfV5TifIQYKJrbqCZTgd9ZEj3+fhSTMxO0axBdethqAflA=@vger.kernel.org X-Gm-Message-State: AOJu0YxY6f7WCR54z4wtSBTq+W6eGbmxowUbMFip8R6k0axFGFvqKGP1 aJLfjsZXha3HE9n26VsRo5FiQLpWXorbLTcLg6uxeuViEONs8bkvKn0l7OaPGrE3VP0hy6AD+jj wc6s3XXzpTw== X-Google-Smtp-Source: AGHT+IE9gj54QP/bO7euNEkea4aABXmJLtEXYvaXSmrB2uf5bk6Si4j7pdhGAsywgRdY7g3igkBIfc4zV989 X-Received: from ioyy26.prod.google.com ([2002:a05:6602:215a:b0:87c:605f:297f]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:6429:b0:87c:30d4:65f2 with SMTP id ca18e2360f4ac-88467e8db10mr82476339f.3.1755558638227; Mon, 18 Aug 2025 16:10:38 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:45 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-4-e4f9ab0add84@google.com> Subject: [PATCH v3 04/11] HID: haptic: introduce hid_haptic_device From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Define a new structure that contains simple haptic device configuration as well as current state. Add functions that recognize auto trigger and manual trigger reports as well as save their addresses. Verify that the pressure unit is either grams or newtons. Mark the input device as a haptic touchpad if the unit is correct and the reports are found. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/Kconfig | 11 ++++++ drivers/hid/Makefile | 1 + drivers/hid/hid-haptic.c | 72 +++++++++++++++++++++++++++++++++ drivers/hid/hid-haptic.h | 101 +++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 185 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 43859fc757470caf6ad43bd5f72f119e9c36aea7..fa0a53287c0ed6b5853d0e80641= df341fb728332 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -92,6 +92,17 @@ config HID_GENERIC =20 If unsure, say Y. =20 +config HID_HAPTIC + tristate "Haptic touchpad support" + default n + help + Support for touchpads with force sensors and haptic actuators instead of a + traditional button. + Adds extra parsing and FF device for the hid multitouch driver. + It can be used for Elan 2703 haptic touchpad. + + If unsure, say N. + menu "Special HID drivers" =20 config HID_A4TECH diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 10ae5dedbd84708d988ea1f594d409ccebd85ebb..361a7daedeb85454114def8afb5= f58caeab58a00 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -4,6 +4,7 @@ # hid-y :=3D hid-core.o hid-input.o hid-quirks.o hid-$(CONFIG_DEBUG_FS) +=3D hid-debug.o +hid-$(CONFIG_HID_HAPTIC) +=3D hid-haptic.o =20 obj-$(CONFIG_HID_BPF) +=3D bpf/ =20 diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c new file mode 100644 index 0000000000000000000000000000000000000000..d659a430c1a6b06ded31d49efe4= bded909671cb6 --- /dev/null +++ b/drivers/hid/hid-haptic.c @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * HID Haptic support for Linux + * + * Copyright (c) 2021 Angela Czubak + */ + +#include "hid-haptic.h" + +void hid_haptic_feature_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_field *field, struct hid_usage *usage) +{ + if (usage->hid =3D=3D HID_HP_AUTOTRIGGER) { + if (usage->usage_index >=3D field->report_count) { + dev_err(&hdev->dev, + "HID_HP_AUTOTRIGGER out of range\n"); + return; + } + + hid_device_io_start(hdev); + hid_hw_request(hdev, field->report, HID_REQ_GET_REPORT); + hid_hw_wait(hdev); + hid_device_io_stop(hdev); + haptic->default_auto_trigger =3D + field->value[usage->usage_index]; + haptic->auto_trigger_report =3D field->report; + } +} +EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping); + +bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic, + struct hid_input *hi, struct hid_field *field) +{ + if (field->unit =3D=3D HID_UNIT_GRAM || field->unit =3D=3D HID_UNIT_NEWTO= N) + return true; + return false; +} +EXPORT_SYMBOL_GPL(hid_haptic_check_pressure_unit); + +int hid_haptic_input_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if (usage->hid =3D=3D HID_HP_MANUALTRIGGER) { + haptic->manual_trigger_report =3D field->report; + /* we don't really want to map these fields */ + return -1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(hid_haptic_input_mapping); + +int hid_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi) +{ + + if (hi->application =3D=3D HID_DG_TOUCHPAD) { + if (haptic->auto_trigger_report && + haptic->manual_trigger_report) { + __set_bit(INPUT_PROP_HAPTIC_TOUCHPAD, hi->input->propbit); + return 1; + } + return 0; + } + return -1; +} +EXPORT_SYMBOL_GPL(hid_haptic_input_configured); diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h new file mode 100644 index 0000000000000000000000000000000000000000..2e89addf5ec280d5b9a59d06088= cc08bd4f445c1 --- /dev/null +++ b/drivers/hid/hid-haptic.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * HID Haptic support for Linux + * + * Copyright (c) 2021 Angela Czubak + */ + +#include + +#define HID_HAPTIC_ORDINAL_WAVEFORMNONE 1 +#define HID_HAPTIC_ORDINAL_WAVEFORMSTOP 2 + +#define HID_HAPTIC_MODE_DEVICE 0 +#define HID_HAPTIC_MODE_HOST 1 + +struct hid_haptic_effect { + u8 *report_buf; + struct input_dev *input_dev; + struct work_struct work; + struct list_head control; + struct mutex control_mutex; +}; + +struct hid_haptic_effect_node { + struct list_head node; + struct file *file; +}; + +struct hid_haptic_device { + struct input_dev *input_dev; + struct hid_device *hdev; + struct hid_report *auto_trigger_report; + struct mutex auto_trigger_mutex; + struct workqueue_struct *wq; + struct hid_report *manual_trigger_report; + struct mutex manual_trigger_mutex; + size_t manual_trigger_report_len; + int pressed_state; + s32 pressure_sum; + s32 force_logical_minimum; + s32 force_physical_minimum; + s32 force_resolution; + u32 mode; + u32 default_auto_trigger; + u32 vendor_page; + u32 vendor_id; + u32 max_waveform_id; + u32 max_duration_id; + u16 *hid_usage_map; + u32 *duration_map; + u16 press_ordinal; + u16 release_ordinal; + struct hid_haptic_effect *effect; + struct hid_haptic_effect stop_effect; +}; + +#if IS_ENABLED(CONFIG_HID_HAPTIC) +void hid_haptic_feature_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_field *field, struct hid_usage + *usage); +bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic, + struct hid_input *hi, struct hid_field *field); +int hid_haptic_input_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max); +int hid_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi); +#else +static inline +void hid_haptic_feature_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_field *field, struct hid_usage + *usage) +{} +static inline +bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic, + struct hid_input *hi, struct hid_field *field) +{ + return false; +} +static inline +int hid_haptic_input_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + return 0; +} +static inline +int hid_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi) +{ + return 0; +} +#endif --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-il1-f201.google.com (mail-il1-f201.google.com [209.85.166.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AA20327A904 for ; Mon, 18 Aug 2025 23:10:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558641; cv=none; b=pcNXaqr1C01MOEuvtM8xcMjbYlN+z3enr0oVmy4W2PQMhAx6Oqi60d2oHFn7xVnBZRmDp9FrOwsSahPo9MAwM1/ojJJHJ2UX6jbVgnwxhA4vHk39VGydP772DIFSHyoSDPPzphb1j1N10ICbXGBLv6GnBmuwVvTmcH+vQ/5ilsw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558641; c=relaxed/simple; bh=kyVuZ1ePOiBKb24SnEItkzkqQ35cVznwS9078OsQVq0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=K5JL4XDh1c48g5sFrnnhTxKTZIM+NaQBqcnp59fyVQAx47wlEY51lCwfg8E2yKCrBkxmxT5n8LBiaen/lRVTgGyu/oTsfH4d4h6oeaugLLFlES7n27ReT1qJo3zu7eFE+z5IWjt+f117yQCNGsKkRqQ9UxvIX4a3H73lXo4QuLg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=u3Lzo8WX; arc=none smtp.client-ip=209.85.166.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="u3Lzo8WX" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3e56face5fbso49307485ab.0 for ; Mon, 18 Aug 2025 16:10:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558639; x=1756163439; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=tCcFbkxPQyh6tgMC7pg429eb+U79ldGABIAzkJx5VBc=; b=u3Lzo8WXbQo3EYRwCke8IX9fW4gFHt1yCv/HpHqZ3GVaX9CAR5jDhZNLxBzGWhYvEF qWNtHfVGkCTWXaa1z0LywyGKRsH1D9Wgx9SXA0S2HxZ11HrJTKozL2tMyorOxruisXCS qGMlJYxBpohAXrYuXD0faoDn5k8iek9993JBqYFGcYR5h7vEvalPxU1Nzd5PPrbn/MtV yVCX+iOSe7aTtEjV8Yk090r78LXgSobsypYBqymT5TSrZtnDzlVhLdt+U0I6hfEbYpiC F+3OUCKciY3bVaKE8W8q2q8tnKPMW0IKP4Lz5cU/hDV6oqK3StJLOxk8bbB2lfDzKw0x S3yA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558639; x=1756163439; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=tCcFbkxPQyh6tgMC7pg429eb+U79ldGABIAzkJx5VBc=; b=w/8zCjXbWMqZtukREHd5h1YsZKRWajoIRvUWWXPM+69wzabddf5sj/sBni57l+xvFD igzI9pLqdpchoRdrKeZG6XZICA8EgRuLnL9I2MHmHXDHn3PQgGUoFXF3o9e74SJOT7v6 sxYO5ePd3qUU690u91IH5YcZjj+wAWD3WV+jwS1vNHuu2cGQAw6UJkz2DJ9+LB8JCMpD 2rVicO7en6VHBhDtngMmyviE9Kab+gldcSaQvuGquQpYS5I2saWQyVKd+H/k5widiYGm s9Q5ZA0v5ZF4vUNYbHjUlkXr+0Dx25Grd0XITgWDGkKwUh2ijp3esEDndsQMxYslZmxx hRvw== X-Forwarded-Encrypted: i=1; AJvYcCWFadFU81jkMsnfyfMY9l97WeGND7keYZpg4XFyBhTG8yYFQ+597FP2Kzu5XGf25s92WiwLBKpxrXIvngU=@vger.kernel.org X-Gm-Message-State: AOJu0Yw2LRe/6jPohqAjylXzAwxLlrrzxsxAOuWON5YAfW54sGQCJfJp PjKxX3Sib2xmQFFxFALAUYONsMwQCoiEZ0vvs3uEmOcJiGZPk6D0s4QCiR0z4dtXdOkY132AkZO KucpPmWvz+A== X-Google-Smtp-Source: AGHT+IFH4d2TZoQ5zu2dR3bo/GDEtSZKym2ory9RtgV29M5CZHpcDZ6mOgVVAF88TxZXYNhFPp6HjoXISFcs X-Received: from jabhb19.prod.google.com ([2002:a05:6638:6c13:b0:4fd:c6b9:3df7]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:1d97:b0:3e5:42aa:4c37 with SMTP id e9e14a558f8ab-3e676c09cc3mr5883325ab.2.1755558639036; Mon, 18 Aug 2025 16:10:39 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:46 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-5-e4f9ab0add84@google.com> Subject: [PATCH v3 05/11] HID: input: allow mapping of haptic output From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak This change makes it possible to parse output reports by input mapping functions by HID drivers. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/hid-input.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 9d80635a91ebd8d8bdafaac07b5f85693b179cb4..d42c1fbd20a1cc01c04f93cf10f= 1d1c18043929c 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -682,9 +682,10 @@ static void hidinput_configure_usage(struct hid_input = *hidinput, struct hid_fiel if (field->report_count < 1) goto ignore; =20 - /* only LED usages are supported in output fields */ + /* only LED and HAPTIC usages are supported in output fields */ if (field->report_type =3D=3D HID_OUTPUT_REPORT && - (usage->hid & HID_USAGE_PAGE) !=3D HID_UP_LED) { + (usage->hid & HID_USAGE_PAGE) !=3D HID_UP_LED && + (usage->hid & HID_USAGE_PAGE) !=3D HID_UP_HAPTIC) { goto ignore; } =20 --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f74.google.com (mail-io1-f74.google.com [209.85.166.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DFAAD27B516 for ; Mon, 18 Aug 2025 23:10:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558643; cv=none; b=K8++NfedeSYyZSXqIalrZUcvnN3FSbHeCLAtLLxl50sehMLVRO0qolPn5fQUlDM5ZHu1mGz6eyUeWDEJjylwoJjS9yB4fjfhzFzKEAijuzcT5WcOkcqE3gy7rXk3aX38Ie1CTRcwZ0vohbLwCwu/idaaHJdScuuvtvfekqiTDR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558643; c=relaxed/simple; bh=96ckk3w4BE3eFejRPR7cCz/hnXvvKjoIJJBFTE9EyWA=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=iXZOFBoNga5a3rw8KzXGwz9+xToXfRF40Pe4r+f10L/s606DZmFGR9+z9uz4Ure5dQg9Ka5RfxwhqWoQcvy44Jzv5/XFl1qKEmDDHU3d71xy5BGLdn/Ue/TGMYZlhtW/tp7nTP4onEHbGHkJe8PoQ+fWbbu0czGaM0G95Id1wHg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=xT29vCG0; arc=none smtp.client-ip=209.85.166.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="xT29vCG0" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88432e1630fso474479339f.2 for ; Mon, 18 Aug 2025 16:10:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558640; x=1756163440; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=IFFdFO6bExoyO3S6sABBHDDzfLD5xTf6iI9L+uYHnwA=; b=xT29vCG0q4hIw8hVppOnJ/p6s505eN8PI1tgZOq+KsAPe47nmvksG3FOdlOtJ02cwc FWbohmmAYr1KYcg0e9mArjeIZIgvWYFHKNLoOwY/PWK/YIcVXWgjz+8VbXFf2ZMflCGo zG1JJNRveBLhP99PC1v/Oim/W4FsSEn9/OyjI2+YIgKG2251bdBdUzibcQl49uiSG+23 RWyUmEIoVNbKRpdo7txJS1f1ggx53k1sipZ/WyBS3e3Id8J7QGykWqB0XnGc2o2sZcYo 2y8Sz70Ttv+Soq6ANqH0w/4wsYihmRn0DKKMBIeA4smPyRCMIs9rt+1vMXswgGh3byY9 Z6XQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558640; x=1756163440; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=IFFdFO6bExoyO3S6sABBHDDzfLD5xTf6iI9L+uYHnwA=; b=MEV7d2xKarNdexDangeY4tjLU5kB+bZ0j9+kHbSRS6hDzDiDMhDUjn5g9yQL1PLAME CYp9jaZbghiOn4IybwKzXVq7b8yDxnfGuvlsBU6+TNsKVqeMrVjcE+7NtuxPlBvbLX5A 4/ipxYXDQQKdw+kVIs+TmgzVlkfC28YEVifOBGCmAwCc+VvXXoTnHUspO91Hf6kG0gWu TJN7DZw8nrCAtlgzgC09qma/K3wObOmuyHvF1Nepx+m0IERXBtjMnFqoc+2UCHQ+HOO3 ZyMIEAex85qIHSPuk3CZpMGr+LdFEoLYf3zdt2QDUFLmNre98mx46X848cjZVF9MTGh0 RTHA== X-Forwarded-Encrypted: i=1; AJvYcCWXG3cXAsk7zEEOEq7TvYq+2KUaYO80cC3j1R0dyynoUGFE0uJesOimdesWkLdiutc6xAT79BfHpLzAMpA=@vger.kernel.org X-Gm-Message-State: AOJu0YzM9mGVUzGHwYHSzeplShAObl5zwRUUvlByxINljf0k9k/iw2jC qAaOMuLQmyPzFgDaZO4J6nqijbAgL+1a1NyijATitQMT0H++wJ1tWuMPzWBJ9PPgQP+qH2BHizG JWjA+U4eRrw== X-Google-Smtp-Source: AGHT+IFh/CHWQFRkkC0rMB4wTcUHbxuLC22Xi/iQOnekBPr75+nxd9UeL/0LYZeJ8jx0aiDR9sbxghIqkd1D X-Received: from iobfb19.prod.google.com ([2002:a05:6602:3f93:b0:884:1a59:5308]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:3fc3:b0:884:476b:352b with SMTP id ca18e2360f4ac-88467f641a9mr95739539f.9.1755558640071; Mon, 18 Aug 2025 16:10:40 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:47 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-6-e4f9ab0add84@google.com> Subject: [PATCH v3 06/11] HID: haptic: initialize haptic device From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Add hid_haptic_init(). Parse autotrigger report to retrieve ordinals for press and release waveforms. Implement force feedback functions. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/hid-haptic.c | 438 +++++++++++++++++++++++++++++++++++++++++++= ++++ drivers/hid/hid-haptic.h | 5 + 2 files changed, 443 insertions(+) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index d659a430c1a6b06ded31d49efe4bded909671cb6..ef09b4039f33f15d7220e69fbed= 10bd8b0362bb4 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -5,12 +5,16 @@ * Copyright (c) 2021 Angela Czubak */ =20 +#include + #include "hid-haptic.h" =20 void hid_haptic_feature_mapping(struct hid_device *hdev, struct hid_haptic_device *haptic, struct hid_field *field, struct hid_usage *usage) { + u16 usage_hid; + if (usage->hid =3D=3D HID_HP_AUTOTRIGGER) { if (usage->usage_index >=3D field->report_count) { dev_err(&hdev->dev, @@ -25,6 +29,20 @@ void hid_haptic_feature_mapping(struct hid_device *hdev, haptic->default_auto_trigger =3D field->value[usage->usage_index]; haptic->auto_trigger_report =3D field->report; + } else if ((usage->hid & HID_USAGE_PAGE) =3D=3D HID_UP_ORDINAL) { + usage_hid =3D usage->hid & HID_USAGE; + switch (field->logical) { + case HID_HP_WAVEFORMLIST: + if (usage_hid > haptic->max_waveform_id) + haptic->max_waveform_id =3D usage_hid; + break; + case HID_HP_DURATIONLIST: + if (usage_hid > haptic->max_duration_id) + haptic->max_duration_id =3D usage_hid; + break; + default: + break; + } } } EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping); @@ -70,3 +88,423 @@ int hid_haptic_input_configured(struct hid_device *hdev, return -1; } EXPORT_SYMBOL_GPL(hid_haptic_input_configured); + +static void parse_auto_trigger_field(struct hid_haptic_device *haptic, + struct hid_field *field) +{ + int count =3D field->report_count; + int n; + u16 usage_hid; + + for (n =3D 0; n < count; n++) { + switch (field->usage[n].hid & HID_USAGE_PAGE) { + case HID_UP_ORDINAL: + usage_hid =3D field->usage[n].hid & HID_USAGE; + switch (field->logical) { + case HID_HP_WAVEFORMLIST: + haptic->hid_usage_map[usage_hid] =3D field->value[n]; + if (field->value[n] =3D=3D + (HID_HP_WAVEFORMPRESS & HID_USAGE)) { + haptic->press_ordinal =3D usage_hid; + } else if (field->value[n] =3D=3D + (HID_HP_WAVEFORMRELEASE & HID_USAGE)) { + haptic->release_ordinal =3D usage_hid; + } + break; + case HID_HP_DURATIONLIST: + haptic->duration_map[usage_hid] =3D + field->value[n]; + break; + default: + break; + } + break; + case HID_UP_HAPTIC: + switch (field->usage[n].hid) { + case HID_HP_WAVEFORMVENDORID: + haptic->vendor_id =3D field->value[n]; + break; + case HID_HP_WAVEFORMVENDORPAGE: + haptic->vendor_page =3D field->value[n]; + break; + default: + break; + } + break; + default: + /* Should not really happen */ + break; + } + } +} + +static void fill_effect_buf(struct hid_haptic_device *haptic, + struct ff_haptic_effect *effect, + struct hid_haptic_effect *haptic_effect, + int waveform_ordinal) +{ + struct hid_report *rep =3D haptic->manual_trigger_report; + struct hid_usage *usage; + struct hid_field *field; + s32 value; + int i, j; + u8 *buf =3D haptic_effect->report_buf; + + mutex_lock(&haptic->manual_trigger_mutex); + for (i =3D 0; i < rep->maxfield; i++) { + field =3D rep->field[i]; + /* Ignore if report count is out of bounds. */ + if (field->report_count < 1) + continue; + + for (j =3D 0; j < field->maxusage; j++) { + usage =3D &field->usage[j]; + + switch (usage->hid) { + case HID_HP_INTENSITY: + if (effect->intensity > 100) { + value =3D field->logical_maximum; + } else { + value =3D field->logical_minimum + + effect->intensity * + (field->logical_maximum - + field->logical_minimum) / 100; + } + break; + case HID_HP_REPEATCOUNT: + value =3D effect->repeat_count; + break; + case HID_HP_RETRIGGERPERIOD: + value =3D effect->retrigger_period; + break; + case HID_HP_MANUALTRIGGER: + value =3D waveform_ordinal; + break; + default: + break; + } + + field->value[j] =3D value; + } + } + + hid_output_report(rep, buf); + mutex_unlock(&haptic->manual_trigger_mutex); +} + +static int hid_haptic_upload_effect(struct input_dev *dev, struct ff_effec= t *effect, + struct ff_effect *old) +{ + struct ff_device *ff =3D dev->ff; + struct hid_haptic_device *haptic =3D ff->private; + int i, ordinal =3D 0; + + /* If vendor range, check vendor id and page */ + if (effect->u.haptic.hid_usage >=3D (HID_HP_VENDORWAVEFORMMIN & HID_USAGE= ) && + effect->u.haptic.hid_usage <=3D (HID_HP_VENDORWAVEFORMMAX & HID_USAGE= ) && + (effect->u.haptic.vendor_id !=3D haptic->vendor_id || + effect->u.haptic.vendor_waveform_page !=3D haptic->vendor_page)) + return -EINVAL; + + /* Check hid_usage */ + for (i =3D 1; i <=3D haptic->max_waveform_id; i++) { + if (haptic->hid_usage_map[i] =3D=3D effect->u.haptic.hid_usage) { + ordinal =3D i; + break; + } + } + if (ordinal < 1) + return -EINVAL; + + /* Fill the buffer for the effect id */ + fill_effect_buf(haptic, &effect->u.haptic, &haptic->effect[effect->id], + ordinal); + + return 0; +} + +static int play_effect(struct hid_device *hdev, struct hid_haptic_device *= haptic, + struct hid_haptic_effect *effect) +{ + int ret; + + ret =3D hid_hw_output_report(hdev, effect->report_buf, + haptic->manual_trigger_report_len); + if (ret < 0) { + ret =3D hid_hw_raw_request(hdev, + haptic->manual_trigger_report->id, + effect->report_buf, + haptic->manual_trigger_report_len, + HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); + } + + return ret; +} + +static void haptic_work_handler(struct work_struct *work) +{ + + struct hid_haptic_effect *effect =3D container_of(work, + struct hid_haptic_effect, + work); + struct input_dev *dev =3D effect->input_dev; + struct hid_device *hdev =3D input_get_drvdata(dev); + struct hid_haptic_device *haptic =3D dev->ff->private; + + mutex_lock(&haptic->manual_trigger_mutex); + if (effect !=3D &haptic->stop_effect) + play_effect(hdev, haptic, &haptic->stop_effect); + + play_effect(hdev, haptic, effect); + mutex_unlock(&haptic->manual_trigger_mutex); + +} + +static int hid_haptic_playback(struct input_dev *dev, int effect_id, int v= alue) +{ + struct hid_haptic_device *haptic =3D dev->ff->private; + + if (value) + queue_work(haptic->wq, &haptic->effect[effect_id].work); + else + queue_work(haptic->wq, &haptic->stop_effect.work); + + return 0; +} + +static void effect_set_default(struct ff_effect *effect) +{ + effect->type =3D FF_HAPTIC; + effect->id =3D -1; + effect->u.haptic.hid_usage =3D HID_HP_WAVEFORMNONE & HID_USAGE; + effect->u.haptic.intensity =3D 100; + effect->u.haptic.retrigger_period =3D 0; + effect->u.haptic.repeat_count =3D 0; +} + +static int hid_haptic_erase(struct input_dev *dev, int effect_id) +{ + struct hid_haptic_device *haptic =3D dev->ff->private; + struct ff_effect effect; + int ordinal; + + effect_set_default(&effect); + + if (effect.u.haptic.hid_usage =3D=3D (HID_HP_WAVEFORMRELEASE & HID_USAGE)= ) { + ordinal =3D haptic->release_ordinal; + if (!ordinal) + ordinal =3D HID_HAPTIC_ORDINAL_WAVEFORMNONE; + else + effect.u.haptic.hid_usage =3D HID_HP_WAVEFORMRELEASE & + HID_USAGE; + fill_effect_buf(haptic, &effect.u.haptic, &haptic->effect[effect_id], + ordinal); + } else if (effect.u.haptic.hid_usage =3D=3D (HID_HP_WAVEFORMPRESS & HID_U= SAGE)) { + ordinal =3D haptic->press_ordinal; + if (!ordinal) + ordinal =3D HID_HAPTIC_ORDINAL_WAVEFORMNONE; + else + effect.u.haptic.hid_usage =3D HID_HP_WAVEFORMPRESS & + HID_USAGE; + fill_effect_buf(haptic, &effect.u.haptic, &haptic->effect[effect_id], + ordinal); + } + + return 0; +} + +static void hid_haptic_destroy(struct ff_device *ff) +{ + struct hid_haptic_device *haptic =3D ff->private; + struct hid_device *hdev =3D haptic->hdev; + int r; + + if (hdev) + put_device(&hdev->dev); + + kfree(haptic->stop_effect.report_buf); + haptic->stop_effect.report_buf =3D NULL; + + if (haptic->effect) { + for (r =3D 0; r < ff->max_effects; r++) + kfree(haptic->effect[r].report_buf); + kfree(haptic->effect); + } + haptic->effect =3D NULL; + + destroy_workqueue(haptic->wq); + haptic->wq =3D NULL; + + kfree(haptic->duration_map); + haptic->duration_map =3D NULL; + + kfree(haptic->hid_usage_map); + haptic->hid_usage_map =3D NULL; + + module_put(THIS_MODULE); +} + +int hid_haptic_init(struct hid_device *hdev, + struct hid_haptic_device **haptic_ptr) +{ + struct hid_haptic_device *haptic =3D *haptic_ptr; + struct input_dev *dev =3D NULL; + struct hid_input *hidinput; + struct ff_device *ff; + int ret =3D 0, r; + struct ff_haptic_effect stop_effect =3D { + .hid_usage =3D HID_HP_WAVEFORMSTOP & HID_USAGE, + }; + const char *prefix =3D "hid-haptic"; + char *name; + int (*flush)(struct input_dev *dev, struct file *file); + int (*event)(struct input_dev *dev, unsigned int type, unsigned int code,= int value); + + haptic->hdev =3D hdev; + haptic->max_waveform_id =3D max(2u, haptic->max_waveform_id); + haptic->max_duration_id =3D max(2u, haptic->max_duration_id); + + haptic->hid_usage_map =3D kcalloc(haptic->max_waveform_id + 1, + sizeof(u16), GFP_KERNEL); + if (!haptic->hid_usage_map) { + ret =3D -ENOMEM; + goto exit; + } + haptic->duration_map =3D kcalloc(haptic->max_duration_id + 1, + sizeof(u32), GFP_KERNEL); + if (!haptic->duration_map) { + ret =3D -ENOMEM; + goto usage_map; + } + + if (haptic->max_waveform_id !=3D haptic->max_duration_id) + dev_warn(&hdev->dev, + "Haptic duration and waveform lists have different max id (%u and %u).= \n", + haptic->max_duration_id, haptic->max_waveform_id); + + haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMNONE] =3D + HID_HP_WAVEFORMNONE & HID_USAGE; + haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMSTOP] =3D + HID_HP_WAVEFORMSTOP & HID_USAGE; + + for (r =3D 0; r < haptic->auto_trigger_report->maxfield; r++) + parse_auto_trigger_field(haptic, haptic->auto_trigger_report->field[r]); + + list_for_each_entry(hidinput, &hdev->inputs, list) { + if (hidinput->application =3D=3D HID_DG_TOUCHPAD) { + dev =3D hidinput->input; + break; + } + } + + if (!dev) { + dev_err(&hdev->dev, "Failed to find the input device\n"); + ret =3D -ENODEV; + goto duration_map; + } + + haptic->input_dev =3D dev; + haptic->manual_trigger_report_len =3D + hid_report_len(haptic->manual_trigger_report); + mutex_init(&haptic->manual_trigger_mutex); + name =3D kmalloc(strlen(prefix) + strlen(hdev->name) + 2, GFP_KERNEL); + if (name) { + sprintf(name, "%s %s", prefix, hdev->name); + haptic->wq =3D create_singlethread_workqueue(name); + kfree(name); + } + if (!haptic->wq) { + ret =3D -ENOMEM; + goto duration_map; + } + haptic->effect =3D kcalloc(FF_MAX_EFFECTS, + sizeof(struct hid_haptic_effect), GFP_KERNEL); + if (!haptic->effect) { + ret =3D -ENOMEM; + goto output_queue; + } + for (r =3D 0; r < FF_MAX_EFFECTS; r++) { + haptic->effect[r].report_buf =3D + hid_alloc_report_buf(haptic->manual_trigger_report, + GFP_KERNEL); + if (!haptic->effect[r].report_buf) { + dev_err(&hdev->dev, + "Failed to allocate a buffer for an effect.\n"); + ret =3D -ENOMEM; + goto buffer_free; + } + haptic->effect[r].input_dev =3D dev; + INIT_WORK(&haptic->effect[r].work, haptic_work_handler); + } + haptic->stop_effect.report_buf =3D + hid_alloc_report_buf(haptic->manual_trigger_report, + GFP_KERNEL); + if (!haptic->stop_effect.report_buf) { + dev_err(&hdev->dev, + "Failed to allocate a buffer for stop effect.\n"); + ret =3D -ENOMEM; + goto buffer_free; + } + haptic->stop_effect.input_dev =3D dev; + INIT_WORK(&haptic->stop_effect.work, haptic_work_handler); + fill_effect_buf(haptic, &stop_effect, &haptic->stop_effect, + HID_HAPTIC_ORDINAL_WAVEFORMSTOP); + + input_set_capability(dev, EV_FF, FF_HAPTIC); + + flush =3D dev->flush; + event =3D dev->event; + ret =3D input_ff_create(dev, FF_MAX_EFFECTS); + if (ret) { + dev_err(&hdev->dev, "Failed to create ff device.\n"); + goto stop_buffer_free; + } + + ff =3D dev->ff; + ff->private =3D haptic; + ff->upload =3D hid_haptic_upload_effect; + ff->playback =3D hid_haptic_playback; + ff->erase =3D hid_haptic_erase; + ff->destroy =3D hid_haptic_destroy; + if (!try_module_get(THIS_MODULE)) { + dev_err(&hdev->dev, "Failed to increase module count.\n"); + goto input_free; + } + if (!get_device(&hdev->dev)) { + dev_err(&hdev->dev, "Failed to get hdev device.\n"); + module_put(THIS_MODULE); + goto input_free; + } + return 0; + +input_free: + input_ff_destroy(dev); + /* Do not let double free happen, input_ff_destroy will call + * hid_haptic_destroy. + */ + *haptic_ptr =3D NULL; + /* Restore dev flush and event */ + dev->flush =3D flush; + dev->event =3D event; + return ret; +stop_buffer_free: + kfree(haptic->stop_effect.report_buf); + haptic->stop_effect.report_buf =3D NULL; +buffer_free: + while (--r >=3D 0) + kfree(haptic->effect[r].report_buf); + kfree(haptic->effect); + haptic->effect =3D NULL; +output_queue: + destroy_workqueue(haptic->wq); + haptic->wq =3D NULL; +duration_map: + kfree(haptic->duration_map); + haptic->duration_map =3D NULL; +usage_map: + kfree(haptic->hid_usage_map); + haptic->hid_usage_map =3D NULL; +exit: + return ret; +} +EXPORT_SYMBOL_GPL(hid_haptic_init); diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index 2e89addf5ec280d5b9a59d06088cc08bd4f445c1..25e0e2cef9399199796d8679d66= 209381b6a59f2 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -69,6 +69,7 @@ int hid_haptic_input_mapping(struct hid_device *hdev, int hid_haptic_input_configured(struct hid_device *hdev, struct hid_haptic_device *haptic, struct hid_input *hi); +int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **ha= ptic_ptr); #else static inline void hid_haptic_feature_mapping(struct hid_device *hdev, @@ -98,4 +99,8 @@ int hid_haptic_input_configured(struct hid_device *hdev, { return 0; } +int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **ha= ptic_ptr) +{ + return 0; +} #endif --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 151CC27D77D for ; Mon, 18 Aug 2025 23:10:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558643; cv=none; b=CIarRYegfKKMbRHkwaAGUhZj2Sy7Qm87c9kswQhEmUPJKdt65Gd8lL/K7LUJq+BrjUANVZH21lqilTTYsMsl25O38yESib0aL7iYhpan5dt/lbFTAOBYRLMjilgcAr9ucwcVbXIRtOtC1dusfuB13aM2AmcWSNTc3l2voRWCpKQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558643; c=relaxed/simple; bh=0zxJTqS++QzeTMN7ELVT/4x9pOXf62yqfBvIp9OiakU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=s5bcigIYlJY7MnvZGFlLxrgHHpO83K3WzcMoxZhVlB/GfmJsm6C08V73pFmzMGR8GJpbNwkpVuACIqPB+g53/1LN2j8O1YOyNCBAQ3mqvDIbxT6VsY5t/lB0Ee8LSw8uP1F1mbRi7ARl/FbOf7GPQRxSSbVLzdKp2W3w0lEz6hc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=MQ9eTwgf; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="MQ9eTwgf" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-88432e62d01so633431039f.3 for ; Mon, 18 Aug 2025 16:10:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558641; x=1756163441; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=bjzFjLZ/9nuKad8tzU4AwxzdMRz4hEl/2ABsOkFafDU=; b=MQ9eTwgfhKPWap+CTiMuwuual5qQnFFkODg5wGKKvtAKNcUMsitkeS3Qe4Vf4x2pPa GJ6SW8HnX/v8s76W5xG9FXUUxEsv/2z1jUm6Zyc5q0OPsIOjMshKMVhECJMDvwwpPEFk 3AZrDvEhS+TWSXqBqP7R5EQLZH0oBkwyy33VDBTpeUu2MfUai4CX/H7NhOYugeNIY8yz 2BvwLb3YqKKqrbCZnPKQ6S/a6W5TFHTVRUC764ZqWxTbPa8JiGNYTz8qQb4ydwVuYG0D zad28eZJk5cWEgZEUihL1NM/QllI7Tiz3W9iky+DFm+v9eaM7cLMYfGbtbCizAvTl8Ih XcBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558641; x=1756163441; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=bjzFjLZ/9nuKad8tzU4AwxzdMRz4hEl/2ABsOkFafDU=; b=VC9fUHSitPZuTfBxXdPvoVq3KVhKSvI3OLRu0wGyOhzsuRlqDpo6CbIoEQp8H7c9fb 73FNQMecI5q7c4/RElapT1MPNyTcWpbpqdTiaZXkrIP4BWzMyyfbgRDfVqsMKQcxhQOL AMr30uUJ3XshDaaGSFAXoRtDLAzWS3fMAnP7sUSYXHxPTR2qLsg13SHxM37mrT8j4BWd 8wx0qBTJYxiPTbawCUFfGLvxlyB8sihveW5CaaDjNd9d7wggrfzVcx6wGOFlu+xgAwOn SrPfph5+2v+zs7KBbX7Hrbptno45l1obqVocK+TEvCL/tdri3zYMQ5fX+XqDl3uaJKa7 U57g== X-Forwarded-Encrypted: i=1; AJvYcCUwJ87djIY2DzrvlyD1jq9xRsLF+pVYjNg+dPNrQxk9ZNyrA+HpKY304t/nkp9SuQPaTbj1iX3QdFYb4sQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwHv0F3qekv8t0zF2VQlrLr/BvjGXdYQ08/xIPD2ASzw/VXTmAQ U1KyFonDf+pxNP9WTeQDLiHdw9dkMbcYglj8PALNBqnVoZJywn2JUEBfMosv2gk0do+f7HFpRHD Qa47dSdKiKA== X-Google-Smtp-Source: AGHT+IGZLTz+lqQtSWbfLXXAEC8acdwTT51EP9+iU8mLrGDi0z1WLLK3wDQzAomLi0As6Qv94y0KEgUeoz/L X-Received: from iojp6.prod.google.com ([2002:a5d:8d06:0:b0:881:77ef:6edb]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:3fc3:b0:875:d675:55f2 with SMTP id ca18e2360f4ac-88467ede8f2mr79072139f.7.1755558641274; Mon, 18 Aug 2025 16:10:41 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:48 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-7-e4f9ab0add84@google.com> Subject: [PATCH v3 07/11] HID: input: calculate resolution for pressure From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Assume that if the pressure is given in newtons it should be normalized to grams. If the pressure has no unit do not calculate resolution. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/hid-input.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index d42c1fbd20a1cc01c04f93cf10f1d1c18043929c..1d59787bd0c0e251698e2a2944d= ae1c4a96adefe 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -303,6 +303,19 @@ __s32 hidinput_calc_abs_res(const struct hid_field *fi= eld, __u16 code) } break; =20 + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + if (field->unit =3D=3D HID_UNIT_NEWTON) { + /* Convert to grams, 1 newton is 101.97 grams */ + prev =3D physical_extents; + physical_extents *=3D 10197; + if (physical_extents < prev) + return 0; + unit_exponent -=3D 2; + } else if (field->unit !=3D HID_UNIT_GRAM) { + return 0; + } + break; default: return 0; } --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-il1-f202.google.com (mail-il1-f202.google.com [209.85.166.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 22E7D27E1DC for ; Mon, 18 Aug 2025 23:10:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558644; cv=none; b=mgokomWqXTpXZQ1j7Zi2BdXU5va2jPrNADVmilyLnmgBLzVXSEFUbOtodVfBzvARAL3O+P0I5I3yOr2Md/gQWVoH3eI6B1D75GJ13AHZQZkBmTwi5NA7Fu4bJO2xMKzqWCe5n/qmkQgl6oJRgKXmVioncpeM2b7L+jWD5N5BdIo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558644; c=relaxed/simple; bh=Jkdjos4RgOTVipcn+UeTFakdYiYYbNUhS5lMAT2XaQg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=G+REGnJmGcYTvzwPUMYIOaXN4RLnNRUO9RTqnR6zCWtG37+azzevLk0rqPj4T3VUJzeUUCFiQb12cotLr+zrdz0uHDJ0vsZRfvwwxtzdKiHT5dXkTfBc9UzvaRkpFiHqwQrpnM/QyXX7MRDmUPyOriaZCwwm7b6KGlAtyt4ei+Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=MHoVwHmJ; arc=none smtp.client-ip=209.85.166.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="MHoVwHmJ" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e57008a646so149512615ab.3 for ; Mon, 18 Aug 2025 16:10:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558642; x=1756163442; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=no73ok1TStGeLP/XVd+vdAffNUb1wcTzWByPRFwJ434=; b=MHoVwHmJbHFKM94Slb6tZs7CAhlnCEwVE/6q8MN2xVEjOQlDaopsuAATbQLHzTTbWf QqsLvVG9877HlT//Fv3RJmLUTfUTYZIsTzbHlcEG6QA77LKrw9cfvVQOuFZziFOHht/u RaUsqqdBaM8Ki/Wuue4vxhBNZIcOtzZFY5dOOcYxWek+1kIskjFPIw0W4xzCU9AVyrO0 sj45fRSlGKE17OLaBpOYx05rQwuw+jTgkj9/3evI3kDYII9Ln5JUmaeALiT8zU1XjNF/ jJyqYSKipKXU2jI1aQRF3xo8ZnYqg9W7L8/fZz48QrhLxd6WZbwrR+mS0GHN+31B7wfd NuBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558642; x=1756163442; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=no73ok1TStGeLP/XVd+vdAffNUb1wcTzWByPRFwJ434=; b=v6iiXFAKq6ChpL/nYp++FerJRvMNZFc3wu436/f9z0sD/vpkCNdd2P3jyiPXAh5NgC RJxNE4Xv2D58uYYEG2cu7Zu17BHMhaSX0fEhmNJUtCPkoAYmNa9/rWUtNZR6iFg2D55A GkvIzjhmRPOIc1iDjsDQ/63+prUXnq8h2Huo8TmwDTNudZAIvqWH7Hog5CusAlv/aOuK M/FsftnMSzq69APnZ/2NKk/nn0w/Oig+5sByKgjdrRJiukegNBjr/4nrJUyf9lnIofo2 m3V/cCxsjms9Ajggf6wSoGJwrnVka4tPazCuUrf+x/aLfoQ+mnRydTPV2Xh7iIxU1DqJ ceXg== X-Forwarded-Encrypted: i=1; AJvYcCXP2ve+Em9iv/VCXjyt8Hs7UMMg17+Jm9YllWE0Y0TDTKLrNZ9rH0Nb2Bob159jMHhqH4qkgMad3+8CK/s=@vger.kernel.org X-Gm-Message-State: AOJu0YwStoAVQnOOD5v9wVxf3mIybYgygKEvwjKzGKuWY83dE/e3nbtP G4XGOSgEDTfDud+41kU9VA5SsRONWPeDmIkt/d897oBnI37N0GZu9XtuJtGBVrPiLalyac2fRYC 7DbescuSRFw== X-Google-Smtp-Source: AGHT+IHurdh+bNvbqq4rcSts2NvIBgNlA+bfgJ0A1Iz1oYUr7I4W0BYAjz+BOz9KO1SHicln1gt8LPcc/sEJ X-Received: from jablw11.prod.google.com ([2002:a05:6638:ad0b:b0:501:ed30:8c8e]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:3a03:b0:3e5:4bc5:538a with SMTP id e9e14a558f8ab-3e676640018mr9183085ab.11.1755558642340; Mon, 18 Aug 2025 16:10:42 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:49 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-8-e4f9ab0add84@google.com> Subject: [PATCH v3 08/11] HID: haptic: add functions handling events From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Implement hid_haptic_handle_press_release() which generates haptic feedback as well as saves the pressed state of the haptic device. Add functions to increase and reset the state of the pressure detected by the device. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/hid-haptic.c | 20 +++++++++++++++++++- drivers/hid/hid-haptic.h | 15 +++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index ef09b4039f33f15d7220e69fbed10bd8b0362bb4..c02af820051c22d1c899db84496= c5a44b868fe49 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -50,8 +50,13 @@ EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping); bool hid_haptic_check_pressure_unit(struct hid_haptic_device *haptic, struct hid_input *hi, struct hid_field *field) { - if (field->unit =3D=3D HID_UNIT_GRAM || field->unit =3D=3D HID_UNIT_NEWTO= N) + if (field->unit =3D=3D HID_UNIT_GRAM || field->unit =3D=3D HID_UNIT_NEWTO= N) { + haptic->force_logical_minimum =3D field->logical_minimum; + haptic->force_physical_minimum =3D field->physical_minimum; + haptic->force_resolution =3D input_abs_get_res(hi->input, + ABS_MT_PRESSURE); return true; + } return false; } EXPORT_SYMBOL_GPL(hid_haptic_check_pressure_unit); @@ -508,3 +513,16 @@ int hid_haptic_init(struct hid_device *hdev, return ret; } EXPORT_SYMBOL_GPL(hid_haptic_init); + +void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) +{ + haptic->pressure_sum =3D 0; +} +EXPORT_SYMBOL_GPL(hid_haptic_pressure_reset); + +void hid_haptic_pressure_increase(struct hid_haptic_device *haptic, + __s32 pressure) +{ + haptic->pressure_sum +=3D pressure; +} +EXPORT_SYMBOL_GPL(hid_haptic_pressure_increase); diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index 25e0e2cef9399199796d8679d66209381b6a59f2..abdd7d710c0b832ad0be8fe63eb= fa7692c8ea5ca 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -70,6 +70,10 @@ int hid_haptic_input_configured(struct hid_device *hdev, struct hid_haptic_device *haptic, struct hid_input *hi); int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **ha= ptic_ptr); +void hid_haptic_handle_press_release(struct hid_haptic_device *haptic); +void hid_haptic_pressure_reset(struct hid_haptic_device *haptic); +void hid_haptic_pressure_increase(struct hid_haptic_device *haptic, + __s32 pressure); #else static inline void hid_haptic_feature_mapping(struct hid_device *hdev, @@ -103,4 +107,15 @@ int hid_haptic_init(struct hid_device *hdev, struct hi= d_haptic_device **haptic_p { return 0; } +static inline +void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) +{} +static inline +void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) +{} +static inline +void hid_haptic_pressure_increase(struct hid_haptic_device *haptic, + __s32 pressure) +{} #endif + --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f74.google.com (mail-io1-f74.google.com [209.85.166.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1D9E27EFE9 for ; Mon, 18 Aug 2025 23:10:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558645; cv=none; b=e+1MFrNYWK/UCP1kaWb71vRlkzhhvN97ik8cn143a32TQfWn8aHl9EVM8Q3gySHePMWVjT7YzfkIcGFD+BvUUFKyUcQ7KTImmUSrK5t0ksapz/zIIZpAjjGsTkAxHYRAgkOqDZQE6Eog1+Pep5ov6Z1wQwmmADozqCuMosIxxig= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558645; c=relaxed/simple; bh=fOUQ9iN+/TFHSMLuk8u/9z0NqvmTbx1gpw+j00H42/I=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oNDHbNOdJSDzhbdtaomnNVajbURH8ObEGThSoixqfrBuBl+2GlOmFo35qP0Fv9D8zxDPfh6T6u06ezXRzWJpxS8pBi1ty9OPoKLx3uJfWJBDHdLSGoen6ROQGttyM9C+HNMQQV14JTUnqxJ+wmKP3uq/eWOeeOD6G4FmtPaY8W4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Pb6gLOym; arc=none smtp.client-ip=209.85.166.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Pb6gLOym" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88432cb7627so476269239f.0 for ; Mon, 18 Aug 2025 16:10:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558643; x=1756163443; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=Xze907Psa5S/IYsuccVxAJQ0ljBH6WFw3XWFWUMA8Qk=; b=Pb6gLOymF78pcFKu/yTkaCyui64GqS000a7v2BPGC3fhIQaux2tdTv9ksI2vY48enA yRYJvtOorJN4aT7i5Y20mM8mNC33qiSaSRo6+yoyvquoWzPeFfqKS3Sni+YCGhaBaKuk C2ndCa5NZ5mJojRu5Rung9HUMHDa295rWax81DHaD+lJ0iICaOL8VBdiYhvaiuUdltqK 74+vykMcryqxBVfLzk6Mb7RQyWKoyQfIIIRQ5mWPR8sk1xEG4mK4nkO1/CycV7D5aGKn LIvVEFvN6XHMkBQ+0al4MBT+/Pmt6Z5UXvTGYpUn1X9BBb5AcpUeEdPG/+8O5/Gyz+kb OIBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558643; x=1756163443; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=Xze907Psa5S/IYsuccVxAJQ0ljBH6WFw3XWFWUMA8Qk=; b=V32FIO9Go2x4mk8o94L0em6kXbW4u/KW8unE0ryNsdFtAtYM2tdRU0pm+1CMTkpC9c qfx2CF4B+23Yu/X83SdAWHbE9jiH7s7vnu8lbMZRxC61paaSBIzAg5Gun6hs9CgI/vOP nEZq5LoLeLI3GgW4HZpHPaNVNXhFbT00opnDpqGeRWCu2AJHFdkCRjXtJf/CrwcOvLJc hCdNbGdWxOitsmZJbUxCB+Eovs1ncWM0VVtbgKbGEOk0WM2NnVKOIC/pYS0dw3Dfj4+Z 8MUnoYl9gbHEM7V6endM3socvF4WJPAzgtwzdAv418KSnV8CMRkvCXZ/bmuzP/5/dQao i0Sw== X-Forwarded-Encrypted: i=1; AJvYcCXREbkQax9+UKuEJJXSH6zk+xyjBeeKOztGzNcQMc3vV1T3U2yKhAh2fCrGKvBvfh9wjzNLtDuGkEbRxZw=@vger.kernel.org X-Gm-Message-State: AOJu0YzH2H+0BFDisSA90ImERIVeegw04x0SoHv4F+9ZEr56CogSYYcF OBjtD0pNkFCh0Retm9xMoXyXeiOLNu0HNznkCEcDrHB83fGnJSxwBhrOJU8g1Ceq7TCPnV+MUTi oa4DJ43fAWg== X-Google-Smtp-Source: AGHT+IEae1a+RGpmevjA4aZuqHwjm+8LM/JeSvDhnxxKn/QsDajDWX8k6ANbWJ5eqhAEwHBj0zXnOe75dCaS X-Received: from iobjk23.prod.google.com ([2002:a05:6602:7217:b0:881:8ed2:a750]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:2d8b:b0:87c:1d65:3aeb with SMTP id ca18e2360f4ac-88467e8caa0mr98419439f.2.1755558643163; Mon, 18 Aug 2025 16:10:43 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:50 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-9-e4f9ab0add84@google.com> Subject: [PATCH v3 09/11] Input: MT - add INPUT_MT_TOTAL_FORCE flags From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Add a flag to generate ABS_PRESSURE as sum of ABS_MT_PRESSURE across all slots. This flag should be set if one knows a device reports true force and would like to report total force to the userspace. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose Acked-by: Dmitry Torokhov --- drivers/input/input-mt.c | 14 ++++++++++---- include/linux/input/mt.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 337006dd9dcf72ef2eeb8580e4dd83babf8100be..09f518897d4a71a4a7625367dc2= c652ee6035d98 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -198,6 +198,7 @@ void input_mt_report_pointer_emulation(struct input_dev= *dev, bool use_count) struct input_mt *mt =3D dev->mt; struct input_mt_slot *oldest; int oldid, count, i; + int p, reported_p =3D 0; =20 if (!mt) return; @@ -216,6 +217,13 @@ void input_mt_report_pointer_emulation(struct input_de= v *dev, bool use_count) oldest =3D ps; oldid =3D id; } + if (test_bit(ABS_MT_PRESSURE, dev->absbit)) { + p =3D input_mt_get_value(ps, ABS_MT_PRESSURE); + if (mt->flags & INPUT_MT_TOTAL_FORCE) + reported_p +=3D p; + else if (oldid =3D=3D id) + reported_p =3D p; + } count++; } =20 @@ -245,10 +253,8 @@ void input_mt_report_pointer_emulation(struct input_de= v *dev, bool use_count) input_event(dev, EV_ABS, ABS_X, x); input_event(dev, EV_ABS, ABS_Y, y); =20 - if (test_bit(ABS_MT_PRESSURE, dev->absbit)) { - int p =3D input_mt_get_value(oldest, ABS_MT_PRESSURE); - input_event(dev, EV_ABS, ABS_PRESSURE, p); - } + if (test_bit(ABS_MT_PRESSURE, dev->absbit)) + input_event(dev, EV_ABS, ABS_PRESSURE, reported_p); } else { if (test_bit(ABS_MT_PRESSURE, dev->absbit)) input_event(dev, EV_ABS, ABS_PRESSURE, 0); diff --git a/include/linux/input/mt.h b/include/linux/input/mt.h index 2cf89a538b18bbc7c99c8705c2d22bdc95065238..d30286298a00a356bc9db954ae3= 62f034cdd359b 100644 --- a/include/linux/input/mt.h +++ b/include/linux/input/mt.h @@ -17,6 +17,7 @@ #define INPUT_MT_DROP_UNUSED 0x0004 /* drop contacts not seen in frame */ #define INPUT_MT_TRACK 0x0008 /* use in-kernel tracking */ #define INPUT_MT_SEMI_MT 0x0010 /* semi-mt device, finger count handled ma= nually */ +#define INPUT_MT_TOTAL_FORCE 0x0020 /* calculate total force from slots pr= essure */ =20 /** * struct input_mt_slot - represents the state of an input MT slot --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F24E727F754 for ; Mon, 18 Aug 2025 23:10:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558647; cv=none; b=YcuJGebjPQf5LDPY++MCb3Yoe9qvo7Qmnq0w3BHrI/G371kMg5jpqBsJj+4sfp7Gx2rocsKagvT4tRzKmD7m0gbyzV0ohXjZWHvHquF0hVLVfHTx95o9EBpRhKycFNdv32vMw1MOASZdBaQQfpXcAl0Q20j18DaBDAw9Ao8GGx0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558647; c=relaxed/simple; bh=QzCEIxx18I6Dj0G3rDwWXnTsi3l8IYWfitCaWWFrWcM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=mAr18dfWQb+LnStE5NHZaoYD6dA0fWkcPEbNSFPItcfXkCHeNd4KhDsyExCQJR3SY51RZd+1FRsdIXqcEmPtYSrLcMVDa/W3T723iC8mPowZH0KlEhY2FvMKb/Ul0KSFsnHDLkUQsbHnB8EZYaYHSudgrCtB02JuSTXwe+XWahc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=2KuOCjSD; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="2KuOCjSD" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-88432ccc4f9so1209458639f.0 for ; Mon, 18 Aug 2025 16:10:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558644; x=1756163444; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=ITZzkiLaqD060Ratl1OWwnlE4RAvXOmdgj6yIgMWt2w=; b=2KuOCjSDquAmEWfnHLRwwqnydeQ54PAgJIdzXWJHI1hbjUFLqa9gDkBlC+bUeE+Fvv +7jdHhOmz14ANN/j1NnrvgpZKeRzfBsVyUTiphDPSOJyH+hjJyInIMQ5uutxprG8PvCI eq1KYz8S6O+tMxaqMTOhZZCfDOPXnSoShcZ5hjM6lYPwU0qwOHdiV60h1aswYPfR/FVw yzhwXKW9K01Cq9uucaWOZ5uuU0XdeE86bPkV08OaBrj0xPBFBn3FwWJ+HrmhaFyUI116 pLE1XaX+r49ROifsy3GVMEM4sLbCVfCr11ZRyh+hyXjkPWcDgjdwokBB1Gwm1hbqMjXx V5mw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558644; x=1756163444; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=ITZzkiLaqD060Ratl1OWwnlE4RAvXOmdgj6yIgMWt2w=; b=XtevXQ9NrL6FYaEq1cTmmw2pG/zKN1Yg+frW+XsdzSvLfAL4KRyB9t0RNC7YYVbh8+ bAK65gESvI8vKWWL2wwXxdoXNa8MT+UkDVb0sFKO+oM5UUYDOLrvpfJl6MmPGV+i7oph NBh4VxIqF9MTVRlzoVtcq7nTStLrYb4hruzgy6Xci+L1gzstejeVIxcUbMdO0kpi83MG K3yBnPWSyCHQVTUsjBnfgoaXsEqfgqlZGOnNUXRIiZE077NDHnc+Jy6wwKWCPfGEipvo J+1Ons8rfbTPJSEbLuRjEW41o2H/xLsiIQP8Cqf/3bBjYQ1u/mtP2T8bXtkl9fJdDu8V 8I7Q== X-Forwarded-Encrypted: i=1; AJvYcCV4eQF7bPkGBgF2ngA2IqiKOnTWdpKgwSTsSGJdbDlHq4PazZcN0ivl48u//SDqEntJ6Vw1NRnBoKC8XvM=@vger.kernel.org X-Gm-Message-State: AOJu0YyjJsaAeG+Hb0aTiPCgP+zCycZd07c94PdEvyVUFNVpIMhtt260 SM5g7RPjtoKoNZTyhSDq+oknVHE3I5fOP6ELMwD6gjafyfF1wbmg40rBWybhbLUtTQy7jC43O2W 1mGenih1nYg== X-Google-Smtp-Source: AGHT+IHIXN747lwgxpSgQ+h7oFBZFXW1MQGKxYRpOFDSVedpgyT/xvpq+lb9cz7ebi+XMoNgB+oEOljtC5hb X-Received: from iotq15.prod.google.com ([2002:a5d:9f0f:0:b0:881:a131:25d7]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:1683:b0:880:f288:e8e5 with SMTP id ca18e2360f4ac-88467ebfc66mr85554639f.5.1755558644101; Mon, 18 Aug 2025 16:10:44 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:51 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-10-e4f9ab0add84@google.com> Subject: [PATCH v3 10/11] HID: haptic: add hid_haptic_switch_mode From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak Function hid_haptic_switch_mode() can be used to switch between device-controlled mode and host-controlled mode. Uploading a WAVEFORMPRESS or WAVEFORMRELEASE effect triggers host-controlled mode if the device is in device-controlled mode. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/hid-haptic.c | 66 +++++++++++++++++++++++++++++++++++++++++++-= ---- 1 file changed, 59 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index c02af820051c22d1c899db84496c5a44b868fe49..aa090684c1f23b61a1ac4e9e7e5= 23b31a8166a21 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -5,6 +5,7 @@ * Copyright (c) 2021 Angela Czubak */ =20 +#include #include =20 #include "hid-haptic.h" @@ -197,12 +198,46 @@ static void fill_effect_buf(struct hid_haptic_device = *haptic, mutex_unlock(&haptic->manual_trigger_mutex); } =20 +static void switch_mode(struct hid_device *hdev, struct hid_haptic_device = *haptic, + int mode) +{ + struct hid_report *rep =3D haptic->auto_trigger_report; + struct hid_field *field; + s32 value; + int i, j; + + if (mode =3D=3D HID_HAPTIC_MODE_HOST) + value =3D HID_HAPTIC_ORDINAL_WAVEFORMSTOP; + else + value =3D haptic->default_auto_trigger; + + mutex_lock(&haptic->auto_trigger_mutex); + for (i =3D 0; i < rep->maxfield; i++) { + field =3D rep->field[i]; + /* Ignore if report count is out of bounds. */ + if (field->report_count < 1) + continue; + + for (j =3D 0; j < field->maxusage; j++) { + if (field->usage[j].hid =3D=3D HID_HP_AUTOTRIGGER) + field->value[j] =3D value; + } + } + + /* send the report */ + hid_hw_request(hdev, rep, HID_REQ_SET_REPORT); + mutex_unlock(&haptic->auto_trigger_mutex); + haptic->mode =3D mode; +} + static int hid_haptic_upload_effect(struct input_dev *dev, struct ff_effec= t *effect, struct ff_effect *old) { + struct hid_device *hdev =3D input_get_drvdata(dev); struct ff_device *ff =3D dev->ff; struct hid_haptic_device *haptic =3D ff->private; int i, ordinal =3D 0; + bool switch_modes =3D false; =20 /* If vendor range, check vendor id and page */ if (effect->u.haptic.hid_usage >=3D (HID_HP_VENDORWAVEFORMMIN & HID_USAGE= ) && @@ -225,6 +260,16 @@ static int hid_haptic_upload_effect(struct input_dev *= dev, struct ff_effect *eff fill_effect_buf(haptic, &effect->u.haptic, &haptic->effect[effect->id], ordinal); =20 + if (effect->u.haptic.hid_usage =3D=3D (HID_HP_WAVEFORMPRESS & HID_USAGE) = || + effect->u.haptic.hid_usage =3D=3D (HID_HP_WAVEFORMRELEASE & HID_USAGE)) + switch_modes =3D true; + + /* If device is in autonomous mode, and the uploaded effect signals users= pace + * wants control of the device, change modes + */ + if (switch_modes && haptic->mode =3D=3D HID_HAPTIC_MODE_DEVICE) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_HOST); + return 0; } =20 @@ -290,6 +335,7 @@ static void effect_set_default(struct ff_effect *effect) static int hid_haptic_erase(struct input_dev *dev, int effect_id) { struct hid_haptic_device *haptic =3D dev->ff->private; + struct hid_device *hdev =3D input_get_drvdata(dev); struct ff_effect effect; int ordinal; =20 @@ -297,20 +343,25 @@ static int hid_haptic_erase(struct input_dev *dev, in= t effect_id) =20 if (effect.u.haptic.hid_usage =3D=3D (HID_HP_WAVEFORMRELEASE & HID_USAGE)= ) { ordinal =3D haptic->release_ordinal; - if (!ordinal) + if (!ordinal) { ordinal =3D HID_HAPTIC_ORDINAL_WAVEFORMNONE; - else - effect.u.haptic.hid_usage =3D HID_HP_WAVEFORMRELEASE & - HID_USAGE; + if (haptic->mode =3D=3D HID_HAPTIC_MODE_HOST) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE); + } else + effect.u.haptic.hid_usage =3D HID_HP_WAVEFORMRELEASE & HID_USAGE; + fill_effect_buf(haptic, &effect.u.haptic, &haptic->effect[effect_id], ordinal); } else if (effect.u.haptic.hid_usage =3D=3D (HID_HP_WAVEFORMPRESS & HID_U= SAGE)) { ordinal =3D haptic->press_ordinal; - if (!ordinal) + if (!ordinal) { ordinal =3D HID_HAPTIC_ORDINAL_WAVEFORMNONE; + if (haptic->mode =3D=3D HID_HAPTIC_MODE_HOST) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE); + } else - effect.u.haptic.hid_usage =3D HID_HP_WAVEFORMPRESS & - HID_USAGE; + effect.u.haptic.hid_usage =3D HID_HP_WAVEFORMPRESS & HID_USAGE; + fill_effect_buf(haptic, &effect.u.haptic, &haptic->effect[effect_id], ordinal); } @@ -392,6 +443,7 @@ int hid_haptic_init(struct hid_device *hdev, haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMSTOP] =3D HID_HP_WAVEFORMSTOP & HID_USAGE; =20 + mutex_init(&haptic->auto_trigger_mutex); for (r =3D 0; r < haptic->auto_trigger_report->maxfield; r++) parse_auto_trigger_field(haptic, haptic->auto_trigger_report->field[r]); =20 --=20 2.51.0.rc1.193.gad69d77794-goog From nobody Sat Oct 4 08:03:31 2025 Received: from mail-oi1-f202.google.com (mail-oi1-f202.google.com [209.85.167.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 388DB28000F for ; Mon, 18 Aug 2025 23:10:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558648; cv=none; b=C8aeKsY7r+MXKNjPD0ZFoVoT11lRRUfN9gC9Vv4SByV0TwNYn26AhE4NAOYHQp44S3Kxankbnb7mdwqmGeCkxeNO41PdaNtaJdklKm/zDoJDLwOScZvS7Lhzmf9XfBu0VjjrF5cjCHW1F5OH42dZ7cMeDXtqReISI+eWe0jCtnE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755558648; c=relaxed/simple; bh=2hHEU72PYJh+SNwdPqD8UkbjBlmg8/6dhsKpY3DeON4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WAQR+n4phAxlaJziWQSvSsLtZ812+hzXwAWhQ6zTZ+hb4WMSEdETg3cR4URb/XZ4myjt4Wf19CJUqzUo+gQrtWqTfFep7wtG71oJRa+YISttE+xcLSjlU2cewsggkjy019DeVhu3YeIqXKu0nEKQCo4Zb36DGn0mFYxJBrBEUTA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=jOrlyiBK; arc=none smtp.client-ip=209.85.167.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="jOrlyiBK" Received: by mail-oi1-f202.google.com with SMTP id 5614622812f47-435de71710cso7150158b6e.1 for ; Mon, 18 Aug 2025 16:10:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755558645; x=1756163445; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=v6LP4kbkBa88jvBhrFEiryEKhPYdSyeLgBMrYzBXaW8=; b=jOrlyiBKYTnXaAb79/VUneC6kJzsV7MaCwLamcSHrzUJQSxMM8EdLcYRWSLp/GHZyC VZzzJBJ1sT6+TL1AxydN/rLis6nxQ0Nw3Y2KKnNvVJ7/EKZP5OoDshHGkv//nquCaF6K iO/rmbxs7V/o7TV6pzzthOB2dZGiX0+zIJTQiFQeNi9GuQZnZ1g44tRczaETACzqHT6b Jirpihi+3OvKupb6u/9CNfm6VFeAY/lIba/SCN6qx8umljrQkl9kiND8ZSIwJ/MhgrJA kjmLGoO49sfY2XT+OYxgqoT9SLJNTJzXIDy6H19YIfjSMhfnOkGwCVDONpJcTnINFx4/ Qi8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755558645; x=1756163445; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=v6LP4kbkBa88jvBhrFEiryEKhPYdSyeLgBMrYzBXaW8=; b=vFQFTLWnnbMKiLHBHmxGA5/LIRktakgTyzoPtMfgtoc9hr30nJrHYQ+KipxBVmqnso 3TqTJuQzVs7eAynsU4UbDQuX9CjhLfQ8GfYAQdEo+ZAqnr+4X7oXp4+Q+EIN9Oceyh1D lJSlen/6CU0QXuwtyhylTor4dhq2ikBRMSxJRV8qlo/MH4WZXtNCC5IHpp/ihIfHrKMM kMVFGO1qexQjJqy8moW6QikAV9wLEr3lY89gMsb476SoVixOfUkCpVT40Di1eEnY4Bnv aNX1+wLUDRpB7R8hzaTG6DLTbWFbgp4rcG9v6UbbzoBONwqlifA3rlfu7Pq8XGrZ9blO J/fw== X-Forwarded-Encrypted: i=1; AJvYcCVQgMBxNx9B/FhVywmVZrKqnS+zraWdeeR+qsyuKXNPAUIjvXnnbycGpVS/SBGaqLQocTBpI9gQdy7asdQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwOSOIvM5K6EABwB/LVN0zluhi8uMKcZJm+YUEmzJULU7wKwgrG dpYdDdAAzb+5/4HoKqKNmcLj1cVtb41xyvU6coFAg09AUb3Bz9vRGFmyVdyU83ww6W9So9rvx4M NAj9x5LnBcg== X-Google-Smtp-Source: AGHT+IGvHvXylkHG6WHZrQWzPSMwYKk8K05RhCTgWLj+FR1COmKkfK+rlfyJhr4vBYqNgMXFLIyPTGnZ4b1E X-Received: from oibbj22.prod.google.com ([2002:a05:6808:1996:b0:408:fef8:9c6e]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6808:218f:b0:406:71fd:b610 with SMTP id 5614622812f47-436da1e7e5cmr308794b6e.33.1755558645195; Mon, 18 Aug 2025 16:10:45 -0700 (PDT) Date: Mon, 18 Aug 2025 23:08:52 +0000 In-Reply-To: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250818-support-forcepads-v3-0-e4f9ab0add84@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v3-11-e4f9ab0add84@google.com> Subject: [PATCH v3 11/11] HID: multitouch: add haptic multitouch support From: Jonathan Denose To: Jiri Kosina , Benjamin Tissoires , Dmitry Torokhov , Jonathan Corbet , Henrik Rydberg Cc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Angela Czubak , "Sean O'Brien" , Jonathan Denose Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Angela Czubak If CONFIG_HID_HAPTIC is enabled, and the device is recognized to have simple haptic capabilities, try initializing the haptic device, check input frames for pressure and handle it using hid_haptic_* API. Signed-off-by: Angela Czubak Co-developed-by: Jonathan Denose Signed-off-by: Jonathan Denose --- drivers/hid/hid-haptic.h | 16 ++++++++++----- drivers/hid/hid-multitouch.c | 47 ++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index abdd7d710c0b832ad0be8fe63ebfa7692c8ea5ca..c6539ac04c1dbd36fb25eed9370= e6fe747a28f10 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -103,19 +103,25 @@ int hid_haptic_input_configured(struct hid_device *hd= ev, { return 0; } +static inline +void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *h= aptic) +{} +static inline int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **ha= ptic_ptr) { return 0; } static inline -void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) -{} +void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) {} static inline -void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) -{} +bool hid_haptic_handle_input(struct hid_haptic_device *haptic) +{ + return false; +} +static inline +void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) {} static inline void hid_haptic_pressure_increase(struct hid_haptic_device *haptic, __s32 pressure) {} #endif - diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index b41001e02da7e02d492bd85743b359ed7ec16e7f..94dd0033290d6ae37d82f0992b9= 4e24ebbc1f301 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -49,6 +49,8 @@ MODULE_LICENSE("GPL"); =20 #include "hid-ids.h" =20 +#include "hid-haptic.h" + /* quirks to control the device */ #define MT_QUIRK_NOT_SEEN_MEANS_UP BIT(0) #define MT_QUIRK_SLOT_IS_CONTACTID BIT(1) @@ -167,11 +169,13 @@ struct mt_report_data { struct mt_device { struct mt_class mtclass; /* our mt device class */ struct timer_list release_timer; /* to release sticky fingers */ + struct hid_haptic_device *haptic; /* haptic related configuration */ struct hid_device *hdev; /* hid_device we're attached to */ unsigned long mt_io_flags; /* mt flags (MT_IO_FLAGS_*) */ __u8 inputmode_value; /* InputMode HID feature value */ __u8 maxcontacts; bool is_buttonpad; /* is this device a button pad? */ + bool is_haptic_touchpad; /* is this device a haptic touchpad? */ bool serial_maybe; /* need to check for serial protocol */ =20 struct list_head applications; @@ -525,6 +529,8 @@ static void mt_feature_mapping(struct hid_device *hdev, mt_get_feature(hdev, field->report); break; } + + hid_haptic_feature_mapping(hdev, td->haptic, field, usage); } =20 static void set_abs(struct input_dev *input, unsigned int code, @@ -856,6 +862,9 @@ static int mt_touch_input_mapping(struct hid_device *hd= ev, struct hid_input *hi, case HID_DG_TIPPRESSURE: set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); + td->is_haptic_touchpad =3D + hid_haptic_check_pressure_unit(td->haptic, + hi, field); MT_STORE_FIELD(p); return 1; case HID_DG_SCANTIME: @@ -980,6 +989,8 @@ static void mt_sync_frame(struct mt_device *td, struct = mt_application *app, =20 app->num_received =3D 0; app->left_button_state =3D 0; + if (td->is_haptic_touchpad) + hid_haptic_pressure_reset(td->haptic); =20 if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags)) set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags); @@ -1137,6 +1148,9 @@ static int mt_process_slot(struct mt_device *td, stru= ct input_dev *input, minor =3D minor >> 1; } =20 + if (td->is_haptic_touchpad) + hid_haptic_pressure_increase(td->haptic, *slot->p); + x =3D hdev->quirks & HID_QUIRK_X_INVERT ? input_abs_get_max(input, ABS_MT_POSITION_X) - *slot->x : *slot->x; @@ -1324,6 +1338,9 @@ static int mt_touch_input_configured(struct hid_devic= e *hdev, if (cls->is_indirect) app->mt_flags |=3D INPUT_MT_POINTER; =20 + if (td->is_haptic_touchpad) + app->mt_flags |=3D INPUT_MT_TOTAL_FORCE; + if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) app->mt_flags |=3D INPUT_MT_DROP_UNUSED; =20 @@ -1359,6 +1376,7 @@ static int mt_input_mapping(struct hid_device *hdev, = struct hid_input *hi, struct mt_device *td =3D hid_get_drvdata(hdev); struct mt_application *application; struct mt_report_data *rdata; + int ret; =20 rdata =3D mt_find_report_data(td, field->report); if (!rdata) { @@ -1421,6 +1439,11 @@ static int mt_input_mapping(struct hid_device *hdev,= struct hid_input *hi, if (field->physical =3D=3D HID_DG_STYLUS) hi->application =3D HID_DG_STYLUS; =20 + ret =3D hid_haptic_input_mapping(hdev, td->haptic, hi, field, usage, bit, + max); + if (ret !=3D 0) + return ret; + /* let hid-core decide for the others */ return 0; } @@ -1635,6 +1658,14 @@ static int mt_input_configured(struct hid_device *hd= ev, struct hid_input *hi) struct hid_report *report; int ret; =20 + if (td->is_haptic_touchpad && (td->mtclass.name =3D=3D MT_CLS_WIN_8 || + td->mtclass.name =3D=3D MT_CLS_WIN_8_FORCE_MULTI_INPUT)) { + if (hid_haptic_input_configured(hdev, td->haptic, hi) =3D=3D 0) + td->is_haptic_touchpad =3D false; + } else { + td->is_haptic_touchpad =3D false; + } + list_for_each_entry(report, &hi->reports, hidinput_list) { rdata =3D mt_find_report_data(td, report); if (!rdata) { @@ -1777,6 +1808,11 @@ static int mt_probe(struct hid_device *hdev, const s= truct hid_device_id *id) dev_err(&hdev->dev, "cannot allocate multitouch data\n"); return -ENOMEM; } + td->haptic =3D devm_kzalloc(&hdev->dev, sizeof(*(td->haptic)), GFP_KERNEL= ); + if (!td->haptic) + return -ENOMEM; + + td->haptic->hdev =3D hdev; td->hdev =3D hdev; td->mtclass =3D *mtclass; td->inputmode_value =3D MT_INPUTMODE_TOUCHSCREEN; @@ -1840,6 +1876,17 @@ static int mt_probe(struct hid_device *hdev, const s= truct hid_device_id *id) =20 mt_set_modes(hdev, HID_LATENCY_NORMAL, TOUCHPAD_REPORT_ALL); =20 + if (td->is_haptic_touchpad) { + if (hid_haptic_init(hdev, &td->haptic)) { + dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n", + hdev->name); + td->is_haptic_touchpad =3D false; + devm_kfree(&hdev->dev, td->haptic); + } + } else { + devm_kfree(&hdev->dev, td->haptic); + } + return 0; } =20 --=20 2.51.0.rc1.193.gad69d77794-goog