From nobody Sat Oct 4 09:39:56 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 6BB461F4177 for ; Mon, 18 Aug 2025 14:28:58 +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=1755527340; cv=none; b=mvnHsMi6yyHqMb4KzSkt/GeqiIc0dvFQegKftKJkIdpD7LN/b2e5u9am3H8TSZ1iyF2rl8hCw1GGRg4tKW7wWe0WS+hJeQMuSKy772jj3IK70akMJuvzmcVaRjIjL57f0YPKVAHOSD3QCpfG/S6tWEr+pHiUJ6OJjuWbSfsKw0Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527340; c=relaxed/simple; bh=41a2+FA9bH8X9sXvLwRCtUwLratquyBIH2dNcY3H2CY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=byXX19H3c+6x/5QZiNOw5TGMCsL5HVe6aPgeMGiFXkj739zm1V7pSFwC+xUSmfDgltfueDLMF9dI7t37U3DuroYEEX30RR7EBqw3JXWQ3/vYIzlvfQ/UOI7ZEEVewtL5czITLsk2mrj7w5J4Xx5ED2/uJG+3F5zFFs0ntpRP9Vw= 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=h/3hGC1H; 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="h/3hGC1H" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e56ffb33b7so134874185ab.1 for ; Mon, 18 Aug 2025 07:28:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527337; x=1756132137; 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=3tFznBWM0IW+McHrcF61sMaSKByQa6x4BTWeVHOyUXw=; b=h/3hGC1HYQrRlAE/RQSB32dPF1dobMrrppbfpWldAG6LHFx2zktmoeRje6CC5kxGiG aLRit/nVMqQhQELoN2pce1Y3OOL6qK7lzCfk2va/wkL12oTuyrM7q5zY00aEfUB4lHwg eguxf4NOmcAEP7YMlvdRlRvgeAxqLNLjp4Byi2KC6x3gHEHCjbLF8xGkwpuNoNghTRYU C8+3Fvz3ZdRsaJfK7FwdA7JKfT1SWE5CgHYymr+CHEXOfR1PgETr257d8B9iKd9MxVSO 2rNBlmq94g0KOOBCZPAT6K0K0ibMC3XG8icK+toMHglvKTt9XZajRorWi+BeJNIermtW IMhQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527337; x=1756132137; 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=3tFznBWM0IW+McHrcF61sMaSKByQa6x4BTWeVHOyUXw=; b=beEzosxbMJMox1chR6iLNDdBt6qNhgFQuZ2Z6yUsCjiTNOl5mOAbpBT9USK6GybmCj rsNdAozQ34NNxfSqiBB5+RyXVEgti75UQExBGP00qMkwRI/vkvDzFYUMZF+X0hnuAsxc AWSyT0CN4y6EUt7Rf5Bm3dY/hnnjBnXyJmKU1BAptMLUvL4XPWb3bT0mdQqm4O/wljUS jCfoC9I53aGW8GW+7pu0BOoCs9nDwQLzJKcBNSKwcq6Yq1HVKIWEsvQmykCZmFxyLMJQ 11DVgCKy4L+dSViEjT0mjYjQzNEJx5fT766SxKjKrFoQ96NwxFRy0/VHt7tqs9Jpq/SK pufg== X-Forwarded-Encrypted: i=1; AJvYcCU22OaAOgiz6XCGfkggFHh09ZX3lQBJNVsk04C7ML/RrlxPQXrsNmFpdWCpe8imnplvkjJwZE867OKHhIQ=@vger.kernel.org X-Gm-Message-State: AOJu0Yy8iRDIauHsTF5zX+oW5ReA9i565+tG+OowMni6VrHxgNVs5C/L jr2VUmnMQJ0/I4P9pvyIjlg5FBj9R2riNTPrcW+F4HHHM/5hHGkvtyqnViYNMa+L+p46QRnQziD Xc+s+JE3BLw== X-Google-Smtp-Source: AGHT+IEBsBH62doUUoirtmqHQgZp9vQHBcGYX9e9luOmWcXQBkoj3b2JLGzvlK8O2+EdtDms+JwRqGLtS19k 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:6e02:1b05:b0:3e5:4b2e:3afd with SMTP id e9e14a558f8ab-3e57e7fdcb8mr245795495ab.8.1755527337603; Mon, 18 Aug 2025 07:28:57 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:01 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-1-ca2546e319d5@google.com> Subject: [PATCH v2 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 2025 Received: from mail-oo1-f73.google.com (mail-oo1-f73.google.com [209.85.161.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 BDD76321F2B for ; Mon, 18 Aug 2025 14:29:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.161.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527343; cv=none; b=in+VXNW/wgvlyAVjScwtjHDeKCW73JB3bKxtslrhuX414apGC0amS8nYOxweCW9V+P3m/q1MDRbiUIzW6Xo9x6L0uKSOmaj8+vOy5co4T1PviygF7JpNIgmL+v7jLtebgYn0VW0U2C5unQH4GcbVTL5eQTTUI0V3E3ONWAin3sM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527343; c=relaxed/simple; bh=aNI7wDQq42gvs6IHxjTesvg9Tj0CDvewX31lLbl3nkg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=NKwugN7sFrMJj89bSKSRHRGX4d9zsKWckwrcN0yMordyzi2bFgRdXgrHmPtaDApNJ5G93REwAo4wdJZBABhO8PGfh+9ykTkvBUkvRzWGQt5ZeU+ezXxIxjzR5NeXwPlbTDqx5GdNVficTpJOcCRRYLofpCPGyWn5o5fQT5malms= 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=TyPypqhX; arc=none smtp.client-ip=209.85.161.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="TyPypqhX" Received: by mail-oo1-f73.google.com with SMTP id 006d021491bc7-61bd4e3f1e9so5475968eaf.3 for ; Mon, 18 Aug 2025 07:29:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527341; x=1756132141; 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=vH390rPGDQhOeuFsB0LWL8BwN5F2vRABC0vSgzm+Fzg=; b=TyPypqhXVL8+cnvqZgXTJKETelcgMQcQZnqkRVQaAdwJqeK3Uptm7ce0f8F4RT4oqg sSP0E+5buTrlaGGfWeFOUzceON/xJ87JtYI/+K2oDUJL7WoNjY2X9BCog++GtESMC5o/ IeeIInZR+IYInKV79u6hvy1uyHbhHVzhg50c0C0I5sGtMh0X3P4kK1/vJ76KFPW9Xee1 RrzxflavY7ahnlG/f/BUVAAnQ6FRHHdF/x5xX25lDOT+2jQjGf5/SZ4OQ3GGTSLleuTi KEVWlxemQUUqMh6NfPol9/xKUsm0ZKXqKLY2uGPnLiqNzNLGaBoqRXaOxTyPqKQdAsXC h44g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527341; x=1756132141; 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=vH390rPGDQhOeuFsB0LWL8BwN5F2vRABC0vSgzm+Fzg=; b=Otq7eIQe5AtvNJgD0rh+tpmyvH06/BlXmAMMyB/XJJqXDCLf2NxomAUuIceYFwGc0k KAvZWCcxK9XGe2eTC1rO9WLHBijp1h/cf3VKy27sRq9b9ANUVUHXZEvoX0KMyV2fAI3Q fpn7KtOtQKmUV0LgbANP+8fPjxMPsXQxHYre8eDbEoFw+8WDSBnLLL8rPBzxdHWq+bhl czTOEUxqEF5sNo6vMKvu1T7wyFanvi5BPvRii1nueK2Pk4CT/4bmt/aOQJVtioCayqSz 1NW74T52FP7c8TBbitmGiZ/fwOVfRYKF25I3x2HfO/U1opzqf0D3PC+UZXMUBluBRUef nPaQ== X-Forwarded-Encrypted: i=1; AJvYcCV0J7l5Z5JtHZVIQeydy/ulVNvmGzzrlR1WtnEuXOEP0m/aUJw2ZvLe/iZAejxDR28BJIC5pHnBImV08/U=@vger.kernel.org X-Gm-Message-State: AOJu0YzWgox1v5IGGvARwSZ2+/+1BLCFuh9QaZGXG5C47tS/A/aCldVD Nu6oyETFdOCQr5vQwYiQ/Bz6sbt+Jm1Dvf7/ckHpHBTb7LiXC+OXqLB9Se6W071VWKZUgo98IDl EktkDiA/i6g== X-Google-Smtp-Source: AGHT+IF7LQB2VtAzNdF/oWnkJJ4JU18PbSCONf+I4O61kiuhlhO80SRgJyZjwu7I4Eeb+rnaih3gvPXcL6/O X-Received: from oabut16.prod.google.com ([2002:a05:6870:ad90:b0:2f7:8c6a:6ac5]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6871:520b:b0:2ef:3e4f:de9d with SMTP id 586e51a60fabf-310aacf254bmr6245173fac.17.1755527340838; Mon, 18 Aug 2025 07:29:00 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:02 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-2-ca2546e319d5@google.com> Subject: [PATCH v2 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 --- 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 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 7B037321F39 for ; Mon, 18 Aug 2025 14:29:02 +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=1755527345; cv=none; b=Gk7xV7rduAVtIZeXIvaSjaIzwfsMZu0CmloHlFPKOUsL3Lk/ThxONF3FqLhwsLQbG22xD0levI3QoqmS3S8rf+85NCSpSqMtIaWSkUP0R9V4Mo9gY4dhJptCbdEb/SPrQnBKqI3tgUaBbHi9fbprm0lhO0yFTo/wDZY86smuTvI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527345; c=relaxed/simple; bh=eyRsoGGC88VxfOwOqnlreduF9Is8JdSJNsfmGu/sGbU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=HBC7wddV5jlX7AULeIwv/geqFyeQVU1EhXQAh4frH1eK2lOlOlqJ4rf32MZ8jIf8V+x3KRxzenytq0lpbd6SLTcHFPnxA6IUH1K/ZXzAzyG5ahagDKfjMSubZUz9VJBASwT5Vf7mkxUGfJyQZaAZYAzzdePxytZ42vn+gwYYrOM= 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=ESc4LO7I; 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="ESc4LO7I" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-88432ccc211so434175339f.0 for ; Mon, 18 Aug 2025 07:29:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527342; x=1756132142; 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=RipN+nv3SXYZFWbwNBz8QltNazthleRYvjWSHCZV55w=; b=ESc4LO7IOwKojRNjLXogioSQpWnm3pMoVjs98y7DOtHNqzNMgrQBaS0WbLbXafYO5F 1C9+pC6jIeommnuGagZIYJ+tcOr1B8FVSPLU20av8Lute3zfu8orHaRtxvBReJ4Yk1Vo fufUAvIO0qf8pE85C4nVLhmQjMZOxbYgAFFxgnn6sRY+wvVZw+jy4E6PSR2oOMNygkzk kpUBzpo1YyGjTYFNvaHwgWLCx+hhzMIHIypGDJ+uy8c/lrlbKWJkf6aZR1HXZQAq9z6O eYpwXockQUGpGb8+N2LLiwVGwpNyNUEAC7lAGllqLpYdwSOQhQj/l8rA958x5ELy4J3W gomA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527342; x=1756132142; 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=RipN+nv3SXYZFWbwNBz8QltNazthleRYvjWSHCZV55w=; b=Fb4GPj/3dS6BOVZ+l3fSUMFjF01mqpcIF2XvvqMbghrUQy3ryqd9dsrAWgBVhdlWSf AeAJ31Abqxrjjw7gp6Vy+pE+xqaH+OZPJRc9+oKO2nQiLBZRX+w7hxfFLougiukTw88h PUPz6D+0V0RzC2CNPNnHy2eidaMV1sT1dEEwGzqnBLZx1yoDAswCnI/+LFWdoR+j4YqU X1omO0/AU3L+0T58NalCZoXGce5M7jq6UPNzUTb1KF4cIOr1W1uNmvLBCib8VJw3PJ16 3i3p9AaQEA0y/PSLWQUHFynx1Hk78kQTvPHsNbl1jrlbMqYQoaECMA913raRx2HaakjE AIIA== X-Forwarded-Encrypted: i=1; AJvYcCVgTVGDmJjwVfEMnMciMpXk+Ne8ZlV0K8RzIV3Lzy/rGryDeSxTrMDErNIP1hRjR5k/9qgOH+Er9VEQxJA=@vger.kernel.org X-Gm-Message-State: AOJu0YwwmV+wSh+VHKUgEhoJzj4PTRxMWJwPIenilySr7DFbDngQV+bC t/y3HwbBVt8YHyBbTxp27vN+I2ge0sBROUzcDU0PXXrV/wlVoL1C+SyRCzMGsV7NSVO4XQdhU7f XsGqGhqixQA== X-Google-Smtp-Source: AGHT+IGsMJ1dugoDXs5YZjVy2GFxqSG36FxsyLGBMgRfZ8WXl7iarDTVmB6g6sDJ/ZydNTMQVIHJ8yhRdk17 X-Received: from iov15.prod.google.com ([2002:a05:6602:750f:b0:884:4d31:3618]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:48:b0:884:552:d2be with SMTP id ca18e2360f4ac-884471cf28cmr1453961439f.12.1755527341772; Mon, 18 Aug 2025 07:29:01 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:03 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-3-ca2546e319d5@google.com> Subject: [PATCH v2 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 --- 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..6f7aa9e8207c4aa825d9694ad89= 1f4d105fe8196 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) +- report correct force per touch, and correct units for them (newtons or g= rams) +- 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 2025 Received: from mail-oi1-f201.google.com (mail-oi1-f201.google.com [209.85.167.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 D2C1A321F5F for ; Mon, 18 Aug 2025 14:29:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527345; cv=none; b=PeQnHcR2r+4WbcPL6VxCL6PZz9eyKZoNnPFpQ4sWXvMtJ2lVYVMt202Z2yWhuCKovalC7oKkqEKroSI06xgsOtoMHF4N2WU9DUyDW+Yzmq0rwQtDzN50D1wpgbk4uddueH3xBqiOrCEm+a9GY3vAsmYqqU8qY4EgiwEEnGQnsMs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527345; c=relaxed/simple; bh=LJ1GlPQvHqQu3u0FYX989UGu1oTfcrJCz9sTwuz2MHc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=orDjzljx7aHV7gMZBpDwcW0MIJQVA2VgCWHFhp8tYJUNC8RrB0yivqgLSe4GW9y2B+92t3nlN4FBxIlLBd9cQqC5jZmfmcnlhgNd+SPMkjUoxcZyeIjYF3UxdXsSYJEBEWQagQMCTDPwfVUd3DoNktzLedLqNVao2uD7jF8ypOI= 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=AirM45sr; arc=none smtp.client-ip=209.85.167.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="AirM45sr" Received: by mail-oi1-f201.google.com with SMTP id 5614622812f47-435de5bb303so2568866b6e.0 for ; Mon, 18 Aug 2025 07:29:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527343; x=1756132143; 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=TAAxlO68X25OTp3J1WUCgKbQRx2Z1emMAKOD610BueU=; b=AirM45srXIm2uP3KGduWo7q/B1pGNX0rBV7BNvoP8Pu7QnPAUdfOtiG7ebAOMc6kiT pjcW/uNtLhnSpyelwF3RbLSd+wWo6lM40hQhAmJrECRWBUzFD53zVa4dUi6gEl2rLso5 rm9t6d4CZtnCNetO0GluVZHqjqvbv5uaiUruHk+2DXK+w7SWYpG4l16ZDGfY2Vpj3iro ewBLvoQve2/4Y5gm85sAa+KsQ7t8xgoUaNrJwHJkg5UhJ6PLxyzGNT/nWtS/uPfWUrF2 MVTqTencoQepj2KnyUEBTKjo1v05fPtAXN1M1KXkXfwNXoVFqmEFjh8GBM6fBYoMHI8P plhg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527343; x=1756132143; 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=TAAxlO68X25OTp3J1WUCgKbQRx2Z1emMAKOD610BueU=; b=V/CQT1KjTX2/qPfAwMSsLkyK1bLUt7FSaNLsDZDWB4IQ3EUnWWSHhbZhBt+1AepjvZ OOWlxDO9E2p1TVE/nkXZLI8LNHnF9nGWBIIWqMfCgrY8G7d2IWbPmu/mrgN2mwjfbuZB w03AQkoXxttgeMU2gOlpBxBZAk3zixRcrZkUsyb6dm+pKJw287/ywKSNOgYmjUf/Dtno D/z2tGvCyC8FZmbwKjoWhiaDmjKl85Jc04ScYoWUyLLGlHISwsDMbo2AefV3i6ENcX6+ IOuLe78bBGJeD83XhE5wyS9K23cxaPg7CFKaKPaEuZLX8ybIFWQEDUjIsD4lwkQoA1fB WQsQ== X-Forwarded-Encrypted: i=1; AJvYcCVniNwI3ttWyjjSk8D7hgXglnuaGtWhYsguJMPc0qAIVFV9ExdjQ8BlXtIyaKnLR7tQx2DnGbAv9ARZL6U=@vger.kernel.org X-Gm-Message-State: AOJu0Yxo0KfeYRizty+XvR61vwGB143mwk1Ofl5g6VAo5u72HBV7MIdx zxUeQBtrCZiGQOgvDCH2QFYLw9Bj5YwtTwIDJD9tZa7G5KN4Vlm5vvuFOcqV9iC7qwGk3T17MxK m14FKXQtVzQ== X-Google-Smtp-Source: AGHT+IEwbnYw3hhSKeD0w0SzfJ/3gajyKjN1LgLpZCzsAHO9XaTpDy4Q1dpo5YON1mlN+ZzLIBRAIQjM/G31 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:6808:23c2:b0:434:39d7:cb11 with SMTP id 5614622812f47-435ec361f40mr6179116b6e.6.1755527342946; Mon, 18 Aug 2025 07:29:02 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:04 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-4-ca2546e319d5@google.com> Subject: [PATCH v2 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 | 105 +++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 189 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 43859fc757470caf6ad43bd5f72f119e9c36aea7..cbbe82a0a2ba257e45f77ca014f= b5f08b71fc62f 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 + bool "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..b729f8245aa60c3d06b79b11846= dccf6fcc0c08b --- /dev/null +++ b/drivers/hid/hid-haptic.h @@ -0,0 +1,105 @@ +/* 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; +}; + +#ifdef 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 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 CEDB432253E for ; Mon, 18 Aug 2025 14:29:04 +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=1755527346; cv=none; b=n/OrHEKG3Tz8P6mY86D3T9bZuYSnPpRLBCak8ikDgiUle1FFKzNkHlgxL7dYw4KHxfJC53TbBOfBrGArOv8SbcHQ5CObFPk+Hvfd0dfOKt1h2CfxDRig+PQockQKzuKLwomXYqz/pZXvrKWlySxlvJPBaFn0LFmSxO6cavAgDUA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527346; c=relaxed/simple; bh=x/oEAdvTY89TEEY1xHYiXUYgEnx1TSPHrLh5CPsg2H0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=HR5awaTAJUQUP+km9W9e7OpXidQXcHMUFjm6k+wBYceozTi7IC3YyBFeB1fuUj1RnOYsY1ef9i+fBUynRBNOTX0f3F0Sf4JmFl5jMrPrhvOW7XoRE5uxDhbw6KsruF3LxIpjtpVpnRwA3K2dvfaW9TNj2pRbgUbiG+3iN4NuOio= 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=Dna2+mSN; 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="Dna2+mSN" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88432e1c782so530998239f.2 for ; Mon, 18 Aug 2025 07:29:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527344; x=1756132144; 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=3z0lOGnoy2DTiFRtSQ834KWO6kfpYDPrVEHJnQZTKok=; b=Dna2+mSNhgWoIoabV72mea5G+en/4hp4KwWb5A/F6j3jTpeTxOBB+UkVX/VupT+Sqm IirdhzormGDNtuuuJxpuymvlc8GczjZgkMTwIRsGRamI8Rxktg4+6M8wc4kWemAOaHSO tf4Wn3dutHnUhIpUqFDYRjJFhkZ+DKPTywWfg/5aXoRfW2eUGe4i77J4WjYrhhPEfG5n mSqa9pBHpzR2ypr/qsP+pglL97lfxe5R45odUNRnL5J3eYZr1Zz8XXjEfA9IKjjjEvgX UaV8g778LZCxGIZen2Ppkw4SxyeAd+ryDG+d6/+GsLEccrjE9p5yWkg4s/CH3ndvWhlj PaDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527344; x=1756132144; 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=3z0lOGnoy2DTiFRtSQ834KWO6kfpYDPrVEHJnQZTKok=; b=MDO9UztJ/278kboOp55EP0TTXItnfkwoCgtxlsHImzH4fA4Xkj+j024hdlOlk7nyxU 0MAMhHCxqCpMifHYI2QJ10lVD1Wk9f+kFMlOhbfGjMquXdPz+peHyVBOxMa7tllLXura QArsl8W0q6KBpxdaznwMsEXH91Uei9on3RRHGPNEbLUijrXzEZeK8MgVwO/WCwpK3Lmq dd4N5K2kiDkHCGRmacBZXFgyEpO8gzsYkySCy8RHvxa6TVOtHfCYXOseIbDZYd6/sP0b cX47fNlgRZmzv7B4AtG/doXae8ngqC9tRNO5OMOvXGzisDAqu/0uJkq2D5hE9vK01IXb TPOQ== X-Forwarded-Encrypted: i=1; AJvYcCW/V58FFJ1L6BOZsqeodE6zs1w2f0x5wVq1HS1k79CXd8deM9rYVSiysFXjLzXJO8K+gl2n5K/I4Up9ogA=@vger.kernel.org X-Gm-Message-State: AOJu0YxS5o6GKDtr/eLY+at2SoEhDA+rPac3p6y1e7sDalRO1IFQhD2f oQmQvao4iAAtkdRhKwIQfjZGJY5c1NDaPswEkmSCtdISkKWx+8kQWnvqWZ6v/1WDd0YO1j5bb9r AXUUejqocrQ== X-Google-Smtp-Source: AGHT+IHn1f5s0goJbEhBCAC7DNa7GiAi2gXYe6kZJfpneYr5QGRSUwUzApKz5hpqoRdffdS5McJgcY5ZqlP+ X-Received: from iov15.prod.google.com ([2002:a05:6602:750f:b0:884:4d31:3618]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:640e:b0:881:983d:dd7b with SMTP id ca18e2360f4ac-8843e3eba5emr2445335539f.8.1755527344033; Mon, 18 Aug 2025 07:29:04 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:05 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-5-ca2546e319d5@google.com> Subject: [PATCH v2 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 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 744A132255F for ; Mon, 18 Aug 2025 14:29:06 +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=1755527348; cv=none; b=tnq3uaNbQ7QV7oSwLQkxBp2V+nLIsx7RiolFQfHGAZmRlLAzaoze9I9UhI1pd2k8rwGZLkXDcb/HoX235pRWkyOfJT1fBtG8mAfzbbz0EryrjjLFCwZABqFeSHbdRY/DqS04DtlsnYiWAIqS/Gf+X7dwIj/kxTtTXwOb83/p2jI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527348; c=relaxed/simple; bh=BnYlPFEAjksAQJlo3K0HFoQK9nQo4zHql3sG4pGt6A0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=RVokVNvpO9F3VaR0GxPxk0/qDremagLyuPzzJr/FfTqGaM2zTe5oHq1MaUgGsviUPdhKVZ9yqAKwsZSmPxr2P29ch94kO2Vd/32SEGAjA7a2HdcS5/8faTkEWikc/2eszn3ybQhJEZVbl+1AD6fN5GIqVPbLlUEUtifG94XJLYk= 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=zX25m3mw; 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="zX25m3mw" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-884454c97dbso224352939f.1 for ; Mon, 18 Aug 2025 07:29:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527345; x=1756132145; 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=Y2DJ0jN8+wv+XocKphcaRc1V65MsyOdZAx9xhRNM/5k=; b=zX25m3mwPqxBIzoeWG4u5ECs/Zh5hxUeNu8QbQoms0MUwtgWx+wgvMiT3YLcrZ6yfM oaTLb1Kr8Fg0EGQzfXbIX8M8U8ZJ7aKGft1NFOQFqPSvBrrAA1AgC1JJfMGk7okiunpf GDR+AxRWvY+/zPLz7qexqc8Pq6gEURA9IILZ7N1i0vk2gtcXyv6HaSuFTzf3BCjtm0Wf 0lluG6auauFBLMBGjOZtyTPpbdJYgOCgLIByrByZd3Kj0U+DDCBxnzAXnKU4mCuzH9U8 4M16TWEWGkcDRd7ovcGokmWAaEG8f+JnoT+ds2O7qEwM+culO/kgeT1K6zAEN1WuySXB BNOA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527345; x=1756132145; 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=Y2DJ0jN8+wv+XocKphcaRc1V65MsyOdZAx9xhRNM/5k=; b=BZZz/AiNoDh54OoQFZhRjz/l5ZKEHm7Mjc/JBP/iJbESuVMA6oTVmEXsO6/i5zdcJ8 aRRu/IdwJUPofiaucshhaAVXuEXHgFT5TMabN7jr0breDHS4dXm6eYkCU4xQAOxsKdFc 3Z6Y6N5Kh4YaPS6CUo6FqmmcrputDAiesCPlVI3cwtQecTOgYJfA0c0oPYur39BM6Xqd mtaVp1XufG+Cybec95y9eOP3vImlafSFmfFyd1hisuogv+g5248epLhonyd4GnQ0kQoS uHG1yU1nFjYJTtib5h4v8OA1qagb5LUQ3iBoH1PTjmbKQ94GAipxFDgb2vEdMmCBD/Fv n0JQ== X-Forwarded-Encrypted: i=1; AJvYcCVcL6gWAptS5Hq0F+RhJcOcp+z5+Nu0MQqfugCGwE8RMPigErqo3A313/tQlE3o80PzYQO+KdUIJtlXuhk=@vger.kernel.org X-Gm-Message-State: AOJu0YzksXZv6hRvgo3wsQ5ymRUKvWAlx959VOs8H0tHd32j6hzoSAzd ToW3HW8LO/ZmPRymm656LV5ukjmZ4S9fSe72B0xTPx7nqvJfI/X2w0ClD09oLVo1jcQ5Kd1Atu1 lYIVpEpxlgA== X-Google-Smtp-Source: AGHT+IFS5aUiUnBfWLGVc4Y+MgpvgZkuWe39xGXjDJjJjBcW4lVK+SY6uqbln7Ic6rCaD0y3jpzOr2Cbbny8 X-Received: from iotw23.prod.google.com ([2002:a05:6602:1d7:b0:881:7069:9679]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:3401:b0:881:b557:7a1d with SMTP id ca18e2360f4ac-8843e39116fmr2178084839f.5.1755527345263; Mon, 18 Aug 2025 07:29:05 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:06 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-6-ca2546e319d5@google.com> Subject: [PATCH v2 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 b729f8245aa60c3d06b79b11846dccf6fcc0c08b..402ac66954e315eb5444df277ab= 2b9a4ec415dd6 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -73,6 +73,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, @@ -102,4 +103,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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 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 4FACB322764 for ; Mon, 18 Aug 2025 14:29:06 +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=1755527348; cv=none; b=GB/fuwhfqMgHf+rF+jipTCVZiXEME88ghA+G3nYMtx+o/8Nz8STXAUNosaGN3rX02+Gfsif/cePBzlAYaKIGIxbqoOmzJfGvU/TYgYZaxmqbD82wb2XhLvIPXcLEg4bGQdOsdwWks3BqQQDY8ruXEGbqyL7H2VM3TyM6u6SS82g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527348; c=relaxed/simple; bh=Atcf/onrjtwlUDJDKbgX+nxH8WoEO/HoYTnRVc1sXTk=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QCo7pxo5eV5VEHJpJLHlfl1sMCMFY6fyt3th7qMBeFbfDp8zSKJSo46EYOUSLojUQ2c6AecyLTLGiB1MmcbG8BPfUdaS5m0gl6/REoQIEaJe+MdqTLob6IZDkp+VPcxug16J/2FaXdb9Tcu3HTO5RKPYPMbqVpqt+YZjW76GCaY= 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=3Ct0a0Gt; 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="3Ct0a0Gt" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88432ccc4f9so1122151939f.0 for ; Mon, 18 Aug 2025 07:29:06 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527346; x=1756132146; 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=q1k1mjvOHwuify9LTlOteZLmh387iXArNoe6DszPTuA=; b=3Ct0a0GtXUmplU5qI0Q8BVm/wBsDt2ZGxAPGxK0wRomjXvqDHSKxAlWMtNSJZLX+Oy 5fSGc4ctmtpVJEzmAb+Jitdk/PnY0wOMm2vGlh45cePIFqtawEO06OlUJt8bJpJRdn7b THO62ceIv5nIo6CwMS8L8D14lJwpmd/BeukBu9kxtv5SAEBb8Ty4cZuVDszVdYUhAjMS 8ufY/OShbuP4ySi/9E5ZrDCNRgwWcmYGYtBgbbkQitc+d0tIoH2fMwFgoLdOk7CmOmbx vvulinrMHFJzs0rRJzK+Leyh+CnhVnEN1e1eD3OmQvFnMFBMddLpTLymgy39m2+tDNaj Fgsg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527346; x=1756132146; 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=q1k1mjvOHwuify9LTlOteZLmh387iXArNoe6DszPTuA=; b=uJidIHdqvo6QbKTX17kBa3CTo+yoxVmkXMq8K5ZQwYxKMgBE0uVWBxG7PKdZAlBodD f4Lo3+QaNT6ll56DAB1JLHx4pwovXx1vjY1TydX5+k1i2OYoPVGZ7fYuKiSFXFMBW9sG cpuGmqFK+okKI2dNxcYh9cW8NhcATxifERjNn0NULUkxoEmAmbV2Pb3RIG5kxJUX4rn5 /z6Vvn/ARg9PkfexdjQKVHkMBnEmu7mlmhNsXs6H6DvgactksE8/kIprYKYmAyYqNv+S 1LXkpAxZ+KmHtC3/xU5zimc8wnijrJB498RCkH/WOnLeg+8TpRzAYvK6UaAyzsF07UcB 6qdg== X-Forwarded-Encrypted: i=1; AJvYcCV0FIEZVKtZtR4FAFywvDjVFkHtzSMAlUpU2X3Sxsss3VvlIYR69zG9i/yNz0OxoV46dL4AH3P7alIDZIc=@vger.kernel.org X-Gm-Message-State: AOJu0YwCI7qJVwt+vwO4pyYj1vdxXvJzUasZHB9JYLxkbfaRjQ3gCNje fot+RnmR1atQy6X3fGH1H9q2Bk10FfD4tMxQp4cKLRurwFh+owJvqpbFrSDmb2F7dLKZNLAC3aE VZ9TPbfHpyQ== X-Google-Smtp-Source: AGHT+IHskcxyJpFYjk5Ryp9JEoiKYpePKMrSar2kRX1rGmIsjtIdsVkijDGJ4H7+mfWpdUH3OI2LF6xfPnW8 X-Received: from iobce3.prod.google.com ([2002:a05:6602:42c3:b0:881:9efa:4bc8]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:2cd3:b0:876:7555:9cb4 with SMTP id ca18e2360f4ac-884470f7150mr1505137639f.1.1755527346152; Mon, 18 Aug 2025 07:29:06 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:07 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-7-ca2546e319d5@google.com> Subject: [PATCH v2 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 2025 Received: from mail-ot1-f74.google.com (mail-ot1-f74.google.com [209.85.210.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 2639032277F for ; Mon, 18 Aug 2025 14:29:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527350; cv=none; b=ShSOcw/gL97UiozaLefuHkyt/+tr2svmfRi4cdbWqBc7MknvwyagJomG+YXRAz2Bp7ItUFo6JYWGNNlJmJAQFGpKkoEdceFsyz1kvE1fQ7i79+JzpqPq79v+lkx9xlT6Uy5mXqQ7mr9MmEZPmOhBsP8b4D3SDHzpYY9sisS2qcc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527350; c=relaxed/simple; bh=NWZOt7Tv/JR11rhWhB2/TKtjzpxtTktoH9dWK3nHU4w=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=s9xkDeiJ6paX+9a3fJuik08sjFfeowLKJiniyuacQIfMoVNiD+bh6B0dWl/0b8355garLe/A/fA2ANuEF42GHsO+ZjRSBgN27lJEqG7Pr1C2EMkl9+A7AQmzy4G7DIYYOSu3AacF3v1+fvxDaHxdkR7Qu0r87KM2F8LdnwvVC4M= 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=kRRRVc2H; arc=none smtp.client-ip=209.85.210.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="kRRRVc2H" Received: by mail-ot1-f74.google.com with SMTP id 46e09a7af769-74381ff6dcbso1092982a34.2 for ; Mon, 18 Aug 2025 07:29:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527347; x=1756132147; 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=OWqdzpYUL7+PpXDh/tU9TKsciamS6RX7nVkdacIMWsQ=; b=kRRRVc2HQH1Jsn6PtczYQg50oJDl8xMJsg87ksNogm4YmBRjzZ4Nm/CS7Y/imJCft2 FLtrSJbLMhoKiu5D4k8YpWtuEhAqVwW3JQwjbtuhdzU7KUKU0baPC+uDK8ga2oj9HySr 8tNU85QTyuMYkd4YAfUTuKMV0eFUGZ57ArYfcdyyb0ZuI3Ta0x9n9obSc7sgwdr/Enkb 6On97Z/eUI4+mAEIsE7dHrLgyG+2+AxNMojRVTLR7jafYGHgVGKkU3+S76jjTeTdRdjp sMiZ5GGVOlVOimcPEG9FzfoCAuC800JdUzAxKBipK07iqJH2fuXVyFX4hwYDI2YvgKw2 zP7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527347; x=1756132147; 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=OWqdzpYUL7+PpXDh/tU9TKsciamS6RX7nVkdacIMWsQ=; b=ox718Az5CzsjoSgn4AcG9IVUdY4MZ0itWjKPR8KDfqyeMINs4tGsFrRN3XlfHjFtH1 xpw2TxdanIfysPESRPhH0BbbTXokjEQcMusp/oyBVMhOOjc87I3c8U4pb3eIk1wJCd5y zOimRbSzxLf7ES5u/z+7t5vjgampjP/xj1+hcz0EFOB8vMju7IQuNIEGhkm8E9Djk54D VqBJjVr1KugbvtlMluSdlofdJ5mgR9D7hLmAj/8K76HKIrXYT4PzVwUMZKbAAd2+ESIE W/HW6rr2KCvRyfK21jTVasfzx6S+JBQpy0BvXPktweFeS86NJW/th1EVuMxHlP2K3MTW mNNg== X-Forwarded-Encrypted: i=1; AJvYcCU+7Jh+eunB9OnSbZiJbNiXU4vj6rBHvOV9xeVJi/3MC9MRsSqryhqDJjIHM3mN2s7ACgCBhBGMx5TZyII=@vger.kernel.org X-Gm-Message-State: AOJu0YwttIBF4cENR8SvyEDZ+YcdM5papcbOrYxIqpQy1g2yRtc2uTDf It56pY9lMTn/N8utygKsouJcQ+P8Atm9HEW2+QrpscD/OwipQ919Mbbyp/jD5GzWPBGXl0tdnGC /6CgVCvmLrA== X-Google-Smtp-Source: AGHT+IH/qWzGqtEr/vp9llvd19SDMUbdy4409bfsCXcE5kPKwgW4iYVg3RWQ/06UA2ygO5oVNc/NYMA1/tmT X-Received: from otvq39.prod.google.com ([2002:a05:6830:4427:b0:741:614a:ed95]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6830:6110:b0:743:8443:6b31 with SMTP id 46e09a7af769-7439b9ccd8dmr4664627a34.6.1755527347292; Mon, 18 Aug 2025 07:29:07 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:08 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-8-ca2546e319d5@google.com> Subject: [PATCH v2 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 402ac66954e315eb5444df277ab2b9a4ec415dd6..73601f429de16bae3b1d877445f= 7eebf41a69d94 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -74,6 +74,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, @@ -107,4 +111,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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 2025 Received: from mail-ot1-f74.google.com (mail-ot1-f74.google.com [209.85.210.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 59451322A2F for ; Mon, 18 Aug 2025 14:29:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527351; cv=none; b=SgOtXMrz6cUj22Xiya9slu1faHF/OJRCCnP+bKqhG3DU1Y2Ou4n+ofoUFJgwefjm0bgldc0W/S744jC4ZrRiA875QHba9holem90zQP02uvvACeITZq0UaR3Q0H0gtY8wLWFwxP5JS3LWIAECRKAzbBFzinYSds6LI89LBOJ8j8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527351; c=relaxed/simple; bh=rCE3y8aoab+T16WIWRRfap0CwUtLbudmqpC74B556QQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=iH7r4Z1sfsN5qVigg0jkCyCIbQMrRkcqgW8zs2aIZcJcZtJAij+LP5DlartZm8G7OzrbLkHXL4DzIxPvRGcZS7/B0VUajUvzGc+/EF6oGT+aywTpBR73eKD+04F2tYPNKkQbImURAqlvLYkAe2yffKkw6bxwaLtdlf44/l76Pqo= 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=NOgf5rJ6; arc=none smtp.client-ip=209.85.210.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="NOgf5rJ6" Received: by mail-ot1-f74.google.com with SMTP id 46e09a7af769-74381e20b87so685898a34.0 for ; Mon, 18 Aug 2025 07:29:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527348; x=1756132148; 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=CmbjY97js7MZoomYoQByPkN7C3yikiFKHaLpjjYDFzo=; b=NOgf5rJ6kNQr7wPOvDAHivjUmduO1W/FQjVLwGfBFeB1JxRdqneYRWVi4ci+BNnk1A yehO2b4ug89E8i8nw9erJp/+JE3yr1Z3tMZ083Z9QQQmBTzs17cghq7gKi6FAbcdt0rT F1C6UEiGC4/tHZMiTvdS577WoChfEntkXCZ5IMNE9eDT3TSFDPmivaUEA0w5Q/FH4Tjt BUB2PSiLBqDxq2PaWUJCdOEjtwNiUqb/MjkfHyZVKMmH72qcFQSNuvOY5ZPPViUz93ht KVAsCKE7ZSkZp07x/1nlMbZtHsL6VRpOaxEvKnNa4AFygP8+yi8pBLzqvpRiNOfFn3Zc Ysbg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527348; x=1756132148; 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=CmbjY97js7MZoomYoQByPkN7C3yikiFKHaLpjjYDFzo=; b=Ia1nkA7/gko+UwkKGzt2nlN3hscfFCh0ElGZjnv5xFsHxlXq8Wxm23uMGTLqVJHwcZ PIqi6snVw+9bMyI5Y6KPrpv+snAJIHwWE6ayE/gb4K1WdmDhDUAYN53uh9yHkvtHy6gw kl8ZP0MBCoJ7nL+/bqmVDGcANC+a/yEZdEN44W2ypEyHn3hP5N2Ftb55AERoyjGOuhmS iCAlYHI3RElla5CqDi+9E9PHjoyfcgKXCVGUpVAJyrr7r9vVNhxj+a1rh0UNgzNSAvBs rjDRPLovijOSvsNULi/jZ1qz0eCT8+Lv60frGDRg6ZyxbQOFbTJ8EZeqpkN3g4ICvhYp ddtw== X-Forwarded-Encrypted: i=1; AJvYcCWpIYvdY7+NHbNEO2wpjtpyyBo63JarlfBvLJ++tgzYXIMIdGR70hHc0tM+I4rEJ76peVg6coezkY+5n/Q=@vger.kernel.org X-Gm-Message-State: AOJu0YzfwOzdlb1zFN3tCcory9YOzYBxQ1cRRS86nUnezgrm6ftBMUqW PoXEJS8dFRjWkFLE2GENxY8i0way0qHSJG1iWXBcB629ypHeumYbs7b6xd94G9LSSkir+M9Hwcr tiMVC4uewQw== X-Google-Smtp-Source: AGHT+IED3u74ay8tcQaNJ38d6RJ25uk7CVOONcsE53tm1TMDzLqx0DtwfKRaMxJZbEPBl6IzeTe9X/CyNZfQ X-Received: from ottl45.prod.google.com ([2002:a05:6830:336d:b0:742:f8fd:5cbb]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6830:f94:b0:73e:9293:554b with SMTP id 46e09a7af769-7439ba037a6mr5886059a34.12.1755527348469; Mon, 18 Aug 2025 07:29:08 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:09 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-9-ca2546e319d5@google.com> Subject: [PATCH v2 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 --- 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 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 35F19322C79 for ; Mon, 18 Aug 2025 14:29:10 +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=1755527353; cv=none; b=Tn4gICi01QSdkCpHMIT7/NH85fpzd2OFvA8rYNFvleCIq1+aogTI3SUKOPY2m6pUyuD1VdUOR4mTRgzUmG9xIjfKAH25rZ3a5LM1w78hGyIP1YHeL4DWxrFsL8DifQ4Iy7eKGKoAmMq1knpuvvGC8Jl3m2lOAaM/pJukMmuEh5M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527353; c=relaxed/simple; bh=EzJdaMtvWN8urpUikh8Q4GZb6HxTthrpcmrUKVjniQw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=tTy25PVaLknVvdtA/7O6D+wPYBar3sDQ39FBTBO60xKEKyzaXcgB6nU4JOxvs0zA7/ZXQgey9CC1TPgtkpEgL2OnnZ8U2hiMhq4JPVkCuSFFpRomwtGCiD4s5Zk5I/tL+u5GTYJ7LgXGnNPNDdqV0OXcGOHxRcNwERwC97vGE28= 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=xmXgomrJ; 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="xmXgomrJ" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-88432e1f068so475424339f.2 for ; Mon, 18 Aug 2025 07:29:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527349; x=1756132149; 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=bXZVcgVQ+g42oJnrkZEqV6Ovv0XvfsNhZapIq9gDRSY=; b=xmXgomrJOfYebnTGzYvuYYgVly8cNxwJOsaFYdqCKsimViCSqalWrZRxY2h+YqL56s RhS++C4XWlY+XKhzIq5TqcmPfXMSlhNnjuoCHcxt/6Fx8zbxX6dgbTUDb8mpZf2dHPdM d1i61Rmz1ah90EOlQ0nQ/79TNjmhN+YI4fJoBwDASiWLHbXuza9mkasgEhKBSfLdEwpL DSzVBWI3d8x9MnoX93MKvbdeuYDVV7O73OyY5c6aOPv5JL/rAZq3RmQeWRibt0vHK8gL b/2Qv5FZC520NtFB2ScOGyjCh9YQ7CWprSMfAkHEblh8fq56+67furfodkwIjmDKX1ZV CraA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527349; x=1756132149; 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=bXZVcgVQ+g42oJnrkZEqV6Ovv0XvfsNhZapIq9gDRSY=; b=tQEZzoW9YRmiiykJYNaFXniYRVVYrBtwB9QV7ytJvbeB3uh5zdax4CfKmAD27sRs5s aimPEDieMcZ+IvmUgk2qUDITaogJuR0gClgFaYW23+zdCiD5wkoK/IW/eZlOz5Z2fmn7 JgTmpQnAdeISX1MvrHJHbPiPPkLLdBZTbZtYMHmfgNnrle8WM8r0MvWa7NIIjJtxk1iK YDkntlWr40HD0CbCL5DAQKwgwPaLJK7KVk2SsQPNGvbCY2ejOfClMVxSHIVgs34jg4vK f0rCd67KBJg3fDLvWWGQm+hyWFblOzkW21CaRQbY82MtodFZE7VhPhs9pIP+YxWbawqU XhPg== X-Forwarded-Encrypted: i=1; AJvYcCVMIR1oP0T/MyLJ1r9IuDBeLbcFyuvG2gv5SP+wIn4eZaL2TlSnUzCSrf/kZDC+UX1FbOW3P46nCY0TI3g=@vger.kernel.org X-Gm-Message-State: AOJu0Yy6sLGelpjBt5WIx3kaZyI3sGP5KKJXWne5lzgaDq6eugs/RqAQ sj0DcFAd/p6rVzaQUf2bCZ1tbjZ7GCEfpKYclTb+/NVvZWgUzhFmT0/rTGzQX5d/i5d1Wm3iuYJ udeu/jV5c8A== X-Google-Smtp-Source: AGHT+IERQLDHL1rvPQ/kzY3xQlBsZ9A5yJyKXeDv4afvAsJ2FJMmdxwbnVaibbx2bSVgs951jmpuwDTgQ6b9 X-Received: from jay8.prod.google.com ([2002:a05:6638:c2d8:b0:4f6:9195:b4a3]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:1a4d:b0:3e5:7282:4a94 with SMTP id e9e14a558f8ab-3e583928632mr203922345ab.23.1755527349380; Mon, 18 Aug 2025 07:29:09 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:10 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-10-ca2546e319d5@google.com> Subject: [PATCH v2 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.163.g2494970778-goog From nobody Sat Oct 4 09:39:56 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 62C04322C75 for ; Mon, 18 Aug 2025 14:29:12 +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=1755527354; cv=none; b=HTD9uQWwB8jYxnBgoNJajGrQtz/JNUhiHJi5ypuXWcA0eCSZAWPtl8Ou0nfFMZ1kpdT9yNrriaiuX6VTXO4SRhb/u21QxYUfmvF7MMexR7ZpoO90TCS15mm8nhT9vDF9otgJmtXaJDZ6z9PTPHat6fGqFsj68OYm84p2GEMXXno= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1755527354; c=relaxed/simple; bh=LLDKD3jhhd01cSyNnUJ72AfCscFxZnYBV4yXzLlYTqo=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CRQ6YmrKSP6ZdP569d38a2rShRsUudr6o+rXsILYxkafZGH34mA9HyQppXWhaK9A2FU3MBhu3hvjQb0FCmVC6nT9kQ28wtqXHEcdXqt9Mp7krKqiP2ouST23rnbeMFsXaD5UQwrO9wHWrNO2DS1Oupm5EMNLCbIRFGcpCUiKr2I= 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=yYwH4BXL; 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="yYwH4BXL" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e56ff8e3d1so156541095ab.1 for ; Mon, 18 Aug 2025 07:29:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1755527351; x=1756132151; 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=G6sergV1NCFzSiZ+q+TgB6G9QZTiH10/oQ/v7cI0WS4=; b=yYwH4BXLRpPkdDTd8DPpEQ8nykfudYucIX2MC7fKyHBu785pvk5A7KcxpwwIU2y961 xJAJCa1U53oHvJuTmKnWLCsKy2CfyIlmaldhpnCu1+GbhEOQcAd8sjHbKAyIfvBOLXYo 3Td+v3ek2eio8RVHObiquTCKxujsRp+iWdgSpnw7P3+p++piRu9ioyWSjwhBUjbZjmPg VPJhe+edYIsshlBUs7KyjKZsnlO3iZ/BaKuYfsj4yiBp5/GSuDVRua7lWJOESPXAC6iE tYVFYYiC9b9CHPOI7FYuLh2V6O91j6DpNYla5AIiTK/+ne5IVsXM82GFhh8h+XoHNcbG VGVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1755527351; x=1756132151; 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=G6sergV1NCFzSiZ+q+TgB6G9QZTiH10/oQ/v7cI0WS4=; b=b9YjmrmCJ3xoQVZlJ8RbvEyw+pomjcl2KVAkzTsbVW7N7AaQ+JcwTkPjiCZSarqRHB 6w60bf5cuuBLIV7H1fJ39L1ddYTfNuDVhYTQnnmZgCjaWMSpJ4WDYAllDUk4+6jfSmOT /tA4MQ61E4ysof12l1fshDgHtRvWGMr9DMC/MEwDcfSr1dHiSSKAcXhBpl6YaofdiCni FkOWr/Ajh9BZKFXIAmoZkayVk6mMKmsd9z4Cwa8LTVLBX/L6ZpxtX866H8livWGzCf9g bmjNI3v7lcsHuaBmi4an6sXY4YGwZHXqsbIDxTXmiUcafrcDY5kGLZ1i0OKS0j8SmZYi HCEQ== X-Forwarded-Encrypted: i=1; AJvYcCUi0d0MogGK0taqaf73CmKulpeDaaxqDpJg9ca7JcCuUr1qtsTfhZ3iuhZqYCne1i190sGPFcjtpVANwU4=@vger.kernel.org X-Gm-Message-State: AOJu0Yxim/zB3eeb3kuH8cJy94dbGGO6/0mg555gVIQ1hto5c9lzHarJ 9x9MRL3lwuIOuPCChPw1OzPVoqlCv1L2qXanfByxg7pDMKOSIpOTdm6fNfelgM52uWe4jHKleFH qnlmJsaUfmw== X-Google-Smtp-Source: AGHT+IEVI4czH0v4ysw3PzKSt8mNpOp3N0G7bFAqtIz9bfKarZAPIeOxGROw17qMCYOdTJuFKSBK+rdcnw2i 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:1b03:b0:3e5:4631:549e with SMTP id e9e14a558f8ab-3e57e8b109cmr245148445ab.12.1755527350269; Mon, 18 Aug 2025 07:29:10 -0700 (PDT) Date: Mon, 18 Aug 2025 14:28:11 +0000 In-Reply-To: <20250818-support-forcepads-v2-0-ca2546e319d5@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-v2-0-ca2546e319d5@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250818-support-forcepads-v2-11-ca2546e319d5@google.com> Subject: [PATCH v2 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 configured, 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 73601f429de16bae3b1d877445f7eebf41a69d94..6fbe07a8df42c2dc77681b013a6= f948357253bf8 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -107,19 +107,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..bbbd5c49dbd480ecad2a0c074b2= f973f099dc054 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(&td->hdev->dev, sizeof(*(td->haptic)), GFP_KE= RNEL); + 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(&td->hdev->dev, td->haptic); + } + } else { + devm_kfree(&td->hdev->dev, td->haptic); + } + return 0; } =20 --=20 2.51.0.rc1.163.g2494970778-goog