From 2f1f11d1bbc7570ffad8a93f1b0e2742922a9541 Mon Sep 17 00:00:00 2001 From: Evan Reichard Date: Fri, 3 Oct 2025 16:21:48 -0400 Subject: [PATCH] add: readme --- README.md | 21 ++++++ sam_hid_kbd_rem.patch | 145 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 README.md create mode 100644 sam_hid_kbd_rem.patch diff --git a/README.md b/README.md new file mode 100644 index 0000000..21c2cc5 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# KernelPatch / APatch - Android Generic BT Keyboard Fix + +### Description + +This is a [KernelPatch](https://github.com/bmax121/KernelPatch) / [APatch](https://github.com/bmax121/APatch) module used to fix an +issue with the Samsung Galaxy Tab S7 on some kernels where a Bluetooth keyboard connects but fails to work. + +The underlying issue is that some cheap keyboards report their USB Vendor ID as `0x04E8` and Product ID as `0x7021`, which is the +same as a Samsung Wireless Keyboard. This causes the Samsung HID driver to claim the device, which doesn't support the keyboard properly. + +This patch blocks the Samsung driver from matching these devices and prevents custom quirks from being applied, allowing the generic HID driver to handle them instead. + +### Installation + +Install the patch by copying the `sam_hid_kbd_rem.kpm` file to your device, opening APatch, and loading/installing the module. + +### Kernel Patch + +You can also patch the kernel directly by applying the provided patch file `sam_hid_kbd_rem.patch`. At the time of writing this, the patch was +applied to the [LineageOS/android_kernel_samsung_sm8250](https://github.com/LineageOS/android_kernel_samsung_sm8250/tree/8acbe9760ef02f0d044c0f0ec1bb469fa383fb07) +at hash `8acbe9760ef02f0d044c0f0ec1bb469fa383fb07`. diff --git a/sam_hid_kbd_rem.patch b/sam_hid_kbd_rem.patch new file mode 100644 index 0000000..de1551f --- /dev/null +++ b/sam_hid_kbd_rem.patch @@ -0,0 +1,145 @@ +diff --git i/drivers/hid/hid-quirks.c w/drivers/hid/hid-quirks.c +index f30faf09823c..2a8334e66db3 100644 +--- i/drivers/hid/hid-quirks.c ++++ w/drivers/hid/hid-quirks.c +@@ -638,7 +638,6 @@ static const struct hid_device_id hid_have_special_driver[] = { + #if IS_ENABLED(CONFIG_HID_SAMSUNG) + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, +- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_ACTIONMOUSE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_BOOKCOVER) }, +diff --git i/drivers/hid/hid-samsung.c w/drivers/hid/hid-samsung.c +index 75825e3dd26b..4e2ce1476981 100644 +--- i/drivers/hid/hid-samsung.c ++++ w/drivers/hid/hid-samsung.c +@@ -130,110 +130,6 @@ static int samsung_kbd_mouse_input_mapping(struct hid_device *hdev, + return 1; + } + +-static int samsung_kbd_input_mapping(struct hid_device *hdev, +- struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, +- unsigned long **bit, int *max) +-{ +- if (!(HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE) || +- HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE))) +- return 0; +- +- dbg_hid("samsung wireless keyboard input mapping event [0x%x]\n", +- usage->hid & HID_USAGE); +- +- if (HID_UP_KEYBOARD == (usage->hid & HID_USAGE_PAGE)) { +- switch (usage->hid & HID_USAGE) { +- set_bit(EV_REP, hi->input->evbit); +- /* Only for UK keyboard */ +- /* key found */ +-#ifdef CONFIG_HID_KK_UPGRADE +- case 0x32: +- samsung_kbd_mouse_map_key_clear(KEY_KBDILLUMTOGGLE); +- break; +- case 0x64: +- samsung_kbd_mouse_map_key_clear(KEY_BACKSLASH); +- break; +-#else +- case 0x32: +- samsung_kbd_mouse_map_key_clear(KEY_BACKSLASH); +- break; +- case 0x64: +- samsung_kbd_mouse_map_key_clear(KEY_102ND); +- break; +-#endif +- /* Only for BR keyboard */ +- case 0x87: +- samsung_kbd_mouse_map_key_clear(KEY_RO); +- break; +- default: +- return 0; +- } +- } +- +- if (HID_UP_CONSUMER == (usage->hid & HID_USAGE_PAGE)) { +- switch (usage->hid & HID_USAGE) { +- /* report 2 */ +- /* MENU */ +- case 0x040: +- samsung_kbd_mouse_map_key_clear(KEY_MENU); +- break; +- case 0x18a: +- samsung_kbd_mouse_map_key_clear(KEY_MAIL); +- break; +- case 0x196: +- samsung_kbd_mouse_map_key_clear(KEY_WWW); +- break; +- case 0x19e: +- samsung_kbd_mouse_map_key_clear(KEY_SCREENLOCK); +- break; +- case 0x221: +- samsung_kbd_mouse_map_key_clear(KEY_SEARCH); +- break; +- case 0x223: +- samsung_kbd_mouse_map_key_clear(KEY_HOMEPAGE); +- break; +- /* Smtart Voice Key */ +- case 0x300: +- samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY13); +- break; +- /* RECENTAPPS */ +- case 0x301: +- samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY1); +- break; +- /* APPLICATION */ +- case 0x302: +- samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY2); +- break; +- /* Voice search */ +- case 0x305: +- samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY4); +- break; +- /* QPANEL on/off */ +- case 0x306: +- samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY5); +- break; +- /* SIP on/off */ +- case 0x307: +- samsung_kbd_mouse_map_key_clear(BTN_TRIGGER_HAPPY3); +- break; +- /* LANG */ +- case 0x308: +- samsung_kbd_mouse_map_key_clear(KEY_LANGUAGE); +- break; +- case 0x30a: +- samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSDOWN); +- break; +- case 0x30b: +- samsung_kbd_mouse_map_key_clear(KEY_BRIGHTNESSUP); +- break; +- default: +- return 0; +- } +- } +- +- return 1; +-} +- + static int samsung_gamepad_input_mapping(struct hid_device *hdev, + struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +@@ -499,9 +395,6 @@ static int samsung_input_mapping(struct hid_device *hdev, struct hid_input *hi, + if (USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE == hdev->product) + ret = samsung_kbd_mouse_input_mapping(hdev, + hi, field, usage, bit, max); +- else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD) +- ret = samsung_kbd_input_mapping(hdev, +- hi, field, usage, bit, max); + else if (hdev->product == USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD) + ret = samsung_gamepad_input_mapping(hdev, + hi, field, usage, bit, max); +@@ -555,7 +448,6 @@ static int samsung_probe(struct hid_device *hdev, + static const struct hid_device_id samsung_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, +- { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_GAMEPAD) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_ACTIONMOUSE) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SAMSUNG_ELECTRONICS, USB_DEVICE_ID_SAMSUNG_WIRELESS_UNIVERSAL_KBD) },