From patchwork Fri May 13 09:39:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848575 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 C9201C433EF for ; Fri, 13 May 2022 09:39:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379113AbiEMJjx (ORCPT ); Fri, 13 May 2022 05:39:53 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51772 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353324AbiEMJjr (ORCPT ); Fri, 13 May 2022 05:39:47 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A0022291CE2 for ; Fri, 13 May 2022 02:39:46 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id w4so10611534wrg.12 for ; Fri, 13 May 2022 02:39:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WdwIy7/v1iTivZ6vsqK8ZiirGRhaJyIa1aow2Y2Yi8k=; b=Qg3wANH1Qb/PtBHYcIfr7H9phP7hhfq0/RipbnXyavLe33we8flBJurKgI8lSOsxRd G79KvZaF1IVMRLSupFAF+SGcEafpOSZrNpMP0GqyY6vN/Cqlk0wX8TszBmeUQ6HBF+jT 7vdPoiiERlsqb+MCytJgvtdXF5aSOwQ+PjBehoxd8eB/r6G8ejiFZGH4t4Q3aJHw6+na U2OKw7014xDtl3N1sorn5vvEfXdrdQcpWMMXUcVKwBtK3agay/1NIiujuM9zT64JNJRf DJE4AsiP+2Bm15FxUPqJYYKD6WwYN8ckgsNZPlSV4h87e7I3jMO5R0xW1uhbPKO0MF71 AmWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WdwIy7/v1iTivZ6vsqK8ZiirGRhaJyIa1aow2Y2Yi8k=; b=TLFrkUMovm28ffJssvMHcox5h1UicSiVQRTNRqYiB3dkQVS4i7IHwZMsaYagbRm2ev nz8pH1yshEA8sCj8tG+e93L99+fCeTlQrSoPIwDbUrp4lUf255FXOOV8uCDhjjJGYtn6 js2NRM7sKDAxhbT64pbRsal9Hckmg6qJIZUwG1slOPHhjH5SswKK4CJXhDpoVokSdMyK SgO5CNDH4+59ZxcWhmegUXScHPc6kZcE1LBvrM7T8XOP1MMUrnh1PxggA8nLNp6gYzRB mrowWPIZs184x8EHsi/EdtkRu4yUvvk2YW1v9P2JPCGRLpjPpsCWG53uh3HivtiqwcFy chnA== X-Gm-Message-State: AOAM532evhcEeyLpgv5aB4oJicvpihOpEKZl8X8/6M59bBbTDLWeOqGJ a5ex8MiHWciIi7/Y0Ef01uqcQ3Ygg1SYWRhno0w= X-Google-Smtp-Source: ABdhPJylgszupHn+IFWAFeAJkrRzCl6Rbv5/5o46ai5vKkDnNLcqS1QHKLr2CuKlR2kWGtig4E+WDQ== X-Received: by 2002:a05:6000:1f0f:b0:20c:87b6:df9d with SMTP id bv15-20020a0560001f0f00b0020c87b6df9dmr3345602wrb.115.1652434785220; Fri, 13 May 2022 02:39:45 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.44 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:44 -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 v3 01/17] HID: add haptics page defines Date: Fri, 13 May 2022 09:39:11 +0000 Message-Id: <20220513093927.1632262-2-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 4363a63b9775..3f5899c62821 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 May 13 09:39:12 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848576 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 1481DC433F5 for ; Fri, 13 May 2022 09:39:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379121AbiEMJjy (ORCPT ); Fri, 13 May 2022 05:39:54 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51784 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379069AbiEMJjs (ORCPT ); Fri, 13 May 2022 05:39:48 -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 13B3F291CF2 for ; Fri, 13 May 2022 02:39:47 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id j25so9637267wrc.9 for ; Fri, 13 May 2022 02:39:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=QukRnRADZ2W2DS8/08MZQ2pgAnb2HoWz6ujhm4UEe6Y=; b=p7C+6AaxZIeKWHY4ODqC1K1iJga/xJSEr6qjTvWk9tiASXJ0uViCUXSOmj9lCbfa6U C6jlMn9W0IMmueeSAwDKrTv6DV7YgWiXaTC7Z1oEaEfWloFyQCvmSVmaPwEJhuh5s0Wm jNlItCAMFsDAKCnFsKaV86D8QUccAKQcfh28qN1psWPp5+UhELX4xcY5dfrUV3hKa4lQ 7tHYOcajaKy0P5F8q8cyFymaZPsJvOCYtJOVKQ2UXr7TXSpHTyzzUZazshVdRy6gywZv 1JncAeRc2+5wRVrHwi6w//PMexatze8tN8cKgLmgyH7lPZUuvN1E1Csu8l0ZpfhMzbeN QohA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QukRnRADZ2W2DS8/08MZQ2pgAnb2HoWz6ujhm4UEe6Y=; b=iPoAyJjNv72tpbKmPv025+pffRsh9Lh8CHZBG/H8HwrAwMgBJI4A5HDlpsACod7qEL iKdcM1/g3ItlfNo8vPQWBJkMtnf6YpIi/W9yGEStMBBQIu9Gr4DyS63KHvL6RHqMWt8a an2oyrUg8Iq/HbN7KNmHjh/jOB8RV3bnjjl7Ywy6vONgUMDAdFjlAUZYBLB0wk4x8jiH C2giawE2iODWwzSl9hHOjwboSH5iPZU/R9WVFICyPEPVsdwhh6HI6Rs3IarCvF1KgJQs gJEU7GcQ9LG817pr4Q87rjNu25BaAaLJlOQP8Xu2miU2oSVuZ6KP6u0viMBj/l0rNnKz 9JJw== X-Gm-Message-State: AOAM531AOHMvDR3NQGrfyvbv8g4VU0dwr9BvuGgpHFH6hZtchCjyt96f ITgiIWzu3odtl/L9jtMvCPQUgy8TwIsyGDT2/WE= X-Google-Smtp-Source: ABdhPJz6LhRZnfA+rfbN45Xc9amhu84y8YvzqsHUb/AOPKUu9JvtOFd1aXRIHYbkcKw8ApDcXC2I6g== X-Received: by 2002:a5d:5228:0:b0:20a:d7e9:7ed8 with SMTP id i8-20020a5d5228000000b0020ad7e97ed8mr3000474wra.687.1652434785699; Fri, 13 May 2022 02:39:45 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:45 -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 v3 02/17] Input: add FF_HID effect type Date: Fri, 13 May 2022 09:39:12 +0000 Message-Id: <20220513093927.1632262-3-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 ee3127461ee0..ccf43a21d43d 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -424,6 +424,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, @@ -460,6 +478,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; }; @@ -467,6 +486,7 @@ struct ff_effect { * Force feedback effect types */ +#define FF_HID 0x4f #define FF_RUMBLE 0x50 #define FF_PERIODIC 0x51 #define FF_CONSTANT 0x52 @@ -476,7 +496,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 May 13 09:39:13 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848578 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 DFBBEC4332F for ; Fri, 13 May 2022 09:39:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379096AbiEMJj5 (ORCPT ); Fri, 13 May 2022 05:39:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379042AbiEMJjt (ORCPT ); Fri, 13 May 2022 05:39:49 -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 D7D5729ED0B for ; Fri, 13 May 2022 02:39:47 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id d5so10661583wrb.6 for ; Fri, 13 May 2022 02:39:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=g3Y7mgRa4QHnOk2vJqykkfvQEB+3h0r4ILNwSLuGqGs=; b=bsttD1pO+WkIvIIEqgvCQZKaoC7yJBJDW66XhvyKBjScvuR40cVYFCGAhrwlFuIJE7 tKqyFfRBPm03pO1/pnGV6q5e7MOwJC3+8NsNmxdqajKVk6uIV/HsUVACJtWvbiTZnAP0 OBd/3TeFafZLEiyywkeQND/ThAdId/hya5mpoCF+EdBxRNv1xjE9hPt4yGp8+ByDxeL5 t4LCOgEeID+F6jCU+ggLokFD1T5bn5eZhxjkaeLQSLVhVpH8DZWlgJOKJvRP5QW3CaYB nq9TGqwzAjLROdV264Msbeo3k4ma/Fwx/a2PP7sXT9n2Y+twXb/3jA8ETpmkXgOga4bw mMTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=g3Y7mgRa4QHnOk2vJqykkfvQEB+3h0r4ILNwSLuGqGs=; b=SCdW1U4VkBkb01CMl45pTA6pfqCni4nr/6n8yf7pwbYWhFAVQVQ+1ilIFs+OBKd2kM Piu8o8KSJ78hfzRIuyyHAiP4EOt7XQcxhzJEY5PGD6rfhd/UjKkVA1LbEsKo9HeD1P1t zpXazuuA6/ZNcORopGey6iJfCtPcZSvm+beaMtJ3Yu3iEchglJtBaKC5eioI9yarWa94 c7TYXaqLyJY7NB4QQPP1IDKp3jAzndlG2sFqul0SKgxA7rX6s7aiaeJEQfR0BFRYBeA0 9giTx4fBHw9w9WaV/DswP+o8MjQrwgO25vlAXfpZlo29D6NspgcEk13SQ7qiUVIvTQmR 15oA== X-Gm-Message-State: AOAM530CfoOZWVeV/PcTUTfW/I3p7rTQFHvnHGry9xZP/3FzFmCkQ0AB xts+5viuv8TYVdea8AH0RE050KIWlRYEIje3YxA= X-Google-Smtp-Source: ABdhPJxbZK5tL6koGJgZemWAw7SmHUYSgzNNaNITWymDg0VHcXDecmTDgqRr/HE0+/KUE1aKxFlTUQ== X-Received: by 2002:a5d:6d0b:0:b0:20c:4ecb:1113 with SMTP id e11-20020a5d6d0b000000b0020c4ecb1113mr3075566wrq.203.1652434786383; Fri, 13 May 2022 02:39:46 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:45 -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 v3 03/17] HID: haptic: introduce hid_haptic_device Date: Fri, 13 May 2022 09:39:13 +0000 Message-Id: <20220513093927.1632262-4-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 a95a7cbc4a59..c892cfea3bb5 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 345ac5581bd8..bfd09957e58d 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 000000000000..ea1004319bc0 --- /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 000000000000..ea96b0fb540f --- /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 May 13 09:39:14 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848577 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 775DDC433FE for ; Fri, 13 May 2022 09:39:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379069AbiEMJj4 (ORCPT ); Fri, 13 May 2022 05:39:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51794 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379096AbiEMJjt (ORCPT ); Fri, 13 May 2022 05:39:49 -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 68AF0291CDE for ; Fri, 13 May 2022 02:39:48 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id e29so1015748wrc.11 for ; Fri, 13 May 2022 02:39:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=O9z/PqC89pqgqEOOhqgahLZjJuV2bITnseB+HB7kVRI=; b=sPP2EEFfPQVwNd5Bz8A34V6S2F1cUmjnVdrr3ms/ynkfYRWWdcK+2zsvfPpFZda6LX Ys/A4T9v+n/MeWpDtkt4ngiyHXWwt/qlSjAhvG7MR1LWzg9pOL8Z8sfqW2LvSUws1zTX J8+6pez8CTlmQBhXOQn6Plz2eG3Hs4UxH3RxGvS6XGrEM2oergHuTmy5+j3qao7A7a7E Lz891sdScFjtfKFQbm+QkCZw3bggkj8B6/67/VSlTEmgBu1F4c9rAo84s9hyybl3YjoU yWIvfC73tu2rzehwLy9LJ6DAjjcql3o2Aib9WFB9sin6MB3C76Io2XAQJtb3i48zJmYu 2hpg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=O9z/PqC89pqgqEOOhqgahLZjJuV2bITnseB+HB7kVRI=; b=JI0gfiAiUXsLvoHK/S/r7wEofhOOsJOjJCRfHghVCDH6d3z+yT50RIlMANKykipEYN 6oR+OfMegYCKqN4CvbW7HsJVTUPeQZGUbNX3kbbKeeiEEmVGRrGhuWZD48V0cmZm8rGP jMcK7jNZ2HXl/sbzbQRkUCkD6KIzVXLQB5+tbXFvZfDIdqHyNFiLePVuWTL8VFR6zVW5 do85UuGdhKqU2Jxshy3NbOcYO08qeYLCh9r22q9WKDXhHfiSCUC2oYASwT82RHQqblz+ L1pfxDBHqdD1sUcAQd30q8M1vKvb7NkeZx+rGHzZLEg25WfKMzYjNCFy++EobjEi+Q7L Gc4Q== X-Gm-Message-State: AOAM530jH4ie1eQnA4H6Ehh1qCHJ1zqeFIofxvdjec3rWazQS4Bc9rfB 0emoXdyufcgGXjDsqaamlAUtd0W/tK14McUBego= X-Google-Smtp-Source: ABdhPJyH2z6wSh62B31TWZ6OvH2dGuYUOroqh/7QLIQ3OVfvhfVdaj0J2pDdy4M9jkTfmkeiaCKnCg== X-Received: by 2002:a5d:524f:0:b0:20a:cff1:1cef with SMTP id k15-20020a5d524f000000b0020acff11cefmr3145351wrc.157.1652434787033; Fri, 13 May 2022 02:39:47 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:46 -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 v3 04/17] HID: input: allow mapping of haptic output Date: Fri, 13 May 2022 09:39:14 +0000 Message-Id: <20220513093927.1632262-5-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 c6b27aab9041..77f2930f78f5 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -649,9 +649,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 May 13 09:39:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848579 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 1F118C433F5 for ; Fri, 13 May 2022 09:39:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379097AbiEMJj5 (ORCPT ); Fri, 13 May 2022 05:39:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379105AbiEMJjv (ORCPT ); Fri, 13 May 2022 05:39:51 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1D0D53A709 for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id q23so10666863wra.1 for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=qemkfG6SKXFq49UM+387xqI+WvSUi4dcCe5TaBc3Q9E=; b=trgxbZt3y8lTNh/A9Aa8TusjrC8HuZ1cd00efSUgqM8T8oeqF0E1jGnljzEWLFZ29v weF29EIPavOlvGZxCeoHp4DvKh++U+OLdq6Obw+9NIvoSOzpKzPTC7af6SG+UelLcfV8 EM8sMsnImJU21/1Q6g5oXpHVMd6Ja+j4fIGXT0SNSAPPk0EjQzFSBDfy85qToiC1iiVF tkY9aCgvICcCIehrr+FFITCwsaZ+9eXHUGRuWItqTlqD3RWoesM1/UbTZmtSQgGBQSjm Awf5IhsRcPhLIC1yH+CpCOstnYNtpe9hJV3j2i6orDWhINPIKBVXMeLULjffO/6QjilY c4yw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=qemkfG6SKXFq49UM+387xqI+WvSUi4dcCe5TaBc3Q9E=; b=Y6COvO1yVH1yFOHkfn6K7gM+koNrUNbgBVhF5rWma//qxZr+EBXxtYmAyfhtvr9Qv4 aTxfmXcJtQiTnnyTdAQrqXFZgiV6aig4S4auIAvURT0Wmbm5Tdvu4ApVl+GXsPWeX6l9 G0XT5/LhgVcNHsYtxXfLPB0rZZrgLFtozyVuz9PO7zib6OBaJRmHUuB99iYxLXfnTV7i RoRT33FK0tDuRHYDUrMYEodSUQv9COp+O/QDpYJzXi+JXFNBoji5y5kuzUNgpSwcZtLR bkYvI4L4WgLcJJpEUwMZtL+I/jNkg9x2m2xYiURzh0GJheF4Sv2+uan5o31linPNXRnJ wyYA== X-Gm-Message-State: AOAM532B7wLbkrCMIY5EILSFutrnWfs3a5yREaMT/OaR9ShvzpKppuFK YPO3OB+sNZjl+RcTVN+3z53NQzSX89+5b4vS94M= X-Google-Smtp-Source: ABdhPJy43Q4w8L0KViq6+Wu18AY6x0wMJFBd4R2OF7HrR1Qa5i8M+lFD47Fu9BV3MjCs/zSBuAzl+w== X-Received: by 2002:a5d:47a2:0:b0:20c:5f8c:a645 with SMTP id 2-20020a5d47a2000000b0020c5f8ca645mr3119152wrb.526.1652434787649; Fri, 13 May 2022 02:39:47 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:47 -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 v3 05/17] HID: haptic: initialize haptic device Date: Fri, 13 May 2022 09:39:15 +0000 Message-Id: <20220513093927.1632262-6-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 ea1004319bc0..327106152d79 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 ea96b0fb540f..67096cc8c233 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 May 13 09:39:16 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848582 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 4D32CC433F5 for ; Fri, 13 May 2022 09:40:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379100AbiEMJkB (ORCPT ); Fri, 13 May 2022 05:40:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51830 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379101AbiEMJjv (ORCPT ); Fri, 13 May 2022 05:39:51 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9BF2A291CDC for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id v12so10620690wrv.10 for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=21VAODRnaYGO5mjcXKrja1BvMEwTAYGDEk9j65ebLNw=; b=2itsY17oZS2xUiB0FdX4gPMxJne+bt0ypOU0pHctSOE/YaFBaagGVpNLeXG4lmBtyN ZrNM3B/gEfwpJ/GgNOhc8AzhHDOF3ktITkFFpC6PM7MHTPakSEO2Y83HKeQMKLtlKbQ+ WkQ3k2pkgGSQIiqVdSTqPXiGjnxxv+P1eFslNoF6TO0SUo5NJzYjgCQOQ9vUcj859oji IeeZtlQTZaVg6z6QTj4L0e4vkV4Kd6vVyOHA8fILLV6HwTC2CJqaBFV7SPym+M18ZpKN yLR4+DKywgnMhX8HEqCizTnz6/O/nntpBMc5ITfjU4qabbCiWAE9jwMBc7u42npavrQ1 3F/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=21VAODRnaYGO5mjcXKrja1BvMEwTAYGDEk9j65ebLNw=; b=Axczns+trTulFw8w0ABBsGcbFBrsuxGbhvCSf3EALlKzdjhSJQda2NXHaHMZ0G7Fa3 9cUNyIOU5DfhJtX9qTUfelaYkLGR/r38Yuj6FPQtjiU5atcmsSVN9qsBgnpADtRnq28G LVo4oVNYS7D+0aEAu6fdRPKM94ARKFMWWOhFTQ43qsOE4Wv6+oD0COW4Qy1NYGRcfO6Y dn8/B+os/RHxVBgSt3NJYnFmK1QriqJyNg3mdB5qXYisr2jg2Jzz4X8Y7zUZLvz8Ghrs lgvbp6+Pl8jGPBL3rac8ktGsQfc/cruNfD5l04BKJu96ffGhTu3WU+K/ndPNxtjCVVMj ibAw== X-Gm-Message-State: AOAM5336/FmAq59atbuE3+yMSeJqjfkn9A+9L+9BtBV1G+fqlNOiezJt aFu09fvXhFtltUn1TyigLI1jPk2Yu2c5enzlTpk= X-Google-Smtp-Source: ABdhPJyv162lIInR0bctTyVM3lMkY4QPwKPionk0xj6wMmosvzUWHDN8VcsEEfbxvl5Au5qGvB3CxA== X-Received: by 2002:a05:6000:188a:b0:20c:e43e:83f3 with SMTP id a10-20020a056000188a00b0020ce43e83f3mr3262983wri.621.1652434788246; Fri, 13 May 2022 02:39:48 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:47 -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 v3 06/17] Input: add shared effects Date: Fri, 13 May 2022 09:39:16 +0000 Message-Id: <20220513093927.1632262-7-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 fa8d1a466014..1a9a5401acb5 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 May 13 09:39:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848581 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 5E399C4332F for ; Fri, 13 May 2022 09:40:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379093AbiEMJj7 (ORCPT ); Fri, 13 May 2022 05:39:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379100AbiEMJju (ORCPT ); Fri, 13 May 2022 05:39:50 -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 364182A5E9B for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) Received: by mail-wr1-x429.google.com with SMTP id j25so9637267wrc.9 for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gfpO9dugdZxvOunltm8uXiDYgZvaCVfhDaKWWoOV/HI=; b=QN/I2ztTZGh9zohZx+ANhrOTO/NXrHR0WFm7r5vprnRIZ629PEp+WwXuVbHSCLhV5J 9drBf2YO4nJelL1LuMhny8gkOGqJ99AsdFo1PG//X2fmd8Qecwn+uAafhPrN2cpZ9fid stUXnO72KWdc54VI0rmX+9p0iiqtDMoaHqrpTgHwZgud08q0zjWpL6y+0aQwIdqB6SBI jfjsIMpX8SHdF35/EWpJE9zb30NIe6RGdFIOjdFji+VIEx5AxKcIil9V14+rPLX8HV9O Y7GRkgu/WZ3lXv/SvA2bRNap4CkyMfPKyUuXOzKCovV6ePtxKSdXHmJhB+hHTstURJjU 6Z3A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gfpO9dugdZxvOunltm8uXiDYgZvaCVfhDaKWWoOV/HI=; b=gIBJtU0pInk9783xEKTOvLIkciDgFp7SggQKOkzh17Rh0+SOpkI74mqtPuNXfv4RpZ 9BwqB1fLugWUg57QUjlpNiicu6pnpD1eSqQzrmNDh4PlrAHP2EArAdV6PZIDJ3h42uRO zBeYwWJuDnqH4kWvOpMu8ehtt0X3uKPApyD3ZD3cSYEy+nn4mUKVQvT8bqjmeC/eJZPO rq6edTocxWA6uKQIbqVBRNSZMqdaMi5u+YVBdO/7++5lMTTxGHrn/FWZLMtQK8FM3hwf XPSCDwsguQcRLDciUbzBujvCnZUDPL907cm3hVpxQnWxnNwfc88qw5xPBXV34q1Mbmlw GAhA== X-Gm-Message-State: AOAM533dWrtrSakwzenIfE+7OsyglE8XU3nwDuj/6Ozb/PpzMaCEdEsu L7OPE8pY2ccugiAxEcQ0Icbijb+IQjW6R4tQjYw= X-Google-Smtp-Source: ABdhPJx7erWoGDiBOJGvF+AFnSdIX5eNNje9gxhpLgD22y6Tg1L4ScTrTh3L5WRMNYbkQ3Cr0S5NiA== X-Received: by 2002:adf:d213:0:b0:20a:d703:154f with SMTP id j19-20020adfd213000000b0020ad703154fmr3296663wrh.604.1652434788762; Fri, 13 May 2022 02:39:48 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:48 -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 v3 07/17] HID: haptic: implement release and press effects Date: Fri, 13 May 2022 09:39:17 +0000 Message-Id: <20220513093927.1632262-8-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 327106152d79..3301bf27dfde 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 May 13 09:39:18 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848580 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 E226BC433FE for ; Fri, 13 May 2022 09:40:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379105AbiEMJj6 (ORCPT ); Fri, 13 May 2022 05:39:58 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51838 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379108AbiEMJjv (ORCPT ); Fri, 13 May 2022 05:39:51 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AEFFD2A5E9D for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id w4so10611534wrg.12 for ; Fri, 13 May 2022 02:39:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=5sHT1hvhkDQhIBW03xv/+oQei1z39Nj9aJXqgHfxZbg=; b=KMDXpfW3VFcom+1r3ChXyr95fAMzmpNyob2pnDZl2sulCSAEfHOaT2RSzW0TYjk37d V2UhH8D5C7Dtpdjt+bAL/+ns1n1AhTrGnxCCVnjM9jgxNRVweHRPdUtBgqd2o/JkLHAV 0KHbFu3+oWa23UFQcZiifMsacX9gPs8QbLE6Ap116ad6fLXga7ZOl+lnua56UAyxdTtB jlRfOo3W/WMPxhq3mhum/dYVZJG4v9oWl+mtOpBXyb+WU7P+IsT0ncAk9zDprmgML6vs S04cyiBMVZHJ9mjGne2YspEvtXRavpMKL5IRiG7c0iqwE6gkWcQzbA4n8NFiHZknH7t5 RcTg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5sHT1hvhkDQhIBW03xv/+oQei1z39Nj9aJXqgHfxZbg=; b=eGkZ0KOnBPAWkimbJvnApqfCB9fCoP82hMTpgTgCxLCAYh3GuY2c5ZP4t19O9DrKBZ Ktmbwogw1YmgWJDn137993pMHfB4XkuBDcdEfLKiXikkKkLuSC8XtOybVqJl1RUyi8zR HhBQ6fhIdj8PBaJ+qLbTfGJqkiWjfpmk8XfTH2L4ipMF+iTL9HoOMlZCUqdOL/Fvy/+5 gOEs5JjPDND1mRygTBBX6O2xhONmn7SmkVmaytxkofOQuxR+ANNsiqOgAbnXo2ylTl7r hRcWHB/YDePszZ+wz9f3VX+REaTK/oMhc6l9mdNkgWhGZiixACr+MC5fEA+7KWfckR9Q 74WQ== X-Gm-Message-State: AOAM533jGJj6b9BM/YIQXB1xU5kkQjFedm2Mgudf4QsmN/wTOAa7TykI XHTRoryzv0LKN8TU/BMXpI4mWY21unGvOlli5lc= X-Google-Smtp-Source: ABdhPJy3e+fZ99h27WpNLYKA0IXYlGTWCulPyUV/TE+ISHIMZ2oVnnSNdJ2NS0rlyua0L+vhYeN4og== X-Received: by 2002:a05:6000:186d:b0:20c:6b74:f31a with SMTP id d13-20020a056000186d00b0020c6b74f31amr3203853wri.286.1652434789331; Fri, 13 May 2022 02:39:49 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:49 -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 v3 08/17] HID: input: calculate resolution for pressure Date: Fri, 13 May 2022 09:39:18 +0000 Message-Id: <20220513093927.1632262-9-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 77f2930f78f5..c9f8405c0522 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 May 13 09:39:19 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848591 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 4631EC433EF for ; Fri, 13 May 2022 09:40:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1353324AbiEMJkG (ORCPT ); Fri, 13 May 2022 05:40:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51840 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379110AbiEMJjv (ORCPT ); Fri, 13 May 2022 05:39:51 -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 29CB72A7694 for ; Fri, 13 May 2022 02:39:50 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id d5so10661583wrb.6 for ; Fri, 13 May 2022 02:39:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=xyYoV9VEJR4KI6DtmLczZLEmtSnMRuKw1Cj6fks1u+g=; b=wbyD9M2Zz4qCGg4iGKb6Ymdv16agQPVP6aClej3V8gFYSWYjqj252TmFd/6ELrN7Xv A5Xdap0S+3v19Z++luABjuwxC/r9bDFlhlPjF8HN9F0rA6C+StxIDOjesyf3pDB182nA YqL/dk3bAv5gT88TtuTdaLUQhZzfouTBsY8YFWpYlCqkXz6NlTxpBDkVzMI08RoNBB2v uHj7Rru7FkvSJCiIBlwrcuJo1J6IB941M6WZHgbpnGMMshHqE9R7hYaoL/cJ6LJ8tEFd se3BB/WOHxN5fvZ10iIPqtIGC17URDkLELWNb/fY6m42AR9rAj8xcn7yqeBrcMSq6CRn 2IUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=xyYoV9VEJR4KI6DtmLczZLEmtSnMRuKw1Cj6fks1u+g=; b=CMIpIfTbZwCDVFUz7upBvFDn7Ibr3cJwKCBuWLHSZa0Xea2cqm/0T80WjTN1gEn0IZ FX6/CxOZaINwL7ntysMotD0zp86tStIRD82pDVWoitWqRxO9woz/H1QEeQ0/NYf0ZkuV /6YeE3n0VD3RejGtKfsgKvHScltCWQp83lzdQRxALSeYBHASKq6Zgn9xqn3UPId18nbK 9pU5SWVWMpRm9xrz10pfAzFWOQAVyNLv2oG5kSaVW2IvpH/qIEgSjyOlt5rJGx8XWM3j ZpMVNy39Jyu96EkTk8MrP1QnqEyMMSYlC5Uh6nmCqXf/F9d31ChEIVCfC363KtelpUg/ pFrg== X-Gm-Message-State: AOAM531T9GQDx53tcqz+NecuH82cmqI2T3iQH3MsS3mg4JKbQuJLYPrl XXcSdk6Ilmm0QYWjiNnIxFAlUXhDLAt3AJbgWu8= X-Google-Smtp-Source: ABdhPJzG/VuJV5F8pJS6Ra+gky+pEjEsojhy5UQD90AX3OjZRHmfaI5ul0FRahuthV3EJmnK9XTwAw== X-Received: by 2002:adf:fc4b:0:b0:20c:efe4:19ec with SMTP id e11-20020adffc4b000000b0020cefe419ecmr2027497wrs.430.1652434789761; Fri, 13 May 2022 02:39:49 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:49 -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 v3 09/17] HID: haptic: add functions handling events Date: Fri, 13 May 2022 09:39:19 +0000 Message-Id: <20220513093927.1632262-10-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 3301bf27dfde..9b89a1f8a631 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 67096cc8c233..c26093e3773d 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 May 13 09:39:20 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848588 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 E6409C433FE for ; Fri, 13 May 2022 09:40:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379114AbiEMJkE (ORCPT ); Fri, 13 May 2022 05:40:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51862 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379028AbiEMJjx (ORCPT ); Fri, 13 May 2022 05:39:53 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id E15F52A768E for ; Fri, 13 May 2022 02:39:50 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id u3so10681071wrg.3 for ; Fri, 13 May 2022 02:39:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=VLGDt9e4tXlA7Mt8BvOVBgx9tBgjbNn1Ls+c9OEeFJ0=; b=kc/+pCQKX0fAoMH+ATG43DWyWNMpT3IW+Lk7j6oUlRKuVyrZwAwa6C5NgDXP0usiH1 42FQVkVZK6Kb8llWqyRQNewAAALW3382SLIt1JPMTFL30uBNkVkhFDq+1i5Sw41CUdcq j0IhF+E1T8RJ8uai+XdQFCaE3pDIagECrRdYmpx5FgIFERndbYMStl7RpQtA+ERm0hU3 0zv+w4bblbsZbNiS9plvHZ/9FlOI/xAu5Mc/H2lDiEVxCXXokJihxx3+wlOwuME6TSPw 4tQg3515EQ2bJE7JcsmlB/lJTRIZfuf9nQ+WR+OxWV6W5qjHPKs/ecIqr173Dx8uGILP K5jQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=VLGDt9e4tXlA7Mt8BvOVBgx9tBgjbNn1Ls+c9OEeFJ0=; b=t9h5Jbq9mtW0bDzWjd36z3e8vAMnOmMKWfmRJ7JR/KrWpeK06Y0/p/Tj9bEALamxV8 2ANUYytXpjNdvE9MPPYP3NDc9UJhfc95zl5Ilo9f2WSf7ZrNhZQKx9MycjBmVDJzb1QN Bjn/M87cGeofUk8F3RXaQHRVWlGD38DcPjWl+s6JWaBGDpeQeimHV/5HqYje97Lc2XMt XEXokBfqd9G1mJQCMYDVYttGH7TDy60eoDjzGd14WaOeukrQKdRXM20CQG4/dwKIl1Qx uiPMKVjMGYjG+iJPBTAqZo5Q5m3OIsx9MwEy+xXvkNlqapSUhJC85ILZSOHzXrbWQ7rX 3NDw== X-Gm-Message-State: AOAM531igDuAJKLUvsSAscQeDkIl2KO2340bvyp4TRcR2ul3XHO1TIe+ wLrfqCciiIXtF5L8/jrMK7pQQS6km2SuxUUSjoM= X-Google-Smtp-Source: ABdhPJxc3y+BSgKQdqJ7+4jq0CaMkPTiAEfL9nU/LCXcrIbIXhYCU8+YI+JM6jwkeG/rJu6PVdEdoQ== X-Received: by 2002:adf:df05:0:b0:20a:c402:6811 with SMTP id y5-20020adfdf05000000b0020ac4026811mr3157783wrl.275.1652434790322; Fri, 13 May 2022 02:39:50 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:50 -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 v3 10/17] Input: MT - add INPUT_MT_MAX_FORCE flags Date: Fri, 13 May 2022 09:39:20 +0000 Message-Id: <20220513093927.1632262-11-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 44fe6f2f063c..6dcef47aac71 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -197,6 +197,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; @@ -215,6 +216,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++; } @@ -244,10 +254,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 3b8580bd33c1..b23216cf9923 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 May 13 09:39:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848584 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 5118BC4332F for ; Fri, 13 May 2022 09:40:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379111AbiEMJkC (ORCPT ); Fri, 13 May 2022 05:40:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51794 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379114AbiEMJjx (ORCPT ); Fri, 13 May 2022 05:39:53 -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 41A0B2A76A3 for ; Fri, 13 May 2022 02:39:52 -0700 (PDT) Received: by mail-wr1-x434.google.com with SMTP id h16so9962019wrb.2 for ; Fri, 13 May 2022 02:39:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=0o8FpS3T+wY71hcSpCIcEDwQdqsdO67K+SEUgTCk0dA=; b=J/hnV2NN/n8X+SPLKFYwrE/NnO1akb5SU2m9feZ4Ii49/2XORIYEZAtSszndEkwvel S7xEhfbkKlZYcp5+UTTvBlo5d8ZT373IMftv9vm0VA0wUoFVeEguCp0+WFv0tU5cJek2 g3XJMlwokdHFOQFP5WsrOXVb6+PnjQq6lSGLaDA240r+75wuniS19uq+B3qRQTlaxt6W fpDdaFoI+cfSmp8aPmUCPCUxnnEqw0cL55k79SrGdUBAR9BwHPdl1gT9L++5hLSIIpOo +ESflKc3ZEtCm+cvNMHhYL5mkRJ+2/c8FHpIEbPc+22nuefdqcghopLRgq/jXARaF3e1 PEdA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=0o8FpS3T+wY71hcSpCIcEDwQdqsdO67K+SEUgTCk0dA=; b=RmabbzlJ5tCMuw5gmPvDJ9ANU6QrCzjywN29Q/Z3El3pwCY+3tPmCio5Cyw9bOaBG6 R3tITrUiu3DMOg4nNh1shcEdn0dv0gGiEhbb27m5BAA+903Y8gvmYj/y3Ubie4TOEtyy 9LnNbopUIvqhzU1xdWIZgsEL4gtm79BmNgyy7UOWEZdvEzPjvlWt98QEgbXLYn1OugAS S+zwlXA13SWQBuABDBo91ffC2oCTKDwr/o86HrjU1Kkb69Smk2/VPQo4CG74Kj06OMNj k+JVx3HrrFMm5Bne/FcEbwRpsG7tmoqqVfSnEysfUjwboH4U54ImHNu2+anf66TXlFMY Dnjw== X-Gm-Message-State: AOAM5324OLV5b29UiGkpa405zCb4WqCLFrBwRVEMXH6WvOirByFvcc5q DD/3YfLMzMobrj77Vkvn0CDgCbO7qwKEVm5wT8w= X-Google-Smtp-Source: ABdhPJzEFq/ztb+R9kp7HpduT1ULzN0dnmju++bz5ou7P6A6t3w8+yIpmnVh4ENqBwvoB86ZkquPmw== X-Received: by 2002:a05:6000:1f0f:b0:20c:87b6:df9d with SMTP id bv15-20020a0560001f0f00b0020c87b6df9dmr3345916wrb.115.1652434790847; Fri, 13 May 2022 02:39:50 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:50 -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 v3 11/17] HID: haptic: add hid_haptic_switch_mode Date: Fri, 13 May 2022 09:39:21 +0000 Message-Id: <20220513093927.1632262-12-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 9b89a1f8a631..3d26bd5d15a4 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 c26093e3773d..96757a4655ec 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 May 13 09:39:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848586 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 5C7A7C433F5 for ; Fri, 13 May 2022 09:40:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1354780AbiEMJkD (ORCPT ); Fri, 13 May 2022 05:40:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379115AbiEMJjx (ORCPT ); Fri, 13 May 2022 05:39:53 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C4FA2291CE2 for ; Fri, 13 May 2022 02:39:51 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id v12so10620690wrv.10 for ; Fri, 13 May 2022 02:39:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=jvbL12JBsvUnjK8beQwP9IotG1D9vlXC3JgbiZAuuyg=; b=5YEQGMyjgZrhyRZvmVXnqRC69A41SxRxTMAdTlg8IPsVZxO9oiPbUlCertmV3XXrJF waDkfNUtYggyyUpKsloIHtq2OcG7iSPB95rT+enmUgGXX8ba/9FBmTHu8Ogw87X08++w 8gzR7BS6Nxrw6MkhkYBaC+ivzt5j/xoLUre/kOSCMhYhTvJNzWTs+kev5IcopAKYQ/09 oI3I2HITl5lckb5YEI+8p7NI0YLX0bZM+lH3jeAzDUxDaUw2bmZoMPVC9B+NugWUlAWb ucDK5RzbKWM/9T/3vPfZi//IvYfWwUFFamBOejCqxk0PbEOxmZJPJUBykppQjh0taHBk YusA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=jvbL12JBsvUnjK8beQwP9IotG1D9vlXC3JgbiZAuuyg=; b=XJaehWE4D+8TYatnV5uwuWHGIBUTNLLOEwlD5SxVw0Qo1zWHcauPta3Ki9KtltiVma Ejk/ta2/VnXGC9OLUol6mBh2WEqYPjSXBFZbw7ePH9vlMJycxpBvV59q5RiN4tcvM3iI da4sSx3BCNDWsY6AD0CrLGoIv9URzjvUkUuqMIGG5dpbdmausk5nSv2xo4251OoH2Yzt AjzZqJ2wOK4lk4lPQG1c3XmP+s/UREyyZ4krsriBpPV7v43pEHqwhkTKRtTV0q4qwoP1 AR+hMm7zd7xuwLwWdpFNi57/4VQNMiLh5AQ94iK06BkUIQDd3gIUUFkHYhnzhbyIuyE9 mqRw== X-Gm-Message-State: AOAM533wN471Ik8qiDY4rYBddcnblqZb/jxIoPH5iRUZirvmh/0MsWKn ijsRiEdpBI8q9TLwDSh3XcVBdXITYMWtQtstMBs= X-Google-Smtp-Source: ABdhPJzCQKRCbA1VOr0B4ecjh8Qbkk5OUGA1kJKccj6ERvdSC88vI9ivWHZw62h4REmtO7W8NlCArQ== X-Received: by 2002:adf:f0c6:0:b0:20a:d31b:6 with SMTP id x6-20020adff0c6000000b0020ad31b0006mr3147243wro.162.1652434791332; Fri, 13 May 2022 02:39:51 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:51 -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 v3 12/17] HID: multitouch: add haptic multitouch support Date: Fri, 13 May 2022 09:39:22 +0000 Message-Id: <20220513093927.1632262-13-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 c892cfea3bb5..58f42489bdb1 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -768,6 +768,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 99eabfb4145b..7546c98de503 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; @@ -501,6 +506,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, @@ -831,6 +838,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: @@ -944,8 +953,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); @@ -955,6 +972,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); @@ -1104,6 +1123,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); @@ -1278,6 +1300,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; @@ -1313,6 +1339,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) { @@ -1375,6 +1402,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; } @@ -1568,6 +1600,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) { @@ -1713,6 +1756,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; @@ -1764,6 +1810,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; } @@ -1771,6 +1828,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) || @@ -1779,18 +1837,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. */ @@ -1799,6 +1870,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 May 13 09:39:23 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848585 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 752E5C43217 for ; Fri, 13 May 2022 09:40:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379108AbiEMJkD (ORCPT ); Fri, 13 May 2022 05:40:03 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51884 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379119AbiEMJjy (ORCPT ); Fri, 13 May 2022 05:39:54 -0400 Received: from mail-wr1-x42c.google.com (mail-wr1-x42c.google.com [IPv6:2a00:1450:4864:20::42c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 47FEC2A76AC for ; Fri, 13 May 2022 02:39:52 -0700 (PDT) Received: by mail-wr1-x42c.google.com with SMTP id q23so10666863wra.1 for ; Fri, 13 May 2022 02:39:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UF0MhXoHWhEuPSuC1UnVX2vTar7MPY0wNts0gUteJyw=; b=jcx6vxrqcutHlNhopZSyo6s7t36h8717vALJXtQKB9YqjGK72rqQSTNw5ozQg+8Src 9BOV9T1rnFU6qLm1364p0E2DDknBpbNjKs6UZSdDS5iQwf3kuEhNlDCpbSqmIHzx21CX oXiHOZZL0ud8r3aEBx+RGWIkrsXjbACcf4YW9yk5VGMQGNHBTQg9Kv0zFqt0w8+s55Sh zIK1NCyqcO6tgUWPGAePE3E2ua4XLDXm8jRVINxmedBfFVbodyq3hVSD2xdnbO+i3P44 SvX0E1u72o7ASBDtYyLM8ulhh/hFdcn86UBBGLT1EcGASc02sjozqKdCWQMxHAIW+irJ R4Fw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UF0MhXoHWhEuPSuC1UnVX2vTar7MPY0wNts0gUteJyw=; b=nxibnuYngQuaOcdScb/afBPy3a2e/LrapdInsjSVJs5ZRSDXN2nRPXEjFx8OFgJb1w Bq0Z6axdV01LAUb1+cFjzyST+scshkkFXxv37lRvknjGjc2h9Ah1zRM3gmjVeqSA5AwF wPOmikPxDHrNNh8/NteKQDKl+nVOu5Xd8Ybol52II1ae61JpXw2wJXqLYOs4b2DFWp2y jXxD/CvfsxSAFDEou++OW7QOgPi39Yijb55TzBZIUZLaYcRhNFHbiBncjvnfAKoHHAca J81invHXi/gU1TtDZsCgHI7r5o1bn3wjKO1uBG+oQ+kC8vBhWMpTtb9/b5wnDXT5hcTP TDsw== X-Gm-Message-State: AOAM531WsUaLEDiy/Y/h/+KHlw95HcxS6/GfedN75zH0qSJJc19hdtJr X2ehWrWtfFb7yBdICLAqIjHHqo5k9m0haT2gVhc= X-Google-Smtp-Source: ABdhPJzsD6qJsXi0BBA2n7uGdOH9sMwvXYOUfHOneMr2nAUiZBK30/YcgL0AJtlgZ88eEqyz8XEPrw== X-Received: by 2002:a5d:6d0b:0:b0:20c:4ecb:1113 with SMTP id e11-20020a5d6d0b000000b0020c4ecb1113mr3075828wrq.203.1652434791850; Fri, 13 May 2022 02:39:51 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:51 -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 v3 13/17] Input: introduce EVIOCFF(TAKE|RELEASE)CONTROL Date: Fri, 13 May 2022 09:39:23 +0000 Message-Id: <20220513093927.1632262-14-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 95f90699d2b1..6d25eb19e28e 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 1a9a5401acb5..d6b76a479fc2 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 49790c1bd2c4..39091730c2fc 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 ccf43a21d43d..cce37336ab38 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -178,6 +178,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 May 13 09:39:24 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848590 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 DE71CC433F5 for ; Fri, 13 May 2022 09:40:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241657AbiEMJkG (ORCPT ); Fri, 13 May 2022 05:40:06 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1353324AbiEMJjy (ORCPT ); Fri, 13 May 2022 05:39:54 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D73912A76A1 for ; Fri, 13 May 2022 02:39:52 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id w4so10611534wrg.12 for ; Fri, 13 May 2022 02:39:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JMet90BJ0GvhDF9Jhlj70gOV/8yFnhrxXYWAcJMC/0Q=; b=CtNyAGEHfHRORlzMyY2rlFeHwD8EBC0hNNP2aosjpwM5zxuI/GeGbHotlnDzrw4K79 b3HEZZAXhtvz6NvLNZqXaEqsxLHJ8SO2++99UMt/uSuOxVSI20/6hHpV3C46+0a8djWD eiM9vOUjPOKUhp9ZCWV3l+FgJf7oZ6A91lTF/XRB7zJoLi9zwd85XgDoHpro/WLDonwb cqz8Q4Pl4rxVWU5Xy0uFjKT/5mHf+nhv+jrzGLBM7hqL41SKPn4hYgi000klOgu7k/wA aQYLg5960QiTIDoG+mngG3bnngw+VfUj5pln0ahtjBRZrBXYY9YqC0CZ3N02+y+MhuDV 6glg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JMet90BJ0GvhDF9Jhlj70gOV/8yFnhrxXYWAcJMC/0Q=; b=Ykka/Os+2J5zD9qZc/fTVUeTh7250hcMwek6RwMjfmhqcfRYGkIp6MW2q9lTNUulrs n8g54psL+hp7ofnOu1UEWwzcP58RWVqZ+tIPC+UNIbXzJllxaBSdeXVmZf6I73Fi6mUW brsZYgxvrHHwDoTgAbXEhfckg/wg1dNNbOrOGQgQljiwBQmUjIKB2+vxPRVtPhRG+qUR 5BRTwYJtNKl3rnHygxQzIFKjimPkj728x6mWSOhSfeoDTVg8VpuJzHbHfnHxbZlfzfBU LkW6DrJWbOxua3I/y80F/MFLZjRO42l6XqK1fceW3exeHK3iJBlHJcxsQPPIOL+hSQr0 zfVA== X-Gm-Message-State: AOAM531kQQdjn7nw/mGU7YJ1mDpiF6rF5KTwsjrV4RE5myP/1sHHFOsR 6fowV8n8TV37a/RqBtUbaPuqyK8LHFJiLzOPCUE= X-Google-Smtp-Source: ABdhPJwdd7NYrXdXum7EfmD2TiuBjeAHTek/u+/kQouMMQ/9f5Ypl6+DL4k1a8w/L0YzmkzRxJd0wg== X-Received: by 2002:a5d:64e7:0:b0:20c:5b42:a93c with SMTP id g7-20020a5d64e7000000b0020c5b42a93cmr3210308wri.619.1652434792454; Fri, 13 May 2022 02:39:52 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:52 -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 v3 14/17] HID: haptic: add hid_haptic_change_control Date: Fri, 13 May 2022 09:39:24 +0000 Message-Id: <20220513093927.1632262-15-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 3d26bd5d15a4..4b3ad5168fbb 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 May 13 09:39:25 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848583 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 67C62C433EF for ; Fri, 13 May 2022 09:40:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379101AbiEMJkB (ORCPT ); Fri, 13 May 2022 05:40:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51838 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379123AbiEMJjz (ORCPT ); Fri, 13 May 2022 05:39:55 -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 48982291CF2 for ; Fri, 13 May 2022 02:39:54 -0700 (PDT) Received: by mail-wr1-x435.google.com with SMTP id a5so6848543wrp.7 for ; Fri, 13 May 2022 02:39:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=flKb5XvgSjC4TVDtKYTkzDo0feCAfP5GPsMQQeLy88U=; b=RlMOJzNkCNkpZnaJgPcdeG2gPHko+hufgMruirJ7LVWxJrLQLv7cIRnTDW9rgmxgt5 WIsbeKRKpwXoc3KUyD8hcbGtNptaDgS3ay/igXCyd5lkg637qkr6r2RpPL3sRFYgfS39 gjjgWx4HQKimwyLvK7QXGIv118RqFBuEPK4TMwwA1f8YptJF4tT9eye12T6z3boa5WHR W0Hy6fg6Pm39aNlcT2foAhO1hy2hFYlgykkB9OY3v5rpkORMvt8YxB0rCN2hlmONPGQh fRTgGQ9LT1s0O+I0toAzh7eOYGkK/xIgDxOec0Jnw0p8rzgYLJx5sDlKv1gnHGlQhose va8Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=flKb5XvgSjC4TVDtKYTkzDo0feCAfP5GPsMQQeLy88U=; b=oBatjoKnePHdit2wpRkeKP8LrWxu9gGlzpjXQgFeyHGJ6AbFPqadowuGQtBv+YKOoQ jchjwt8oNme8LD+xVk/ADhXTSiuBOvXcVDTa7Xq71h46RtDMcbrMciKO8pjINolF/5Fj 6rmDRmOLgh1jaldJd99T0SA3ks9e6unpgJKecKpsC8WCYgI7GAdI4nGnL4U1hHtOVF+A indFvry7cV/wfpLgkhuqL0W+bREJP1Yc8ROxh3Y+NyVwj3xnQVSv4lAUN9W9v2L/Pb43 43IaXvHkrPBal6GERjECVQUmes9EfiC0oKowcnXyrGny3H4wygNk8YSxbznP3EdZVvn6 VBNA== X-Gm-Message-State: AOAM531pXn0/69J8UoAtE55uwJ9KelHeRC+4cskoWCqoxz9dkF8UTw1R ii1nvvetVQ80F3XMV3IAoE67mOI+ULjK/BITm7o= X-Google-Smtp-Source: ABdhPJwvp/O4HH0Cfa9E0w5mhfjw6pgWsHqsn3MlMhRWDvcwydSz2elgcVGE2STTjoTY7kG1teTKkw== X-Received: by 2002:a05:6000:1283:b0:20a:e149:a9ab with SMTP id f3-20020a056000128300b0020ae149a9abmr3102175wrx.330.1652434792921; Fri, 13 May 2022 02:39:52 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:52 -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 v3 15/17] HID: add HID device reset callback Date: Fri, 13 May 2022 09:39:25 +0000 Message-Id: <20220513093927.1632262-16-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 c078f09a2318..37f134a3d9cb 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 3f5899c62821..9db9b7133f1a 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 May 13 09:39:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848587 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 723FCC433EF for ; Fri, 13 May 2022 09:40:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379119AbiEMJkE (ORCPT ); Fri, 13 May 2022 05:40:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51806 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379122AbiEMJjy (ORCPT ); Fri, 13 May 2022 05:39:54 -0400 Received: from mail-wr1-x42e.google.com (mail-wr1-x42e.google.com [IPv6:2a00:1450:4864:20::42e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CBA7E291CDE for ; Fri, 13 May 2022 02:39:53 -0700 (PDT) Received: by mail-wr1-x42e.google.com with SMTP id v12so10620690wrv.10 for ; Fri, 13 May 2022 02:39:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=sYXD96b2plf8NyekUlKZlUyJ7fPvj/lz8no+CsIMAkU=; b=KnlKzq2K9WdhkuhyfLU3VGfvHRS8SkgXoWViG7EQ+rtW3QfnQQ92NzNGU2NITBrZIz h7UfgrPr4DQ/IPTzpKvE5id6eWXbCbi5MlVKylj5BohtVyo+pC3yA1Lg6MFn3Wqw12CF /5H/JlXyQe0o3U6iPARsx5bBEYB95fIrTcMcf+p0hVinH89KC+rl9pkNve6W/CVkw4tk bIjpVN2VFcL8CFOTh8oMTSqiKSoLEnOvffYt8Kimc3kBXuYY2+w+JLdBVlRhpxH6X5e1 9RbmW2oqU1ys2AHRtKfK5NBibD5aMd0tIY8daDX/3mLHyeI2ciaTynMiCFhZLxqM/cAX eBAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=sYXD96b2plf8NyekUlKZlUyJ7fPvj/lz8no+CsIMAkU=; b=YLAxsGRFuIntCVcAKCzrCW90lwhRIBW/To8AuObUCVTxFfoB23VmiakzDUle9vkO12 9o29Of4/3fr3o3Hwib9gYNl2qOSKzbRyRfzsi+vt97seAoaRvArmnzfZY3SNR0H6RVQp etnHf3C/P+jA708t5oeLUm+2OIwtsYMu0aOKockQ4kKwXZAoGjaUFr4WwBA873weXM5p l9DSMZ8//p0/dMriInf/rU+E8gDwh5GKnliRj2zxvOYa6OdSuVoZ5zAp+S/L1Vd5fzjm 5PvNsmMbhgD/zY5/vATKQPZmY7c1baCKPe11SM3tfhc+gxSeEMnAO85e7Ljxx1auNKRD Zggw== X-Gm-Message-State: AOAM533VDuGUadyZslFYU6VbRxd8oLIsEHPBe8U22YuJLJ1AIZ3ddo+c yU3ucPal1YiwAGTqXfPS7rYvA0ukrbVhTU0Mig0= X-Google-Smtp-Source: ABdhPJzPlH2nTQObcPMPxoVIPoDkCXJelJI7Qup2k4wFM29WlwHbWIdbLZcm6pA1RfZ/VQVtcCVaKw== X-Received: by 2002:a05:6000:c:b0:20a:df2e:2c38 with SMTP id h12-20020a056000000c00b0020adf2e2c38mr3058716wrx.481.1652434793428; Fri, 13 May 2022 02:39:53 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:53 -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 v3 16/17] HID: haptic: implement HID haptic reset callback Date: Fri, 13 May 2022 09:39:26 +0000 Message-Id: <20220513093927.1632262-17-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 | 7 +++++++ drivers/hid/hid-haptic.h | 5 +++++ drivers/hid/hid-multitouch.c | 15 +++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/drivers/hid/hid-haptic.c b/drivers/hid/hid-haptic.c index 4b3ad5168fbb..a8d89a9235e7 100644 --- a/drivers/hid/hid-haptic.c +++ b/drivers/hid/hid-haptic.c @@ -226,6 +226,13 @@ static void switch_mode(struct hid_device *hdev, struct hid_haptic_device *hapti haptic->mode = mode; } +void hid_haptic_reset(struct hid_device *hdev, struct hid_haptic_device *haptic) +{ + if (haptic->press_ordinal_cur && haptic->release_ordinal_cur) + switch_mode(hdev, haptic, HID_HAPTIC_MODE_KERNEL); +} +EXPORT_SYMBOL_GPL(hid_haptic_reset); + #ifdef CONFIG_PM void hid_haptic_resume(struct hid_device *hdev, struct hid_haptic_device *haptic) { diff --git a/drivers/hid/hid-haptic.h b/drivers/hid/hid-haptic.h index 96757a4655ec..03e657094dae 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); +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 +121,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 7546c98de503..2d1b8c400c2f 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1877,6 +1877,20 @@ 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; + + 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); @@ -2284,6 +2298,7 @@ static struct hid_driver mt_driver = { #ifdef CONFIG_PM .suspend = mt_suspend, .reset_resume = mt_reset_resume, + .reset = mt_reset, .resume = mt_resume, #endif }; From patchwork Fri May 13 09:39:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Angela Czubak X-Patchwork-Id: 12848589 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 5796CC4332F for ; Fri, 13 May 2022 09:40:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379028AbiEMJkF (ORCPT ); Fri, 13 May 2022 05:40:05 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51824 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379124AbiEMJjz (ORCPT ); Fri, 13 May 2022 05:39:55 -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 4B9F829ED0B for ; Fri, 13 May 2022 02:39:54 -0700 (PDT) Received: by mail-wr1-x431.google.com with SMTP id d5so10661583wrb.6 for ; Fri, 13 May 2022 02:39:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=n5UYlbJE7KgtvbDSeSWBvvZodyAZpSzAXxwslYd2ufI=; b=uxxj5DQDidcKj90trqyhWbc/X5ptRL3GfesFqOEeapFNxYDqnncZvcrve3ite+18M3 THFbhZBZ6Q/U3Foi4w37bmH6pgWXPF2XYdQdkQrwVST7+3HzPd7Al7JEoCodT3Ch9JR4 ke8FXrxTsLX0se2LOyCiR23QJZc/hx2QjgmNcTFAV7MHbD3YkQxQ8WC2jTvHzxRrQ5k1 MUqqwwvEvUJL9oAALlygo+ew0nP3VA32W6/qOTOYya4KhJtAPacVzoJA1Sicofn7D1bE aPcD+HaLyejGKYtWCE5FDmzFsCStU/8eWyhzu9wtXhqeQbaRntVZyBMv2xWN592AoQ3d 2wIA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=n5UYlbJE7KgtvbDSeSWBvvZodyAZpSzAXxwslYd2ufI=; b=WNHpZ2cnDTgPk/y94XTIQrml4Wt/Zw85TXr4kTUdnCaGf6LE+G49NSK0L+0rtDGcoj SDVl2x6XQOPEFM2JFZ4PfaGJNz3lRLrHBZtilyRHtEeS9aVtcAoOefXmmLIWo+HqyIRB 1pFNJ8u+saW6dYfKKt38kSpp87dG2pIoieOGflB3Fmn6MUKclV1odHtMQOP5F/BywXxH 4xv0AGq7ELjiG8+wnM8ZNRGNM6lU4jtk7/8nRWfHtLKV/DfbNYOHz3dz3srsxjcqy303 StIUF0Y/TDrp5Ru1YQVchKYgyYmr449Q5Aicr5MUQmqwZVQ9TYCGW1+/iSUhEjtRhqXs F+Qg== X-Gm-Message-State: AOAM530S4k5/DC8GC9eOeggNy93mcQN4ttNgLBVFpu1JF6XGcZ01s2DD ncIx+LHFWLqiUMjb77XEgXRbG7jByr+ckznXrRU= X-Google-Smtp-Source: ABdhPJxFce/UR4H8Z6+9mFQVyIRakkrSgASOxmC0i2OiWiIm4XTH/Q8wCe67WsEeo4vfihqbpc6c9w== X-Received: by 2002:a5d:47a6:0:b0:20c:5f07:2c5 with SMTP id 6-20020a5d47a6000000b0020c5f0702c5mr3089421wrb.397.1652434793864; Fri, 13 May 2022 02:39:53 -0700 (PDT) Received: from aczubak.c.googlers.com.com (88.140.78.34.bc.googleusercontent.com. [34.78.140.88]) by smtp.gmail.com with ESMTPSA id l5-20020adfa385000000b0020ce015ed48sm1631404wrb.103.2022.05.13.02.39.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 13 May 2022 02:39:53 -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 v3 17/17] HID: multitouch: Add lid handler for touchpad on Redrix chromebook Date: Fri, 13 May 2022 09:39:27 +0000 Message-Id: <20220513093927.1632262-18-acz@semihalf.com> X-Mailer: git-send-email 2.36.0.550.gb090851708-goog In-Reply-To: <20220513093927.1632262-1-acz@semihalf.com> References: <20220513093927.1632262-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 2d1b8c400c2f..73e47fe7d773 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); @@ -394,6 +405,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) @@ -548,6 +644,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) { @@ -571,6 +744,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; @@ -1767,6 +1942,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; @@ -1830,12 +2009,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); @@ -1849,7 +2034,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); @@ -1868,7 +2056,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); @@ -1883,7 +2073,9 @@ static int mt_reset(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_reset(hdev, haptic); @@ -1899,6 +2091,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); } /* @@ -2302,4 +2496,28 @@ static struct hid_driver mt_driver = { .resume = mt_resume, #endif }; -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);