From: David Given dg@cowlark.com
[ Upstream commit b2ec92bb5605452d539a7aa1e42345b95acd8583 ]
Adds a quirk to make the NXP Semiconductors 1fc9:009b chipset work.
lsusb for the device reports:
Bus 003 Device 011: ID 1fc9:009b NXP Semiconductors IR VIDEO Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 2.00 bDeviceClass 239 Miscellaneous Device bDeviceSubClass 2 [unknown] bDeviceProtocol 1 Interface Association bMaxPacketSize0 64 idVendor 0x1fc9 NXP Semiconductors idProduct 0x009b IR VIDEO bcdDevice 1.01 iManufacturer 1 Guide sensmart iProduct 2 IR VIDEO iSerial 0 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x00c2 bNumInterfaces 2 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xc0 Self Powered MaxPower 100mA Interface Association: bLength 8 bDescriptorType 11 bFirstInterface 0 bInterfaceCount 2 bFunctionClass 14 Video bFunctionSubClass 3 Video Interface Collection bFunctionProtocol 0 iFunction 3 IR Camera Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 14 Video bInterfaceSubClass 1 Video Control bInterfaceProtocol 0 iInterface 0 VideoControl Interface Descriptor: bLength 13 bDescriptorType 36 bDescriptorSubtype 1 (HEADER) bcdUVC 1.00 wTotalLength 0x0033 dwClockFrequency 6.000000MHz bInCollection 1 baInterfaceNr( 0) 1 VideoControl Interface Descriptor: bLength 18 bDescriptorType 36 bDescriptorSubtype 2 (INPUT_TERMINAL) bTerminalID 1 wTerminalType 0x0201 Camera Sensor bAssocTerminal 0 iTerminal 0 wObjectiveFocalLengthMin 0 wObjectiveFocalLengthMax 0 wOcularFocalLength 0 bControlSize 3 bmControls 0x00000000 VideoControl Interface Descriptor: bLength 9 bDescriptorType 36 bDescriptorSubtype 3 (OUTPUT_TERMINAL) bTerminalID 2 wTerminalType 0x0101 USB Streaming bAssocTerminal 0 bSourceID 1 iTerminal 0 VideoControl Interface Descriptor: bLength 11 bDescriptorType 36 bDescriptorSubtype 5 (PROCESSING_UNIT) Warning: Descriptor too short bUnitID 3 bSourceID 1 wMaxMultiplier 0 bControlSize 2 bmControls 0x00000000 iProcessing 0 bmVideoStandards 0x62 NTSC - 525/60 PAL - 525/60 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 1 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 0 bInterfaceClass 14 Video bInterfaceSubClass 2 Video Streaming bInterfaceProtocol 0 iInterface 0 VideoStreaming Interface Descriptor: bLength 14 bDescriptorType 36 bDescriptorSubtype 1 (INPUT_HEADER) bNumFormats 1 wTotalLength 0x0055 bEndpointAddress 0x82 EP 2 IN bmInfo 0 bTerminalLink 2 bStillCaptureMethod 2 bTriggerSupport 0 bTriggerUsage 0 bControlSize 1 bmaControls( 0) 0 VideoStreaming Interface Descriptor: bLength 27 bDescriptorType 36 bDescriptorSubtype 4 (FORMAT_UNCOMPRESSED) bFormatIndex 1 bNumFrameDescriptors 1 guidFormat {e436eb7b-524f-11ce-9f53-0020af0ba770} bBitsPerPixel 16 bDefaultFrameIndex 1 bAspectRatioX 0 bAspectRatioY 0 bmInterlaceFlags 0x00 Interlaced stream or variable: No Fields per frame: 2 fields Field 1 first: No Field pattern: Field 1 only bCopyProtect 0 VideoStreaming Interface Descriptor: bLength 34 bDescriptorType 36 bDescriptorSubtype 5 (FRAME_UNCOMPRESSED) bFrameIndex 1 bmCapabilities 0x00 Still image unsupported wWidth 240 wHeight 322 dwMinBitRate 12364800 dwMaxBitRate 30912000 dwMaxVideoFrameBufferSize 154560 dwDefaultFrameInterval 400000 bFrameIntervalType 2 dwFrameInterval( 0) 400000 dwFrameInterval( 1) 1000000 VideoStreaming Interface Descriptor: bLength 10 bDescriptorType 36 bDescriptorSubtype 3 (STILL_IMAGE_FRAME) bEndpointAddress 0x00 EP 0 OUT bNumImageSizePatterns 1 wWidth( 0) 240 wHeight( 0) 322 bNumCompressionPatterns 0 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 1 bNumEndpoints 1 bInterfaceClass 14 Video bInterfaceSubClass 2 Video Streaming bInterfaceProtocol 0 iInterface 0 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 5 Transfer Type Isochronous Synch Type Asynchronous Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 1 Device Status: 0x0001 Self Powered
Signed-off-by: David Given dg@cowlark.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Reviewed-by: Ricardo Ribalda ribalda@chromium.org Link: https://lore.kernel.org/r/20240918180540.10830-2-dg@cowlark.com Signed-off-by: Laurent Pinchart laurent.pinchart@ideasonboard.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/uvc/uvc_driver.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index cbad244a307d2..473cc23ef8431 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -2402,6 +2402,8 @@ static const struct uvc_device_info uvc_quirk_force_y8 = { * The Logitech cameras listed below have their interface class set to * VENDOR_SPEC because they don't announce themselves as UVC devices, even * though they are compliant. + * + * Sort these by vendor/product ID. */ static const struct usb_device_id uvc_ids[] = { /* LogiLink Wireless Webcam */ @@ -2852,6 +2854,15 @@ static const struct usb_device_id uvc_ids[] = { .bInterfaceProtocol = 0, .driver_info = UVC_QUIRK_INFO(UVC_QUIRK_PROBE_MINMAX | UVC_QUIRK_IGNORE_SELECTOR_UNIT) }, + /* NXP Semiconductors IR VIDEO */ + { .match_flags = USB_DEVICE_ID_MATCH_DEVICE + | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1fc9, + .idProduct = 0x009b, + .bInterfaceClass = USB_CLASS_VIDEO, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 0, + .driver_info = (kernel_ulong_t)&uvc_quirk_probe_minmax }, /* Oculus VR Positional Tracker DK2 */ { .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO,
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 88785982a19daa765e30ab3a605680202cfaee4e ]
If the wait_prepare or wait_finish callback is set, then call it. If it is NULL and the queue lock pointer is not NULL, then just unlock/lock that mutex.
This allows simplifying drivers by dropping the wait_prepare and wait_finish ops (and eventually the vb2_ops_wait_prepare/finish helpers).
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/common/videobuf2/videobuf2-core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 98719aa986bb9..e439831f6df46 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -1528,7 +1528,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) * become ready or for streamoff. Driver's lock is released to * allow streamoff or qbuf to be called while waiting. */ - call_void_qop(q, wait_prepare, q); + if (q->ops->wait_prepare) + call_void_qop(q, wait_prepare, q); + else if (q->lock) + mutex_unlock(q->lock);
/* * All locks have been released, it is safe to sleep now. @@ -1538,12 +1541,16 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) !list_empty(&q->done_list) || !q->streaming || q->error);
+ if (q->ops->wait_finish) + call_void_qop(q, wait_finish, q); + else if (q->lock) + mutex_lock(q->lock); + + q->waiting_in_dqbuf = 0; /* * We need to reevaluate both conditions again after reacquiring * the locks or return an error if one occurred. */ - call_void_qop(q, wait_finish, q); - q->waiting_in_dqbuf = 0; if (ret) { dprintk(1, "sleep was interrupted\n"); return ret;
Hi Sasha,
This shouldn't be backported. It is not a fix, and it relies on a number of other changes for this to work anyway, and none of those other changes are backported.
So please drop this patch.
Thank you,
Hans
On 24/11/2024 13:58, Sasha Levin wrote:
From: Hans Verkuil hverkuil-cisco@xs4all.nl
[ Upstream commit 88785982a19daa765e30ab3a605680202cfaee4e ]
If the wait_prepare or wait_finish callback is set, then call it. If it is NULL and the queue lock pointer is not NULL, then just unlock/lock that mutex.
This allows simplifying drivers by dropping the wait_prepare and wait_finish ops (and eventually the vb2_ops_wait_prepare/finish helpers).
Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Mauro Carvalho Chehab mchehab+huawei@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org
drivers/media/common/videobuf2/videobuf2-core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 98719aa986bb9..e439831f6df46 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -1528,7 +1528,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) * become ready or for streamoff. Driver's lock is released to * allow streamoff or qbuf to be called while waiting. */
call_void_qop(q, wait_prepare, q);
if (q->ops->wait_prepare)
call_void_qop(q, wait_prepare, q);
else if (q->lock)
mutex_unlock(q->lock);
/* * All locks have been released, it is safe to sleep now. @@ -1538,12 +1541,16 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking) !list_empty(&q->done_list) || !q->streaming || q->error);
if (q->ops->wait_finish)
call_void_qop(q, wait_finish, q);
else if (q->lock)
mutex_lock(q->lock);
/*q->waiting_in_dqbuf = 0;
*/
- We need to reevaluate both conditions again after reacquiring
- the locks or return an error if one occurred.
call_void_qop(q, wait_finish, q);
if (ret) { dprintk(1, "sleep was interrupted\n"); return ret;q->waiting_in_dqbuf = 0;
On Mon, Nov 25, 2024 at 08:33:06AM +0100, Hans Verkuil wrote:
Hi Sasha,
This shouldn't be backported. It is not a fix, and it relies on a number of other changes for this to work anyway, and none of those other changes are backported.
So please drop this patch.
Will do, thanks!
From: Rohan Barar rohan.barar@gmail.com
[ Upstream commit 61a830bc0ea69a05d8a4534f825c6aa618263649 ]
Add Dexatek Technology Ltd USB Video Grabber 1d19:6108 to the cx231xx driver. This device is sold under the name "BAUHN DVD Maker (DK8723)" by ALDI in Australia.
This device is similar to 1d19:6109, which is already included in cx231xx.
Both video and audio capture function correctly after installing the patched cx231xx driver.
Patch Changelog v1: - Initial submission. v2: - Fix SoB + Improve subject. v3: - Rephrase message to not exceed 75 characters per line. - Removed reference to external GitHub URL.
Signed-off-by: Rohan Barar rohan.barar@gmail.com Signed-off-by: Hans Verkuil hverkuil-cisco@xs4all.nl Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/media/usb/cx231xx/cx231xx-cards.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c index a431a998d58f7..db7d64b5858e7 100644 --- a/drivers/media/usb/cx231xx/cx231xx-cards.c +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c @@ -1006,6 +1006,8 @@ const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
/* table of devices that work with this driver */ struct usb_device_id cx231xx_id_table[] = { + {USB_DEVICE(0x1D19, 0x6108), + .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, {USB_DEVICE(0x1D19, 0x6109), .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB}, {USB_DEVICE(0x0572, 0x5A3C),
From: Benjamin Tissoires bentiss@kernel.org
[ Upstream commit 9bc089307e8dff7797233308372b4a90ce8f79be ]
Mistel MD770 keyboard (using Holtek Semiconductor, Inc. controller) has a quirk in report descriptor in one of its interfaces (more detail in the source file). Fix up the descriptor to allow NKRO to work again.
Tested by loading the BPF program and confirming that 8 simultaneous keypresses work.
Link: https://bugzilla.kernel.org/show_bug.cgi?id=218495 Link: https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/merge_requests/122 Signed-off-by: Tatsuyuki Ishi ishitatsuyuki@gmail.com Acked-by: Jiri Kosina jkosina@suse.com Link: https://patch.msgid.link/20241017-import_bpf_6-13-v2-1-6a7acb89a97f@kernel.o... Signed-off-by: Benjamin Tissoires bentiss@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org --- drivers/hid/bpf/progs/Mistel__MD770.bpf.c | 154 ++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 drivers/hid/bpf/progs/Mistel__MD770.bpf.c
diff --git a/drivers/hid/bpf/progs/Mistel__MD770.bpf.c b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c new file mode 100644 index 0000000000000..fb8b5a6968b12 --- /dev/null +++ b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Tatsuyuki Ishi + */ + +#include "vmlinux.h" +#include "hid_bpf.h" +#include "hid_bpf_helpers.h" +#include <bpf/bpf_tracing.h> + +#define VID_HOLTEK 0x04D9 +#define PID_MD770 0x0339 +#define RDESC_SIZE 203 + +HID_BPF_CONFIG( + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HOLTEK, PID_MD770) +); + +/* + * The Mistel MD770 keyboard reports the first 6 simultaneous key presses + * through the first interface, and anything beyond that through a second + * interface. Unfortunately, the second interface's report descriptor has an + * error, causing events to be malformed and ignored. This HID-BPF driver + * fixes the descriptor to allow NKRO to work again. + * + * For reference, this is the original report descriptor: + * + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 + * 0x09, 0x80, // Usage (System Control) 2 + * 0xa1, 0x01, // Collection (Application) 4 + * 0x85, 0x01, // Report ID (1) 6 + * 0x19, 0x81, // Usage Minimum (129) 8 + * 0x29, 0x83, // Usage Maximum (131) 10 + * 0x15, 0x00, // Logical Minimum (0) 12 + * 0x25, 0x01, // Logical Maximum (1) 14 + * 0x95, 0x03, // Report Count (3) 16 + * 0x75, 0x01, // Report Size (1) 18 + * 0x81, 0x02, // Input (Data,Var,Abs) 20 + * 0x95, 0x01, // Report Count (1) 22 + * 0x75, 0x05, // Report Size (5) 24 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 26 + * 0xc0, // End Collection 28 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 29 + * 0x09, 0x01, // Usage (Consumer Control) 31 + * 0xa1, 0x01, // Collection (Application) 33 + * 0x85, 0x02, // Report ID (2) 35 + * 0x15, 0x00, // Logical Minimum (0) 37 + * 0x25, 0x01, // Logical Maximum (1) 39 + * 0x95, 0x12, // Report Count (18) 41 + * 0x75, 0x01, // Report Size (1) 43 + * 0x0a, 0x83, 0x01, // Usage (AL Consumer Control Config) 45 + * 0x0a, 0x8a, 0x01, // Usage (AL Email Reader) 48 + * 0x0a, 0x92, 0x01, // Usage (AL Calculator) 51 + * 0x0a, 0x94, 0x01, // Usage (AL Local Machine Browser) 54 + * 0x09, 0xcd, // Usage (Play/Pause) 57 + * 0x09, 0xb7, // Usage (Stop) 59 + * 0x09, 0xb6, // Usage (Scan Previous Track) 61 + * 0x09, 0xb5, // Usage (Scan Next Track) 63 + * 0x09, 0xe2, // Usage (Mute) 65 + * 0x09, 0xea, // Usage (Volume Down) 67 + * 0x09, 0xe9, // Usage (Volume Up) 69 + * 0x0a, 0x21, 0x02, // Usage (AC Search) 71 + * 0x0a, 0x23, 0x02, // Usage (AC Home) 74 + * 0x0a, 0x24, 0x02, // Usage (AC Back) 77 + * 0x0a, 0x25, 0x02, // Usage (AC Forward) 80 + * 0x0a, 0x26, 0x02, // Usage (AC Stop) 83 + * 0x0a, 0x27, 0x02, // Usage (AC Refresh) 86 + * 0x0a, 0x2a, 0x02, // Usage (AC Bookmarks) 89 + * 0x81, 0x02, // Input (Data,Var,Abs) 92 + * 0x95, 0x01, // Report Count (1) 94 + * 0x75, 0x0e, // Report Size (14) 96 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 98 + * 0xc0, // End Collection 100 + * 0x05, 0x01, // Usage Page (Generic Desktop) 101 + * 0x09, 0x02, // Usage (Mouse) 103 + * 0xa1, 0x01, // Collection (Application) 105 + * 0x09, 0x01, // Usage (Pointer) 107 + * 0xa1, 0x00, // Collection (Physical) 109 + * 0x85, 0x03, // Report ID (3) 111 + * 0x05, 0x09, // Usage Page (Button) 113 + * 0x19, 0x01, // Usage Minimum (1) 115 + * 0x29, 0x08, // Usage Maximum (8) 117 + * 0x15, 0x00, // Logical Minimum (0) 119 + * 0x25, 0x01, // Logical Maximum (1) 121 + * 0x75, 0x01, // Report Size (1) 123 + * 0x95, 0x08, // Report Count (8) 125 + * 0x81, 0x02, // Input (Data,Var,Abs) 127 + * 0x05, 0x01, // Usage Page (Generic Desktop) 129 + * 0x09, 0x30, // Usage (X) 131 + * 0x09, 0x31, // Usage (Y) 133 + * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 135 + * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 138 + * 0x75, 0x10, // Report Size (16) 141 + * 0x95, 0x02, // Report Count (2) 143 + * 0x81, 0x06, // Input (Data,Var,Rel) 145 + * 0x09, 0x38, // Usage (Wheel) 147 + * 0x15, 0x81, // Logical Minimum (-127) 149 + * 0x25, 0x7f, // Logical Maximum (127) 151 + * 0x75, 0x08, // Report Size (8) 153 + * 0x95, 0x01, // Report Count (1) 155 + * 0x81, 0x06, // Input (Data,Var,Rel) 157 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 159 + * 0x0a, 0x38, 0x02, // Usage (AC Pan) 161 + * 0x95, 0x01, // Report Count (1) 164 + * 0x81, 0x06, // Input (Data,Var,Rel) 166 + * 0xc0, // End Collection 168 + * 0xc0, // End Collection 169 + * 0x05, 0x01, // Usage Page (Generic Desktop) 170 + * 0x09, 0x06, // Usage (Keyboard) 172 + * 0xa1, 0x01, // Collection (Application) 174 + * 0x85, 0x04, // Report ID (4) 176 + * 0x05, 0x07, // Usage Page (Keyboard) 178 + * 0x95, 0x01, // Report Count (1) 180 + * 0x75, 0x08, // Report Size (8) 182 + * 0x81, 0x03, // Input (Cnst,Var,Abs) 184 + * 0x95, 0xe8, // Report Count (232) 186 + * 0x75, 0x01, // Report Size (1) 188 + * 0x15, 0x00, // Logical Minimum (0) 190 + * 0x25, 0x01, // Logical Maximum (1) 192 + * 0x05, 0x07, // Usage Page (Keyboard) 194 + * 0x19, 0x00, // Usage Minimum (0) 196 + * 0x29, 0xe7, // Usage Maximum (231) 198 + * 0x81, 0x00, // Input (Data,Arr,Abs) 200 <- change to 0x81, 0x02 (Data,Var,Abs) + * 0xc0, // End Collection 202 + */ + +SEC(HID_BPF_RDESC_FIXUP) +int BPF_PROG(hid_rdesc_fixup_mistel_md770, struct hid_bpf_ctx *hctx) +{ + __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); + + if (!data) + return 0; /* EPERM check */ + + if (data[201] == 0x00) + data[201] = 0x02; + + return 0; +} + +HID_BPF_OPS(mistel_md770) = { + .hid_rdesc_fixup = (void *)hid_rdesc_fixup_mistel_md770, +}; + +SEC("syscall") +int probe(struct hid_bpf_probe_args *ctx) +{ + ctx->retval = ctx->rdesc_size != RDESC_SIZE; + if (ctx->retval) + ctx->retval = -EINVAL; + + return 0; +} + +char _license[] SEC("license") = "GPL";
Hi!
From: Benjamin Tissoires bentiss@kernel.org
[ Upstream commit 9bc089307e8dff7797233308372b4a90ce8f79be ]
Mistel MD770 keyboard (using Holtek Semiconductor, Inc. controller) has a quirk in report descriptor in one of its interfaces (more detail in the source file). Fix up the descriptor to allow NKRO to work again.
Tested by loading the BPF program and confirming that 8 simultaneous keypresses work.
Ummm. No. drivers/hid/bpf/progs/ not existing in 4.19 should be a hint.
Best regards, Pavel
+++ b/drivers/hid/bpf/progs/Mistel__MD770.bpf.c @@ -0,0 +1,154 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2024 Tatsuyuki Ishi
- */
+#include "vmlinux.h" +#include "hid_bpf.h" +#include "hid_bpf_helpers.h" +#include <bpf/bpf_tracing.h>
+#define VID_HOLTEK 0x04D9 +#define PID_MD770 0x0339 +#define RDESC_SIZE 203
+HID_BPF_CONFIG(
- HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HOLTEK, PID_MD770)
+);
+/*
- The Mistel MD770 keyboard reports the first 6 simultaneous key presses
- through the first interface, and anything beyond that through a second
- interface. Unfortunately, the second interface's report descriptor has an
- error, causing events to be malformed and ignored. This HID-BPF driver
- fixes the descriptor to allow NKRO to work again.
- For reference, this is the original report descriptor:
- 0x05, 0x01, // Usage Page (Generic Desktop) 0
- 0x09, 0x80, // Usage (System Control) 2
- 0xa1, 0x01, // Collection (Application) 4
- 0x85, 0x01, // Report ID (1) 6
- 0x19, 0x81, // Usage Minimum (129) 8
- 0x29, 0x83, // Usage Maximum (131) 10
- 0x15, 0x00, // Logical Minimum (0) 12
- 0x25, 0x01, // Logical Maximum (1) 14
- 0x95, 0x03, // Report Count (3) 16
- 0x75, 0x01, // Report Size (1) 18
- 0x81, 0x02, // Input (Data,Var,Abs) 20
- 0x95, 0x01, // Report Count (1) 22
- 0x75, 0x05, // Report Size (5) 24
- 0x81, 0x01, // Input (Cnst,Arr,Abs) 26
- 0xc0, // End Collection 28
- 0x05, 0x0c, // Usage Page (Consumer Devices) 29
- 0x09, 0x01, // Usage (Consumer Control) 31
- 0xa1, 0x01, // Collection (Application) 33
- 0x85, 0x02, // Report ID (2) 35
- 0x15, 0x00, // Logical Minimum (0) 37
- 0x25, 0x01, // Logical Maximum (1) 39
- 0x95, 0x12, // Report Count (18) 41
- 0x75, 0x01, // Report Size (1) 43
- 0x0a, 0x83, 0x01, // Usage (AL Consumer Control Config) 45
- 0x0a, 0x8a, 0x01, // Usage (AL Email Reader) 48
- 0x0a, 0x92, 0x01, // Usage (AL Calculator) 51
- 0x0a, 0x94, 0x01, // Usage (AL Local Machine Browser) 54
- 0x09, 0xcd, // Usage (Play/Pause) 57
- 0x09, 0xb7, // Usage (Stop) 59
- 0x09, 0xb6, // Usage (Scan Previous Track) 61
- 0x09, 0xb5, // Usage (Scan Next Track) 63
- 0x09, 0xe2, // Usage (Mute) 65
- 0x09, 0xea, // Usage (Volume Down) 67
- 0x09, 0xe9, // Usage (Volume Up) 69
- 0x0a, 0x21, 0x02, // Usage (AC Search) 71
- 0x0a, 0x23, 0x02, // Usage (AC Home) 74
- 0x0a, 0x24, 0x02, // Usage (AC Back) 77
- 0x0a, 0x25, 0x02, // Usage (AC Forward) 80
- 0x0a, 0x26, 0x02, // Usage (AC Stop) 83
- 0x0a, 0x27, 0x02, // Usage (AC Refresh) 86
- 0x0a, 0x2a, 0x02, // Usage (AC Bookmarks) 89
- 0x81, 0x02, // Input (Data,Var,Abs) 92
- 0x95, 0x01, // Report Count (1) 94
- 0x75, 0x0e, // Report Size (14) 96
- 0x81, 0x01, // Input (Cnst,Arr,Abs) 98
- 0xc0, // End Collection 100
- 0x05, 0x01, // Usage Page (Generic Desktop) 101
- 0x09, 0x02, // Usage (Mouse) 103
- 0xa1, 0x01, // Collection (Application) 105
- 0x09, 0x01, // Usage (Pointer) 107
- 0xa1, 0x00, // Collection (Physical) 109
- 0x85, 0x03, // Report ID (3) 111
- 0x05, 0x09, // Usage Page (Button) 113
- 0x19, 0x01, // Usage Minimum (1) 115
- 0x29, 0x08, // Usage Maximum (8) 117
- 0x15, 0x00, // Logical Minimum (0) 119
- 0x25, 0x01, // Logical Maximum (1) 121
- 0x75, 0x01, // Report Size (1) 123
- 0x95, 0x08, // Report Count (8) 125
- 0x81, 0x02, // Input (Data,Var,Abs) 127
- 0x05, 0x01, // Usage Page (Generic Desktop) 129
- 0x09, 0x30, // Usage (X) 131
- 0x09, 0x31, // Usage (Y) 133
- 0x16, 0x01, 0x80, // Logical Minimum (-32767) 135
- 0x26, 0xff, 0x7f, // Logical Maximum (32767) 138
- 0x75, 0x10, // Report Size (16) 141
- 0x95, 0x02, // Report Count (2) 143
- 0x81, 0x06, // Input (Data,Var,Rel) 145
- 0x09, 0x38, // Usage (Wheel) 147
- 0x15, 0x81, // Logical Minimum (-127) 149
- 0x25, 0x7f, // Logical Maximum (127) 151
- 0x75, 0x08, // Report Size (8) 153
- 0x95, 0x01, // Report Count (1) 155
- 0x81, 0x06, // Input (Data,Var,Rel) 157
- 0x05, 0x0c, // Usage Page (Consumer Devices) 159
- 0x0a, 0x38, 0x02, // Usage (AC Pan) 161
- 0x95, 0x01, // Report Count (1) 164
- 0x81, 0x06, // Input (Data,Var,Rel) 166
- 0xc0, // End Collection 168
- 0xc0, // End Collection 169
- 0x05, 0x01, // Usage Page (Generic Desktop) 170
- 0x09, 0x06, // Usage (Keyboard) 172
- 0xa1, 0x01, // Collection (Application) 174
- 0x85, 0x04, // Report ID (4) 176
- 0x05, 0x07, // Usage Page (Keyboard) 178
- 0x95, 0x01, // Report Count (1) 180
- 0x75, 0x08, // Report Size (8) 182
- 0x81, 0x03, // Input (Cnst,Var,Abs) 184
- 0x95, 0xe8, // Report Count (232) 186
- 0x75, 0x01, // Report Size (1) 188
- 0x15, 0x00, // Logical Minimum (0) 190
- 0x25, 0x01, // Logical Maximum (1) 192
- 0x05, 0x07, // Usage Page (Keyboard) 194
- 0x19, 0x00, // Usage Minimum (0) 196
- 0x29, 0xe7, // Usage Maximum (231) 198
- 0x81, 0x00, // Input (Data,Arr,Abs) 200 <- change to 0x81, 0x02 (Data,Var,Abs)
- 0xc0, // End Collection 202
- */
+SEC(HID_BPF_RDESC_FIXUP) +int BPF_PROG(hid_rdesc_fixup_mistel_md770, struct hid_bpf_ctx *hctx) +{
- __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE);
- if (!data)
return 0; /* EPERM check */
- if (data[201] == 0x00)
data[201] = 0x02;
- return 0;
+}
+HID_BPF_OPS(mistel_md770) = {
- .hid_rdesc_fixup = (void *)hid_rdesc_fixup_mistel_md770,
+};
+SEC("syscall") +int probe(struct hid_bpf_probe_args *ctx) +{
- ctx->retval = ctx->rdesc_size != RDESC_SIZE;
- if (ctx->retval)
ctx->retval = -EINVAL;
- return 0;
+}
+char _license[] SEC("license") = "GPL";
linux-stable-mirror@lists.linaro.org