| // SPDX-License-Identifier: GPL-2.0-only | |
| /* Copyright (c) 2025 Benjamin Tissoires | |
| */ | |
| #include "vmlinux.h" | |
| #include "hid_bpf.h" | |
| #include "hid_bpf_helpers.h" | |
| #include "hid_report_helpers.h" | |
| #include "hid_usages.h" | |
| #include <bpf/bpf_tracing.h> | |
| HID_BPF_CONFIG( | |
| HID_DEVICE(BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8, HID_VID_ANY, HID_PID_ANY), | |
| ); | |
| EXPORT_UDEV_PROP(HID_DIGITIZER_PAD_TYPE, 32); | |
| __u8 hw_req_buf[1024]; | |
| /* to be filled by udev-hid-bpf */ | |
| struct hid_rdesc_descriptor HID_REPORT_DESCRIPTOR; | |
| SEC("syscall") | |
| int probe(struct hid_bpf_probe_args *ctx) | |
| { | |
| struct hid_rdesc_report *pad_type_feature = NULL; | |
| struct hid_rdesc_field *pad_type = NULL; | |
| struct hid_rdesc_report *feature; | |
| struct hid_bpf_ctx *hid_ctx; | |
| char *pad_type_str = ""; | |
| int ret; | |
| hid_bpf_for_each_feature_report(&HID_REPORT_DESCRIPTOR, feature) { | |
| struct hid_rdesc_field *field; | |
| hid_bpf_for_each_field(feature, field) { | |
| if (field->usage_page == HidUsagePage_Digitizers && | |
| field->usage_id == HidUsage_Dig_PadType) { | |
| pad_type = field; | |
| pad_type_feature = feature; | |
| break; | |
| } | |
| } | |
| if (pad_type) | |
| break; | |
| } | |
| if (!pad_type || !pad_type_feature) { | |
| ctx->retval = -EINVAL; | |
| return 0; | |
| } | |
| hid_ctx = hid_bpf_allocate_context(ctx->hid); | |
| if (!hid_ctx) | |
| return -1; /* EPERM check */ | |
| hw_req_buf[0] = pad_type_feature->report_id; | |
| ret = hid_bpf_hw_request(hid_ctx, hw_req_buf, sizeof(hw_req_buf), | |
| HID_FEATURE_REPORT, HID_REQ_GET_REPORT); | |
| hid_bpf_release_context(hid_ctx); | |
| if (ret < 0) { | |
| ctx->retval = ret; | |
| return 0; | |
| } | |
| ctx->retval = 0; | |
| switch (EXTRACT_BITS(hw_req_buf, pad_type)) { | |
| case 0: | |
| pad_type_str = "Clickpad"; | |
| break; | |
| case 1: | |
| pad_type_str = "Pressurepad"; | |
| break; | |
| case 2: | |
| pad_type_str = "Discrete"; | |
| break; | |
| default: | |
| pad_type_str = "Unknown"; | |
| } | |
| UDEV_PROP_SPRINTF(HID_DIGITIZER_PAD_TYPE, "%s", pad_type_str); | |
| return 0; | |
| } | |
| char _license[] SEC("license") = "GPL"; |