From patchwork Fri Oct 7 18:29:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001394 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 030E7C433F5 for ; Fri, 7 Oct 2022 18:30:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229694AbiJGSaX (ORCPT ); Fri, 7 Oct 2022 14:30:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55052 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229688AbiJGSaR (ORCPT ); Fri, 7 Oct 2022 14:30:17 -0400 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DA372A2A95 for ; Fri, 7 Oct 2022 11:30:13 -0700 (PDT) Received: by mail-wr1-x430.google.com with SMTP id w18so8476136wro.7 for ; Fri, 07 Oct 2022 11:30:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=6jkGo1OIbnjIVX1JbkUMDvAp+56f3Eb6cx0364sTMGE=; b=qodRW/rtlsgXyqqaQEHEagLuyZ1hwS2l1r0QDHHqHulJwMVbrSkmjHHoUKaJVB/Ec1 WK4MyLcGF7piu7XQkqW8viKVGA9/Ge4bIfF7tjIS4MIUYA5//FQgn3C/DjkLQhBQ1v4B be7maIZTZIiWLGqaYyL3wIvh+k8319JeaL374N3N4x2kpdYhI2O9W6gF/wiILFMz5GVy 6CRhb5FeGIa+Z14MWajBgbfmn2mTvp4imSGPLCUTCiEZIZpCpNTtImWVSuBG5+gdt1Xi peZObQHPOyy8nIZryTE7j+o4XEriSo1PKDGCeF0DKQ5Fw4h199oeN52R/4AEiqzD2dr+ caMA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=6jkGo1OIbnjIVX1JbkUMDvAp+56f3Eb6cx0364sTMGE=; b=cYa10YDw9dTEPZv2BeoFehHqoyq/cNeawJheIrroC4zoC1yI2x+MyeKPZ2Ys4zAPaM kW4xdN4cYC3z7jqsBNgLpmE917ULU0wxoZJY4/Ck1KiD75O8Jj7REDBCn94xzYxeoeNp 914rcs6Vs87gadfmv4EREVAoD/YFeK/lE2n0W20FTU9uMk3e9+8IthjMb10MvEBEEsNX guL5pjrF8B3TpMRFFAN96r2D++jsxr/n08XKlGhLyyP2cUR3n5FV1wrPGY7at89oFEfp a1fqm165ffCG76+mEUsjuZ2XO/te6C3k/NfHNmkl8Ui15bxAgXlrHlgfAKR2qZYGzHxn ztmg== X-Gm-Message-State: ACrzQf2bHxlopsyur67QOii5XuYC2EJFvhmh3fryso8j/fSjTtVINGhF o6c6KyABKMobl/JAxRkHOFKm65422iY9onLS X-Google-Smtp-Source: AMsMyM7lsPO+aZsIWlnd43JjRF3RqEBmxMBAlJVNwRm6yAuO2Qcfy+12rPUYc8sZH6xsnI2KGpAsDQ== X-Received: by 2002:a5d:5306:0:b0:22c:d927:fc8a with SMTP id e6-20020a5d5306000000b0022cd927fc8amr4128192wrv.700.1665167412378; Fri, 07 Oct 2022 11:30:12 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:11 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 01/17] HID: add haptics page defines Date: Fri, 7 Oct 2022 18:29:29 +0000 Message-Id: <20221007182945.1654046-2-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Introduce haptic usages as defined in HID Usage Tables specification. Add HID units for newton and gram. Signed-off-by: Angela Czubak --- include/linux/hid.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/include/linux/hid.h b/include/linux/hid.h index 4363a63b9775e..3f5899c628211 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -153,6 +153,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_HPVENDOR 0xff7f0000 @@ -311,6 +312,28 @@ struct hid_item { #define HID_DG_TOOLSERIALNUMBER 0x000d005b #define HID_DG_LATENCYMODE 0x000d0060 +#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_VD_ASUS_CUSTOM_MEDIA_KEYS 0xff310076 @@ -398,6 +421,12 @@ struct hid_item { #define HID_REPORT_PROTOCOL 1 #define HID_BOOT_PROTOCOL 0 +/* + * 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 From patchwork Fri Oct 7 18:29:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001395 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E6164C4332F for ; Fri, 7 Oct 2022 18:30:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229790AbiJGSaX (ORCPT ); Fri, 7 Oct 2022 14:30:23 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229703AbiJGSaV (ORCPT ); Fri, 7 Oct 2022 14:30:21 -0400 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6C3B6A3F4D for ; Fri, 7 Oct 2022 11:30:14 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id a10so8444130wrm.12 for ; Fri, 07 Oct 2022 11:30:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=gNcP0V+BsO+JizwSO2P7jcmp++wZlZAJV8zZGust2kg=; b=cEX7SqM7ui53mq1DSd3t8StextmPdA0twE5fmK/Y2571DdumhdZGb3akgjL3BHIwbk QIeyKyrBA1i7lUjurtewy5rqAita6GAaUUVZUjlRHWftMZyxBp2EZrV/UKjtXYWf2kg1 +8e6MIbN+Z82fID29R5qqinWlJbSReRKc7lJcDmlHEIAitQksafsZHXIVwh5V9Iollvf S56SzdLeUoFXm0+amQl9XctpKtRFxn4/geM0cGPAuFL4+tUYwUkk+pkiKHjOjgdtiTCt cWoBpbAidhuEe2GNSFN4TrrerirrbgWxD5bpSRsq353aRembmJEilqCJMzxSXNGCflrv fgww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=gNcP0V+BsO+JizwSO2P7jcmp++wZlZAJV8zZGust2kg=; b=gz58wKzv+mArWWj61q4vJ20hGhNM6bJq4bOLJPFFZcMTdxfWcQcTRRKeJKr7R3tW6p 01mnx3HTACudc2ljbjD+AiIqjOkn8Gwo9vsKbnaRE3h+3IVisHwdnyf7aBzaEFCOIZu8 TjLeoUUJ1HD3AUDuyQjalmKfbARN3mSk+oLzSnGeIb0vRr1s3KXzb4tcI2XSshPECr23 /uLU1fz09tKXoSW8bGw4HUCpX+bkX9r9WD3HNWVUF40ecJx7Wp+ZTD9xzRUr6lxYuFu/ WmkKdsO5nRpaj47dtOEAOQ0HAzjxvGiF0QdT8e81JCLZ1l/c7U+YpnEj2hvtf/zziEzl 6g+Q== X-Gm-Message-State: ACrzQf23vR/bt1h3Pt/mX6bvXP70m0I3tqg7IcpzPPdG2p/eCUkLo/h5 dPp7EzUo1jEwM58qYARjIl+J0KbSEq4mfT7I X-Google-Smtp-Source: AMsMyM6Q0qjzv2tC3lUhwqTXYBxMzabtlBqu8vXLnWIzSbecI/HiKhh66pDDI7ZCrmNAU6JTkANVFQ== X-Received: by 2002:adf:f5c5:0:b0:22e:264b:2179 with SMTP id k5-20020adff5c5000000b0022e264b2179mr4070028wrp.386.1665167412969; Fri, 07 Oct 2022 11:30:12 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:12 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 02/17] Input: add FF_HID effect type Date: Fri, 7 Oct 2022 18:29:30 +0000 Message-Id: <20221007182945.1654046-3-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org FF_HID effect type can be used to trigger haptic feedback with HID simple haptic usages. Signed-off-by: Angela Czubak --- 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 2557eb7b05617..3ea7c826c6fb2 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -428,6 +428,24 @@ struct ff_rumble_effect { __u16 weak_magnitude; }; +/** + * 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-defined 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; }; @@ -471,6 +490,7 @@ struct ff_effect { * Force feedback effect types */ +#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 -#define FF_EFFECT_MIN FF_RUMBLE +#define FF_EFFECT_MIN FF_HID #define FF_EFFECT_MAX FF_RAMP /* From patchwork Fri Oct 7 18:29:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001397 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81655C433F5 for ; Fri, 7 Oct 2022 18:30:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229829AbiJGSa0 (ORCPT ); Fri, 7 Oct 2022 14:30:26 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55462 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229710AbiJGSaV (ORCPT ); Fri, 7 Oct 2022 14:30:21 -0400 Received: from mail-wr1-x434.google.com (mail-wr1-x434.google.com [IPv6:2a00:1450:4864:20::434]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35DFBA3F7B for ; Fri, 7 Oct 2022 11:30:15 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id j16so8471448wrh.5 for ; Fri, 07 Oct 2022 11:30:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=drDDGSL6Q8RDfLC8xntw44nc3OWMxJhGm2KM89I9WAQ=; b=F30GtYkx9OYa+gXvcFUXX4+OfQhzAotOfiX/tVdZWhbZ34fhfGcTnHK/WKlqOr+zQR rt4Rr6fZ3IJPApJlVjWvp+oxtXAYsgMJVWe17f//0srhfuZMS7HXf6qdAqdPWubpLzXf ZbmN9h91GF18tVXsv6vqXrqReNEI67B9RNUtOLfwoRmSUuN6MtooUUZxVXKQ3+xssmoM B+OZmoi97b3SCSSt5cykjiCqOFcy8Md7H5tetSvxM6QLhUGdMgwbLvoROQeSTdHfzoHK yYgDoP3Gr9yye3daUxFheKfueY/+1Go5UvFMF8S3FpycsIEYq2bfMVJMaIcd4QxvZeOY aWQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=drDDGSL6Q8RDfLC8xntw44nc3OWMxJhGm2KM89I9WAQ=; b=Qp2/nXvtQdQTfSbGhJKw/u0DmQr0gpwSlMIbizDZapvP19btZdJk2DdT0XYpsVxjc4 9Cr7cuOyyCw8xYDb3GAlVIVuSOXF8FtVfyaSV0/lET/gHyz4KRnaF3nClRr0XnYyJ1rj DrFGTJjHUR+THUEnVGViM/bKBc4e1B88PUordkO8+3GBDIVMgtH38KFxSrxtjCdUIJg5 R8AU+UXS85tFjebkcupnXRDG2YKo1LqnTOKkEA41TRHj64+S8k/nfetkgfGJfeuySS/3 ecxhoZ34KkeVEy42Co1AiXlpSTgpEO8FZk01c7zvoRS0Fe8s1kWmFijy/BzxGzN+YGCt WUFA== X-Gm-Message-State: ACrzQf3ZCf7Oo01xGkTM87Ae1eDEudq1u7HtepEG+WNRL7AQXulZQS6S Gk4gnH+i5hSHxLppxWHho8dN4d9VD1rikjj5 X-Google-Smtp-Source: AMsMyM5uOSqt6sgJrFv47k99D1KSDvUcQNUwWzj6LdXwsaANmO1qXNA41KwsNkekSMYGGiRBqMx4pg== X-Received: by 2002:adf:e18b:0:b0:22e:a2ce:7746 with SMTP id az11-20020adfe18b000000b0022ea2ce7746mr2897225wrb.468.1665167413910; Fri, 07 Oct 2022 11:30:13 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:13 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 03/17] HID: haptic: introduce hid_haptic_device Date: Fri, 7 Oct 2022 18:29:31 +0000 Message-Id: <20221007182945.1654046-4-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org 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. Recognize the input device as a haptic one if the reports are found. Verify that the pressure unit is either grams or newtons. Mark the input device as a haptic forcepad if the unit is correct. Signed-off-by: Angela Czubak --- drivers/hid/Kconfig | 3 ++ drivers/hid/Makefile | 1 + drivers/hid/hid-haptic.c | 65 ++++++++++++++++++++++ drivers/hid/hid-haptic.h | 113 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 drivers/hid/hid-haptic.c create mode 100644 drivers/hid/hid-haptic.h diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 6ce92830b5d1f..1b47e5d0d1c07 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -89,6 +89,9 @@ config HID_GENERIC If unsure, say Y. +config HID_HAPTIC + bool + menu "Special HID drivers" depends on HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b0bef80981394..8ae531355f5bf 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -4,6 +4,7 @@ # hid-y := hid-core.o hid-input.o hid-quirks.o hid-$(CONFIG_DEBUG_FS) += hid-debug.o +hid-$(CONFIG_HID_HAPTIC) += hid-haptic.o obj-$(CONFIG_HID) += hid.o obj-$(CONFIG_UHID) += uhid.o diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c new file mode 100644 index 0000000000000..ea1004319bc02 --- /dev/null +++ b/drivers/hid/hid-haptic.c @@ -0,0 +1,65 @@ +// 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 == HID_HP_AUTOTRIGGER) { + if (usage->usage_index >= 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 = + field->value[usage->usage_index]; + haptic->auto_trigger_report = field->report; + } +} +EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping); + +bool hid_haptic_is_forcepad(struct hid_haptic_device *haptic, + struct hid_input *hi, struct hid_field *field) +{ + if (field->unit == HID_UNIT_GRAM || field->unit == HID_UNIT_NEWTON) + haptic->is_forcepad = true; + return haptic->is_forcepad; +} +EXPORT_SYMBOL_GPL(hid_haptic_is_forcepad); + +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 == HID_HP_MANUALTRIGGER) { + haptic->manual_trigger_report = field->report; + /* we don't really want to map these fields */ + return -1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(hid_haptic_input_mapping); + +bool hid_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic) +{ + if (haptic->auto_trigger_report && haptic->manual_trigger_report) + return true; + + return false; +} +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 0000000000000..ea96b0fb540f2 --- /dev/null +++ b/drivers/hid/hid-haptic.h @@ -0,0 +1,113 @@ +/* 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_PRESS_THRESH 200 +#define HID_HAPTIC_RELEASE_THRESH 180 + +#define HID_HAPTIC_MODE_DEVICE 0 +#define HID_HAPTIC_MODE_KERNEL 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; + s32 force_logical_minimum; + s32 force_physical_minimum; + s32 force_resolution; + u32 press_threshold; + u32 release_threshold; + 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_orig; + u16 press_ordinal_cur; + u16 release_ordinal_orig; + u16 release_ordinal_cur; +#define HID_HAPTIC_RELEASE_EFFECT_ID 0 +#define HID_HAPTIC_PRESS_EFFECT_ID 1 + struct hid_haptic_effect *effect; + struct hid_haptic_effect stop_effect; + bool is_forcepad; +}; + +#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 + *usage); +bool hid_haptic_is_forcepad(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); +bool hid_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic); +#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_is_forcepad(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 +bool hid_haptic_input_configured(struct hid_device *hdev, + struct hid_haptic_device *haptic) +{ + return 0; +} +#endif From patchwork Fri Oct 7 18:29:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001396 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D952AC43217 for ; Fri, 7 Oct 2022 18:30:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229713AbiJGSaZ (ORCPT ); Fri, 7 Oct 2022 14:30:25 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55438 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229708AbiJGSaV (ORCPT ); Fri, 7 Oct 2022 14:30:21 -0400 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35D3FA3F77 for ; Fri, 7 Oct 2022 11:30:16 -0700 (PDT) Received: by mail-wr1-x435.google.com with SMTP id b4so8501693wrs.1 for ; Fri, 07 Oct 2022 11:30:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=CmRNqBI0gFXizyEQOegkkhDKDDOx721TmYyEvWtSMlk=; b=awDm5bCjYoyV0SgM0kmYHxalh3xodyD+6ORkktAtd1zgeFB/+XAy+k4tGTrjaaWzU5 rDXAa6QlkjlHpVx+giz+8zD3nzPq/VqP+VV0wxrBICTewTjBDTfc3z/JsBLgI9UDQW1M hPkiNZ0AqhnbuN6jYNX3wROkfO7WbczRKM+ADe0+0t34s6LEK6qzDiDo0FD9eCpbbRQj UOEYKha27PkqQ3/Ng6SFzw8PAo6QTRnjN2bs3tOuJSLD1mjODC+XMPWARmRiXYKe+YwI uYaSal21ilYM14M4Q4na24/PiHgYefuguwuBkyzQANAQ/kdkQveooIaNPs2cgd0HPllt pRUg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=CmRNqBI0gFXizyEQOegkkhDKDDOx721TmYyEvWtSMlk=; b=YPAQ4sTR6zzmzYVbmTrmACYB+E66Quxt2BOm3Qw3OAoklRAvF7nD8CFEfp6alTxHgM pgmZ393bwM9+LfA5pPxTUPWuCAz5gjjJobsGjTXWyxrdqvFpfTbGdL4eh+1pqg/FSuLl CxVOHyZFpYX76/4HhzK/DMlToddGpAfpNxmigu3l0J7uaJguKB12N4xb24rsNdsXkbhL TFn3H4mn/6mYtjf2Bk/eVVGroRC4BxQPJYtwwP0RIgMJC3hYTmSGrSdOHLShsDwuToPd IaPPf9nk5x4zWQ/xXoGrqxuuDAfBKO9SxSkAGhS2I2G9H4AirPyTlbzB0NCMdfUykFwg iFAg== X-Gm-Message-State: ACrzQf0Z8qdCyF4Llnm6vDra404qfk5a9VjN9VWXMTKyL/5RYz4McXPP ZHA7k3y7xkLfoVY1i6bhYrhqsTDYY5F7yF1E X-Google-Smtp-Source: AMsMyM5EpCcZjuY6zXzdLBjT0bhOoyu5Z1tzZ/FSw3mt2oDw6nTFd/oljtvoaUN+J/UAxT9bMTlj8Q== X-Received: by 2002:a5d:6dad:0:b0:22e:734f:31b1 with SMTP id u13-20020a5d6dad000000b0022e734f31b1mr4294521wrs.11.1665167414663; Fri, 07 Oct 2022 11:30:14 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:14 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 04/17] HID: input: allow mapping of haptic output Date: Fri, 7 Oct 2022 18:29:32 +0000 Message-Id: <20221007182945.1654046-5-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org This change makes it possible to parse output reports by input mapping functions by HID drivers. Signed-off-by: Angela Czubak --- 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 859aeb07542e3..c60cee4bb6aa6 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -653,9 +653,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel if (field->report_count < 1) goto ignore; - /* only LED usages are supported in output fields */ + /* only LED and HAPTIC usages are supported in output fields */ if (field->report_type == HID_OUTPUT_REPORT && - (usage->hid & HID_USAGE_PAGE) != HID_UP_LED) { + (usage->hid & HID_USAGE_PAGE) != HID_UP_LED && + (usage->hid & HID_USAGE_PAGE) != HID_UP_HAPTIC) { goto ignore; } From patchwork Fri Oct 7 18:29:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001399 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EA0BEC433FE for ; Fri, 7 Oct 2022 18:30:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229450AbiJGSa2 (ORCPT ); Fri, 7 Oct 2022 14:30:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229689AbiJGSaW (ORCPT ); Fri, 7 Oct 2022 14:30:22 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5460B0B1F for ; Fri, 7 Oct 2022 11:30:16 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id a3so8529303wrt.0 for ; Fri, 07 Oct 2022 11:30:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Wjc/grcbvpRYxWtNVyhfXz4bwGO/ZdZiH0OoA/I8AcM=; b=I7s5qjQkj3r0TgA8DwYf877Uwk27TEMaXrrWLuFgbcXOIsN2vqyc6gcvaxve2YOqdB KmGqwIusF7O8l9encr/1OQOGsw4344FJLV4Vs8hllJhoD7LJ+4/TrEemPBXJSP3mxcFS P9eUqeXMQLDRIxo5ez4AVicRYNVsxwqD0oHLoETqs7R2swDAniLTNeICzD9Qt99qtzWu JjtIOb8IVGeWrg4wwlLLdOtscJihgPoj3+wVOlKCLVSWY5JhuS2Tpf0TMMvvbkd+6FUy udpDfHqN0R0pzRiaFBAXHoeMg8FdbuwrFXWZBYmffvkYmX4FVdfJEXN1AYf6SqKr4o0B w07g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Wjc/grcbvpRYxWtNVyhfXz4bwGO/ZdZiH0OoA/I8AcM=; b=Vem2dNLC/N2d4d6A5sIGZ/GH7xfe1YlYliYE0xkcEL4ahPS2OGjWhqM6TRaJ1oa/8J htoS6btY638oYKdpx7nPYVGwA7AEogmFWDrg1ZeDOF8hEMqXq+9N1DhKg++CtSaK7t8+ rmSi4z6jCaLykxiKp3dSsDMRd0H+7W2707L16Avwqfs9zjftM3c5rbVuq+SzdtBU3lSJ 0j87c5zel7nTqS37uFPX4CHhGpNgAl49AQczWfsdSmoL3TgVE3l+4tzQTjQjC/pa4HMF Ks43kKnnqhJWJuRrF6k5NlW7NDfeIQGb98PV2bYzFPvf6g/CqtWNLB7v8ZZNFRMqdyei ST4g== X-Gm-Message-State: ACrzQf0HoIGgRt3p6zKZ21ZSHNsnWTFuKLjDaxbRjoagU+BqtSkHQ04R N6nhWzRl/iuh35Rr3yCPDlwaxddxM3w/FLW8 X-Google-Smtp-Source: AMsMyM7McWv6QpQteNMUUv5uQ8kKMXAF6yR+knvdX+BSU5UvfOJCIPCWMQnbf6uuG0sRwX7acZ8ghw== X-Received: by 2002:a5d:5988:0:b0:22e:5a65:1e21 with SMTP id n8-20020a5d5988000000b0022e5a651e21mr4262513wri.338.1665167415288; Fri, 07 Oct 2022 11:30:15 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:14 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 05/17] HID: haptic: initialize haptic device Date: Fri, 7 Oct 2022 18:29:33 +0000 Message-Id: <20221007182945.1654046-6-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Add hid_haptic_init(). Parse autotrigger report to retrieve ordinals for press and release waveforms. Implement force feedback functions. Signed-off-by: Angela Czubak --- drivers/hid/hid-haptic.c | 447 +++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-haptic.h | 6 + 2 files changed, 453 insertions(+) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index ea1004319bc02..327106152d795 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -5,12 +5,16 @@ * Copyright (c) 2021 Angela Czubak */ +#include + #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) { + u16 usage_hid; + if (usage->hid == HID_HP_AUTOTRIGGER) { if (usage->usage_index >= field->report_count) { dev_err(&hdev->dev, @@ -25,6 +29,20 @@ void hid_haptic_feature_mapping(struct hid_device *hdev, haptic->default_auto_trigger = field->value[usage->usage_index]; haptic->auto_trigger_report = field->report; + } else if ((usage->hid & HID_USAGE_PAGE) == HID_UP_ORDINAL) { + usage_hid = usage->hid & HID_USAGE; + switch (field->logical) { + case HID_HP_WAVEFORMLIST: + if (usage_hid > haptic->max_waveform_id) + haptic->max_waveform_id = usage_hid; + break; + case HID_HP_DURATIONLIST: + if (usage_hid > haptic->max_duration_id) + haptic->max_duration_id = usage_hid; + break; + default: + break; + } } } EXPORT_SYMBOL_GPL(hid_haptic_feature_mapping); @@ -63,3 +81,432 @@ bool hid_haptic_input_configured(struct hid_device *hdev, return false; } EXPORT_SYMBOL_GPL(hid_haptic_input_configured); + +static void parse_auto_trigger_field(struct hid_haptic_device *haptic, + struct hid_field *field) +{ + int count = field->report_count; + int n; + u16 usage_hid; + + for (n = 0; n < count; n++) { + switch (field->usage[n].hid & HID_USAGE_PAGE) { + case HID_UP_ORDINAL: + usage_hid = field->usage[n].hid & HID_USAGE; + switch (field->logical) { + case HID_HP_WAVEFORMLIST: + haptic->hid_usage_map[usage_hid] = field->value[n]; + if (field->value[n] == + (HID_HP_WAVEFORMPRESS & HID_USAGE)) { + haptic->press_ordinal_orig = usage_hid; + haptic->press_ordinal_cur = usage_hid; + } else if (field->value[n] == + (HID_HP_WAVEFORMRELEASE & HID_USAGE)) { + haptic->release_ordinal_orig = usage_hid; + haptic->release_ordinal_cur = usage_hid; + } + break; + case HID_HP_DURATIONLIST: + haptic->duration_map[usage_hid] = + field->value[n]; + break; + default: + break; + } + break; + case HID_UP_HAPTIC: + switch (field->usage[n].hid) { + case HID_HP_WAVEFORMVENDORID: + haptic->vendor_id = field->value[n]; + break; + case HID_HP_WAVEFORMVENDORPAGE: + haptic->vendor_page = 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 = haptic->manual_trigger_report; + struct hid_usage *usage; + struct hid_field *field; + s32 value; + int i, j; + u8 *buf = haptic_effect->report_buf; + + mutex_lock(&haptic->manual_trigger_mutex); + for (i = 0; i < rep->maxfield; i++) { + field = rep->field[i]; + /* Ignore if report count is out of bounds. */ + if (field->report_count < 1) + continue; + + for (j = 0; j < field->maxusage; j++) { + usage = &field->usage[j]; + + switch (usage->hid) { + case HID_HP_INTENSITY: + if (effect->intensity > 100) { + value = field->logical_maximum; + } else { + value = field->logical_minimum + + effect->intensity * + (field->logical_maximum - + field->logical_minimum) / 100; + } + break; + case HID_HP_REPEATCOUNT: + value = effect->repeat_count; + break; + case HID_HP_RETRIGGERPERIOD: + value = effect->retrigger_period; + break; + case HID_HP_MANUALTRIGGER: + value = waveform_ordinal; + break; + default: + break; + } + + field->value[j] = value; + } + } + + hid_output_report(rep, buf); + mutex_unlock(&haptic->manual_trigger_mutex); +} + +static int hid_haptic_upload_effect(struct input_dev *dev, struct ff_effect *effect, + struct ff_effect *old) +{ + struct ff_device *ff = dev->ff; + struct hid_haptic_device *haptic = ff->private; + int i, ordinal = 0; + + /* If vendor range, check vendor id and page */ + if (effect->u.hid.hid_usage >= (HID_HP_VENDORWAVEFORMMIN & HID_USAGE) && + effect->u.hid.hid_usage <= (HID_HP_VENDORWAVEFORMMAX & HID_USAGE) && + (effect->u.hid.vendor_id != haptic->vendor_id || + effect->u.hid.vendor_waveform_page != haptic->vendor_page)) + return -EINVAL; + + /* Check hid_usage */ + for (i = 1; i <= haptic->max_waveform_id; i++) { + if (haptic->hid_usage_map[i] == effect->u.hid.hid_usage) { + ordinal = i; + break; + } + } + if (ordinal < 1) + return -EINVAL; + + /* Fill the buffer for the efect 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 = hid_hw_output_report(hdev, effect->report_buf, + haptic->manual_trigger_report_len); + if (ret < 0) { + ret = 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 = container_of(work, + struct hid_haptic_effect, + work); + struct input_dev *dev = effect->input_dev; + struct hid_device *hdev = input_get_drvdata(dev); + struct hid_haptic_device *haptic = dev->ff->private; + + mutex_lock(&haptic->manual_trigger_mutex); + if (effect != &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 value) +{ + struct hid_haptic_device *haptic = 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 = FF_HID; + effect->id = -1; + effect->u.hid.hid_usage = HID_HP_WAVEFORMNONE & HID_USAGE; + effect->u.hid.intensity = 100; + effect->u.hid.retrigger_period = 0; + effect->u.hid.repeat_count = 0; +} + +static int hid_haptic_erase(struct input_dev *dev, int effect_id) +{ + struct hid_haptic_device *haptic = dev->ff->private; + struct ff_effect effect; + int ordinal; + + if (!haptic->is_forcepad) + return 0; + + effect_set_default(&effect); + switch (effect_id) { + case HID_HAPTIC_RELEASE_EFFECT_ID: + ordinal = haptic->release_ordinal_orig; + if (!ordinal) + ordinal = HID_HAPTIC_ORDINAL_WAVEFORMNONE; + else + effect.u.hid.hid_usage = HID_HP_WAVEFORMRELEASE & + HID_USAGE; + fill_effect_buf(haptic, &effect.u.hid, &haptic->effect[effect_id], + ordinal); + break; + case HID_HAPTIC_PRESS_EFFECT_ID: + ordinal = haptic->press_ordinal_orig; + if (!ordinal) + ordinal = HID_HAPTIC_ORDINAL_WAVEFORMNONE; + else + effect.u.hid.hid_usage = HID_HP_WAVEFORMPRESS & + HID_USAGE; + fill_effect_buf(haptic, &effect.u.hid, &haptic->effect[effect_id], + ordinal); + break; + default: + break; + } + + return 0; +} + +static void hid_haptic_destroy(struct ff_device *ff) +{ + struct hid_haptic_device *haptic = ff->private; + struct hid_device *hdev = haptic->hdev; + int r; + + if (hdev) + put_device(&hdev->dev); + + kfree(haptic->stop_effect.report_buf); + haptic->stop_effect.report_buf = NULL; + + if (haptic->effect) { + for (r = 0; r < ff->max_effects; r++) + kfree(haptic->effect[r].report_buf); + kfree(haptic->effect); + } + haptic->effect = NULL; + + destroy_workqueue(haptic->wq); + haptic->wq = NULL; + + kfree(haptic->duration_map); + haptic->duration_map = NULL; + + kfree(haptic->hid_usage_map); + haptic->hid_usage_map = NULL; + + module_put(THIS_MODULE); +} + +int hid_haptic_init(struct hid_device *hdev, + struct hid_haptic_device **haptic_ptr) +{ + struct hid_haptic_device *haptic = *haptic_ptr; + struct input_dev *dev = NULL; + struct hid_input *hidinput; + struct ff_device *ff; + int ret = 0, r; + struct ff_hid_effect stop_effect = { + .hid_usage = HID_HP_WAVEFORMSTOP & HID_USAGE, + }; + const char *prefix = "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 = hdev; + haptic->max_waveform_id = max(2u, haptic->max_waveform_id); + haptic->max_duration_id = max(2u, haptic->max_duration_id); + + haptic->hid_usage_map = kcalloc(haptic->max_waveform_id + 1, + sizeof(u16), GFP_KERNEL); + if (!haptic->hid_usage_map) { + ret = -ENOMEM; + goto exit; + } + haptic->duration_map = kcalloc(haptic->max_duration_id + 1, + sizeof(u32), GFP_KERNEL); + if (!haptic->duration_map) { + ret = -ENOMEM; + goto usage_map; + } + + if (haptic->max_waveform_id != 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] = + HID_HP_WAVEFORMNONE & HID_USAGE; + haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMSTOP] = + HID_HP_WAVEFORMSTOP & HID_USAGE; + + for (r = 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 == HID_DG_TOUCHPAD) { + dev = hidinput->input; + break; + } + } + + if (!dev) { + dev_err(&hdev->dev, "Failed to find the input device\n"); + ret = -ENODEV; + goto duration_map; + } + + haptic->input_dev = dev; + haptic->manual_trigger_report_len = + hid_report_len(haptic->manual_trigger_report); + mutex_init(&haptic->manual_trigger_mutex); + name = kmalloc(strlen(prefix) + strlen(hdev->name) + 2, GFP_KERNEL); + if (name) { + sprintf(name, "%s %s", prefix, hdev->name); + haptic->wq = create_singlethread_workqueue(name); + kfree(name); + } + if (!haptic->wq) { + ret = -ENOMEM; + goto duration_map; + } + haptic->effect = kcalloc(FF_MAX_EFFECTS, + sizeof(struct hid_haptic_effect), GFP_KERNEL); + if (!haptic->effect) { + ret = -ENOMEM; + goto output_queue; + } + for (r = 0; r < FF_MAX_EFFECTS; r++) { + haptic->effect[r].report_buf = + 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 = -ENOMEM; + goto buffer_free; + } + haptic->effect[r].input_dev = dev; + INIT_WORK(&haptic->effect[r].work, haptic_work_handler); + } + haptic->stop_effect.report_buf = + 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 = -ENOMEM; + goto buffer_free; + } + haptic->stop_effect.input_dev = 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 = dev->flush; + event = dev->event; + ret = input_ff_create(dev, FF_MAX_EFFECTS); + if (ret) { + dev_err(&hdev->dev, "Failed to create ff device.\n"); + goto stop_buffer_free; + } + + ff = dev->ff; + ff->private = haptic; + ff->upload = hid_haptic_upload_effect; + ff->playback = hid_haptic_playback; + ff->erase = hid_haptic_erase; + ff->destroy = 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 = NULL; + /* Restore dev flush and event */ + dev->flush = flush; + dev->event = event; + return ret; +stop_buffer_free: + kfree(haptic->stop_effect.report_buf); + haptic->stop_effect.report_buf = NULL; +buffer_free: + while (--r >= 0) + kfree(haptic->effect[r].report_buf); + kfree(haptic->effect); + haptic->effect = NULL; +output_queue: + destroy_workqueue(haptic->wq); + haptic->wq = NULL; +duration_map: + kfree(haptic->duration_map); + haptic->duration_map = NULL; +usage_map: + kfree(haptic->hid_usage_map); + haptic->hid_usage_map = 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 ea96b0fb540f2..67096cc8c2331 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -82,6 +82,7 @@ int hid_haptic_input_mapping(struct hid_device *hdev, unsigned long **bit, int *max); bool hid_haptic_input_configured(struct hid_device *hdev, struct hid_haptic_device *haptic); +int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr); #else static inline void hid_haptic_feature_mapping(struct hid_device *hdev, @@ -110,4 +111,9 @@ bool hid_haptic_input_configured(struct hid_device *hdev, { return 0; } +static inline +int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr) +{ + return 0; +} #endif From patchwork Fri Oct 7 18:29:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001410 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B1D12C43217 for ; Fri, 7 Oct 2022 18:30:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229675AbiJGSah (ORCPT ); Fri, 7 Oct 2022 14:30:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55558 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229871AbiJGSa2 (ORCPT ); Fri, 7 Oct 2022 14:30:28 -0400 Received: from mail-wr1-x430.google.com (mail-wr1-x430.google.com [IPv6:2a00:1450:4864:20::430]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 67262B0B1F for ; Fri, 7 Oct 2022 11:30:27 -0700 (PDT) Received: by mail-wr1-x430.google.com with SMTP id b7so8462618wrq.9 for ; Fri, 07 Oct 2022 11:30:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=t9IN2ULqB2l+f+6YAJyLJNYvDkMq2mv3Np5c5UD+cq8=; b=iqkgyBXsZBnZ6mvaawQO3t6YoY9ocxw7uDp+Ip9U7foeoaAVf3xFJswYkWkNnsU0Fo KYcs11gkYGwmM9P7rGjbddcXR9li3/GMarPBIeP23zoT1BK242z6RpJD+ogBIbXYsxle HXbXDiVbZ6Vsga0ZO/dkvsnx/iB7WFlBXVjlWRPA5VtbUdcAP4fLdPPxC1nzkAdhzem4 AX77sg3It076+TJL8VjWZzGBZ4kbtTQLqSKH+TqRTKHboWUi+o41/PShnnNVFvDmY8r3 oxWzSjSNoafmJFffvuNoiLZkO8+rczsmAA6Jsg4UUTCtufFlDXmpqTurTqr6KNFGNRxB Xrag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=t9IN2ULqB2l+f+6YAJyLJNYvDkMq2mv3Np5c5UD+cq8=; b=x3ZUyhmAezi+Go2fzkg/b959zwa2ILssG2MR0kIjO+ptj20zVaq9mb3ncw0hKt7xTf B/t2o9ZWa32PWPy1cUfiIUX7RSvoPpNwquiuG43+NYQenJ1MrYaOwLZ993zzRZNdJYBC xM+UHt6+8hkAbPzWHcEW1uDw3P1HYFGkMC+lfMeOb/wbfKoZvOOa6xSm3S9LFWmQ2OSx UViaNydGg0XMYyfSZn6RARL94fcn8SHTr/ASZbEd+TdnCT6onq31Dd8Ku13P30GXr67P tM6Ln6MtCaqrsm0BK9ThLRMh+8GdPAwyJ+dm7AuwONFDy6IuOjNwIuOE1776/cStzdCA dLwA== X-Gm-Message-State: ACrzQf2H7rHN5XleMuaJPBha3ihnEbgW5KsQyak/+EJDzcsv4eu2MFhn jGC+824iLxsvGeqGpp0MV3M9qk/x3IwKb0ED X-Google-Smtp-Source: AMsMyM7NrImtrWquMj7wiNt8bTSNQuyEZb2wmyF9aoOAE+PB9F0ZUWi8xhfzcWoMFAataautpA9lLA== X-Received: by 2002:a05:6000:61c:b0:22e:5e08:43e7 with SMTP id bn28-20020a056000061c00b0022e5e0843e7mr4225163wrb.176.1665167416164; Fri, 07 Oct 2022 11:30:16 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:15 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 06/17] Input: add shared effects Date: Fri, 7 Oct 2022 18:29:34 +0000 Message-Id: <20221007182945.1654046-7-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org If an effect is uploaded with file handle equal UINTPTR_MAX assume this effect should be shared and so may be modified using different file handles. Signed-off-by: Angela Czubak --- drivers/input/ff-core.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index fa8d1a4660142..1a9a5401acb55 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -34,6 +34,23 @@ static int check_effect_access(struct ff_device *ff, int effect_id, return 0; } +/* + * Check that the effect_id is a valid effect and whether the effect + * is shared + */ +static int check_effect_shared(struct ff_device *ff, int effect_id) +{ + if (effect_id < 0 || effect_id >= ff->max_effects || + !ff->effect_owners[effect_id]) + return -EINVAL; + + /* Shared effect */ + if (ff->effect_owners[effect_id] == (struct file *)UINTPTR_MAX) + return 0; + + return -EACCES; +} + /* * Checks whether 2 effects can be combined together */ @@ -139,8 +156,11 @@ int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, id = effect->id; ret = check_effect_access(ff, id, file); - if (ret) - goto out; + if (ret) { + ret = check_effect_shared(ff, id); + if (ret) + goto out; + } old = &ff->effects[id]; @@ -174,21 +194,29 @@ static int erase_effect(struct input_dev *dev, int effect_id, { struct ff_device *ff = dev->ff; int error; + bool shared = false; error = check_effect_access(ff, effect_id, file); - if (error) - return error; + if (error) { + error = check_effect_shared(ff, effect_id); + if (!error) + shared = true; + else + return error; + } spin_lock_irq(&dev->event_lock); ff->playback(dev, effect_id, 0); - ff->effect_owners[effect_id] = NULL; + if (!shared) + ff->effect_owners[effect_id] = NULL; spin_unlock_irq(&dev->event_lock); if (ff->erase) { error = ff->erase(dev, effect_id); if (error) { spin_lock_irq(&dev->event_lock); - ff->effect_owners[effect_id] = file; + if (!shared) + ff->effect_owners[effect_id] = file; spin_unlock_irq(&dev->event_lock); return error; From patchwork Fri Oct 7 18:29:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001398 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2C318C4332F for ; Fri, 7 Oct 2022 18:30:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229873AbiJGSa2 (ORCPT ); Fri, 7 Oct 2022 14:30:28 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55538 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229731AbiJGSaW (ORCPT ); Fri, 7 Oct 2022 14:30:22 -0400 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1809EC5113 for ; Fri, 7 Oct 2022 11:30:18 -0700 (PDT) Received: by mail-wr1-x435.google.com with SMTP id bk15so8429703wrb.13 for ; Fri, 07 Oct 2022 11:30:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EiRWz3/ju05cpZJVAmO9L3pe6FrhtoFaBzT/35Bs1Uk=; b=Ky9Sli+8xgtf1RpNmKLvZ2thfkDTKWiG2hgvtWJzv2jjeo+1do7gbuJF4K25EhSXsC E0n30BSVm+uuoXE3Ii4fSX3MwTkI/hB2gtTRbuYSC7QY8ho2r6fwJFZcRttXUg08GCeq nt56B0WxBSpoFApO18AaUJmqmwXe+ZdTG536qMilz+CdsBBsZIJjfu74JOD2hUHOSm2d KnZGSWUAfwMxObHY4gaficqSOfThCLceOAre2Nqgd5YhZ6q6yq3hEt7n2WphxLFeLjsN jkhWUG5hStHXrpQITCn3YPoxvKTxcFeoMjPOMO9y9g89Mq9HVuQ0fNXBrNKypMPXdKh7 VFfA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=EiRWz3/ju05cpZJVAmO9L3pe6FrhtoFaBzT/35Bs1Uk=; b=5X6g2P7TaghPyZYesNBgVijyh0WDe/6SdZtfD9P5Kqe49yXKO785bGn3x5z+n2LQL9 VXe9Cxx5tZLWLa0ltDzU83IBItG8TJJZ+fezJdKUkvrha4YBtbv9dqeRipxGbB/rabGg sbK90XWHvaHjbd5TfiYLiOMwLIBnDkdSjtWycg+sajrXvhC7qI/+fx3P+8/fYOQJ2dSi Xnx/8lmAWSCPpM11Ev7lClQ65HAoXKm9CpsLMZZ17wX9cfe92ydQQMsmKYcHna8CTPhP LDgSlsqRFaa8aCkR3iS7kdc3x/k7Ihe9QJgpVIic4/WsIu4yoTasX+zyTPTxv4+qqOQS 7QRg== X-Gm-Message-State: ACrzQf2vfsgY77L5xiHGW1LRnabEL93LCHU3qGYu39Zu0IPjnd5+atjZ gQMRzqBD9tB99KlkiQbuwn51Y+0ETNjNExcj X-Google-Smtp-Source: AMsMyM509+WcxOKTuCBbxavkvpfF/avs/9OydMugjuhYfWYuJBx2VeXmGlmNyJCagGJQ3Kpu4T36bg== X-Received: by 2002:a5d:5224:0:b0:22e:397:d4da with SMTP id i4-20020a5d5224000000b0022e0397d4damr4027315wra.364.1665167417024; Fri, 07 Oct 2022 11:30:17 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:16 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 07/17] HID: haptic: implement release and press effects Date: Fri, 7 Oct 2022 18:29:35 +0000 Message-Id: <20221007182945.1654046-8-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Upload shared haptic affects for release and press waveforms if a device exposes them and it is a forcepad Signed-off-by: Angela Czubak --- drivers/hid/hid-haptic.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 327106152d795..3301bf27dfdee 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -361,6 +361,7 @@ int hid_haptic_init(struct hid_device *hdev, 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); + struct ff_effect release_effect, press_effect; haptic->hdev = hdev; haptic->max_waveform_id = max(2u, haptic->max_waveform_id); @@ -477,8 +478,44 @@ int hid_haptic_init(struct hid_device *hdev, module_put(THIS_MODULE); goto input_free; } + + if (!haptic->is_forcepad) + goto exit; + + effect_set_default(&release_effect); + if (haptic->release_ordinal_orig) + release_effect.u.hid.hid_usage = HID_HP_WAVEFORMRELEASE & + HID_USAGE; + ret = input_ff_upload(dev, &release_effect, (struct file *)UINTPTR_MAX); + if (ret || release_effect.id != HID_HAPTIC_RELEASE_EFFECT_ID) { + if (!ret) { + ret = -EBUSY; + input_ff_erase(dev, release_effect.id, + (struct file *)UINTPTR_MAX); + } + dev_err(&hdev->dev, + "Failed to allocate id 0 for release effect.\n"); + goto input_free; + } + effect_set_default(&press_effect); + if (haptic->press_ordinal_orig) + press_effect.u.hid.hid_usage = HID_HP_WAVEFORMPRESS & HID_USAGE; + ret = input_ff_upload(dev, &press_effect, (struct file *)UINTPTR_MAX); + if (ret || press_effect.id != HID_HAPTIC_PRESS_EFFECT_ID) { + if (!ret) { + ret = -EBUSY; + input_ff_erase(dev, press_effect.id, + (struct file *)UINTPTR_MAX); + } + dev_err(&hdev->dev, + "Failed to allocate id 1 for press effect.\n"); + goto release_free; + } + return 0; +release_free: + input_ff_erase(dev, release_effect.id, (struct file *)UINTPTR_MAX); input_free: input_ff_destroy(dev); /* Do not let double free happen, input_ff_destroy will call From patchwork Fri Oct 7 18:29:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001400 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E79FBC43219 for ; Fri, 7 Oct 2022 18:30:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229555AbiJGSa3 (ORCPT ); Fri, 7 Oct 2022 14:30:29 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55416 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229739AbiJGSaW (ORCPT ); Fri, 7 Oct 2022 14:30:22 -0400 Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 69558C5132 for ; Fri, 7 Oct 2022 11:30:19 -0700 (PDT) Received: by mail-wm1-x329.google.com with SMTP id p26-20020a7bcc9a000000b003c384e59047so1087720wma.4 for ; Fri, 07 Oct 2022 11:30:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=PKC52XlIlH735cslPfUrYxygdtrY6mzDY7jHX6I0Dr8=; b=onCVtizQqS24clBBpDwECLJHkh3NX9WiWTUaqxR9e44Y4KCf0+kw4/1jkL4bnKXvtG Dw2tPKmSv1nLL2kNoaX7yHhHxAJM6pLzOYKY4xzn/vANNvphnzwdLOKv5704kMmwnnrn 9APyJAFBHIqLuV8y10ZAxNuthVLdJiTkrWClCdnnnFrV9L8oNTh6cy9k1+8utWL3Pa10 Y0WgORaOSgSWLm/vQzZ15s2IFD94/CYhYE0hADBpKY11LtF/WhUya3GlmYGvi/QypVOB E6wZQ8kEBxLgNi/CIc6bVO21tkajMtoU0Ua7xewkPoRwn0ZTsH99MvvP4Lx5Xcq8gG8W lAaQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PKC52XlIlH735cslPfUrYxygdtrY6mzDY7jHX6I0Dr8=; b=yAlM3+AZRDJ2xeRJBDnmm3l69X94phYtghVhsK8AvY3rss9ioSwij0iakfbfFdTytK 0vnZRtteh8fVLw0fkRbUY6uXlTH/9airKDda4UttUDpWLLkpLFQYYQLgufLU11kmb7A+ qu+e8Y8kSgzaR2jNocMl/1yrEonnG1gH4SLdKWJc6CQhIS/cO985+q8SucL0p2nPasWf wh6Ue+f6RD7AOSbuCL0XSXnKHCUQhOGy1o2k/mRMTMttpvbiQzPIzmYep/YGbo9c8W7O dlCOeHOAPJtLCjOilY8nW2pLRIX4/UXOWyAJnsr0X/G8ux577zH3obzM/kuYE231+yHJ c/9w== X-Gm-Message-State: ACrzQf0zwve4d5E3EAabjM5wbm5OIt1cIz3gAbWRQ0KQpciA5q/fRI8t I1ve9wg57ofgVPLSaCc2+eeuMwhfgHEizGgH X-Google-Smtp-Source: AMsMyM6yX4B+6p0TDKI5ppG81GR7iyhZuz+VKd5QGinEqvew26sBWh0+4cSV1dn2Jr7yKot7c6+++Q== X-Received: by 2002:a05:600c:348c:b0:3b4:85b6:e7c5 with SMTP id a12-20020a05600c348c00b003b485b6e7c5mr4268112wmq.45.1665167417739; Fri, 07 Oct 2022 11:30:17 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:17 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 08/17] HID: input: calculate resolution for pressure Date: Fri, 7 Oct 2022 18:29:36 +0000 Message-Id: <20221007182945.1654046-9-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org 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 --- 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 c60cee4bb6aa6..151823ad29166 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 *field, __u16 code) } break; + case ABS_PRESSURE: + case ABS_MT_PRESSURE: + if (field->unit == HID_UNIT_NEWTON) { + /* Convert to grams, 1 newton is 101.97 grams */ + prev = physical_extents; + physical_extents *= 10197; + if (physical_extents < prev) + return 0; + unit_exponent -= 2; + } else if (field->unit != HID_UNIT_GRAM) { + return 0; + } + break; default: return 0; } From patchwork Fri Oct 7 18:29:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001401 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6A1D4C4332F for ; Fri, 7 Oct 2022 18:30:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229668AbiJGSaa (ORCPT ); Fri, 7 Oct 2022 14:30:30 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229763AbiJGSaX (ORCPT ); Fri, 7 Oct 2022 14:30:23 -0400 Received: from mail-wm1-x32a.google.com (mail-wm1-x32a.google.com [IPv6:2a00:1450:4864:20::32a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D6FFBC58A6 for ; Fri, 7 Oct 2022 11:30:19 -0700 (PDT) Received: by mail-wm1-x32a.google.com with SMTP id e18so3373233wmq.3 for ; Fri, 07 Oct 2022 11:30:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7eNbqH85cekTZ3ChqflSp/zVaHBllGQnGWvg/J+jNkk=; b=mpASMn2puuT8Sx2p9YkYN79tYcSGUIsiRRrijozmi2cC1AI85uAqYiwxF7FCgDwz9k +Iqcpf6rREVklO5bBnPYSxQ6JNpd2SGf4sTnvtuXalYME2MvL4L+qCd6bsBDcnVC2tfO hzqVeeWR6DjSp67u5KeyIsovfOUJfpEHTfLB8nvB9AxxAFDdbeMryimbQXfvT2gyMl7T j8AsegFdCfmnClFoup5hsr8xQZCAT12c+DmN4QtBXyTw0Z1gMisvtXybCZCC4afdnkaU I9on0SP3LZBq1EHkMwLY0Z6gSOXgNMNvdh0uivgvfxk6Kio0ptsyX/z26yq7axmv+1yN CfPw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7eNbqH85cekTZ3ChqflSp/zVaHBllGQnGWvg/J+jNkk=; b=DqkrjRA/Hr+xPsaQ/kQdAcXuGwaUU/Jbh255PIVkb6UO9G8iDCwD20d5HGHMzTTGqf +4Vs68HgvuFoWLiaiKFSzRic7JS36qXqVw7/Y1V4mtTNpyt5mfib+UhDw/dChfRyk9bk nXqlb5N8vU0wCjhQjMv0d44DdWQZLDoT63ik9Vwyx6lp0h+q81kqgdEMBwouZ4XMhWdM aU34A8j/dlWw0r24l+ClER1SrTInrPEJX0cGL6LWpc+GwPfeLxpneDAyQPjx55NN18qD PkqC2LSGtffj7zz+1XuqeF66PvrP5hxNlx9EPBraUPazxhD1zvOLyGDzEZjunatBZpr5 utDg== X-Gm-Message-State: ACrzQf1ebNFpah9TLEcYJTKMuxuJQQxrGZo2WL5JrTAJI+q0MQwjxbaM gDEo59DBRx8777Yiu1hefDsOnnH0tpjTLOMB X-Google-Smtp-Source: AMsMyM6pKfYUOfiLh+GbP49XXsi33xeYf8ymcNb1/jlFuKt3g52CdvWBj+RBXlTmFw0fpM9qNokHkA== X-Received: by 2002:a05:600c:1d84:b0:3c2:1ba7:d7c8 with SMTP id p4-20020a05600c1d8400b003c21ba7d7c8mr6038922wms.57.1665167418384; Fri, 07 Oct 2022 11:30:18 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:17 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 09/17] HID: haptic: add functions handling events Date: Fri, 7 Oct 2022 18:29:37 +0000 Message-Id: <20221007182945.1654046-10-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Implement hid_haptic_handle_press_release() which generates haptic feedback as well as saves the pressed state of the haptic device. Function hid_haptic_handle_input() inserts BTN_LEFT and ABS_PRESSURE events if the device is in kernel mode. Add functions to increase and reset the state of the pressure detected by the device. Signed-off-by: Angela Czubak --- drivers/hid/hid-haptic.c | 73 +++++++++++++++++++++++++++++++++++++++- drivers/hid/hid-haptic.h | 18 ++++++++++ 2 files changed, 90 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 3301bf27dfdee..9b89a1f8a6316 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_is_forcepad(struct hid_haptic_device *haptic, struct hid_input *hi, struct hid_field *field) { - if (field->unit == HID_UNIT_GRAM || field->unit == HID_UNIT_NEWTON) + if (field->unit == HID_UNIT_GRAM || field->unit == HID_UNIT_NEWTON) { + haptic->force_logical_minimum = field->logical_minimum; + haptic->force_physical_minimum = field->physical_minimum; + haptic->force_resolution = input_abs_get_res(hi->input, + ABS_MT_PRESSURE); haptic->is_forcepad = true; + } return haptic->is_forcepad; } EXPORT_SYMBOL_GPL(hid_haptic_is_forcepad); @@ -346,6 +351,12 @@ static void hid_haptic_destroy(struct ff_device *ff) module_put(THIS_MODULE); } +static u32 convert_force_to_logical(struct hid_haptic_device *haptic, u32 value) +{ + return (value - haptic->force_physical_minimum) * + haptic->force_resolution + haptic->force_logical_minimum; +} + int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr) { @@ -479,9 +490,16 @@ int hid_haptic_init(struct hid_device *hdev, goto input_free; } + haptic->mode = HID_HAPTIC_MODE_DEVICE; + if (!haptic->is_forcepad) goto exit; + haptic->press_threshold = convert_force_to_logical(haptic, + HID_HAPTIC_PRESS_THRESH); + haptic->release_threshold = convert_force_to_logical(haptic, + HID_HAPTIC_RELEASE_THRESH); + effect_set_default(&release_effect); if (haptic->release_ordinal_orig) release_effect.u.hid.hid_usage = HID_HP_WAVEFORMRELEASE & @@ -547,3 +565,56 @@ int hid_haptic_init(struct hid_device *hdev, return ret; } EXPORT_SYMBOL_GPL(hid_haptic_init); + +void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) +{ + int prev_pressed_state = haptic->pressed_state; + struct input_dev *input = haptic->input_dev; + unsigned long flags; + + if (!haptic->is_forcepad) + return; + + if (haptic->pressure > haptic->press_threshold) + haptic->pressed_state = 1; + else if (haptic->pressure < haptic->release_threshold) + haptic->pressed_state = 0; + if (!prev_pressed_state && haptic->pressed_state && + haptic->mode == HID_HAPTIC_MODE_KERNEL) { + spin_lock_irqsave(&input->event_lock, flags); + input->ff->playback(input, PRESS_HID_EFFECT_ID, 1); + spin_unlock_irqrestore(&input->event_lock, flags); + } + if (prev_pressed_state && !haptic->pressed_state && + haptic->mode == HID_HAPTIC_MODE_KERNEL) { + spin_lock_irqsave(&input->event_lock, flags); + input->ff->playback(input, RELEASE_HID_EFFECT_ID, 1); + spin_unlock_irqrestore(&input->event_lock, flags); + } +} +EXPORT_SYMBOL_GPL(hid_haptic_handle_press_release); + +bool hid_haptic_handle_input(struct hid_haptic_device *haptic) +{ + if (haptic->is_forcepad && haptic->mode == HID_HAPTIC_MODE_KERNEL) { + input_event(haptic->input_dev, EV_KEY, BTN_LEFT, + haptic->pressed_state); + return true; + } + return false; +} +EXPORT_SYMBOL_GPL(hid_haptic_handle_input); + +void hid_haptic_pressure_reset(struct hid_haptic_device *haptic) +{ + haptic->pressure = 0; +} +EXPORT_SYMBOL_GPL(hid_haptic_pressure_reset); + +void hid_haptic_pressure_update(struct hid_haptic_device *haptic, + __s32 pressure) +{ + if (pressure > haptic->pressure) + haptic->pressure = pressure; +} +EXPORT_SYMBOL_GPL(hid_haptic_pressure_update); diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index 67096cc8c2331..c26093e3773d1 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -83,6 +83,11 @@ int hid_haptic_input_mapping(struct hid_device *hdev, bool hid_haptic_input_configured(struct hid_device *hdev, struct hid_haptic_device *haptic); int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr); +void hid_haptic_handle_press_release(struct hid_haptic_device *haptic); +bool hid_haptic_handle_input(struct hid_haptic_device *haptic); +void hid_haptic_pressure_reset(struct hid_haptic_device *haptic); +void hid_haptic_pressure_update(struct hid_haptic_device *haptic, + __s32 pressure); #else static inline void hid_haptic_feature_mapping(struct hid_device *hdev, @@ -116,4 +121,17 @@ int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_p { 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_update(struct hid_haptic_device *haptic, + __s32 pressure) +{} #endif From patchwork Fri Oct 7 18:29:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001402 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 26D96C433F5 for ; Fri, 7 Oct 2022 18:30:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229688AbiJGSab (ORCPT ); Fri, 7 Oct 2022 14:30:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55612 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229768AbiJGSaX (ORCPT ); Fri, 7 Oct 2022 14:30:23 -0400 Received: from mail-wr1-x436.google.com (mail-wr1-x436.google.com [IPv6:2a00:1450:4864:20::436]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3E1EC696C for ; Fri, 7 Oct 2022 11:30:20 -0700 (PDT) Received: by mail-wr1-x436.google.com with SMTP id n12so8445111wrp.10 for ; Fri, 07 Oct 2022 11:30:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Y3LRdC6fJaw14nph11Cyflovqm6lPGnWjctYaKLwwRU=; b=RzOhzh6/Db9dc2oADlwFzGvNByOciGKFWGFaLHsm5ZHrUfyQRY8tb0XK4LF9Q6ACIh nJfW3kFEwcqWpqMHZ6vZ7bBO+DuEJzNW+vTZeUqRFdP/I1RdFhosStn8teuoa8tg25xM oSKAX1mirTOeGUjVtEqxVhKu9oTxLhomx22FPZ164hJ0mMaleR8eoyuoniOe0ETXsSDH /W5aeHi03Wvl+6ssyuthzpZcYRhkXbvtKExU9EUDgKLs34mtXEtVLknkfp6GyxtE5ZiT wkGBEYP1Nmvrp+W4NHeZkwwxRa1pzImndUMGqIxocdJWltoeKzfdoKq25Tj53E3o6fOA RLXA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Y3LRdC6fJaw14nph11Cyflovqm6lPGnWjctYaKLwwRU=; b=yetlJ1KnWmClWhx9OH4/GwIvuttPW3YaLmk1qAM3ZxtwbVDNB5NboHpx/jm8Dg/B1A TwxovMxsAr0CX3G4I//ZfWXivRvMHjG95ITcfnmfzM2obUovmTMGQrPrDSxGpAAqrGUZ J9s0Db8ZE5Kz45ePhlPB+7iGfRo/31OhDmhfL8W5YPwwKQGmR2KaM6MC+JFR35sranQm ST54fEnBr6dYL5fXgxdTD+n2T3JteopZxKNkXpOhFvL5ucxpQhmYPClhyvhVFiAebHcg JwfRU6O1uNpRQCodsmz46Crq+8cuO7hjkoZm0y6zuO+TT7MvF0DiXLFZuUVdCDavxj6K Snyg== X-Gm-Message-State: ACrzQf3e9WMNWbfAJgwgv5eppv7lAPAx6weveUrsrPQIAMAjBDM+SeBJ MgY3PSZ/K0YKbgcv4wrUxrhAzkkY8aowrTBJ X-Google-Smtp-Source: AMsMyM6xrI5ufkrqFFH1hCFiZed4zf8etsrLW4Z1grlEKn7uK+k8wHPXNvaHj8iiCMu6lmY/SViJ5w== X-Received: by 2002:adf:edc3:0:b0:22c:dbe9:e3b6 with SMTP id v3-20020adfedc3000000b0022cdbe9e3b6mr4129163wro.282.1665167419173; Fri, 07 Oct 2022 11:30:19 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:18 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 10/17] Input: MT - add INPUT_MT_MAX_FORCE flags Date: Fri, 7 Oct 2022 18:29:38 +0000 Message-Id: <20221007182945.1654046-11-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Add a flag to generate ABS_PRESSURE as a maximum 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 --- drivers/input/input-mt.c | 16 ++++++++++++---- include/linux/input/mt.h | 1 + 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index 14b53dac1253b..bc710a8de3e0f 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 = dev->mt; struct input_mt_slot *oldest; int oldid, count, i; + int p, reported_p = 0; if (!mt) return; @@ -216,6 +217,15 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) oldest = ps; oldid = id; } + if (test_bit(ABS_MT_PRESSURE, dev->absbit)) { + p = input_mt_get_value(ps, ABS_MT_PRESSURE); + if (mt->flags & INPUT_MT_MAX_FORCE) { + if (p > reported_p) + reported_p = p; + } else if (oldid == id) { + reported_p = p; + } + } count++; } @@ -245,10 +255,8 @@ void input_mt_report_pointer_emulation(struct input_dev *dev, bool use_count) input_event(dev, EV_ABS, ABS_X, x); input_event(dev, EV_ABS, ABS_Y, y); - if (test_bit(ABS_MT_PRESSURE, dev->absbit)) { - int p = 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 3b8580bd33c14..b23216cf99230 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 manually */ +#define INPUT_MT_MAX_FORCE 0x0020 /* choose max force from slots pressure */ /** * struct input_mt_slot - represents the state of an input MT slot From patchwork Fri Oct 7 18:29:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001403 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C9D6FC43217 for ; Fri, 7 Oct 2022 18:30:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229689AbiJGSab (ORCPT ); Fri, 7 Oct 2022 14:30:31 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55638 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229798AbiJGSaY (ORCPT ); Fri, 7 Oct 2022 14:30:24 -0400 Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 78615C8210 for ; Fri, 7 Oct 2022 11:30:21 -0700 (PDT) Received: by mail-wm1-x32e.google.com with SMTP id e10-20020a05600c4e4a00b003b4eff4ab2cso5048235wmq.4 for ; Fri, 07 Oct 2022 11:30:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=uGxkm6XBvgDiNW7rLvat9h7MScXofNNR407zemwbG/c=; b=bgJkCRztb0Vpoz8P7F/umzlbkkLX4yTxGCMhJk0NIDrZ8ak6iYCp39SQ1PFqiurI4b P/4efhC4HiwvMWfzMb1eE7SQd49d5Tiv328N5u2qnp0FbqD6QeCeg7+dnMhyobv7UHdk 4/YBz9selqTjWAtxqBuoQrKZWNn2A6j0FLyciEjjskmyO2sxrhsbzfeEBuBOqNhF9TUH FYOQaXG4Y+5yV3xYQo7f+Y9U0Zjp6q7TGUITjn8APxyBK2xtkadQvkk1rvBNSM++OO5X hI2HsQd+WtxBI0wEt+bUPHPz0FCaS+nUnLEFcYuUrIYNQBgLX8UxB4oFEtnGV8lctqpk XB/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uGxkm6XBvgDiNW7rLvat9h7MScXofNNR407zemwbG/c=; b=xRz86CaQ8Zd4xVVqvOC/FqkktcPtlwu2vZcW1InaGBGBV6VjaKlxCp+lDK4NsXQkMs LsNgPhM54RbV8Zl87D6lFOzFSJSpyFkBoLOcnr3sdiSHqf11TBeR1oVTOcPUXTCir/wj grmeE/vnczSudyg844mEwCZf4y/kWjAiJasb3VdDlE3/bIxneFOOnmHgqNVgq1oWGoaZ wTtVUCjFhIuaFHwz8pDWjQWSBeJBXOwtPsL7qO4P+5bvTOSlxGHrSnApAT/zGqAUKXje px2Q00GvLYBmqY0/mnXprYF37lsdPtumg+jYjjPmVz8DVFPQbkGVLYF+rMRKqDGKzmQ0 rDiQ== X-Gm-Message-State: ACrzQf3ZyWlDPN0mQqVqvTDb7kK4XZxCpvj9/JSQnmz/JHjGJNClzudO kNz88pMTqJU9QfplBY6xJlclGBIgFpiWvn40 X-Google-Smtp-Source: AMsMyM4nMP3vbQZ/et8UIu7JC9PApvmYmi7VFb1n/xVzvf6lxSYDw8UpjNbP+dV9s7WqNH6GrWLL9g== X-Received: by 2002:a05:600c:3582:b0:3c2:7002:2cb0 with SMTP id p2-20020a05600c358200b003c270022cb0mr4219949wmq.170.1665167419873; Fri, 07 Oct 2022 11:30:19 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:19 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 11/17] HID: haptic: add hid_haptic_switch_mode Date: Fri, 7 Oct 2022 18:29:39 +0000 Message-Id: <20221007182945.1654046-12-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Function hid_haptic_switch_mode() can be used to turn off and on the autonomoums mode for the device. If the device is a forcepad andsupports press and release waveforms, let the kernel handle generation of haptic feedback instead of the device itself. Implement hid_haptic_resume() and hid_haptic_suspend() so that the autonomous mode gets switched off at resume and switched on at suspend. Signed-off-by: Angela Czubak --- drivers/hid/hid-haptic.c | 92 +++++++++++++++++++++++++++++++++++++--- drivers/hid/hid-haptic.h | 10 +++++ 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 9b89a1f8a6316..3d26bd5d15a4f 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -5,6 +5,7 @@ * Copyright (c) 2021 Angela Czubak */ +#include #include #include "hid-haptic.h" @@ -192,9 +193,60 @@ static void fill_effect_buf(struct hid_haptic_device *haptic, mutex_unlock(&haptic->manual_trigger_mutex); } +static void switch_mode(struct hid_device *hdev, struct hid_haptic_device *haptic, + int mode) +{ + struct hid_report *rep = haptic->auto_trigger_report; + struct hid_field *field; + s32 value; + int i, j; + + if (mode == HID_HAPTIC_MODE_KERNEL) + value = HID_HAPTIC_ORDINAL_WAVEFORMSTOP; + else + value = haptic->default_auto_trigger; + + mutex_lock(&haptic->auto_trigger_mutex); + for (i = 0; i < rep->maxfield; i++) { + field = rep->field[i]; + /* Ignore if report count is out of bounds. */ + if (field->report_count < 1) + continue; + + for (j = 0; j < field->maxusage; j++) { + if (field->usage[j].hid == HID_HP_AUTOTRIGGER) + field->value[j] = value; + } + } + + /* send the report */ + hid_hw_request(hdev, rep, HID_REQ_SET_REPORT); + mutex_unlock(&haptic->auto_trigger_mutex); + haptic->mode = mode; +} + +#ifdef CONFIG_PM +void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic) +{ + if (haptic->is_forcepad && haptic->press_ordinal_cur && + haptic->release_ordinal_cur) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_KERNEL); +} +EXPORT_SYMBOL_GPL(hid_haptic_resume); + +void hid_haptic_suspend(struct hid_device *hdev, struct hid_haptic_device *haptic) +{ + if (haptic->is_forcepad && haptic->press_ordinal_cur && + haptic->release_ordinal_cur) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE); +} +EXPORT_SYMBOL_GPL(hid_haptic_suspend); +#endif + static int hid_haptic_upload_effect(struct input_dev *dev, struct ff_effect *effect, struct ff_effect *old) { + struct hid_device *hdev = input_get_drvdata(dev); struct ff_device *ff = dev->ff; struct hid_haptic_device *haptic = ff->private; int i, ordinal = 0; @@ -220,6 +272,24 @@ 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); + /* Mode switching needed only for forcepads. */ + if (!haptic->is_forcepad) + return 0; + + if (effect->id == HID_HAPTIC_RELEASE_EFFECT_ID) { + if (haptic->press_ordinal_cur && + haptic->mode == HID_HAPTIC_MODE_DEVICE) { + switch_mode(hdev, haptic, HID_HAPTIC_MODE_KERNEL); + } + haptic->release_ordinal_cur = ordinal; + } else if (effect->id == HID_HAPTIC_PRESS_EFFECT_ID) { + if (haptic->release_ordinal_cur && + haptic->mode == HID_HAPTIC_MODE_DEVICE) { + switch_mode(hdev, haptic, HID_HAPTIC_MODE_KERNEL); + } + haptic->press_ordinal_cur = ordinal; + } + return 0; } @@ -285,6 +355,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 = dev->ff->private; + struct hid_device *hdev = input_get_drvdata(dev); struct ff_effect effect; int ordinal; @@ -295,21 +366,29 @@ static int hid_haptic_erase(struct input_dev *dev, int effect_id) switch (effect_id) { case HID_HAPTIC_RELEASE_EFFECT_ID: ordinal = haptic->release_ordinal_orig; - if (!ordinal) + haptic->release_ordinal_cur = ordinal; + if (!ordinal) { ordinal = HID_HAPTIC_ORDINAL_WAVEFORMNONE; - else + if (haptic->mode == HID_HAPTIC_MODE_KERNEL) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE); + } else { effect.u.hid.hid_usage = HID_HP_WAVEFORMRELEASE & HID_USAGE; + } fill_effect_buf(haptic, &effect.u.hid, &haptic->effect[effect_id], ordinal); break; case HID_HAPTIC_PRESS_EFFECT_ID: ordinal = haptic->press_ordinal_orig; - if (!ordinal) + haptic->press_ordinal_cur = ordinal; + if (!ordinal) { ordinal = HID_HAPTIC_ORDINAL_WAVEFORMNONE; - else + if (haptic->mode == HID_HAPTIC_MODE_KERNEL) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_DEVICE); + } else { effect.u.hid.hid_usage = HID_HP_WAVEFORMPRESS & HID_USAGE; + } fill_effect_buf(haptic, &effect.u.hid, &haptic->effect[effect_id], ordinal); break; @@ -401,6 +480,7 @@ int hid_haptic_init(struct hid_device *hdev, haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMSTOP] = HID_HP_WAVEFORMSTOP & HID_USAGE; + mutex_init(&haptic->auto_trigger_mutex); for (r = 0; r < haptic->auto_trigger_report->maxfield; r++) parse_auto_trigger_field(haptic, haptic->auto_trigger_report->field[r]); @@ -582,13 +662,13 @@ void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) if (!prev_pressed_state && haptic->pressed_state && haptic->mode == HID_HAPTIC_MODE_KERNEL) { spin_lock_irqsave(&input->event_lock, flags); - input->ff->playback(input, PRESS_HID_EFFECT_ID, 1); + input->ff->playback(input, HID_HAPTIC_PRESS_EFFECT_ID, 1); spin_unlock_irqrestore(&input->event_lock, flags); } if (prev_pressed_state && !haptic->pressed_state && haptic->mode == HID_HAPTIC_MODE_KERNEL) { spin_lock_irqsave(&input->event_lock, flags); - input->ff->playback(input, RELEASE_HID_EFFECT_ID, 1); + input->ff->playback(input, HID_HAPTIC_RELEASE_EFFECT_ID, 1); spin_unlock_irqrestore(&input->event_lock, flags); } } diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index c26093e3773d1..96757a4655ec7 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -82,6 +82,10 @@ int hid_haptic_input_mapping(struct hid_device *hdev, unsigned long **bit, int *max); bool hid_haptic_input_configured(struct hid_device *hdev, struct hid_haptic_device *haptic); +#ifdef CONFIG_PM +void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic); +void hid_haptic_suspend(struct hid_device *hdev, struct hid_haptic_device *haptic); +#endif int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr); void hid_haptic_handle_press_release(struct hid_haptic_device *haptic); bool hid_haptic_handle_input(struct hid_haptic_device *haptic); @@ -116,6 +120,12 @@ bool hid_haptic_input_configured(struct hid_device *hdev, { return 0; } +#ifdef CONFIG_PM +static inline +void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic) {} +static inline +void hid_haptic_suspend(struct hid_device *hdev, struct hid_haptic_device *haptic) {} +#endif static inline int hid_haptic_init(struct hid_device *hdev, struct hid_haptic_device **haptic_ptr) { From patchwork Fri Oct 7 18:29:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001404 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A3F94C433FE for ; Fri, 7 Oct 2022 18:30:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229623AbiJGSac (ORCPT ); Fri, 7 Oct 2022 14:30:32 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55488 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229708AbiJGSa0 (ORCPT ); Fri, 7 Oct 2022 14:30:26 -0400 Received: from mail-wr1-x431.google.com (mail-wr1-x431.google.com [IPv6:2a00:1450:4864:20::431]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2BF93C8227 for ; Fri, 7 Oct 2022 11:30:22 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id f11so8480001wrm.6 for ; Fri, 07 Oct 2022 11:30:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=D6rpZCk23DAd4uxYBcpQwglvD4SXC9N8TOJY5DIzZYw=; b=On1y+nVe0bhmiG2K1vH3+gr85TCesWhNbQzcW2J6Uo+j39eqClPfaUO42dYRvW7u0M j6JJzvxTzQwByX3aUDQS6MzF9xfrMnDk3uJU1vBAcdMO4rx4Fj9uivc0q+NuiyUlWTdy qRuVzRQgRB+IYrZvMZDntPcpgS7m3RxnMDfp3XU3OpeOdUECa5GDIx7jLMZ9L6h6HX8M KxvZVkh8Ask7Loo+yZ6VdoIUS/PXob4VJe0OrFAoFWQO0afnSVwlHzXj2HKeJLOA7VxB ciF4qskb0jlw6VvSy+tFdEUOxpTfR0+qdo/Rd6dP1P5dJGEun6nwRAGbabTKLVvYfuq7 H6/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=D6rpZCk23DAd4uxYBcpQwglvD4SXC9N8TOJY5DIzZYw=; b=m+FryXEE8CLI/D25ImjNap/gR1bKcfblOmZPFxzDgMkE7V8XJxbY6btdAYxQYpvtvc q5QwNHIfbmF/5IPuAESb5oGE+QvwNme1rsKQgA9Ffkrv9Qna31zkSmnJeo8/qJ2f7eKT M1+CnXE7DE0tZEU4pg0OgZTns7X2SedoRjQBvXyUT4LB/+eHrwWFtPLLm+SDbcGncMJf pEK5vGptmLKFI/c28xyli414+halGPUvT5Av4L7fPtx7kyJVMzPX32k1KBJExXuRcsbu hppQwB4ykqn7TLsKvjqzKimse9aCWDLnnp/skTjoyMiOPT0sr+DowgeffHPsnWlheY/V Q2zg== X-Gm-Message-State: ACrzQf0JlCq280tpL97g/6RD/MgpuScpfQbKuNjK2T54+Kvl3l0+AcE/ YSl1tk3XsTIhINUwVcxQGI2HPEuHhOJTBDq7 X-Google-Smtp-Source: AMsMyM4p9YAnutBTiE+/QxwN+TN1BSYh2UkmEofNXyzkcfELDNi7Xrg4/KyfgxDjgUdd1QgT999ESQ== X-Received: by 2002:adf:dd04:0:b0:22e:4671:f092 with SMTP id a4-20020adfdd04000000b0022e4671f092mr4106822wrm.604.1665167420689; Fri, 07 Oct 2022 11:30:20 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:20 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 12/17] HID: multitouch: add haptic multitouch support Date: Fri, 7 Oct 2022 18:29:40 +0000 Message-Id: <20221007182945.1654046-13-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org 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 --- drivers/hid/Kconfig | 11 +++++ drivers/hid/hid-multitouch.c | 78 +++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 1b47e5d0d1c07..1dee1fa4589ea 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -776,6 +776,17 @@ config HID_MULTITOUCH To compile this driver as a module, choose M here: the module will be called hid-multitouch. +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 and Pro Controller support" depends on HID diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 2e72922e36f56..c50425a4de62c 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -48,6 +48,8 @@ MODULE_LICENSE("GPL"); #include "hid-ids.h" +#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) @@ -159,11 +161,14 @@ 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 is_forcepad; /* is this device a forcepad? */ bool serial_maybe; /* need to check for serial protocol */ struct list_head applications; @@ -511,6 +516,8 @@ static void mt_feature_mapping(struct hid_device *hdev, mt_get_feature(hdev, field->report); break; } + + hid_haptic_feature_mapping(hdev, td->haptic, field, usage); } static void set_abs(struct input_dev *input, unsigned int code, @@ -842,6 +849,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_DG_TIPPRESSURE: set_abs(hi->input, ABS_MT_PRESSURE, field, cls->sn_pressure); + td->is_forcepad = + hid_haptic_is_forcepad(td->haptic, hi, field); MT_STORE_FIELD(p); return 1; case HID_DG_SCANTIME: @@ -955,8 +964,16 @@ static void mt_release_pending_palms(struct mt_device *td, static void mt_sync_frame(struct mt_device *td, struct mt_application *app, struct input_dev *input) { - if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) - input_event(input, EV_KEY, BTN_LEFT, app->left_button_state); + if (td->is_haptic_touchpad) + hid_haptic_handle_press_release(td->haptic); + + if (app->quirks & MT_QUIRK_WIN8_PTP_BUTTONS) { + if (!(td->is_haptic_touchpad && + hid_haptic_handle_input(td->haptic))) { + input_event(input, EV_KEY, BTN_LEFT, + app->left_button_state); + } + } input_mt_sync_frame(input); input_event(input, EV_MSC, MSC_TIMESTAMP, app->timestamp); @@ -966,6 +983,8 @@ static void mt_sync_frame(struct mt_device *td, struct mt_application *app, app->num_received = 0; app->left_button_state = 0; + if (td->is_haptic_touchpad) + hid_haptic_pressure_reset(td->haptic); if (test_bit(MT_IO_FLAGS_ACTIVE_SLOTS, &td->mt_io_flags)) set_bit(MT_IO_FLAGS_PENDING_SLOTS, &td->mt_io_flags); @@ -1115,6 +1134,9 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input, minor = minor >> 1; } + if (td->is_haptic_touchpad) + hid_haptic_pressure_update(td->haptic, *slot->p); + input_event(input, EV_ABS, ABS_MT_POSITION_X, *slot->x); input_event(input, EV_ABS, ABS_MT_POSITION_Y, *slot->y); input_event(input, EV_ABS, ABS_MT_TOOL_X, *slot->cx); @@ -1289,6 +1311,10 @@ static int mt_touch_input_configured(struct hid_device *hdev, if (cls->is_indirect) app->mt_flags |= INPUT_MT_POINTER; + /* Get rid of and use default behaviour? */ + if (td->is_haptic_touchpad) + app->mt_flags |= INPUT_MT_MAX_FORCE; + if (app->quirks & MT_QUIRK_NOT_SEEN_MEANS_UP) app->mt_flags |= INPUT_MT_DROP_UNUSED; @@ -1324,6 +1350,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct mt_device *td = hid_get_drvdata(hdev); struct mt_application *application; struct mt_report_data *rdata; + int ret; rdata = mt_find_report_data(td, field->report); if (!rdata) { @@ -1386,6 +1413,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, if (field->physical == HID_DG_STYLUS) hi->application = HID_DG_STYLUS; + ret = hid_haptic_input_mapping(hdev, td->haptic, hi, field, usage, bit, + max); + if (ret != 0) + return ret; + /* let hid-core decide for the others */ return 0; } @@ -1579,6 +1611,17 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi) struct hid_report *report; int ret; + /* check if hi application is touchpad? */ + if (hi->application == HID_DG_TOUCHPAD) { + if (td->is_forcepad && (td->mtclass.name == MT_CLS_WIN_8 || + td->mtclass.name == MT_CLS_WIN_8_FORCE_MULTI_INPUT)) { + if (hid_haptic_input_configured(hdev, td->haptic)) + td->is_haptic_touchpad = true; + } else { + td->is_haptic_touchpad = false; + } + } + list_for_each_entry(report, &hi->reports, hidinput_list) { rdata = mt_find_report_data(td, report); if (!rdata) { @@ -1724,6 +1767,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) dev_err(&hdev->dev, "cannot allocate multitouch data\n"); return -ENOMEM; } + td->haptic = kzalloc(sizeof(*(td->haptic)), GFP_KERNEL); + if (!td->haptic) + return -ENOMEM; td->hdev = hdev; td->mtclass = *mtclass; td->inputmode_value = MT_INPUTMODE_TOUCHSCREEN; @@ -1775,6 +1821,17 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + if (td->is_haptic_touchpad) { + if (hid_haptic_init(hdev, &td->haptic)) { + dev_warn(&hdev->dev, "Cannot allocate haptic for %s\n", + hdev->name); + td->is_haptic_touchpad = false; + kfree(td->haptic); + } + } else { + kfree(td->haptic); + } + return 0; } @@ -1782,6 +1839,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) static int mt_suspend(struct hid_device *hdev, pm_message_t state) { struct mt_device *td = hid_get_drvdata(hdev); + struct hid_haptic_device *haptic = td->haptic; /* High latency is desirable for power savings during S3/S0ix */ if ((td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP) || @@ -1790,18 +1848,31 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state) else mt_set_modes(hdev, HID_LATENCY_HIGH, true, true); + if (td->is_haptic_touchpad) + hid_haptic_suspend(hdev, haptic); + return 0; } static int mt_reset_resume(struct hid_device *hdev) { + struct mt_device *td = hid_get_drvdata(hdev); + struct hid_haptic_device *haptic = td->haptic; + mt_release_contacts(hdev); mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + + if (td->is_haptic_touchpad) + hid_haptic_resume(hdev, haptic); + return 0; } static int mt_resume(struct hid_device *hdev) { + struct mt_device *td = hid_get_drvdata(hdev); + struct hid_haptic_device *haptic = td->haptic; + /* Some Elan legacy devices require SET_IDLE to be set on resume. * It should be safe to send it to other devices too. * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */ @@ -1810,6 +1881,9 @@ static int mt_resume(struct hid_device *hdev) mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + if (td->is_haptic_touchpad) + hid_haptic_resume(hdev, haptic); + return 0; } #endif From patchwork Fri Oct 7 18:29:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001405 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 763A2C4332F for ; Fri, 7 Oct 2022 18:30:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229703AbiJGSad (ORCPT ); Fri, 7 Oct 2022 14:30:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229682AbiJGSa0 (ORCPT ); Fri, 7 Oct 2022 14:30:26 -0400 Received: from mail-wm1-x333.google.com (mail-wm1-x333.google.com [IPv6:2a00:1450:4864:20::333]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A621CAE69 for ; Fri, 7 Oct 2022 11:30:22 -0700 (PDT) Received: by mail-wm1-x333.google.com with SMTP id n40-20020a05600c3ba800b003b49aefc35fso3054713wms.5 for ; Fri, 07 Oct 2022 11:30:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=35lu5QN2zWAPxQjzdgnWOj0Wl1hHDV3zTu2YrzXNYfw=; b=D5P7RuT3imORZ/p/OwbgUpaMu8ucdmni72W8l5mDMyJYyYJxiE1zdxK+mAcBUpnyVE QqkPrEr/nEHN3AZDCOXU7JuCg26neAtfOtB80icljFmMKyYWtu+ea8OqNWdWNlyfoQp3 6SOAXxObG3/fPdiV8BDea01OlTZASHSd0RJgigTMy0vIBEc1DWbxW6xLmrgxD5rsexZG K/Dq9ug0iVmhayIo6K4/d+yrZ5hfRZd03Y527N+VGUCH1qYEV6gT1QYsvBZm0bjGQfIG 7cHOJDL1uaSnTYx0nJ8VoSqaN36EF33JZGt/ffgJNP4BVsWo6HA/I5LXvXLb1cTPsUAk Ur1w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=35lu5QN2zWAPxQjzdgnWOj0Wl1hHDV3zTu2YrzXNYfw=; b=Uac5dnDch9QR6xP+LFS+SMlGPTXxYJnkmk91KaQY3kSQ9vKEGuA4m4aDEMUQlR+nRj JY2RA4tg3zTHJ9K9jsBqfHuOHWkslrx8tcINvb88yj0Po1e10y+AmiBjl8JNIEc6yBO3 kWdAnvp9vC1daZNuPJAP3OuiNN24qWN2N6EWo3kNup77Jixm5DH/ohIC34SJKVew71O3 rxnvDaLAsTFHhJLQ0eSzu4ki+HHFNmV/HFL5trVdz6fNpd7GA/z2ODhMG3xvw9AkGWra KyInUWWNsFeCltOwoPX2z4EEgiAab7eG+jyxqcFfjKcgLhHP9PCSI7qsn+49uAsYtHd4 OMyw== X-Gm-Message-State: ACrzQf05mwozNr26H73qayaWF/6KrgvHGJ2S+ZxfyowW2V8mVI4lXVdZ WO9qnK59qAi/RFo9GDUSLKkz5eApQf1xbnX6 X-Google-Smtp-Source: AMsMyM7QqZhEfs/RUcCcVdJoHOp5BkSwi2P0A8Q2QpeXl+2hBa8P3QFyj9Rk3w2iKkTSs5MgDCEytA== X-Received: by 2002:a05:600c:19d2:b0:3b4:a4cb:2416 with SMTP id u18-20020a05600c19d200b003b4a4cb2416mr4294246wmq.6.1665167421470; Fri, 07 Oct 2022 11:30:21 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:20 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 13/17] Input: introduce EVIOCFF(TAKE|RELEASE)CONTROL Date: Fri, 7 Oct 2022 18:29:41 +0000 Message-Id: <20221007182945.1654046-14-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Add new ioctls which can be used for simple haptic force feedback effects. Once the control is taken over the effect the kernel does not generate it on its own (EVIOCFFTAKECONTROL). To revert this action use EVIOCFFRELEASECONTROL. Signed-off-by: Angela Czubak --- drivers/input/evdev.c | 6 +++ drivers/input/ff-core.c | 89 +++++++++++++++++++++++++++++++++++++- include/linux/input.h | 5 +++ include/uapi/linux/input.h | 4 ++ 4 files changed, 103 insertions(+), 1 deletion(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 95f90699d2b17..6d25eb19e28ec 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -1076,6 +1076,12 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, case EVIOCRMFF: return input_ff_erase(dev, (int)(unsigned long) p, file); + case EVIOCFFTAKECONTROL: + return input_ff_take_control(dev, (int)(unsigned long) p, file); + + case EVIOCFFRELEASECONTROL: + return input_ff_release_control(dev, (int)(unsigned long) p, file); + case EVIOCGEFFECTS: i = test_bit(EV_FF, dev->evbit) ? dev->ff->max_effects : 0; diff --git a/drivers/input/ff-core.c b/drivers/input/ff-core.c index 1a9a5401acb55..d6b76a479fc21 100644 --- a/drivers/input/ff-core.c +++ b/drivers/input/ff-core.c @@ -252,6 +252,91 @@ int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file) } EXPORT_SYMBOL_GPL(input_ff_erase); +/* + * Take control over the effect if the requester is also the effect owner. + * The mutex should already be locked before calling this function. + */ +static int control_effect(struct input_dev *dev, int effect_id, + struct file *file, int take) +{ + struct ff_device *ff = dev->ff; + int error; + + error = check_effect_access(ff, effect_id, file); + if (error) { + error = check_effect_shared(ff, effect_id); + if (error) + return error; + } + + if (ff->change_control) { + error = ff->change_control(dev, effect_id, file, take); + if (error) + return error; + } + + return 0; +} +/** + * input_ff_take_control - take control over a force-feedback effect from kernel + * @dev: input device to take control over effect from + * @effect_id: id of the effect to take control over + * @file: purported owner of the request + * + * This function switches user-controlled mode on for the given force-feedback + * effect. The user-mode will persist unitl the last caller releases control. + * The effect will only be taken control of if it was uploaded through the same + * file handle that is requesting taking control or for simple haptic effects + * 0 and 1. + * Valid only for simple haptic effects (ff_hid_effect). + */ +int input_ff_take_control(struct input_dev *dev, int effect_id, + struct file *file) +{ + struct ff_device *ff = dev->ff; + int ret; + + if (!test_bit(EV_FF, dev->evbit)) + return -EINVAL; + + mutex_lock(&ff->mutex); + ret = control_effect(dev, effect_id, file, 1); + mutex_unlock(&ff->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(input_ff_take_control); + +/** + * input_ff_release_control - release control over a force-feedback effect + * @dev: input device to release control over effect to + * @effect_id: id of the effect to release control + * @file: purported owner of the request + * + * This function switches user-controlled mode off for the given force-feedback + * effect. The user-mode will persist unitl the last caller releases control. + * The control will be released of if it was uploaded through the same + * file handle that is requesting taking control or for simple haptic effects + * 0 and 1. + * Valid only for simple haptic effects (ff_hid_effect). + */ +int input_ff_release_control(struct input_dev *dev, int effect_id, + struct file *file) +{ + struct ff_device *ff = dev->ff; + int ret; + + if (!test_bit(EV_FF, dev->evbit)) + return -EINVAL; + + mutex_lock(&ff->mutex); + ret = control_effect(dev, effect_id, file, 0); + mutex_unlock(&ff->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(input_ff_release_control); + /* * input_ff_flush - erase all effects owned by a file handle * @dev: input device to erase effect from @@ -270,8 +355,10 @@ int input_ff_flush(struct input_dev *dev, struct file *file) mutex_lock(&ff->mutex); - for (i = 0; i < ff->max_effects; i++) + for (i = 0; i < ff->max_effects; i++) { + control_effect(dev, i, file, 0); erase_effect(dev, i, file); + } mutex_unlock(&ff->mutex); diff --git a/include/linux/input.h b/include/linux/input.h index 49790c1bd2c43..39091730c2fca 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -521,6 +521,7 @@ extern struct class input_class; * @upload: Called to upload an new effect into device * @erase: Called to erase an effect from device * @playback: Called to request device to start playing specified effect + * @change_control: Called to change control over specified effect * @set_gain: Called to set specified gain * @set_autocenter: Called to auto-center device * @destroy: called by input core when parent input device is being @@ -549,6 +550,8 @@ struct ff_device { int (*erase)(struct input_dev *dev, int effect_id); int (*playback)(struct input_dev *dev, int effect_id, int value); + int (*change_control)(struct input_dev *dev, int effect_id, + struct file *file, int take); void (*set_gain)(struct input_dev *dev, u16 gain); void (*set_autocenter)(struct input_dev *dev, u16 magnitude); @@ -572,6 +575,8 @@ int input_ff_event(struct input_dev *dev, unsigned int type, unsigned int code, int input_ff_upload(struct input_dev *dev, struct ff_effect *effect, struct file *file); int input_ff_erase(struct input_dev *dev, int effect_id, struct file *file); +int input_ff_take_control(struct input_dev *dev, int effect_id, struct file *file); +int input_ff_release_control(struct input_dev *dev, int effect_id, struct file *file); int input_ff_flush(struct input_dev *dev, struct file *file); int input_ff_create_memless(struct input_dev *dev, void *data, diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index 3ea7c826c6fb2..a332e7fb2686f 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -181,6 +181,10 @@ struct input_mask { #define EVIOCSFF _IOW('E', 0x80, struct ff_effect) /* send a force effect to a force feedback device */ #define EVIOCRMFF _IOW('E', 0x81, int) /* Erase a force effect */ +/* Take control over a force effect */ +#define EVIOCFFTAKECONTROL _IOW('E', 0x82, int) +/* Release control over a force effect */ +#define EVIOCFFRELEASECONTROL _IOW('E', 0x83, int) #define EVIOCGEFFECTS _IOR('E', 0x84, int) /* Report number of effects playable at the same time */ #define EVIOCGRAB _IOW('E', 0x90, int) /* Grab/Release device */ From patchwork Fri Oct 7 18:29:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001407 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5EBD0C43217 for ; Fri, 7 Oct 2022 18:30:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229637AbiJGSae (ORCPT ); Fri, 7 Oct 2022 14:30:34 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55742 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229853AbiJGSa0 (ORCPT ); Fri, 7 Oct 2022 14:30:26 -0400 Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A4547A3F77 for ; Fri, 7 Oct 2022 11:30:23 -0700 (PDT) Received: by mail-wm1-x32f.google.com with SMTP id bi26-20020a05600c3d9a00b003c1e11f54d2so1823834wmb.2 for ; Fri, 07 Oct 2022 11:30:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=yN/8SV8HwDu2Kf1AyTyMFHAwI3gsRsKJUfLOfyh00Qw=; b=iEDP6eGaklG7u2cDM9KCLTqADgUCNBwuEVTjWtmdkcBwzqpbKuzCCkCN+UufWfB+Vy 0oS72mlLqRT4Ovhib2pG1nhgSvSbHCchqXZKWoZSPwYjdPetaoI8SV6jLAPMhVMXQZAv QKCXp9GiZy/N8U46QTH46jIADprMG9JqSWkMd6lQtVJzA0REeiRj/0tJF6RMEhHkJfRo xCyLYeD66jwa9f19u3Z7rMPkXkyd5nW/xT+cPctElQg6S/uRbQQR/7U6E/TkRmxaHNM8 v6NfWmUQJ+Xc+gY8x3MM9hSq8wkGeKIkyCotGjf4gt75Li5e8uONczPIbFW9YV3KQOWf aEew== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=yN/8SV8HwDu2Kf1AyTyMFHAwI3gsRsKJUfLOfyh00Qw=; b=DdsOIeF2ptgfBH+9Q8e2l7c7kfeKuOBcaEmjVbdUaCTaJvOddINzSZFoj6jnrFCspl 94VMENTEbQJLBJOct3izcnv9/PAHRV063M2fcLSAJl5rC4VOOZtyFnjRV6hn0VdLVdQT R2vgZzXO/A9CvZ3/czZWTyeQuOelC4NqA6JNRNOJdY9pGHsho40iobsaIH5Fks/WyoDS OfrgNv1rdc5Ud23a/83kebCATzj47ymV6azyI776PmPJ9+t4+/oV5u3GurgspopT9ww9 E1fx2fLh2XXDRpkQgdxKDqlZyj60qnfdmextghPQMtBRPjjlb8sB8DVpwtsCJLEYqjfX woVA== X-Gm-Message-State: ACrzQf1HsZy6MmYgEHoiJdAS8RCKmWrx2VMnsdWR2RG8/52wER/+KArl mBGcRV3Cc8/tgvL8FAXFAOZct0Gquq4O4d6s X-Google-Smtp-Source: AMsMyM5G+fpf3KQrhW4cx9M9EwjZdvjAcxbyXxkTnz/vhddqqn6A77OAJBfZqRmrCJGSuJCXxYqgDw== X-Received: by 2002:a1c:7912:0:b0:3c0:a1a7:e622 with SMTP id l18-20020a1c7912000000b003c0a1a7e622mr8238601wme.138.1665167422185; Fri, 07 Oct 2022 11:30:22 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:21 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 14/17] HID: haptic: add hid_haptic_change_control Date: Fri, 7 Oct 2022 18:29:42 +0000 Message-Id: <20221007182945.1654046-15-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Implement change_control callbacks for simple haptic device. If anybody has requested control over an effect, do not generate it in kernel. Signed-off-by: Angela Czubak --- drivers/hid/hid-haptic.c | 50 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 3d26bd5d15a4f..4b3ad5168fbb4 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -6,6 +6,7 @@ */ #include +#include #include #include "hid-haptic.h" @@ -342,6 +343,46 @@ static int hid_haptic_playback(struct input_dev *dev, int effect_id, int value) return 0; } +static int hid_haptic_change_control(struct input_dev *dev, int effect_id, + struct file *file, int take) +{ + struct hid_haptic_device *haptic = dev->ff->private; + struct hid_haptic_effect_node *effect_node; + struct hid_haptic_effect *effect; + bool found = false; + int ret = 0; + + effect = &haptic->effect[effect_id]; + mutex_lock(&effect->control_mutex); + list_for_each_entry(effect_node, &effect->control, node) { + if (effect_node->file == file) { + found = true; + break; + } + } + if (take) { + if (!found) { + effect_node = kvzalloc(sizeof(struct hid_haptic_effect), + GFP_KERNEL); + if (!effect_node) { + ret = -ENOMEM; + goto exit; + } + effect_node->file = file; + } + list_add(&effect_node->node, &effect->control); + } else { + if (found) { + list_del(&effect_node->node); + kvfree(effect_node); + } + } +exit: + mutex_unlock(&effect->control_mutex); + + return ret; +} + static void effect_set_default(struct ff_effect *effect) { effect->type = FF_HID; @@ -529,6 +570,8 @@ int hid_haptic_init(struct hid_device *hdev, } haptic->effect[r].input_dev = dev; INIT_WORK(&haptic->effect[r].work, haptic_work_handler); + INIT_LIST_HEAD(&haptic->effect[r].control); + mutex_init(&haptic->effect[r].control_mutex); } haptic->stop_effect.report_buf = hid_alloc_report_buf(haptic->manual_trigger_report, @@ -558,6 +601,7 @@ int hid_haptic_init(struct hid_device *hdev, ff->private = haptic; ff->upload = hid_haptic_upload_effect; ff->playback = hid_haptic_playback; + ff->change_control = hid_haptic_change_control; ff->erase = hid_haptic_erase; ff->destroy = hid_haptic_destroy; if (!try_module_get(THIS_MODULE)) { @@ -660,13 +704,15 @@ void hid_haptic_handle_press_release(struct hid_haptic_device *haptic) else if (haptic->pressure < haptic->release_threshold) haptic->pressed_state = 0; if (!prev_pressed_state && haptic->pressed_state && - haptic->mode == HID_HAPTIC_MODE_KERNEL) { + haptic->mode == HID_HAPTIC_MODE_KERNEL && + list_empty(&haptic->effect[HID_HAPTIC_PRESS_EFFECT_ID].control)) { spin_lock_irqsave(&input->event_lock, flags); input->ff->playback(input, HID_HAPTIC_PRESS_EFFECT_ID, 1); spin_unlock_irqrestore(&input->event_lock, flags); } if (prev_pressed_state && !haptic->pressed_state && - haptic->mode == HID_HAPTIC_MODE_KERNEL) { + haptic->mode == HID_HAPTIC_MODE_KERNEL && + list_empty(&haptic->effect[HID_HAPTIC_RELEASE_EFFECT_ID].control)) { spin_lock_irqsave(&input->event_lock, flags); input->ff->playback(input, HID_HAPTIC_RELEASE_EFFECT_ID, 1); spin_unlock_irqrestore(&input->event_lock, flags); From patchwork Fri Oct 7 18:29:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001406 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BEA87C433F5 for ; Fri, 7 Oct 2022 18:30:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229682AbiJGSad (ORCPT ); Fri, 7 Oct 2022 14:30:33 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229834AbiJGSa0 (ORCPT ); Fri, 7 Oct 2022 14:30:26 -0400 Received: from mail-wr1-x429.google.com (mail-wr1-x429.google.com [IPv6:2a00:1450:4864:20::429]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 682C2CAE71 for ; Fri, 7 Oct 2022 11:30:23 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id a10so8444680wrm.12 for ; Fri, 07 Oct 2022 11:30:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JNN28EYVyipGF0nBWtHYc0eS8Dpeqf76Q08EI6PsIYU=; b=qxAr0agrBtuhcTLuSxwaDckdMbmBM1fxleKKtepgIMmgz97EO5RtBq16Aloynl2ov6 8XBY6hmYNKFgOWfdKY0qUBW0tTrDO4xK47f6XOpdQHCyT5foyc2aMV1tC4fScK7Ne8nW +gy3kQw7XdyKGuuzBaB6iHyYjZ7thDm/A1ztZo/4vTvRfoXH8kGy9Hr2LnxzT6KuAKeF 4j2Nz/N7rBxB8B2/bhVviWfXt2MJNlveZcMArUmp9DTHQ6Mbh2NpuRwfK4vx8CGfOa8l toKpys5WqMglynMrsgyC7pQH6c31fZKHVv+RR1Bgh4VePtF6sruOak9OSOfp2vYQ9tNE /BAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JNN28EYVyipGF0nBWtHYc0eS8Dpeqf76Q08EI6PsIYU=; b=tMvYdJ29YP0+J9bbGoNfa/dac4zW74dwCmHTlVfbLOrGtkwR6Ow9LNVpNHcFEvo8jI lyS+yQY0C1PmmbaiftIJo8Xqqfqej7PTptnMKakOTD6QCi+uNJz6h9Y0EQPewG8oYcFn tJzQvlpUsrSbdXuy6hmBRLoUHMiLDxOQ1Cm1I/TtrOYyJcvx9yDQbs3z7m3MMRRNROUA 8r31dT6jSIao7M4ubBWZHim3VSQcM4VyexB2XQdn8zHtBXfwxWlu8x3H0zU/HZoRcqMo dvFV8a4SsFsvnkuBfpOtmpZl7SwrVUim61ZW8PLQilBF2iPyME8hoCOCnLYIGFtQZ6uc RRZQ== X-Gm-Message-State: ACrzQf0j1VVVhka1qbAGUAEU3gUNP1zNVvR7sljaoff6fgbuXVbd0iVQ U3jCiUHc5he7EF4RYnXjOSy1Q0MLqy9MZsDP X-Google-Smtp-Source: AMsMyM5OznlW71Wh2uVbuhX3QbKu7s447vTLifwqhN25O96FWDC//RTi9aKWj742ZrNNiosUpskkIA== X-Received: by 2002:adf:dc41:0:b0:22e:3dac:b066 with SMTP id m1-20020adfdc41000000b0022e3dacb066mr4168953wrj.344.1665167422781; Fri, 07 Oct 2022 11:30:22 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:22 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 15/17] HID: add HID device reset callback Date: Fri, 7 Oct 2022 18:29:43 +0000 Message-Id: <20221007182945.1654046-16-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org HID-over-I2C devices might reset on their own. Any device configuration applied before the reset might be brought back to defaults so we need to reconfigure to make sure the driver state is consistent. Add a reset callback to the hid driver structure. Issue it if the driver implements it and the device reset gets observed. Signed-off-by: Angela Czubak --- drivers/hid/i2c-hid/i2c-hid-core.c | 21 +++++++++++++++++++++ include/linux/hid.h | 2 ++ 2 files changed, 23 insertions(+) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 95cefae47adfe..f8a54eda2ff98 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -116,6 +116,7 @@ struct i2c_hid { struct mutex reset_lock; struct i2chid_ops *ops; + struct work_struct reset_work; }; static const struct i2c_hid_quirks { @@ -504,6 +505,19 @@ static int i2c_hid_hwreset(struct i2c_hid *ihid) return ret; } +static void i2c_hid_reset_worker(struct work_struct *work) +{ + struct i2c_hid *ihid = container_of(work, struct i2c_hid, reset_work); + struct hid_device *hid = ihid->hid; + + down(&hid->driver_input_lock); + + if (hid->driver && hid->driver->reset) + hid->driver->reset(hid); + + up(&hid->driver_input_lock); +} + static void i2c_hid_get_input(struct i2c_hid *ihid) { u16 size = le16_to_cpu(ihid->hdesc.wMaxInputLength); @@ -529,6 +543,8 @@ static void i2c_hid_get_input(struct i2c_hid *ihid) /* host or device initiated RESET completed */ if (test_and_clear_bit(I2C_HID_RESET_PENDING, &ihid->flags)) wake_up(&ihid->wait); + else + schedule_work(&ihid->reset_work); return; } @@ -821,6 +837,10 @@ static int i2c_hid_start(struct hid_device *hid) static void i2c_hid_stop(struct hid_device *hid) { + struct i2c_client *client = hid->driver_data; + struct i2c_hid *ihid = i2c_get_clientdata(client); + + cancel_work_sync(&ihid->reset_work); hid->claimed = 0; } @@ -988,6 +1008,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, ihid->wHIDDescRegister = cpu_to_le16(hid_descriptor_address); init_waitqueue_head(&ihid->wait); + INIT_WORK(&ihid->reset_work, i2c_hid_reset_worker); mutex_init(&ihid->reset_lock); /* we need to allocate the command buffer without knowing the maximum diff --git a/include/linux/hid.h b/include/linux/hid.h index 3f5899c628211..9db9b7133f1a1 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -784,6 +784,7 @@ struct hid_usage_id { * @suspend: invoked on suspend (NULL means nop) * @resume: invoked on resume if device was not reset (NULL means nop) * @reset_resume: invoked on resume if device was reset (NULL means nop) + * @reset: invoked if device was reset (NULL means nop) * * probe should return -errno on error, or 0 on success. During probe, * input will not be passed to raw_event unless hid_device_io_start is @@ -840,6 +841,7 @@ struct hid_driver { int (*resume)(struct hid_device *hdev); int (*reset_resume)(struct hid_device *hdev); #endif + int (*reset)(struct hid_device *hdev); /* private: */ struct device_driver driver; }; From patchwork Fri Oct 7 18:29:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001408 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B3328C4332F for ; Fri, 7 Oct 2022 18:30:37 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229708AbiJGSag (ORCPT ); Fri, 7 Oct 2022 14:30:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55376 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229710AbiJGSa1 (ORCPT ); Fri, 7 Oct 2022 14:30:27 -0400 Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 35FD31ADA2 for ; Fri, 7 Oct 2022 11:30:24 -0700 (PDT) Received: by mail-wr1-x435.google.com with SMTP id b4so8502171wrs.1 for ; Fri, 07 Oct 2022 11:30:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=tSTs+DROsNy8R98PSP2dWqb8FD9s3mzgTmR5HllyQDg=; b=mUpRXT5aeGgLAB10eMTUWeBOe9kDtdvMf5MPZq/rziHD0WjX29W0dJoR7ucLfA6wBB DFL99JELWsVHv4Lrh/fyruGuM+1u9Eh+CMrKPydV6WQq6L+CsVLCwb8sLx1KoeAQURvG lGtPZSZ+mB8NolDZj59ZeQUBUObqsMta34sME1f1KAKXGkBquHAY3GRDJA02UfBAU5JL fv8cGn7LoZ9PX93Uy1wL+904gM9en43qA768qhMtdYdZbXdJWPc3Au44GAa4bJF34u0J IfgKsjHanNQD4kykkEz5ZtwbnTAV+W9m1Ai3+vTMg7rOcnsddidL6K4J1T9rNpBv/RzE U21w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tSTs+DROsNy8R98PSP2dWqb8FD9s3mzgTmR5HllyQDg=; b=IzoYCUtRNJyTqhKyrxZL3DNOqD9T8APxUNWFgZFd9zN27/ivtvQq5p7vcVZKgLQ271 ywydujj4oLapCs27izLdIEYOLo7xqwKtud571zl/NHFC4EJPE+nziiHMIsVlFytdSK5w aXYF47MxpYhgHJqLFNgS+fD1AoDHN/GzOmpgJc6/V0kiiIGQHIw8iCyOf0YsuSfkP4AR gainfZGzrGSIzcIwtLf4eWay/RN88/dtmbY2eRpbp5nzi4MHNwn/Ysw6PYrQViRQA6UI 7V3Wrq6QIVTOAFH4e+++qSs1xKHFDEfHyHUoA0jUsuv4e4sg7a6F5Qfz8TBkl07OOwCS ggvQ== X-Gm-Message-State: ACrzQf0xiaivP2Fz9VkPWkIXJVmLys8rQSGni+sFDVB/lbbfzUb0uMo/ vyG9ozRlNtFwOznkS9fR/vTf/af56cNMsBND X-Google-Smtp-Source: AMsMyM7ZIIicvCAtIHVfb5jfRJ8ZgSpRzgk2X617DvWBTvEp67UkXnechYeKGI74YoXe7FnKNtgGZQ== X-Received: by 2002:a05:6000:981:b0:22e:6b59:fe52 with SMTP id by1-20020a056000098100b0022e6b59fe52mr3941797wrb.188.1665167423636; Fri, 07 Oct 2022 11:30:23 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:23 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 16/17] HID: haptic: implement HID haptic reset callback Date: Fri, 7 Oct 2022 18:29:44 +0000 Message-Id: <20221007182945.1654046-17-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org When a haptic device performs device initiated reset it puts itself back into autonomous mode. This leads to incosistency in the actual device state and the state configured by the kernel (manual mode). Hence user may observe duplicated force feedback, initiated by the device itself (due to its autonomous mode) and the host (by sending manual reports). Configure the device and put it back into manual mode once reset is noticed. Signed-off-by: Angela Czubak --- drivers/hid/hid-haptic.c | 21 +++++++++++++++++++++ drivers/hid/hid-haptic.h | 6 ++++++ drivers/hid/hid-multitouch.c | 18 ++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 4b3ad5168fbb4..d00103be536c2 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -226,6 +226,26 @@ static void switch_mode(struct hid_device *hdev, struct hid_haptic_device *hapti haptic->mode = mode; } +static void haptic_reset_work_handler(struct work_struct *work) +{ + + struct hid_haptic_device *haptic = container_of(work, + struct hid_haptic_device, + reset_work); + struct hid_device *hdev = haptic->hdev; + + if (haptic->press_ordinal_cur && haptic->release_ordinal_cur) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_KERNEL); +} + + +void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic) +{ + if (haptic->wq) + queue_work(haptic->wq, &haptic->reset_work); +} +EXPORT_SYMBOL_GPL(hid_haptic_reset); + #ifdef CONFIG_PM void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic) { @@ -521,6 +541,7 @@ int hid_haptic_init(struct hid_device *hdev, haptic->hid_usage_map[HID_HAPTIC_ORDINAL_WAVEFORMSTOP] = HID_HP_WAVEFORMSTOP & HID_USAGE; + INIT_WORK(&haptic->reset_work, haptic_reset_work_handler); mutex_init(&haptic->auto_trigger_mutex); for (r = 0; r < haptic->auto_trigger_report->maxfield; r++) parse_auto_trigger_field(haptic, haptic->auto_trigger_report->field[r]); diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index 96757a4655ec7..86823c2de5dd4 100644 --- a/drivers/hid/hid-haptic.h +++ b/drivers/hid/hid-haptic.h @@ -65,6 +65,7 @@ struct hid_haptic_device { #define HID_HAPTIC_PRESS_EFFECT_ID 1 struct hid_haptic_effect *effect; struct hid_haptic_effect stop_effect; + struct work_struct reset_work; bool is_forcepad; }; @@ -82,6 +83,7 @@ int hid_haptic_input_mapping(struct hid_device *hdev, unsigned long **bit, int *max); bool hid_haptic_input_configured(struct hid_device *hdev, struct hid_haptic_device *haptic); +void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic); #ifdef CONFIG_PM void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic); void hid_haptic_suspend(struct hid_device *hdev, struct hid_haptic_device *haptic); @@ -120,6 +122,10 @@ bool hid_haptic_input_configured(struct hid_device *hdev, { return 0; } +static inline +void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic) +{ +} #ifdef CONFIG_PM static inline void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic) {} diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index c50425a4de62c..f492becbab374 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1888,6 +1888,23 @@ static int mt_resume(struct hid_device *hdev) } #endif +static int mt_reset(struct hid_device *hdev) +{ + struct mt_device *td = hid_get_drvdata(hdev); + struct hid_haptic_device *haptic = td->haptic; + + if (!(hdev->claimed & HID_CLAIMED_INPUT)) + return -ENODEV; + + mt_release_contacts(hdev); + mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + + if (td->is_haptic_touchpad) + hid_haptic_reset(hdev, haptic); + + return 0; +} + static void mt_remove(struct hid_device *hdev) { struct mt_device *td = hid_get_drvdata(hdev); @@ -2306,5 +2323,6 @@ static struct hid_driver mt_driver = { .reset_resume = mt_reset_resume, .resume = mt_resume, #endif + .reset = mt_reset, }; module_hid_driver(mt_driver); From patchwork Fri Oct 7 18:29:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 13001409 X-Patchwork-Delegate: jikos@jikos.cz Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1BBBAC433F5 for ; Fri, 7 Oct 2022 18:30:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229578AbiJGSag (ORCPT ); Fri, 7 Oct 2022 14:30:36 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55816 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229865AbiJGSa2 (ORCPT ); Fri, 7 Oct 2022 14:30:28 -0400 Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AC671A3F7B for ; Fri, 7 Oct 2022 11:30:25 -0700 (PDT) Received: by mail-wr1-x432.google.com with SMTP id bv10so4903494wrb.4 for ; Fri, 07 Oct 2022 11:30:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf.com; s=google; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=3eX6NDYV/kFbZUS0kGHYJJXlnLzcSdyJKSxZSY1+oaU=; b=CL5yorzAuk3/FEJQ3DOJx5oryef81XS3hoWOkzXu6dbmbiltb0YfMQiKj6QDXCihzx cdqofGG0enePb2IK06Taeaz5DLyHUjoEEI+uwQjICxBkXS+NPNRr7u/aPgjd4yL+3VkB X1iAVuRTGVN4NwYEXnVzaZQFBl4UbiZ0cV9aKxfB1zQKyDtM7xwaGGBOlQsBBkofr0nk 8XBg8EwNniUHRtNzBvweoVpiaSCgbrjXPhptGBeXY1cZs1pzcUvvbgO0LKX0i9Kh+bqz syiDdxzrS+s8zE5Ai42M2LArD8qlxifZIaaNJkx6iHTNcg2tWXlCYcXL/qvOYiThX++N wqyg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=3eX6NDYV/kFbZUS0kGHYJJXlnLzcSdyJKSxZSY1+oaU=; b=NzkOVd2fNwN9VZAABbl1MeWZVXl/qQNHA9zLWW4d5KHdmPF4FLzziFJtn8GY1OLxgv WIzF6PzKOFLHO6GJJipmo8Vzu/ib93PR/wUg91koUTKo93u3rTtqE1zmamlSqavTP+Xr M4jcxLCO/6EtqCZBH74lhLiUOJ2kqnX7dfbB0CnsX/2/PsyYwEjdt3rUlNCdJwuFJLS6 HQUVugSBFBMPG8DEJb35h66tFulOeGV6aIW5BedDg5rDUyUhGWo6kmCRFTL9/0+VChFU mg5MQgRzudyACucNYkV8LTxj+Xe3BnthvX/8ltMASWHWjrEZ9bloqvRpC38yICk6QPMA amMA== X-Gm-Message-State: ACrzQf3TSya9va0w5kTgsmKIUNFl/tpwYRG/l1n/EOTYOVV+bJiy7TqB 7zZpCG6PWNBBk9TrO1uNG5J7Z8RQXyE+7DWF X-Google-Smtp-Source: AMsMyM5OzizpBWT68dAUHglD4LJyxbmCkc3qQEyu9VaQf1AuuqtdkNqSKQru4NwA1pzfj2zWRDC0lQ== X-Received: by 2002:a5d:47a6:0:b0:22e:80a3:ac95 with SMTP id 6-20020a5d47a6000000b0022e80a3ac95mr3262678wrb.507.1665167424277; Fri, 07 Oct 2022 11:30:24 -0700 (PDT) Received: from aczubak.c.googlers.com.com (230.213.79.34.bc.googleusercontent.com. [34.79.213.230]) by smtp.gmail.com with ESMTPSA id l10-20020a05600012ca00b002258235bda3sm2573627wrx.61.2022.10.07.11.30.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 07 Oct 2022 11:30:23 -0700 (PDT) From: Angela Czubak To: linux-input@vger.kernel.org Cc: upstream@semihalf.com, benjamin.tissoires@redhat.com, jikos@kernel.org, dmitry.torokhov@gmail.com, Angela Czubak Subject: [PATCH v4 17/17] HID: multitouch: Add lid handler for touchpad on Redrix chromebook Date: Fri, 7 Oct 2022 18:29:45 +0000 Message-Id: <20221007182945.1654046-18-acz@semihalf.com> X-Mailer: git-send-email 2.38.0.rc1.362.ged0d419d3c-goog In-Reply-To: <20221007182945.1654046-1-acz@semihalf.com> References: <20221007182945.1654046-1-acz@semihalf.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org If user closes the lid the touchscreen gets close to the touchpad surface, which causes interference and makes the touchpad enter noise mode. Right after opening the lid the cursor is unresponsive because of the mode mentioned. To fix this issue we switch the surface off and on so that Elan's FW performs recalibration once the lid has been opened. Signed-off-by: Angela Czubak --- drivers/hid/hid-multitouch.c | 220 ++++++++++++++++++++++++++++++++++- 1 file changed, 219 insertions(+), 1 deletion(-) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f492becbab374..92541ed153557 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -32,11 +32,14 @@ */ #include +#include +#include #include #include #include #include #include +#include #include #include @@ -159,6 +162,7 @@ struct mt_report_data { }; struct mt_device { + struct list_head list; /* for list of devices needing input handler */ 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 */ @@ -173,8 +177,15 @@ struct mt_device { struct list_head applications; struct list_head reports; + + struct work_struct lid_work; + struct mutex mode_mutex; + bool lid_switch; }; +static struct workqueue_struct *mt_mode_wq; +static LIST_HEAD(mt_devices_with_lid_handler); + static void mt_post_parse_default_settings(struct mt_device *td, struct mt_application *app); static void mt_post_parse(struct mt_device *td, struct mt_application *app); @@ -404,6 +415,91 @@ static const struct mt_class mt_classes[] = { { } }; +static void mt_input_lid_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + struct mt_device *td, *n; + + if (type == EV_SW && code == SW_LID && !value) { + list_for_each_entry_safe(td, n, &mt_devices_with_lid_handler, list) + queue_work(mt_mode_wq, &td->lid_work); + } +} + +struct mt_input_lid { + struct input_handle handle; +}; + +static int mt_input_lid_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct mt_input_lid *lid; + char *name; + int error; + + lid = kzalloc(sizeof(*lid), GFP_KERNEL); + if (!lid) + return -ENOMEM; + + name = kasprintf(GFP_KERNEL, "hid-mt-lid-%s", dev_name(&dev->dev)); + if (!name) { + error = -ENOMEM; + goto err_free_lid; + } + + lid->handle.dev = dev; + lid->handle.handler = handler; + lid->handle.name = name; + lid->handle.private = lid; + + error = input_register_handle(&lid->handle); + if (error) + goto err_free_name; + + error = input_open_device(&lid->handle); + if (error) + goto err_unregister_handle; + + return 0; + +err_unregister_handle: + input_unregister_handle(&lid->handle); +err_free_name: + kfree(name); +err_free_lid: + kfree(lid); + return error; +} + +static void mt_input_lid_disconnect(struct input_handle *handle) +{ + struct mt_input_lid *lid = handle->private; + + input_close_device(handle); + input_unregister_handle(handle); + + kfree(handle->name); + kfree(lid); +} + +static const struct input_device_id mt_input_lid_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | INPUT_DEVICE_ID_MATCH_SWBIT, + .evbit = { BIT_MASK(EV_SW) }, + .swbit = { [BIT_WORD(SW_LID)] = BIT_MASK(SW_LID) }, + }, + { }, +}; + +static struct input_handler mt_input_lid_handler = { + .event = mt_input_lid_event, + .connect = mt_input_lid_connect, + .disconnect = mt_input_lid_disconnect, + .name = "hid-mt-lid", + .id_table = mt_input_lid_ids, +}; + static ssize_t mt_show_quirks(struct device *dev, struct device_attribute *attr, char *buf) @@ -558,6 +654,83 @@ static struct mt_usages *mt_allocate_usage(struct hid_device *hdev, return usage; } +static void mt_set_modes(struct hid_device *hdev, enum latency_mode latency, + bool surface_switch, bool button_switch); + +static void lid_work_handler(struct work_struct *work) +{ + + struct mt_device *td = container_of(work, struct mt_device, + lid_work); + struct hid_device *hdev = td->hdev; + + mutex_lock(&td->mode_mutex); + mt_set_modes(hdev, HID_LATENCY_NORMAL, false, false); + /* Elan's touchpad VID 323B needs this delay to handle both switch + * surface off and switch surface on and trigger recalibration + * properly. + */ + msleep(50); + mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + mutex_unlock(&td->mode_mutex); +} + +static const struct dmi_system_id mt_lid_handler_dmi_table[] = { + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Redrix"), + }, + }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Google"), + DMI_MATCH(DMI_PRODUCT_NAME, "Redrix4ES"), + }, + }, + {} +}; + +static int mt_create_lid_handler(void) +{ + int error = 0; + + if (!dmi_check_system(mt_lid_handler_dmi_table)) + return 0; + + mt_mode_wq = alloc_ordered_workqueue("hid-mt-lid", WQ_FREEZABLE); + if (mt_mode_wq == NULL) + return -ENOMEM; + + error = input_register_handler(&mt_input_lid_handler); + if (error) + goto remove_wq; + + return 0; + +remove_wq: + destroy_workqueue(mt_mode_wq); + mt_mode_wq = NULL; + return error; +} + +static void mt_configure_lid_handler(struct mt_device *td) +{ + struct hid_device *hdev = td->hdev; + + if (hdev->bus != BUS_I2C) + return; + + td->lid_switch = true; + list_add_tail(&td->list, &mt_devices_with_lid_handler); +} + +static void mt_destroy_lid_handler(void) +{ + input_unregister_handler(&mt_input_lid_handler); + destroy_workqueue(mt_mode_wq); +} + static struct mt_application *mt_allocate_application(struct mt_device *td, struct hid_report *report) { @@ -581,6 +754,8 @@ static struct mt_application *mt_allocate_application(struct mt_device *td, if (application == HID_DG_TOUCHPAD) { mt_application->mt_flags |= INPUT_MT_POINTER; td->inputmode_value = MT_INPUTMODE_TOUCHPAD; + if (mt_mode_wq) + mt_configure_lid_handler(td); } mt_application->scantime = DEFAULT_ZERO; @@ -1778,6 +1953,10 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) INIT_LIST_HEAD(&td->applications); INIT_LIST_HEAD(&td->reports); + INIT_LIST_HEAD(&td->list); + INIT_WORK(&td->lid_work, lid_work_handler); + mutex_init(&td->mode_mutex); + if (id->vendor == HID_ANY_ID && id->product == HID_ANY_ID) td->serial_maybe = true; @@ -1841,12 +2020,18 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state) struct mt_device *td = hid_get_drvdata(hdev); struct hid_haptic_device *haptic = td->haptic; + /* Wait for switch on completion */ + if (td->lid_switch) + flush_workqueue(mt_mode_wq); + + mutex_lock(&td->mode_mutex); /* High latency is desirable for power savings during S3/S0ix */ if ((td->mtclass.quirks & MT_QUIRK_DISABLE_WAKEUP) || !hid_hw_may_wakeup(hdev)) mt_set_modes(hdev, HID_LATENCY_HIGH, false, false); else mt_set_modes(hdev, HID_LATENCY_HIGH, true, true); + mutex_unlock(&td->mode_mutex); if (td->is_haptic_touchpad) hid_haptic_suspend(hdev, haptic); @@ -1860,7 +2045,10 @@ static int mt_reset_resume(struct hid_device *hdev) struct hid_haptic_device *haptic = td->haptic; mt_release_contacts(hdev); + + mutex_lock(&td->mode_mutex); mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + mutex_unlock(&td->mode_mutex); if (td->is_haptic_touchpad) hid_haptic_resume(hdev, haptic); @@ -1879,7 +2067,9 @@ static int mt_resume(struct hid_device *hdev) hid_hw_idle(hdev, 0, 0, HID_REQ_SET_IDLE); + mutex_lock(&td->mode_mutex); mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + mutex_unlock(&td->mode_mutex); if (td->is_haptic_touchpad) hid_haptic_resume(hdev, haptic); @@ -1897,7 +2087,9 @@ static int mt_reset(struct hid_device *hdev) return -ENODEV; mt_release_contacts(hdev); + mutex_lock(&td->mode_mutex); mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true); + mutex_unlock(&td->mode_mutex); if (td->is_haptic_touchpad) hid_haptic_reset(hdev, haptic); @@ -1913,6 +2105,8 @@ static void mt_remove(struct hid_device *hdev) sysfs_remove_group(&hdev->dev.kobj, &mt_attribute_group); hid_hw_stop(hdev); + + list_del(&td->list); } /* @@ -2325,4 +2519,28 @@ static struct hid_driver mt_driver = { #endif .reset = mt_reset, }; -module_hid_driver(mt_driver); + +static int __init mt_init(void) +{ + int ret; + + ret = hid_register_driver(&mt_driver); + if (ret) + return ret; + + ret = mt_create_lid_handler(); + if (ret) + hid_unregister_driver(&mt_driver); + + return ret; +} +module_init(mt_init); + +static void __exit mt_exit(void) +{ + if (mt_mode_wq) + mt_destroy_lid_handler(); + + hid_unregister_driver(&mt_driver); +} +module_exit(mt_exit);