Совет : без логического анализатора в USB дебрях делать нечего...
Кратко для справки алгоритм USB HOST библиотеки от STM
Все начинается с
MX_USB_HOST_Init();
.
MX_USB_HOST_Init() один раз в начале иницилизирует USB и запускает поток(задачу) USBH_Process_OS , который ждет подключения девайса (у нас клавиатура).
Для ожидания в потоке USBH_Process_OS постоянно запускает USBH_Process, который отрабатывает этапы (кейсы/case):
HOST_IDLE
HOST_DEV_WAIT_FOR_ATTACHMENT
HOST_DEV_ATTACHED
HOST_ENUMERATION
HOST_INPUT
HOST_SET_CONFIGURATION
HOST_SET_WAKEUP_FEATURE
HOST_CHECK_CLASS
HOST_CLASS_REQUEST
HOST_CLASS
HOST_DEV_DISCONNECTED
HOST_DEV_ATTACHED
тут в уже проскакивает сообщение (трассировка):
USB Device Attached
HOST_ENUMERATION
трассировка :
PID: 3002h
VID: 566h
Address (#1) assigned.
Manufacturer : N/A
Product : N/A
Serial Number : N/A
Enumeration done.
This device has only 1 configuration.
HOST_INPUT
HOST_SET_CONFIGURATION
трассировка :
Default configuration set.
HOST_CHECK_CLASS
Когда дело доходит до HOST_CHECK_CLASS - это уже инициализация конкретно подключаемого устройства (т.е. его класса).
Вход по инструкции
phost->pActiveClass->Init(phost)
трассировка:
Switching to Interface (#0)
Class : 3h
SubClass : 1h
Protocol : 1h
KeyBoard device found!
HID class started.
usbh_hid.c
(есть тут выделение памяти USBH_malloc)
У каждого устройства (точнее его класса) есть указатель на функцию инициализации класса USBH_HID_InterfaceInit:
USBH_ClassTypeDef HID_Class =
{
"HID",
USB_HID_CLASS,
USBH_HID_InterfaceInit,
USBH_HID_InterfaceDeInit,
USBH_HID_ClassRequest,
USBH_HID_Process,
USBH_HID_SOFProcess,
NULL,
};
Через инструкцию
phost->pActiveClass->Init(phost)
попадаем на USBH_HID_InterfaceInit , где происходит злосчастное выделение памяти (с ним очень много проблем, точнее с не выделением памяти) под класс нашего устройства (например, под HID устройство):
phost->pActiveClass->pData = (HID_HandleTypeDef *) pvPortMalloc (sizeof(HID_HandleTypeDef));
На картинке зафиксировано содержание
phost->pActiveClass->pData
(у которого есть также свой pData и он пока пустой, не путаем)

В конце устанавливаем следующий кейс HID_INIT.
HOST_CLASS_REQUEST
Переходим по времени к инициализации класса уже конкретного устройства.
Инструкция входа
phost->pActiveClass->Requests(phost);
. Попадаем в USBH_HID_ClassRequest :
HID_REQ_INIT банально пропускается
HID_REQ_GET_HID_DESC посылается запрос девайсу USBH_HID_GetHIDDescriptor, он отвечает
HID_REQ_GET_REPORT_DESC посылается запрос девайсу USBH_HID_GetHIDReportDescriptor,
HID_REQ_SET_IDLE ...
HID_REQ_SET_PROTOCOL ...
HID_REQ_IDLE ...
HOST_CLASS
вход по инструкции
phost->pActiveClass->BgndProcess(phost);
.
Постоянно долбим в потоке USBH_Process / HOST_CLASS_REQUEST -> USBH_HID_Process с последовательным переходом по кейсам (точнее под/кейсам):
HID_INIT иницализация
HID_IDLE запрос USBH_HID_GetReport (ожет не поддерживаться подключаемым девайсом)
HID_SYNC периодическая посылка пакета SYNC для чтения кода нажатой клавиши от клавиатуры
HID_GET_DATA и потом попытка получить данные от клавиатуры
HID_POLL тоже постоянная долбежка
Тут уже происходит до-инициализия и строятся такие цепочки :
phost->pActiveClass->pData
phost->pActiveClass->pData->pData
Потом после инициализации постоянно вызывается HID_SYNC, HID_GET_DATA, HID_POLL.
Пакет HID_SYNC периодически посылается с целью получить в ответ (HID_GET_DATA) скан код нажатой клавиши.

и вот в какой-то момент получаем нужный ответ :

Вот собственно и все пока.
Будьте готовы , что стек USB часто не работает в разных частных случаях. Не выделяется память по USBH_malloc и т.д. Все это надо решать метом изучения и правки кода.