mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/usb/host/hid_example_update_v5.1' into 'release/v5.1'
USB Host (HID): HID Host example update (backport v5.1) See merge request espressif/esp-idf!24532
This commit is contained in:
commit
fed2e21594
@ -1,3 +0,0 @@
|
|||||||
idf_component_register(SRCS "hid_host.c"
|
|
||||||
PRIV_REQUIRES usb
|
|
||||||
INCLUDE_DIRS "include")
|
|
File diff suppressed because it is too large
Load Diff
@ -1,147 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Subclass
|
|
||||||
*
|
|
||||||
* @see 4.2 Subclass, p.8 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_SUBCLASS_NO_SUBCLASS = 0x00,
|
|
||||||
HID_SUBCLASS_BOOT_INTERFACE = 0x01
|
|
||||||
} __attribute__((packed)) hid_subclass_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Protocols
|
|
||||||
*
|
|
||||||
* @see 4.3 Protocols, p.9 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_PROTOCOL_NONE = 0x00,
|
|
||||||
HID_PROTOCOL_KEYBOARD = 0x01,
|
|
||||||
HID_PROTOCOL_MOUSE = 0x02,
|
|
||||||
HID_PROTOCOL_MAX
|
|
||||||
} __attribute__((packed)) hid_protocol_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Descriptor
|
|
||||||
*
|
|
||||||
* @see 6.2.1 HID Descriptor, p.22 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
uint8_t bLength; // Numeric expression that is the total size of the HID descriptor
|
|
||||||
uint8_t bDescriptorType; // Constant name specifying type of HID descriptor
|
|
||||||
uint16_t bcdHID; // Numeric expression identifying the HIDClass Specification release
|
|
||||||
int8_t bCountryCode; // Numeric expression identifying country code of the localized hardware
|
|
||||||
uint8_t bNumDescriptors; // Numeric expression specifying the number of class descriptors (always at least one i.e. Report descriptor.)
|
|
||||||
uint8_t bReportDescriptorType; // Constant name identifying type of class descriptor. See Section 7.1.2: Set_Descriptor Request for a table of class descriptor constants
|
|
||||||
uint16_t wReportDescriptorLength; // Numeric expression that is the total size of the Report descriptor
|
|
||||||
// Optional descriptors may follow further
|
|
||||||
} __attribute__((packed)) hid_descriptor_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Country Codes
|
|
||||||
*
|
|
||||||
* @see 6.2.1 HID Descriptor, p.23 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
HID_COUNTRY_CODE_NOT_SUPPORTED = 0x00,
|
|
||||||
HID_COUNTRY_CODE_ARABIC = 0x01,
|
|
||||||
HID_COUNTRY_CODE_BELGIAN = 0x02,
|
|
||||||
HID_COUNTRY_CODE_CANADIAN_BILINGUAL = 0x03,
|
|
||||||
HID_COUNTRY_CODE_CANADIAN_FRENCH = 0x04,
|
|
||||||
HID_COUNTRY_CODE_CZECH = 0x05,
|
|
||||||
HID_COUNTRY_CODE_DANISH = 0x06,
|
|
||||||
HID_COUNTRY_CODE_FINNISH = 0x07,
|
|
||||||
HID_COUNTRY_CODE_FRENCH = 0x08,
|
|
||||||
HID_COUNTRY_CODE_GERMAN = 0x09,
|
|
||||||
HID_COUNTRY_CODE_GREEK = 0x0A,
|
|
||||||
HID_COUNTRY_CODE_HEBREW = 0x0B,
|
|
||||||
HID_COUNTRY_CODE_HUNGARY = 0x0C,
|
|
||||||
HID_COUNTRY_CODE_ISO = 0x0D,
|
|
||||||
HID_COUNTRY_CODE_ITALIAN = 0x0E,
|
|
||||||
HID_COUNTRY_CODE_JAPAN = 0x0F,
|
|
||||||
HID_COUNTRY_CODE_KOREAN = 0x10,
|
|
||||||
HID_COUNTRY_CODE_LATIN_AMERICAN = 0x11,
|
|
||||||
HID_COUNTRY_CODE_NETHERLANDS = 0x12,
|
|
||||||
HID_COUNTRY_CODE_NORWEGIAN = 0x13,
|
|
||||||
HID_COUNTRY_CODE_PERSIAN = 0x14,
|
|
||||||
HID_COUNTRY_CODE_POLAND = 0x15,
|
|
||||||
HID_COUNTRY_CODE_PORTUGUESE = 0x16,
|
|
||||||
HID_COUNTRY_CODE_RUSSIA = 0x17,
|
|
||||||
HID_COUNTRY_CODE_SLOVAKIA = 0x18,
|
|
||||||
HID_COUNTRY_CODE_SPANISH = 0x19,
|
|
||||||
HID_COUNTRY_CODE_SWEDISH = 0x1A,
|
|
||||||
HID_COUNTRY_CODE_SWISS_F = 0x1B,
|
|
||||||
HID_COUNTRY_CODE_SWISS_G = 0x1C,
|
|
||||||
HID_COUNTRY_CODE_SWITZERLAND = 0x1D,
|
|
||||||
HID_COUNTRY_CODE_TAIWAN = 0x1E,
|
|
||||||
HID_COUNTRY_CODE_TURKISH_Q = 0x1F,
|
|
||||||
HID_COUNTRY_CODE_UK = 0x20,
|
|
||||||
HID_COUNTRY_CODE_US = 0x21,
|
|
||||||
HID_COUNTRY_CODE_YUGOSLAVIA = 0x22,
|
|
||||||
HID_COUNTRY_CODE_TURKISH_F = 0x23
|
|
||||||
} __attribute__((packed)) hid_country_code_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Class Descriptor Types
|
|
||||||
*
|
|
||||||
* @see 7.1, p.49 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_CLASS_DESCRIPTOR_TYPE_HID = 0x21,
|
|
||||||
HID_CLASS_DESCRIPTOR_TYPE_REPORT = 0x22,
|
|
||||||
HID_CLASS_DESCRIPTOR_TYPE_PHYSICAL = 0x23
|
|
||||||
} __attribute__((packed)) hid_class_descritpor_type_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Class-Specific Requests
|
|
||||||
*
|
|
||||||
* @see 7.2, p.50 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_CLASS_SPECIFIC_REQ_GET_REPORT = 0x01,
|
|
||||||
HID_CLASS_SPECIFIC_REQ_GET_IDLE = 0x02,
|
|
||||||
HID_CLASS_SPECIFIC_REQ_GET_PROTOCOL = 0x03,
|
|
||||||
HID_CLASS_SPECIFIC_REQ_SET_REPORT = 0x09,
|
|
||||||
HID_CLASS_SPECIFIC_REQ_SET_IDLE = 0x0A,
|
|
||||||
HID_CLASS_SPECIFIC_REQ_SET_PROTOCOL = 0x0B
|
|
||||||
} __attribute__((packed)) hid_class_specific_req_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Report Types
|
|
||||||
*
|
|
||||||
* @see 7.2.1, p.51 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_REPORT_TYPE_INPUT = 0x01,
|
|
||||||
HID_REPORT_TYPE_OUTPUT = 0x02,
|
|
||||||
HID_REPORT_TYPE_FEATURE = 0x03,
|
|
||||||
} __attribute__((packed)) hid_report_type_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Report protocol
|
|
||||||
*
|
|
||||||
* @see 7.2.5/7.2.6, p.54 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_REPORT_PROTOCOL_BOOT = 0x00,
|
|
||||||
HID_REPORT_PROTOCOL_REPORT = 0x01,
|
|
||||||
HID_REPORT_PROTOCOL_MAX
|
|
||||||
} __attribute__((packed)) hid_report_protocol_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif //__cplusplus
|
|
@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <wchar.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
|
|
||||||
#include "hid.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct hid_host_device *hid_host_device_handle_t; /**< Handle to a HID */
|
|
||||||
typedef struct hid_interface *hid_host_interface_handle_t; /**< Handle to a particular HID interface */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Interface input report callback
|
|
||||||
*
|
|
||||||
* @param[in] data Pointer to buffer containing input report data
|
|
||||||
* @param[in] length Data length
|
|
||||||
*/
|
|
||||||
typedef void (*hid_input_report_cb_t)(const uint8_t *const data, const int length);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID event containing event type and associated device handle
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
enum {
|
|
||||||
HID_DEVICE_CONNECTED, /**< HID device has been connected to the system.*/
|
|
||||||
HID_DEVICE_DISCONNECTED, /**< HID device has been disconnected from the system.*/
|
|
||||||
} event;
|
|
||||||
union {
|
|
||||||
uint8_t address; /**< Address of connected HID device.*/
|
|
||||||
hid_host_device_handle_t handle; /**< HID device handle to disconnected device.*/
|
|
||||||
} device;
|
|
||||||
} hid_host_event_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID interface event for application logic
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_DEVICE_INTERFACE_INIT = 0x00, /**< Interface available for application logic */
|
|
||||||
HID_DEVICE_INTERFACE_CLAIM, /**< Interface was claimed */
|
|
||||||
HID_DEVICE_INTERFACE_RELEASE, /**< Interface was released */
|
|
||||||
HID_DEVICE_INTERFACE_TRANSFER_ERROR /**< Interface transfer error occurred */
|
|
||||||
} hid_interface_event_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID Host interface event containing event type and associated parameters
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
hid_interface_event_t event; /**< USB HID Interface event */
|
|
||||||
struct interface_event_param {
|
|
||||||
uint8_t dev_addr; /**< USB Device address */
|
|
||||||
uint8_t num; /**< USB Interface number */
|
|
||||||
hid_protocol_t proto; /**< USB HID Interface protocol */
|
|
||||||
} interface;
|
|
||||||
} hid_host_interface_event_t;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID host event callback.
|
|
||||||
*
|
|
||||||
* @param[in] event mass storage event
|
|
||||||
*/
|
|
||||||
typedef void (*hid_host_event_cb_t)(const hid_host_event_t *event, void *arg);
|
|
||||||
|
|
||||||
typedef void (*hid_host_interface_event_cb_t)(const hid_host_interface_event_t *event, void *arg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID configuration structure.
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
bool create_background_task; /**< When set to true, background task handling USB events is created.
|
|
||||||
Otherwise user has to periodically call hid_host_handle_events function */
|
|
||||||
size_t task_priority; /**< Task priority of created background task */
|
|
||||||
size_t stack_size; /**< Stack size of created background task */
|
|
||||||
BaseType_t core_id; /**< Select core on which background task will run or tskNO_AFFINITY */
|
|
||||||
hid_host_event_cb_t callback; /**< Callback invoked when HID event occurs. Must not be NULL. */
|
|
||||||
void *callback_arg; /**< User provided argument passed to callback */
|
|
||||||
} hid_host_driver_config_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint8_t dev_addr;
|
|
||||||
hid_host_interface_event_cb_t iface_event_cb; /**< Callback invoked when HID event occurs. Must not be NULL. */
|
|
||||||
void *iface_event_arg; /**< User provided argument passed to callback */
|
|
||||||
} hid_host_device_config_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
hid_protocol_t proto;
|
|
||||||
hid_input_report_cb_t callback;
|
|
||||||
} hid_host_interface_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Install USB Host HID Class driver
|
|
||||||
*
|
|
||||||
* @param[in] config configuration structure HID to create
|
|
||||||
* @return esp_err_r
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_install(const hid_host_driver_config_t *config);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Uninstall HID Class driver
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_uninstall(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Host USB event handler
|
|
||||||
*
|
|
||||||
* If HID Host install was made with create_background_task=false configuration,
|
|
||||||
* application needs to handle USB Host events itself.
|
|
||||||
* Do not used id HID host install was made with create_background_task=true configuration
|
|
||||||
*
|
|
||||||
* @param[in] arg Pointer to handler argument
|
|
||||||
* @return none
|
|
||||||
*/
|
|
||||||
void hid_host_event_handler_task(void *arg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Initialization of HID device.
|
|
||||||
*
|
|
||||||
* @param[in] hid_host_dev_config Pointer to HID Host device configuration structure
|
|
||||||
* @param[out] hid_device_handle Pointer to HID device handle
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_install_device(const hid_host_device_config_t *hid_host_dev_config,
|
|
||||||
hid_host_device_handle_t *hid_device_handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deinitialization of HID device.
|
|
||||||
*
|
|
||||||
* @param[in] hid_device_handle Device handle obtained from hid_host_install_device function
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_uninstall_device(hid_host_device_handle_t hid_device_handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Print configuration descriptor.
|
|
||||||
*
|
|
||||||
* @param[in] hid_device_handle Device handle obtained from hid_host_install_device function
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_print_descriptors(hid_host_device_handle_t hid_device_handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID Interface claim
|
|
||||||
*
|
|
||||||
* @param[in] iface_config Pointer to Interface configuration structure
|
|
||||||
* @param[out] iface_handle Pointer to Interface handle
|
|
||||||
* @param[in] esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_claim_interface(const hid_host_interface_config_t *iface_config,
|
|
||||||
hid_host_interface_handle_t *iface_handle);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID Interface release
|
|
||||||
*
|
|
||||||
* @param[in] iface_handle Interface handle obtained from hid_host_claim_interface function
|
|
||||||
* @param[in] esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t hid_host_release_interface(hid_host_interface_handle_t iface_handle);
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif //__cplusplus
|
|
@ -1,292 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------------------------------------ HID usage keys ---------------------------------------------------------------
|
|
||||||
/**
|
|
||||||
* @brief HID Keys
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_KEY_NO_PRESS = 0x00,
|
|
||||||
HID_KEY_ROLLOVER = 0x01,
|
|
||||||
HID_KEY_POST_FAIL = 0x02,
|
|
||||||
HID_KEY_ERROR_UNDEFINED = 0x03,
|
|
||||||
HID_KEY_A = 0x04,
|
|
||||||
HID_KEY_B = 0x05,
|
|
||||||
HID_KEY_C = 0x06,
|
|
||||||
HID_KEY_D = 0x07,
|
|
||||||
HID_KEY_E = 0x08,
|
|
||||||
HID_KEY_F = 0x09,
|
|
||||||
HID_KEY_G = 0x0A,
|
|
||||||
HID_KEY_H = 0x0B,
|
|
||||||
HID_KEY_I = 0x0C,
|
|
||||||
HID_KEY_J = 0x0D,
|
|
||||||
HID_KEY_K = 0x0E,
|
|
||||||
HID_KEY_L = 0x0F,
|
|
||||||
HID_KEY_M = 0x10,
|
|
||||||
HID_KEY_N = 0x11,
|
|
||||||
HID_KEY_O = 0x12,
|
|
||||||
HID_KEY_P = 0x13,
|
|
||||||
HID_KEY_Q = 0x14,
|
|
||||||
HID_KEY_R = 0x15,
|
|
||||||
HID_KEY_S = 0x16,
|
|
||||||
HID_KEY_T = 0x17,
|
|
||||||
HID_KEY_U = 0x18,
|
|
||||||
HID_KEY_V = 0x19,
|
|
||||||
HID_KEY_W = 0x1A,
|
|
||||||
HID_KEY_X = 0x1B,
|
|
||||||
HID_KEY_Y = 0x1C,
|
|
||||||
HID_KEY_Z = 0x1D,
|
|
||||||
HID_KEY_1 = 0x1E,
|
|
||||||
HID_KEY_2 = 0x1F,
|
|
||||||
HID_KEY_3 = 0x20,
|
|
||||||
HID_KEY_4 = 0x21,
|
|
||||||
HID_KEY_5 = 0x22,
|
|
||||||
HID_KEY_6 = 0x23,
|
|
||||||
HID_KEY_7 = 0x24,
|
|
||||||
HID_KEY_8 = 0x25,
|
|
||||||
HID_KEY_9 = 0x26,
|
|
||||||
HID_KEY_0 = 0x27,
|
|
||||||
HID_KEY_ENTER = 0x28,
|
|
||||||
HID_KEY_ESC = 0x29,
|
|
||||||
HID_KEY_DEL = 0x2A,
|
|
||||||
HID_KEY_TAB = 0x2B,
|
|
||||||
HID_KEY_SPACE = 0x2C,
|
|
||||||
HID_KEY_MINUS = 0x2D,
|
|
||||||
HID_KEY_EQUAL = 0x2E,
|
|
||||||
HID_KEY_OPEN_BRACKET = 0x2F,
|
|
||||||
HID_KEY_CLOSE_BRACKET = 0x30,
|
|
||||||
HID_KEY_BACK_SLASH = 0x31,
|
|
||||||
HID_KEY_SHARP = 0x32,
|
|
||||||
HID_KEY_COLON = 0x33,
|
|
||||||
HID_KEY_QUOTE = 0x34,
|
|
||||||
HID_KEY_TILDE = 0x35,
|
|
||||||
HID_KEY_LESS = 0x36,
|
|
||||||
HID_KEY_GREATER = 0x37,
|
|
||||||
HID_KEY_SLASH = 0x38,
|
|
||||||
HID_KEY_CAPS_LOCK = 0x39,
|
|
||||||
HID_KEY_F1 = 0x3A,
|
|
||||||
HID_KEY_F2 = 0x3B,
|
|
||||||
HID_KEY_F3 = 0x3C,
|
|
||||||
HID_KEY_F4 = 0x3D,
|
|
||||||
HID_KEY_F5 = 0x3E,
|
|
||||||
HID_KEY_F6 = 0x3F,
|
|
||||||
HID_KEY_F7 = 0x40,
|
|
||||||
HID_KEY_F8 = 0x41,
|
|
||||||
HID_KEY_F9 = 0x42,
|
|
||||||
HID_KEY_F10 = 0x43,
|
|
||||||
HID_KEY_F11 = 0x44,
|
|
||||||
HID_KEY_F12 = 0x45,
|
|
||||||
HID_KEY_PRINT_SCREEN = 0x46,
|
|
||||||
HID_KEY_SCROLL_LOCK = 0x47,
|
|
||||||
HID_KEY_PAUSE = 0x48,
|
|
||||||
HID_KEY_INSERT = 0x49,
|
|
||||||
HID_KEY_HOME = 0x4A,
|
|
||||||
HID_KEY_PAGEUP = 0x4B,
|
|
||||||
HID_KEY_DELETE = 0x4C,
|
|
||||||
HID_KEY_END = 0x4D,
|
|
||||||
HID_KEY_PAGEDOWN = 0x4E,
|
|
||||||
HID_KEY_RIGHT = 0x4F,
|
|
||||||
HID_KEY_LEFT = 0x50,
|
|
||||||
HID_KEY_DOWN = 0x51,
|
|
||||||
HID_KEY_UP = 0x52,
|
|
||||||
HID_KEY_NUM_LOCK = 0x53,
|
|
||||||
HID_KEY_KEYPAD_DIV = 0x54,
|
|
||||||
HID_KEY_KEYPAD_MUL = 0x55,
|
|
||||||
HID_KEY_KEYPAD_SUB = 0x56,
|
|
||||||
HID_KEY_KEYPAD_ADD = 0x57,
|
|
||||||
HID_KEY_KEYPAD_ENTER = 0x58,
|
|
||||||
HID_KEY_KEYPAD_1 = 0x59,
|
|
||||||
HID_KEY_KEYPAD_2 = 0x5A,
|
|
||||||
HID_KEY_KEYPAD_3 = 0x5B,
|
|
||||||
HID_KEY_KEYPAD_4 = 0x5C,
|
|
||||||
HID_KEY_KEYPAD_5 = 0x5D,
|
|
||||||
HID_KEY_KEYPAD_6 = 0x5E,
|
|
||||||
HID_KEY_KEYPAD_7 = 0x5F,
|
|
||||||
HID_KEY_KEYPAD_8 = 0x60,
|
|
||||||
HID_KEY_KEYPAD_9 = 0x61,
|
|
||||||
HID_KEY_KEYPAD_0 = 0x62,
|
|
||||||
HID_KEY_KEYPAD_DELETE = 0x63,
|
|
||||||
HID_KEY_KEYPAD_SLASH = 0x64,
|
|
||||||
HID_KEY_APPLICATION = 0x65,
|
|
||||||
HID_KEY_POWER = 0x66,
|
|
||||||
HID_KEY_KEYPAD_EQUAL = 0x67,
|
|
||||||
HID_KEY_F13 = 0x68,
|
|
||||||
HID_KEY_F14 = 0x69,
|
|
||||||
HID_KEY_F15 = 0x6A,
|
|
||||||
HID_KEY_F16 = 0x6B,
|
|
||||||
HID_KEY_F17 = 0x6C,
|
|
||||||
HID_KEY_F18 = 0x6D,
|
|
||||||
HID_KEY_F19 = 0x6E,
|
|
||||||
HID_KEY_F20 = 0x6F,
|
|
||||||
HID_KEY_F21 = 0x70,
|
|
||||||
HID_KEY_F22 = 0x71,
|
|
||||||
HID_KEY_F23 = 0x72,
|
|
||||||
HID_KEY_F24 = 0x73,
|
|
||||||
HID_KEY_EXECUTE = 0x74,
|
|
||||||
HID_KEY_HELP = 0x75,
|
|
||||||
HID_KEY_MENU = 0x76,
|
|
||||||
HID_KEY_SELECT = 0x77,
|
|
||||||
HID_KEY_STOP = 0x78,
|
|
||||||
HID_KEY_AGAIN = 0x79,
|
|
||||||
HID_KEY_UNDO = 0x7A,
|
|
||||||
HID_KEY_CUT = 0x7B,
|
|
||||||
HID_KEY_COPY = 0x7C,
|
|
||||||
HID_KEY_PASTE = 0x7D,
|
|
||||||
HID_KEY_FIND = 0x7E,
|
|
||||||
HID_KEY_MUTE = 0x7F,
|
|
||||||
HID_KEY_VOLUME_UP = 0x80,
|
|
||||||
HID_KEY_VOLUME_DOWN = 0x81,
|
|
||||||
HID_KEY_LOCKING_CAPS_LOCK = 0x82,
|
|
||||||
HID_KEY_LOCKING_NUM_LOCK = 0x83,
|
|
||||||
HID_KEY_LOCKING_SCROLL_LOCK = 0x84,
|
|
||||||
HID_KEY_KEYPAD_COMMA = 0x85,
|
|
||||||
HID_KEY_KEYPAD_EQUAL_SIGN = 0x86,
|
|
||||||
HID_KEY_INTERNATIONAL_1 = 0x87,
|
|
||||||
HID_KEY_INTERNATIONAL_2 = 0x88,
|
|
||||||
HID_KEY_INTERNATIONAL_3 = 0x89,
|
|
||||||
HID_KEY_INTERNATIONAL_4 = 0x8A,
|
|
||||||
HID_KEY_INTERNATIONAL_5 = 0x8B,
|
|
||||||
HID_KEY_INTERNATIONAL_6 = 0x8C,
|
|
||||||
HID_KEY_INTERNATIONAL_7 = 0x8D,
|
|
||||||
HID_KEY_INTERNATIONAL_8 = 0x8E,
|
|
||||||
HID_KEY_INTERNATIONAL_9 = 0x8F,
|
|
||||||
HID_KEY_LANG_1 = 0x90,
|
|
||||||
HID_KEY_LANG_2 = 0x91,
|
|
||||||
HID_KEY_LANG_3 = 0x92,
|
|
||||||
HID_KEY_LANG_4 = 0x93,
|
|
||||||
HID_KEY_LANG_5 = 0x94,
|
|
||||||
HID_KEY_LANG_6 = 0x95,
|
|
||||||
HID_KEY_LANG_7 = 0x96,
|
|
||||||
HID_KEY_LANG_8 = 0x97,
|
|
||||||
HID_KEY_LANG_9 = 0x98,
|
|
||||||
HID_KEY_ALTERNATE_ERASE = 0x99,
|
|
||||||
HID_KEY_SYSREQ = 0x9A,
|
|
||||||
HID_KEY_CANCEL = 0x9B,
|
|
||||||
HID_KEY_CLEAR = 0x9C,
|
|
||||||
HID_KEY_PRIOR = 0x9D,
|
|
||||||
HID_KEY_RETURN = 0x9E,
|
|
||||||
HID_KEY_SEPARATOR = 0x9F,
|
|
||||||
HID_KEY_OUT = 0xA0,
|
|
||||||
HID_KEY_OPER = 0xA1,
|
|
||||||
HID_KEY_CLEAR_AGAIN = 0xA2,
|
|
||||||
HID_KEY_CRSEL = 0xA3,
|
|
||||||
HID_KEY_EXSEL = 0xA4,
|
|
||||||
HID_KEY_KEYPAD_00 = 0xB0,
|
|
||||||
HID_KEY_KEYPAD_000 = 0xB1,
|
|
||||||
HID_KEY_THOUSANDS_SEPARATOR = 0xB2,
|
|
||||||
HID_KEY_DECIMAL_SEPARATOR = 0xB3,
|
|
||||||
HID_KEY_CURRENCY_UNIT = 0xB4,
|
|
||||||
HID_KEY_CURRENCY_SUB_UNIT = 0xB5,
|
|
||||||
HID_KEY_KEYPAD_OPEN_PARENTHESIS = 0xB6,
|
|
||||||
HID_KEY_KEYPAD_CLOSE_PARENTHESIS = 0xB7,
|
|
||||||
HID_KEY_KEYPAD_OPEN_BRACE = 0xB8,
|
|
||||||
HID_KEY_KEYPAD_CLOSE_BRACE = 0xB9,
|
|
||||||
HID_KEY_KEYPAD_TAB = 0xBA,
|
|
||||||
HID_KEY_KEYPAD_BACKSPACE = 0xBB,
|
|
||||||
HID_KEY_KEYPAD_A = 0xBC,
|
|
||||||
HID_KEY_KEYPAD_B = 0xBD,
|
|
||||||
HID_KEY_KEYPAD_C = 0xBE,
|
|
||||||
HID_KEY_KEYPAD_D = 0xBF,
|
|
||||||
HID_KEY_KEYPAD_E = 0xC0,
|
|
||||||
HID_KEY_KEYPAD_F = 0xC1,
|
|
||||||
HID_KEY_KEYPAD_XOR = 0xC2,
|
|
||||||
HID_KEY_KEYPAD_CARET = 0xC3,
|
|
||||||
HID_KEY_KEYPAD_PERCENT = 0xC4,
|
|
||||||
HID_KEY_KEYPAD_LESSER = 0xC5,
|
|
||||||
HID_KEY_KEYPAD_GREATER = 0xC6,
|
|
||||||
HID_KEY_KEYPAD_AND = 0xC7,
|
|
||||||
HID_KEY_KEYPAD_LOGICAL_AND = 0xC8,
|
|
||||||
HID_KEY_KEYPAD_OR = 0xC9,
|
|
||||||
HID_KEY_KEYPAD_LOGICAL_OR = 0xCA,
|
|
||||||
HID_KEY_KEYPAD_COLON = 0xCB,
|
|
||||||
HID_KEY_KEYPAD_SHARP = 0xCC,
|
|
||||||
HID_KEY_KEYPAD_SPACE = 0xCD,
|
|
||||||
HID_KEY_KEYPAD_AT = 0xCE,
|
|
||||||
HID_KEY_KEYPAD_BANG = 0xCF,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_STORE = 0xD0,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_RECALL = 0xD1,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_CLEAD = 0xD2,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_ADD = 0xD3,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_SUBSTRACT = 0xD4,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_MULTIPLY = 0xD5,
|
|
||||||
HID_KEY_KEYPAD_MEMORY_DIVIDE = 0xD6,
|
|
||||||
HID_KEY_KEYPAD_SIGN = 0xD7,
|
|
||||||
HID_KEY_KEYPAD_CLEAR = 0xD8,
|
|
||||||
HID_KEY_KEYPAD_CLEAR_ENTRY = 0xD9,
|
|
||||||
HID_KEY_KEYPAD_BINARY = 0xDA,
|
|
||||||
HID_KEY_KEYPAD_OCTAL = 0xDB,
|
|
||||||
HID_KEY_KEYPAD_DECIMAL = 0xDC,
|
|
||||||
HID_KEY_KEYPAD_HEXADECIMAL = 0xDD,
|
|
||||||
HID_KEY_LEFT_CONTROL = 0xE0,
|
|
||||||
HID_KEY_LEFT_SHIFT = 0xE1,
|
|
||||||
HID_KEY_LEFT_ALT = 0xE2,
|
|
||||||
HID_KEY_LEFT_GUI = 0xE3,
|
|
||||||
HID_KEY_RIGHT_CONTROL = 0xE0,
|
|
||||||
HID_KEY_RIGHT_SHIFT = 0xE1,
|
|
||||||
HID_KEY_RIGHT_ALT = 0xE2,
|
|
||||||
HID_KEY_RIGHT_GUI = 0xE3
|
|
||||||
} __attribute__((packed)) hid_key_t;
|
|
||||||
|
|
||||||
// Modifier bit mask
|
|
||||||
#define HID_LEFT_CONTROL (1 << 0)
|
|
||||||
#define HID_LEFT_SHIFT (1 << 1)
|
|
||||||
#define HID_LEFT_ALT (1 << 2)
|
|
||||||
#define HID_LEFT_GUI (1 << 3)
|
|
||||||
#define HID_RIGHT_CONTROL (1 << 4)
|
|
||||||
#define HID_RIGHT_SHIFT (1 << 5)
|
|
||||||
#define HID_RIGHT_ALT (1 << 6)
|
|
||||||
#define HID_RIGHT_GUI (1 << 7)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Keyboard Key number for Boot Interface
|
|
||||||
*
|
|
||||||
* @see B.1, p.60 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
HID_KEYBOARD_KEY_NUMBER0 = 0,
|
|
||||||
HID_KEYBOARD_KEY_NUMBER1,
|
|
||||||
HID_KEYBOARD_KEY_NUMBER2,
|
|
||||||
HID_KEYBOARD_KEY_NUMBER3,
|
|
||||||
HID_KEYBOARD_KEY_NUMBER4,
|
|
||||||
HID_KEYBOARD_KEY_NUMBER5,
|
|
||||||
HID_KEYBOARD_KEY_MAX,
|
|
||||||
} hid_keyboard_key_number_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Keyboard Input Report for Boot Interfaces
|
|
||||||
*
|
|
||||||
* @see B.1, p.60 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint8_t left_ctr: 1;
|
|
||||||
uint8_t left_shift: 1;
|
|
||||||
uint8_t left_alt: 1;
|
|
||||||
uint8_t left_gui: 1;
|
|
||||||
uint8_t rigth_ctr: 1;
|
|
||||||
uint8_t right_shift: 1;
|
|
||||||
uint8_t right_alt: 1;
|
|
||||||
uint8_t right_gui: 1;
|
|
||||||
};
|
|
||||||
uint8_t val;
|
|
||||||
} modifier;
|
|
||||||
uint8_t reserved;
|
|
||||||
uint8_t key[HID_KEYBOARD_KEY_MAX];
|
|
||||||
} __attribute__((packed)) hid_keyboard_input_report_boot_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif //__cplusplus
|
|
@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Mouse Input Report for Boot Interfaces
|
|
||||||
*
|
|
||||||
* @see B.1, p.60 of Device Class Definition for Human Interface Devices (HID) Version 1.11
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
uint8_t button1: 1;
|
|
||||||
uint8_t button2: 1;
|
|
||||||
uint8_t button3: 1;
|
|
||||||
uint8_t reserved: 5;
|
|
||||||
};
|
|
||||||
uint8_t val;
|
|
||||||
} buttons;
|
|
||||||
int8_t x_displacement;
|
|
||||||
int8_t y_displacement;
|
|
||||||
} __attribute__((packed)) hid_mouse_input_report_boot_t;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif //__cplusplus
|
|
@ -1,5 +0,0 @@
|
|||||||
#This is the project CMakeLists.txt file for the test subproject
|
|
||||||
cmake_minimum_required(VERSION 3.16)
|
|
||||||
|
|
||||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
|
||||||
project(test_app_hid_basic)
|
|
@ -1,3 +0,0 @@
|
|||||||
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
|
||||||
| ----------------- | -------- | -------- |
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
|||||||
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
|
|
||||||
# the component can be registered as WHOLE_ARCHIVE
|
|
||||||
idf_component_register(SRC_DIRS "." "../../../"
|
|
||||||
INCLUDE_DIRS "." "../../../include" ${CMAKE_CURRENT_BINARY_DIR}
|
|
||||||
REQUIRES usb unity esp_common
|
|
||||||
WHOLE_ARCHIVE)
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "esp_heap_caps.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "unity.h"
|
|
||||||
#include "unity_test_utils.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
#include "hid_host.h"
|
|
||||||
#include "test_hid_basic.h"
|
|
||||||
|
|
||||||
void setUp(void)
|
|
||||||
{
|
|
||||||
unity_utils_record_free_mem();
|
|
||||||
}
|
|
||||||
|
|
||||||
void tearDown(void)
|
|
||||||
{
|
|
||||||
unity_utils_evaluate_leaks();
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
// ____ ___ ___________________ __ __
|
|
||||||
// | | \/ _____/\______ \ _/ |_ ____ _______/ |_
|
|
||||||
// | | /\_____ \ | | _/ \ __\/ __ \ / ___/\ __\.
|
|
||||||
// | | / / \ | | \ | | \ ___/ \___ \ | |
|
|
||||||
// |______/ /_______ / |______ / |__| \___ >____ > |__|
|
|
||||||
// \/ \/ \/ \/
|
|
||||||
printf(" ____ ___ ___________________ __ __ \r\n");
|
|
||||||
printf("| | \\/ _____/\\______ \\ _/ |_ ____ _______/ |_ \r\n");
|
|
||||||
printf("| | /\\_____ \\ | | _/ \\ __\\/ __ \\ / ___/\\ __\\\r\n");
|
|
||||||
printf("| | / / \\ | | \\ | | \\ ___/ \\___ \\ | | \r\n");
|
|
||||||
printf("|______/ /_______ / |______ / |__| \\___ >____ > |__| \r\n");
|
|
||||||
printf(" \\/ \\/ \\/ \\/ \r\n");
|
|
||||||
|
|
||||||
unity_utils_setup_heap_record(80);
|
|
||||||
unity_utils_set_leak_level(20);
|
|
||||||
unity_run_menu();
|
|
||||||
}
|
|
@ -1,379 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "unity.h"
|
|
||||||
#include "unity_test_utils.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "usb/usb_host.h"
|
|
||||||
|
|
||||||
#include "hid_host.h"
|
|
||||||
#include "hid_usage_keyboard.h"
|
|
||||||
#include "hid_usage_mouse.h"
|
|
||||||
|
|
||||||
#include "test_hid_basic.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
HOST_NO_CLIENT = 0x1,
|
|
||||||
HOST_ALL_FREE = 0x2,
|
|
||||||
DEVICE_CONNECTED = 0x4,
|
|
||||||
DEVICE_DISCONNECTED = 0x8,
|
|
||||||
DEVICE_ADDRESS_MASK = 0xFF0,
|
|
||||||
} test_app_event_t;
|
|
||||||
|
|
||||||
static EventGroupHandle_t test_usb_flags;
|
|
||||||
hid_host_device_handle_t test_hid_device = NULL;
|
|
||||||
TaskHandle_t test_usb_event_task_handle;
|
|
||||||
SemaphoreHandle_t test_semaphore;
|
|
||||||
|
|
||||||
// ----------------------- Private -------------------------
|
|
||||||
/**
|
|
||||||
* @brief USB HID Host event callback. Handle such event as device connection and removing
|
|
||||||
*
|
|
||||||
* @param[in] event HID Host device event
|
|
||||||
* @param[in] arg Pointer to arguments, does not used
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void test_hid_host_event_callback(const hid_host_event_t *event, void *arg)
|
|
||||||
{
|
|
||||||
if (event->event == HID_DEVICE_CONNECTED) {
|
|
||||||
// Obtained USB device address is placed after application events
|
|
||||||
xEventGroupSetBits(test_usb_flags, DEVICE_CONNECTED | (event->device.address << 4));
|
|
||||||
} else if (event->event == HID_DEVICE_DISCONNECTED) {
|
|
||||||
xEventGroupSetBits(test_usb_flags, DEVICE_DISCONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief USB HID Host interface callback
|
|
||||||
*
|
|
||||||
* @param[in] event HID Host interface event
|
|
||||||
* @param[in] arg Pointer to arguments, does not used
|
|
||||||
*/
|
|
||||||
static void test_hid_host_interface_event_callback(const hid_host_interface_event_t *event, void *arg)
|
|
||||||
{
|
|
||||||
switch (event->event) {
|
|
||||||
case HID_DEVICE_INTERFACE_INIT:
|
|
||||||
printf("Found Interface number %d, protocol %s\n",
|
|
||||||
event->interface.num,
|
|
||||||
(event->interface.proto == HID_PROTOCOL_KEYBOARD)
|
|
||||||
? "Keyboard"
|
|
||||||
: "Mouse");
|
|
||||||
break;
|
|
||||||
case HID_DEVICE_INTERFACE_TRANSFER_ERROR:
|
|
||||||
case HID_DEVICE_INTERFACE_CLAIM:
|
|
||||||
case HID_DEVICE_INTERFACE_RELEASE:
|
|
||||||
default:
|
|
||||||
// ... do nothing here for now
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Handle common USB host library events
|
|
||||||
*
|
|
||||||
* @param[in] args Pointer to arguments, does not used
|
|
||||||
*/
|
|
||||||
static void test_handle_usb_events(void *args)
|
|
||||||
{
|
|
||||||
while (1) {
|
|
||||||
uint32_t event_flags;
|
|
||||||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
|
||||||
|
|
||||||
// Release devices once all clients has deregistered
|
|
||||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
|
||||||
usb_host_device_free_all();
|
|
||||||
xEventGroupSetBits(test_usb_flags, HOST_NO_CLIENT);
|
|
||||||
}
|
|
||||||
// Give ready_to_uninstall_usb semaphore to indicate that USB Host library
|
|
||||||
// can be deinitialized, and terminate this task.
|
|
||||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
|
||||||
xEventGroupSetBits(test_usb_flags, HOST_ALL_FREE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Create global semaphore
|
|
||||||
*/
|
|
||||||
static void test_create_semaphore(void)
|
|
||||||
{
|
|
||||||
test_semaphore = xSemaphoreCreateBinary();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Deletes global semaphore
|
|
||||||
*/
|
|
||||||
static void test_delete_semaphore(void)
|
|
||||||
{
|
|
||||||
vSemaphoreDelete(test_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Keyboard report callback
|
|
||||||
*
|
|
||||||
* Keyboard report length == size of keyboard boot report
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void test_hid_host_keyboard_report_callback(const uint8_t *const data, const int length)
|
|
||||||
{
|
|
||||||
printf("Keyboard report length %d\n", length);
|
|
||||||
TEST_ASSERT_EQUAL(sizeof(hid_keyboard_input_report_boot_t), length);
|
|
||||||
xSemaphoreGive(test_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Mouse report callback
|
|
||||||
*
|
|
||||||
* Mouse report length >= size of mouse boot report
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void test_hid_host_mouse_report_callback(const uint8_t *const data, const int length)
|
|
||||||
{
|
|
||||||
printf("Mouse report length %d\n", length);
|
|
||||||
TEST_ASSERT_GREATER_OR_EQUAL(sizeof(hid_mouse_input_report_boot_t), length);
|
|
||||||
xSemaphoreGive(test_semaphore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Waits global semaphore for timeout
|
|
||||||
*/
|
|
||||||
static bool test_wait_semaphore_timeout(unsigned int ms)
|
|
||||||
{
|
|
||||||
return ( xSemaphoreTake(test_semaphore, pdMS_TO_TICKS(ms)) )
|
|
||||||
? true
|
|
||||||
: false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Keyboard report length test
|
|
||||||
*
|
|
||||||
* - Claim Keyboard interface
|
|
||||||
* - Wait Keyboard interface report callback for 5 sec
|
|
||||||
* - Release Keyboard interface
|
|
||||||
*/
|
|
||||||
static void test_hid_keyboard_report_length(void)
|
|
||||||
{
|
|
||||||
hid_host_interface_handle_t keyboard_handle;
|
|
||||||
hid_host_interface_config_t keyboard_iface_config = {
|
|
||||||
.proto = HID_PROTOCOL_KEYBOARD,
|
|
||||||
.callback = test_hid_host_keyboard_report_callback,
|
|
||||||
};
|
|
||||||
|
|
||||||
// claim keyboard interface
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_claim_interface(&keyboard_iface_config, &keyboard_handle) );
|
|
||||||
// wait report
|
|
||||||
printf("Please, press any keyboard key ...\n");
|
|
||||||
fflush(stdout);
|
|
||||||
test_wait_semaphore_timeout(5000);
|
|
||||||
// release keyboard interface
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_release_interface(keyboard_handle) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID Mouse report length test
|
|
||||||
*
|
|
||||||
* - Claim Mouse interface
|
|
||||||
* - Wait Mouse interface report callback for 5 sec
|
|
||||||
* - Release Mouse interface
|
|
||||||
*/
|
|
||||||
static void test_hid_mouse_report_length(void)
|
|
||||||
{
|
|
||||||
hid_host_interface_handle_t mouse_handle;
|
|
||||||
hid_host_interface_config_t mouse_iface_config = {
|
|
||||||
.proto = HID_PROTOCOL_MOUSE,
|
|
||||||
.callback = test_hid_host_mouse_report_callback,
|
|
||||||
};
|
|
||||||
// claim mouse interface
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_claim_interface(&mouse_iface_config, &mouse_handle) );
|
|
||||||
// wait report
|
|
||||||
printf("Please, move mouse or press any button ...\n");
|
|
||||||
fflush(stdout);
|
|
||||||
test_wait_semaphore_timeout(5000);
|
|
||||||
// release mouse interface
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_release_interface(mouse_handle) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------- Public -------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Setups HID
|
|
||||||
*
|
|
||||||
* - Create events handle
|
|
||||||
* - Create usb_events task
|
|
||||||
* - Install USB Host driver
|
|
||||||
* - Install HID Host driver
|
|
||||||
*/
|
|
||||||
void test_hid_setup(void)
|
|
||||||
{
|
|
||||||
test_usb_flags = xEventGroupCreate();
|
|
||||||
const usb_host_config_t host_config = { .intr_flags = ESP_INTR_FLAG_LEVEL1 };
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_install(&host_config) );
|
|
||||||
|
|
||||||
xTaskCreate(test_handle_usb_events, "usb_events", 4096, NULL, 2, &test_usb_event_task_handle);
|
|
||||||
|
|
||||||
// hid host driver config
|
|
||||||
const hid_host_driver_config_t hid_host_config = {
|
|
||||||
.create_background_task = true,
|
|
||||||
.task_priority = 5,
|
|
||||||
.stack_size = 4096,
|
|
||||||
.callback = test_hid_host_event_callback,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_install(&hid_host_config) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Waits HID connection and install
|
|
||||||
*
|
|
||||||
* - Wait events: DEVICE_CONNECTED, DEVICE_ADDRESS_MASK
|
|
||||||
* - On DEVICE_ADDRESS_MASK install HID Host device driver and return handle
|
|
||||||
*
|
|
||||||
* @return hid_host_device_handle_t HID Device handle
|
|
||||||
*/
|
|
||||||
hid_host_device_handle_t test_hid_wait_connection_and_install(void)
|
|
||||||
{
|
|
||||||
TEST_ASSERT_NULL(test_hid_device);
|
|
||||||
|
|
||||||
printf("Please, insert HID device ...\n");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
EventBits_t event = xEventGroupWaitBits(test_usb_flags,
|
|
||||||
DEVICE_CONNECTED | DEVICE_ADDRESS_MASK,
|
|
||||||
pdTRUE,
|
|
||||||
pdFALSE,
|
|
||||||
portMAX_DELAY);
|
|
||||||
|
|
||||||
if (event & DEVICE_CONNECTED) {
|
|
||||||
xEventGroupClearBits(test_usb_flags, DEVICE_CONNECTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event & DEVICE_ADDRESS_MASK) {
|
|
||||||
xEventGroupClearBits(test_usb_flags, DEVICE_ADDRESS_MASK);
|
|
||||||
|
|
||||||
const hid_host_device_config_t hid_host_device_config = {
|
|
||||||
.dev_addr = (event & DEVICE_ADDRESS_MASK) >> 4,
|
|
||||||
.iface_event_cb = test_hid_host_interface_event_callback,
|
|
||||||
.iface_event_arg = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_install_device(&hid_host_device_config, &test_hid_device) );
|
|
||||||
}
|
|
||||||
|
|
||||||
return test_hid_device;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Test HID Wait device removal
|
|
||||||
*
|
|
||||||
* - Wait events: DEVICE_DISCONNECTED
|
|
||||||
* - On DEVICE_DISCONNECTED proceed
|
|
||||||
*/
|
|
||||||
void test_hid_wait_for_removal(void)
|
|
||||||
{
|
|
||||||
printf("Please, remove HID device ...\n");
|
|
||||||
fflush(stdout);
|
|
||||||
|
|
||||||
EventBits_t event = xEventGroupWaitBits(test_usb_flags,
|
|
||||||
DEVICE_DISCONNECTED,
|
|
||||||
pdTRUE,
|
|
||||||
pdFALSE,
|
|
||||||
portMAX_DELAY);
|
|
||||||
|
|
||||||
if (event & DEVICE_DISCONNECTED) {
|
|
||||||
xEventGroupClearBits(test_usb_flags, DEVICE_DISCONNECTED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Uninstalls HID device by handle obtained from test_hid_wait_connection_and_install()
|
|
||||||
*
|
|
||||||
* - Wait events: DEVICE_DISCONNECTED
|
|
||||||
* - On DEVICE_DISCONNECTED proceed
|
|
||||||
*/
|
|
||||||
void test_hid_uninstall_hid_device(hid_host_device_handle_t hid_device_handle)
|
|
||||||
{
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_uninstall_device(test_hid_device) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Teardowns HID
|
|
||||||
*
|
|
||||||
* - Uninstall HID Host driver
|
|
||||||
* - Uninstall USB Host driver
|
|
||||||
* - Delete usb_events task
|
|
||||||
* - Delete events handle
|
|
||||||
*/
|
|
||||||
void test_hid_teardown(void)
|
|
||||||
{
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, hid_host_uninstall() );
|
|
||||||
TEST_ASSERT_EQUAL(ESP_OK, usb_host_uninstall() );
|
|
||||||
|
|
||||||
vTaskDelete(test_usb_event_task_handle);
|
|
||||||
vEventGroupDelete(test_usb_flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------------------- HID Test ------------------------------------------
|
|
||||||
|
|
||||||
static void test_setup_hid_basic(void)
|
|
||||||
{
|
|
||||||
test_hid_setup();
|
|
||||||
test_create_semaphore();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_teardown_hid_basic(void)
|
|
||||||
{
|
|
||||||
test_delete_semaphore();
|
|
||||||
test_hid_teardown();
|
|
||||||
//Short delay to allow task to be cleaned up
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
test_hid_device = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("(HID Host) Memory leakage basic", "[auto][hid_host]")
|
|
||||||
{
|
|
||||||
test_setup_hid_basic();
|
|
||||||
test_teardown_hid_basic();
|
|
||||||
vTaskDelay(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("(HID Host) Memory leakage with HID device", "[hid_host]")
|
|
||||||
{
|
|
||||||
test_setup_hid_basic();
|
|
||||||
test_hid_device = test_hid_wait_connection_and_install();
|
|
||||||
test_hid_wait_for_removal();
|
|
||||||
test_hid_uninstall_hid_device(test_hid_device);
|
|
||||||
test_teardown_hid_basic();
|
|
||||||
vTaskDelay(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("(HID Host) HID Keyboard report length", "[hid_host]")
|
|
||||||
{
|
|
||||||
test_setup_hid_basic();
|
|
||||||
test_hid_device = test_hid_wait_connection_and_install();
|
|
||||||
test_hid_keyboard_report_length();
|
|
||||||
test_hid_wait_for_removal();
|
|
||||||
test_hid_uninstall_hid_device(test_hid_device);
|
|
||||||
test_teardown_hid_basic();
|
|
||||||
vTaskDelay(20);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("(HID Host) HID Mouse report length", "[hid_host]")
|
|
||||||
{
|
|
||||||
test_setup_hid_basic();
|
|
||||||
test_hid_device = test_hid_wait_connection_and_install();
|
|
||||||
test_hid_mouse_report_length();
|
|
||||||
test_hid_wait_for_removal();
|
|
||||||
test_hid_uninstall_hid_device(test_hid_device);
|
|
||||||
test_teardown_hid_basic();
|
|
||||||
vTaskDelay(20);
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "hid_host.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern hid_host_device_handle_t test_hid_device;
|
|
||||||
|
|
||||||
// ------------------------ HID Test -------------------------------------------
|
|
||||||
|
|
||||||
void test_hid_setup(void);
|
|
||||||
|
|
||||||
hid_host_device_handle_t test_hid_wait_connection_and_install(void);
|
|
||||||
|
|
||||||
void test_hid_wait_for_removal(void);
|
|
||||||
|
|
||||||
void test_hid_uninstall_hid_device(hid_host_device_handle_t hid_device_handle);
|
|
||||||
|
|
||||||
void test_hid_teardown(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif //__cplusplus
|
|
@ -1,150 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "unity.h"
|
|
||||||
#include "unity_test_utils.h"
|
|
||||||
|
|
||||||
#include "hid_host.h"
|
|
||||||
|
|
||||||
#define TEST_HID_ERR_HANDLING_CASES (3)
|
|
||||||
|
|
||||||
static void test_install_hid_driver_without_config(void);
|
|
||||||
static void test_install_hid_driver_with_wrong_config(void);
|
|
||||||
static void test_claim_interface_without_driver(void);
|
|
||||||
|
|
||||||
void (*test_hid_err_handling_case[TEST_HID_ERR_HANDLING_CASES])(void) = {
|
|
||||||
test_install_hid_driver_without_config,
|
|
||||||
test_install_hid_driver_with_wrong_config,
|
|
||||||
test_claim_interface_without_driver
|
|
||||||
};
|
|
||||||
// ----------------------- Private -------------------------
|
|
||||||
/**
|
|
||||||
* @brief USB HID Host event callback. Handle such event as device connection and removing
|
|
||||||
*
|
|
||||||
* @param[in] event HID Host device event
|
|
||||||
* @param[in] arg Pointer to arguments, does not used
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static void test_hid_host_event_callback_stub(const hid_host_event_t *event, void *arg)
|
|
||||||
{
|
|
||||||
if (event->event == HID_DEVICE_CONNECTED) {
|
|
||||||
// Device connected
|
|
||||||
} else if (event->event == HID_DEVICE_DISCONNECTED) {
|
|
||||||
// Device disconnected
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install HID driver without USB Host and without configuration
|
|
||||||
static void test_install_hid_driver_without_config(void)
|
|
||||||
{
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, hid_host_install(NULL));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Install HID driver without USB Host and with configuration
|
|
||||||
static void test_install_hid_driver_with_wrong_config(void)
|
|
||||||
{
|
|
||||||
const hid_host_driver_config_t hid_host_config_callback_null = {
|
|
||||||
.create_background_task = true,
|
|
||||||
.task_priority = 5,
|
|
||||||
.stack_size = 4096,
|
|
||||||
.core_id = 0,
|
|
||||||
.callback = NULL, /* error expected */
|
|
||||||
.callback_arg = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, hid_host_install(&hid_host_config_callback_null));
|
|
||||||
|
|
||||||
const hid_host_driver_config_t hid_host_config_stack_size_null = {
|
|
||||||
.create_background_task = true,
|
|
||||||
.task_priority = 5,
|
|
||||||
.stack_size = 0, /* error expected */
|
|
||||||
.core_id = 0,
|
|
||||||
.callback = NULL,
|
|
||||||
.callback_arg = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, hid_host_install(&hid_host_config_stack_size_null));
|
|
||||||
|
|
||||||
const hid_host_driver_config_t hid_host_config_task_priority_null = {
|
|
||||||
.create_background_task = true,
|
|
||||||
.task_priority = 0,/* error expected */
|
|
||||||
.stack_size = 4096,
|
|
||||||
.core_id = 0,
|
|
||||||
.callback = NULL,
|
|
||||||
.callback_arg = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, hid_host_install(&hid_host_config_task_priority_null));
|
|
||||||
|
|
||||||
const hid_host_driver_config_t hid_host_config_correct = {
|
|
||||||
.create_background_task = true,
|
|
||||||
.task_priority = 5,
|
|
||||||
.stack_size = 4096,
|
|
||||||
.core_id = 0,
|
|
||||||
.callback = test_hid_host_event_callback_stub,
|
|
||||||
.callback_arg = NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, hid_host_install(&hid_host_config_correct));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open device without installed driver
|
|
||||||
static void test_claim_interface_without_driver(void)
|
|
||||||
{
|
|
||||||
hid_host_interface_handle_t keyboard_handle;
|
|
||||||
|
|
||||||
|
|
||||||
hid_host_interface_config_t keyboard_iface_config_wrong_proto1 = {
|
|
||||||
.proto = HID_PROTOCOL_NONE,
|
|
||||||
.callback = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
|
||||||
hid_host_claim_interface(&keyboard_iface_config_wrong_proto1, &keyboard_handle));
|
|
||||||
|
|
||||||
hid_host_interface_config_t keyboard_iface_config_wrong_proto2 = {
|
|
||||||
.proto = HID_PROTOCOL_MAX,
|
|
||||||
.callback = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG,
|
|
||||||
hid_host_claim_interface(&keyboard_iface_config_wrong_proto2, &keyboard_handle));
|
|
||||||
|
|
||||||
/*
|
|
||||||
hid_host_interface_config_t keyboard_iface_config = {
|
|
||||||
.proto = HID_PROTOCOL_KEYBOARD,
|
|
||||||
.callback = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE,
|
|
||||||
hid_host_claim_interface(&keyboard_iface_config, &keyboard_handle));
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------- Public --------------------------
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief HID
|
|
||||||
*
|
|
||||||
* There are multiple erroneous scenarios checked in this test:
|
|
||||||
*
|
|
||||||
* -# Install HID driver without USB Host
|
|
||||||
* -# Open device without installed driver
|
|
||||||
* -# Uninstall driver before installing it
|
|
||||||
* -# Open non-existent device
|
|
||||||
* -# Open the same device twice
|
|
||||||
* -# Uninstall driver with open devices
|
|
||||||
*/
|
|
||||||
TEST_CASE("(HID Host) Error handling", "[auto][hid_host]")
|
|
||||||
{
|
|
||||||
for (int i = 0; i < TEST_HID_ERR_HANDLING_CASES; i++) {
|
|
||||||
(*test_hid_err_handling_case[i])();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include "unity.h"
|
|
||||||
#include "unity_test_utils.h"
|
|
||||||
|
|
||||||
#include "hid_host.h"
|
|
||||||
#include "test_hid_basic.h"
|
|
||||||
|
|
||||||
// ----------------------- Private -------------------------
|
|
||||||
/**
|
|
||||||
* @brief Test HID Uninstall USB driver with device inserted
|
|
||||||
*
|
|
||||||
* - Wait events: DEVICE_DISCONNECTED
|
|
||||||
* - On DEVICE_DISCONNECTED proceed
|
|
||||||
*/
|
|
||||||
void test_hid_usb_uninstall(void)
|
|
||||||
{
|
|
||||||
printf("HID device remain inserted, uninstall device ... ");
|
|
||||||
test_hid_uninstall_hid_device(test_hid_device);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------- Public --------------------------
|
|
||||||
|
|
||||||
|
|
||||||
// ------------------------- USB Test ------------------------------------------
|
|
||||||
static void test_setup_hid_usb_driver(void)
|
|
||||||
{
|
|
||||||
test_hid_setup();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void test_teardown_hid_usb_driver(void)
|
|
||||||
{
|
|
||||||
test_hid_teardown();
|
|
||||||
//Short delay to allow task to be cleaned up
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(10));
|
|
||||||
test_hid_device = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_CASE("(HID Host) USB uninstall (dev present)", "[hid_host]")
|
|
||||||
{
|
|
||||||
test_setup_hid_usb_driver();
|
|
||||||
|
|
||||||
test_hid_device = test_hid_wait_connection_and_install();
|
|
||||||
test_hid_usb_uninstall();
|
|
||||||
test_teardown_hid_usb_driver();
|
|
||||||
vTaskDelay(20);
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
|
||||||
# SPDX-License-Identifier: Unlicense OR CC0-1.0
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from pytest_embedded_idf.dut import IdfDut
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.esp32s2
|
|
||||||
@pytest.mark.esp32s3
|
|
||||||
def test_hid_basic(dut: IdfDut) -> None:
|
|
||||||
dut.expect_exact('Press ENTER to see the list of tests')
|
|
||||||
dut.write('[auto]')
|
|
||||||
dut.expect_unity_test_output()
|
|
@ -1,3 +0,0 @@
|
|||||||
CONFIG_ESP_TASK_WDT=n
|
|
||||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
|
||||||
CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y
|
|
@ -11,41 +11,46 @@
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "freertos/event_groups.h"
|
#include "freertos/event_groups.h"
|
||||||
|
#include "freertos/queue.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "usb/usb_host.h"
|
#include "usb/usb_host.h"
|
||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "driver/gpio.h"
|
#include "driver/gpio.h"
|
||||||
|
|
||||||
#include "hid_host.h"
|
#include "usb/hid_host.h"
|
||||||
#include "hid_usage_keyboard.h"
|
#include "usb/hid_usage_keyboard.h"
|
||||||
#include "hid_usage_mouse.h"
|
#include "usb/hid_usage_mouse.h"
|
||||||
|
|
||||||
|
/* GPIO Pin number for quit from example logic */
|
||||||
#define APP_QUIT_PIN GPIO_NUM_0
|
#define APP_QUIT_PIN GPIO_NUM_0
|
||||||
#define APP_QUIT_PIN_POLL_MS 500
|
|
||||||
|
|
||||||
#define READY_TO_UNINSTALL (HOST_NO_CLIENT | HOST_ALL_FREE)
|
static const char *TAG = "example";
|
||||||
|
QueueHandle_t hid_host_event_queue;
|
||||||
/* Main char symbol for ENTER key */
|
bool user_shutdown = false;
|
||||||
#define KEYBOARD_ENTER_MAIN_CHAR '\r'
|
|
||||||
/* When set to 1 pressing ENTER will be extending with LineFeed during serial debug output */
|
|
||||||
#define KEYBOARD_ENTER_LF_EXTEND 1
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Application Event from USB Host driver
|
* @brief HID Host event
|
||||||
*
|
*
|
||||||
|
* This event is used for delivering the HID Host event from callback to a task.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef struct {
|
||||||
HOST_NO_CLIENT = 0x1,
|
hid_host_device_handle_t hid_device_handle;
|
||||||
HOST_ALL_FREE = 0x2,
|
hid_host_driver_event_t event;
|
||||||
DEVICE_CONNECTED = 0x4,
|
void *arg;
|
||||||
DEVICE_DISCONNECTED = 0x8,
|
} hid_host_event_queue_t;
|
||||||
DEVICE_ADDRESS_MASK = 0xFF0,
|
|
||||||
} app_event_t;
|
/**
|
||||||
|
* @brief HID Protocol string names
|
||||||
|
*/
|
||||||
|
static const char *hid_proto_name_str[] = {
|
||||||
|
"NONE",
|
||||||
|
"KEYBOARD",
|
||||||
|
"MOUSE"
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Key event
|
* @brief Key event
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
enum key_state {
|
enum key_state {
|
||||||
@ -56,14 +61,10 @@ typedef struct {
|
|||||||
uint8_t key_code;
|
uint8_t key_code;
|
||||||
} key_event_t;
|
} key_event_t;
|
||||||
|
|
||||||
#define USB_EVENTS_TO_WAIT (DEVICE_CONNECTED | DEVICE_ADDRESS_MASK | DEVICE_DISCONNECTED)
|
/* Main char symbol for ENTER key */
|
||||||
|
#define KEYBOARD_ENTER_MAIN_CHAR '\r'
|
||||||
static const char *TAG = "example";
|
/* When set to 1 pressing ENTER will be extending with LineFeed during serial debug output */
|
||||||
static EventGroupHandle_t usb_flags;
|
#define KEYBOARD_ENTER_LF_EXTEND 1
|
||||||
static bool hid_device_connected = false;
|
|
||||||
|
|
||||||
hid_host_interface_handle_t keyboard_handle = NULL;
|
|
||||||
hid_host_interface_handle_t mouse_handle = NULL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Scancode to ascii table
|
* @brief Scancode to ascii table
|
||||||
@ -135,16 +136,17 @@ const uint8_t keycode2ascii [57][2] = {
|
|||||||
*/
|
*/
|
||||||
static void hid_print_new_device_report_header(hid_protocol_t proto)
|
static void hid_print_new_device_report_header(hid_protocol_t proto)
|
||||||
{
|
{
|
||||||
static hid_protocol_t prev_proto_output = HID_PROTOCOL_NONE;
|
static hid_protocol_t prev_proto_output = -1;
|
||||||
|
|
||||||
if (prev_proto_output != proto) {
|
if (prev_proto_output != proto) {
|
||||||
prev_proto_output = proto;
|
prev_proto_output = proto;
|
||||||
printf("\r\n");
|
printf("\r\n");
|
||||||
if (proto == HID_PROTOCOL_MOUSE) {
|
if (proto == HID_PROTOCOL_MOUSE) {
|
||||||
printf("Mouse\r\n");
|
printf("Mouse\r\n");
|
||||||
}
|
} else if (proto == HID_PROTOCOL_KEYBOARD) {
|
||||||
if (proto == HID_PROTOCOL_KEYBOARD) {
|
|
||||||
printf("Keyboard\r\n");
|
printf("Keyboard\r\n");
|
||||||
|
} else {
|
||||||
|
printf("Generic\r\n");
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@ -160,8 +162,8 @@ static void hid_print_new_device_report_header(hid_protocol_t proto)
|
|||||||
*/
|
*/
|
||||||
static inline bool hid_keyboard_is_modifier_shift(uint8_t modifier)
|
static inline bool hid_keyboard_is_modifier_shift(uint8_t modifier)
|
||||||
{
|
{
|
||||||
if ((modifier && HID_LEFT_SHIFT) ||
|
if (((modifier & HID_LEFT_SHIFT) == HID_LEFT_SHIFT) ||
|
||||||
(modifier && HID_RIGHT_SHIFT)) {
|
((modifier & HID_RIGHT_SHIFT) == HID_RIGHT_SHIFT)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -324,113 +326,118 @@ static void hid_host_mouse_report_callback(const uint8_t *const data, const int
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USB HID Host event callback. Handle such event as device connection and removing
|
* @brief USB HID Host Generic Interface report callback handler
|
||||||
*
|
*
|
||||||
* @param[in] event HID device event
|
* 'generic' means anything else than mouse or keyboard
|
||||||
* @param[in] arg Pointer to arguments, does not used
|
*
|
||||||
|
* @param[in] data Pointer to input report data buffer
|
||||||
|
* @param[in] length Length of input report data buffer
|
||||||
*/
|
*/
|
||||||
static void hid_host_event_callback(const hid_host_event_t *event, void *arg)
|
static void hid_host_generic_report_callback(const uint8_t *const data, const int length)
|
||||||
{
|
{
|
||||||
if (event->event == HID_DEVICE_CONNECTED) {
|
hid_print_new_device_report_header(HID_PROTOCOL_NONE);
|
||||||
// Obtained USB device address is placed after application events
|
for (int i = 0; i < length; i++) {
|
||||||
xEventGroupSetBits(usb_flags, DEVICE_CONNECTED | (event->device.address << 4));
|
printf("%02X", data[i]);
|
||||||
} else if (event->event == HID_DEVICE_DISCONNECTED) {
|
|
||||||
xEventGroupSetBits(usb_flags, DEVICE_DISCONNECTED);
|
|
||||||
}
|
}
|
||||||
|
putchar('\r');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USB HID Host interface callback
|
* @brief USB HID Host interface callback
|
||||||
*
|
*
|
||||||
* @param[in] event HID interface event
|
* @param[in] hid_device_handle HID Device handle
|
||||||
|
* @param[in] event HID Host interface event
|
||||||
* @param[in] arg Pointer to arguments, does not used
|
* @param[in] arg Pointer to arguments, does not used
|
||||||
*/
|
*/
|
||||||
static void hid_host_interface_event_callback(const hid_host_interface_event_t *event, void *arg)
|
void hid_host_interface_callback(hid_host_device_handle_t hid_device_handle,
|
||||||
|
const hid_host_interface_event_t event,
|
||||||
|
void *arg)
|
||||||
{
|
{
|
||||||
switch (event->event) {
|
uint8_t data[64] = { 0 };
|
||||||
case HID_DEVICE_INTERFACE_INIT:
|
size_t data_length = 0;
|
||||||
ESP_LOGI(TAG, "Interface number %d, protocol %s",
|
hid_host_dev_params_t dev_params;
|
||||||
event->interface.num,
|
ESP_ERROR_CHECK( hid_host_device_get_params(hid_device_handle, &dev_params));
|
||||||
(event->interface.proto == HID_PROTOCOL_KEYBOARD)
|
|
||||||
? "Keyboard"
|
|
||||||
: "Mouse");
|
|
||||||
|
|
||||||
if (event->interface.proto == HID_PROTOCOL_KEYBOARD) {
|
switch (event) {
|
||||||
const hid_host_interface_config_t hid_keyboard_config = {
|
case HID_HOST_INTERFACE_EVENT_INPUT_REPORT:
|
||||||
.proto = HID_PROTOCOL_KEYBOARD,
|
ESP_ERROR_CHECK( hid_host_device_get_raw_input_report_data(hid_device_handle,
|
||||||
.callback = hid_host_keyboard_report_callback,
|
data,
|
||||||
};
|
64,
|
||||||
|
&data_length));
|
||||||
|
|
||||||
hid_host_claim_interface(&hid_keyboard_config, &keyboard_handle);
|
if (HID_SUBCLASS_BOOT_INTERFACE == dev_params.sub_class) {
|
||||||
|
if (HID_PROTOCOL_KEYBOARD == dev_params.proto) {
|
||||||
|
hid_host_keyboard_report_callback(data, data_length);
|
||||||
|
} else if (HID_PROTOCOL_MOUSE == dev_params.proto) {
|
||||||
|
hid_host_mouse_report_callback(data, data_length);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if (event->interface.proto == HID_PROTOCOL_MOUSE) {
|
hid_host_generic_report_callback(data, data_length);
|
||||||
const hid_host_interface_config_t hid_mouse_config = {
|
|
||||||
.proto = HID_PROTOCOL_MOUSE,
|
|
||||||
.callback = hid_host_mouse_report_callback,
|
|
||||||
};
|
|
||||||
|
|
||||||
hid_host_claim_interface(&hid_mouse_config, &mouse_handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case HID_DEVICE_INTERFACE_TRANSFER_ERROR:
|
case HID_HOST_INTERFACE_EVENT_DISCONNECTED:
|
||||||
ESP_LOGD(TAG, "Interface number %d, transfer error",
|
ESP_LOGI(TAG, "HID Device, protocol '%s' DISCONNECTED",
|
||||||
event->interface.num);
|
hid_proto_name_str[dev_params.proto]);
|
||||||
|
ESP_ERROR_CHECK( hid_host_device_close(hid_device_handle) );
|
||||||
break;
|
break;
|
||||||
|
case HID_HOST_INTERFACE_EVENT_TRANSFER_ERROR:
|
||||||
case HID_DEVICE_INTERFACE_CLAIM:
|
ESP_LOGI(TAG, "HID Device, protocol '%s' TRANSFER_ERROR",
|
||||||
case HID_DEVICE_INTERFACE_RELEASE:
|
hid_proto_name_str[dev_params.proto]);
|
||||||
// ... do nothing here for now
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ESP_LOGI(TAG, "%s Unhandled event %X, Interface number %d",
|
ESP_LOGE(TAG, "HID Device, protocol '%s' Unhandled event",
|
||||||
__FUNCTION__,
|
hid_proto_name_str[dev_params.proto]);
|
||||||
event->event,
|
|
||||||
event->interface.num);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Handle common USB host library events
|
* @brief USB HID Host Device event
|
||||||
*
|
*
|
||||||
* @param[in] args Pointer to arguments, does not used
|
* @param[in] hid_device_handle HID Device handle
|
||||||
|
* @param[in] event HID Host Device event
|
||||||
|
* @param[in] arg Pointer to arguments, does not used
|
||||||
*/
|
*/
|
||||||
static void handle_usb_events(void *args)
|
void hid_host_device_event(hid_host_device_handle_t hid_device_handle,
|
||||||
|
const hid_host_driver_event_t event,
|
||||||
|
void *arg)
|
||||||
{
|
{
|
||||||
while (1) {
|
hid_host_dev_params_t dev_params;
|
||||||
uint32_t event_flags;
|
ESP_ERROR_CHECK( hid_host_device_get_params(hid_device_handle, &dev_params));
|
||||||
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
|
||||||
|
|
||||||
// Release devices once all clients has deregistered
|
switch (event) {
|
||||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
case HID_HOST_DRIVER_EVENT_CONNECTED:
|
||||||
usb_host_device_free_all();
|
ESP_LOGI(TAG, "HID Device, protocol '%s' CONNECTED",
|
||||||
xEventGroupSetBits(usb_flags, HOST_NO_CLIENT);
|
hid_proto_name_str[dev_params.proto]);
|
||||||
}
|
|
||||||
// Give ready_to_uninstall_usb semaphore to indicate that USB Host library
|
|
||||||
// can be deinitialized, and terminate this task.
|
|
||||||
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
|
||||||
xEventGroupSetBits(usb_flags, HOST_ALL_FREE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
const hid_host_device_config_t dev_config = {
|
||||||
|
.callback = hid_host_interface_callback,
|
||||||
|
.callback_arg = NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
ESP_ERROR_CHECK( hid_host_device_open(hid_device_handle, &dev_config) );
|
||||||
|
if (HID_SUBCLASS_BOOT_INTERFACE == dev_params.sub_class) {
|
||||||
|
ESP_ERROR_CHECK( hid_class_request_set_protocol(hid_device_handle, HID_REPORT_PROTOCOL_BOOT));
|
||||||
|
if (HID_PROTOCOL_KEYBOARD == dev_params.proto) {
|
||||||
|
ESP_ERROR_CHECK( hid_class_request_set_idle(hid_device_handle, 0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ESP_ERROR_CHECK( hid_host_device_start(hid_device_handle) );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool wait_for_event(EventBits_t event, TickType_t timeout)
|
/**
|
||||||
|
* @brief Start USB Host install and handle common USB host library events while app pin not low
|
||||||
|
*
|
||||||
|
* @param[in] arg Not used
|
||||||
|
*/
|
||||||
|
static void usb_lib_task(void *arg)
|
||||||
{
|
{
|
||||||
return xEventGroupWaitBits(usb_flags, event, pdTRUE, pdTRUE, timeout) & event;
|
|
||||||
}
|
|
||||||
|
|
||||||
void app_main(void)
|
|
||||||
{
|
|
||||||
TaskHandle_t usb_events_task_handle;
|
|
||||||
hid_host_device_handle_t hid_device;
|
|
||||||
|
|
||||||
BaseType_t task_created;
|
|
||||||
|
|
||||||
const gpio_config_t input_pin = {
|
const gpio_config_t input_pin = {
|
||||||
.pin_bit_mask = BIT64(APP_QUIT_PIN),
|
.pin_bit_mask = BIT64(APP_QUIT_PIN),
|
||||||
.mode = GPIO_MODE_INPUT,
|
.mode = GPIO_MODE_INPUT,
|
||||||
@ -438,78 +445,129 @@ void app_main(void)
|
|||||||
};
|
};
|
||||||
ESP_ERROR_CHECK( gpio_config(&input_pin) );
|
ESP_ERROR_CHECK( gpio_config(&input_pin) );
|
||||||
|
|
||||||
ESP_LOGI(TAG, "HID HOST example");
|
|
||||||
|
|
||||||
usb_flags = xEventGroupCreate();
|
|
||||||
assert(usb_flags);
|
|
||||||
|
|
||||||
const usb_host_config_t host_config = {
|
const usb_host_config_t host_config = {
|
||||||
.skip_phy_setup = false,
|
.skip_phy_setup = false,
|
||||||
.intr_flags = ESP_INTR_FLAG_LEVEL1
|
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||||
};
|
};
|
||||||
|
|
||||||
ESP_ERROR_CHECK( usb_host_install(&host_config) );
|
ESP_ERROR_CHECK( usb_host_install(&host_config) );
|
||||||
task_created = xTaskCreate(handle_usb_events, "usb_events", 4096, NULL, 2, &usb_events_task_handle);
|
xTaskNotifyGive(arg);
|
||||||
assert(task_created);
|
|
||||||
|
|
||||||
// hid host driver config
|
while (gpio_get_level(APP_QUIT_PIN) != 0) {
|
||||||
const hid_host_driver_config_t hid_host_config = {
|
uint32_t event_flags;
|
||||||
|
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
|
||||||
|
|
||||||
|
// Release devices once all clients has deregistered
|
||||||
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||||
|
usb_host_device_free_all();
|
||||||
|
ESP_LOGI(TAG, "USB Event flags: NO_CLIENTS");
|
||||||
|
}
|
||||||
|
// All devices were removed
|
||||||
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||||
|
ESP_LOGI(TAG, "USB Event flags: ALL_FREE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// App Button was pressed, trigger the flag
|
||||||
|
user_shutdown = true;
|
||||||
|
ESP_LOGI(TAG, "USB shutdown");
|
||||||
|
// Clean up USB Host
|
||||||
|
vTaskDelay(10); // Short delay to allow clients clean-up
|
||||||
|
ESP_ERROR_CHECK( usb_host_uninstall());
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HID Host main task
|
||||||
|
*
|
||||||
|
* Creates queue and get new event from the queue
|
||||||
|
*
|
||||||
|
* @param[in] pvParameters Not used
|
||||||
|
*/
|
||||||
|
void hid_host_task(void *pvParameters)
|
||||||
|
{
|
||||||
|
hid_host_event_queue_t evt_queue;
|
||||||
|
// Create queue
|
||||||
|
hid_host_event_queue = xQueueCreate(10, sizeof(hid_host_event_queue_t));
|
||||||
|
|
||||||
|
// Wait queue
|
||||||
|
while (!user_shutdown) {
|
||||||
|
if (xQueueReceive(hid_host_event_queue, &evt_queue, pdMS_TO_TICKS(50))) {
|
||||||
|
hid_host_device_event(evt_queue.hid_device_handle,
|
||||||
|
evt_queue.event,
|
||||||
|
evt_queue.arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xQueueReset(hid_host_event_queue);
|
||||||
|
vQueueDelete(hid_host_event_queue);
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief HID Host Device callback
|
||||||
|
*
|
||||||
|
* Puts new HID Device event to the queue
|
||||||
|
*
|
||||||
|
* @param[in] hid_device_handle HID Device handle
|
||||||
|
* @param[in] event HID Device event
|
||||||
|
* @param[in] arg Not used
|
||||||
|
*/
|
||||||
|
void hid_host_device_callback(hid_host_device_handle_t hid_device_handle,
|
||||||
|
const hid_host_driver_event_t event,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
const hid_host_event_queue_t evt_queue = {
|
||||||
|
.hid_device_handle = hid_device_handle,
|
||||||
|
.event = event,
|
||||||
|
.arg = arg
|
||||||
|
};
|
||||||
|
xQueueSend(hid_host_event_queue, &evt_queue, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
BaseType_t task_created;
|
||||||
|
ESP_LOGI(TAG, "HID Host example");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create usb_lib_task to:
|
||||||
|
* - initialize USB Host library
|
||||||
|
* - Handle USB Host events while APP pin in in HIGH state
|
||||||
|
*/
|
||||||
|
task_created = xTaskCreatePinnedToCore(usb_lib_task,
|
||||||
|
"usb_events",
|
||||||
|
4096,
|
||||||
|
xTaskGetCurrentTaskHandle(),
|
||||||
|
2, NULL, 0);
|
||||||
|
assert(task_created == pdTRUE);
|
||||||
|
|
||||||
|
// Wait for notification from usb_lib_task to proceed
|
||||||
|
ulTaskNotifyTake(false, 1000);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* HID host driver configuration
|
||||||
|
* - create background task for handling low level event inside the HID driver
|
||||||
|
* - provide the device callback to get new HID Device connection event
|
||||||
|
*/
|
||||||
|
const hid_host_driver_config_t hid_host_driver_config = {
|
||||||
.create_background_task = true,
|
.create_background_task = true,
|
||||||
.task_priority = 5,
|
.task_priority = 5,
|
||||||
.stack_size = 4096,
|
.stack_size = 4096,
|
||||||
.core_id = 0,
|
.core_id = 0,
|
||||||
.callback = hid_host_event_callback,
|
.callback = hid_host_device_callback,
|
||||||
.callback_arg = NULL
|
.callback_arg = NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
ESP_ERROR_CHECK( hid_host_install(&hid_host_config) );
|
ESP_ERROR_CHECK( hid_host_install(&hid_host_driver_config) );
|
||||||
|
|
||||||
do {
|
// Task is working until the devices are gone (while 'user_shutdown' if false)
|
||||||
EventBits_t event = xEventGroupWaitBits(usb_flags, USB_EVENTS_TO_WAIT, pdTRUE, pdFALSE, pdMS_TO_TICKS(APP_QUIT_PIN_POLL_MS));
|
user_shutdown = false;
|
||||||
|
|
||||||
if (event & DEVICE_CONNECTED) {
|
/*
|
||||||
xEventGroupClearBits(usb_flags, DEVICE_CONNECTED);
|
* Create HID Host task process for handle events
|
||||||
hid_device_connected = true;
|
* IMPORTANT: Task is necessary here while there is no possibility to interact
|
||||||
}
|
* with USB device from the callback.
|
||||||
|
*/
|
||||||
if (event & DEVICE_ADDRESS_MASK) {
|
task_created = xTaskCreate(&hid_host_task, "hid_task", 4 * 1024, NULL, 2, NULL);
|
||||||
xEventGroupClearBits(usb_flags, DEVICE_ADDRESS_MASK);
|
assert(task_created == pdTRUE);
|
||||||
|
|
||||||
const hid_host_device_config_t hid_host_device_config = {
|
|
||||||
.dev_addr = (event & DEVICE_ADDRESS_MASK) >> 4,
|
|
||||||
.iface_event_cb = hid_host_interface_event_callback,
|
|
||||||
.iface_event_arg = NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( hid_host_install_device(&hid_host_device_config, &hid_device) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (event & DEVICE_DISCONNECTED) {
|
|
||||||
xEventGroupClearBits(usb_flags, DEVICE_DISCONNECTED);
|
|
||||||
|
|
||||||
hid_host_release_interface(keyboard_handle);
|
|
||||||
hid_host_release_interface(mouse_handle);
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK( hid_host_uninstall_device(hid_device) );
|
|
||||||
|
|
||||||
hid_device_connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} while (gpio_get_level(APP_QUIT_PIN) != 0);
|
|
||||||
|
|
||||||
if (hid_device_connected) {
|
|
||||||
ESP_LOGI(TAG, "Uninitializing HID Device");
|
|
||||||
hid_host_release_interface(keyboard_handle);
|
|
||||||
hid_host_release_interface(mouse_handle);
|
|
||||||
ESP_ERROR_CHECK( hid_host_uninstall_device(hid_device) );
|
|
||||||
hid_device_connected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Uninitializing USB");
|
|
||||||
ESP_ERROR_CHECK( hid_host_uninstall() );
|
|
||||||
wait_for_event(READY_TO_UNINSTALL, portMAX_DELAY);
|
|
||||||
ESP_ERROR_CHECK( usb_host_uninstall() );
|
|
||||||
vTaskDelete(usb_events_task_handle);
|
|
||||||
vEventGroupDelete(usb_flags);
|
|
||||||
ESP_LOGI(TAG, "Done");
|
|
||||||
}
|
}
|
||||||
|
4
examples/peripherals/usb/host/hid/main/idf_component.yml
Normal file
4
examples/peripherals/usb/host/hid/main/idf_component.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
idf: ">=4.4"
|
||||||
|
usb_host_hid: "1.0.0"
|
Loading…
Reference in New Issue
Block a user