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