remove tinyusb_dfu component, incompatible with ESP-IDF v5.0
This commit is contained in:
parent
d76f6ee6df
commit
0b1104ed89
|
@ -1,85 +0,0 @@
|
||||||
idf_build_get_property(target IDF_TARGET)
|
|
||||||
|
|
||||||
set(srcs)
|
|
||||||
set(includes_public)
|
|
||||||
set(includes_private)
|
|
||||||
set(compile_options)
|
|
||||||
|
|
||||||
if(CONFIG_TINYUSB_DFU)
|
|
||||||
if(target STREQUAL "esp32s3")
|
|
||||||
set(tusb_mcu "OPT_MCU_ESP32S3")
|
|
||||||
set(tusb_family "esp32sx")
|
|
||||||
elseif(target STREQUAL "esp32s2")
|
|
||||||
set(tusb_mcu "OPT_MCU_ESP32S2")
|
|
||||||
set(tusb_family "esp32sx")
|
|
||||||
else()
|
|
||||||
# CONFIG_TINYUSB_DFU dependency has been garanteed by Kconfig logic,
|
|
||||||
# So it's not possible that cmake goes here
|
|
||||||
message(FATAL_ERROR "TinyUSB is not support on ${target}.")
|
|
||||||
return()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
list(APPEND compile_options
|
|
||||||
"-DCFG_TUSB_MCU=${tusb_mcu}"
|
|
||||||
"-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DFU_DEBUG_LEVEL}"
|
|
||||||
)
|
|
||||||
|
|
||||||
idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR)
|
|
||||||
|
|
||||||
set(tusb_idf "$ENV{IDF_PATH}/components/tinyusb")
|
|
||||||
|
|
||||||
list(APPEND includes_private
|
|
||||||
"${tusb_idf}/tinyusb/hw/bsp/"
|
|
||||||
"${tusb_idf}/tinyusb/src/"
|
|
||||||
"${tusb_idf}/tinyusb/src/device"
|
|
||||||
"additions/include_private"
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND includes_public
|
|
||||||
"${tusb_idf}/tinyusb/src/"
|
|
||||||
"additions/include"
|
|
||||||
# The FreeRTOS API include convention in tinyusb is different from esp-idf
|
|
||||||
"${freertos_component_dir}/include/freertos"
|
|
||||||
)
|
|
||||||
|
|
||||||
list(APPEND srcs
|
|
||||||
"${tusb_idf}/tinyusb/src/portable/espressif/${tusb_family}/dcd_${tusb_family}.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/class/cdc/cdc_device.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/class/hid/hid_device.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/class/midi/midi_device.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/class/msc/msc_device.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/class/vendor/vendor_device.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/class/dfu/dfu_rt_device.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/common/tusb_fifo.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/device/usbd_control.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/device/usbd.c"
|
|
||||||
"${tusb_idf}/tinyusb/src/tusb.c"
|
|
||||||
"additions/src/descriptors_control.c"
|
|
||||||
"additions/src/tinyusb.c"
|
|
||||||
"additions/src/tusb_tasks.c"
|
|
||||||
"additions/src/usb_descriptors.c"
|
|
||||||
"additions/src/tusb_dfu_rt.c"
|
|
||||||
)
|
|
||||||
|
|
||||||
# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false
|
|
||||||
set_source_files_properties("tinyusb/src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits")
|
|
||||||
|
|
||||||
if(CONFIG_TINYUSB_DFU_CDC_ENABLED)
|
|
||||||
list(APPEND srcs
|
|
||||||
"additions/src/cdc.c"
|
|
||||||
"additions/src/tusb_cdc_acm.c"
|
|
||||||
"additions/src/tusb_console.c"
|
|
||||||
"additions/src/vfs_tinyusb.c"
|
|
||||||
)
|
|
||||||
endif() # CONFIG_TINYUSB_DFU_CDC_ENABLED
|
|
||||||
endif() # CONFIG_TINYUSB_DFU
|
|
||||||
|
|
||||||
idf_component_register(SRCS ${srcs}
|
|
||||||
INCLUDE_DIRS ${includes_public}
|
|
||||||
PRIV_INCLUDE_DIRS ${includes_private}
|
|
||||||
PRIV_REQUIRES "vfs" "usb" "app_update"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(CONFIG_TINYUSB_DFU)
|
|
||||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${compile_options})
|
|
||||||
endif()
|
|
|
@ -1,155 +0,0 @@
|
||||||
menu "TinyUSB (with DFU) Stack"
|
|
||||||
visible if USB_OTG_SUPPORTED
|
|
||||||
|
|
||||||
config TINYUSB_DFU
|
|
||||||
bool "Use TinyUSB (with DFU) Stack"
|
|
||||||
depends on USB_OTG_SUPPORTED
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Enable TinyUSB stack support.
|
|
||||||
Note that, esp-idf only uses the device stack provided by TinyUSB.
|
|
||||||
|
|
||||||
if TINYUSB_DFU
|
|
||||||
config TINYUSB_DFU_DEBUG_LEVEL
|
|
||||||
int "TinyUSB log level (0-3)"
|
|
||||||
default 0
|
|
||||||
range 0 3
|
|
||||||
help
|
|
||||||
Specify verbosity of TinyUSB log output.
|
|
||||||
|
|
||||||
menu "TinyUSB task configuration"
|
|
||||||
config TINYUSB_DFU_NO_DEFAULT_TASK
|
|
||||||
bool "Do not create a TinyUSB task"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
This option allows to not create the FreeRTOS task during the driver initialization.
|
|
||||||
User will have to handle TinyUSB events manually.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_TASK_PRIORITY
|
|
||||||
int "TinyUSB task priority"
|
|
||||||
default 5
|
|
||||||
depends on !TINYUSB_DFU_NO_DEFAULT_TASK
|
|
||||||
help
|
|
||||||
Set the priority of the default TinyUSB main task.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_TASK_STACK_SIZE
|
|
||||||
int "TinyUSB task stack size (bytes)"
|
|
||||||
default 4096
|
|
||||||
depends on !TINYUSB_DFU_NO_DEFAULT_TASK
|
|
||||||
help
|
|
||||||
Set the stack size of the default TinyUSB main task.
|
|
||||||
endmenu
|
|
||||||
|
|
||||||
menu "Descriptor configuration"
|
|
||||||
config TINYUSB_DFU_DESC_USE_ESPRESSIF_VID
|
|
||||||
bool "VID: Use Espressif's vendor ID"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Enable this option, USB device will use Espressif's vendor ID as its VID.
|
|
||||||
This is helpful at product develop stage.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_CUSTOM_VID
|
|
||||||
hex "VID: Custom vendor ID"
|
|
||||||
default 0x1234
|
|
||||||
depends on !TINYUSB_DFU_DESC_USE_ESPRESSIF_VID
|
|
||||||
help
|
|
||||||
Custom Vendor ID.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_USE_DEFAULT_PID
|
|
||||||
bool "PID: Use a default PID assigned to TinyUSB"
|
|
||||||
default y
|
|
||||||
help
|
|
||||||
Default TinyUSB PID assigning uses values 0x4000...0x4007.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_CUSTOM_PID
|
|
||||||
hex "PID: Custom product ID"
|
|
||||||
default 0x5678
|
|
||||||
depends on !TINYUSB_DFU_DESC_USE_DEFAULT_PID
|
|
||||||
help
|
|
||||||
Custom Product ID.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_BCD_DEVICE
|
|
||||||
hex "bcdDevice"
|
|
||||||
default 0x0100
|
|
||||||
help
|
|
||||||
Version of the firmware of the USB device.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_MANUFACTURER_STRING
|
|
||||||
string "Manufacturer name"
|
|
||||||
default "Espressif Systems"
|
|
||||||
help
|
|
||||||
Name of the manufacturer of the USB device.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_PRODUCT_STRING
|
|
||||||
string "Product name"
|
|
||||||
default "Espressif Device"
|
|
||||||
help
|
|
||||||
Name of the USB device.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_SERIAL_STRING
|
|
||||||
string "Serial string"
|
|
||||||
default "123456"
|
|
||||||
help
|
|
||||||
Serial number of the USB device.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_CDC_STRING
|
|
||||||
depends on TINYUSB_DFU_CDC_ENABLED
|
|
||||||
string "CDC Device String"
|
|
||||||
default "Espressif CDC Device"
|
|
||||||
help
|
|
||||||
Name of the CDC device.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_MSC_STRING
|
|
||||||
depends on TINYUSB_DFU_MSC_ENABLED
|
|
||||||
string "MSC Device String"
|
|
||||||
default "Espressif MSC Device"
|
|
||||||
help
|
|
||||||
Name of the MSC device.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_DESC_HID_STRING
|
|
||||||
depends on TINYUSB_DFU_HID_ENABLED
|
|
||||||
string "HID Device String"
|
|
||||||
default "Espressif HID Device"
|
|
||||||
help
|
|
||||||
Name of the HID device
|
|
||||||
endmenu # "Descriptor configuration"
|
|
||||||
|
|
||||||
menu "Massive Storage Class (MSC)"
|
|
||||||
config TINYUSB_DFU_MSC_ENABLED
|
|
||||||
bool "Enable TinyUSB MSC feature"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Enable TinyUSB MSC feature.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_MSC_BUFSIZE
|
|
||||||
depends on TINYUSB_DFU_MSC_ENABLED
|
|
||||||
int "MSC FIFO size"
|
|
||||||
default 512
|
|
||||||
help
|
|
||||||
MSC FIFO size, in bytes.
|
|
||||||
endmenu # "Massive Storage Class"
|
|
||||||
|
|
||||||
menu "Communication Device Class (CDC)"
|
|
||||||
config TINYUSB_DFU_CDC_ENABLED
|
|
||||||
bool "Enable TinyUSB CDC feature"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Enable TinyUSB CDC feature.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_CDC_RX_BUFSIZE
|
|
||||||
depends on TINYUSB_DFU_CDC_ENABLED
|
|
||||||
int "CDC FIFO size of RX channel"
|
|
||||||
default 64
|
|
||||||
help
|
|
||||||
CDC FIFO size of RX channel.
|
|
||||||
|
|
||||||
config TINYUSB_DFU_CDC_TX_BUFSIZE
|
|
||||||
depends on TINYUSB_DFU_CDC_ENABLED
|
|
||||||
int "CDC FIFO size of TX channel"
|
|
||||||
default 64
|
|
||||||
help
|
|
||||||
CDC FIFO size of TX channel.
|
|
||||||
endmenu # "Communication Device Class"
|
|
||||||
endif # TINYUSB_DFU
|
|
||||||
|
|
||||||
endmenu # "TinyUSB Stack"
|
|
|
@ -1,102 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tusb_option.h"
|
|
||||||
#include "tusb_config.h"
|
|
||||||
#include "tinyusb_types.h"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/* tinyusb uses buffers with type of uint8_t[] but in our driver we are reading them as a 32-bit word */
|
|
||||||
#if (CFG_TUD_ENDPOINT0_SIZE < 4)
|
|
||||||
# define CFG_TUD_ENDPOINT0_SIZE 4
|
|
||||||
# warning "CFG_TUD_ENDPOINT0_SIZE was too low and was set to 4"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if TUSB_OPT_DEVICE_ENABLED
|
|
||||||
|
|
||||||
# if CFG_TUD_HID
|
|
||||||
# if (CFG_TUD_HID_BUFSIZE < 4)
|
|
||||||
# define CFG_TUD_HID_BUFSIZE 4
|
|
||||||
# warning "CFG_TUD_HID_BUFSIZE was too low and was set to 4"
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if CFG_TUD_CDC
|
|
||||||
# if (CFG_TUD_CDC_EP_BUFSIZE < 4)
|
|
||||||
# define CFG_TUD_CDC_EP_BUFSIZE 4
|
|
||||||
# warning "CFG_TUD_CDC_EP_BUFSIZE was too low and was set to 4"
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if CFG_TUD_MSC
|
|
||||||
# if (CFG_TUD_MSC_BUFSIZE < 4)
|
|
||||||
# define CFG_TUD_MSC_BUFSIZE 4
|
|
||||||
# warning "CFG_TUD_MSC_BUFSIZE was too low and was set to 4"
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if CFG_TUD_MIDI
|
|
||||||
# if (CFG_TUD_MIDI_EPSIZE < 4)
|
|
||||||
# define CFG_TUD_MIDI_EPSIZE 4
|
|
||||||
# warning "CFG_TUD_MIDI_EPSIZE was too low and was set to 4"
|
|
||||||
# endif
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if CFG_TUD_CUSTOM_CLASS
|
|
||||||
# warning "Please check that the buffer is more then 4 bytes"
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration structure of the tinyUSB core
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
tusb_desc_device_t *descriptor; /*!< Pointer to a device descriptor */
|
|
||||||
const char **string_descriptor; /*!< Pointer to an array of string descriptors */
|
|
||||||
bool external_phy; /*!< Should USB use an external PHY */
|
|
||||||
} tinyusb_config_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This is an all-in-one helper function, including:
|
|
||||||
* 1. USB device driver initialization
|
|
||||||
* 2. Descriptors preparation
|
|
||||||
* 3. TinyUSB stack initialization
|
|
||||||
* 4. Creates and start a task to handle usb events
|
|
||||||
*
|
|
||||||
* @note Don't change Custom descriptor, but if it has to be done,
|
|
||||||
* Suggest to define as follows in order to match the Interface Association Descriptor (IAD):
|
|
||||||
* bDeviceClass = TUSB_CLASS_MISC,
|
|
||||||
* bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
|
||||||
*
|
|
||||||
* @param config tinyusb stack specific configuration
|
|
||||||
* @retval ESP_ERR_INVALID_ARG Install driver and tinyusb stack failed because of invalid argument
|
|
||||||
* @retval ESP_FAIL Install driver and tinyusb stack failed because of internal error
|
|
||||||
* @retval ESP_OK Install driver and tinyusb stack successfully
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config);
|
|
||||||
|
|
||||||
// TODO esp_err_t tinyusb_driver_uninstall(void); (IDF-1474)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,32 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define USB_ESPRESSIF_VID 0x303A
|
|
||||||
#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8
|
|
||||||
|
|
||||||
typedef enum{
|
|
||||||
TINYUSB_USBDEV_0,
|
|
||||||
} tinyusb_usbdev_t;
|
|
||||||
|
|
||||||
typedef const char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,202 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/ringbuf.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "freertos/timers.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tinyusb.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CDC ports available to setup
|
|
||||||
*/
|
|
||||||
typedef enum{
|
|
||||||
TINYUSB_CDC_ACM_0 = 0x0
|
|
||||||
}tinyusb_cdcacm_itf_t;
|
|
||||||
|
|
||||||
/* Callbacks and events
|
|
||||||
********************************************************************* */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data provided to the input of the `callback_rx_wanted_char` callback
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
char wanted_char; /*!< Wanted character */
|
|
||||||
} cdcacm_event_rx_wanted_char_data_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data provided to the input of the `callback_line_state_changed` callback
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
bool dtr; /*!< Data Terminal Ready (DTR) line state */
|
|
||||||
bool rts; /*!< Request To Send (RTS) line state */
|
|
||||||
} cdcacm_event_line_state_changed_data_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Data provided to the input of the `line_coding_changed` callback
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
cdc_line_coding_t const *p_line_coding; /*!< New line coding value */
|
|
||||||
} cdcacm_event_line_coding_changed_data_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Types of CDC ACM events
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
CDC_EVENT_RX,
|
|
||||||
CDC_EVENT_RX_WANTED_CHAR,
|
|
||||||
CDC_EVENT_LINE_STATE_CHANGED,
|
|
||||||
CDC_EVENT_LINE_CODING_CHANGED
|
|
||||||
} cdcacm_event_type_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Describes an event passing to the input of a callbacks
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
cdcacm_event_type_t type; /*!< Event type */
|
|
||||||
union {
|
|
||||||
cdcacm_event_rx_wanted_char_data_t rx_wanted_char_data; /*!< Data input of the `callback_rx_wanted_char` callback */
|
|
||||||
cdcacm_event_line_state_changed_data_t line_state_changed_data; /*!< Data input of the `callback_line_state_changed` callback */
|
|
||||||
cdcacm_event_line_coding_changed_data_t line_coding_changed_data; /*!< Data input of the `line_coding_changed` callback */
|
|
||||||
};
|
|
||||||
} cdcacm_event_t;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief CDC-ACM callback type
|
|
||||||
*/
|
|
||||||
typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event);
|
|
||||||
|
|
||||||
/*********************************************************************** Callbacks and events*/
|
|
||||||
/* Other structs
|
|
||||||
********************************************************************* */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Configuration structure for CDC-ACM
|
|
||||||
*/
|
|
||||||
typedef struct {
|
|
||||||
tinyusb_usbdev_t usb_dev; /*!< Usb device to set up */
|
|
||||||
tinyusb_cdcacm_itf_t cdc_port; /*!< CDC port */
|
|
||||||
size_t rx_unread_buf_sz; /*!< Amount of data that can be passed to the AMC at once */
|
|
||||||
tusb_cdcacm_callback_t callback_rx; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
|
|
||||||
tusb_cdcacm_callback_t callback_rx_wanted_char; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
|
|
||||||
tusb_cdcacm_callback_t callback_line_state_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
|
|
||||||
tusb_cdcacm_callback_t callback_line_coding_changed; /*!< Pointer to the function with the `tusb_cdcacm_callback_t` type that will be handled as a callback */
|
|
||||||
} tinyusb_config_cdcacm_t;
|
|
||||||
|
|
||||||
/*********************************************************************** Other structs*/
|
|
||||||
/* Public functions
|
|
||||||
********************************************************************* */
|
|
||||||
/**
|
|
||||||
* @brief Initialize CDC ACM. Initialization will be finished with
|
|
||||||
* the `tud_cdc_line_state_cb` callback
|
|
||||||
*
|
|
||||||
* @param cfg - init configuration structure
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register a callback invoking on CDC event. If the callback had been
|
|
||||||
* already registered, it will be overwritten
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param event_type - type of registered event for a callback
|
|
||||||
* @param callback - callback function
|
|
||||||
* @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf,
|
|
||||||
cdcacm_event_type_t event_type,
|
|
||||||
tusb_cdcacm_callback_t callback);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unregister a callback invoking on CDC event.
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param event_type - type of registered event for a callback
|
|
||||||
* @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Sent one character to a write buffer
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param ch - character to send
|
|
||||||
* @return size_t - amount of queued bytes
|
|
||||||
*/
|
|
||||||
size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Write data to write buffer from a byte array
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param in_buf - a source array
|
|
||||||
* @param in_size - size to write from arr_src
|
|
||||||
* @return size_t - amount of queued bytes
|
|
||||||
*/
|
|
||||||
size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Send all data from a write buffer. Use `tinyusb_cdcacm_write_queue` to add data to the buffer.
|
|
||||||
*
|
|
||||||
* WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush
|
|
||||||
* after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until
|
|
||||||
* ont of the next callbacks ends.
|
|
||||||
* SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param timeout_ticks - waiting until flush will be considered as failed
|
|
||||||
* @return esp_err_t - ESP_OK if (timeout_ticks > 0) and and flush was successful,
|
|
||||||
* ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0)
|
|
||||||
* ESP_FAIL if flush was unsuccessful
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Read a content to the array, and defines it's size to the sz_store
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param out_buf - to this array will be stored the object from a CDC buffer
|
|
||||||
* @param out_buf_sz - size of buffer for results
|
|
||||||
* @param rx_data_size - to this address will be stored the object's size
|
|
||||||
* @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Check if the ACM initialized
|
|
||||||
*
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @return true or false
|
|
||||||
*/
|
|
||||||
bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf);
|
|
||||||
|
|
||||||
/*********************************************************************** Public functions*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,98 +0,0 @@
|
||||||
/*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2019 Ha Thach (tinyusb.org),
|
|
||||||
* Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "tusb_option.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_TINYUSB_DFU_CDC_ENABLED
|
|
||||||
# define CONFIG_TINYUSB_DFU_CDC_ENABLED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_TINYUSB_DFU_MSC_ENABLED
|
|
||||||
# define CONFIG_TINYUSB_DFU_MSC_ENABLED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_TINYUSB_DFU_HID_ENABLED
|
|
||||||
# define CONFIG_TINYUSB_DFU_HID_ENABLED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_TINYUSB_DFU_MIDI_ENABLED
|
|
||||||
# define CONFIG_TINYUSB_DFU_MIDI_ENABLED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CONFIG_TINYUSB_DFU_CUSTOM_CLASS_ENABLED
|
|
||||||
# define CONFIG_TINYUSB_DFU_CUSTOM_CLASS_ENABLED 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED
|
|
||||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
|
||||||
|
|
||||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
|
||||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
|
||||||
* into those specific section.
|
|
||||||
* e.g
|
|
||||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
|
||||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
|
||||||
*/
|
|
||||||
#ifndef CFG_TUSB_MEM_SECTION
|
|
||||||
# define CFG_TUSB_MEM_SECTION
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CFG_TUSB_MEM_ALIGN
|
|
||||||
# define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
|
||||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// CDC FIFO size of TX and RX
|
|
||||||
#define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_DFU_CDC_RX_BUFSIZE
|
|
||||||
#define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_DFU_CDC_TX_BUFSIZE
|
|
||||||
|
|
||||||
// MSC Buffer size of Device Mass storage
|
|
||||||
#define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_DFU_MSC_BUFSIZE
|
|
||||||
|
|
||||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
|
||||||
#define CFG_TUD_HID_BUFSIZE CONFIG_TINYUSB_DFU_HID_BUFSIZE
|
|
||||||
|
|
||||||
// Enabled device class driver
|
|
||||||
#define CFG_TUD_CDC CONFIG_TINYUSB_DFU_CDC_ENABLED
|
|
||||||
#define CFG_TUD_MSC CONFIG_TINYUSB_DFU_MSC_ENABLED
|
|
||||||
#define CFG_TUD_HID CONFIG_TINYUSB_DFU_HID_ENABLED
|
|
||||||
#define CFG_TUD_MIDI CONFIG_TINYUSB_DFU_MIDI_ENABLED
|
|
||||||
#define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_DFU_CUSTOM_CLASS_ENABLED
|
|
||||||
#define CFG_TUD_DFU_RUNTIME 1
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,41 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Redirect output to the USB serial
|
|
||||||
* @param cdc_intf - interface number of TinyUSB's CDC
|
|
||||||
*
|
|
||||||
* @return esp_err_t - ESP_OK, ESP_FAIL or an error code
|
|
||||||
*/
|
|
||||||
esp_err_t esp_tusb_init_console(int cdc_intf);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Switch log to the default output
|
|
||||||
* @param cdc_intf - interface number of TinyUSB's CDC
|
|
||||||
*
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t esp_tusb_deinit_console(int cdc_intf);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,37 +0,0 @@
|
||||||
// Copyright 2022 King Kévin <kingkevin@cuvoodoo.info>
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tinyusb.h"
|
|
||||||
|
|
||||||
/* Public functions */
|
|
||||||
/**
|
|
||||||
* @brief Initialize DFU runtime.
|
|
||||||
*
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
esp_err_t tusb_dfu_rf_init(void);
|
|
||||||
|
|
||||||
/** Public functions*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,46 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This helper function creates and starts a task which wraps `tud_task()`.
|
|
||||||
*
|
|
||||||
* The wrapper function basically wraps tud_task and some log.
|
|
||||||
* Default parameters: stack size and priority as configured, argument = NULL, not pinned to any core.
|
|
||||||
* If you have more requirements for this task, you can create your own task which calls tud_task as the last step.
|
|
||||||
*
|
|
||||||
* @retval ESP_OK run tinyusb main task successfully
|
|
||||||
* @retval ESP_FAIL run tinyusb main task failed of internal error
|
|
||||||
* @retval ESP_ERR_INVALID_STATE tinyusb main task has been created before
|
|
||||||
*/
|
|
||||||
esp_err_t tusb_run_task(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This helper function stops and destroys the task created by `tusb_run_task()`
|
|
||||||
*
|
|
||||||
* @retval ESP_OK stop and destory tinyusb main task successfully
|
|
||||||
* @retval ESP_ERR_INVALID_STATE tinyusb main task hasn't been created yet
|
|
||||||
*/
|
|
||||||
esp_err_t tusb_stop_task(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,42 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "esp_err.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Register TinyUSB CDC at VFS with path
|
|
||||||
* @param cdc_intf - interface number of TinyUSB's CDC
|
|
||||||
* @param path - path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL.
|
|
||||||
*
|
|
||||||
* @return esp_err_t ESP_OK or ESP_FAIL
|
|
||||||
*/
|
|
||||||
esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Unregister TinyUSB CDC from VFS
|
|
||||||
* @param path - path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc`
|
|
||||||
*
|
|
||||||
* @return esp_err_t ESP_OK or ESP_FAIL
|
|
||||||
*/
|
|
||||||
esp_err_t esp_vfs_tusb_cdc_unregister(char const *path);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,99 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/ringbuf.h"
|
|
||||||
#include "freertos/semphr.h"
|
|
||||||
#include "freertos/timers.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tinyusb_types.h"
|
|
||||||
|
|
||||||
/* CDC classification
|
|
||||||
********************************************************************* */
|
|
||||||
typedef enum {
|
|
||||||
TINYUSB_CDC_DATA = 0x00,
|
|
||||||
} cdc_data_sublcass_type_t; // CDC120 specification
|
|
||||||
|
|
||||||
/* Note:other classification is represented in the file components\tinyusb\tinyusb\src\class\cdc\cdc.h */
|
|
||||||
|
|
||||||
/*********************************************************************** CDC classification*/
|
|
||||||
/* Structs
|
|
||||||
********************************************************************* */
|
|
||||||
typedef struct {
|
|
||||||
tinyusb_usbdev_t usb_dev; /*!< USB device to set up */
|
|
||||||
tusb_class_code_t cdc_class; /*!< CDC device class : Communications or Data device */
|
|
||||||
union {
|
|
||||||
cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: AMC, ECM, etc. */
|
|
||||||
cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/
|
|
||||||
} cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */
|
|
||||||
} tinyusb_config_cdc_t; /*!< Main configuration structure of a CDC device */
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
tinyusb_usbdev_t usb_dev; /*!< USB device used for the instance */
|
|
||||||
tusb_class_code_t type;
|
|
||||||
union {
|
|
||||||
cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: AMC, ECM, etc. */
|
|
||||||
cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/
|
|
||||||
} cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */
|
|
||||||
void *subclass_obj; /*!< Dynamically allocated subclass specific object */
|
|
||||||
} esp_tusb_cdc_t;
|
|
||||||
/*********************************************************************** Structs*/
|
|
||||||
/* Functions
|
|
||||||
********************************************************************* */
|
|
||||||
/**
|
|
||||||
* @brief Initializing CDC basic object
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @param cfg - CDC configuration structure
|
|
||||||
*
|
|
||||||
* @return esp_err_t ESP_OK or ESP_FAIL
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief De-initializing CDC. Clean its objects
|
|
||||||
* @param itf - number of a CDC object
|
|
||||||
* @return esp_err_t ESP_OK, ESP_ERR_INVALID_ARG, ESP_ERR_INVALID_STATE
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
esp_err_t tinyusb_cdc_deinit(int itf);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Checks if the CDC initialized and ready to interaction
|
|
||||||
*
|
|
||||||
* @return true or false
|
|
||||||
*/
|
|
||||||
bool tinyusb_cdc_initialized(int itf);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Return interface of a CDC device
|
|
||||||
*
|
|
||||||
* @param itf_num
|
|
||||||
* @return esp_tusb_cdc_t* pointer to the interface or (NULL) on error
|
|
||||||
*/
|
|
||||||
esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num);
|
|
||||||
/*********************************************************************** Functions*/
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,72 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include "usb_descriptors.h"
|
|
||||||
|
|
||||||
|
|
||||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
|
||||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
|
||||||
*
|
|
||||||
* Auto ProductID layout's Bitmap:
|
|
||||||
* [MSB] HID | MSC | CDC [LSB]
|
|
||||||
*/
|
|
||||||
#define EPNUM_MSC 0x03
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
//------------- HID Report Descriptor -------------//
|
|
||||||
#if CFG_TUD_HID
|
|
||||||
enum {
|
|
||||||
REPORT_ID_KEYBOARD = 1,
|
|
||||||
REPORT_ID_MOUSE
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//------------- Configuration Descriptor -------------//
|
|
||||||
enum {
|
|
||||||
# if CFG_TUD_CDC
|
|
||||||
ITF_NUM_CDC = 0,
|
|
||||||
ITF_NUM_CDC_DATA,
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if CFG_TUD_MSC
|
|
||||||
ITF_NUM_MSC,
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# if CFG_TUD_HID
|
|
||||||
ITF_NUM_HID,
|
|
||||||
# endif
|
|
||||||
|
|
||||||
ITF_NUM_DFU_RT,
|
|
||||||
ITF_NUM_TOTAL
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN + CFG_TUD_CDC * TUD_CDC_DESC_LEN + CFG_TUD_MSC * TUD_MSC_DESC_LEN +
|
|
||||||
CFG_TUD_HID * TUD_HID_DESC_LEN + CFG_TUD_DFU_RUNTIME * TUD_DFU_RT_DESC_LEN
|
|
||||||
};
|
|
||||||
|
|
||||||
bool tusb_desc_set;
|
|
||||||
void tusb_set_descriptor(tusb_desc_device_t *desc, const char **str_desc);
|
|
||||||
tusb_desc_device_t *tusb_get_active_desc(void);
|
|
||||||
char **tusb_get_active_str_desc(void);
|
|
||||||
void tusb_clear_descriptor(void);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tinyusb_types.h"
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
|
|
||||||
|
|
||||||
extern tusb_desc_device_t descriptor_tinyusb;
|
|
||||||
extern tusb_desc_strarray_device_t descriptor_str_tinyusb;
|
|
||||||
|
|
||||||
extern tusb_desc_device_t descriptor_kconfig;
|
|
||||||
extern tusb_desc_strarray_device_t descriptor_str_kconfig;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -1,161 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "cdc.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
static const char *TAG = "tusb_cdc";
|
|
||||||
|
|
||||||
#define CDC_INTF_NUM CFG_TUD_CDC // number of cdc blocks
|
|
||||||
|
|
||||||
static esp_tusb_cdc_t *cdc_obj[CDC_INTF_NUM] = {};
|
|
||||||
|
|
||||||
/* Common CDC functions
|
|
||||||
********************************************************************* */
|
|
||||||
bool tinyusb_cdc_initialized(int itf)
|
|
||||||
{
|
|
||||||
return (cdc_obj[itf] != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t cdc_interface_check(int itf)
|
|
||||||
{
|
|
||||||
if (tinyusb_cdc_initialized(itf)) {
|
|
||||||
return ESP_OK;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief
|
|
||||||
*
|
|
||||||
* @param itf
|
|
||||||
* @param expected_inited
|
|
||||||
* @param expected_type use -1 if you don't care
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
|
||||||
static esp_err_t cdc_obj_check(int itf, bool expected_inited, tusb_class_code_t expected_type)
|
|
||||||
{
|
|
||||||
bool inited = (cdc_obj[itf] != NULL);
|
|
||||||
if (expected_inited != inited) {
|
|
||||||
ESP_LOGE(TAG, "Wrong state of the interface. Expected state: %s",
|
|
||||||
expected_inited ? "initialized" : "not initialized");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
if (inited && (expected_type != -1) && !(cdc_obj[itf]->type == expected_type)) {
|
|
||||||
ESP_LOGE(TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num)
|
|
||||||
{
|
|
||||||
if (cdc_interface_check(itf_num) != ESP_OK) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return cdc_obj[itf_num];
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************** Common CDC functions*/
|
|
||||||
/* CDC class funcs
|
|
||||||
********************************************************************* */
|
|
||||||
static esp_err_t tusb_cdc_comm_init(int itf)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed");
|
|
||||||
cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t));
|
|
||||||
if (cdc_obj[itf] != NULL) {
|
|
||||||
cdc_obj[itf]->type = TUSB_CLASS_CDC;
|
|
||||||
ESP_LOGD(TAG, "CDC Comm class initialized");
|
|
||||||
return ESP_OK;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "CDC Comm initialization error");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t tusb_cdc_deinit_comm(int itf)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC), TAG, "cdc_obj_check failed");
|
|
||||||
free(cdc_obj[itf]);
|
|
||||||
cdc_obj[itf] = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t tusb_cdc_data_init(int itf)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed");
|
|
||||||
cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t));
|
|
||||||
if (cdc_obj[itf] != NULL) {
|
|
||||||
cdc_obj[itf]->type = TUSB_CLASS_CDC_DATA;
|
|
||||||
ESP_LOGD(TAG, "CDC Data class initialized");
|
|
||||||
return ESP_OK;
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "CDC Data initialization error");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t tusb_cdc_deinit_data(int itf)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed");
|
|
||||||
free(cdc_obj[itf]);
|
|
||||||
cdc_obj[itf] = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
/*********************************************************************** CDC class funcs*/
|
|
||||||
/* CDC initialization
|
|
||||||
********************************************************************* */
|
|
||||||
esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "CDC initialization...");
|
|
||||||
if (itf != 0) {
|
|
||||||
ESP_LOGE(TAG, "There is not CDC no.%d", itf);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
if (cfg->cdc_class == TUSB_CLASS_CDC) {
|
|
||||||
ESP_RETURN_ON_ERROR(tusb_cdc_comm_init(itf), TAG, "tusb_cdc_comm_init failed");
|
|
||||||
cdc_obj[itf]->cdc_subclass.comm_subclass = cfg->cdc_subclass.comm_subclass;
|
|
||||||
} else {
|
|
||||||
ESP_RETURN_ON_ERROR(tusb_cdc_data_init(itf), TAG, "tusb_cdc_data_init failed");
|
|
||||||
cdc_obj[itf]->cdc_subclass.data_subclass = cfg->cdc_subclass.data_subclass;
|
|
||||||
}
|
|
||||||
cdc_obj[itf]->usb_dev = cfg->usb_dev;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
esp_err_t tinyusb_cdc_deinit(int itf)
|
|
||||||
{
|
|
||||||
if (itf != 0) {
|
|
||||||
ESP_LOGE(TAG, "There is not CDC no.%d", itf);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
if (cdc_obj[itf]->type == TUSB_CLASS_CDC) {
|
|
||||||
ESP_RETURN_ON_ERROR(tusb_cdc_deinit_comm(itf), TAG, "tusb_cdc_deinit_comm failed");
|
|
||||||
} else if (cdc_obj[itf]->type == TUSB_CLASS_CDC_DATA) {
|
|
||||||
ESP_RETURN_ON_ERROR(tusb_cdc_deinit_data(itf), TAG, "tusb_cdc_deinit_data failed");
|
|
||||||
} else {
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
ESP_LOGD(TAG, "De-initialized");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
/*********************************************************************** CDC initialization*/
|
|
|
@ -1,195 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "descriptors_control.h"
|
|
||||||
#include "class/dfu/dfu_rt_device.h"
|
|
||||||
|
|
||||||
static const char *TAG = "tusb_desc";
|
|
||||||
static tusb_desc_device_t s_descriptor;
|
|
||||||
static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
|
|
||||||
#define MAX_DESC_BUF_SIZE 32
|
|
||||||
|
|
||||||
#if CFG_TUD_HID //HID Report Descriptor
|
|
||||||
uint8_t const desc_hid_report[] = {
|
|
||||||
TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD), ),
|
|
||||||
TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_MOUSE), )
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint8_t const desc_configuration[] = {
|
|
||||||
// interface count, string index, total length, attribute, power in mA
|
|
||||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
|
||||||
|
|
||||||
# if CFG_TUD_CDC
|
|
||||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
|
||||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64),
|
|
||||||
# endif
|
|
||||||
# if CFG_TUD_MSC
|
|
||||||
// Interface number, string index, EP Out & EP In address, EP size
|
|
||||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
|
|
||||||
# endif
|
|
||||||
# if CFG_TUD_HID
|
|
||||||
// Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
|
|
||||||
TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x84, 16, 10),
|
|
||||||
# endif
|
|
||||||
# if CFG_TUD_DFU_RUNTIME
|
|
||||||
// Interface number, string index, attributes, detach timeout, transfer size */
|
|
||||||
TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 7, 0x0f, 1000, 512), // allow detach, manifest, upload, download; set transfer size to high speed 512
|
|
||||||
# endif
|
|
||||||
};
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// CALLBACKS
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Invoked when received GET DEVICE DESCRIPTOR.
|
|
||||||
* Application returns pointer to descriptor
|
|
||||||
*
|
|
||||||
* @return uint8_t const*
|
|
||||||
*/
|
|
||||||
uint8_t const *tud_descriptor_device_cb(void)
|
|
||||||
{
|
|
||||||
return (uint8_t const *)&s_descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Invoked when received GET CONFIGURATION DESCRIPTOR.
|
|
||||||
* Descriptor contents must exist long enough for transfer to complete
|
|
||||||
*
|
|
||||||
* @param index
|
|
||||||
* @return uint8_t const* Application return pointer to descriptor
|
|
||||||
*/
|
|
||||||
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
|
|
||||||
{
|
|
||||||
(void)index; // for multiple configurations
|
|
||||||
return desc_configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint16_t _desc_str[MAX_DESC_BUF_SIZE];
|
|
||||||
|
|
||||||
// Invoked when received GET STRING DESCRIPTOR request
|
|
||||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
|
||||||
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
|
||||||
{
|
|
||||||
(void) langid;
|
|
||||||
|
|
||||||
uint8_t chr_count;
|
|
||||||
|
|
||||||
if ( index == 0) {
|
|
||||||
memcpy(&_desc_str[1], s_str_descriptor[0], 2);
|
|
||||||
chr_count = 1;
|
|
||||||
} else {
|
|
||||||
// Convert ASCII string into UTF-16
|
|
||||||
|
|
||||||
if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *str = s_str_descriptor[index];
|
|
||||||
|
|
||||||
// Cap at max char
|
|
||||||
chr_count = strlen(str);
|
|
||||||
if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) {
|
|
||||||
chr_count = MAX_DESC_BUF_SIZE - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < chr_count; i++) {
|
|
||||||
_desc_str[1 + i] = str[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// first byte is length (including header), second byte is string type
|
|
||||||
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2);
|
|
||||||
|
|
||||||
return _desc_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Invoked when received GET HID REPORT DESCRIPTOR
|
|
||||||
* Application returns pointer to descriptor. Descriptor contents must exist
|
|
||||||
* long enough for transfer to complete
|
|
||||||
*
|
|
||||||
* @return uint8_t const*
|
|
||||||
*/
|
|
||||||
#if CFG_TUD_HID
|
|
||||||
uint8_t const *tud_hid_descriptor_report_cb(void)
|
|
||||||
{
|
|
||||||
return desc_hid_report;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// =============================================================================
|
|
||||||
// Driver functions
|
|
||||||
// =============================================================================
|
|
||||||
|
|
||||||
void tusb_set_descriptor(tusb_desc_device_t *dev_desc, const char **str_desc)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "\n"
|
|
||||||
"┌─────────────────────────────────┐\n"
|
|
||||||
"│ USB Device Descriptor Summary │\n"
|
|
||||||
"├───────────────────┬─────────────┤\n"
|
|
||||||
"│bDeviceClass │ %-4u │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│bDeviceSubClass │ %-4u │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│bDeviceProtocol │ %-4u │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│bMaxPacketSize0 │ %-4u │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│idVendor │ %-#10x │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│idProduct │ %-#10x │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│bcdDevice │ %-#10x │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│iManufacturer │ %-#10x │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│iProduct │ %-#10x │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│iSerialNumber │ %-#10x │\n"
|
|
||||||
"├───────────────────┼─────────────┤\n"
|
|
||||||
"│bNumConfigurations │ %-#10x │\n"
|
|
||||||
"└───────────────────┴─────────────┘",
|
|
||||||
dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
|
|
||||||
dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0,
|
|
||||||
dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice,
|
|
||||||
dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber,
|
|
||||||
dev_desc->bNumConfigurations);
|
|
||||||
s_descriptor = *dev_desc;
|
|
||||||
|
|
||||||
if (str_desc != NULL) {
|
|
||||||
memcpy(s_str_descriptor, str_desc,
|
|
||||||
sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE);
|
|
||||||
}
|
|
||||||
tusb_desc_set = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
tusb_desc_device_t *tusb_get_active_desc(void)
|
|
||||||
{
|
|
||||||
return &s_descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
char **tusb_get_active_str_desc(void)
|
|
||||||
{
|
|
||||||
return s_str_descriptor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void tusb_clear_descriptor(void)
|
|
||||||
{
|
|
||||||
memset(&s_descriptor, 0, sizeof(s_descriptor));
|
|
||||||
memset(&s_str_descriptor, 0, sizeof(s_str_descriptor));
|
|
||||||
tusb_desc_set = false;
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_private/usb_phy.h"
|
|
||||||
#include "soc/usb_pins.h"
|
|
||||||
#include "tinyusb.h"
|
|
||||||
#include "descriptors_control.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tusb_tasks.h"
|
|
||||||
|
|
||||||
const static char *TAG = "TinyUSB";
|
|
||||||
static usb_phy_handle_t phy_hdl;
|
|
||||||
|
|
||||||
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
|
|
||||||
{
|
|
||||||
tusb_desc_device_t *dev_descriptor;
|
|
||||||
const char **string_descriptor;
|
|
||||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
|
||||||
|
|
||||||
// Configure USB PHY
|
|
||||||
usb_phy_config_t phy_conf = {
|
|
||||||
.controller = USB_PHY_CTRL_OTG,
|
|
||||||
.otg_mode = USB_OTG_MODE_DEVICE,
|
|
||||||
};
|
|
||||||
if (config->external_phy) {
|
|
||||||
phy_conf.target = USB_PHY_TARGET_EXT;
|
|
||||||
usb_phy_gpio_conf_t gpio_conf = {
|
|
||||||
.vp_io_num = USBPHY_VP_NUM,
|
|
||||||
.vm_io_num = USBPHY_VM_NUM,
|
|
||||||
.rcv_io_num = USBPHY_RCV_NUM,
|
|
||||||
.oen_io_num = USBPHY_OEN_NUM,
|
|
||||||
.vpo_io_num = USBPHY_VPO_NUM,
|
|
||||||
.vmo_io_num = USBPHY_VMO_NUM,
|
|
||||||
};
|
|
||||||
phy_conf.gpio_conf = &gpio_conf;
|
|
||||||
} else {
|
|
||||||
phy_conf.target = USB_PHY_TARGET_INT;
|
|
||||||
}
|
|
||||||
ESP_RETURN_ON_ERROR(usb_new_phy(&phy_conf, &phy_hdl), TAG, "Install USB PHY failed");
|
|
||||||
|
|
||||||
dev_descriptor = config->descriptor ? config->descriptor : &descriptor_kconfig;
|
|
||||||
if (!config->string_descriptor) { // use configured strings
|
|
||||||
// set MAC as serial
|
|
||||||
uint8_t mac[6];
|
|
||||||
esp_read_mac(mac, ESP_MAC_ETH);
|
|
||||||
static char usb_serial[13] = {0};
|
|
||||||
snprintf(usb_serial, sizeof(usb_serial), "%02X%02X%02X%02X%02X%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
|
||||||
descriptor_str_kconfig[3] = usb_serial;
|
|
||||||
}
|
|
||||||
string_descriptor = config->string_descriptor ? config->string_descriptor : descriptor_str_kconfig;
|
|
||||||
|
|
||||||
tusb_set_descriptor(dev_descriptor, string_descriptor);
|
|
||||||
|
|
||||||
ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed");
|
|
||||||
#if !CONFIG_TINYUSB_DFU_NO_DEFAULT_TASK
|
|
||||||
ESP_RETURN_ON_ERROR(tusb_run_task(), TAG, "Run TinyUSB task failed");
|
|
||||||
#endif
|
|
||||||
ESP_LOGI(TAG, "TinyUSB Driver installed");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
|
@ -1,426 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tusb_cdc_acm.h"
|
|
||||||
#include "cdc.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
#define RX_UNREADBUF_SZ_DEFAULT 64 // buffer storing all unread RX data
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
bool initialized;
|
|
||||||
size_t rx_unread_buf_sz;
|
|
||||||
RingbufHandle_t rx_unread_buf;
|
|
||||||
xSemaphoreHandle ringbuf_read_mux;
|
|
||||||
uint8_t *rx_tfbuf;
|
|
||||||
tusb_cdcacm_callback_t callback_rx;
|
|
||||||
tusb_cdcacm_callback_t callback_rx_wanted_char;
|
|
||||||
tusb_cdcacm_callback_t callback_line_state_changed;
|
|
||||||
tusb_cdcacm_callback_t callback_line_coding_changed;
|
|
||||||
} esp_tusb_cdcacm_t; /*!< CDC_AMC object */
|
|
||||||
|
|
||||||
static const char *TAG = "tusb_cdc_acm";
|
|
||||||
|
|
||||||
static inline esp_tusb_cdcacm_t *get_acm(tinyusb_cdcacm_itf_t itf)
|
|
||||||
{
|
|
||||||
esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf);
|
|
||||||
if (cdc_inst == NULL) {
|
|
||||||
return (esp_tusb_cdcacm_t *)NULL;
|
|
||||||
}
|
|
||||||
return (esp_tusb_cdcacm_t *)(cdc_inst->subclass_obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* TinyUSB callbacks
|
|
||||||
********************************************************************* */
|
|
||||||
|
|
||||||
/* Invoked by cdc interface when line state changed e.g connected/disconnected */
|
|
||||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (dtr && rts) { // connected
|
|
||||||
if (acm != NULL) {
|
|
||||||
ESP_LOGV(TAG, "Host connected to CDC no.%d.", itf);
|
|
||||||
} else {
|
|
||||||
ESP_LOGW(TAG, "Host is connected to CDC no.%d, but it is not initialized. Initialize it using `tinyusb_cdc_init`.", itf);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else { // disconnected
|
|
||||||
if (acm != NULL) {
|
|
||||||
ESP_LOGV(TAG, "Serial device is ready to connect to CDC no.%d", itf);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acm) {
|
|
||||||
tusb_cdcacm_callback_t cb = acm->callback_line_state_changed;
|
|
||||||
if (cb) {
|
|
||||||
cdcacm_event_t event = {
|
|
||||||
.type = CDC_EVENT_LINE_STATE_CHANGED,
|
|
||||||
.line_state_changed_data = {
|
|
||||||
.dtr = dtr,
|
|
||||||
.rts = rts
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cb(itf, &event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Invoked when CDC interface received data from host */
|
|
||||||
void tud_cdc_rx_cb(uint8_t itf)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (acm) {
|
|
||||||
if (!acm->rx_unread_buf) {
|
|
||||||
ESP_LOGE(TAG, "There is no RX buffer created");
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tud_cdc_n_read_flush(itf); // we have no place to store data, so just drop it
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while (tud_cdc_n_available(itf)) {
|
|
||||||
int read_res = tud_cdc_n_read( itf,
|
|
||||||
acm->rx_tfbuf,
|
|
||||||
CONFIG_TINYUSB_DFU_CDC_RX_BUFSIZE );
|
|
||||||
int res = xRingbufferSend(acm->rx_unread_buf,
|
|
||||||
acm->rx_tfbuf,
|
|
||||||
read_res, 0);
|
|
||||||
if (res != pdTRUE) {
|
|
||||||
ESP_LOGW(TAG, "The unread buffer is too small, the data has been lost");
|
|
||||||
} else {
|
|
||||||
ESP_LOGV(TAG, "Sent %d bytes to the buffer", read_res);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acm) {
|
|
||||||
tusb_cdcacm_callback_t cb = acm->callback_rx;
|
|
||||||
if (cb) {
|
|
||||||
cdcacm_event_t event = {
|
|
||||||
.type = CDC_EVENT_RX
|
|
||||||
};
|
|
||||||
cb(itf, &event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked when line coding is change via SET_LINE_CODING
|
|
||||||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (acm) {
|
|
||||||
tusb_cdcacm_callback_t cb = acm->callback_line_coding_changed;
|
|
||||||
if (cb) {
|
|
||||||
cdcacm_event_t event = {
|
|
||||||
.type = CDC_EVENT_LINE_CODING_CHANGED,
|
|
||||||
.line_coding_changed_data = {
|
|
||||||
.p_line_coding = p_line_coding,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cb(itf, &event);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoked when received `wanted_char`
|
|
||||||
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (acm) {
|
|
||||||
tusb_cdcacm_callback_t cb = acm->callback_rx_wanted_char;
|
|
||||||
if (cb) {
|
|
||||||
cdcacm_event_t event = {
|
|
||||||
.type = CDC_EVENT_RX_WANTED_CHAR,
|
|
||||||
.rx_wanted_char_data = {
|
|
||||||
.wanted_char = wanted_char,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cb(itf, &event);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf,
|
|
||||||
cdcacm_event_type_t event_type,
|
|
||||||
tusb_cdcacm_callback_t callback)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (acm) {
|
|
||||||
switch (event_type) {
|
|
||||||
case CDC_EVENT_RX:
|
|
||||||
acm->callback_rx = callback;
|
|
||||||
return ESP_OK;
|
|
||||||
case CDC_EVENT_RX_WANTED_CHAR:
|
|
||||||
acm->callback_rx_wanted_char = callback;
|
|
||||||
return ESP_OK;
|
|
||||||
case CDC_EVENT_LINE_STATE_CHANGED:
|
|
||||||
acm->callback_line_state_changed = callback;
|
|
||||||
return ESP_OK;
|
|
||||||
case CDC_EVENT_LINE_CODING_CHANGED:
|
|
||||||
acm->callback_line_coding_changed = callback;
|
|
||||||
return ESP_OK;
|
|
||||||
default:
|
|
||||||
ESP_LOGE(TAG, "Wrong event type");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ESP_LOGE(TAG, "CDC-ACM is not initialized");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf,
|
|
||||||
cdcacm_event_type_t event_type)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (!acm) {
|
|
||||||
ESP_LOGE(TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
switch (event_type) {
|
|
||||||
case CDC_EVENT_RX:
|
|
||||||
acm->callback_rx = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
case CDC_EVENT_RX_WANTED_CHAR:
|
|
||||||
acm->callback_rx_wanted_char = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
case CDC_EVENT_LINE_STATE_CHANGED:
|
|
||||||
acm->callback_line_state_changed = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
case CDC_EVENT_LINE_CODING_CHANGED:
|
|
||||||
acm->callback_line_coding_changed = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
default:
|
|
||||||
ESP_LOGE(TAG, "Wrong event type");
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************** TinyUSB callbacks*/
|
|
||||||
/* CDC-ACM
|
|
||||||
********************************************************************* */
|
|
||||||
|
|
||||||
static esp_err_t read_from_rx_unread_to_buffer(esp_tusb_cdcacm_t *acm, uint8_t *out_buf, size_t req_bytes, size_t *read_bytes)
|
|
||||||
{
|
|
||||||
uint8_t *buf = xRingbufferReceiveUpTo(acm->rx_unread_buf, read_bytes, 0, req_bytes);
|
|
||||||
if (buf) {
|
|
||||||
memcpy(out_buf, buf, *read_bytes);
|
|
||||||
vRingbufferReturnItem(acm->rx_unread_buf, (void *)(buf));
|
|
||||||
return ESP_OK;
|
|
||||||
} else {
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ringbuf_mux_take(esp_tusb_cdcacm_t *acm)
|
|
||||||
{
|
|
||||||
if (xSemaphoreTake(acm->ringbuf_read_mux, 0) != pdTRUE) {
|
|
||||||
ESP_LOGW(TAG, "Read error: ACM is busy");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t ringbuf_mux_give(esp_tusb_cdcacm_t *acm)
|
|
||||||
{
|
|
||||||
BaseType_t ret = xSemaphoreGive(acm->ringbuf_read_mux);
|
|
||||||
assert(ret == pdTRUE);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
ESP_RETURN_ON_FALSE(acm, ESP_ERR_INVALID_STATE, TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
|
|
||||||
size_t read_sz;
|
|
||||||
|
|
||||||
/* Take a mutex to proceed two uninterrupted read operations */
|
|
||||||
ESP_RETURN_ON_ERROR(ringbuf_mux_take(acm), TAG, "ringbuf_mux_take failed");
|
|
||||||
|
|
||||||
esp_err_t res = read_from_rx_unread_to_buffer(acm, out_buf, out_buf_sz, &read_sz);
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed");
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
*rx_data_size = read_sz;
|
|
||||||
/* Buffer's data can be wrapped, at that situations we should make another retrievement */
|
|
||||||
if (read_from_rx_unread_to_buffer(acm, out_buf + read_sz, out_buf_sz - read_sz, &read_sz) == ESP_OK) {
|
|
||||||
*rx_data_size += read_sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch)
|
|
||||||
{
|
|
||||||
if (!get_acm(itf)) { // non-initialized
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return tud_cdc_n_write_char(itf, ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size)
|
|
||||||
{
|
|
||||||
if (!get_acm(itf)) { // non-initialized
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return tud_cdc_n_write(itf, in_buf, in_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t tud_cdc_n_write_occupied(tinyusb_cdcacm_itf_t itf)
|
|
||||||
{
|
|
||||||
return CFG_TUD_CDC_TX_BUFSIZE - tud_cdc_n_write_available(itf);
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks)
|
|
||||||
{
|
|
||||||
if (!get_acm(itf)) { // non-initialized
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!timeout_ticks) { // if no timeout - nonblocking mode
|
|
||||||
int res = tud_cdc_n_write_flush(itf);
|
|
||||||
if (!res) {
|
|
||||||
ESP_LOGW(TAG, "flush failed (res: %d)", res);
|
|
||||||
return ESP_FAIL;
|
|
||||||
} else {
|
|
||||||
if (tud_cdc_n_write_occupied(itf)) {
|
|
||||||
ESP_LOGW(TAG, "remained data to flush!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_ERR_TIMEOUT;
|
|
||||||
} else { // trying during the timeout
|
|
||||||
uint32_t ticks_start = xTaskGetTickCount();
|
|
||||||
uint32_t ticks_now = ticks_start;
|
|
||||||
while (1) { // loop until success or until the time runs out
|
|
||||||
ticks_now = xTaskGetTickCount();
|
|
||||||
if (!tud_cdc_n_write_occupied(itf)) { // if nothing to write - nothing to flush
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (tud_cdc_n_write_flush(itf)) { // Success
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( (ticks_now - ticks_start) > timeout_ticks ) { // Time is up
|
|
||||||
ESP_LOGW(TAG, "Flush failed");
|
|
||||||
return ESP_ERR_TIMEOUT;
|
|
||||||
}
|
|
||||||
vTaskDelay(1);
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t alloc_obj(tinyusb_cdcacm_itf_t itf)
|
|
||||||
{
|
|
||||||
esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf);
|
|
||||||
cdc_inst->subclass_obj = calloc(1, sizeof(esp_tusb_cdcacm_t));
|
|
||||||
if (!cdc_inst->subclass_obj) {
|
|
||||||
return ESP_FAIL;
|
|
||||||
} else {
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void free_obj(tinyusb_cdcacm_itf_t itf)
|
|
||||||
{
|
|
||||||
esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf);
|
|
||||||
free(cdc_inst->subclass_obj);
|
|
||||||
cdc_inst->subclass_obj = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg)
|
|
||||||
{
|
|
||||||
int itf = (int)cfg->cdc_port;
|
|
||||||
/* Creating a CDC object */
|
|
||||||
const tinyusb_config_cdc_t cdc_cfg = {
|
|
||||||
.usb_dev = cfg->usb_dev,
|
|
||||||
.cdc_class = TUSB_CLASS_CDC,
|
|
||||||
.cdc_subclass.comm_subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
|
|
||||||
};
|
|
||||||
ESP_RETURN_ON_ERROR(tinyusb_cdc_init(itf, &cdc_cfg), TAG, "tinyusb_cdc_init failed");
|
|
||||||
ESP_RETURN_ON_ERROR(alloc_obj(itf), TAG, "alloc_obj failed");
|
|
||||||
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
/* Callbacks setting up*/
|
|
||||||
if (cfg->callback_rx) {
|
|
||||||
tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX, cfg->callback_rx);
|
|
||||||
}
|
|
||||||
if (cfg->callback_rx_wanted_char) {
|
|
||||||
tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX_WANTED_CHAR, cfg->callback_rx_wanted_char);
|
|
||||||
}
|
|
||||||
if (cfg->callback_line_state_changed) {
|
|
||||||
tinyusb_cdcacm_register_callback(itf, CDC_EVENT_LINE_STATE_CHANGED, cfg->callback_line_state_changed);
|
|
||||||
}
|
|
||||||
if (cfg->callback_line_coding_changed) {
|
|
||||||
tinyusb_cdcacm_register_callback( itf, CDC_EVENT_LINE_CODING_CHANGED, cfg->callback_line_coding_changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Buffers */
|
|
||||||
|
|
||||||
acm->ringbuf_read_mux = xSemaphoreCreateMutex();
|
|
||||||
if (acm->ringbuf_read_mux == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Creation of a ringbuf mutex failed");
|
|
||||||
free_obj(itf);
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
acm->rx_tfbuf = malloc(CONFIG_TINYUSB_DFU_CDC_RX_BUFSIZE);
|
|
||||||
if (!acm->rx_tfbuf) {
|
|
||||||
ESP_LOGE(TAG, "Creation buffer error");
|
|
||||||
free_obj(itf);
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
}
|
|
||||||
acm->rx_unread_buf_sz = cfg->rx_unread_buf_sz == 0 ? RX_UNREADBUF_SZ_DEFAULT : cfg->rx_unread_buf_sz;
|
|
||||||
acm->rx_unread_buf = xRingbufferCreate(acm->rx_unread_buf_sz, RINGBUF_TYPE_BYTEBUF);
|
|
||||||
if (acm->rx_unread_buf == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Creation buffer error");
|
|
||||||
free_obj(itf);
|
|
||||||
return ESP_ERR_NO_MEM;
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "Comm Initialized buff:%d bytes", cfg->rx_unread_buf_sz);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf)
|
|
||||||
{
|
|
||||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
|
||||||
if (acm) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*********************************************************************** CDC-ACM*/
|
|
|
@ -1,142 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdio_ext.h>
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "cdc.h"
|
|
||||||
#include "tusb_console.h"
|
|
||||||
#include "tinyusb.h"
|
|
||||||
#include "vfs_tinyusb.h"
|
|
||||||
|
|
||||||
#define STRINGIFY(s) STRINGIFY2(s)
|
|
||||||
#define STRINGIFY2(s) #s
|
|
||||||
|
|
||||||
static const char *TAG = "tusb_console";
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
FILE *in;
|
|
||||||
FILE *out;
|
|
||||||
FILE *err;
|
|
||||||
} console_handle_t;
|
|
||||||
|
|
||||||
static console_handle_t con;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Reopen standard streams using a new path
|
|
||||||
*
|
|
||||||
* @param f_in - pointer to a pointer holding a file for in or NULL to don't change stdin
|
|
||||||
* @param f_out - pointer to a pointer holding a file for out or NULL to don't change stdout
|
|
||||||
* @param f_err - pointer to a pointer holding a file for err or NULL to don't change stderr
|
|
||||||
* @param path - mount point
|
|
||||||
* @return esp_err_t ESP_FAIL or ESP_OK
|
|
||||||
*/
|
|
||||||
static esp_err_t redirect_std_streams_to(FILE **f_in, FILE **f_out, FILE **f_err, const char *path)
|
|
||||||
{
|
|
||||||
if (f_in) {
|
|
||||||
*f_in = freopen(path, "r", stdin);
|
|
||||||
if (*f_in == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to reopen in!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (f_out) {
|
|
||||||
*f_out = freopen(path, "w", stdout);
|
|
||||||
if (*f_out == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to reopen out!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (f_err) {
|
|
||||||
*f_err = freopen(path, "w", stderr);
|
|
||||||
if (*f_err == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to reopen err!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Restore output to default
|
|
||||||
*
|
|
||||||
* @param f_in - pointer to a pointer of an in file updated with `redirect_std_streams_to` or NULL to don't change stdin
|
|
||||||
* @param f_out - pointer to a pointer of an out file updated with `redirect_std_streams_to` or NULL to don't change stdout
|
|
||||||
* @param f_err - pointer to a pointer of an err file updated with `redirect_std_streams_to` or NULL to don't change stderr
|
|
||||||
* @return esp_err_t ESP_FAIL or ESP_OK
|
|
||||||
*/
|
|
||||||
static esp_err_t restore_std_streams(FILE **f_in, FILE **f_out, FILE **f_err)
|
|
||||||
{
|
|
||||||
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
|
||||||
if (f_in) {
|
|
||||||
stdin = freopen(default_uart_dev, "r", *f_in);
|
|
||||||
if (stdin == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to reopen stdin!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (f_out) {
|
|
||||||
stdout = freopen(default_uart_dev, "w", *f_out);
|
|
||||||
if (stdout == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to reopen stdout!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (f_err) {
|
|
||||||
stderr = freopen(default_uart_dev, "w", *f_err);
|
|
||||||
if (stderr == NULL) {
|
|
||||||
ESP_LOGE(TAG, "Failed to reopen stderr!");
|
|
||||||
return ESP_FAIL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_tusb_init_console(int cdc_intf)
|
|
||||||
{
|
|
||||||
if (!tinyusb_cdc_initialized(cdc_intf)) {
|
|
||||||
ESP_LOGE(TAG, "Can't init the console because TinyUSB's CDC is not initialized!");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
/* Registering TUSB at VFS */
|
|
||||||
int res = esp_vfs_tusb_cdc_register(cdc_intf, NULL);
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc");
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_tusb_deinit_console(int cdc_intf)
|
|
||||||
{
|
|
||||||
if (!tinyusb_cdc_initialized(cdc_intf)) {
|
|
||||||
ESP_LOGE(TAG, "Can't deinit the console because TinyUSB's CDC is not initialized!");
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int res = restore_std_streams(&con.in, &con.out, &con.err);
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
esp_vfs_tusb_cdc_unregister(NULL);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
|
@ -1,61 +0,0 @@
|
||||||
// Copyright 2022 King Kévin <kingkevin@cuvoodoo.info>
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "esp_err.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_partition.h"
|
|
||||||
#include "esp_ota_ops.h"
|
|
||||||
#include "tusb.h"
|
|
||||||
#include "tusb_dfu_rt.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
static const char *TAG = "tusb_dfu_rt";
|
|
||||||
|
|
||||||
esp_err_t tusb_dfu_rf_init(void)
|
|
||||||
{
|
|
||||||
// verify if factory partition exists
|
|
||||||
const esp_partition_t *factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
|
||||||
if (!factory) {
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
// verify if ota data partition exists
|
|
||||||
const esp_partition_t *otadata = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
|
||||||
if (!otadata) {
|
|
||||||
return ESP_ERR_NOT_FOUND;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TinyUSB callbacks */
|
|
||||||
|
|
||||||
// Invoked on DFU_DETACH request to reboot to the bootloader
|
|
||||||
// WARNING: function linked until public function (e.g. tusb_dfu_rf_init) is called
|
|
||||||
void tud_dfu_runtime_reboot_to_dfu_cb(void)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "reboot");
|
|
||||||
// switch to dfu factory
|
|
||||||
const esp_partition_t *factory = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
|
|
||||||
if (!factory) {
|
|
||||||
ESP_LOGE(TAG, "factory partition not found");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
esp_err_t rc = esp_ota_set_boot_partition(factory);
|
|
||||||
if (ESP_OK != rc) {
|
|
||||||
ESP_LOGE(TAG, "can't set boot to factory");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
esp_restart();
|
|
||||||
}
|
|
|
@ -1,54 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_check.h"
|
|
||||||
#include "tinyusb.h"
|
|
||||||
#include "tusb_tasks.h"
|
|
||||||
|
|
||||||
const static char *TAG = "tusb_tsk";
|
|
||||||
static TaskHandle_t s_tusb_tskh;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief This top level thread processes all usb events and invokes callbacks
|
|
||||||
*/
|
|
||||||
static void tusb_device_task(void *arg)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "tinyusb task started");
|
|
||||||
while (1) { // RTOS forever loop
|
|
||||||
tud_task();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t tusb_run_task(void)
|
|
||||||
{
|
|
||||||
// This function is not garanteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak
|
|
||||||
// doing a sanity check anyway
|
|
||||||
ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started");
|
|
||||||
// Create a task for tinyusb device stack:
|
|
||||||
xTaskCreate(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_DFU_TASK_STACK_SIZE, NULL, CONFIG_TINYUSB_DFU_TASK_PRIORITY, &s_tusb_tskh);
|
|
||||||
ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed");
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t tusb_stop_task(void)
|
|
||||||
{
|
|
||||||
ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet");
|
|
||||||
vTaskDelete(s_tusb_tskh);
|
|
||||||
s_tusb_tskh = NULL;
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
|
@ -1,131 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include "usb_descriptors.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
#define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3))
|
|
||||||
|
|
||||||
/**** TinyUSB default ****/
|
|
||||||
tusb_desc_device_t descriptor_tinyusb = {
|
|
||||||
.bLength = sizeof(descriptor_tinyusb),
|
|
||||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
|
||||||
.bcdUSB = 0x0200,
|
|
||||||
|
|
||||||
#if CFG_TUD_CDC
|
|
||||||
// Use Interface Association Descriptor (IAD) for CDC
|
|
||||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
|
||||||
.bDeviceClass = TUSB_CLASS_MISC,
|
|
||||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
|
||||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
|
||||||
#else
|
|
||||||
.bDeviceClass = 0x00,
|
|
||||||
.bDeviceSubClass = 0x00,
|
|
||||||
.bDeviceProtocol = 0x00,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
|
||||||
|
|
||||||
.idVendor = 0xCafe,
|
|
||||||
.idProduct = USB_TUSB_PID,
|
|
||||||
.bcdDevice = 0x0100,
|
|
||||||
|
|
||||||
.iManufacturer = 0x01,
|
|
||||||
.iProduct = 0x02,
|
|
||||||
.iSerialNumber = 0x03,
|
|
||||||
|
|
||||||
.bNumConfigurations = 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
tusb_desc_strarray_device_t descriptor_str_tinyusb = {
|
|
||||||
// array of pointer to string descriptors
|
|
||||||
(char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
|
|
||||||
"TinyUSB", // 1: Manufacturer
|
|
||||||
"TinyUSB Device", // 2: Product
|
|
||||||
"123456", // 3: Serials, should use chip ID
|
|
||||||
"TinyUSB CDC", // 4: CDC Interface
|
|
||||||
"TinyUSB MSC", // 5: MSC Interface
|
|
||||||
"TinyUSB HID", // 6: HID
|
|
||||||
"TinyUSB DFU RT" // 7: DFU RT
|
|
||||||
};
|
|
||||||
/* End of TinyUSB default */
|
|
||||||
|
|
||||||
/**** Kconfig driven Descriptor ****/
|
|
||||||
tusb_desc_device_t descriptor_kconfig = {
|
|
||||||
.bLength = sizeof(descriptor_kconfig),
|
|
||||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
|
||||||
.bcdUSB = 0x0200,
|
|
||||||
|
|
||||||
#if CFG_TUD_CDC
|
|
||||||
// Use Interface Association Descriptor (IAD) for CDC
|
|
||||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
|
||||||
.bDeviceClass = TUSB_CLASS_MISC,
|
|
||||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
|
||||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
|
||||||
#else
|
|
||||||
.bDeviceClass = 0x00,
|
|
||||||
.bDeviceSubClass = 0x00,
|
|
||||||
.bDeviceProtocol = 0x00,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
|
||||||
|
|
||||||
#if CONFIG_TINYUSB_DFU_DESC_USE_ESPRESSIF_VID
|
|
||||||
.idVendor = USB_ESPRESSIF_VID,
|
|
||||||
#else
|
|
||||||
.idVendor = CONFIG_TINYUSB_DFU_DESC_CUSTOM_VID,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_TINYUSB_DFU_DESC_USE_DEFAULT_PID
|
|
||||||
.idProduct = USB_TUSB_PID,
|
|
||||||
#else
|
|
||||||
.idProduct = CONFIG_TINYUSB_DFU_DESC_CUSTOM_PID,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.bcdDevice = CONFIG_TINYUSB_DFU_DESC_BCD_DEVICE,
|
|
||||||
|
|
||||||
.iManufacturer = 0x01,
|
|
||||||
.iProduct = 0x02,
|
|
||||||
.iSerialNumber = 0x03,
|
|
||||||
|
|
||||||
.bNumConfigurations = 0x01
|
|
||||||
};
|
|
||||||
|
|
||||||
tusb_desc_strarray_device_t descriptor_str_kconfig = {
|
|
||||||
// array of pointer to string descriptors
|
|
||||||
(char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
|
|
||||||
CONFIG_TINYUSB_DFU_DESC_MANUFACTURER_STRING, // 1: Manufacturer
|
|
||||||
CONFIG_TINYUSB_DFU_DESC_PRODUCT_STRING, // 2: Product
|
|
||||||
CONFIG_TINYUSB_DFU_DESC_SERIAL_STRING, // 3: Serials, should use chip ID
|
|
||||||
|
|
||||||
#if CONFIG_TINYUSB_DFU_CDC_ENABLED
|
|
||||||
CONFIG_TINYUSB_DFU_DESC_CDC_STRING, // 4: CDC Interface
|
|
||||||
#else
|
|
||||||
"",
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_TINYUSB_DFU_MSC_ENABLED
|
|
||||||
CONFIG_TINYUSB_DFU_DESC_MSC_STRING, // 5: MSC Interface
|
|
||||||
#else
|
|
||||||
"",
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_TINYUSB_DFU_HID_ENABLED
|
|
||||||
CONFIG_TINYUSB_DFU_DESC_HID_STRING, // 6: HIDs
|
|
||||||
#else
|
|
||||||
"",
|
|
||||||
#endif
|
|
||||||
"DFU (runtime mode)" // 7: DFU RT
|
|
||||||
};
|
|
||||||
/* End of Kconfig driven Descriptor */
|
|
|
@ -1,297 +0,0 @@
|
||||||
// Copyright 2020 Espressif Systems (Shanghai) Co. Ltd.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdio_ext.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/errno.h>
|
|
||||||
#include <sys/fcntl.h>
|
|
||||||
#include <sys/lock.h>
|
|
||||||
#include <sys/param.h>
|
|
||||||
#include "esp_attr.h"
|
|
||||||
#include "esp_log.h"
|
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "esp_vfs_dev.h"
|
|
||||||
#include "tinyusb.h"
|
|
||||||
#include "tusb_cdc_acm.h"
|
|
||||||
#include "vfs_tinyusb.h"
|
|
||||||
#include "sdkconfig.h"
|
|
||||||
|
|
||||||
const static char *TAG = "tusb_vfs";
|
|
||||||
#define VFS_TUSB_MAX_PATH 16
|
|
||||||
#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc"
|
|
||||||
|
|
||||||
// Token signifying that no character is available
|
|
||||||
#define NONE -1
|
|
||||||
|
|
||||||
#define FD_CHECK(fd, ret_val) do { \
|
|
||||||
if ((fd) != 0) { \
|
|
||||||
errno = EBADF; \
|
|
||||||
return (ret_val); \
|
|
||||||
} \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF
|
|
||||||
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CRLF
|
|
||||||
#elif CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR
|
|
||||||
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CR
|
|
||||||
#else
|
|
||||||
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_LF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF
|
|
||||||
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CRLF
|
|
||||||
#elif CONFIG_NEWLIB_STDIN_LINE_ENDING_CR
|
|
||||||
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CR
|
|
||||||
#else
|
|
||||||
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_LF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
_lock_t write_lock;
|
|
||||||
_lock_t read_lock;
|
|
||||||
esp_line_endings_t tx_mode; // Newline conversion mode when transmitting
|
|
||||||
esp_line_endings_t rx_mode; // Newline conversion mode when receiving
|
|
||||||
uint32_t flags;
|
|
||||||
char vfs_path[VFS_TUSB_MAX_PATH];
|
|
||||||
int cdc_intf;
|
|
||||||
} vfs_tinyusb_t;
|
|
||||||
|
|
||||||
static vfs_tinyusb_t s_vfstusb;
|
|
||||||
|
|
||||||
|
|
||||||
static esp_err_t apply_path(char const *path)
|
|
||||||
{
|
|
||||||
if (path != NULL) {
|
|
||||||
size_t path_len = strlen(path) + 1;
|
|
||||||
if (path_len > VFS_TUSB_MAX_PATH) {
|
|
||||||
ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH);
|
|
||||||
return ESP_ERR_INVALID_ARG;
|
|
||||||
}
|
|
||||||
strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1));
|
|
||||||
} else {
|
|
||||||
strncpy(s_vfstusb.vfs_path,
|
|
||||||
VFS_TUSB_PATH_DEFAULT,
|
|
||||||
(VFS_TUSB_MAX_PATH - 1));
|
|
||||||
}
|
|
||||||
ESP_LOGV(TAG, "Path is set to `%s`", s_vfstusb.vfs_path);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Fill s_vfstusb
|
|
||||||
*
|
|
||||||
* @param cdc_intf - interface of tusb for registration
|
|
||||||
* @param path - a path where the CDC will be registered
|
|
||||||
* @return esp_err_t ESP_OK or ESP_ERR_INVALID_ARG
|
|
||||||
*/
|
|
||||||
static esp_err_t vfstusb_init(int cdc_intf, char const *path)
|
|
||||||
{
|
|
||||||
s_vfstusb.cdc_intf = cdc_intf;
|
|
||||||
s_vfstusb.tx_mode = DEFAULT_TX_MODE;
|
|
||||||
s_vfstusb.rx_mode = DEFAULT_RX_MODE;
|
|
||||||
|
|
||||||
return apply_path(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Clear s_vfstusb to default values
|
|
||||||
*/
|
|
||||||
static void vfstusb_deinit(void)
|
|
||||||
{
|
|
||||||
memset(&s_vfstusb, 0, sizeof(s_vfstusb));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int tusb_open(const char *path, int flags, int mode)
|
|
||||||
{
|
|
||||||
(void) mode;
|
|
||||||
(void) path;
|
|
||||||
s_vfstusb.flags = flags | O_NONBLOCK; // for now only non-blocking mode is implemented
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t tusb_write(int fd, const void *data, size_t size)
|
|
||||||
{
|
|
||||||
FD_CHECK(fd, -1);
|
|
||||||
size_t written_sz = 0;
|
|
||||||
const char *data_c = (const char *)data;
|
|
||||||
_lock_acquire(&(s_vfstusb.write_lock));
|
|
||||||
for (size_t i = 0; i < size; i++) {
|
|
||||||
int c = data_c[i];
|
|
||||||
/* handling the EOL */
|
|
||||||
if (c == '\n' && s_vfstusb.tx_mode != ESP_LINE_ENDINGS_LF) {
|
|
||||||
if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, '\r')) {
|
|
||||||
written_sz++;
|
|
||||||
} else {
|
|
||||||
break; // can't write anymore
|
|
||||||
}
|
|
||||||
if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* write a char */
|
|
||||||
if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) {
|
|
||||||
written_sz++;
|
|
||||||
} else {
|
|
||||||
break; // can't write anymore
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
tud_cdc_n_write_flush(s_vfstusb.cdc_intf);
|
|
||||||
_lock_release(&(s_vfstusb.write_lock));
|
|
||||||
return written_sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tusb_close(int fd)
|
|
||||||
{
|
|
||||||
FD_CHECK(fd, -1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t tusb_read(int fd, void *data, size_t size)
|
|
||||||
{
|
|
||||||
FD_CHECK(fd, -1);
|
|
||||||
char *data_c = (char *) data;
|
|
||||||
size_t received = 0;
|
|
||||||
_lock_acquire(&(s_vfstusb.read_lock));
|
|
||||||
int cm1 = NONE;
|
|
||||||
int c = NONE;
|
|
||||||
|
|
||||||
while (received < size) {
|
|
||||||
cm1 = c; // store the old char
|
|
||||||
int c = tud_cdc_n_read_char(0); // get a new one
|
|
||||||
if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) {
|
|
||||||
if (c == '\r') {
|
|
||||||
c = '\n';
|
|
||||||
}
|
|
||||||
} else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) {
|
|
||||||
if ((c == '\n') & (cm1 == '\r')) {
|
|
||||||
--received; // step back
|
|
||||||
c = '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( c == NONE) { // if data ends
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
data_c[received] = (char) c;
|
|
||||||
++received;
|
|
||||||
if (c == '\n') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_lock_release(&(s_vfstusb.read_lock));
|
|
||||||
if (received > 0) {
|
|
||||||
return received;
|
|
||||||
}
|
|
||||||
errno = EWOULDBLOCK;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int tusb_fstat(int fd, struct stat *st)
|
|
||||||
{
|
|
||||||
FD_CHECK(fd, -1);
|
|
||||||
memset(st, 0, sizeof(*st));
|
|
||||||
st->st_mode = S_IFCHR;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tusb_fcntl(int fd, int cmd, int arg)
|
|
||||||
{
|
|
||||||
FD_CHECK(fd, -1);
|
|
||||||
int result = 0;
|
|
||||||
switch (cmd) {
|
|
||||||
case F_GETFL:
|
|
||||||
result = s_vfstusb.flags;
|
|
||||||
break;
|
|
||||||
case F_SETFL:
|
|
||||||
s_vfstusb.flags = arg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
result = -1;
|
|
||||||
errno = ENOSYS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_err_t esp_vfs_tusb_cdc_unregister(char const *path)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "Unregistering TinyUSB driver");
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (path == NULL) { // NULL means using the default path for unregistering: VFS_TUSB_PATH_DEFAULT
|
|
||||||
res = strcmp(s_vfstusb.vfs_path, VFS_TUSB_PATH_DEFAULT);
|
|
||||||
} else {
|
|
||||||
res = strcmp(s_vfstusb.vfs_path, path);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res) {
|
|
||||||
res = ESP_ERR_INVALID_ARG;
|
|
||||||
ESP_LOGE(TAG, "There is no TinyUSB driver registerred to the path '%s' (err: 0x%x)", s_vfstusb.vfs_path, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
res = esp_vfs_unregister(s_vfstusb.vfs_path);
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Can't unregister TinyUSB driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res);
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "Unregistered TinyUSB driver");
|
|
||||||
vfstusb_deinit();
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path)
|
|
||||||
{
|
|
||||||
ESP_LOGD(TAG, "Registering TinyUSB CDC driver");
|
|
||||||
int res;
|
|
||||||
if (!tusb_cdc_acm_initialized(cdc_intf)) {
|
|
||||||
ESP_LOGE(TAG, "TinyUSB CDC#%d is not initialized", cdc_intf);
|
|
||||||
return ESP_ERR_INVALID_STATE;
|
|
||||||
}
|
|
||||||
|
|
||||||
res = vfstusb_init(cdc_intf, path);
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
esp_vfs_t vfs = {
|
|
||||||
.flags = ESP_VFS_FLAG_DEFAULT,
|
|
||||||
.close = &tusb_close,
|
|
||||||
.fcntl = &tusb_fcntl,
|
|
||||||
.fstat = &tusb_fstat,
|
|
||||||
.open = &tusb_open,
|
|
||||||
.read = &tusb_read,
|
|
||||||
.write = &tusb_write,
|
|
||||||
};
|
|
||||||
|
|
||||||
res = esp_vfs_register(s_vfstusb.vfs_path, &vfs, NULL);
|
|
||||||
if (res != ESP_OK) {
|
|
||||||
ESP_LOGE(TAG, "Can't register TinyUSB driver (err: %x)", res);
|
|
||||||
} else {
|
|
||||||
ESP_LOGD(TAG, "TinyUSB CDC registered (%s)", s_vfstusb.vfs_path);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
|
@ -1,22 +0,0 @@
|
||||||
# sdkconfig replacement configurations for deprecated options formatted as
|
|
||||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
|
||||||
CONFIG_USB_ENABLED CONFIG_TINYUSB_DFU
|
|
||||||
CONFIG_USB_DO_NOT_CREATE_TASK CONFIG_TINYUSB_DFU_NO_DEFAULT_TASK
|
|
||||||
CONFIG_USB_TASK_PRIORITY CONFIG_TINYUSB_DFU_TASK_PRIORITY
|
|
||||||
CONFIG_USB_DESC_USE_ESPRESSIF_VID CONFIG_TINYUSB_DFU_DESC_USE_ESPRESSIF_VID
|
|
||||||
CONFIG_USB_DESC_CUSTOM_VID CONFIG_TINYUSB_DFU_DESC_CUSTOM_VID
|
|
||||||
CONFIG_USB_DESC_USE_DEFAULT_PID CONFIG_TINYUSB_DFU_DESC_USE_DEFAULT_PID
|
|
||||||
CONFIG_USB_DESC_CUSTOM_PID CONFIG_TINYUSB_DFU_DESC_CUSTOM_PID
|
|
||||||
CONFIG_USB_DESC_BCDDEVICE CONFIG_TINYUSB_DFU_DESC_BCD_DEVICE
|
|
||||||
CONFIG_USB_DESC_MANUFACTURER_STRING CONFIG_TINYUSB_DFU_DESC_MANUFACTURER_STRING
|
|
||||||
CONFIG_USB_DESC_PRODUCT_STRING CONFIG_TINYUSB_DFU_DESC_PRODUCT_STRING
|
|
||||||
CONFIG_USB_DESC_SERIAL_STRING CONFIG_TINYUSB_DFU_DESC_SERIAL_STRING
|
|
||||||
CONFIG_USB_DESC_CDC_STRING CONFIG_TINYUSB_DFU_DESC_CDC_STRING
|
|
||||||
CONFIG_USB_DESC_MSC_STRING CONFIG_TINYUSB_DFU_DESC_MSC_STRING
|
|
||||||
CONFIG_USB_DESC_HID_STRING CONFIG_TINYUSB_DFU_DESC_HID_STRING
|
|
||||||
CONFIG_USB_MSC_ENABLED CONFIG_TINYUSB_DFU_MSC_ENABLED
|
|
||||||
CONFIG_USB_MSC_BUFSIZE CONFIG_TINYUSB_DFU_MSC_BUFSIZE
|
|
||||||
CONFIG_USB_CDC_ENABLED CONFIG_TINYUSB_DFU_CDC_ENABLED
|
|
||||||
CONFIG_USB_CDC_RX_BUFSIZE CONFIG_TINYUSB_DFU_CDC_RX_BUFSIZE
|
|
||||||
CONFIG_USB_CDC_TX_BUFSIZE CONFIG_TINYUSB_DFU_CDC_TX_BUFSIZE
|
|
||||||
CONFIG_USB_DEBUG_LEVEL CONFIG_TINYUSB_DFU_DEBUG_LEVEL
|
|
Loading…
Reference in New Issue