From nobody Tue Oct 7 03:46:21 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 9E0082571DD for ; Mon, 14 Jul 2025 15:09:41 +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=1752505783; cv=none; b=IdFJwTEmfP4cNji5Yh2QfQTMK8cPsOnxYy+/PLQhSfIBUUiv+KgCzX3SOQJLH1dlxOXby4IvPOBlOe4hYUPed8M+OUxVOekWo39J+kezeqFr99Fi21zojyZ9f8O7/GRkYkWwoPloItjVv/CxegFEpvZaDK9H85jsd3/bp28fXhs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505783; c=relaxed/simple; bh=YNzJxgDiI5v3Q9YLogrSdDXxE5SUiXnUu/73gAN/4Tw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=gqNald+gDMz56bejjZqHumIKQleWSbN3C42iLQTZAWWrZrdKqwzK/Xy001eOAsyYpJuX2Bu4M1wQrWynCFJQSfRObc7MptHMexUI6376UH+lP3HUtlzxn29gL05+oIpXbeeIBbUJUjRhQ4btUQieui7sRjwljXrb22WFNWeQoj0= 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=I6SU5Vwu; 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="I6SU5Vwu" Received: by mail-il1-f202.google.com with SMTP id e9e14a558f8ab-3e0513ec553so98962475ab.3 for ; Mon, 14 Jul 2025 08:09:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505781; x=1753110581; 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=nTkp/+68hZXrxsbuIWT9PqNYoeinIAKwggwOQCHGGJ4=; b=I6SU5VwuXIp1VjFnAJZHGfvKaqGut4fOFEE2z+N4FVXAL/U2RLWPaapgmn3Vfsy/hC xrrtEeMuoswVGyoF11hyIuLH9J6znErmSOKgkaw0huN3kolOcKUHqCmXx4ObOulWqJlV EUby5QuwmQv4JyTeIlqIEHkNbuhAc/ULzCzOLxLKvfYY17M3e4mFn7uf63QdkoIgNIuP Bp9KjN8juRYdDbR34Qmxc0/gnBTpSHm7OrTWt3iPW1RF3+JrPXqOySDto9/B2dF5wEp9 yEn2slgN5v3IMm7dVB6hkEq18dAkB+1M8sb4l5y7ky1ee3NTPwVxv6p/cyduWdtToVbP 9/Pg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505781; x=1753110581; 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=nTkp/+68hZXrxsbuIWT9PqNYoeinIAKwggwOQCHGGJ4=; b=A1pmR9rfUckub/+LCmLo/B9+dgjA7x9sbVOYQaAkbyzD/tHpBxDp722kWbnijOKIKn VKbaemN1QJha+Y0x7ctu8tvGc/Qz8viH2om92KnMXRghn5hXUeFeCT3Hm+9KV9S/fmwu XUpiraEAudACJCHLqCbIJlt15V035SxM2f70fNZtNepHe/BJXm0Mupvzn3OMkJr36Twd yi2nOh1UXZ+xK18a3tutYrpn5Wiic95WouiD0EFVxCBGFDPSUT4dSAvvKe8ZAGWcDUHR 2q8WX6/kEhQEPnx0S9RgRoScH7FQYwyJkZsZdAiVwu4hGNB0YOq/bNOEf6rAy8alCBlx jeEA== X-Forwarded-Encrypted: i=1; AJvYcCX05KGU90LzonxSyGV/zYaDSpgB74gNEHAkZ+ntcq78aHQ8f9f1KFBQNAtjMxmOxNyAiq2G9KBnIiTGJGs=@vger.kernel.org X-Gm-Message-State: AOJu0YzlP2QCy1D1/F5wRPwXN7+G0d7GtP9vUvc7MGo9owKr8C5bsBct UyaVCDPDk8Nq6OcSnA5/W73kZX5rb0Y5IhGmqhShP9UF5sAuxUmaG2Wf2ln6tzYrmr1MrlU3yL9 05DlujCDJAw== X-Google-Smtp-Source: AGHT+IE3G79mHx2jWovSJ3GXo/H85VA7RbU6ArP3q0xZY/vEDsrgte2dk+MESlRVaTvfrBk4jrfK/U56yv/H X-Received: from ilmo4.prod.google.com ([2002:a92:d4c4:0:b0:3e1:4c75:1b6]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6e02:3bc7:b0:3df:3208:968e with SMTP id e9e14a558f8ab-3e2556650e5mr119714415ab.14.1752505778209; Mon, 14 Jul 2025 08:09:38 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:34 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-1-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 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 93B4C25B2F4 for ; Mon, 14 Jul 2025 15:09:40 +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=1752505782; cv=none; b=MlXwWsufDAV0DjOFx3Juzd1dJUEDL5QcuvA7qSr3N0xKaEK1wfETeGHMxVHJDdDyE8lXsNJkI0En+BbVH0sEf/dIhsQ5UcpYB4aGZhrE/XO+QTIgGWa3jexDm8CeIAdm51kXMoh9ZhmwOr4j98qzJUxzzv04Cn8AGepFQkXOlsc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505782; c=relaxed/simple; bh=+dxNjWZwyG3m3cqvuwbj0l/9t+XgQgCGtFB3r1FCdQI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ub26DonDeg3ZPwv9DtDhi522OIKR5DLZ8EpjD0/Dfk/69rFSZnc3coQQ6jux7BY0n2wCQ/nfGbLZGBPYRUnpiqWKQB+HxZInvGWJ632NJJHQg7mrFlsvxJRqVKujBVyqvVukJ6gQ22Hz9Mdyu3E2m36kT+bAI1dDiwN7f17UwUo= 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=nTr7HNOt; 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="nTr7HNOt" Received: by mail-il1-f201.google.com with SMTP id e9e14a558f8ab-3df2d0b7c50so50245745ab.1 for ; Mon, 14 Jul 2025 08:09:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505780; x=1753110580; 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=GZkmyEunIC8PulMHPkw5gRVEvCR20gn2L4yB1DhL5fw=; b=nTr7HNOtBx/BYH7KRwADuDEnI42fRLw3yiI7sC/bnappmvFm2Y2DaHrUz7BsEaP3jG 1Md5F7+aNri91pzIESw1C8mFYT8U5mzLkPjKggXOdyINFbJsfKzrVr8Qj5vD57+EiAN1 Md6r+sdPMRw9A600fRjb7kX4jAYE9l7EKn4yP7ei855An/y8iAXhmJI11xyjTBd7ZmcX d0eZH25UZ93scBhhh+c1JgKUydtyME3LXPfhmWPrve45OXihmZqXeCqF7xKNZyxBW81M V3htnN1sMw67NEm7nnui6F9pIes235f1Cydy9AjRrx8N7Tg5/cKreg1epzZXvOXovyC2 OcXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505780; x=1753110580; 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=GZkmyEunIC8PulMHPkw5gRVEvCR20gn2L4yB1DhL5fw=; b=Y40iPWfBgZDXlRw5+KVrXnYkl5vQd+S6ggiHAW7/GkkfraEkFwoFi/lrtfxq8qmgMP GcRpXkrRivXF0LsIB8Ufr4cWUlMFKlJbaGXP+7F0kYEJr/F0C0h0b3ilaQk4yw+G5m6t l/fFDiBdwhkOh3zZgSHOhG3uIzlap0uUcPCDBZD2HpMr4ZQaDzB05Hp6Mt5fcRJG66Gi 9lI9n9GhGQMmg6hrowBDOnNOxFWRJl3cOYdJqJFePaky6sxFhVDzh66cgTJXOjyss4Cq GLklcVoMY1Gc4PTRgDeiDj1rxuVc77diGniKk6wz8t7Xni3wyxUq8ZHaugvZAEvmr4IC xxbg== X-Forwarded-Encrypted: i=1; AJvYcCUAP0CCFuhr/Db3gowIqtSSgFxJup0OK3jYHdenkBO6VLqCBr6oDIcEiOEJM/5hppn28T3zAop3TNd3j7Y=@vger.kernel.org X-Gm-Message-State: AOJu0YxMFxrn0Ov2+u/aP/t7+FYR/+tZmhocXoqEW4TTV/Yqwx7IHhnl irKL0xyeGUlmxBbQCO38LqGL4+IEiIqI8QLISIWHmpYp8TkbBQdZU6i6krt5pVIJXdI5q/raVSa qVATejXxtQQ== X-Google-Smtp-Source: AGHT+IFbrHzvnu4/zXYPhqDZiNfeDWowVUBss3+pfKlFBXod19WPIg5vvZ5K2c+Viq2W38Xca+2hy+6vp9Bw X-Received: from ilkk4.prod.google.com ([2002:a05:6e02:5e84:b0:3e0:50cf:827f]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a92:ca4f:0:b0:3dd:f4d5:1c1a with SMTP id e9e14a558f8ab-3e25429f85emr122743825ab.17.1752505779805; Mon, 14 Jul 2025 08:09:39 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:35 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-2-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 38A7325BEF4 for ; Mon, 14 Jul 2025 15:09:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505784; cv=none; b=cTTvpvI+ZeQXQcAWYg8JvEg4k4i5gAG0gyH04RABSpycX2TWPqYPeLyIk5vJUhwgWO3x5b0Fw022LYXzPTKTCYTl8AxjHhUg/w3E7TaPh207R36BOgBXN17BPildQjE5wAL0W3tu8iXFGabR6Oob1QCsleNEEH04IR4JhRCDNx0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505784; c=relaxed/simple; bh=iKtLUhh+Juh+ZG5ZUtQEO+EvDyZI3U42bbFTejP3W+A=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QJrRuF16B7IwnN4HPLddvazGMIBlH/Pzdu1hYVa/EVTPpTltifMbi8a29HtxLsQin3ldZ953Qm87OXCl7QPN31XBCY75l8rc/DuGFWRcDugnZzeTol8bIPPbbSG79Ahr5HDU52JvvaCnmHLfKi0r2ciOcE+8fZYtZSZVivD2ezk= 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=qvYIyOdR; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="qvYIyOdR" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-86cf89ff625so394682039f.0 for ; Mon, 14 Jul 2025 08:09:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505781; x=1753110581; 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=d92+E+KSbQZBuJofw2A2ClLCuZNxqiGAFRkpw01JM3k=; b=qvYIyOdRmVv5i7hJbe9huqyjertdm6yJPUAx7njPgyMmYAC5wmG8GMT5K5mKOPMGDO Ukq2LDWst/RVg1zIgRNaw5z0QSugiPjgeX7Z2OwXG1Mk7KncIecyGBjCrOotE7OI54kj frym8Y2kAzH2ni3nStyAfIE7ckFsi3FFbPd7ZT8PeRpTw2YwRFSgASJQZUxkz6yPNwjR Mgzl1WW4oUBvKN1VeQntjlYuM511CRaG0PSvwwtYo601uf/gR0LtBIvkIJIvsnn0sTMU zjoA+YgaNmQGwrfZyIFEqEYi8Ebx1HI8XUql5dPdMLwr7/5jRZDiIxg5YfaZoiWaYXxX ZJjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505781; x=1753110581; 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=d92+E+KSbQZBuJofw2A2ClLCuZNxqiGAFRkpw01JM3k=; b=KUntI6b/PoON5LNk1LKs7v8zv01q6XZcLf+zHjEj8HxQ7+w5W6nvwgnGq7ccNDY8mI UWCXcvgYY/FxJxURz9U2nVEZUs6N0A1SeJYafpubUsGSAk5s26/ogOUWCfYASmudSA5U gWlwkV/FUbqIng0BzjypDiPcpb7ZrsOpF/TKVCMqlV2xECbrkUd/DT9RN8aLqyMoVrXO ONvNW3IvCeRIy3WpoOuvLlYfzSen3nQrTJFCSGjjukhB0SCPsQ5jRTJzWXt8fZoGGLXC L42htE+vplE+3DAq5B1MIktlAWr7GeM8ycAKEiY8q1pPV2xoD5+pR2DwydN3vlKguHQj Up8g== X-Forwarded-Encrypted: i=1; AJvYcCWl6fH1aoBxDspKgNOLtspIfy3fpyVX3EDQQrYVkXBVbL5Fw3pslZfVB1tZnyXuUT9JG8+p8rt9ACIJ/Yo=@vger.kernel.org X-Gm-Message-State: AOJu0YzhzXBnzul5u3bWJD5DUBOTuOP1yr1WNljh+sDddXjD0m4gwuE3 /HgZDt3RHehpi0T5HnEvtT4oT7D2k7J6jmLe3/m0uZbIvlO6oZ1uUgaFBGMF8bjU5f9c5udWfG3 TB2I6Cpmt4Q== X-Google-Smtp-Source: AGHT+IEcKRCtcMlN0Fkp2Ir1eirpv9/Ou2L7oqRs5AZkqrIcCcmIz4HcIIXKSOAy5dw9XMk3JoVW9jSbyHZl X-Received: from iola12.prod.google.com ([2002:a5d:980c:0:b0:86c:f382:ca95]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:6426:b0:875:bc7c:5cf3 with SMTP id ca18e2360f4ac-879786d4ae0mr1434918539f.0.1752505780955; Mon, 14 Jul 2025 08:09:40 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:36 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-3-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 2025 Received: from mail-oi1-f202.google.com (mail-oi1-f202.google.com [209.85.167.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EA84F25C70C for ; Mon, 14 Jul 2025 15:09:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505784; cv=none; b=EtfwQBSF4D7qQou3CfPq+eIAYQV7zFFraWNLlIhQ6AKkji+dCs6oqWuO6NIhcSH+Rn0ZuJmJxoMC+VUixmP5NhkQ+QsSDVKLw1+PZTW5x9I8WN9qRQXDUpI30Az3ui9Eon4sl/9iW/mGT4Nq+ocDBO7iHZMdbcSiltSofTKeJe4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505784; c=relaxed/simple; bh=Uok6DILoPOvZp+Qs77VyjaNIdhcdWjtHXCSGgyLUUqw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=hP9xNIpT6BAQyKdqTP5+HNeXeR6f05jg3ujNHES75I5yJm3s/RviwsspmdROjZc+i+IlmTJBmcONf9aNmY+15naIm3GX/DYEmB+hekFQ/88wtQUjln1gVXKPk4zzVtLO6i4QzUBj2PadjJqAvWG7OLrnHeJHULapjgkbPP75HSc= 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=D0RIjovo; arc=none smtp.client-ip=209.85.167.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="D0RIjovo" Received: by mail-oi1-f202.google.com with SMTP id 5614622812f47-40b94543b86so3794869b6e.0 for ; Mon, 14 Jul 2025 08:09:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505782; x=1753110582; 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=rBfnI0Cc6NSdPSEAHn85ghZ26F1kZSQkAMZb6beNyPo=; b=D0RIjovoTWsLvZ6ucQVwnBtJjl7jW+3oNpwWcgE3P+1+BAnoWl3Cu4/ZpelQNaTb0i zx2LjeMbXcawKJNkt/fQhpZSh3o4N5qlXOCSC7w1F98cQlQlQaKgy0nSceDxmeIarcHE Yqb6BjWr5a+YCocW8htZ3QcWjbBMivGjiZxt+fyPt0K/qIs11m8Du0FGhunT5nRo961n USzZTQ4tUAggAFWdueTuYzsGuU8hv+mIJqF0XGssRunA3mEQf24UXtj5Gtsp9zND92DU MacBzQq0Zho+Yaip38+tqbZjS7BirP9liXZmQcnfvQW+aiXfvn1lb9LGCGPH4DlVacON afOQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505782; x=1753110582; 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=rBfnI0Cc6NSdPSEAHn85ghZ26F1kZSQkAMZb6beNyPo=; b=U4c9qF4+S9DJNyh09TsXm++UII+jYKBxTzBJoC6KXTuIPLi3pZFeTbR+081m/VR+28 kmrVQGZeq3IFsIPxpDkbN219bma3wI7Xd/naPsPIoKBNvYDn8PSn1Ni5FMm+yvqt7l66 CpMml2WOyKdc9zNQzCKYZb4ZcDwdREiAEw9wV+nacTJxq1zsc74d6hkvgYHUDpOdoXlz aLM0MwxkCwUwZBkadAdv8cf3GjO0ez4i5ZMgm42IT+8DwsF6Kq1tdt8Kpi9AcnVFdBI7 QBCC6002R0i9cMXc/qqzQ+/FFJfcpZm2MKXh//yNpfZ14igl9LZPBiN2cjyXKsaUmLhO 9YGw== X-Forwarded-Encrypted: i=1; AJvYcCXWrSpMj7RMQsfUb4IbgxsA3D/VbRyFalARnUQHrmQ3bLFT8R5kdA5l3+Yr8ysPSLOOHAZIPgeLDNmeFnw=@vger.kernel.org X-Gm-Message-State: AOJu0YwegZkurigTWyZK6S0lwl7Mx4Ieb+D/tBFLD46v0/6LEV+d9kwD C4krK/mD8s54uCa5ny+uX3IcVZLYrLIproFjD0AGLfpG+TMUoC8csE5wMKHvBrs6lnisS3xF0fY wKCAUpQ4DBw== X-Google-Smtp-Source: AGHT+IFeQhPP+MSpH+mhTXBJwOZLGuJglj/5F4ZUR92EYeytZhgKDlZN+rECrspde6vsI5uHjJK1ZcUvOl+k X-Received: from oibki2.prod.google.com ([2002:a05:6808:6782:b0:404:e160:ecd8]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6808:690c:b0:40b:711:377d with SMTP id 5614622812f47-415393d60b3mr8755441b6e.18.1752505782144; Mon, 14 Jul 2025 08:09:42 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:37 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-4-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 2025 Received: from mail-oa1-f74.google.com (mail-oa1-f74.google.com [209.85.160.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 4222C25CC7A for ; Mon, 14 Jul 2025 15:09:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505786; cv=none; b=sxBOIQ/LjKamuhAAMNuyuzTpC63y6pUTeYf7edLVIjiNS1zz5Nmam/YBAVkyTQG2BiPHr1itWgiqUYZZ578323ZyoFDe3Rv801M9Aav1SpugFAAv4YtpysfxjE7Caf/wGBB+QVGeQ0Qmzu7wHP9E29UDlmTQ8H4K6TmxcKJYbUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505786; c=relaxed/simple; bh=/xx44fZm9CFefiwNufDk2tw2SX+xzRq16zogo7FXey4=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=WY9mHMsQcH25zFj2uh54Owpko89zliS/fzkvsbERhJ0it3127GuPktU0gpOtvolE6+gEsegeG6B2nocu8C2spgaBTLR9CyfBsq5h2QCTwhFx5wgRYeyIrVtQBkrSG12sN6YhRjnDxuO8zwghi7GgU6QgRlf8lMRhRgf4ZPh7VcA= 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=XmrlTTkc; arc=none smtp.client-ip=209.85.160.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="XmrlTTkc" Received: by mail-oa1-f74.google.com with SMTP id 586e51a60fabf-2f78930a026so5271951fac.2 for ; Mon, 14 Jul 2025 08:09:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505783; x=1753110583; 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=67bqH3GyDp5YSS0C73rDz9/lGoijs6/n2SixQxLDey4=; b=XmrlTTkcuaMOcHWBnyg+r6lVthSGu9jWM1R1oPpthAHtrxnh+0n/ZLKGOHvknPAq+U cBtzPfslmgunbmi0dlLbK1V7+Im+Nhm7X6sn4oGyby8Hy+u7UcnBKKDw/Lw4DYbd1L7Y BFHP1QWha7in6hWKVRhcfRPEXVKrHHLUN2JZHoLTiGNXscVHo9L9cDXiE52U2CJsOowf 0k6wm7/BHuo7NxggkVKugM7WsGHikosJHkgnR82N1sj5w1MzfbRQKZEnRQLlhiCkPKfQ hQUZSMyFEHlVxYS1IbnMqva5zr/1UwI4JBCQKxemtiunnsoeBEnHvwl3LW21A4slcuzA Mi8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505783; x=1753110583; 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=67bqH3GyDp5YSS0C73rDz9/lGoijs6/n2SixQxLDey4=; b=BIFUTHc9nhEPsNrGoBNJqwHU1e4i59RKOSp8rd1WRwjAg5UKBg1Vu20H/Qq+xHWg7w laYBlrtwCc1UuITHaHF7HpUo4RZFA2PK1mg98oUWlpJwiHdac8nIowzgbEOVbn3zrDBx Hcq+RGuHcFq/+NQHyLtr0nBbnx9zrStiqK9Z1RHOoDBOgI3Es9hR/SEXR5ewR0jQXJmr CAfn6xvwyziDYLcpjLxHJVscihdrdolAXSXP1knRoa9GIbGzX+IAUaokNQ1nW81qRvAi 5Sn2E/uQO3OYOqyWuv4tXUzncOQx35FBgD8bh657C80TzLRqSGYJ0GO4F1Wz1JeZIogN x0ew== X-Forwarded-Encrypted: i=1; AJvYcCUQLOhUvZNniT3r7Co5AIBFD300Ov9Cjoyk8qZOZ1uIIbWZtmbJ9NXZdjV4cBiYDF3Wu4aqg9d+vsoEcKY=@vger.kernel.org X-Gm-Message-State: AOJu0Yy6Yf8zXGapYxyTMU9N3c4vYltvbu4kjVrJKqjfwnQ66DhkO8Lh uhORdWK2NbV4ttAwriuxvdPWgErnoL1Us2zk90LNZU+HlrnTD7ZB9Y10TwJC9gR5egewcdoLx7B FwV/A0ye/vg== X-Google-Smtp-Source: AGHT+IGuSQqfqovrFAWMf6k1waoV/ChJgmKytwt31JmlAyf3zT371GAzTFjKdu0b7R7LKngAf0vQQJHsGIF7 X-Received: from oabwn16.prod.google.com ([2002:a05:6871:a910:b0:2c1:64e4:adb9]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6870:e609:b0:2ea:7101:7dc1 with SMTP id 586e51a60fabf-2ff27166c23mr9125788fac.33.1752505783196; Mon, 14 Jul 2025 08:09:43 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:38 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-5-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 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 1413D2594B4 for ; Mon, 14 Jul 2025 15:09:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505787; cv=none; b=KH/ewNxuu0esZ/qthLcvheZwWkinRsxWFIBiDn/X34d6CIoQVOmMWJ8/7KgqTFO4dbq2wq9oTt5PSQCWFRG47NsX8wnwDx7Ks65O48rgnjmVGeeV5n/40s3xTD7/qBWWgk3oXQFSKmt0gn0Zgb9aZN2WDlKuKIC069PbdhhOFjI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505787; c=relaxed/simple; bh=2UzEQwz6IIWkHcbav6H/O9jHS+oVWKPZ8uY23WilaAI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=QWo19b3SAHFrXx9NsdY/g9jyPyNsVW1cLks/lOkWuzBrXZdnaXEz/SyeifyFrAMqzrVlmX5RnkwWiNA8XbN6oZLVIuDMmsM6bEN10y9uTjlskp6nFW3SmWMHQmhtE6i2tntlCKL3NZcAScR5ID/Z/3UJrq2WmgOX+wPshEkuud8= 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=NG15GJgf; 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="NG15GJgf" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-86cf306fc68so755162139f.3 for ; Mon, 14 Jul 2025 08:09:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505784; x=1753110584; 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=mediJG1fLNIDC9THV1/kgz6rwnJycfDV8hM8YJ4EjSc=; b=NG15GJgfqJe29KZ1dA+hzRVle725vznPm9iJ1n97LT2Y9zqgGDi3kYot7Df+P78S9D a1H2UtRPmJ7pXwkL3fIO4v1MvqxhGD9stLCJbeyY2KmirZuLc1Hk9kuGzQkt5BZklbcr 1BEx7mv5M9qA+umUGpQOWz4EuAnJgzOFa3j8J6t2+Tgqv5njK21L+sQ1WSUumMMxIWv9 DtOr/6mIIDCahWcJ0ZT27ojmQz9mJ3t2mQFX14WswCEcLk7bWVL7Jyu0apltJ/cbke5d QTcHJzddIyOU0/AeVxm0eqT5wJTM+0iXPLohJePgSSxGSVU/RCbxjbrik1z94TDxbBld wNMw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505784; x=1753110584; 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=mediJG1fLNIDC9THV1/kgz6rwnJycfDV8hM8YJ4EjSc=; b=NnDI6xTNU6MlmZtvbaPH26a18Q1zUJLU1gVttV8tX1vpmNB/4x9eIUAupWRntsf8DA H6SLQU+vT2tTLHP/7uyq3cAplwCyFefjrpXYhkUt7lOqFtXvx5Jj9UnKYAQ+w5VGwFfa CB+pBCLBwm0zG0DT/onhChIS1ZOYWO9ylnxkDw8IiJk5/BsApngBy4CL9zUAiPqB2TLv QrDgEdw6ns92EbVF1K9lVT4rBii2ASgMIoOxiKPpOGyiB0vISpWe0QsPiHxBtL1LJePF UByZFw5Yf4npbObh9+l+H/KfnqF4FiEd310fpnEe6u9Uswj7e2b9C7fETCrqNPQpypCY gTOA== X-Forwarded-Encrypted: i=1; AJvYcCVbaLTyVC2EaHx5XJsRjSWY/dq2Ag/BHTQNK9Bk7TxjSzPtdjb0FOKAGI8Y532JXO6hbdVydU49PiwRLIo=@vger.kernel.org X-Gm-Message-State: AOJu0Yz4+O5HfBZFrkoCdxqcj8qK53Z2HDfXHJISOgbH7Z+3Gyp5y6rg 6TR4x2gUTaQXIPtetucZ/2UlnU4b38v9RNilI+jRlC8zYg6VxCiXeFnFWD1NYgr6LsYeLSbF15j NnIDW6jpaRQ== X-Google-Smtp-Source: AGHT+IEoUQ32fQIF9+YfICmDAr5NBX2A/eDIFYyTM7mmmTcPLjMke9pMARuRndK9qexL9I2exEycGhwqzoRg X-Received: from iobbh18.prod.google.com ([2002:a05:6602:3712:b0:875:bba9:7a4f]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:7408:b0:876:8790:6ac8 with SMTP id ca18e2360f4ac-87977f5f085mr1286176539f.1.1752505784374; Mon, 14 Jul 2025 08:09:44 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:39 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-6-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 84C3E25A34B for ; Mon, 14 Jul 2025 15:09:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505788; cv=none; b=HxWvIet5E7Hwi+zHjC9mXOcqEphFJp6BJMDfhqrEuKQ6M5UNh5s2bRF7ihynRDylfJH2289dqAaDnSqGuYTnu2c9e1bltmsnsOPVDClblYNwKcBVCIKrB7ileaKztky8mCTHhZ/ouPVhV034NQ3CMlhaBeXDiFSNUlHnoX3LzbA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505788; c=relaxed/simple; bh=Wj07uc8vlmcVFwwaG+KqOnRbxIFVIENOzHLiNdvyj4k=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=TzpIJmcs1k13SYHDBxN2eCx5Va3eQ4g+Vhu8j2JGKe+t0tGctIbQYbspCwxxHmUpI+6Y8A8EYowBLff0sLsAMa3QBxwiqyEQoZ3OGPh2G247HJbe8SVWFym8BwNnY+neJeci8XoKOnfSNORXDpPlzhpjCdUWJ11oi8RqddxeuCo= 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=V7WiEdxF; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="V7WiEdxF" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-873fd6e896bso466159539f.3 for ; Mon, 14 Jul 2025 08:09:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505786; x=1753110586; 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=KXg+nnRrj6QcbCtFDjmsIexAyHPfEUdpnx9NOU2xnIA=; b=V7WiEdxFJY5wMTRv3u/3tFsMI/EPJcE6mEgQi4XcBAb2+7owQSPrcEsTOruYQcVAFS h4gtP0ax9ntDVXCx7abPq8IkwtSM9NJgOEsR/ieQ8qqlF9h4J2OTEYaMzTzvN56+T2P1 5F5PZgCoRGEiwcg+e+OQXIOcqzicvOAj9D+p6B9Qy+DdTaMLTNsm2dsMVtZMJ00eV2/M aDJAWv3aBAbtbB7jXiim2D7VGEj/EosmkTneBzXetoFGOAcku7dNbUq3RdTbcmtcpZ2U I8dw1owg6y1O+1OzQa/NyWob2NzdtC+y6cR2GZsxoaGZNJE6nsmhzQ4PJOQ88iJ10aRv +txQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505786; x=1753110586; 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=KXg+nnRrj6QcbCtFDjmsIexAyHPfEUdpnx9NOU2xnIA=; b=SzzeyjYP6kUHA+ZcIBAzT/Nm+rAwczdHnMB+6CbRozeMHn+FF8xeCaedvfaeZGjSD3 qsCyXoZjlxEJo71qXSTvZBe7cpzR09o3JOHFoXTearhQ6fpfY+oi6eDjrZTjaF9k8GSY 0sNkOSIfI8VKj5PK/TH4zcJQUTtnNuUbXyf12/k2cjISMPYQfmV65QsvDJeNUeagjC/0 FEEg+LGHQgzE09Klu6MByIMkZOXoV0Pg8f3ERii4YQSmXY7gGwdufVIEfPZAX0NsJaB5 1BT2DCyMFVBahgUg4X92rZLD/H7lETyZs2q0MtB/xGFP0NWOtjPcRQDOHs2b8aSLiFHp 3AYg== X-Forwarded-Encrypted: i=1; AJvYcCXS0EJjsXc6OEFJau0P/mPkmBQBsLDPOl61m/m5pboEBuwHfmY4emay/g0eDl2BlOBOMkBy3RVPR8D3d10=@vger.kernel.org X-Gm-Message-State: AOJu0YwcJ0wkpjqsCsxIMdiyiat6YIId4+muL5IvEU+Dxab3QAok1CkP joPHpi4peHpDPNfTYYt77KbyNthni9OEoesbILOnLsR65uwixUUZgsFKSPghoU5QpMYdTv9sfDJ O9MGPV/ydbw== X-Google-Smtp-Source: AGHT+IFP5MLxvfUExYo0yaLckU2HYF2gsyl5lWw//sDEDztcF7zqNGg73rlWEC/2cZwgZoIHQ4hytC2muViD X-Received: from iobeu8.prod.google.com ([2002:a05:6602:4c88:b0:879:8855:695d]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:6417:b0:876:c5ff:24d4 with SMTP id ca18e2360f4ac-87977f78015mr1469868939f.4.1752505785679; Mon, 14 Jul 2025 08:09:45 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:40 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-7-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 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 6444C25F96B for ; Mon, 14 Jul 2025 15:09:47 +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=1752505789; cv=none; b=GDZ7rG63o4f67/ssLDQoB6yLGjjBFz4jICO9gTA4+oVPVKDOGzjKFdj/vWYZHjwhzraDBI9TO41b/YoK6oD48GAaohrGcv4pt1Es/PSeH9BnnRJlH3x0lGY1cEP4bWySMfyypKulFbTsRun75kce4oGeSvxrDdG9GIiPqMFdNV8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505789; c=relaxed/simple; bh=aBLwgLHN44SXrMtvSsPNS/ea4+z3ssj7TR0jIqT7srw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=AOcyaN5wM9NdyFLWbLvFKUdZxnLbDDa1D52lWH1MS7R+vgVz6qeNFub5oohJe5yAKlFrgPi1ScpGyFCAZ9Uc5xypYeTphq1brtFsW5emgUKs7cZ4FAEgoDAEj4bkd13aQ9maZP9ANjKT2tNxZ5LFYLu+8RO/1g2jVVFsj47nFn0= 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=TD4Ez4TW; 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="TD4Ez4TW" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-86cfe68a8bbso312710139f.1 for ; Mon, 14 Jul 2025 08:09:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505786; x=1753110586; 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=FgAgE/U54Vfw8FMo01HLbSRZxI4RE3EOliqkSMOeg7o=; b=TD4Ez4TWFKqEQId+6qMkpCbnYc9PRsAo8sUFSEgdqcGlmQOUEKSAziNSkl/gZRNIOi QusV6yPu5nawKSaQMOLULlXVz1Q6zq6fT/h3IIeMna+5tZbLx7SyRCIGCluiRdhp7KRE 0Qu5udTi8Hyti5JZpdydJM7K28epKtf9q1tm0yihn84yuSiLDEAog3c7u95bJT+qsbms HTl9Ph8b4m3Ido00Qh7txDGGnNg0jih1nWxXTS/Ws5GKyAEgsoX+9KcdQv4wQjD/cAae D+fscI+QgNNHbmtlw1tiZE+VO0BllwsyzNBpg+Aa/GTFe1MSlGfnGFb+mdFhjNGhIGTY CQoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505786; x=1753110586; 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=FgAgE/U54Vfw8FMo01HLbSRZxI4RE3EOliqkSMOeg7o=; b=nhv7ViyYQLBjf3ClxuOvrkmf7NYRsSFQOsLdK27VreNwe5hFOjxnjPvhC/tEr/+xBJ F9y+DZlOtfooAJ27lwR823I1a76AfrFyuFDrz1BslnR4WQnGw9jUgNnXHsbo8bs+xa81 F4f/MR3T808cLJS5eDiWmbHQuljUJVnAWSEZXktZHuWWj6eOTDLdtrEB8rUlvYl0FZtL 7VXcxZ58EZQTfjCjvWdqB3+5+lXT3Bi832Fu1aXr7OIz56dEU/enExzJYmiWpc2b8iyk k/Yi831o/rS5M9kebYcJElbaAPkyJ2Y9JyItWr5sljSHcVL9xooBfLrqkKV1VyQsPqR9 onlA== X-Forwarded-Encrypted: i=1; AJvYcCXXXhHEUsUbXtrNH3pIneCMg+js6WrGI/rGkzQBnpTwn58V5zPuvWryvIzdLUvhebvdNqtqQRqK6O+JnaY=@vger.kernel.org X-Gm-Message-State: AOJu0YwaTjHm6xD4x37FStid41FyL/cqO+cl/MlzFpoVbomn2bUwtMUC 7V2h3XAWd5uAfFAvnHDNpvJM6qW3I5XfVOy15zkmqmQZtkH/j3cGR7vSt+qbgqmVvh9YPL1MhHl 0wcOmPOw+HQ== X-Google-Smtp-Source: AGHT+IEc/wuJWYRSw6yookOyeVU2LGUdFtjrU9b7Z9gz+2dBupfl3JLFSJ1MwP4gdhw8Bp96/AigIB6V5p3e X-Received: from iovs9.prod.google.com ([2002:a05:6602:2bc9:b0:867:5082:3d56]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:7181:b0:879:652a:ac7 with SMTP id ca18e2360f4ac-87977fe76b3mr1232192439f.13.1752505786566; Mon, 14 Jul 2025 08:09:46 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:41 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-8-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 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 1956425FA29 for ; Mon, 14 Jul 2025 15:09:48 +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=1752505790; cv=none; b=Sw4nho8uXXFHDaeQ+YyV+aLPiWnLiit60qGgtekFtVFihAfrhBfkL65TFfNjRaMaX+Tvc5f4e2u6AbrB9pSkoT3e/DkZ1r5iSHT9AgTkhtBgLOU5tUrwPy75Cj7SR+sP9DdDQ00cnxPrqGTOeg3DDi8kxbv5xmwJBx/J+jb5LFk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505790; c=relaxed/simple; bh=UrnSB+AYwWQCe3zBRSCE/AsL/WcQasDyOs6FFVGl3U0=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=lkr9AzKj+e7v7mCCn/jiMhJbX4YlsKnCi4RbUnZsIBGNxrlTulIMmgwzGuo6tdSYQYHbSNKY/icLd+VbQfKi58vyPan5ac3Q4w0hXcHzGNj7hkXbyBKxJgLyGk5YEqDHC6Kztoks7vNQsLj820+3olm0hMjTbCcCb874QHuI8kY= 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=LvN767ax; 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="LvN767ax" Received: by mail-io1-f74.google.com with SMTP id ca18e2360f4ac-87313ccba79so879787239f.2 for ; Mon, 14 Jul 2025 08:09:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505787; x=1753110587; 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=1XeQ2f7hdl7fMjWobSYvSh68hOpph/lgZTAzcMslzSQ=; b=LvN767axR9tglj3JkzFEbioR2+xhMvi9TVP1EnqrfNTrKBy/QVzdqWVMN3idF5VaF4 GlwV+3bjA1Omh+Cmw7deIVEPGrNMb8L94V+BpmnNumCwzMlyf8nU+aaNasgm7sJ0k1Oi PZ67lZ7Peq5CyqBnzfJC5oe19lA83UgMiMiS4FiCGDJWOHmhlCa62NlaqDW73vfqTYY9 A4lbzN5tPMkNYmtpl3KT0008m8hArvwjietVVLHCTdUbYkKPTfWzbsmUp5KJHa0q0mIn MF0J24UGlR5k9vcoZKiALb7qQAkzw1r3Hy5KjDm7vL2G7KyRres2RokkHcbMIk7oXSuK 1RXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505787; x=1753110587; 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=1XeQ2f7hdl7fMjWobSYvSh68hOpph/lgZTAzcMslzSQ=; b=gk4TBkuS/pfaVNvrGYBVXmreOPVnxsTQ61t0IBOuyTkC9hlvD7RL5zzr9jxLs2kKWh kNZIAQlIiFpNE40UrqPsLdDhDNLtzsTaznGiq5bJJYNCi4RedhP1XwY8czvBycgNYXxj ruMb+hSB1ZDSjy4Sn/156P8a19JuG4pgLoF/i8y/by7uKBixsGY0Nn4ZwV6iy10Buwgv KwCxvzZ+KRgakVz6YLvjAe64EVeoj0NbPaPq3rfdHDOY3H4jQdNrcff0PbwdBrS1nLC/ TC7PZ9oGbil6YR8/ITQ5rClaTODb/sYH+NM+43CXSp8ZEz/hCmOVjYBa4Z1Pu/JY41oq Ag+Q== X-Forwarded-Encrypted: i=1; AJvYcCVoyXgQVkjoEKxJAbwxyRhE4ZOZ5dVu8oNylnj46+z+FprZSup0IRae7MG+5RmQsf50zux3vjiVlMqiqLY=@vger.kernel.org X-Gm-Message-State: AOJu0YxZamw78eKNwcB1gAuwyjta4xkAldVL7pJdMS6wWYoGT+29J+Us 5NhzqpkKS3WFtmqaIjQGqTd6t4TAAZYDOlyTLFnXb7IxDZT/AEyf60zE1rPWqQmC47pl7zPCLsV LOn3NDedqwQ== X-Google-Smtp-Source: AGHT+IHBbM/0ggsfRNUfgicPHaMmWiNqsB8R07KqRu569QcPVbUgLFwgBVvWjp+gQAKMnIvWOYpBtbh0Vj4h X-Received: from iovt22.prod.google.com ([2002:a05:6602:1416:b0:86c:fede:130b]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:36cf:b0:86a:93c:f5fb with SMTP id ca18e2360f4ac-879787a0c07mr1320634039f.1.1752505787532; Mon, 14 Jul 2025 08:09:47 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:42 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-9-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D4B0261574 for ; Mon, 14 Jul 2025 15:09:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505791; cv=none; b=qLCYwJXKF/sS88dRcBjx/dox1hNUZZo2KZpGjo0v6meFv2Zaq9fnfDF1wQnv1BQp2mWwhPxaPI0cunkUHwbQ2e8DU/nj4DzF2LHYjxuHzmLQreQpL2zHAv0ZPpDN/C8NfkE89P5fhluz1yMgzZ5HHUBlIcDbovPfFemRC8KHxb8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505791; c=relaxed/simple; bh=5k4hOmm5FsRqTINdSqHY+MKywj3slz9dJzmfWE/9h3o=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=oDUUSM9diz2Sb0mrlLfiL963uBXua4o4vDlT+9y2DAQCkyW7aoql+4BG18xcSUse/KWK2ZY88UOtQySiteM4FWeYIio9D0WffXWSsFjbEIOTiXxt6TnFSCBNA1I3h0trNzZ/3MlF9l87lMRtGbP5QcWJVfJMJcTUsMQco05XwGw= 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=V/hjgysu; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="V/hjgysu" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-86cfccca327so919529039f.2 for ; Mon, 14 Jul 2025 08:09:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505788; x=1753110588; 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=fJOIFm+8Lh6RSd39ar/6t/YbVeNymW5Iv03T46CT4Yw=; b=V/hjgysuLAfD6hx8bS2dPeJmOu4nUOMObvq447LObOR+Li1BU+nWUiX4AG+qWVh5rP fQEtp/48gSewqasmw4Nmc4ehYWkGbmTW/aFi1exFwL4oZd7zRQgyQN4LPfuZcpBxauMk I2S2NXBxUHb6hgnQyE6zBVj6IErEi/NNr9mynubrUYHiHDIzXCWZCQjPuCThiOyRlqBm V+b1zR2KTIlsvs/FTxvati8FdLmqfre9ZGsVY6a6szPF9hp0e8xwYsfIAjjRkJtdyGCW hUEBhbtb0oEBoktP9Qu1bhbCXKpet75srmN+yPwwbcBmzI5Tjl6ZcvxCI7xuFLeCkBeT 8TUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505788; x=1753110588; 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=fJOIFm+8Lh6RSd39ar/6t/YbVeNymW5Iv03T46CT4Yw=; b=tBYSyKl8rlN2zvdcXnnKAdzyfXIPJyuJHGLNifJLqJglRaUbJnwiFeVmJdpyIgGe3u 66ucL26Jr3czH+2x/Dtk4Beqrbm2jURymM3tb83DiMQw0DiqtCMrdM78YcLPFaFt/6+G l9Bm/MTXaIXgCf+qeS8wkUlz/dUL250OJuqzb7PU+QYUNb4KYOLygpH4q2RO+JeSrDiT Hj9jHBfAZEMZ9KiR6tRWN33In63yxXId8/n4C4JaBVNiWacqgHgCFHAYs5LtdqttfxZa gfCR1JkchnPVITnh0ipPqXmu+59XXqGyHWmPpEJUcGzW+iO6B3CV8GOsMucnax69+fzI LhvA== X-Forwarded-Encrypted: i=1; AJvYcCUSI+lRLTgvbYleUpqQdvfGlhjWjKr/ejwb+TTLLY/wzscU7uyRL97qiU3Q+vjEAMQCsH+VmBUIgIElWTE=@vger.kernel.org X-Gm-Message-State: AOJu0YwmMA4NrpTSNYDBraTwTY4y1n32QJi8m74IV54hst192U5eb2sb 0+SzK91R4lL2ic06qi/BOc5d3rBUBD3LwoRo9lpbgY5DUF/jQv/me04UVrdWG2Pnz+VC8oFwtmG GD6+706GAsw== X-Google-Smtp-Source: AGHT+IEmubYECGBWdfe0DU+VaAT0zPkTkvt6Zg9ztBCJhb69BYC8pSS9D9DRVzRcXnXRT57XcoW6QDr+BH4R X-Received: from iovt22.prod.google.com ([2002:a05:6602:1416:b0:86c:fede:130b]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:7408:b0:876:8790:6ac8 with SMTP id ca18e2360f4ac-87977f5f085mr1286207339f.1.1752505788704; Mon, 14 Jul 2025 08:09:48 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:43 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-10-71c7c05748c9@google.com> Subject: [PATCH 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.0.727.gbf7dc18ff4-goog From nobody Tue Oct 7 03:46:21 2025 Received: from mail-io1-f73.google.com (mail-io1-f73.google.com [209.85.166.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7EF68262FE3 for ; Mon, 14 Jul 2025 15:09:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505792; cv=none; b=js2oiQBzwMhx32bvSgu0sQ4fiMdAF1AFqTkgfPnYmAy72xjvE3RaoeAadMRDviJBZRnZFZGmSQTo5sGfQ5v1/ad41Yew0i1r7HUKdp1S5LOTjwhpKDEzYAjv0/hOsp08o0K3P4nWjL01k9i2BNZUNEMvxB75YefOKa0uLrdhLqA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752505792; c=relaxed/simple; bh=tCeGjqnFdNQ0NPSFczvXaBFfpko5DBPet4fKc/RqNQE=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=jpjryvcX4gcjlmuVt6HoGKdO/qMxMCK3+2PbsvHz29akiosv/ZvuKCueDwdtfqw1opo1R05sJ/JmQrfOHTuoYj+Tkskdy3YdyNAMQPS6MMsDR7n7U/dcecfVYMihKrAByRQCcDMbXAvgZ9bYib5+ZpWvLKNVwRhPJKtkQN8IDwI= 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=bok1OWWY; arc=none smtp.client-ip=209.85.166.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--jdenose.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bok1OWWY" Received: by mail-io1-f73.google.com with SMTP id ca18e2360f4ac-86d126265baso412738739f.0 for ; Mon, 14 Jul 2025 08:09:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1752505790; x=1753110590; 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=nHnoetcpMIxLyjvjZ8ksTCx7rsHXxHPVxp+v8N4Zr/k=; b=bok1OWWYRR1xbSD0m0PevtoFw1UNYu/uK5sXSdrPXGZN6byU/WOQCwzMw7lwY7OvkK WmCpUZ8Gmji8GDypxY9ktPa0+Y+jcS+JYlJVQxCWORpxxgZH1qMS48uVs2LOfq7Xuace YfQHjlSyYQtfHG0jgESpz8lWe9jp2EJIhAbtSFB/Uk6qBSF94ONYp57JfbaZl9Yq6cRe diVXzl1332uv7JdbwhO/qpdM9Z7zqYMY++eiD00l2aoq2RfYRSTNYDy7+FWtP5004DB6 ikScXx6WLKS9zeqRrnXws/MoVno0ZkEd9sBJ7CZxktdgyJkvMSbFvo5+yS3WYfwuEO9R voUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752505790; x=1753110590; 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=nHnoetcpMIxLyjvjZ8ksTCx7rsHXxHPVxp+v8N4Zr/k=; b=Q9OtI/HNl71PE+4/kvSrY0HqZGwTXWuJEwusm569iWwEKOHiDwQRKlJZu0SVjshSfP mZxMpC90prQgeMziFDiBOuipFCTKaGvnOwARNencpptxMNrw75UpDRJ2QBmh9VVUthVV yCiFEW9TRTnpI9Q8F37Ti/JfuwzZK0VXao8H2J+mBqI5dZzuLb0OyzB1GzhVAYIypsbE SCBb2g2tE1znbxV2/yPx8yRpHs0Ef4mfapdc5cBmdoyzg0HWaFCgKzhqI2TqMdbGwqQo 8cIV1/nzmhY7GXQ5E05pkdxmja+UgsR0XYvfPtTgJCDZiKj+8wKp/MQKKPbG1K18Jc46 1xjA== X-Forwarded-Encrypted: i=1; AJvYcCVvirbAPX0Y16hhSKuJJcInByazanorjL0Q/zvoE+1E5KUGH6SQqXJGKkJgTUiUS9RK0LcEz2yaN/yPTyc=@vger.kernel.org X-Gm-Message-State: AOJu0YyfB7JM6ZhzZ8CKqReETXpIx06rNgaYWFR7rxwLuUJeis8qTO/C X5MKoprSKPIJorXdL3CBcvdIVrNNNS3gw8y0jdeDcGC8qZlzUWr6jck9uUR4DBdkBeuf93wdZaV N/cbDj7w+9w== X-Google-Smtp-Source: AGHT+IGb4Ih01RYOXIIFyvcMicKVfqZ7k8uINJiabawClKus6rgEQT02suwBT6IS5Nkz1ZVRzviT8K9QrZdY X-Received: from iovt22.prod.google.com ([2002:a05:6602:1416:b0:86c:fede:130b]) (user=jdenose job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6602:6b0f:b0:86c:f8ba:5f08 with SMTP id ca18e2360f4ac-87977f65e0amr1476438839f.1.1752505789851; Mon, 14 Jul 2025 08:09:49 -0700 (PDT) Date: Mon, 14 Jul 2025 15:09:44 +0000 In-Reply-To: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250714-support-forcepads-v1-0-71c7c05748c9@google.com> X-Mailer: b4 0.14.2 Message-ID: <20250714-support-forcepads-v1-11-71c7c05748c9@google.com> Subject: [PATCH 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/hid-haptic.h | 52 +++++++++++++++++ drivers/hid/hid-multitouch.c | 136 +++++++++++++++++++++++++++++++++++++++= +++- 3 files changed, 198 insertions(+), 1 deletion(-) 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/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.0.727.gbf7dc18ff4-goog