diff --git a/CMakeLists.txt b/CMakeLists.txt index cb440ef..484afce 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ set(USB_Sources src/usb/usbh_pipes.c src/usb/usbh_hid.c src/usb/usbh_hid_mouse.c + src/usb/usbh_hid_keyboard.c ) add_definitions( diff --git a/src/gfx_main.c b/src/gfx_main.c index c34b6c1..69b4deb 100644 --- a/src/gfx_main.c +++ b/src/gfx_main.c @@ -285,9 +285,13 @@ void gfx_set_byte_offsets_text(void) hid_data_location_t * button = xlat_get_button_location(); hid_data_location_t * x = xlat_get_x_location(); hid_data_location_t * y = xlat_get_y_location(); + hid_data_location_t * key = xlat_get_key_location(); + uint8_t interface = xlat_get_found_interface(); - if (button->found && x->found && y->found) { - sprintf(text, "Data: click@%d motion@%d,%d", button->byte_offset, x->byte_offset, y->byte_offset); + if (button->found && x->found && y->found && XLAT_MODE_KEY != xlat_get_mode()) { + sprintf(text, "Mouse Data (#%d): click@%d motion@%d,%d", interface, button->byte_offset, x->byte_offset, y->byte_offset); + } else if (key->found && XLAT_MODE_KEY == xlat_get_mode()) { + sprintf(text, "Keyboard Data (#%d): pressed@%d", interface, key->byte_offset); } else { // offsets not found sprintf(text, "Data: offsets not found"); diff --git a/src/gfx_settings.c b/src/gfx_settings.c index fc48ca3..f3dd6cb 100644 --- a/src/gfx_settings.c +++ b/src/gfx_settings.c @@ -27,6 +27,7 @@ lv_dropdown_t *edge_dropdown; lv_slider_t *debounce_dropdown; lv_dropdown_t *trigger_dropdown; lv_dropdown_t *detection_dropdown; +lv_dropdown_t *interface_dropdown; lv_obj_t *prev_screen = NULL; // Pointer to store previous screen LV_IMG_DECLARE(xlat_logo); @@ -92,12 +93,36 @@ static void event_handler(lv_event_t* e) else if (obj == (lv_obj_t *)detection_dropdown) { // Detection mode changed uint16_t sel = lv_dropdown_get_selected(obj); - if (sel == 0) { - // Click - xlat_set_mode(XLAT_MODE_CLICK); - } else { - // Motion - xlat_set_mode(XLAT_MODE_MOTION); + + switch (sel) { + // Motion [M] + case 1: + xlat_set_mode(XLAT_MODE_MOTION); + break; + + // Key [K] + case 2: + xlat_set_mode(XLAT_MODE_KEY); + break; + + // Click [M] + default: + xlat_set_mode(XLAT_MODE_CLICK); + } + } + else if (obj == (lv_obj_t *)interface_dropdown) { + // Interface number changed + uint16_t sel = lv_dropdown_get_selected(obj); + + switch (sel) { + // Auto + case 0: + xlat_set_interface_selection(XLAT_INTERFACE_AUTO); + break; + + // Any specific interface number + default: + xlat_set_interface_selection(XLAT_INTERFACE_0 + sel - 1); } } else { @@ -146,16 +171,26 @@ void gfx_settings_create_page(lv_obj_t *previous_screen) lv_obj_add_event_cb((struct _lv_obj_t *) trigger_dropdown, event_handler, LV_EVENT_VALUE_CHANGED, NULL); - // Click vs. motion detection label + // Click, motion & key detection label lv_obj_t *detection_mode = lv_label_create(settings_screen); lv_label_set_text(detection_mode, "Detection Mode:"); lv_obj_align_to(detection_mode, trigger_label, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 30); - // Click vs. motion detection dropdown + // Click, motion & key detection dropdown detection_dropdown = (lv_dropdown_t *) lv_dropdown_create(settings_screen); - lv_dropdown_set_options((lv_obj_t *) detection_dropdown, "Click\nMotion"); + lv_dropdown_set_options((lv_obj_t *) detection_dropdown, "Click [M]\nMotion [M]\nKey [K]"); lv_obj_add_event_cb((struct _lv_obj_t *) detection_dropdown, event_handler, LV_EVENT_VALUE_CHANGED, NULL); + // Interface selection label + lv_obj_t *interface_label = lv_label_create(settings_screen); + lv_label_set_text(interface_label, "Interface Number:"); + lv_obj_align_to(interface_label, detection_mode, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 30); + + // Interface selection dropdown + interface_dropdown = (lv_dropdown_t *) lv_dropdown_create(settings_screen); + lv_dropdown_set_options((lv_obj_t *) interface_dropdown, "AUTO\n0\n1\n2\n3\n4\n5\n6\n7\n8"); + lv_obj_add_event_cb((struct _lv_obj_t *) interface_dropdown, event_handler, LV_EVENT_VALUE_CHANGED, NULL); + // If we don't add this label, the y-value of the last item will be 0 lv_obj_t *debounce_label2 = lv_label_create(settings_screen); lv_label_set_text(debounce_label2, ""); @@ -173,6 +208,7 @@ void gfx_settings_create_page(lv_obj_t *previous_screen) lv_obj_align((struct _lv_obj_t *) debounce_dropdown, LV_ALIGN_DEFAULT, max_width + widget_gap, lv_obj_get_y(debounce_label) - 10); lv_obj_align((struct _lv_obj_t *) trigger_dropdown, LV_ALIGN_DEFAULT, max_width + widget_gap, lv_obj_get_y(trigger_label) - 10); lv_obj_align((struct _lv_obj_t *) detection_dropdown, LV_ALIGN_DEFAULT, max_width + widget_gap, lv_obj_get_y(detection_mode) - 10); + lv_obj_align((struct _lv_obj_t *) interface_dropdown, LV_ALIGN_DEFAULT, max_width + widget_gap, lv_obj_get_y(interface_label) - 10); // Print all y-values for debugging //printf("edge_label y: %d\n", lv_obj_get_y(edge_label)); @@ -222,7 +258,7 @@ void gfx_settings_create_page(lv_obj_t *previous_screen) lv_dropdown_set_selected((lv_obj_t *) debounce_dropdown, debounce_index); // Display current detection mode - lv_dropdown_set_selected((lv_obj_t *) detection_dropdown, xlat_get_mode() == XLAT_MODE_MOTION); + lv_dropdown_set_selected((lv_obj_t *) detection_dropdown, xlat_get_mode()); // Display current detection edge @@ -231,5 +267,19 @@ void gfx_settings_create_page(lv_obj_t *previous_screen) // Display current auto-trigger level lv_dropdown_set_selected((lv_obj_t *) trigger_dropdown, xlat_auto_trigger_level_is_high()); -} + // Display current interface selection + uint16_t interface_index = 0; + xlat_interface_t interface_selection = xlat_get_interface_selection(); + + switch (interface_selection) { + case XLAT_INTERFACE_AUTO: + interface_index = 0; + break; + + default: + interface_index = 1 + interface_selection - XLAT_INTERFACE_0; + } + + lv_dropdown_set_selected((lv_obj_t *) interface_dropdown, interface_index); +} diff --git a/src/usb/usbh_hid.c b/src/usb/usbh_hid.c index 9d93d4f..8d1399e 100644 --- a/src/usb/usbh_hid.c +++ b/src/usb/usbh_hid.c @@ -20,6 +20,7 @@ #include "usbh_hid_parser.h" #include "xlat.h" #include "usbh_hid_mouse.h" +#include "usbh_hid_keyboard.h" static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost); @@ -65,12 +66,20 @@ static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost) uint8_t num = 0U; uint8_t interface; - // First try to find a Mouse interface, specifically: - interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, HID_MOUSE_BOOT_CODE); + // Handle the AUTO interface detection mode + if (XLAT_INTERFACE_AUTO == xlat_get_interface_selection()) { + // First try to find a Mouse or Keyboard interface depending on the detection mode, specifically: + interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, (XLAT_MODE_KEY == xlat_get_mode()) ? HID_KEYBRD_BOOT_CODE : HID_MOUSE_BOOT_CODE); - // Broaden the search criteria to no specific protocol - if (interface == 0xFFU) { - interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFFU); + // Broaden the search criteria to no specific protocol + if (interface == 0xFFU) { + interface = USBH_FindInterface(phost, phost->pActiveClass->ClassCode, HID_BOOT_CODE, 0xFFU); + } + } + // Use the selected interface + else + { + interface = xlat_get_interface_selection() - XLAT_INTERFACE_0;; } #if 0 @@ -97,6 +106,8 @@ static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost) return USBH_FAIL; } + xlat_set_found_interface(interface); + phost->pActiveClass->pData = (HID_HandleTypeDef *)USBH_malloc(sizeof(HID_HandleTypeDef)); HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; @@ -113,6 +124,7 @@ static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost) /*Decode Bootclass Protocol: Mouse or Keyboard, see HID_KEYBRD_BOOT_CODE, HID_MOUSE_BOOT_CODE */ if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_KEYBRD_BOOT_CODE) { USBH_UsrLog("KeyBoard device found! (iface: %d)", interface); + HID_Handle->Init = USBH_HID_KeyboardInit; } else if (phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol == HID_MOUSE_BOOT_CODE) { USBH_UsrLog("Mouse device found! (iface: %d)", interface); HID_Handle->Init = USBH_HID_MouseInit; diff --git a/src/usb/usbh_hid_keyboard.c b/src/usb/usbh_hid_keyboard.c new file mode 100644 index 0000000..7744ece --- /dev/null +++ b/src/usb/usbh_hid_keyboard.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015 STMicroelectronics. + * Copyright (c) 2023 Finalmouse, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +/* BSPDependencies +- "stm32xxxxx_{eval}{discovery}{nucleo_144}.c" +- "stm32xxxxx_{eval}{discovery}_io.c" +- "stm32xxxxx_{eval}{discovery}{adafruit}_lcd.c" +- "stm32xxxxx_{eval}{discovery}_sdram.c" +EndBSPDependencies */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid_keyboard.h" +#include "usbh_hid_parser.h" + + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_KEYBOARD + * @brief This file includes HID Layer Handlers for USB Host HID class. + * @{ + */ + +/** @defgroup USBH_HID_KEYBOARD_Private_TypesDefinitions + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_KEYBOARD_Private_Defines + * @{ + */ +/** + * @} + */ + + +/** @defgroup USBH_HID_KEYBOARD_Private_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBOARD_Private_FunctionPrototypes + * @{ + */ +static USBH_StatusTypeDef USBH_HID_KeyboardDecode(USBH_HandleTypeDef *phost); + +/** + * @} + */ + + +/** @defgroup USBH_HID_KEYBOARD_Private_Variables + * @{ + */ +HID_KEYBOARD_Info_TypeDef keyboard_info; +uint8_t keyboard_report_data[USBH_HID_KEYBOARD_REPORT_SIZE]; +uint8_t keyboard_rx_report_buf[USBH_HID_KEYBOARD_REPORT_SIZE]; + +/* Structures defining how to access items in a HID keyboard report */ +/* Access key 1 state. */ +static const HID_Report_ItemTypedef prop_k1 = +{ + keyboard_report_data, /*data*/ + 1, /*size*/ + 0, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min value device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + +/* Access key 2 state. */ +static const HID_Report_ItemTypedef prop_k2 = +{ + keyboard_report_data, /*data*/ + 1, /*size*/ + 1, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min value device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + +/* Access key 3 state. */ +static const HID_Report_ItemTypedef prop_k3 = +{ + keyboard_report_data, /*data*/ + 1, /*size*/ + 2, /*shift*/ + 0, /*count (only for array items)*/ + 0, /*signed?*/ + 0, /*min value read can return*/ + 1, /*max value read can return*/ + 0, /*min vale device can report*/ + 1, /*max value device can report*/ + 1 /*resolution*/ +}; + + +/** + * @} + */ + + +/** @defgroup USBH_HID_KEYBOARD_Private_Functions + * @{ + */ + +/** + * @brief USBH_HID_KeyboardInit + * The function init the HID keyboard. + * @param phost: Host handle + * @retval USBH Status + */ +USBH_StatusTypeDef USBH_HID_KeyboardInit(USBH_HandleTypeDef *phost) +{ + uint32_t i; + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + keyboard_info.keys[0] = 0U; + keyboard_info.keys[1] = 0U; + keyboard_info.keys[2] = 0U; + + for (i = 0U; i < sizeof(keyboard_report_data); i++) + { + keyboard_report_data[i] = 0U; + keyboard_rx_report_buf[i] = 0U; + } + + if (HID_Handle->length > sizeof(keyboard_report_data)) + { + HID_Handle->length = (uint16_t)sizeof(keyboard_report_data); + } + HID_Handle->pData = keyboard_rx_report_buf; + + if ((HID_QUEUE_SIZE * sizeof(keyboard_report_data)) > sizeof(phost->device.Data)) { + return USBH_FAIL; + } else { + USBH_HID_FifoInit(&HID_Handle->fifo, phost->device.Data, (uint16_t)(HID_QUEUE_SIZE * sizeof(keyboard_report_data))); + } + + return USBH_OK; +} + +/** + * @brief USBH_HID_GetKeyboardInfo + * The function return keyboard information. + * @param phost: Host handle + * @retval keyboard information + */ +HID_KEYBOARD_Info_TypeDef *USBH_HID_GetKeyboardInfo(USBH_HandleTypeDef *phost) +{ + if (USBH_HID_KeyboardDecode(phost) == USBH_OK) + { + return &keyboard_info; + } + else + { + return NULL; + } +} + +/** + * @brief USBH_HID_KeyboardDecode + * The function decode keyboard data. + * @param phost: Host handle + * @retval USBH Status + */ +static USBH_StatusTypeDef USBH_HID_KeyboardDecode(USBH_HandleTypeDef *phost) +{ + HID_HandleTypeDef *HID_Handle = (HID_HandleTypeDef *) phost->pActiveClass->pData; + + if ((HID_Handle->length == 0U) || (HID_Handle->fifo.buf == NULL)) + { + return USBH_FAIL; + } + /*Fill report */ + if (USBH_HID_FifoRead(&HID_Handle->fifo, &keyboard_report_data, HID_Handle->length) == HID_Handle->length) + { + /*Decode report */ + keyboard_info.keys[0] = (uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_k1, 0U); + keyboard_info.keys[1] = (uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_k2, 0U); + keyboard_info.keys[2] = (uint8_t)HID_ReadItem((HID_Report_ItemTypedef *) &prop_k3, 0U); + + return USBH_OK; + } + return USBH_FAIL; +} + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + + +/** + * @} + */ diff --git a/src/usb/usbh_hid_keyboard.h b/src/usb/usbh_hid_keyboard.h new file mode 100644 index 0000000..3fca22d --- /dev/null +++ b/src/usb/usbh_hid_keyboard.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015 STMicroelectronics. + * Copyright (c) 2023 Finalmouse, LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* Define to prevent recursive ----------------------------------------------*/ +#ifndef __USBH_HID_KEYBOARD_H +#define __USBH_HID_KEYBOARD_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* Includes ------------------------------------------------------------------*/ +#include "usbh_hid.h" + +/** @addtogroup USBH_LIB + * @{ + */ + +/** @addtogroup USBH_CLASS + * @{ + */ + +/** @addtogroup USBH_HID_CLASS + * @{ + */ + +/** @defgroup USBH_HID_KEYBOARD + * @brief This file is the Header file for usbh_hid_keyboard.c + * @{ + */ + + +/** @defgroup USBH_HID_KEYBOARD_Exported_Types + * @{ + */ + +typedef struct _HID_KEYBOARD_Info +{ + uint8_t keys[3]; +} +HID_KEYBOARD_Info_TypeDef; + +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBOARD_Exported_Defines + * @{ + */ +#ifndef USBH_HID_KEYBOARD_REPORT_SIZE +#define USBH_HID_KEYBOARD_REPORT_SIZE (64) //max interrupt transfer size -- was: 0x8U +#endif /* USBH_HID_KEYBOARD_REPORT_SIZE */ +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBOARD_Exported_Macros + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBOARD_Exported_Variables + * @{ + */ +/** + * @} + */ + +/** @defgroup USBH_HID_KEYBOARD_Exported_FunctionsPrototype + * @{ + */ +USBH_StatusTypeDef USBH_HID_KeyboardInit(USBH_HandleTypeDef *phost); +HID_KEYBOARD_Info_TypeDef *USBH_HID_GetKeyboardInfo(USBH_HandleTypeDef *phost); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __USBH_HID_KEYBOARD_H */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + +/** + * @} + */ + diff --git a/src/xlat.c b/src/xlat.c index 359cf7f..0747f3d 100644 --- a/src/xlat.c +++ b/src/xlat.c @@ -43,10 +43,12 @@ static volatile uint_fast8_t gpio_irq_producer = 0; static volatile uint_fast8_t gpio_irq_consumer = 0; // SETTINGS -volatile bool xlat_initialized = false; -static xlat_mode_t xlat_mode = XLAT_MODE_CLICK; -static bool hid_using_reportid = false; -static bool auto_trigger_level_high = false; +volatile bool xlat_initialized = false; +static xlat_mode_t xlat_mode = XLAT_MODE_CLICK; +static bool hid_using_reportid = false; +static bool auto_trigger_level_high = false; +static xlat_interface_t xlat_interface = XLAT_INTERFACE_AUTO; +static uint8_t found_interface = 0xFF; // The Razer optical switches will constantly trigger the GPIO interrupt, while pressed // Waveform looks like this in ASCII art: @@ -69,6 +71,7 @@ static TimerHandle_t xlat_timer_handle; hid_data_location_t button_location; hid_data_location_t x_location; hid_data_location_t y_location; +hid_data_location_t key_location; static inline void hidreport_print_item(HID_ReportItem_t *item) { @@ -180,6 +183,14 @@ static void hidreport_check_item(HID_ReportItem_t *item) } break; + case 0x07: + printf(" Usage.Page: Keyboard/Keypad (0x0007)\n"); + if (!key_location.found) { + key_location.found = true; + key_location.bit_index = item->BitOffset; + } + break; + case 0x09: printf(" Usage.Page: Button (0x0009)\n"); if (!button_location.found) { @@ -261,54 +272,75 @@ static void check_offsets(void) printf("[*] Using reportId, so actual report data is starting at index [1]\n"); } - if (button_location.found) { - if (button_location.bit_index % 8) { - printf("[!] Button found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n", button_location.bit_index); - button_location.found = false; + // Only print offsets relevant for a mouse + if (XLAT_MODE_KEY != xlat_mode) + { + if (button_location.found) { + if (button_location.bit_index % 8) { + printf("[!] Button found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n", button_location.bit_index); + button_location.found = false; + } else { + button_location.byte_offset = button_location.bit_index / 8 + (size_t)hid_using_reportid; + printf("[*] Button found at bit index %d, which is byte %d\n", button_location.bit_index, button_location.bit_index / 8); + printf(" Button byte offset: %d\n", button_location.byte_offset); + } } else { - button_location.byte_offset = button_location.bit_index / 8 + (size_t)hid_using_reportid; - printf("[*] Button found at bit index %d, which is byte %d\n", button_location.bit_index, button_location.bit_index / 8); - printf(" Button byte offset: %d\n", button_location.byte_offset); + button_location.found = false; + printf("[x] Button not found\n"); } - } else { - button_location.found = false; - printf("[x] Button not found\n"); - } - // X offset has to start at a byte boundary - if (x_location.found) { - if (x_location.bit_index % 8) { - printf("[!] X found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n", x_location.bit_index); - x_location.found = false; + // X offset has to start at a byte boundary + if (x_location.found) { + if (x_location.bit_index % 8) { + printf("[!] X found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n", x_location.bit_index); + x_location.found = false; + } else { + x_location.byte_offset = x_location.bit_index / 8 + (size_t)hid_using_reportid; + printf("[*] X found at bit index %d, which is byte %d\n", x_location.bit_index, x_location.bit_index / 8); + printf(" X size: %d bits, %d bytes\n", x_location.bit_size, x_location.bit_size / 8); + printf(" X byte offset: %d\n", x_location.byte_offset); + } } else { - x_location.byte_offset = x_location.bit_index / 8 + (size_t)hid_using_reportid; - printf("[*] X found at bit index %d, which is byte %d\n", x_location.bit_index, x_location.bit_index / 8); - printf(" X size: %d bits, %d bytes\n", x_location.bit_size, x_location.bit_size / 8); - printf(" X byte offset: %d\n", x_location.byte_offset); + x_location.found = false; + printf("[x] X not found\n"); } - } else { - x_location.found = false; - printf("[x] X not found\n"); - } - // Y offset does NOT have to start at a byte boundary, - // but it has to be contiguous to X - // and their total size has to be a multiple of 8 - if (y_location.found) { - if ((y_location.bit_index % 8) && - ((y_location.bit_index - x_location.bit_index) != x_location.bit_size)) { - printf("[!] Y found at bit index %d, which is not a multiple of 8, and not contiguous to X. Currently not supported by XLAT.\n", - y_location.bit_index); + // Y offset does NOT have to start at a byte boundary, + // but it has to be contiguous to X + // and their total size has to be a multiple of 8 + if (y_location.found) { + if ((y_location.bit_index % 8) && + ((y_location.bit_index - x_location.bit_index) != x_location.bit_size)) { + printf("[!] Y found at bit index %d, which is not a multiple of 8, and not contiguous to X. Currently not supported by XLAT.\n", + y_location.bit_index); + y_location.found = false; + } else { + y_location.byte_offset = y_location.bit_index / 8 + (size_t)hid_using_reportid; + printf("[*] Y found at bit index %d, which is byte %d\n", y_location.bit_index, y_location.bit_index / 8); + printf(" Y size: %d bits, %d bytes\n", y_location.bit_size, y_location.bit_size / 8); + printf(" Y byte offset: %d\n", y_location.byte_offset); + } + } else { y_location.found = false; + printf("[x] Y not found\n"); + } + } + // Only print offsets relevant for a keyboard + else + { + if (key_location.found) { + if (key_location.bit_index % 8) { + printf("[!] Key found at bit index %d, which is not a multiple of 8. Currently not supported by XLAT.\n", key_location.bit_index); + key_location.found = false; + } else { + key_location.byte_offset = key_location.bit_index / 8 + (size_t)hid_using_reportid; + printf("[*] Key found at bit index %d, which is byte %d\n", key_location.bit_index, key_location.bit_index / 8); + printf(" Key byte offset: %d\n", key_location.byte_offset); + } } else { - y_location.byte_offset = y_location.bit_index / 8 + (size_t)hid_using_reportid; - printf("[*] Y found at bit index %d, which is byte %d\n", y_location.bit_index, y_location.bit_index / 8); - printf(" Y size: %d bits, %d bytes\n", y_location.bit_size, y_location.bit_size / 8); - printf(" Y byte offset: %d\n", y_location.byte_offset); + key_location.found = false; + printf("[x] Key not found\n"); } - } else { - y_location.found = false; - printf("[x] Y not found\n"); } printf("\n"); @@ -432,6 +464,49 @@ void xlat_usb_hid_event(void) } } } + else if (USBH_HID_GetDeviceType(phost) == HID_KEYBOARD) + { // if the HID is Keyboard + uint8_t hid_raw_data[64]; + + if (USBH_HID_GetRawData(phost, hid_raw_data) == USBH_OK) { + // check reportId for ULX + if (hid_using_reportid && (hid_raw_data[0] != 0x01)) { + // ignore + goto out; + } + + if (xlat_mode == XLAT_MODE_KEY) { + // FOR KEY/PRESSES: + // The correct location of key data is determined by parsing the HID descriptor + // This information is available in the key_location struct + + // First, check if the location was found + if (!key_location.found) { + return; + } + + static uint8_t prev_key = 0; + uint8_t key = hid_raw_data[key_location.byte_offset]; + + // Check if the key state has changed + if (key != prev_key) { + // Only measure on key PRESS, not on RELEASE + if (key > prev_key) { + // Save the captured USB event timestamp + last_usb_timestamp_us = hevt->timestamp; + + printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); + printf("Key: K=0x%02x @ %lu\n", key, hevt->timestamp); + + calculate_gpio_to_usb_time(); + } + } + + // Save previous state + prev_key = key; + } + } + } #if 0 if (USBH_HID_GetDeviceType(phost) == HID_KEYBOARD) { // if the HID is Keyboard @@ -617,6 +692,26 @@ bool xlat_auto_trigger_level_is_high(void) return auto_trigger_level_high; } +void xlat_set_interface_selection(xlat_interface_t number) +{ + xlat_interface = number; +} + +xlat_interface_t xlat_get_interface_selection() +{ + return xlat_interface; +} + +void xlat_set_found_interface(uint8_t number) +{ + found_interface = number; +} + +uint8_t xlat_get_found_interface() +{ + return found_interface; +} + void xlat_print_measurement(void) { // print the new measurement to the console in csv format @@ -672,12 +767,18 @@ hid_data_location_t * xlat_get_y_location(void) return &y_location; } +hid_data_location_t * xlat_get_key_location(void) +{ + return &key_location; +} + void xlat_clear_locations(void) { printf("Clearing locations\n"); button_location.found = false; x_location.found = false; y_location.found = false; + key_location.found = false; } void xlat_init(void) diff --git a/src/xlat.h b/src/xlat.h index 2f29a83..ed31fb8 100644 --- a/src/xlat.h +++ b/src/xlat.h @@ -46,8 +46,22 @@ typedef enum latency_type { typedef enum xlat_mode { XLAT_MODE_CLICK, XLAT_MODE_MOTION, + XLAT_MODE_KEY, } xlat_mode_t; +typedef enum xlat_interface { + XLAT_INTERFACE_AUTO = -1, + XLAT_INTERFACE_0 = 0, + XLAT_INTERFACE_1, + XLAT_INTERFACE_2, + XLAT_INTERFACE_3, + XLAT_INTERFACE_4, + XLAT_INTERFACE_5, + XLAT_INTERFACE_6, + XLAT_INTERFACE_7, + XLAT_INTERFACE_8, +} xlat_interface_t; + extern volatile bool xlat_initialized; void xlat_init(void); @@ -83,10 +97,17 @@ enum xlat_mode xlat_get_mode(void); hid_data_location_t * xlat_get_button_location(void); hid_data_location_t * xlat_get_x_location(void); hid_data_location_t * xlat_get_y_location(void); +hid_data_location_t * xlat_get_key_location(void); void xlat_clear_locations(void); void xlat_auto_trigger_action(void); void xlat_auto_trigger_level_set(bool high); bool xlat_auto_trigger_level_is_high(void); +void xlat_set_interface_selection(xlat_interface_t number); +xlat_interface_t xlat_get_interface_selection(); + +void xlat_set_found_interface(uint8_t number); +uint8_t xlat_get_found_interface(); + #endif //XLAT_H