mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
add host midi example
This commit is contained in:
parent
c8243465e4
commit
b28af15448
6
examples/peripherals/usb/host/midi/CMakeLists.txt
Normal file
6
examples/peripherals/usb/host/midi/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# The following lines of boilerplate have to be in your project's
|
||||||
|
# CMakeLists in this exact order for cmake to work correctly
|
||||||
|
cmake_minimum_required(VERSION 3.5)
|
||||||
|
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
project(app-template)
|
136
examples/peripherals/usb/host/midi/README.md
Normal file
136
examples/peripherals/usb/host/midi/README.md
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
||||||
|
| ----------------- | -------- | -------- |
|
||||||
|
|
||||||
|
# USB MIDI Class Example
|
||||||
|
|
||||||
|
|
||||||
|
This example provides basic USB Host Midi functionality by implementing a midi class driver and a Host Library task. The example does the following:
|
||||||
|
|
||||||
|
1. Install Host Library and register a client
|
||||||
|
2. Waits for a device connection
|
||||||
|
3. Prints the device's information (such as device/configuration/string descriptors)
|
||||||
|
4. Claims Interface with more that zero endpoints from device
|
||||||
|
5. Prints received bytes, if midi-device sent new data
|
||||||
|
|
||||||
|
The example heavily follows the usb_host_lib example (https://github.com/espressif/esp-idf/tree/master/examples/peripherals/usb/host/usb_host_lib).
|
||||||
|
|
||||||
|
## How to use example
|
||||||
|
|
||||||
|
### Hardware Required
|
||||||
|
|
||||||
|
- Development board with USB capable ESP SoC (ESP32-S2/ESP32-S3)
|
||||||
|
- USB cable for Power supply and programming
|
||||||
|
- USB OTG Cable
|
||||||
|
- MIDI-device (e.g. KORG NANOKONTROL2)
|
||||||
|
|
||||||
|
### Build and Flash
|
||||||
|
|
||||||
|
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||||
|
|
||||||
|
```
|
||||||
|
idf.py -p PORT flash monitor
|
||||||
|
```
|
||||||
|
|
||||||
|
(Replace PORT with the name of the serial port to use.)
|
||||||
|
|
||||||
|
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||||
|
|
||||||
|
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
```
|
||||||
|
I (314) app_start: Starting scheduler on CPU0
|
||||||
|
I (319) app_start: Starting scheduler on CPU1
|
||||||
|
I (319) main_task: Started on CPU0
|
||||||
|
I (329) main_task: Calling app_main()
|
||||||
|
I (329) DAEMON: Installing USB Host Library
|
||||||
|
I (369) MIDI DRIVER: Registering Client
|
||||||
|
I (2109) MIDI DRIVER: Opening device at address 1
|
||||||
|
I (2109) MIDI DRIVER: Getting device information
|
||||||
|
I (2109) MIDI DRIVER: Full speed
|
||||||
|
I (2109) MIDI DRIVER: bConfigurationValue 1
|
||||||
|
I (2119) MIDI DRIVER: Getting device descriptor
|
||||||
|
*** Device descriptor ***
|
||||||
|
bLength 18
|
||||||
|
bDescriptorType 1
|
||||||
|
bcdUSB 1.10
|
||||||
|
bDeviceClass 0x0
|
||||||
|
bDeviceSubClass 0x0
|
||||||
|
bDeviceProtocol 0x0
|
||||||
|
bMaxPacketSize0 8
|
||||||
|
idVendor 0xfc02
|
||||||
|
idProduct 0x101
|
||||||
|
bcdDevice 2.50
|
||||||
|
iManufacturer 0
|
||||||
|
iProduct 2
|
||||||
|
iSerialNumber 0
|
||||||
|
bNumConfigurations 1
|
||||||
|
I (2139) MIDI DRIVER: Getting config descriptor
|
||||||
|
*** Configuration descriptor ***
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 2
|
||||||
|
wTotalLength 101
|
||||||
|
bNumInterfaces 2
|
||||||
|
bConfigurationValue 1
|
||||||
|
iConfiguration 0
|
||||||
|
bmAttributes 0x80
|
||||||
|
bMaxPower 100mA
|
||||||
|
*** Interface descriptor ***
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 4
|
||||||
|
bInterfaceNumber 0
|
||||||
|
bAlternateSetting 0
|
||||||
|
bNumEndpoints 0
|
||||||
|
bInterfaceClass 0x1
|
||||||
|
bInterfaceSubClass 0x1
|
||||||
|
bInterfaceProtocol 0x0
|
||||||
|
iInterface 0
|
||||||
|
*** Interface descriptor ***
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 4
|
||||||
|
bInterfaceNumber 1
|
||||||
|
bAlternateSetting 0
|
||||||
|
bNumEndpoints 2
|
||||||
|
bInterfaceClass 0x1
|
||||||
|
bInterfaceSubClass 0x3
|
||||||
|
bInterfaceProtocol 0x0
|
||||||
|
iInterface 0
|
||||||
|
*** Endpoint descriptor ***
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 5
|
||||||
|
bEndpointAddress 0x81 EP 1 IN
|
||||||
|
bmAttributes 0x2 BULK
|
||||||
|
wMaxPacketSize 8
|
||||||
|
bInterval 0
|
||||||
|
*** Endpoint descriptor ***
|
||||||
|
bLength 9
|
||||||
|
bDescriptorType 5
|
||||||
|
bEndpointAddress 0x2 EP 2 OUT
|
||||||
|
bmAttributes 0x2 BULK
|
||||||
|
wMaxPacketSize 8
|
||||||
|
bInterval 0
|
||||||
|
I (2229) MIDI DRIVER: Getting interface config
|
||||||
|
Interface Number: 1, Alternate Setting: 0
|
||||||
|
endpoint address: 129 , mps: 8
|
||||||
|
I (2239) MIDI DRIVER: Getting Product string descriptor
|
||||||
|
USB MIDI Interface
|
||||||
|
I (2249) MIDI DRIVER: Claiming Interface
|
||||||
|
I (2249) MIDI DRIVER: Configuring usb-transfer object
|
||||||
|
set transfer parameters
|
||||||
|
I (4429) MIDI DRIVER: Received new data:
|
||||||
|
|
||||||
|
15 248 0 0
|
||||||
|
I (4429) MIDI DRIVER: Received new data:
|
||||||
|
|
||||||
|
8 140 0 0
|
||||||
|
I (6159) MIDI DRIVER: Received new data:
|
||||||
|
|
||||||
|
11 176 14 60
|
||||||
|
I (6199) MIDI DRIVER: Received new data:
|
||||||
|
|
||||||
|
11 176 32 15
|
||||||
|
I (6229) MIDI DRIVER: Received new data:
|
||||||
|
|
||||||
|
11 176 2 32
|
||||||
|
```
|
5
examples/peripherals/usb/host/midi/main/CMakeLists.txt
Normal file
5
examples/peripherals/usb/host/midi/main/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
idf_component_register(
|
||||||
|
SRCS "midi_host_example_main.c"
|
||||||
|
INCLUDE_DIRS "."
|
||||||
|
PRIV_REQUIRES usb
|
||||||
|
)
|
@ -0,0 +1,6 @@
|
|||||||
|
## IDF Component Manager Manifest File
|
||||||
|
dependencies:
|
||||||
|
espressif/usb_host_hid: "==1.0.1"
|
||||||
|
## Required IDF version
|
||||||
|
idf:
|
||||||
|
version: ">=4.1.0"
|
313
examples/peripherals/usb/host/midi/main/midi_class_driver.c
Normal file
313
examples/peripherals/usb/host/midi/main/midi_class_driver.c
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "usb/usb_host.h"
|
||||||
|
|
||||||
|
#define ACTION_OPEN_DEV 0x01
|
||||||
|
#define ACTION_GET_DEV_INFO 0x02
|
||||||
|
#define ACTION_GET_DEV_DESC 0x04
|
||||||
|
#define ACTION_GET_CONFIG_DESC 0x08
|
||||||
|
#define ACTION_GET_STR_DESC 0x10
|
||||||
|
#define ACTION_CLAIM_INTERFACE 0x20
|
||||||
|
#define ACTION_START_READING_DATA 0x40
|
||||||
|
#define ACTION_CLOSE_DEV 0x80
|
||||||
|
#define ACTION_EXIT 0xA0
|
||||||
|
|
||||||
|
#define USB_CLIENT_NUM_EVENT_MSG 5
|
||||||
|
#define MIDI_MESSAGE_LENGTH 4
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t interface_nmbr;
|
||||||
|
uint8_t alternate_setting;
|
||||||
|
uint8_t endpoint_address;
|
||||||
|
uint8_t max_packet_size;
|
||||||
|
} interface_config_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
usb_host_client_handle_t client_hdl;
|
||||||
|
uint8_t dev_addr;
|
||||||
|
usb_device_handle_t dev_hdl;
|
||||||
|
uint32_t actions;
|
||||||
|
interface_config_t interface_conf;
|
||||||
|
} class_driver_t;
|
||||||
|
|
||||||
|
static const char *DRIVER_TAG = "MIDI DRIVER";
|
||||||
|
|
||||||
|
static void midi_usb_host_callback(usb_transfer_t *transfer) {
|
||||||
|
int size = (int)transfer->actual_num_bytes;
|
||||||
|
//one message contains 4 bytes of data
|
||||||
|
int num_messages = size/MIDI_MESSAGE_LENGTH;
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
//print messages
|
||||||
|
if(num_messages) {
|
||||||
|
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Received new data: \n");
|
||||||
|
//print each message separately
|
||||||
|
for(int i = 0; i < num_messages; i++) {
|
||||||
|
for (int j = 0; j < MIDI_MESSAGE_LENGTH; j++) {
|
||||||
|
printf("%d ", transfer->data_buffer[j+offset]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
offset += MIDI_MESSAGE_LENGTH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//submit new usb-message to continuously receive data
|
||||||
|
ESP_ERROR_CHECK(usb_host_transfer_submit(transfer));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_midi_interface_settings(const usb_config_desc_t *usb_conf, interface_config_t *interface_conf) {
|
||||||
|
assert(usb_conf != NULL);
|
||||||
|
assert(interface_conf != NULL);
|
||||||
|
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting interface config");
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
uint16_t wTotalLength = usb_conf->wTotalLength;
|
||||||
|
const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)usb_conf;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(next_desc->bDescriptorType == USB_B_DESCRIPTOR_TYPE_INTERFACE) {
|
||||||
|
usb_intf_desc_t *interface_desc = (usb_intf_desc_t *)next_desc;
|
||||||
|
|
||||||
|
//check if there are >0 endpoints
|
||||||
|
if(interface_desc->bNumEndpoints > 0) {
|
||||||
|
//use interface
|
||||||
|
interface_conf->interface_nmbr = interface_desc->bInterfaceNumber;
|
||||||
|
interface_conf->alternate_setting = interface_desc->bAlternateSetting;
|
||||||
|
|
||||||
|
printf("Interface Number: %d, Alternate Setting: %d \n", interface_conf->interface_nmbr, interface_conf->alternate_setting);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(next_desc->bDescriptorType == USB_B_DESCRIPTOR_TYPE_ENDPOINT) {
|
||||||
|
usb_ep_desc_t *ep_desc = (usb_ep_desc_t *)next_desc;
|
||||||
|
if(USB_EP_DESC_GET_EP_DIR(ep_desc)) {
|
||||||
|
//endpoint is IN
|
||||||
|
interface_conf->endpoint_address = ep_desc->bEndpointAddress;
|
||||||
|
interface_conf->max_packet_size = ep_desc->wMaxPacketSize;
|
||||||
|
printf("endpoint address: %d , mps: %d\n", interface_conf->endpoint_address, interface_conf->max_packet_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
next_desc = usb_parse_next_descriptor(next_desc, wTotalLength, &offset);
|
||||||
|
|
||||||
|
} while (next_desc != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void client_event_cb(const usb_host_client_event_msg_t *event_msg, void *arg)
|
||||||
|
{
|
||||||
|
class_driver_t *driver_obj = (class_driver_t *)arg;
|
||||||
|
switch (event_msg->event) {
|
||||||
|
case USB_HOST_CLIENT_EVENT_NEW_DEV:
|
||||||
|
if (driver_obj->dev_addr == 0) {
|
||||||
|
driver_obj->dev_addr = event_msg->new_dev.address;
|
||||||
|
//Open the device next
|
||||||
|
driver_obj->actions |= ACTION_OPEN_DEV;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case USB_HOST_CLIENT_EVENT_DEV_GONE:
|
||||||
|
if (driver_obj->dev_hdl != NULL) {
|
||||||
|
//Cancel any other actions and close the device next
|
||||||
|
driver_obj->actions = ACTION_CLOSE_DEV;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//Should never occur
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_open_dev(class_driver_t *driver_obj)
|
||||||
|
{
|
||||||
|
assert(driver_obj->dev_addr != 0);
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Opening device at address %d", driver_obj->dev_addr);
|
||||||
|
ESP_ERROR_CHECK(usb_host_device_open(driver_obj->client_hdl, driver_obj->dev_addr, &driver_obj->dev_hdl));
|
||||||
|
//Get the device's information next
|
||||||
|
driver_obj->actions &= ~ACTION_OPEN_DEV;
|
||||||
|
driver_obj->actions |= ACTION_GET_DEV_INFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_get_info(class_driver_t *driver_obj)
|
||||||
|
{
|
||||||
|
assert(driver_obj->dev_hdl != NULL);
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting device information");
|
||||||
|
usb_device_info_t dev_info;
|
||||||
|
ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info));
|
||||||
|
ESP_LOGI(DRIVER_TAG, "\t%s speed", (dev_info.speed == USB_SPEED_LOW) ? "Low" : "Full");
|
||||||
|
ESP_LOGI(DRIVER_TAG, "\tbConfigurationValue %d", dev_info.bConfigurationValue);
|
||||||
|
//Todo: Print string descriptors
|
||||||
|
|
||||||
|
//Get the device descriptor next
|
||||||
|
driver_obj->actions &= ~ACTION_GET_DEV_INFO;
|
||||||
|
driver_obj->actions |= ACTION_GET_DEV_DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_get_dev_desc(class_driver_t *driver_obj)
|
||||||
|
{
|
||||||
|
assert(driver_obj->dev_hdl != NULL);
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting device descriptor");
|
||||||
|
const usb_device_desc_t *dev_desc;
|
||||||
|
ESP_ERROR_CHECK(usb_host_get_device_descriptor(driver_obj->dev_hdl, &dev_desc));
|
||||||
|
usb_print_device_descriptor(dev_desc);
|
||||||
|
//Get the device's config descriptor next
|
||||||
|
driver_obj->actions &= ~ACTION_GET_DEV_DESC;
|
||||||
|
driver_obj->actions |= ACTION_GET_CONFIG_DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_get_config_desc(class_driver_t *driver_obj)
|
||||||
|
{
|
||||||
|
assert(driver_obj->dev_hdl != NULL);
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting config descriptor");
|
||||||
|
const usb_config_desc_t *config_desc;
|
||||||
|
ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(driver_obj->dev_hdl, &config_desc));
|
||||||
|
usb_print_config_descriptor(config_desc, NULL);
|
||||||
|
|
||||||
|
//save interface number & alternative setting for later use
|
||||||
|
interface_config_t interface_config = {0};
|
||||||
|
ESP_ERROR_CHECK(usb_host_get_active_config_descriptor(driver_obj->dev_hdl, &config_desc));
|
||||||
|
get_midi_interface_settings(config_desc, &interface_config);
|
||||||
|
|
||||||
|
driver_obj->interface_conf = interface_config;
|
||||||
|
|
||||||
|
//Get the device's string descriptors next
|
||||||
|
driver_obj->actions &= ~ACTION_GET_CONFIG_DESC;
|
||||||
|
driver_obj->actions |= ACTION_GET_STR_DESC;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_get_str_desc(class_driver_t *driver_obj)
|
||||||
|
{
|
||||||
|
assert(driver_obj->dev_hdl != NULL);
|
||||||
|
usb_device_info_t dev_info;
|
||||||
|
ESP_ERROR_CHECK(usb_host_device_info(driver_obj->dev_hdl, &dev_info));
|
||||||
|
if (dev_info.str_desc_manufacturer) {
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting Manufacturer string descriptor");
|
||||||
|
usb_print_string_descriptor(dev_info.str_desc_manufacturer);
|
||||||
|
}
|
||||||
|
if (dev_info.str_desc_product) {
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting Product string descriptor");
|
||||||
|
usb_print_string_descriptor(dev_info.str_desc_product);
|
||||||
|
}
|
||||||
|
if (dev_info.str_desc_serial_num) {
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Getting Serial Number string descriptor");
|
||||||
|
usb_print_string_descriptor(dev_info.str_desc_serial_num);
|
||||||
|
}
|
||||||
|
//Claim interface next
|
||||||
|
driver_obj->actions &= ~ACTION_GET_STR_DESC;
|
||||||
|
driver_obj->actions |= ACTION_CLAIM_INTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_claim_interface(class_driver_t *driver_obj) {
|
||||||
|
assert(driver_obj->dev_hdl != NULL);
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Claiming Interface");
|
||||||
|
ESP_ERROR_CHECK(usb_host_interface_claim(
|
||||||
|
driver_obj->client_hdl,
|
||||||
|
driver_obj->dev_hdl,
|
||||||
|
driver_obj->interface_conf.interface_nmbr,
|
||||||
|
driver_obj->interface_conf.alternate_setting));
|
||||||
|
|
||||||
|
driver_obj->actions &= ~ACTION_CLAIM_INTERFACE;
|
||||||
|
driver_obj->actions |= ACTION_START_READING_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void action_start_reading_data(class_driver_t *driver_obj) {
|
||||||
|
assert(driver_obj->dev_hdl != NULL);
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Configuring usb-transfer object");
|
||||||
|
|
||||||
|
//configure usb-transfer object
|
||||||
|
usb_transfer_t *transfer_obj;
|
||||||
|
|
||||||
|
usb_host_transfer_alloc(1024, 0, &transfer_obj);
|
||||||
|
|
||||||
|
transfer_obj->num_bytes = driver_obj->interface_conf.max_packet_size;
|
||||||
|
transfer_obj->callback = midi_usb_host_callback;
|
||||||
|
transfer_obj->bEndpointAddress = driver_obj->interface_conf.endpoint_address;
|
||||||
|
transfer_obj->device_handle = driver_obj->dev_hdl;
|
||||||
|
printf("set transfer parameters\n");
|
||||||
|
ESP_ERROR_CHECK(usb_host_transfer_submit(transfer_obj));
|
||||||
|
|
||||||
|
//Nothing to do until the device disconnects
|
||||||
|
driver_obj->actions &= ~ACTION_START_READING_DATA;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void aciton_close_dev(class_driver_t *driver_obj)
|
||||||
|
{
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Releasing interface");
|
||||||
|
ESP_ERROR_CHECK(usb_host_interface_release(
|
||||||
|
driver_obj->client_hdl,
|
||||||
|
driver_obj->dev_hdl,
|
||||||
|
driver_obj->interface_conf.interface_nmbr));
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Closing device");
|
||||||
|
ESP_ERROR_CHECK(usb_host_device_close(driver_obj->client_hdl, driver_obj->dev_hdl));
|
||||||
|
driver_obj->dev_hdl = NULL;
|
||||||
|
driver_obj->dev_addr = 0;
|
||||||
|
//We need to exit the event handler loop
|
||||||
|
driver_obj->actions &= ~ACTION_CLOSE_DEV;
|
||||||
|
driver_obj->actions |= ACTION_EXIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void class_driver_task(void *arg)
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)arg;
|
||||||
|
class_driver_t driver_obj = {0};
|
||||||
|
|
||||||
|
//Wait until daemon task has installed USB Host Library
|
||||||
|
xSemaphoreTake(signaling_sem, portMAX_DELAY);
|
||||||
|
|
||||||
|
ESP_LOGI(DRIVER_TAG, "Registering Client");
|
||||||
|
usb_host_client_config_t client_config = {
|
||||||
|
.is_synchronous = false, //Synchronous clients currently not supported. Set this to false
|
||||||
|
.max_num_event_msg = USB_CLIENT_NUM_EVENT_MSG,
|
||||||
|
.async = {
|
||||||
|
.client_event_callback = client_event_cb,
|
||||||
|
.callback_arg = (void *) &driver_obj,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(usb_host_client_register(&client_config, &driver_obj.client_hdl));
|
||||||
|
|
||||||
|
//classic state machine
|
||||||
|
while (1) {
|
||||||
|
if (driver_obj.actions == 0) {
|
||||||
|
usb_host_client_handle_events(driver_obj.client_hdl, portMAX_DELAY);
|
||||||
|
} else {
|
||||||
|
if (driver_obj.actions & ACTION_OPEN_DEV) {
|
||||||
|
action_open_dev(&driver_obj);
|
||||||
|
}
|
||||||
|
if (driver_obj.actions & ACTION_GET_DEV_INFO) {
|
||||||
|
action_get_info(&driver_obj);
|
||||||
|
}
|
||||||
|
if (driver_obj.actions & ACTION_GET_DEV_DESC) {
|
||||||
|
action_get_dev_desc(&driver_obj);
|
||||||
|
}
|
||||||
|
if (driver_obj.actions & ACTION_GET_CONFIG_DESC) {
|
||||||
|
action_get_config_desc(&driver_obj);
|
||||||
|
}
|
||||||
|
if (driver_obj.actions & ACTION_GET_STR_DESC) {
|
||||||
|
action_get_str_desc(&driver_obj);
|
||||||
|
}
|
||||||
|
if(driver_obj.actions & ACTION_CLAIM_INTERFACE) {
|
||||||
|
action_claim_interface(&driver_obj);
|
||||||
|
}
|
||||||
|
if(driver_obj.actions & ACTION_START_READING_DATA) {
|
||||||
|
action_start_reading_data(&driver_obj);
|
||||||
|
}
|
||||||
|
if (driver_obj.actions & ACTION_CLOSE_DEV) {
|
||||||
|
aciton_close_dev(&driver_obj);
|
||||||
|
}
|
||||||
|
if (driver_obj.actions & ACTION_EXIT) {
|
||||||
|
driver_obj.actions = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
|
||||||
|
#include "midi_class_driver.c"
|
||||||
|
|
||||||
|
static const char *TAG = "DAEMON";
|
||||||
|
|
||||||
|
#define DAEMON_TASK_PRIORITY 2
|
||||||
|
#define CLASS_TASK_PRIORITY 3
|
||||||
|
|
||||||
|
static void host_lib_daemon_task(void *arg)
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t signaling_sem = (SemaphoreHandle_t)arg;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Installing USB Host Library");
|
||||||
|
usb_host_config_t host_config = {
|
||||||
|
.skip_phy_setup = false,
|
||||||
|
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||||
|
};
|
||||||
|
ESP_ERROR_CHECK(usb_host_install(&host_config));
|
||||||
|
|
||||||
|
//Signal to the class driver task that the host library is installed
|
||||||
|
xSemaphoreGive(signaling_sem);
|
||||||
|
vTaskDelay(10); //Short delay to let client task spin up
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
uint32_t event_flags;
|
||||||
|
ESP_ERROR_CHECK(usb_host_lib_handle_events(portMAX_DELAY, &event_flags));
|
||||||
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
|
||||||
|
ESP_LOGI(TAG, "no clients available");
|
||||||
|
}
|
||||||
|
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
|
||||||
|
ESP_LOGI(TAG, "no devices connected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
SemaphoreHandle_t signaling_sem = xSemaphoreCreateBinary();
|
||||||
|
|
||||||
|
TaskHandle_t daemon_task_hdl;
|
||||||
|
TaskHandle_t class_driver_task_hdl;
|
||||||
|
//Create daemon task
|
||||||
|
xTaskCreatePinnedToCore(host_lib_daemon_task,
|
||||||
|
"daemon",
|
||||||
|
4096,
|
||||||
|
(void *)signaling_sem,
|
||||||
|
DAEMON_TASK_PRIORITY,
|
||||||
|
&daemon_task_hdl,
|
||||||
|
0);
|
||||||
|
//Create the class driver task
|
||||||
|
xTaskCreatePinnedToCore(class_driver_task,
|
||||||
|
"class",
|
||||||
|
4096,
|
||||||
|
(void *)signaling_sem,
|
||||||
|
CLASS_TASK_PRIORITY,
|
||||||
|
&class_driver_task_hdl,
|
||||||
|
0);
|
||||||
|
|
||||||
|
vTaskDelay(10); //Add a short delay to let the tasks run
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user