diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c index 961b7f35aa67..2e96ec6a3073 100644 --- a/drivers/hid/bpf/hid_bpf_dispatch.c +++ b/drivers/hid/bpf/hid_bpf_dispatch.c @@ -19,7 +19,7 @@ #include #include "hid_bpf_dispatch.h" -struct hid_ops *hid_ops; +const struct hid_ops *hid_ops; EXPORT_SYMBOL(hid_ops); u8 * @@ -352,7 +352,6 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz, { struct hid_report_enum *report_enum; struct hid_report *report; - struct hid_device *hdev; u32 report_len; /* check arguments */ @@ -371,9 +370,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz, if (*buf__sz < 1) return -EINVAL; - hdev = (struct hid_device *)ctx->hid; /* discard const */ - - report_enum = hdev->report_enum + rtype; + report_enum = ctx->hid->report_enum + rtype; report = hid_ops->hid_get_report(report_enum, buf); if (!report) return -EINVAL; @@ -402,7 +399,6 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, enum hid_report_type rtype, enum hid_class_request reqtype) { struct hid_bpf_ctx_kern *ctx_kern; - struct hid_device *hdev; size_t size = buf__sz; u8 *dma_data; int ret; @@ -429,13 +425,11 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz, return -EINVAL; } - hdev = (struct hid_device *)ctx->hid; /* discard const */ - dma_data = kmemdup(buf, size, GFP_KERNEL); if (!dma_data) return -ENOMEM; - ret = hid_ops->hid_hw_raw_request(hdev, + ret = hid_ops->hid_hw_raw_request(ctx->hid, dma_data[0], dma_data, size, @@ -464,7 +458,6 @@ __bpf_kfunc int hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz) { struct hid_bpf_ctx_kern *ctx_kern; - struct hid_device *hdev; size_t size = buf__sz; u8 *dma_data; int ret; @@ -478,13 +471,11 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz) if (ret) return ret; - hdev = (struct hid_device *)ctx->hid; /* discard const */ - dma_data = kmemdup(buf, size, GFP_KERNEL); if (!dma_data) return -ENOMEM; - ret = hid_ops->hid_hw_output_report(hdev, dma_data, size, (u64)(long)ctx, true); + ret = hid_ops->hid_hw_output_report(ctx->hid, dma_data, size, (u64)(long)ctx, true); kfree(dma_data); return ret; diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 98bef39642a9..33a191973324 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -3064,7 +3064,7 @@ int hid_check_keys_pressed(struct hid_device *hid) EXPORT_SYMBOL_GPL(hid_check_keys_pressed); #ifdef CONFIG_HID_BPF -static struct hid_ops __hid_ops = { +static const struct hid_ops __hid_ops = { .hid_get_report = hid_get_report, .hid_hw_raw_request = __hid_hw_raw_request, .hid_hw_output_report = __hid_hw_output_report, diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 43664a24176f..4e87380d3edd 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -414,7 +414,19 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state) i2c_hid_dbg(ihid, "%s\n", __func__); + /* + * Some STM-based devices need 400µs after a rising clock edge to wake + * from deep sleep, in which case the first request will fail due to + * the address not being acknowledged. Try after a short sleep to see + * if the device came alive on the bus. Certain Weida Tech devices also + * need this. + */ ret = i2c_hid_set_power_command(ihid, power_state); + if (ret && power_state == I2C_HID_PWR_ON) { + usleep_range(400, 500); + ret = i2c_hid_set_power_command(ihid, I2C_HID_PWR_ON); + } + if (ret) dev_err(&ihid->client->dev, "failed to change power setting.\n"); @@ -976,14 +988,6 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid) enable_irq(client->irq); - /* Make sure the device is awake on the bus */ - ret = i2c_hid_probe_address(ihid); - if (ret < 0) { - dev_err(&client->dev, "nothing at address after resume: %d\n", - ret); - return -ENXIO; - } - /* On Goodix 27c6:0d42 wait extra time before device wakeup. * It's not clear why but if we send wakeup too early, the device will * never trigger input interrupts. diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 2bc45b24075c..9843b52bd017 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -2241,7 +2241,8 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix) if (hid_is_usb(wacom->hdev)) { struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent); struct usb_device *dev = interface_to_usbdev(intf); - product_name = dev->product; + if (dev->product != NULL) + product_name = dev->product; } if (wacom->hdev->bus == BUS_I2C) { diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h index a6876ab29004..a2e47dbcf82c 100644 --- a/include/linux/hid_bpf.h +++ b/include/linux/hid_bpf.h @@ -78,7 +78,7 @@ struct hid_ops { const struct bus_type *bus_type; }; -extern struct hid_ops *hid_ops; +extern const struct hid_ops *hid_ops; /** * struct hid_bpf_ops - A BPF struct_ops of callbacks allowing to attach HID-BPF diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h index e5db897586bb..531228b849da 100644 --- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h +++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h @@ -22,6 +22,9 @@ #define HID_REQ_SET_IDLE HID_REQ_SET_IDLE___not_used #define HID_REQ_SET_PROTOCOL HID_REQ_SET_PROTOCOL___not_used +/* do not define kfunc through vmlinux.h as this messes up our custom hack */ +#define BPF_NO_KFUNC_PROTOTYPES + #include "vmlinux.h" #undef hid_bpf_ctx @@ -91,31 +94,31 @@ struct hid_bpf_ops { /* following are kfuncs exported by HID for HID-BPF */ extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx, unsigned int offset, - const size_t __sz) __ksym; -extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __ksym; -extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __ksym; + const size_t __sz) __weak __ksym; +extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __weak __ksym; +extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __weak __ksym; extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *data, size_t buf__sz, enum hid_report_type type, - enum hid_class_request reqtype) __ksym; + enum hid_class_request reqtype) __weak __ksym; extern int hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, - __u8 *buf, size_t buf__sz) __ksym; + __u8 *buf, size_t buf__sz) __weak __ksym; extern int hid_bpf_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, __u8 *data, - size_t buf__sz) __ksym; + size_t buf__sz) __weak __ksym; extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx, enum hid_report_type type, __u8 *data, - size_t buf__sz) __ksym; + size_t buf__sz) __weak __ksym; /* bpf_wq implementation */ extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym; extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym; extern int bpf_wq_set_callback_impl(struct bpf_wq *wq, int (callback_fn)(void *map, int *key, void *wq), - unsigned int flags__k, void *aux__ign) __ksym; + unsigned int flags__k, void *aux__ign) __weak __ksym; #define bpf_wq_set_callback(timer, cb, flags) \ bpf_wq_set_callback_impl(timer, cb, flags, NULL) diff --git a/tools/testing/selftests/hid/run-hid-tools-tests.sh b/tools/testing/selftests/hid/run-hid-tools-tests.sh index bdae8464da86..af1682a53c27 100755 --- a/tools/testing/selftests/hid/run-hid-tools-tests.sh +++ b/tools/testing/selftests/hid/run-hid-tools-tests.sh @@ -2,24 +2,26 @@ # SPDX-License-Identifier: GPL-2.0 # Runs tests for the HID subsystem +KSELFTEST_SKIP_TEST=4 + if ! command -v python3 > /dev/null 2>&1; then echo "hid-tools: [SKIP] python3 not installed" - exit 77 + exit $KSELFTEST_SKIP_TEST fi if ! python3 -c "import pytest" > /dev/null 2>&1; then - echo "hid: [SKIP/ pytest module not installed" - exit 77 + echo "hid: [SKIP] pytest module not installed" + exit $KSELFTEST_SKIP_TEST fi if ! python3 -c "import pytest_tap" > /dev/null 2>&1; then - echo "hid: [SKIP/ pytest_tap module not installed" - exit 77 + echo "hid: [SKIP] pytest_tap module not installed" + exit $KSELFTEST_SKIP_TEST fi if ! python3 -c "import hidtools" > /dev/null 2>&1; then - echo "hid: [SKIP/ hid-tools module not installed" - exit 77 + echo "hid: [SKIP] hid-tools module not installed" + exit $KSELFTEST_SKIP_TEST fi TARGET=${TARGET:=.}