From nobody Sun Oct 5 12:22:59 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 A1A9526FA67 for ; Mon, 4 Aug 2025 14:11:20 +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=1754316682; cv=none; b=Mk4Bb7w3Pk6lZxIi8803SoeaOPFY+1LGab65qpTOYN3lCD7s5JXjFVMosbqKRGqVTVNw5SjDrk7c5WkhBpgcpGSZrULMY5Oi6qzAlMdnzX/1V4bpys6T82OIbb/AQMhHX6O0onMWzv2B4v6TOvbpiXBXRlR3+ZhiIY2ubI0cuf4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316682; c=relaxed/simple; bh=wD7KH2nul7xWSFaFztu+JHvu62EHoaiPuiZ2VbswsXQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oU0V7AyW7eAigH/n5l/rPtGFOTn3Oh78/s7NW+EDyiqU4V/pVOGPW8P/pM5G2HZEnKKkTMpl0G8g60WJkLTuYOuS8DcTMm64aQWxqoTtnwgMhOjR11/90bhSTsD4bs8chq5ayHNMArs+jQpdUZxqWtpwKkh49nMYqW2zt7qZ40c= 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=wGbbrE5u; 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="wGbbrE5u" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-88163258c33so573414739f.3 for ; Mon, 04 Aug 2025 07:11:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316680; x=1754921480; 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=nuKq8QjQJ5E3pwFU8vQVEGwZ2XyLx0FOu2w9SY7fuwY=; b=wGbbrE5u0L6vY3yKUtsgUVTk2CO2QGeOfVbJdtQ7ZdSWQfjOww3Z233O/KE1+5MKMO o1Uljxm+Gw216g4teq7ve+xhlQKB1PKWtepWEKy08DeyTXanY0jvLci9XDytsrZUsrU8 gEmylG95EUlDH07eLjfoxBu+cyp2o68LG0KFKZsrJT0sJSus+YhXoHYUcDE/xsUsJBsH R9GEykujNmyGN6NxIB0x0JrbqfbVsYwnfEkwDgKx5ceZhgTCyhXc1TNsTAG7DdCH5b1Z PKoil1C16BCoPRxD9MCHlrd1FpRf6690sVjWe5F8XMi5vCv1XpZWl0hYrojY5eWRcMSO Rscw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316680; x=1754921480; 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=nuKq8QjQJ5E3pwFU8vQVEGwZ2XyLx0FOu2w9SY7fuwY=; b=hPl2oFUB+9qwRu9HEnRaAHNr0Pn4pSF6Nv3ParQ1fcfB2Q65vFpTxUkjE0Wi/UFaaQ QJpOyRbTXbU9/RQCAg78ON7Cbemz3O8LyMVooBm14meE1h28CFlCJDDWFQbshzdpDjkT S41GB+L0It04urE9rwdkpXMftLehco9fKvQpNPD8NafvmF+GkrQfjklQj0bgevhL2E0n nrLnJPHQyZ/XR9KSQnnP719/qbOw68LnkxNUCrWin/W5XIAl85/znPk24tVYslSN1N68 uYC9hk0eBno021UlMq10p0JTHwqeun15wcy+H6uX8qa4WGAsYmbDOAlbQ+p5i2TJWqTA OngQ== X-Forwarded-Encrypted: i=1; AJvYcCUODa5uHvP3j1x6fhFHaV8+oS8cinxIO4KtfR0hksK5xd6kE9PUWBG+vb0BT8jYxVILveCudnKzQAzIi0w=@vger.kernel.org X-Gm-Message-State: AOJu0YymUGaowRGS0VqbDnzVopoMTu4UHPMQsJC+JUHMc5AEF/Y4zZLI VJATzQI4XeFwOMjD7lnDQLWKL2re+c7VWe2gVzHO0GB7yBcdhA2CA5VjgowUfVww6tcAz8uC8aA EOWjQ81cZPw== X-Google-Smtp-Source: AGHT+IHqRipYLC3AElMPz+s9p6pNzZ5o6ocGxk8AyELudHcmR9kBNMUK6KIuj/qjmZElU5urf4KNvsxsch+6 X-Received: from iobbf13.prod.google.com ([2002:a05:6602:368d:b0:881:7968:8236]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:6b81:b0:87c:34e3:1790 with SMTP id ca18e2360f4ac-88168313db5mr1501133939f.1.1754316679742; Mon, 04 Aug 2025 07:11:19 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:16 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-1-138ca980261d@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.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 2025 Received: from mail-il1-f201.google.com (mail-il1-f201.google.com [209.85.166.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 079D626FA6F for ; Mon, 4 Aug 2025 14:11:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316683; cv=none; b=quBmTZgXNt0DgddgwEWxIUjmgbZHNcVbddSQTRMblOo6B5ntUMiwFdb33xBwW0fcdvxgvkG9Sxwst0YTZxdoeB4YcY024XLaqsIFQxsVdILCY84EO9rjAFgASJ7s5oFqdLgxnpKSEE9QAhmj9SuU+Yr594bcx/hEEcH4xV2ZHgg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316683; c=relaxed/simple; bh=F+PXi5nM5lhXJgRf7ORFGFHyO6OD7uAo4HwtKB8OfpY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ACFgBFYAJKGqmeirFCCjWr+A938Ix6Y5SRPzl9Iehw47eJzmUZE577N5V37l+NLw6OkHjrYAw7otAyWOH+kK3MBaFLAUI8iq8OilDfcZeRuCs4SOjcJ7ZZlt+mcYZsEXeXN2L4TOCKCAoVFJ3keOVoeqQlkIjgfnf95TtAZZb2A= 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=sPfhHnOp; arc=none smtp.client-ip=209.85.166.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="sPfhHnOp" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3e3f0287933so90400905ab.0 for ; Mon, 04 Aug 2025 07:11:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316681; x=1754921481; 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=ubZ4Umicq2gw4MKto41GXn4WlYxaCA6Z7+4qXt7C5zs=; b=sPfhHnOpgceGdnwJCChO6j0GkCtX1eBB2RU1sj8BV/dI7QwjH4mG/xYc3tcrCHUEAU Q/W4X6CDzHmA1gpbqOV/3RHDVN48JgG9fe0I5pWNrz85hv+vZofhiKfVwz9uvdbifsLc wa63z+ZobkDCuoW4ocdwAiLFtJTaVIwY0itlofbrCfCWmPLlEFHi7EwGVeJoWqzf+97w VNeuShfB5QTCeOV5MPo85OtFERB/63z981/b2TXhfotIXcGAXKidQKmUhtMoVBxhkrTA fZKsKD5gS54N5o9rBK+kLf1b4/lpEePStTfztkhIyYT8t2L2kfA0HlzHFvZW2VtkdKla rgfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316681; x=1754921481; 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=ubZ4Umicq2gw4MKto41GXn4WlYxaCA6Z7+4qXt7C5zs=; b=f4K9yC0HFpTaRv29Kje6y61LcWL+/p0WIeGbT3cJG8oqkemVd4kzsMlJv4zz1/E2VR VF8DDPsETK5ADPH3dpkOQlnXoiQEuXOHVzvU8hcG8Ob7gjMQWDbmxnYsf2uKwnmjhIhe CXqcfeMOcTAvAkeCdUPtI02Ci003opYxmcDXrx/4XGMTTgxR5khrkD88xZ1MSmgb8YL4 ZkS4vMK7xohStec0YGCf3eIaaO/Q1LCe162cBcps5C9lkOyKweANY2cGJBUg469ZzGsu XuZJEHAmeq+4ivuRf7j7vboGuibG1O3q9GARhhKLXsknTsCJHF0f2ERTYsB7E4UCmwrA qnAg== X-Forwarded-Encrypted: i=1; AJvYcCXlggYK7k1NBvAsosilUVMvGwzmarZ1bEP4tS4xmkEkfJCmZ9bfF4giIb9uP1E28qnO3lHlkHSS2rX3SaI=@vger.kernel.org X-Gm-Message-State: AOJu0YyOEuyfqCcsXGKqf94U1SDmlwpc2jQjVTcDXtWKLUmy9c+qcaVY wEDgkMlO1yG8DafMKo9cCE3jney1I35/fn2RtL+IM4TEfNSR4zsq28QCpQ2L9ZaU6pNraXE/6PA aWoxfK04+7A== X-Google-Smtp-Source: AGHT+IF2q3PwFU6Q37KO4T7Vtt47/cfdjWmrjamRPYqbNsjjM1NxjObawUg+Xrc/aeyAnjn1qvapjP+kXXxu X-Received: from ilbec19.prod.google.com ([2002:a05:6e02:4713:b0:3e4:90c:613a]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:160b:b0:3e3:d50c:d657 with SMTP id e9e14a558f8ab-3e41610a4ccmr163038395ab.3.1754316680974; Mon, 04 Aug 2025 07:11:20 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:17 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-2-138ca980261d@google.com> Subject: [PATCH v2 02/11] Input: add FF_HID 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_HID 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..3ea7c826c6fb2034e46f95cb95b= 84ef6f5b866df 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_hid_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_hid_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_hid_effect hid; } u; }; =20 @@ -471,6 +490,7 @@ struct ff_effect { * Force feedback effect types */ =20 +#define FF_HID 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_HID #define FF_EFFECT_MAX FF_RAMP =20 /* --=20 2.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 2025 Received: from mail-il1-f201.google.com (mail-il1-f201.google.com [209.85.166.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D0775270572 for ; Mon, 4 Aug 2025 14:11:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316685; cv=none; b=PgDr9Aom1MMA1eWHXLIc38DhpVieEu28yqMdJHzUzbi1CqfExosA6b7ZgMx1ctVHgzUV8XLSgTOPeV/g7B/Ogj2gNM5eREfnAuZ/9Q/VA8/w1r+o3I285tZgEoOwcRMY6ANVrWVmn3fn3Kh2NLXrJvWwYYm/F68dzq65xNmEEYg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316685; c=relaxed/simple; bh=sM1diI0+8QwBlMWWKxPjiFubTZJ47+1Rz6WjGiYKJLg=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WgbJeRuqtlJEmKWQ9fchTCb61nJyqDpVpBDNDazoqPomUPkg/zQVrloHdX0OkJ/REO1+OPmdZhFXUKyUp1oB2rFElqEE4DF/TaoACJvgrqXYXexzS0IVzQ14BfDA+l+Q+XoGKl97Z/C1AO2vqwdg5bY93ed61JVgQmKQ1ouBZtA= 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=YRThD+W3; arc=none smtp.client-ip=209.85.166.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="YRThD+W3" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3e3ef793a6aso85679435ab.2 for ; Mon, 04 Aug 2025 07:11:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316682; x=1754921482; 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=HKCR9N5mLRlkbi0TLaRQSzln9H2RUOxEy61mEdM0ngY=; b=YRThD+W33fynYG4tAFFpcjdQAVOVjlusl0PCOE2Cw9y6YzovtmhFYCTi5qC2Oqc0hJ ZT56AYTwPseeCcOzC5vILQB7QUVfKbrLQnpDVFYQd0TqE7QC6yUfNWqPXAZZ+RuhOi37 3gqLQfNTtfYOERgN41k1ow0fiyVwjrDh7pC3sKeANRj1mPKylIV9Gym0yFkV+O7ad2sx 1+hFgG96GXydtUIeMZsNg8uZUwhvn6wYvMeTXYdE2yVpEJj66fAqEuGNIbIDGJHPkBzO VMEOphI6y5otDHXYQikl3xXMCwh/rBytp4b0fHpCnVgP/03fIT97dQif9tCvm7a10CsV BvKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316682; x=1754921482; 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=HKCR9N5mLRlkbi0TLaRQSzln9H2RUOxEy61mEdM0ngY=; b=HCjoMAZ37wdmZ66Oh/i1L2IPfoaLeV/kGeyC776SPbisSX4ZaFt9Uexbm5seOSTGxg hGuyMkw1LV57BlKtI9yrqt51g3onp8oTNwnKvErLmoCCGg/Cm0bcmeqDgn6oC9L4yFdl YVmfhKHH370/0sBF/o9Df3HoDZwIAvUXEZ71iCbekF+zzydwhIZa8OLzGQdJDwfCGiy4 k7p8g8/3FvSuxwgUS4z/PhmaeHmB+mTLReijnluh45Wxa2ofxgIWScJ18IqEE56lgleW oE48nrs22Yxad6yWhYrh+XgXLPC2xD0LU66q2x8px2tkK2ixdmJyfJ1ib2vWAllGvAF3 jnGQ== X-Forwarded-Encrypted: i=1; AJvYcCXTvCO8La0CBEuuVA2LIAgMI7BD+dyaLsHFnRPuHAOcZfqaNtTxJkyeJ3xTxvAQ896nuvzNvNCIFZnkVJY=@vger.kernel.org X-Gm-Message-State: AOJu0Yz9f8mnxBXLDJz+aD/72vBmyvLBnZXmE3Mxmd5fLxYl9nse5kS8 dC8NBenYTd0XvhmF1xy8yBSg6iZJgsWxP/oUkjoawiglvPFCeenOQUtVbBCtg12VUKt0T2copvB fbe9CuF9k+A== X-Google-Smtp-Source: AGHT+IG62l0XeGfQHwqlqdPD5To0kn4v4Bx1GZOjIxLss9+jyRgToxf6b+9GRK7gUtWE2MzF7/Yg60oLI5z1 X-Received: from ilsh9.prod.google.com ([2002:a05:6e02:529:b0:3e3:f33a:a85]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:8e:b0:3dd:89b0:8e1b with SMTP id e9e14a558f8ab-3e4161b3e64mr175173845ab.15.1754316682117; Mon, 04 Aug 2025 07:11:22 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:18 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-3-138ca980261d@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.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 2025 Received: from mail-il1-f201.google.com (mail-il1-f201.google.com [209.85.166.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1F95E270EA3 for ; Mon, 4 Aug 2025 14:11:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316686; cv=none; b=PuI767h3Z3PUFiVjc0+cIQd1PxxcwKY5U/e1KPPzU2eTYAdMk4yoTuOOTueBWffnldEh/1oQS9gUB3yI9dkZXtYVYwTbMlOv4n83xoygHEWLVAAK9ckwvgglDBeH6YRmmi9UNXjdz2lsVtDikg3/7VZNCkaJ0VbaHYU9ss3ghmA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316686; c=relaxed/simple; bh=7C9KnOWBMiDynkpD0XgPEOAXG+leUvk1gAVzZExBgzY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=HriyWo0bJeQQbJq9vwMBPgPSzxG0RpA5Db5cp2ngK3ZmbCErqPyZ6WSuBYOLpzgM32hKJ9I/DN5pXMhMX8pLmGokxHb4T1HGxG6X6RxLYVhuKlnFD4XG2ZWadpBaQIKXEOEZ+xwqdWJfAERDGzQL95qXhk5pJgDkioHdREftKa4= 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=o5i2Z4vS; arc=none smtp.client-ip=209.85.166.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="o5i2Z4vS" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3e3fe1d77ccso29618235ab.2 for ; Mon, 04 Aug 2025 07:11:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316683; x=1754921483; 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=tI2UwnRHp67jtdQcIIHTxEfXbkGwaWKBWOArqM8/7sQ=; b=o5i2Z4vSeAN/Iu/EQIsXG7n38WVM/aStZ1z3h0Lj3s/jsEJvpKKQzt9qzUu14f61mz URsIFxc5J/MD+QTpL6jLuMXv/ZoJ4cbAiDLiF1cemTMw+v9m8fdAzIvt/Tyl/xQYhPy6 GUTvvixD4QwPAq1BqpyNuhqmjasEW9DjMlvqP0iTgZW5NPH6Bqy7EJ9WEb8Nci3ZV2GA RoNblnsq9hHkijMJuvrj7guvCusJhRr2GLePh4fVJEFk5NfuKK7H0v8KLnF946x+y1A1 okvdAxkxTQBFjwFre9XYdgRpb3XlbDvfoh76ybGkFCg4vqT7Jt4hEDKsOEA2WXEvSHEl phtA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316683; x=1754921483; 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=tI2UwnRHp67jtdQcIIHTxEfXbkGwaWKBWOArqM8/7sQ=; b=AyWvrvFujfQfV3jGfGe/x0HDfY1jemD8WlKvAYLKLttuCxUg/rg/tzEGzv6bYCiSec GRMs98uenKw+TKhZnfjmNczvaWpY1jEuLw0uY6d/OOF5hL6CGkrstZ6AaIjzxvLHg6fE YG8m+kWTZiNudk9IMIvSBfZjzQuCeqrsB9gGWQQa9L5G4X+nTEMOrBNp2EJ1xgXZ1Urk Q8d/WPGYxZgL8zIjMoZ8u+2MGqzzQyPCFYh+PLRdHQ5AxyDIDwIbMe2HcBLmG2mtsilc AhvoLu8vGYPVtlsL0WfWKYA2ppMKkfMpnJH9ULAB0o95yqsd+JPB1UoBfdmfKm4jM9an N5lw== X-Forwarded-Encrypted: i=1; AJvYcCXI1mHc9xeJ7XBjNDn4XoDCeThJ43iuuqcEqC9j95tdx/EY1CNp3J7XH4q0/MW2DYN8t60cWn5jQKhsc84=@vger.kernel.org X-Gm-Message-State: AOJu0YyXkUrvvsYzPF3uYD9Q7jqMpu83txT4mjfOPYkz3adnnDz/ONIM 2cys3WWN/uHHkhc5K3TDC0t2oBNhBwTX5E3zgXZv+ok2U4T5i4On8QeQty92zG6GM0vNAujf7OX C6s7vMiaMHA== X-Google-Smtp-Source: AGHT+IG94Ytkdp9v6tw5ED83Vd429b23qGOtJraJWnGWhrOUSoc7Hxd+FrrKYeEDdZs/k3iY2iFFO7Zy8pgh X-Received: from ilbbt17.prod.google.com ([2002:a05:6e02:2491:b0:3e4:1196:9e17]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a92:cda6:0:b0:3e2:a8d7:cbc0 with SMTP id e9e14a558f8ab-3e41610d612mr178872045ab.2.1754316683290; Mon, 04 Aug 2025 07:11:23 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:19 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-4-138ca980261d@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 | 9 ++++++ drivers/hid/Makefile | 1 + drivers/hid/hid-haptic.c | 72 ++++++++++++++++++++++++++++++++++++++++++++= ++ drivers/hid/hid-haptic.h | 74 ++++++++++++++++++++++++++++++++++++++++++++= ++++ 4 files changed, 156 insertions(+) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 43859fc757470caf6ad43bd5f72f119e9c36aea7..ad6bcc4248cc111705d7cfde2b1= 481b46353e2d7 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -92,6 +92,15 @@ 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. + + 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..fc8979772d00e8b3238b26060c5= 541065a61811d --- /dev/null +++ b/drivers/hid/hid-haptic.h @@ -0,0 +1,74 @@ +/* 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; +}; + +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); --=20 2.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 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 2DF172701DF for ; Mon, 4 Aug 2025 14:11:25 +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=1754316686; cv=none; b=Ft4poEbLArsrrqjVfjvye4Ql66FsD9Pm0e+s/n5wL61h+tqN/9UGVDOL80KAMGfDOEr6CVcHWG5p+7k2wvBtbNG0otG/mh4ZvslUGOB5Hl1nRPyvh+G3F12nXtLu+xehwIRG9uHdK0Bg52kOYEYuFPM2UkZhV97Azv3jfw4X7vY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316686; c=relaxed/simple; bh=iPB28TrEQ4MzyoHFPSBZfFSdBRfwDn75E/cHEkPI3WM=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=T2A5xyswM9XAQ66234pP+gOf6KolC9Pbz3CbOgLuSBFOHnFsI67oEXabqvX7nwj1cpty9v+xU80lNjg96x2c6SGZjzKJaapk3XAyfrI876pusoPG40JSPVdTHQIbJ7N9CKuXTJ6pRlHJMzVwztgWt7zeYppC2ggPoF1TYrbHzvE= 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=tHKzsDRz; 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="tHKzsDRz" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e3d462b81cso40931675ab.3 for ; Mon, 04 Aug 2025 07:11:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316684; x=1754921484; 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=2XcyO4Be4c4JXobjE7cGf2J4UxRVRdyWKCOO7WXUW/0=; b=tHKzsDRznyqF+49xYcriauuQh5hkkGMhguYP7PddHXjnP9tgeOepaGHoHKtzsPxZZ8 87B0JHZDH6Ppv5kHueKs5k/Yaf9FJ3+69E6mjtmQ9jSWYNgzxdc+IPzExs49bln2wdE9 XHlwMvj9MEbaJunsvD4pSkoWlqqlfIoLrN5ilHxVenn/LmZ611akmhzikSh/g2/NgNyP bDfOY9cNEZOSmGZLpQ7m2FJeOaYZU/gHo91yC+T9NVgw5BqeEEjCdvAKlQtDnWkUXoY/ QIjyHJRC30IsgfXy70z8bsYJ4fbcD/WV+KH7V4F+1YmdFLghskaRIulceRSldpqLfeEn G6bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316684; x=1754921484; 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=2XcyO4Be4c4JXobjE7cGf2J4UxRVRdyWKCOO7WXUW/0=; b=WSaM8MYpvwxQNOxUm289jInQQ8pQNPZCRCC8xfqY6Dp2BCq1SszwKyWF4oxTS5l1F9 wmTrK+NNYCkvUJ1UpIJX0anjPseONLm1xB/XgJil03306MivHOW06rTQOqlOpx/+FC7z RuJmIkQHfLiPDNiir0ikwMntNfk7hMZzkT0Sbf7W4CJ8VFo4tXkGzAUehRemUlVh2jUT O3k9WJ0itJ7NDtuilbezQG8Od2TudQcyyLRQ4osgdEX+D3/l7ZO7nXkeLnatE3xFTQhS NrtjQgv+dIrtda7MM64nDsgSyUMUFkFqx/WdsxeuVWZgGBiXieffsajjoVco4MFRnaTU x7SA== X-Forwarded-Encrypted: i=1; AJvYcCXkn82mj888Nu4Au+C/WCHbDNDPHovHzXhwaxI2673Jjdh7rI85fPN0fn+a72PIMy4mKkudkmHbhTA2mC8=@vger.kernel.org X-Gm-Message-State: AOJu0Yxrkd05YNIhKVgzTAQkPJSlvBB1smHhoAn1n5xJpQD07/U3bO9F Wt31LSmTnhiCDmGDOdkZ4RZIeagG74d+H2mpxXN2KV/OmwLNUy0AINir4XbOm8z5vmp5LNO3pWu gFLWyNNM6Lw== X-Google-Smtp-Source: AGHT+IGQi4BTJ2NRlvn9MIpnL6hO8RfWm/njfcBlrxUeB0NVxLukwkbFNqqbpuRQl0T8A20PSlKvv7sC5069 X-Received: from ilbec19.prod.google.com ([2002:a05:6e02:4713:b0:3e4:90c:613a]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:2789:b0:3e0:4564:4ef9 with SMTP id e9e14a558f8ab-3e4160fb669mr165839005ab.4.1754316684472; Mon, 04 Aug 2025 07:11:24 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:20 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-5-138ca980261d@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.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 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 3D9302727E9 for ; Mon, 4 Aug 2025 14:11:26 +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=1754316688; cv=none; b=ruvS4LPTg8DzbPIlSKwlleJJmYdIXyGc+u12//9cBujgq3UDzBs87eJ102g7NprToelQ5+RsO6EI5XOHtAP0PskQIe5BGnQPGY/AqCD1uHLvXJEGghsuR/Bj7hqQfauOEDMpPTitm2rS/uwOr4wRSlTun1Whh0srJX2+/onfIOw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316688; c=relaxed/simple; bh=ISHeAtTbjF0ywlkUOrif2m9VMfiKjqLMLKPKTIJ0g2Q=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=i25LCzCP9LKwB/Eq00/m0jD7psemXW4z/OHgEOKk9Ntn/aZ/pCKsxQsuU0u2imFti7XfDy49mhnlWdvpvXtQh1H9FqbCpnAkHDG+p7C5XFN6uTwoaBmE0NlAgBzNHtcfw7fYOpoFlUB/xjBwprxOeYc8jQSdjx4k4NC+ktPVARo= 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=xhr/FzhQ; 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="xhr/FzhQ" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e410d87893so31499345ab.3 for ; Mon, 04 Aug 2025 07:11:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316685; x=1754921485; 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=OevJq0hJai9axJfDLw2hBWWDZmvMq9ola6nPVBRyHUo=; b=xhr/FzhQgltv6KR4PtK1Vbxp2Ftz8Dbd3FTEijUAZdTLu2/SuASIiY2lv3mRWVKTCs QpQywGWY7le/4DBi55/fKYvYW0Pu17M5tcDrG+PpktPF8hZ3y45aS37Er8SY9bb6hgRS RzGYPKZQGIf8FZh3D5zBIs4Fwq25tLQS1ZzezC6zNQbZbujEzVYMIvHWuJhLk9Dqt87b qMxRD1coCr+TkpjooN7eiFekODcZqu7yx3Ie389vepR3HxPfnl+YXPeBcZzK2alsuaaa BBGsBJcNMVlZAMnOjF27U9kY2eyvi2uZHxEFHVCELfHaG8LaGl6J6eGIpNHLpwlNmEAq qk7Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316685; x=1754921485; 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=OevJq0hJai9axJfDLw2hBWWDZmvMq9ola6nPVBRyHUo=; b=iE+D7lqeV1s1tSYFmGwULxHX8XowooL9tMFQjiCutX9pFRn6FdGT3ytF8ilqjZQj9C +wMhIInb5r4p3ju4kg9JDYRj98P/1bMlJ5/XZEFDK1fIu4tw7n7gB+fMoiFBNWOCIHaF 4DQpEhhRgFrYWV79pHz70ISR0ObVZHbHkaHmSVFmKVJboAO4kxmU5wFY5yctLyH8KYSP 5RyHtiSzR4BmESTB5y5uW/f1pL84ZFkLguNCOIHbzgu5TXX3mJhAi9u8/O69w9k++Zf8 Z5bP/OcuceuGFb/awQtft+8X1cfOH1lR20Taa96DTmLxuawRCfVKDf0SUJ4rGemsXWUm rzqQ== X-Forwarded-Encrypted: i=1; AJvYcCUvkf0zigNXXfIUlQaxdSt+erYXQyDrB0gmT8HOPEnflGBOCb8QGznt8P7i7mlPBJr4JAevM8+RNaDjFKw=@vger.kernel.org X-Gm-Message-State: AOJu0YzMVQVSVinsxYoulTiI8WY2uqTIbRTtXMPbee/Axdb3oenu8T+b E6BWqzwESbP06Wu0wzNbCumTLbnX0ZJkJCx9IS3mrcthFpT4vCt3z0QdogdIPihJYhRPCFQBIuA 2XMYaNbDE1Q== X-Google-Smtp-Source: AGHT+IF0g61JQWnl5M9kDiABM6+EyLM9pZdWtQpBCg803gvynVjbvv4u94/0W/gLLGjgBVOPVy0Iqv99X4XB X-Received: from ilbeb7.prod.google.com ([2002:a05:6e02:4607:b0:3e4:1397:9e87]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:1f06:b0:3df:2f47:dc21 with SMTP id e9e14a558f8ab-3e4161cf190mr189998615ab.22.1754316685453; Mon, 04 Aug 2025 07:11:25 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:21 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-6-138ca980261d@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 | 1 + 2 files changed, 439 insertions(+) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index d659a430c1a6b06ded31d49efe4bded909671cb6..923b685f0e1e81b7f95567b1120= 9af264c522373 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_hid_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.hid.hid_usage >=3D (HID_HP_VENDORWAVEFORMMIN & HID_USAGE) && + effect->u.hid.hid_usage <=3D (HID_HP_VENDORWAVEFORMMAX & HID_USAGE) && + (effect->u.hid.vendor_id !=3D haptic->vendor_id || + effect->u.hid.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.hid.hid_usage) { + ordinal =3D i; + break; + } + } + if (ordinal < 1) + return -EINVAL; + + /* Fill the buffer for the effect id */ + fill_effect_buf(haptic, &effect->u.hid, &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_HID; + effect->id =3D -1; + effect->u.hid.hid_usage =3D HID_HP_WAVEFORMNONE & HID_USAGE; + effect->u.hid.intensity =3D 100; + effect->u.hid.retrigger_period =3D 0; + effect->u.hid.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.hid.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.hid.hid_usage =3D HID_HP_WAVEFORMRELEASE & + HID_USAGE; + fill_effect_buf(haptic, &effect.u.hid, &haptic->effect[effect_id], + ordinal); + } else if (effect.u.hid.hid_usage =3D=3D (HID_HP_WAVEFORMPRESS & HID_USAG= E)) { + ordinal =3D haptic->press_ordinal; + if (!ordinal) + ordinal =3D HID_HAPTIC_ORDINAL_WAVEFORMNONE; + else + effect.u.hid.hid_usage =3D HID_HP_WAVEFORMPRESS & + HID_USAGE; + fill_effect_buf(haptic, &effect.u.hid, &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_hid_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_HID); + + 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 fc8979772d00e8b3238b26060c5541065a61811d..9aa910579d09206a2a882a5f708= efd8620428f78 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -72,3 +72,4 @@ 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); --=20 2.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 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 7A57826FA6F for ; Mon, 4 Aug 2025 14:11:27 +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=1754316689; cv=none; b=F9AicGOrsVJFEIicjglAbpt1mz8EFjlZvoIP4lA/IX3fpI1yhesTaWsKvJwEa97ENe4/MmaeJ8pc9OhTbc95LUWn1MuUHNOZCFxRtYOo8I2RYDu09LmNiYrgETMBYu5LmdlE7P2MN3uXDs/QR0mwtqvN2fiQ+Pyti3e/yEUHRjw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316689; c=relaxed/simple; bh=LcDf0eRQa6CauF9x+0Xls3nBIKLOdfur99AWgEtgPGc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=KfChRyJ/QP0m+7JiUvIc3TK/HNAZryPh0C5/F0zfDiZHIhBp2Ht7nq9mUfoCVIeFETc0TUbJiNfSe/rP5B2TylHhbO7sWcmp3LS8fwMaH7Wn6Yo1GBUXPr71LCqEDrj0XdyIlgajb/9kWZzGZwKygM8jTMBAqMu4r/9kJ8oRkUI= 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=LTZwAZ6Q; 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="LTZwAZ6Q" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e3fa175c41so39290735ab.3 for ; Mon, 04 Aug 2025 07:11:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316686; x=1754921486; 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=s5ue1ow6B+qjHFJbRE57LcW6Xcqfgr6lS2a71BgvhiA=; b=LTZwAZ6QzE/FBZEzcr6e2oYqNdc/y1wLFNfCqarlQCaj3vzyKuIMx8YAeKpODY4qkj 3X8WydY5yi+6HDjKbyqsHuDfwXLEXLjHRaHS1C9DZVQcVlBrivUHSZtj4EEoLUj1YXIz LPgirpiDjRQylO0TAeHabk6zYhFF/WpPZgvV/sNx2vDlunIGBy52ER/hk/qFQGjAfnMC Krxsb68qVBSB/RElLYhOf0tmeWBk6J8NK6YMkqFwIpAWxe6UhCk+g4Yob3drDn3mcfBa gNcqNrERixAnBXPrUpRyw3tN6SVupAoNk2kDzYLNHb1kpy6MFWNeL+93gAkfXZ0bDioo uZYw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316686; x=1754921486; 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=s5ue1ow6B+qjHFJbRE57LcW6Xcqfgr6lS2a71BgvhiA=; b=BOkjnwbMDQC1SxbSQ4dz1vd1662otubeg1gOC7eKYIO8WFtkV+z0hJxWANK8tOOqaG MPVAuzsxC0Jv6tLDjfrspPBOLLjVE12wz+fc9k1NJV+ianMKCWtoepPfFELB+grJiwFV GsvIuWfqlzxDOB6SgFl9xnd8FVI2QBzvw7/ynYqqnD0FGXjzw1xqOuqgZ22LAs14EXS6 C4i0eOfadpQxQ3AHxHfwtlibRN7so0Uf66z1Yon0uHJHGObhuCzYwGA5LF6EESfhAKoH IeqjzsP0JnVfEC2LKEr94Afc0MSaser41uWPKPf7nazkeLLFBEmKIVoCYIwBuTkGAe6X 0BcA== X-Forwarded-Encrypted: i=1; AJvYcCUbFEUg4bRY7QysKPxNM4xksmiOYOHWURSiXM7TK1f3JHgmIS3hgbFGdx9kI2FnmA6mj7Z9edEAp4HlIOE=@vger.kernel.org X-Gm-Message-State: AOJu0Yz1BFLMq5G9nBgahose1S58SQA0NB+POqYI8n/G4A7ZlcVulty7 oobDcBqv9jGGUu79BBwGDz+vfCitrvhPlFd5vWaJpVCFFo7o3xo4NR0Qe9ou4zCRi8l4Nz2W0ZN cD8+APvgFvg== X-Google-Smtp-Source: AGHT+IEvuLZqvj7ju8vg5N1aQ1C6x+fs98fRd9oWA6NKgtlabYP/rk9fvPfLoXJvjw/4lU+T796rg6z5WX0F X-Received: from ilbbn7.prod.google.com ([2002:a05:6e02:3387:b0:3e3:eae4:c433]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:398e:b0:3e3:d499:73f with SMTP id e9e14a558f8ab-3e4161b735cmr210331175ab.18.1754316686600; Mon, 04 Aug 2025 07:11:26 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:22 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-7-138ca980261d@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.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 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 C1D8F272E66 for ; Mon, 4 Aug 2025 14:11:29 +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=1754316691; cv=none; b=p5P09P8L/S4CjaYrvKy5bbc6vFouH4jcyGpoffiGO9DGV6vlLqZa20ScVIrGbTFidsiBY04ujUjMsJwc6CuIckuoU/e8cdKtbFv62aiScKz+MQ7JM5xSmdydGKIcDFGtyloFd7hSTW4+LVIXh3lvsAObiV8XFIyXNW6JiWCh4wQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316691; c=relaxed/simple; bh=YA8fLpF/xBHkvyNlZQN1ZRlWkRh2g/iLtt0L44z96mY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QMiSEGmF4JVwKKis2zUvuKFK46fRxnsyNwEp1bijxMxqBWEJH3DwaaEeYoD7jWhGKZEVaDL8y6ZMFTTeK9pzhNta7jmNH92AAryKH/ORkKMOuRj8p6gVMQGQNxYFYdvT89eNDEdmXYrrFOIdpCVy2JSiEjNphRmWkK4DWcNq9Ts= 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=MREqGzNo; 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="MREqGzNo" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e3d23d2e66so45544405ab.2 for ; Mon, 04 Aug 2025 07:11:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316687; x=1754921487; 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=mUwp8SUltYm3fAva2JNxiE1Ag8liv6zV6/FE55B/TvA=; b=MREqGzNoj1OxRDdoIlw3f6IZaVR6Riz0XfrD0vBjz8B1Y7W8MyJpqxdDUwV6NyiBK0 Gm7I1+C9evlJdkie9LP2O2WRRvjnxe5E83CTSfgedVFUs+byUuhjTXQ9thYwBOSXR5De gW5OspcAbRlgrH9i9aBzFkHlprdrQt0+C7lk/1gj57yHGy9elb82YVwQPAGT0P0sU13D dAlIO62RmxZqCkXD1pIYTInODcyH0AiBI7jMxYKG9Mq5FuSGQgXWIuE2+d751z5YW5gw smapheuyl4YPvgHaltjn0GYdwkeW0xZ9xmdzP4j223k+NCof3L+0/huxSRxj+suC+f/B SC2A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316687; x=1754921487; 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=mUwp8SUltYm3fAva2JNxiE1Ag8liv6zV6/FE55B/TvA=; b=QkSeMMvdmcdsaAfu6Q3mL8vBxnN6mQeUtZQpf/2P5Iy34sbD47vWIQoqAEM7/n1OtH cKjNBQSv3zTTZ+yDSKSzjSySyEUe/0wuh7qDlx9Dy/KROJAI7QVog4FNXO2esibRC+93 pU4yphQpF36yr2yl6FS4o95rTrkRaP5GLUqc184YOf3pYLlttQLUPCnu1qXE1bDGdGJo KS8fUJY0lX/Y8w4DvoCxx4gm1fXL+5/Eqx8kzqQmese8ojvWtV84xFmPWQxmpNqKlGJI eEfDvHzfkA80hV8Bouz7lwX8mQgfFaSq8NgsuUAQ4g/Vza2gLFLwZcW8s8ZQ4fcPLILZ ZjcA== X-Forwarded-Encrypted: i=1; AJvYcCWm4vQA5tUtifU/QaP+n8EJLzXF+ya7NDs9z4AfdH3w/3AYk9SmKZXKTkCStbrgdW/iEJJv1S617qm3bQY=@vger.kernel.org X-Gm-Message-State: AOJu0Yy9ohLS3EvtZyL59i96D8ym7kcOABbkCFPO6kL4nRTF3v9kao3W ZE0uJS09Fk3NqhOmRdZF2n7dpXAt5br1WX/0o3RyJpi/Z6k6rvfFSjBg62w6dAqT+eX+WOWZhHP e2aHzboOSAg== X-Google-Smtp-Source: AGHT+IGHisvUCxNFCk/rh543tDzp/qr8GKURFBHfw7awAkPF6bV8B3PQ9TIarjbrhL5VIXBGFZ2fNzAiNyGd X-Received: from ilbed8.prod.google.com ([2002:a05:6e02:4808:b0:3e3:ec97:e375]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:3b82:b0:3e2:83aa:1375 with SMTP id e9e14a558f8ab-3e41615baf9mr169741475ab.14.1754316687442; Mon, 04 Aug 2025 07:11:27 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:23 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-8-138ca980261d@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 | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 923b685f0e1e81b7f95567b11209af264c522373..760dd1d70583489c07e199943eb= ba361d347bfa4 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 9aa910579d09206a2a882a5f708efd8620428f78..0a34b0c6d706a985630962acc41= f7a8eb73cd343 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -73,3 +73,7 @@ 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); --=20 2.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 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 81A0C2749D7 for ; Mon, 4 Aug 2025 14:11:30 +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=1754316692; cv=none; b=Thw8zcbP6SQycILeKb9pmUvViyYNvasJfA31jx+SZ1qeRoDBActaXh7jHG/98cGUjypbRbCIH61KA1WqWGxVJblszbTypi3HqvGScV7YrX2hKDL46gOwzNRc7+kpWS62vFc0+Ak297qle1H5/MHKfFysREwJsjjL1w8LeOebeL0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316692; c=relaxed/simple; bh=6aJ0IUU1tiFShlsFi/Km91IALlxM+CUT5l8lbTEFVkI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=nEd1opTRAKpQMEd4CxIh37JMZGTPSB9DP12td1mIgw1zboZ0EC0WGuPcEkeOICCo9GQXvtKfWUnvLLnEuQOppM5QSjPbr2SDmrTMX/Jo4M5eeAtssh66ftK5nJodELAAv/rgqOmY3hMB3Z/HGKhRFcUFqHjkD5VRtkG30PrSqTA= 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=Ho/n3djK; 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="Ho/n3djK" Received: by mail-oo1-f73.google.com with SMTP id 006d021491bc7-619083195d1so3438482eaf.2 for ; Mon, 04 Aug 2025 07:11:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316688; x=1754921488; 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=Ek7nkTx7oQBr5pmhvnHkJbcjWINhcn0PApuRdg7tPwI=; b=Ho/n3djK/vOziCz6veotTl0aEjkAhlwcVGf6dNfvF9zXQik5iO6xiiBrkdLCEFApk4 RIFUMfGPNJWGAZPyZROIkRTbuUcygeQWU6RnCSQolUdilBctaEfrb9uDipDSFHEhUqFh fZ0JtCDjFKX+yncnF5EhAHriRlDOGOIg0b6oImbBDqTqnBy9wtmdOl4yS52DJPQCOm0A mw7G9Z/vGt3ztODPBC7lWqG9LaxXZ/Px3JBPz9IkafHgOx8NC5iKGRxpLD7f0LgDtdc1 0+l94PFKJQ82NR2OHkMbuXHQEyNZhfZ4oNHtRWIHPdnfYBCBkgm1gndUiokD1UbclRrJ 1vNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316688; x=1754921488; 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=Ek7nkTx7oQBr5pmhvnHkJbcjWINhcn0PApuRdg7tPwI=; b=qhcRf8+GpCGFVIthBVEyB2l+8RTk2/muoKIie5z0txG0CNOjv4DDiIgzymp0Zmg+Y3 CVUpq+vX2M4O/zbazzAgi4KfvDEVgguCp05bl0D1sCau2+7rRXqilEEFhIJyJ8pC33Dy +SaOxGcWOWWPuZ8pHa3QzWhf4QGL0wKmbZd/jx0jL3dm2mg1JGXiSkdNCeSD1Mt8wVbG 23GW3FUplPulgHo1JxvYNIYgi1FnML4k+EPZis1dn2O83u5W3iBZ5S8SX1fsgNsn/vJR nFivqtXwbHbbseWONFllex0b7zuMYGopTsro+6CbZMdICwtD1vvUcIByw7P9/uNrM55B j9Nw== X-Forwarded-Encrypted: i=1; AJvYcCWlFgP3CZuhqXdM6ETP/DUxd7SowkSumUgyGp61b5Iazk9LfLRDmxk/emaxYeXw1o3PgyYNkh97sRJQ/rY=@vger.kernel.org X-Gm-Message-State: AOJu0YzEwk3H+JeVmX6EDgqzZR2lrRQgBY6vjVSD2Ll1KlUOUuhcFpoP EnhF3uqs56waXMSNZlohkMkgKHHpMOLx03mQCv7bQdOCNZUN+DHwFEym67v4Mxd7hDepBz6CwHR 5Ghs0NVl+5g== X-Google-Smtp-Source: AGHT+IEjr5sJfjbBUQYWZhIZ4rOglGuDpQpVSXj939XY+s2kAy7ykktL0lHdO88lLNN48OXhn6sUKk4ZSq/C X-Received: from ooak5.prod.google.com ([2002:a05:6820:c005:b0:619:c124:3048]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6820:f02:b0:619:81ef:2511 with SMTP id 006d021491bc7-6198ef440a8mr5302900eaf.0.1754316688530; Mon, 04 Aug 2025 07:11:28 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:24 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-9-138ca980261d@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.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 2025 Received: from mail-il1-f201.google.com (mail-il1-f201.google.com [209.85.166.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 815622749D6 for ; Mon, 4 Aug 2025 14:11:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316692; cv=none; b=Y3oFA6NGnNrnZ2Y7HoSKmnBi/Hb+mAZAYTWix3zMHPmgf3qTPO4oeJ5eD+xvW94F2Qak4ZMSW6kxy3z3WsZDM6a6NUl3YEKEpVeyi/O8/yuaZn365tEX9VdYrVHP4PlONOcfc7LFICfbYefS/1ok7ENgXz22qOQk3Kc4cubFse8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316692; c=relaxed/simple; bh=6v1MDR/WeMRI65XnJPJkUWNJ4hrJ+LCwOhgu42qcMno=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=r28ZqMV6FubYRuCHYeV6ALOHbMa4r1hXbXuDtN3WqbM5KEg5G9xsXjhd4+wxOVYo3gfnWMcp0OahEVcLCoN4ysaCNSCP/V8JnQg8kcReaPE4JTLSkEAmoyI6l3UuuYT0nxPpvHAVH4QYl5B56g/94psX3nQNmwt9+oOxpUYaGr8= 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=JJyaFl1+; arc=none smtp.client-ip=209.85.166.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="JJyaFl1+" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3e3eec010b9so37721685ab.0 for ; Mon, 04 Aug 2025 07:11:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316689; x=1754921489; 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=7/dNH3FeYrRLFNsE8lPl3SAjeZ5ud/QO8Uhx48+1mZI=; b=JJyaFl1+Mo+E5n927qWPuosXKPmHvJc5zvY+4/FrHI0fSDxHoYSp1szHFLUXcFz9Sp HWwdidEJeR7YrgUC++XPnubPlqcpHEuoAU8HKimAk7g+ivF4PfLl03OKvNX6KuBUAAKr cv8hVifv/R6nVw+vcCmRmaOk15cq0umVF/xs/htwF1aal5V/3vQMaJFyacLd1cL2+O11 OjUiXTIX+3xNzIzulTTyA7h49aodFQgLtk24kjLADT3KNSa0mHSPC88ynP035E1l+xm+ R4dJmFuGk3XQRGvac0o8+PpGRL7EzvMCT9/cbxE2a+BiX9B8Z0/6CSre7tksBI5KZrVS 4NkQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316689; x=1754921489; 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=7/dNH3FeYrRLFNsE8lPl3SAjeZ5ud/QO8Uhx48+1mZI=; b=DoK0BX/j3/PoNUYxDCXB9f9guH/a5CI0z6rGHq2kB6dDv7Y9XEmk/BBO1/tOX+xTB4 gdnw9Oz/KT1LU7pSeLN5fDXG52eUnWEtLV0S31y2Dq5MvYBffHlSQRCwjEUbLDzF5ok7 TGm3pEVx/x8ePtgKg4gNf0lSXqrlN2wdfr5yYHacQrsTBuoozjtlj7kWP71Bo1MR0+2c HDSBQHIeiArckrQBU2YysL4gIE71TxIUzybvZNwNMcFiPv2cBinyE0NpBAsJWnjOgsnS 5wX3KJ9xrl7BSOBeUq6x8m5uwLEabiqSIW5gDGh1TPOYVz+6VepVgwUMTBVA07V9yvbr ASZQ== X-Forwarded-Encrypted: i=1; AJvYcCVNAQHnOPR3IDDPHW1hDXZ79jPlbNKMYm9RanySYAbh7/S+hPweJsVaD1JKpbEVfIDJQ6QBwHPptwSx8Hg=@vger.kernel.org X-Gm-Message-State: AOJu0YwXRhpCKpiWysPDrWxCG1fKEN+cHSJBoYrgP6lTFbg/jYJA0Ogd Sn0yot0WxbkcZmZUjAsB1V0wxYN5yrChYghn7jd3nnfeycCvO4Mdqr8BP7YfmKsnN0Ev8IlNEqC M1IirvWfpag== X-Google-Smtp-Source: AGHT+IE8yJlfGzFt7kta7CCrdssICXTjwzesMzB/FE3Qthy/07S1VLf94JQvmiEXmGBs2sypLXnXQz80YiR6 X-Received: from ilbbm16.prod.google.com ([2002:a05:6e02:3310:b0:3e4:c74:f9f2]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:3007:b0:3e3:d149:8bea with SMTP id e9e14a558f8ab-3e4162bc7e9mr164931645ab.1.1754316689640; Mon, 04 Aug 2025 07:11:29 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:25 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-10-138ca980261d@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 760dd1d70583489c07e199943ebba361d347bfa4..e83363cad6febb5d3fcd786b76e= 05bc16a7e4e94 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.hid.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.hid, &haptic->effect[effect->id], ordinal); =20 + if (effect->u.hid.hid_usage =3D=3D (HID_HP_WAVEFORMPRESS & HID_USAGE) || + effect->u.hid.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.hid.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.hid.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.hid.hid_usage =3D HID_HP_WAVEFORMRELEASE & HID_USAGE; + } fill_effect_buf(haptic, &effect.u.hid, &haptic->effect[effect_id], ordinal); } else if (effect.u.hid.hid_usage =3D=3D (HID_HP_WAVEFORMPRESS & HID_USAG= E)) { 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.hid.hid_usage =3D HID_HP_WAVEFORMPRESS & - HID_USAGE; + effect.u.hid.hid_usage =3D HID_HP_WAVEFORMPRESS & HID_USAGE; + fill_effect_buf(haptic, &effect.u.hid, &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.50.1.565.gc32cd1483b-goog From nobody Sun Oct 5 12:22:59 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 B300B26FA58 for ; Mon, 4 Aug 2025 14:11:31 +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=1754316693; cv=none; b=dZTaSaEePOO5qAzvfqnlMbh92miXJZXPpqaC3t0XzuLouqqObBzfUMbCALU+aXnZ49eFBlhEtkCZeW2qXTb+GXwMYCZfjzVZXTxMjVZp+R2OfggRmwKT5Y79mNzJvNKORubmA2TFlku4bDg6IRLIHK55B6ktqin6w4HCGcjfCiU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1754316693; c=relaxed/simple; bh=md9UePRU22vt6Mwv4wXF5OgaKfWWEer98Wt06d08/OQ=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=DWkTP5qOJUHkTojbIlELpGh8W7LCF2A8etK1RloDTHV/ItkbZXQVojt/eMC+J42r7KGdUhCkzd1HaJt38wYgRoTUwROxIvltunKBnqmu++J1jhPmbVYMu9J2mtp7Apma6rQcY871OGPxSEjLgjG56fBFOqLe+6DKCeTgRkB1uh8= 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=OO06CBDX; 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="OO06CBDX" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e401ca74fbso33745215ab.1 for ; Mon, 04 Aug 2025 07:11:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1754316691; x=1754921491; 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=F6NmZhEmKGYBR+PNmHw027JfaNjka2TCkl4+s269vJA=; b=OO06CBDXdIOcsR1QEVz0Q7qaeNDtCjUX0uzj+ZP40aVvf+bXbO8O5KiDnNqDV5NR3A qNeSx52fXUGVbYgDl2MXvst4uNrMg166lG3bfPLjll5lVYvZ/fLfJSlWLxFzV24xO28r q0mEXjUsimziIf+nfAq1oATW3Ruifj2Nkt0K/pH9uUqz87ia/oldC/Pii9EJL+LTPCba A+pxG0PMs3/EH6WP+YdA63MyB2U0d+ZgagjNEDndUwBs0yKqLAPxEG20u0k06sG/Hf3D wZJhxwf2L9IiYP0FXttKmJvEaZzGsNzsbEViULqFrdN7VtWjNUKgzFAjykrx8n5m/6Eg TTHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1754316691; x=1754921491; 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=F6NmZhEmKGYBR+PNmHw027JfaNjka2TCkl4+s269vJA=; b=R7wqdA8lOQKl0HV3j4itWJzRnlfxFkdOk7BC6gqPMPEth5qU7DBTcwac8QF0aLKA4K PLhcZ3Az7+El5bwr8RW/C5JxyISkjz3LwbOENlGciYp1LzqMLBUDAPY2Jkai3Xk7g1x4 uDJr4O6fXNP9yftzAhMUb4iMgOQoDhQRL7GhPL1zasHPeDlOIXig6gkcmgEu0MPkVjLI hYYbeEPdR0G41fBmmRKaSN/xSgJWnjLo1gW3NPw81AA2XaGxuBYSyBUJEVEXA7aBZjdP NzDVX4wUenxx7i6YTj1wJNo8GLC71uqERDcGjVqAB874GkIo2MsQj1i9ccMUCen1C8B1 aFdg== X-Forwarded-Encrypted: i=1; AJvYcCUkIK6MUvOy7mRqomZv/D8FOKZLxN6jj5ITPDmlSiY9h1l+E1NJFxIjOOJcs4h3HZMbCkYDwEo4WZsqaCQ=@vger.kernel.org X-Gm-Message-State: AOJu0YwdlYdWs7+ysM9W9VjCTb6XtnexsIJZvkG957/lzbgo+jC2+oM9 MxnGowkEhXAS5+yMYviJqMC/F6n59ZzlAOXLFz229H1T6HKgj3/d9LxCuwdk5Rk6A6m9ShcDKuO vTIhWkVclrQ== X-Google-Smtp-Source: AGHT+IFnashLwLqi+8ZIUULRCqBQ8xPAkOpNzmANHD0VchzkUehGr33uHUOQJBilDkrgfGR3jajFwfoMscpG X-Received: from ilbeh24.prod.google.com ([2002:a05:6e02:4c18:b0:3e3:cbd4:ca12]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:1f85:b0:3e3:e78e:4e0a with SMTP id e9e14a558f8ab-3e41610d65cmr191359165ab.1.1754316690876; Mon, 04 Aug 2025 07:11:30 -0700 (PDT) Date: Mon, 04 Aug 2025 14:11:26 +0000 In-Reply-To: <20250804-support-forcepads-v2-0-138ca980261d@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250804-support-forcepads-v2-0-138ca980261d@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250804-support-forcepads-v2-11-138ca980261d@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 Add new option (MULTITOUCH_HAPTIC) to mark whether hid-multitouch should try and configure simple haptic device. Once this option is configured, and the device is recognized to have simple haptic capabilities, 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/Kconfig | 11 ++++ drivers/hid/Makefile | 2 +- drivers/hid/hid-haptic.h | 52 +++++++++++++++++ drivers/hid/hid-multitouch.c | 136 +++++++++++++++++++++++++++++++++++++++= +++- 4 files changed, 199 insertions(+), 2 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index ad6bcc4248cc111705d7cfde2b1481b46353e2d7..b7452f11a4f914f92af582ed054= d42ecbcd6cb9e 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -817,6 +817,17 @@ config HID_MULTITOUCH To compile this driver as a module, choose M here: the module will be called hid-multitouch. =20 +config MULTITOUCH_HAPTIC + bool "Simple haptic multitouch support" + depends on HID_MULTITOUCH + select HID_HAPTIC + default n + help + Support for simple multitouch haptic devices. + Adds extra parsing and FF device for the hid multitouch driver. + It can be used for Elan 2703 haptic touchpad. + To enable, say Y. + config HID_NINTENDO tristate "Nintendo Joy-Con, NSO, and Pro Controller support" depends on NEW_LEDS diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index 361a7daedeb85454114def8afb5f58caeab58a00..be09b4f13b2058a0a1d7eab79f3= 5def758120fc4 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -4,7 +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 +hid-$(CONFIG_MULTITOUCH_HAPTIC) +=3D hid-haptic.o =20 obj-$(CONFIG_HID_BPF) +=3D bpf/ =20 diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index 0a34b0c6d706a985630962acc41f7a8eb73cd343..808cec0b4e51eba1f58b839f3e5= 52493655b7899 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -58,6 +58,7 @@ struct hid_haptic_device { struct hid_haptic_effect stop_effect; }; =20 +#ifdef CONFIG_MULTITOUCH_HAPTIC void hid_haptic_feature_mapping(struct hid_device *hdev, struct hid_haptic_device *haptic, struct hid_field *field, struct hid_usage @@ -77,3 +78,54 @@ void hid_haptic_handle_press_release(struct hid_haptic_d= evice *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, + 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; +} +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) {} +static inline +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..4ff9ac5022b13a0739dbc7ae5f6= ebd84f0114a73 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; @@ -490,6 +494,95 @@ static void mt_get_feature(struct hid_device *hdev, st= ruct hid_report *report) kfree(buf); } =20 +#if defined(CONFIG_MULTITOUCH_HAPTIC) +static int mt_haptic_init(struct hid_device *hdev, + struct hid_haptic_device **haptic_ptr) +{ + return hid_haptic_init(hdev, haptic_ptr); +} + +static void mt_haptic_feature_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_field *field, struct hid_usage *usage) +{ + return hid_haptic_feature_mapping(hdev, haptic, field, usage); +} + +static bool mt_haptic_check_pressure_unit(struct hid_haptic_device *haptic, + struct hid_input *hi, struct hid_field *field) +{ + return hid_haptic_check_pressure_unit(haptic, hi, field); +} + +static void mt_haptic_pressure_reset(struct hid_haptic_device *haptic) +{ + return hid_haptic_pressure_reset(haptic); +} + +static void mt_haptic_pressure_increase(struct hid_haptic_device *haptic, + __s32 pressure) +{ + return hid_haptic_pressure_increase(haptic, pressure); +} + +static int mt_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 hid_haptic_input_mapping(hdev, haptic, hi, field, usage, bit, max); +} + +static int mt_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi) +{ + return hid_haptic_input_configured(hdev, haptic, hi); +} +#else +static int mt_haptic_init(struct hid_device *hdev, + struct hid_haptic_device **haptic_ptr) +{ + return 0; +} + +static void mt_haptic_feature_mapping(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_field *field, struct hid_usage *usage) +{} + +static bool mt_haptic_check_pressure_unit(struct hid_haptic_device *haptic, + struct hid_input *hi, struct hid_field *field) +{ + return 0; +} + +static void mt_haptic_pressure_reset(struct hid_haptic_device *haptic) +{} + +static void mt_haptic_pressure_increase(struct hid_haptic_device *haptic, + __s32 pressure) +{} + +static int mt_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 int mt_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic, + struct hid_input *hi) +{ + return 0; +} +#endif + + static void mt_feature_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage) { @@ -525,6 +618,8 @@ static void mt_feature_mapping(struct hid_device *hdev, mt_get_feature(hdev, field->report); break; } + + mt_haptic_feature_mapping(hdev, td->haptic, field, usage); } =20 static void set_abs(struct input_dev *input, unsigned int code, @@ -856,6 +951,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 + mt_haptic_check_pressure_unit(td->haptic, + hi, field); MT_STORE_FIELD(p); return 1; case HID_DG_SCANTIME: @@ -980,6 +1078,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) + mt_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 +1237,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) + mt_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 +1427,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 +1465,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 +1528,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 mt_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 +1747,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 (mt_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) { @@ -1764,7 +1884,6 @@ static int mt_probe(struct hid_device *hdev, const st= ruct hid_device_id *id) int ret, i; struct mt_device *td; const struct mt_class *mtclass =3D mt_classes; /* MT_CLS_DEFAULT */ - for (i =3D 0; mt_classes[i].name ; i++) { if (id->driver_data =3D=3D mt_classes[i].name) { mtclass =3D &(mt_classes[i]); @@ -1777,6 +1896,10 @@ 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 kzalloc(sizeof(*(td->haptic)), GFP_KERNEL); + if (!td->haptic) + return -ENOMEM; + td->haptic->hdev =3D hdev; td->hdev =3D hdev; td->mtclass =3D *mtclass; td->inputmode_value =3D MT_INPUTMODE_TOUCHSCREEN; @@ -1840,6 +1963,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 (mt_haptic_init(hdev, &td->haptic)) { + dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n", + hdev->name); + td->is_haptic_touchpad =3D false; + kfree(td->haptic); + } + } else { + kfree(td->haptic); + } + return 0; } =20 --=20 2.50.1.565.gc32cd1483b-goog