USB HOST логика (раскладываем по полочкам)

Совет : без логического анализатора в 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 и он пока пустой, не путаем)

фотка 1

В конце устанавливаем следующий кейс 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->pDataphost->pActiveClass->pData->pData

Потом после инициализации постоянно вызывается HID_SYNC, HID_GET_DATA, HID_POLL.

Пакет HID_SYNC периодически посылается с целью получить в ответ (HID_GET_DATA) скан код нажатой клавиши.

фотка 2

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

фотка 3

Вот собственно и все пока.

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