From patchwork Fri Nov 26 13:01:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tero Kristo X-Patchwork-Id: 517248 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 E5EB7C433F5 for ; Fri, 26 Nov 2021 13:06:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240257AbhKZNJ1 (ORCPT ); Fri, 26 Nov 2021 08:09:27 -0500 Received: from mga18.intel.com ([134.134.136.126]:38672 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236270AbhKZNH1 (ORCPT ); Fri, 26 Nov 2021 08:07:27 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10179"; a="222532954" X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="222532954" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:01:57 -0800 X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="498395546" Received: from asaechnx-mobl2.ccr.corp.intel.com (HELO tkristo-desk.intel.com) ([10.249.34.152]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:01:55 -0800 From: Tero Kristo To: linux-input@vger.kernel.org, benjamin.tissoires@redhat.com, jikos@kernel.org, mika.westerberg@linux.intel.com, tero.kristo@linux.intel.com Cc: linux-kernel@vger.kernel.org, dmitry.torokhov@gmail.com, peter.hutterer@who-t.net Subject: [RFCv2 1/8] HID: Add map_msc() to avoid boilerplate code Date: Fri, 26 Nov 2021 15:01:34 +0200 Message-Id: <20211126130141.1811848-2-tero.kristo@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211126130141.1811848-1-tero.kristo@linux.intel.com> References: <20211126130141.1811848-1-tero.kristo@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org From: Mika Westerberg Since we are going to have more MSC events too, add map_msc() that can be used to fill in necessary fields and avoid boilerplate code. Signed-off-by: Mika Westerberg --- drivers/hid/hid-input.c | 6 ++---- include/linux/hid.h | 4 ++++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 2c72ce4147b1..39ebedb2323b 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -52,6 +52,7 @@ static const struct { #define map_rel(c) hid_map_usage(hidinput, usage, &bit, &max, EV_REL, (c)) #define map_key(c) hid_map_usage(hidinput, usage, &bit, &max, EV_KEY, (c)) #define map_led(c) hid_map_usage(hidinput, usage, &bit, &max, EV_LED, (c)) +#define map_msc(c) hid_map_usage(hidinput, usage, &bit, &max, EV_MSC, (c)) #define map_abs_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ &max, EV_ABS, (c)) @@ -872,10 +873,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x5b: /* TransducerSerialNumber */ case 0x6e: /* TransducerSerialNumber2 */ - usage->type = EV_MSC; - usage->code = MSC_SERIAL; - bit = input->mscbit; - max = MSC_MAX; + map_msc(MSC_SERIAL); break; default: goto unknown; diff --git a/include/linux/hid.h b/include/linux/hid.h index e95800bab56a..96eaca0d5322 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -766,6 +766,10 @@ static inline void hid_map_usage(struct hid_input *hidinput, bmap = input->ledbit; limit = LED_MAX; break; + case EV_MSC: + bmap = input->mscbit; + limit = MSC_MAX; + break; } if (unlikely(c > limit || !bmap)) { From patchwork Fri Nov 26 13:01:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tero Kristo X-Patchwork-Id: 517247 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 B88FFC433EF for ; Fri, 26 Nov 2021 13:08:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234351AbhKZNLO (ORCPT ); Fri, 26 Nov 2021 08:11:14 -0500 Received: from mga18.intel.com ([134.134.136.126]:38769 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231215AbhKZNJO (ORCPT ); Fri, 26 Nov 2021 08:09:14 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10179"; a="222532972" X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="222532972" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:02:03 -0800 X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="498395589" Received: from asaechnx-mobl2.ccr.corp.intel.com (HELO tkristo-desk.intel.com) ([10.249.34.152]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:02:01 -0800 From: Tero Kristo To: linux-input@vger.kernel.org, benjamin.tissoires@redhat.com, jikos@kernel.org, mika.westerberg@linux.intel.com, tero.kristo@linux.intel.com Cc: linux-kernel@vger.kernel.org, dmitry.torokhov@gmail.com, peter.hutterer@who-t.net Subject: [RFCv2 3/8] HID: core: Add support for USI style events Date: Fri, 26 Nov 2021 15:01:36 +0200 Message-Id: <20211126130141.1811848-4-tero.kristo@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211126130141.1811848-1-tero.kristo@linux.intel.com> References: <20211126130141.1811848-1-tero.kristo@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org Add support for Universal Stylus Interface (USI) style events to the HID core and input layers. Signed-off-by: Tero Kristo --- drivers/hid/hid-input.c | 18 ++++++++++++++++++ include/linux/mod_devicetable.h | 2 +- include/uapi/linux/hid.h | 10 ++++++++++ include/uapi/linux/input-event-codes.h | 22 ++++++++++++++-------- 4 files changed, 43 insertions(+), 9 deletions(-) diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 73c2edda742e..b428ee9b4d9b 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -829,6 +829,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel } break; + case 0x38: /* Transducer Index */ + map_msc(MSC_PEN_ID); + break; + case 0x3b: /* Battery Strength */ hidinput_setup_battery(device, HID_INPUT_REPORT, field, false); usage->type = EV_PWR; @@ -876,6 +880,20 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel map_msc(MSC_SERIAL); break; + case 0x5c: map_msc(MSC_PEN_COLOR); break; + case 0x5e: map_msc(MSC_PEN_LINE_WIDTH); break; + + case 0x70: + case 0x71: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + map_msc(MSC_PEN_LINE_STYLE); + break; + default: goto unknown; } break; diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h index ae2e75d15b21..4ff40be7676b 100644 --- a/include/linux/mod_devicetable.h +++ b/include/linux/mod_devicetable.h @@ -322,7 +322,7 @@ struct pcmcia_device_id { #define INPUT_DEVICE_ID_KEY_MAX 0x2ff #define INPUT_DEVICE_ID_REL_MAX 0x0f #define INPUT_DEVICE_ID_ABS_MAX 0x3f -#define INPUT_DEVICE_ID_MSC_MAX 0x07 +#define INPUT_DEVICE_ID_MSC_MAX 0x09 #define INPUT_DEVICE_ID_LED_MAX 0x0f #define INPUT_DEVICE_ID_SND_MAX 0x07 #define INPUT_DEVICE_ID_FF_MAX 0x7f diff --git a/include/uapi/linux/hid.h b/include/uapi/linux/hid.h index 861bfbbfc565..60ef9b615a1a 100644 --- a/include/uapi/linux/hid.h +++ b/include/uapi/linux/hid.h @@ -255,6 +255,7 @@ #define HID_DG_TOUCH 0x000d0033 #define HID_DG_UNTOUCH 0x000d0034 #define HID_DG_TAP 0x000d0035 +#define HID_DG_TRANSDUCER_INDEX 0x000d0038 #define HID_DG_TABLETFUNCTIONKEY 0x000d0039 #define HID_DG_PROGRAMCHANGEKEY 0x000d003a #define HID_DG_BATTERYSTRENGTH 0x000d003b @@ -267,6 +268,15 @@ #define HID_DG_BARRELSWITCH 0x000d0044 #define HID_DG_ERASER 0x000d0045 #define HID_DG_TABLETPICK 0x000d0046 +#define HID_DG_PEN_COLOR 0x000d005c +#define HID_DG_PEN_LINE_WIDTH 0x000d005e +#define HID_DG_PEN_LINE_STYLE 0x000d0070 +#define HID_DG_PEN_LINE_STYLE_INK 0x000d0072 +#define HID_DG_PEN_LINE_STYLE_PENCIL 0x000d0073 +#define HID_DG_PEN_LINE_STYLE_HIGHLIGHTER 0x000d0074 +#define HID_DG_PEN_LINE_STYLE_CHISEL_MARKER 0x000d0075 +#define HID_DG_PEN_LINE_STYLE_BRUSH 0x000d0076 +#define HID_DG_PEN_LINE_STYLE_NO_PREFERENCE 0x000d0077 #define HID_CP_CONSUMERCONTROL 0x000c0001 #define HID_CP_NUMERICKEYPAD 0x000c0002 diff --git a/include/uapi/linux/input-event-codes.h b/include/uapi/linux/input-event-codes.h index 225ec87d4f22..98295f71941a 100644 --- a/include/uapi/linux/input-event-codes.h +++ b/include/uapi/linux/input-event-codes.h @@ -901,14 +901,20 @@ * Misc events */ -#define MSC_SERIAL 0x00 -#define MSC_PULSELED 0x01 -#define MSC_GESTURE 0x02 -#define MSC_RAW 0x03 -#define MSC_SCAN 0x04 -#define MSC_TIMESTAMP 0x05 -#define MSC_MAX 0x07 -#define MSC_CNT (MSC_MAX+1) +#define MSC_SERIAL 0x00 +#define MSC_PULSELED 0x01 +#define MSC_GESTURE 0x02 +#define MSC_RAW 0x03 +#define MSC_SCAN 0x04 +#define MSC_TIMESTAMP 0x05 +/* USI Pen events */ +#define MSC_PEN_ID 0x06 +#define MSC_PEN_COLOR 0x07 +#define MSC_PEN_LINE_WIDTH 0x08 +#define MSC_PEN_LINE_STYLE 0x09 +/* TODO: Add USI diagnostic & battery events too */ +#define MSC_MAX 0x09 +#define MSC_CNT (MSC_MAX + 1) /* * LEDs From patchwork Fri Nov 26 13:01:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tero Kristo X-Patchwork-Id: 517246 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 D7434C433EF for ; Fri, 26 Nov 2021 13:08:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232000AbhKZNLc (ORCPT ); Fri, 26 Nov 2021 08:11:32 -0500 Received: from mga18.intel.com ([134.134.136.126]:38673 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236464AbhKZNJb (ORCPT ); Fri, 26 Nov 2021 08:09:31 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10179"; a="222532991" X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="222532991" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:02:08 -0800 X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="498395662" Received: from asaechnx-mobl2.ccr.corp.intel.com (HELO tkristo-desk.intel.com) ([10.249.34.152]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:02:06 -0800 From: Tero Kristo To: linux-input@vger.kernel.org, benjamin.tissoires@redhat.com, jikos@kernel.org, mika.westerberg@linux.intel.com, tero.kristo@linux.intel.com Cc: linux-kernel@vger.kernel.org, dmitry.torokhov@gmail.com, peter.hutterer@who-t.net Subject: [RFCv2 5/8] HID: core: map USI pen style reports directly Date: Fri, 26 Nov 2021 15:01:38 +0200 Message-Id: <20211126130141.1811848-6-tero.kristo@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211126130141.1811848-1-tero.kristo@linux.intel.com> References: <20211126130141.1811848-1-tero.kristo@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org USI pen style reports have funky layout, so don't try to parse them. Instead, handle them identically to variable report items. Signed-off-by: Tero Kristo --- drivers/hid/hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 525dbc59633f..315dc2b8ecbb 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1567,8 +1567,8 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, } for (n = 0; n < count; n++) { - - if (HID_MAIN_ITEM_VARIABLE & field->flags) { + if (HID_MAIN_ITEM_VARIABLE & field->flags || + field->logical == HID_DG_PEN_LINE_STYLE) { hid_process_event(hid, field, &field->usage[n], value[n], interrupt); continue; } From patchwork Fri Nov 26 13:01:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tero Kristo X-Patchwork-Id: 517245 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 F2DDDC433EF for ; Fri, 26 Nov 2021 13:10:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239218AbhKZNN2 (ORCPT ); Fri, 26 Nov 2021 08:13:28 -0500 Received: from mga18.intel.com ([134.134.136.126]:38672 "EHLO mga18.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239337AbhKZNL2 (ORCPT ); Fri, 26 Nov 2021 08:11:28 -0500 X-IronPort-AV: E=McAfee;i="6200,9189,10179"; a="222533009" X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="222533009" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:02:14 -0800 X-IronPort-AV: E=Sophos;i="5.87,266,1631602800"; d="scan'208";a="498395701" Received: from asaechnx-mobl2.ccr.corp.intel.com (HELO tkristo-desk.intel.com) ([10.249.34.152]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Nov 2021 05:02:11 -0800 From: Tero Kristo To: linux-input@vger.kernel.org, benjamin.tissoires@redhat.com, jikos@kernel.org, mika.westerberg@linux.intel.com, tero.kristo@linux.intel.com Cc: linux-kernel@vger.kernel.org, dmitry.torokhov@gmail.com, peter.hutterer@who-t.net Subject: [RFCv2 7/8] samples: hid: add new hid-usi sample Date: Fri, 26 Nov 2021 15:01:40 +0200 Message-Id: <20211126130141.1811848-8-tero.kristo@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211126130141.1811848-1-tero.kristo@linux.intel.com> References: <20211126130141.1811848-1-tero.kristo@linux.intel.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-input@vger.kernel.org HID-usi sample adds support for writing USI pen variables. When the sample is run, it creates a unix fifo under /tmp/usi, which can be written with " set ", where param is in [color,width,style], and val is an integer value for the parameter. Signed-off-by: Tero Kristo --- samples/bpf/Makefile | 3 + samples/bpf/hid_usi.h | 21 ++++ samples/bpf/hid_usi_kern.c | 225 +++++++++++++++++++++++++++++++++ samples/bpf/hid_usi_user.c | 247 +++++++++++++++++++++++++++++++++++++ 4 files changed, 496 insertions(+) create mode 100644 samples/bpf/hid_usi.h create mode 100644 samples/bpf/hid_usi_kern.c create mode 100644 samples/bpf/hid_usi_user.c diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile index 11f6f0cfab9e..6f45f6048979 100644 --- a/samples/bpf/Makefile +++ b/samples/bpf/Makefile @@ -62,6 +62,7 @@ tprogs-y += xdp_monitor tprogs-y += hid_mouse tprogs-y += hid_surface_dial +tprogs-y += hid_usi # Libbpf dependencies LIBBPF_SRC = $(TOOLS_PATH)/lib/bpf @@ -129,6 +130,7 @@ xdp_redirect-objs := xdp_redirect_user.o $(XDP_SAMPLE) xdp_monitor-objs := xdp_monitor_user.o $(XDP_SAMPLE) hid_mouse-objs := hid_mouse_user.o hid_surface_dial-objs := hid_surface_dial_user.o +hid_usi-objs := hid_usi_user.o # Tell kbuild to always build the programs always-y := $(tprogs-y) @@ -188,6 +190,7 @@ always-y += hbm_edt_kern.o always-y += xdpsock_kern.o always-y += hid_mouse_kern.o always-y += hid_surface_dial_kern.o +always-y += hid_usi_kern.o ifeq ($(ARCH), arm) # Strip all except -D__LINUX_ARM_ARCH__ option needed to handle linux diff --git a/samples/bpf/hid_usi.h b/samples/bpf/hid_usi.h new file mode 100644 index 000000000000..90803375d9c1 --- /dev/null +++ b/samples/bpf/hid_usi.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * Copyright(c) 2021 Intel Corporation. + */ + +#ifndef HID_USI_H_ +#define HID_USI_H_ + +#include + +enum { + USI_PEN_ID = 0, + USI_PEN_IN_RANGE, + USI_PEN_TOUCHING, + USI_PEN_COLOR, + USI_PEN_LINE_WIDTH, + USI_PEN_LINE_STYLE, + USI_NUM_PARAMS +}; + +#endif /* HID_USI_H */ diff --git a/samples/bpf/hid_usi_kern.c b/samples/bpf/hid_usi_kern.c new file mode 100644 index 000000000000..8b3c300f7bb2 --- /dev/null +++ b/samples/bpf/hid_usi_kern.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright(c) 2021 Intel Corporation. */ +#include +#include +#include +#include +#include + +#include "hid_usi.h" + +static const char param_names[USI_NUM_PARAMS][6] = { + "id", + "flags", + "color", + "width", + "style", +}; + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, 4096); +} ringbuf SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, int); + __type(value, int); + __uint(max_entries, USI_NUM_PARAMS); +} cache SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __type(key, int); + __type(value, int); + __uint(max_entries, USI_NUM_PARAMS); +} wr_cache SEC(".maps"); + +struct rep_data { + int offset; + int size; + int idx; +}; + +static struct rep_data inputs[USI_NUM_PARAMS]; +static struct rep_data features[USI_NUM_PARAMS]; + +SEC("hid/raw_event") +int hid_raw_event(struct hid_bpf_ctx *ctx) +{ + u32 i; + u32 tmp; + int val; + int *wrc, *c; + u8 *buf; + u32 flags = 0; + int offset; + int size; + int in_range; + int touching; + bool cache_valid; + + if (ctx->event.data[0] != inputs[USI_PEN_IN_RANGE].idx) + return 0; + + in_range = bpf_hid_get_data(ctx, inputs[USI_PEN_IN_RANGE].offset, + inputs[USI_PEN_IN_RANGE].size); + touching = bpf_hid_get_data(ctx, inputs[USI_PEN_TOUCHING].offset, + inputs[USI_PEN_TOUCHING].size); + + bpf_printk("flags: in_range=%d, touching=%d", in_range, touching); + + if (!touching && cache_valid) { + for (i = USI_PEN_COLOR; i < USI_NUM_PARAMS; i++) { + val = 0; + + /* + * Make a local copy of i so that we can get a + * pointer reference to it. i itself must remain + * inside a register so that BPF verifier can + * calculate its value properly. + */ + tmp = i; + bpf_map_update_elem(&wr_cache, &tmp, &val, 0); + bpf_map_update_elem(&cache, &tmp, &val, 0); + } + cache_valid = false; + } + + if (!touching) + return 0; + + for (i = USI_PEN_COLOR; i < USI_NUM_PARAMS; i++) { + offset = inputs[i].offset; + size = inputs[i].size; + val = bpf_hid_get_data(ctx, offset, size); + + /* + * Again, make a local copy of i which we can refer via a + * pointer to satisfy BPF verifier. + */ + tmp = i; + + wrc = bpf_map_lookup_elem(&wr_cache, &tmp); + c = bpf_map_lookup_elem(&cache, &tmp); + if (!wrc || !c) + continue; + + bpf_printk("raw[%d]: %s = %02x", i, param_names[i], val); + bpf_printk(" (c=%02x, wr=%02x)", *c, *wrc); + + if (*wrc != *c) { + val = *wrc; + + buf = bpf_ringbuf_reserve(&ringbuf, 16, 0); + if (!buf) + continue; + + buf[0] = features[i].idx; + buf[1] = 1; + buf[2] = val; + + bpf_hid_raw_request(ctx, buf, 3, + HID_FEATURE_REPORT, + HID_REQ_SET_REPORT); + + bpf_ringbuf_discard(buf, 0); + } + + if (val != *c && !cache_valid) { + bpf_map_update_elem(&cache, &tmp, &val, 0); + bpf_map_update_elem(&wr_cache, &tmp, &val, 0); + cache_valid = true; + } else { + bpf_hid_set_data(ctx, offset, size, *c); + } + } + + return 0; +} + +SEC("hid/event") +int set_haptic(struct hid_bpf_ctx *ctx) +{ + return 0; +} + +static void process_tag(struct hid_bpf_ctx *ctx, struct rep_data *data, + struct hid_bpf_parser *parser, u64 *idx) +{ + u32 i; + int id; + u32 offset; + + for (i = 0; i < parser->local.usage_index && i < 16; i++) { + offset = parser->report.current_offset + + i * parser->global.report_size; + + switch (parser->local.usage[i]) { + case HID_DG_PEN_COLOR: + id = USI_PEN_COLOR; + break; + case HID_DG_PEN_LINE_WIDTH: + id = USI_PEN_LINE_WIDTH; + break; + case HID_DG_PEN_LINE_STYLE_INK: + id = USI_PEN_LINE_STYLE; + break; + case HID_DG_INRANGE: + if (parser->local.usage_index == 1) + continue; + + id = USI_PEN_IN_RANGE; + break; + case HID_DG_TIPSWITCH: + if (parser->local.usage_index == 1) + continue; + + id = USI_PEN_TOUCHING; + break; + default: + continue; + } + + data[id].offset = offset + 8; + data[id].size = parser->global.report_size; + data[id].idx = parser->report.id; + + bpf_printk("parsed id=%d, offset=%d, idx=%d", + id, data[id].offset, data[id].idx); + } +} + +static u64 process_hid_rdesc_item(struct hid_bpf_ctx *ctx, + struct hid_bpf_parser *parser, u64 *idx, + void *data) +{ + struct hid_bpf_item *item = &parser->item; + + switch (item->type) { + case HID_ITEM_TYPE_MAIN: + if (item->tag == HID_MAIN_ITEM_TAG_INPUT) + process_tag(ctx, inputs, parser, idx); + if (item->tag == HID_MAIN_ITEM_TAG_FEATURE) + process_tag(ctx, features, parser, idx); + } + + return 0; +} + +SEC("hid/rdesc_fixup") +int hid_rdesc_fixup(struct hid_bpf_ctx *ctx) +{ + int ret; + + if (ctx->type != HID_BPF_RDESC_FIXUP) + return 0; + + ret = bpf_hid_foreach_rdesc_item(ctx, process_hid_rdesc_item, (void *)0, 0); + bpf_printk("ret: %d", ret); + + return 0; +} + +char _license[] SEC("license") = "GPL"; +u32 _version SEC("version") = LINUX_VERSION_CODE; diff --git a/samples/bpf/hid_usi_user.c b/samples/bpf/hid_usi_user.c new file mode 100644 index 000000000000..b05a3f768835 --- /dev/null +++ b/samples/bpf/hid_usi_user.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2021, Intel Corporation + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bpf_util.h" +#include +#include + +#include + +#include "hid_usi.h" + +static char *sysfs_path; +static char *fifoname = "/tmp/usi"; +static int sysfs_fd; +static int fifo_fd; +static int prog_count; +static int cache, wr_cache; + +static const struct option long_options[] = { + { "help", no_argument, NULL, 'h' }, + { "fifo", required_argument, NULL, 'f' }, +}; + +struct prog { + int fd; + enum bpf_attach_type type; +}; + +static struct prog progs[10]; + +static void int_exit(int sig) +{ + int ret; + + for (prog_count--; prog_count >= 0 ; prog_count--) { + ret = bpf_prog_detach2(progs[prog_count].fd, sysfs_fd, progs[prog_count].type); + if (ret) + fprintf(stderr, "bpf_prog_detach2: returned %m\n"); + } + + close(sysfs_fd); + close(fifo_fd); + remove(fifoname); + exit(0); +} + +static void usage(const char *prog) +{ + fprintf(stderr, + "usage: %s [-f ] /dev/HIDRAW\n\n", + prog); +} + +static int param_to_idx(const char *param) +{ + if (!strcmp(param, "color")) + return USI_PEN_COLOR; + if (!strcmp(param, "width")) + return USI_PEN_LINE_WIDTH; + if (!strcmp(param, "style")) + return USI_PEN_LINE_STYLE; + + return -EINVAL; +} + +static int write_value(const char *param, int value) +{ + int err; + int idx = param_to_idx(param); + + printf("%s: param=%s (%d), value=%d\n", __func__, param, idx, value); + err = bpf_map_update_elem(wr_cache, &idx, &value, BPF_ANY); + if (err) + printf("Update failed for %d, err=%d\n", idx, err); + + return 0; +} + +static int read_value(const char *param) +{ + int value; + int idx = param_to_idx(param); + + printf("%s: param=%s (%d)\n", __func__, param, idx); + + if (bpf_map_lookup_elem(cache, &idx, &value)) + printf("Value missing for %d\n", idx); + else + printf("Value for %d = %d\n", idx, value); + + return 0; +} + +static int attach_progs(int argc, char **argv) +{ + char filename[256]; + struct bpf_prog_info info = {}; + __u32 info_len = sizeof(info); + struct bpf_object *obj; + struct bpf_program *prog; + int err = 0; + char buf[BUFSIZ]; + char param[16]; + char op[8]; + int value; + int m, n; + + snprintf(filename, sizeof(filename), "%s_kern.o", argv[0]); + obj = bpf_object__open_file(filename, NULL); + err = libbpf_get_error(obj); + if (err) { + fprintf(stderr, "ERROR: opening BPF object file failed\n"); + obj = NULL; + err = 1; + goto cleanup; + } + + /* load BPF program */ + err = bpf_object__load(obj); + if (err) { + fprintf(stderr, "ERROR: loading BPF object file failed\n"); + goto cleanup; + } + + sysfs_fd = open(sysfs_path, O_RDONLY); + + bpf_object__for_each_program(prog, obj) { + progs[prog_count].fd = bpf_program__fd(prog); + progs[prog_count].type = bpf_program__get_expected_attach_type(prog); + + err = bpf_prog_attach(progs[prog_count].fd, + sysfs_fd, + progs[prog_count].type, + 0); + if (err) { + fprintf(stderr, "bpf_prog_attach: err=%m\n"); + progs[prog_count].fd = 0; + goto cleanup; + } + printf("attached BPF program with FD=%d, type=%d\n", + progs[prog_count].fd, progs[prog_count].type); + prog_count++; + } + + signal(SIGINT, int_exit); + signal(SIGTERM, int_exit); + + err = bpf_obj_get_info_by_fd(progs[0].fd, &info, &info_len); + if (err) { + printf("can't get prog info - %s\n", strerror(errno)); + goto cleanup; + } + + cache = bpf_object__find_map_fd_by_name(obj, "cache"); + if (cache < 0) { + printf("can't get 'cache' shared mem from object - %m\n"); + goto cleanup; + } + + wr_cache = bpf_object__find_map_fd_by_name(obj, "wr_cache"); + if (wr_cache < 0) { + printf("can't get 'wr_cache' shared mem from object - %m\n"); + goto cleanup; + } + + mkfifo(fifoname, 0666); + + fifo_fd = open(fifoname, O_RDWR); + if (fifo_fd < 0) { + perror("Fifo open error.\n"); + err = fifo_fd; + goto cleanup; + } + + while (1) { + n = read(fifo_fd, buf, BUFSIZ); + if (n < 0) + break; + buf[n] = 0; + + printf("%s: received '%s'\n", __func__, buf); + + m = sscanf(buf, "%16s %8s %d", param, op, &value); + if (m == 2 && strcmp(op, "get") == 0) + read_value(param); + else if (m == 3 && strcmp(op, "set") == 0) + write_value(param, value); + } + + return 0; + + cleanup: + for (prog_count--; prog_count >= 0; prog_count--) { + if (bpf_prog_detach2(progs[prog_count].fd, sysfs_fd, progs[prog_count].type)) + fprintf(stderr, "bpf_prog_detach2: returned %m\n"); + } + + bpf_object__close(obj); + return err; +} + +int main(int argc, char **argv) +{ + int opt; + + while ((opt = getopt_long(argc, argv, "f:", long_options, + NULL)) != -1) { + switch (opt) { + case 'f': + fifoname = optarg; + break; + default: + usage(basename(argv[0])); + return 1; + } + } + + if (optind == argc) { + usage(basename(argv[0])); + return 1; + } + + sysfs_path = argv[optind]; + if (!sysfs_path) { + perror("hidraw"); + return 1; + } + + printf("fifoname: %s\n", fifoname); + printf("sysfs_path: %s\n", sysfs_path); + + return attach_progs(argc, argv); +}