diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 47f0e28..98a1b45 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,10 +3,10 @@ name: Build XLAT firmware on: push: branches: - - main + - '**' pull_request: branches: - - main + - '**' jobs: build: diff --git a/src/gfx_main.c b/src/gfx_main.c index 69b4deb..d3d3672 100644 --- a/src/gfx_main.c +++ b/src/gfx_main.c @@ -289,12 +289,12 @@ void gfx_set_byte_offsets_text(void) uint8_t interface = xlat_get_found_interface(); 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); + sprintf(text, "Mouse Data (#%d): id@%d click@%d motion@%d,%d", interface, xlat_get_reportid(), 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); + sprintf(text, "Keyboard Data (#%d): id@%d pressed@%d", interface, xlat_get_reportid(), key->byte_offset); } else { // offsets not found - sprintf(text, "Data: offsets not found"); + sprintf(text, (XLAT_MODE_KEY == xlat_get_mode()) ? "Keyboard Data: offsets not found" : "Mouse Data: offsets not found"); } lv_checkbox_set_text(hid_offsets_label, text); diff --git a/src/usb/usb_host.c b/src/usb/usb_host.c index ddb62bc..b49080f 100644 --- a/src/usb/usb_host.c +++ b/src/usb/usb_host.c @@ -82,11 +82,12 @@ static void USBH_UserProcess (USBH_HandleTypeDef *phost, uint8_t id) break; } + case HOST_USER_NO_SUPPORTED_CLASS: case HOST_USER_CLASS_ACTIVE: { // Compose vidpid string uint16_t vid = phost->device.DevDesc.idVendor; uint16_t pid = phost->device.DevDesc.idProduct; - printf("USB HID device connected: 0x%04X:%04X\n", vid, pid); + printf("USB device connected: 0x%04X:%04X\n", vid, pid); memset(vidpid_string, 0, sizeof(vidpid_string)); snprintf(vidpid_string, sizeof(vidpid_string), "0x%04X:%04X", vid, pid); vidpid_string[sizeof(vidpid_string) - 1] = '\0'; diff --git a/src/usb/usbh_core.c b/src/usb/usbh_core.c index 0d7d17c..8fa7473 100644 --- a/src/usb/usbh_core.c +++ b/src/usb/usbh_core.c @@ -20,6 +20,7 @@ #include "usbh_core.h" #include "usbh_hid.h" #include "usb_host.h" +#include "Common/Common.h" /** @addtogroup USBH_LIB @@ -480,6 +481,8 @@ USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) { __IO USBH_StatusTypeDef status = USBH_FAIL; uint8_t idx = 0U; + uint8_t i = 0U; + bool stop = false; /* check for Host pending port disconnect event */ if (phost->device.is_disconnected == 1U) @@ -706,12 +709,16 @@ USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) { phost->pActiveClass = NULL; - for (idx = 0U; idx < USBH_MAX_NUM_SUPPORTED_CLASS; idx++) + for (idx = 0U, stop = false; idx < USBH_MAX_NUM_SUPPORTED_CLASS && !stop; idx++) { - if (phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[0].bInterfaceClass) + // Check if the device has an interface where the class is supported + for (i = 0U; i < USBH_MAX_NUM_INTERFACES && !stop; i++) { - phost->pActiveClass = phost->pClass[idx]; - break; + if (phost->pClass[idx]->ClassCode == phost->device.CfgDesc.Itf_Desc[i].bInterfaceClass) + { + phost->pActiveClass = phost->pClass[idx]; + stop = true; + } } } @@ -722,8 +729,11 @@ USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) phost->gState = HOST_CLASS_REQUEST; USBH_UsrLog("%s class started.", phost->pActiveClass->Name); - /* Inform user that a class has been activated */ - phost->pUser(phost, HOST_USER_CLASS_SELECTED); + if (phost->pUser != NULL) + { + /* Inform user that a class has been activated */ + phost->pUser(phost, HOST_USER_CLASS_SELECTED); + } } else { @@ -735,6 +745,12 @@ USBH_StatusTypeDef USBH_Process(USBH_HandleTypeDef *phost) { phost->gState = HOST_ABORT_STATE; USBH_UsrLog("No registered class for this device."); + + if (phost->pUser != NULL) + { + /* Inform user that a class has been activated */ + phost->pUser(phost, HOST_USER_NO_SUPPORTED_CLASS); + } } } diff --git a/src/usb/usbh_core.h b/src/usb/usbh_core.h index b8d65b5..a159a59 100644 --- a/src/usb/usbh_core.h +++ b/src/usb/usbh_core.h @@ -58,6 +58,7 @@ extern "C" { #define HOST_USER_CONNECTION 0x04U #define HOST_USER_DISCONNECTION 0x05U #define HOST_USER_UNRECOVERED_ERROR 0x06U +#define HOST_USER_NO_SUPPORTED_CLASS 0x07U /** diff --git a/src/usb/usbh_hid.c b/src/usb/usbh_hid.c index 8d1399e..67dda2f 100644 --- a/src/usb/usbh_hid.c +++ b/src/usb/usbh_hid.c @@ -129,9 +129,9 @@ static USBH_StatusTypeDef USBH_HID_InterfaceInit(USBH_HandleTypeDef *phost) USBH_UsrLog("Mouse device found! (iface: %d)", interface); HID_Handle->Init = USBH_HID_MouseInit; } else { - USBH_UsrLog("bInterfaceProtocol %d not supported. Assuming Mouse... (iface: %d)", - phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol, interface); - HID_Handle->Init = USBH_HID_MouseInit; + USBH_UsrLog("bInterfaceProtocol %d not supported. Assuming %s... (iface: %d)", + phost->device.CfgDesc.Itf_Desc[interface].bInterfaceProtocol, (XLAT_MODE_KEY == xlat_get_mode()) ? "Keyboard" : "Mouse", interface); + HID_Handle->Init = (XLAT_MODE_KEY == xlat_get_mode()) ? USBH_HID_KeyboardInit : USBH_HID_MouseInit; } HID_Handle->state = USBH_HID_INIT; @@ -272,8 +272,11 @@ static USBH_StatusTypeDef USBH_HID_ClassRequest(USBH_HandleTypeDef *phost) if (classReqStatus == USBH_OK) { HID_Handle->ctl_state = USBH_HID_REQ_IDLE; - /* all requests performed*/ - phost->pUser(phost, HOST_USER_CLASS_ACTIVE); + if (phost->pUser != NULL) + { + /* all requests performed*/ + phost->pUser(phost, HOST_USER_CLASS_ACTIVE); + } status = USBH_OK; } else if (classReqStatus == USBH_NOT_SUPPORTED) { USBH_ErrLog("Control error: HID: Device Set protocol request failed"); @@ -537,7 +540,7 @@ USBH_StatusTypeDef USBH_HID_SetIdle(USBH_HandleTypeDef *phost, phost->Control.setup.b.bRequest = USB_HID_SET_IDLE; phost->Control.setup.b.wValue.w = (uint16_t)(((uint32_t)duration << 8U) | (uint32_t)reportId); - phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wIndex.w = phost->device.current_interface; phost->Control.setup.b.wLength.w = 0U; return USBH_CtlReq(phost, NULL, 0U); @@ -568,7 +571,7 @@ USBH_StatusTypeDef USBH_HID_SetReport(USBH_HandleTypeDef *phost, phost->Control.setup.b.bRequest = USB_HID_SET_REPORT; phost->Control.setup.b.wValue.w = (uint16_t)(((uint32_t)reportType << 8U) | (uint32_t)reportId); - phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wIndex.w = phost->device.current_interface; phost->Control.setup.b.wLength.w = reportLen; return USBH_CtlReq(phost, reportBuff, (uint16_t)reportLen); @@ -599,7 +602,7 @@ USBH_StatusTypeDef USBH_HID_GetReport(USBH_HandleTypeDef *phost, phost->Control.setup.b.bRequest = USB_HID_GET_REPORT; phost->Control.setup.b.wValue.w = (uint16_t)(((uint32_t)reportType << 8U) | (uint32_t)reportId); - phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wIndex.w = phost->device.current_interface; phost->Control.setup.b.wLength.w = reportLen; return USBH_CtlReq(phost, reportBuff, (uint16_t)reportLen); @@ -625,7 +628,7 @@ USBH_StatusTypeDef USBH_HID_SetProtocol(USBH_HandleTypeDef *phost, phost->Control.setup.b.wValue.w = 1U; } - phost->Control.setup.b.wIndex.w = 0U; + phost->Control.setup.b.wIndex.w = phost->device.current_interface; phost->Control.setup.b.wLength.w = 0U; return USBH_CtlReq(phost, NULL, 0U); @@ -698,7 +701,7 @@ HID_TypeTypeDef USBH_HID_GetDeviceType(USBH_HandleTypeDef *phost) } else if (InterfaceProtocol == HID_MOUSE_BOOT_CODE) { type = HID_MOUSE; } else { - type = HID_MOUSE; // fallback to mouse as well + type = HID_UNKNOWN; } } return type; diff --git a/src/xlat.c b/src/xlat.c index 0747f3d..6f8d00f 100644 --- a/src/xlat.c +++ b/src/xlat.c @@ -45,7 +45,7 @@ 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 uint8_t hid_reportid = 0; static bool auto_trigger_level_high = false; static xlat_interface_t xlat_interface = XLAT_INTERFACE_AUTO; static uint8_t found_interface = 0xFF; @@ -169,6 +169,8 @@ static void hidreport_check_item(HID_ReportItem_t *item) x_location.found = true; x_location.bit_index = item->BitOffset; x_location.bit_size = item->Attributes.BitSize; + + hid_reportid = item->ReportID; } break; @@ -178,6 +180,8 @@ static void hidreport_check_item(HID_ReportItem_t *item) y_location.found = true; y_location.bit_index = item->BitOffset; y_location.bit_size = item->Attributes.BitSize; + + hid_reportid = item->ReportID; } break; } @@ -188,6 +192,8 @@ static void hidreport_check_item(HID_ReportItem_t *item) if (!key_location.found) { key_location.found = true; key_location.bit_index = item->BitOffset; + + hid_reportid = item->ReportID; } break; @@ -196,6 +202,8 @@ static void hidreport_check_item(HID_ReportItem_t *item) if (!button_location.found) { button_location.found = true; button_location.bit_index = item->BitOffset; + + hid_reportid = item->ReportID; } break; @@ -268,8 +276,8 @@ static void check_offsets(void) { printf("\n"); - if (hid_using_reportid) { - printf("[*] Using reportId, so actual report data is starting at index [1]\n"); + if (hid_reportid) { + printf("[*] Using reportId '%d', so actual report data is starting at index [1]\n", hid_reportid); } // Only print offsets relevant for a mouse @@ -280,7 +288,7 @@ static void check_offsets(void) 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; + button_location.byte_offset = button_location.bit_index / 8 + (hid_reportid ? 1 : 0); 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); } @@ -295,7 +303,7 @@ static void check_offsets(void) 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; + x_location.byte_offset = x_location.bit_index / 8 + (hid_reportid ? 1 : 0); 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); @@ -315,7 +323,7 @@ static void check_offsets(void) y_location.bit_index); y_location.found = false; } else { - y_location.byte_offset = y_location.bit_index / 8 + (size_t)hid_using_reportid; + y_location.byte_offset = y_location.bit_index / 8 + (hid_reportid ? 1 : 0); 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); @@ -333,7 +341,7 @@ static void check_offsets(void) 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; + key_location.byte_offset = key_location.bit_index / 8 + (hid_reportid ? 1 : 0); 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); } @@ -382,129 +390,113 @@ void xlat_usb_hid_event(void) struct hid_event *hevt = evt.value.p; USBH_HandleTypeDef *phost = hevt->phost; - if (USBH_HID_GetDeviceType(phost) == HID_MOUSE) - { // if the HID is Mouse - uint8_t hid_raw_data[64]; + 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 (USBH_HID_GetRawData(phost, hid_raw_data) == USBH_OK) { + // check reportId for ULX + if (hid_reportid && (hid_raw_data[0] != hid_reportid)) { + // ignore + goto out; + } #if 0 - printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); - for (int i = 0; i < 8 /*sizeof(hid_raw_data) */; i++) { - printf("%02x ", hid_raw_data[i]); - } - printf("\n"); + printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); + for (int i = 0; i < 8 /*sizeof(hid_raw_data) */; i++) { + printf("%02x ", hid_raw_data[i]); + } + printf("\n"); #endif - if (xlat_mode == XLAT_MODE_CLICK) { - // FOR BUTTONS/CLICKS: - // The correct location of button data is determined by parsing the HID descriptor - // This information is available in the button_location struct - - // First, check if the location was found - if (!button_location.found) { - return; - } + if (xlat_mode == XLAT_MODE_CLICK) { + // FOR BUTTONS/CLICKS: + // The correct location of button data is determined by parsing the HID descriptor + // This information is available in the button_location struct - static uint8_t prev_button = 0; - uint8_t button = hid_raw_data[button_location.byte_offset]; + // First, check if the location was found + if (!button_location.found) { + return; + } - // Check if the button state has changed - if (button != prev_button) { - // Only measure on button PRESS, not on RELEASE - if (button > prev_button) { - // Save the captured USB event timestamp - last_usb_timestamp_us = hevt->timestamp; + static uint8_t prev_button = 0; + uint8_t button = hid_raw_data[button_location.byte_offset]; - printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); - printf("Button: B=0x%02x @ %lu\n", button, hevt->timestamp); + // Check if the button state has changed + if (button != prev_button) { + // Only measure on button PRESS, not on RELEASE + if (button > prev_button) { + // Save the captured USB event timestamp + last_usb_timestamp_us = hevt->timestamp; - calculate_gpio_to_usb_time(); - } + printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); + printf("Button: B=0x%02x @ %lu\n", button, hevt->timestamp); + + calculate_gpio_to_usb_time(); } + } - // Save previous state - prev_button = button; + // Save previous state + prev_button = button; + } + else if (xlat_mode == XLAT_MODE_MOTION) { + // FOR MOTION: + // The correct location of button data is determined by parsing the HID descriptor + // This information is available in the [x|y]_location structs + + // First, check if the locations were found + if ((!x_location.found) || (!y_location.found)) { + return; } - else if (xlat_mode == XLAT_MODE_MOTION) { - // FOR MOTION: - // The correct location of button data is determined by parsing the HID descriptor - // This information is available in the [x|y]_location structs - - // First, check if the locations were found - if ((!x_location.found) || (!y_location.found)) { - return; - } - // Check X and Y data is contiguous - if ((x_location.byte_offset + x_location.bit_size / 8) != y_location.byte_offset) { - return; - } + // Check X and Y data is contiguous + if ((x_location.byte_offset + x_location.bit_size / 8) != y_location.byte_offset) { + return; + } - size_t start_idx = x_location.byte_offset; - size_t length = (x_location.bit_size + y_location.bit_size) / 8; + size_t start_idx = x_location.byte_offset; + size_t length = (x_location.bit_size + y_location.bit_size) / 8; - // Loop over the data and check for non-zero values - // In case there is non-zero data, call calculate_gpio_to_usb_tine(); - for (size_t idx = start_idx; idx < start_idx + length; idx++) { - if (hid_raw_data[idx]) { - // Save the captured USB event timestamp - last_usb_timestamp_us = hevt->timestamp; + // Loop over the data and check for non-zero values + // In case there is non-zero data, call calculate_gpio_to_usb_tine(); + for (size_t idx = start_idx; idx < start_idx + length; idx++) { + if (hid_raw_data[idx]) { + // Save the captured USB event timestamp + last_usb_timestamp_us = hevt->timestamp; - printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); - printf("Motion: X=0x%02x, Y=0x%02x @ %lu\n", hid_raw_data[x_location.byte_offset], hid_raw_data[y_location.byte_offset], hevt->timestamp); + printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); + printf("Motion: X=0x%02x, Y=0x%02x @ %lu\n", hid_raw_data[x_location.byte_offset], hid_raw_data[y_location.byte_offset], hevt->timestamp); - calculate_gpio_to_usb_time(); - break; // stop at the first bit of motion in this report - } + calculate_gpio_to_usb_time(); + break; // stop at the first bit of motion in this report } } } - } - 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; - } + else 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 - 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; - } + // 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]; + 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; + // 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); + printf("[%5lu] hid@%lu: ", xTaskGetTickCount(), hevt->timestamp); + printf("Key: K=0x%02x @ %lu\n", key, hevt->timestamp); - calculate_gpio_to_usb_time(); - } + calculate_gpio_to_usb_time(); } - - // Save previous state - prev_key = key; } + + // Save previous state + prev_key = key; } } @@ -644,14 +636,14 @@ void xlat_reset_latency(void) } } -void xlat_set_using_reportid(bool use_reportid) +void xlat_set_reportid(uint8_t reportid) { - hid_using_reportid = use_reportid; + hid_reportid = reportid; } -bool xlat_get_using_reportid(void) +uint8_t xlat_get_reportid(void) { - return hid_using_reportid; + return hid_reportid; } static void xlat_timer_callback(TimerHandle_t xTimer) @@ -738,8 +730,7 @@ void xlat_parse_hid_descriptor(uint8_t *desc, size_t desc_size) } // Check if using reportIDs: - hid_using_reportid = report_info.UsingReportIDs; - printf("Using reportIDs: %d\n", hid_using_reportid); + printf("Using reportIDs: %d\n", report_info.UsingReportIDs); // Find click and motion data offsets check_offsets(); diff --git a/src/xlat.h b/src/xlat.h index ed31fb8..5f778b2 100644 --- a/src/xlat.h +++ b/src/xlat.h @@ -86,8 +86,8 @@ uint32_t xlat_get_last_usb_timestamp_us(void); uint32_t xlat_get_last_button_timestamp_us(void); -void xlat_set_using_reportid(bool use_reportid); -bool xlat_get_using_reportid(void); +void xlat_set_reportid(uint8_t reportid); +uint8_t xlat_get_reportid(void); void xlat_parse_hid_descriptor(uint8_t *desc, size_t desc_size);