From 2ddd74fada9b2f272923fce9c3b1926a6e9f5c80 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Fri, 12 Aug 2022 11:06:36 -0700 Subject: [PATCH 01/87] Add MIDI host support to tinyusb --- hw/bsp/rp2040/family.cmake | 1 + src/class/midi/README_midi_host.md | 111 ++++ src/class/midi/midi.h | 19 +- src/class/midi/midi_host.c | 944 +++++++++++++++++++++++++++++ src/class/midi/midi_host.h | 137 +++++ src/host/hcd.h | 2 +- src/host/usbh.c | 11 + src/tusb.h | 4 + 8 files changed, 1226 insertions(+), 3 deletions(-) create mode 100644 src/class/midi/README_midi_host.md create mode 100644 src/class/midi/midi_host.c create mode 100644 src/class/midi/midi_host.h diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index 5dba9dc39..964855c05 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -93,6 +93,7 @@ if (NOT TARGET _rp2040_family_inclusion_marker) ${TOP}/src/class/cdc/cdc_host.c ${TOP}/src/class/hid/hid_host.c ${TOP}/src/class/msc/msc_host.c + ${TOP}/src/class/midi/midi_host.c ${TOP}/src/class/vendor/vendor_host.c ) diff --git a/src/class/midi/README_midi_host.md b/src/class/midi/README_midi_host.md new file mode 100644 index 000000000..9df2249b3 --- /dev/null +++ b/src/class/midi/README_midi_host.md @@ -0,0 +1,111 @@ +# MIDI HOST DRIVER +This README file contains the design notes and limitations of the +MIDI host driver. + +# MAXIMUM NUMBER OF MIDI DEVICES ATTACHED TO HOST +In this version of the driver, only one MIDI device is supported. This +constraint may change in the future. + +# MAXIMUM NUMBER OF ENDPOINTS +Although the USB MIDI 1.0 Class specification allows an arbitrary number +of endpoints, this driver supports at most one USB BULK DATA IN endpoint +and one USB BULK DATA OUT endpoint. Each endpoint can support up to 16 +virtual cables. If a device has multiple IN endpoints or multiple OUT +endpoints, it will fail to enumerate. + +Most USB MIDI devices contain both an IN endpoint and an OUT endpoint, +but not all do. For example, some USB pedals only support an OUT endpoint. +This driver allows that. + +# PUBLIC API +Applications interact with this driver via 8-bit buffers of MIDI messages +formed using the rules for sending bytes on a 5-pin DIN cable per the +original MIDI 1.0 specification. + +To send a message to a device, the Host application composes a sequence +of status and data bytes in a byte array and calls the API function. +The arguments of the function are a pointer to the byte array, the number +of bytes in the array, and the target virtual cable number 0-15. + +When the host driver receives a message from the device, the host driver +will call a callback function that the host application registers. This +callback function contains a pointer to a message buffer, a message length, +and the virtual cable number of the message buffer. One complete bulk IN +endpoint transfer might contain multiple messages targeted to different +virtual cables. + +# SUBCLASS AUDIO CONTROL +A MIDI device does not absolutely need to have an Audio Control Interface, +unless it adheres to the USB Audio Class 2 spec, but many devices +have them even if the devices do not have an audio streaming interface. +Because this driver does not support audio streaming, the descriptor parser +will skip past any audio control interface and audio streaming interface +and open only the MIDI interface. + +An audio streaming host driver can use this driver by passing a pointer +to the MIDI interface descriptor that is found after the audio streaming +interface to the midih_open() function. That is, an audio streaming host +driver would parse the audio control interface descriptor and then the +audio streaming interface and endpoint descriptors. When the next descriptor +pointer points to a MIDI interface descriptor, call midih_open() with that +descriptor pointer. + +# CLASS SPECIFIC INTERFACE AND REQUESTS +The host driver does not make use of the informaton in the class specific +interface descriptors. In the future, a public API could be created to +retrieve the string descriptors for the names of each ELEMENT, +IN JACK and OUT JACK, and how the device describes the connections. + +This driver also does not support class specific requests to control +ELEMENT items, nor does it support non-MIDI Streaming bulk endpoints. + +# MIDI CLASS SPECIFIC DESCRIPTOR TOTAL LENGTH FIELD IGNORED +I have observed at least one keyboard by a leading manufacturer that +sets the wTotalLength field of the Class-Specific MS Interface Header +Descriptor to include the length of the MIDIStreaming Endpoint +Descriptors. This is wrong per my reading of the specification. + +# MESSAGE BUFFER DETAILS +Messages buffers composed from USB data received on the IN endpoint will never contain +running status because USB MIDI 1.0 class does not support that. Messages +buffers to be sent to the device on the OUT endpont may contain running status +(the message might come from a UART data stream from a 5-pin DIN MIDI IN +cable on the host, for example). The driver may in the future correctly compose +4-byte USB MIDI Class packets using the running status if need be. However, +it does not currently do that. Also, use of running status is not a good idea +overall because a single byte error can really mess up the data stream with no +way to recover until the next non-real time status byte is in the message buffer. + +Message buffers to be sent to the device may contain Real time messages +such as MIDI clock. Real time messages may be inserted in the message +byte stream between status and data bytes of another message without disrupting +the running status. However, because MIDI 1.0 class messages are sent +as four byte packets, a real-time message so inserted will be re-ordered +to be sent to the device in a new 4-byte packet immediately before the +interrupted data stream. + +Real time messages the device sends to the host can only appear between +the status byte and data bytes of the message in System Exclusive messages +that are longer than 3 bytes. + +# POORLY FORMED USB MIDI DATA PACKETS FROM THE DEVICE +Some devices do not properly encode the code index number (CIN) for the +MIDI message status byte even though the 3-byte data payload correctly encodes +the MIDI message. This driver looks to the byte after the CIN byte to decide +how many bytes to place in the message buffer. + +Some devices do not properly encode the virtual cable number. If the virtual +cable number in the CIN data byte of the packet is not less than bNumEmbMIDIJack +for that endpoint, then the host driver assumes virtual cable 0 and does not +report an error. + +Some MIDI devices will always send back exactly wMaxPacketSize bytes on +every endpoint even if only one 4-byte packet is required (e.g., NOTE ON). +These devices send packets with 4 packet bytes 0. This driver ignores all +zero packets without reporting an error. + +# ENUMERATION FAILURES +The host may fail to enumerate a device if it has too many endpoints, if it has +if it has a Standard MS Transfer Bulk Data Endpoint Descriptor (not supported), +if it has a poorly formed descriptor, or if the descriptor is too long for +the host to read the whole thing. diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index 74dc41749..ea2cfec75 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -71,8 +71,8 @@ typedef enum MIDI_CIN_SYSEX_END_1BYTE = 5, // SysEx ends with 1 data, or 1 byte system common message MIDI_CIN_SYSEX_END_2BYTE = 6, // SysEx ends with 2 data MIDI_CIN_SYSEX_END_3BYTE = 7, // SysEx ends with 3 data - MIDI_CIN_NOTE_ON = 8, - MIDI_CIN_NOTE_OFF = 9, + MIDI_CIN_NOTE_ON = 9, + MIDI_CIN_NOTE_OFF = 8, MIDI_CIN_POLY_KEYPRESS = 10, MIDI_CIN_CONTROL_CHANGE = 11, MIDI_CIN_PROGRAM_CHANGE = 12, @@ -106,6 +106,11 @@ enum MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, }; +enum +{ + MIDI_MAX_DATA_VAL = 0x7F, +}; + /// MIDI Interface Header Descriptor typedef struct TU_ATTR_PACKED { @@ -201,6 +206,16 @@ typedef struct TU_ATTR_PACKED uint8_t iElement; \ } +// This descriptor follows the standard bulk data endpoint descriptor +typedef struct +{ + uint8_t bLength ; ///< Size of this descriptor in bytes (4+bNumEmbMIDIJack) + uint8_t bDescriptorType ; ///< Descriptor Type, must be CS_ENDPOINT + uint8_t bDescriptorSubType ; ///< Descriptor SubType, must be MS_GENERAL + uint8_t bNumEmbMIDIJack; ; ///< Number of embedded MIDI jacks associated with this endpoint + uint8_t baAssocJackID[]; ; ///< A list of associated jacks +} midi_cs_desc_endpoint_t; + /** @} */ #ifdef __cplusplus diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c new file mode 100644 index 000000000..e482f5265 --- /dev/null +++ b/src/class/midi/midi_host.c @@ -0,0 +1,944 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_MIDI) + +#include "host/usbh.h" +#include "host/usbh_classdriver.h" + +#include "midi_host.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ +#ifndef CFG_TUH_MAX_CABLES + #define CFG_TUH_MAX_CABLES 16 +#endif +#define CFG_TUH_MIDI_RX_BUFSIZE 64 +#define CFG_TUH_MIDI_TX_BUFSIZE 64 +#ifndef CFG_TUH_MIDI_EP_BUFSIZE + #define CFG_TUH_MIDI_EP_BUFSIZE 64 +#endif + +// TODO: refactor to share code with the MIDI Device driver +typedef struct +{ + uint8_t buffer[4]; + uint8_t index; + uint8_t total; +}midi_stream_t; + +typedef struct +{ + uint8_t dev_addr; + uint8_t itf_num; + + uint8_t ep_in; // IN endpoint address + uint8_t ep_out; // OUT endpoint address + uint16_t ep_in_max; // min( CFG_TUH_MIDI_RX_BUFSIZE, wMaxPacketSize of the IN endpoint) + uint16_t ep_out_max; // min( CFG_TUH_MIDI_TX_BUFSIZE, wMaxPacketSize of the OUT endpoint) + + uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value + uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value + + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midi_stream_t stream_write; + midi_stream_t stream_read; + + /*------------- From this point, data is not cleared by bus reset -------------*/ + // Endpoint FIFOs + tu_fifo_t rx_ff; + tu_fifo_t tx_ff; + + + uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; + + #if CFG_FIFO_MUTEX + osal_mutex_def_t rx_ff_mutex; + osal_mutex_def_t tx_ff_mutex; + #endif + + // Endpoint Transfer buffer + CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUH_MIDI_EP_BUFSIZE]; + CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_MIDI_EP_BUFSIZE]; + + bool configured; + +#if CFG_MIDI_HOST_DEVSTRINGS +#define MAX_STRING_INDICES 32 + uint8_t all_string_indices[MAX_STRING_INDICES]; + uint8_t num_string_indices; +#define MAX_IN_JACKS 8 +#define MAX_OUT_JACKS 8 + struct { + uint8_t jack_id; + int8_t jack_type; + uint8_t string_index; + } in_jack_info[MAX_IN_JACKS]; + uint8_t next_in_jack; + struct { + uint8_t jack_id; + uint8_t jack_type; + uint8_t num_source_ids; + uint8_t source_ids[MAX_IN_JACKS/4]; + uint8_t string_index; + } out_jack_info[MAX_OUT_JACKS]; + uint8_t next_out_jack; + uint8_t ep_in_associated_jacks[MAX_OUT_JACKS/2]; + uint8_t ep_out_associated_jacks[MAX_IN_JACKS/2]; +#endif +}midih_interface_t; + +static midih_interface_t _midi_host[CFG_TUH_DEVICE_MAX]; + +static midih_interface_t *get_midi_host(uint8_t dev_addr) +{ + TU_VERIFY(dev_addr >0 && dev_addr <= CFG_TUH_DEVICE_MAX); + return (_midi_host + dev_addr - 1); +} + +//------------- Internal prototypes -------------// +static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi); + +//--------------------------------------------------------------------+ +// USBH API +//--------------------------------------------------------------------+ +void midih_init(void) +{ + tu_memclr(&_midi_host, sizeof(_midi_host)); + // config fifos + for (int inst = 0; inst < CFG_TUH_DEVICE_MAX; inst++) + { + midih_interface_t *p_midi_host = &_midi_host[inst]; + tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false); // true, true + tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false); // OBVS. + + #if CFG_FIFO_MUTEX + tu_fifo_config_mutex(&p_midi_host->rx_ff, NULL, osal_mutex_create(&p_midi_host->rx_ff_mutex)); + tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL); + #endif + } +} + +bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + if ( ep_addr == p_midi_host->ep_in) + { + if (0 == xferred_bytes) + { + return true; // No data to handle + } + + // receive new data if available + uint32_t packets_queued = 0; + if (xferred_bytes) + { + // put in the RX FIFO only non-zero MIDI IN 4-byte packets + uint8_t* buf = p_midi_host->epin_buf; + uint32_t npackets = xferred_bytes / 4; + uint32_t packet_num; + for (packet_num = 0; packet_num < npackets; packet_num++) + { + // some devices send back all zero packets even if there is no data ready + uint32_t packet = (uint32_t)((*buf)<<24) | ((uint32_t)(*(buf+1))<<16) | ((uint32_t)(*(buf+2))<<8) | ((uint32_t)(*(buf+3))); + if (packet != 0) + { + tu_fifo_write_n(&p_midi_host->rx_ff, buf, 4); + ++packets_queued; + TU_LOG3("MIDI RX=%08x\r\n", packet); + } + buf += 4; + } + } + // invoke receive callback if available + if (tuh_midi_rx_cb) + { + tuh_midi_rx_cb(dev_addr, packets_queued); + } + } + else if ( ep_addr == p_midi_host->ep_out ) + { + if (0 == write_flush(dev_addr, p_midi_host)) + { + // If there is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + if ( !tu_fifo_count(&p_midi_host->tx_ff) && xferred_bytes && (0 == (xferred_bytes % p_midi_host->ep_out_max)) ) + { + if ( usbh_edpt_claim(dev_addr, p_midi_host->ep_out) ) + { + TU_ASSERT(usbh_edpt_xfer(dev_addr, p_midi_host->ep_out, XFER_RESULT_SUCCESS, 0)); + } + } + } + if (tuh_midi_tx_cb) + { + tuh_midi_tx_cb(dev_addr); + } + } + + return true; +} + +void midih_close(uint8_t dev_addr) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + if (p_midi_host == NULL) + return; + if (tuh_midi_umount_cb) + tuh_midi_umount_cb(dev_addr, 0); + tu_fifo_clear(&p_midi_host->rx_ff); + tu_fifo_clear(&p_midi_host->tx_ff); + p_midi_host->ep_in = 0; + p_midi_host->ep_in_max = 0; + p_midi_host->ep_out = 0; + p_midi_host->ep_out_max = 0; + p_midi_host->itf_num = 0; + p_midi_host->num_cables_rx = 0; + p_midi_host->num_cables_tx = 0; + p_midi_host->dev_addr = 255; // invalid + p_midi_host->configured = false; + tu_memclr(&p_midi_host->stream_read, sizeof(p_midi_host->stream_read)); + tu_memclr(&p_midi_host->stream_write, sizeof(p_midi_host->stream_write)); +} + +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ +bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +{ + (void) rhport; + + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + + TU_VERIFY(p_midi_host != NULL); + p_midi_host->num_string_indices = 0; + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); + // There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface + uint8_t const *p_desc = (uint8_t const *) desc_itf; + uint16_t len_parsed = 0; + if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) + { + // Keep track of any string descriptor that might be here + if (desc_itf->iInterface != 0) + p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; + // This driver does not support audio streaming. However, if this is the audio control interface + // there might be a MIDI interface following it. Search through every descriptor until a MIDI + // interface is found or the end of the descriptor is found + while (len_parsed < max_len && (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) + { + len_parsed += desc_itf->bLength; + p_desc = tu_desc_next(p_desc); + desc_itf = (tusb_desc_interface_t const *)p_desc; + } + + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); + } + TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); + len_parsed += desc_itf->bLength; + + // Keep track of any string descriptor that might be here + if (desc_itf->iInterface != 0) + p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; + + p_desc = tu_desc_next(p_desc); + TU_LOG1("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); + // Find out if getting the MIDI class specific interface header or an endpoint descriptor + // or a class-specific endpoint descriptor + // Jack descriptors or element descriptors must follow the cs interface header, + // but this driver does not support devices that contain element descriptors + + // assume it is an interface header + midi_desc_header_t const *p_mdh = (midi_desc_header_t const *)p_desc; + TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || + (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || + p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); + + uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descrptor + p_midi_host->itf_num = desc_itf->bInterfaceNumber; + tusb_desc_endpoint_t const* in_desc = NULL; + tusb_desc_endpoint_t const* out_desc = NULL; + while (len_parsed < max_len) + { + TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || + (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || + p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); + + if (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) { + // The USB host doesn't really need this information unless it uses + // the string descriptor for a jack or Element + + // assume it is an input jack + midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *)p_desc; + if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) + { + TU_LOG2("Found MIDI Interface Header\r\b"); + } + else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) + { + // Then it is an in jack. + TU_LOG2("Found in jack\r\n"); +#if CFG_MIDI_HOST_DEVSTRINGS + if (p_midi_host->next_in_jack < MAX_IN_JACKS) + { + p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_id = p_mdij->bJackID; + p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_type = p_mdij->bJackType; + p_midi_host->in_jack_info[p_midi_host->next_in_jack].string_index = p_mdij->iJack; + ++p_midi_host->next_in_jack; + // Keep track of any string descriptor that might be here + if (p_mdij->iJack != 0) + p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdij->iJack; + + } +#endif + } + else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) + { + // then it is an out jack + TU_LOG2("Found out jack\r\n"); +#if CFG_MIDI_HOST_DEVSTRINGS + if (p_midi_host->next_out_jack < MAX_OUT_JACKS) + { + midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *)p_desc; + p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_id = p_mdoj->bJackID; + p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_type = p_mdoj->bJackType; + p_midi_host->out_jack_info[p_midi_host->next_out_jack].num_source_ids = p_mdoj->bNrInputPins; + struct associated_jack_s { + uint8_t id; + uint8_t pin; + } *associated_jack = (struct associated_jack_s *)(p_desc+6); + int jack; + for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) + { + p_midi_host->out_jack_info[p_midi_host->next_out_jack].source_ids[jack] = associated_jack->id; + } + p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc+6+p_mdoj->bNrInputPins*2); + ++p_midi_host->next_out_jack; + if (p_mdoj->iJack != 0) + p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdoj->iJack; + } +#endif + } + else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) + { + // the it is an element; + #if CFG_MIDI_HOST_DEVSTRINGS + TU_LOG1("Found element; strings not supported\r\n"); + #else + TU_LOG2("Found element\r\n"); + #endif + } + else + { + TU_LOG2("Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); + TU_VERIFY(false); // unknown CS Interface sub-type + } + len_parsed += p_mdij->bLength; + } + else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) + { + TU_LOG2("found CS_ENDPOINT Descriptor for %u\r\n", prev_ep_addr); + TU_VERIFY(prev_ep_addr != 0); + // parse out the mapping between the device's embedded jacks and the endpoints + // Each embedded IN jack is assocated with an OUT endpoint + midi_cs_desc_endpoint_t const* p_csep = (midi_cs_desc_endpoint_t const*)p_mdh; + if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) + { + TU_VERIFY(p_midi_host->ep_out == prev_ep_addr); + TU_VERIFY(p_midi_host->num_cables_tx == 0); + p_midi_host->num_cables_tx = p_csep->bNumEmbMIDIJack; +#if CFG_MIDI_HOST_DEVSTRINGS + uint8_t jack; + uint8_t max_jack = p_midi_host->num_cables_tx; + if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) + { + max_jack = sizeof(p_midi_host->ep_out_associated_jacks); + } + for (jack = 0; jack < max_jack; jack++) + { + p_midi_host->ep_out_associated_jacks[jack] = p_csep->baAssocJackID[jack]; + } +#endif + } + else + { + TU_VERIFY(p_midi_host->ep_in == prev_ep_addr); + TU_VERIFY(p_midi_host->num_cables_rx == 0); + p_midi_host->num_cables_rx = p_csep->bNumEmbMIDIJack; +#if CFG_MIDI_HOST_DEVSTRINGS + uint8_t jack; + uint8_t max_jack = p_midi_host->num_cables_rx; + if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) + { + max_jack = sizeof(p_midi_host->ep_in_associated_jacks); + } + for (jack = 0; jack < max_jack; jack++) + { + p_midi_host->ep_in_associated_jacks[jack] = p_csep->baAssocJackID[jack]; + } +#endif + } + len_parsed += p_csep->bLength; + prev_ep_addr = 0; + } + else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { + // parse out the bulk endpoint info + tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *)p_mdh; + TU_LOG2("found ENDPOINT Descriptor for %u\r\n", p_ep->bEndpointAddress); + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) + { + TU_VERIFY(p_midi_host->ep_out == 0); + TU_VERIFY(p_midi_host->num_cables_tx == 0); + p_midi_host->ep_out = p_ep->bEndpointAddress; + p_midi_host->ep_out_max = p_ep->wMaxPacketSize; + if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) + p_midi_host->ep_out_max = CFG_TUH_MIDI_TX_BUFSIZE; + prev_ep_addr = p_midi_host->ep_out; + out_desc = p_ep; + } + else + { + TU_VERIFY(p_midi_host->ep_in == 0); + TU_VERIFY(p_midi_host->num_cables_rx == 0); + p_midi_host->ep_in = p_ep->bEndpointAddress; + p_midi_host->ep_in_max = p_ep->wMaxPacketSize; + if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) + p_midi_host->ep_in_max = CFG_TUH_MIDI_RX_BUFSIZE; + prev_ep_addr = p_midi_host->ep_in; + in_desc = p_ep; + } + len_parsed += p_mdh->bLength; + } + p_desc = tu_desc_next(p_desc); + p_mdh = (midi_desc_header_t const *)p_desc; + } + TU_VERIFY((p_midi_host->ep_out != 0 && p_midi_host->num_cables_tx != 0) || + (p_midi_host->ep_in != 0 && p_midi_host->num_cables_rx != 0)); + TU_LOG1("MIDI descriptor parsed successfully\r\n"); + // remove duplicate string indices + for (int idx=0; idx < p_midi_host->num_string_indices; idx++) { + for (int jdx = idx+1; jdx < p_midi_host->num_string_indices; jdx++) { + while (jdx < p_midi_host->num_string_indices && p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { + // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 + p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices-1]; + --p_midi_host->num_string_indices; + } + } + } + if (in_desc) + { + TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); + // Some devices always return exactly the request length so transfers won't complete + // unless you assume every transfer is the last one. + // TODO usbh_edpt_force_last_buffer(dev_addr, p_midi_host->ep_in, true); + } + if (out_desc) + { + TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); + } + p_midi_host->dev_addr = dev_addr; + + if (tuh_midi_mount_cb) + { + tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); + } + return true; +} + +bool tuh_midi_configured(uint8_t dev_addr) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + return p_midi_host->configured; +} + +bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + (void) itf_num; + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + p_midi_host->configured = true; + + // TODO I don't think there are any special config things to do for MIDI + + return true; +} + +//--------------------------------------------------------------------+ +// Stream API +//--------------------------------------------------------------------+ +static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) +{ + // No data to send + if ( !tu_fifo_count(&midi->tx_ff) ) return 0; + + // skip if previous transfer not complete + TU_VERIFY( usbh_edpt_claim(dev_addr, midi->ep_out) ); + + uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epout_buf, midi->ep_out_max); + + if (count) + { + TU_ASSERT( usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0 ); + return count; + }else + { + // Release endpoint since we don't make any transfer + usbh_edpt_release(dev_addr, midi->ep_out); + return 0; + } +} + +bool tuh_midi_read_poll( uint8_t dev_addr ) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + bool result = false; + + bool in_edpt_not_busy = !usbh_edpt_busy(dev_addr, p_midi_host->ep_in); + if (in_edpt_not_busy) + { + TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in); + TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, _midi_host->epin_buf, _midi_host->ep_in_max), 0); + result = true; + } + else + { + // Maybe the IN endpoint is only busy because the RP2040 host hardware + // is retrying a NAK'd IN transfer forever. Try aborting the NAK'd + // transfer to allow other transfers to happen on the one shared + // epx endpoint. + // TODO for RP2040 USB shared endpoint: usbh_edpt_clear_in_on_nak(p_midi_host->dev_addr, p_midi_host->ep_in); + } + return result; +} + +uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + TU_VERIFY(cable_num < p_midi_host->num_cables_tx); + midi_stream_t *stream = &p_midi_host->stream_write; + + uint32_t i = 0; + while ( (i < bufsize) && (tu_fifo_remaining(&p_midi_host->tx_ff) >= 4) ) + { + uint8_t const data = buffer[i]; + i++; + if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) + { + // real-time messages need to be sent right away + midi_stream_t streamrt; + streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + streamrt.buffer[1] = data; + streamrt.index = 2; + streamrt.total = 2; + uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, streamrt.buffer, 4); + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, i); + } + else if ( stream->index == 0 ) + { + //------------- New event packet -------------// + + uint8_t const msg = data >> 4; + + stream->index = 2; + stream->buffer[1] = data; + + // Check to see if we're still in a SysEx transmit. + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) + { + if ( data == MIDI_STATUS_SYSEX_END ) + { + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; + } + else + { + stream->total = 4; + } + } + else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) + { + // Channel Voice Messages + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 4; + } + else if ( msg == 0xC || msg == 0xD) + { + // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) + stream->buffer[0] = (cable_num << 4) | msg; + stream->total = 3; + } + else if ( msg == 0xf ) + { + // System message + if ( data == MIDI_STATUS_SYSEX_START ) + { + stream->buffer[0] = MIDI_CIN_SYSEX_START; + stream->total = 4; + } + else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) + { + stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; + stream->total = 3; + } + else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) + { + stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; + stream->total = 4; + } + else + { + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; + } + } + else + { + // Pack individual bytes if we don't support packing them into words. + stream->buffer[0] = cable_num << 4 | 0xf; + stream->buffer[2] = 0; + stream->buffer[3] = 0; + stream->index = 2; + stream->total = 2; + } + } + else + { + //------------- On-going (buffering) packet -------------// + + TU_ASSERT(stream->index < 4, i); + stream->buffer[stream->index] = data; + stream->index++; + // See if this byte ends a SysEx. + if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) + { + stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); + stream->total = stream->index; + } + } + + // Send out packet + if ( stream->index >= 2 && stream->index == stream->total ) + { + // zeroes unused bytes + for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; + TU_LOG3_MEM(stream->buffer, 4, 2); + + uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, stream->buffer, 4); + + // complete current event packet, reset stream + stream->index = 0; + stream->total = 0; + + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, i); + } + } + return i; +} + +bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + + if (tu_fifo_remaining(&p_midi_host->tx_ff) < 4) + { + return false; + } + + tu_fifo_write_n(&p_midi_host->tx_ff, packet, 4); + + return true; +} + +uint32_t tuh_midi_stream_flush( uint8_t dev_addr ) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + + uint32_t bytes_flushed = 0; + if (!usbh_edpt_busy(p_midi_host->dev_addr, p_midi_host->ep_out)) + { + bytes_flushed = write_flush(dev_addr, p_midi_host); + } + return bytes_flushed; +} +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ +uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + TU_VERIFY(p_midi_host->ep_out != 0); // returns 0 if fails + return p_midi_host->num_cables_tx; +} + +uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + TU_VERIFY(p_midi_host->ep_in != 0); // returns 0 if fails + return p_midi_host->num_cables_rx; +} + +bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + TU_VERIFY(tu_fifo_count(&p_midi_host->rx_ff) >= 4); + return tu_fifo_read_n(&p_midi_host->rx_ff, packet, 4) == 4; +} + +uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + uint32_t bytes_buffered = 0; + TU_ASSERT(p_cable_num); + TU_ASSERT(p_buffer); + TU_ASSERT(bufsize); + uint8_t one_byte; + if (!tu_fifo_peek(&p_midi_host->rx_ff, &one_byte)) + { + return 0; + } + *p_cable_num = (one_byte >> 4) & 0xf; + uint32_t nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4); + static uint16_t cable_sysex_in_progress; // bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END + while (nread == 4 && bytes_buffered < bufsize) + { + *p_cable_num=(p_midi_host->stream_read.buffer[0] >> 4) & 0x0f; + uint8_t bytes_to_add_to_stream = 0; + if (*p_cable_num < p_midi_host->num_cables_rx) + { + // ignore the CIN field; too many devices out there encode this wrong + uint8_t status = p_midi_host->stream_read.buffer[1]; + uint16_t cable_mask = 1 << *p_cable_num; + if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) + { + if (status == MIDI_STATUS_SYSEX_START) + { + cable_sysex_in_progress |= cable_mask; + } + // only add the packet if a sysex message is in progress + if (cable_sysex_in_progress & cable_mask) + { + ++bytes_to_add_to_stream; + uint8_t idx; + for (idx = 2; idx < 4; idx++) + { + if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL) + { + ++bytes_to_add_to_stream; + } + else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) + { + ++bytes_to_add_to_stream; + cable_sysex_in_progress &= ~cable_mask; + idx = 4; // force the loop to exit; I hate break statements in loops + } + } + } + } + else if (status < MIDI_STATUS_SYSEX_START) + { + // then it is a channel message either three bytes or two + uint8_t fake_cin = (status & 0xf0) >> 4; + switch (fake_cin) + { + case MIDI_CIN_NOTE_OFF: + case MIDI_CIN_NOTE_ON: + case MIDI_CIN_POLY_KEYPRESS: + case MIDI_CIN_CONTROL_CHANGE: + case MIDI_CIN_PITCH_BEND_CHANGE: + bytes_to_add_to_stream = 3; + break; + case MIDI_CIN_PROGRAM_CHANGE: + case MIDI_CIN_CHANNEL_PRESSURE: + bytes_to_add_to_stream = 2; + break; + default: + break; // Should not get this + } + cable_sysex_in_progress &= ~cable_mask; + } + else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) + { + switch (status) + { + case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME: + case MIDI_STATUS_SYSCOM_SONG_SELECT: + bytes_to_add_to_stream = 2; + break; + case MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER: + bytes_to_add_to_stream = 3; + break; + case MIDI_STATUS_SYSCOM_TUNE_REQUEST: + case MIDI_STATUS_SYSEX_END: + bytes_to_add_to_stream = 1; + break; + default: + break; + cable_sysex_in_progress &= ~cable_mask; + } + } + else + { + // Real-time message: can be inserted into a sysex message, + // so do don't clear cable_sysex_in_progress bit + bytes_to_add_to_stream = 1; + } + } + uint8_t idx; + for (idx = 1; idx <= bytes_to_add_to_stream; idx++) + { + *p_buffer++ = p_midi_host->stream_read.buffer[idx]; + } + bytes_buffered += bytes_to_add_to_stream; + nread = 0; + if (tu_fifo_peek(&p_midi_host->rx_ff, &one_byte)) + { + uint8_t new_cable = (one_byte >> 4) & 0xf; + if (new_cable == *p_cable_num) + { + // still on the same cable. Continue reading the stream + nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4); + } + } + } + + return bytes_buffered; +} + +uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + uint8_t num_cables = 0; + if (p_midi_host) + { + num_cables = p_midi_host->num_cables_rx; + } + return num_cables; +} + +uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + uint8_t num_cables = 0; + if (p_midi_host) + { + num_cables = p_midi_host->num_cables_tx; + } + return num_cables; +} + +#if CFG_MIDI_HOST_DEVSTRINGS +static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) +{ + uint8_t index = 0; + uint8_t assoc; + for (assoc = 0; index == 0 && assoc < ptr->next_in_jack; assoc++) + { + if (jack_id == ptr->in_jack_info[assoc].jack_id) + { + index = ptr->in_jack_info[assoc].string_index; + } + } + for (assoc = 0; index == 0 && assoc < ptr->next_out_jack; assoc++) + { + if (jack_id == ptr->out_jack_info[assoc].jack_id) + { + index = ptr->out_jack_info[assoc].string_index; + } + } + return index; +} +#endif + +#if CFG_MIDI_HOST_DEVSTRINGS +uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) +{ + uint8_t nstrings = 0; + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + nstrings = p_midi_host->num_cables_rx; + if (nstrings > max_istrings) + { + nstrings = max_istrings; + } + uint8_t jack; + for (jack=0; jackep_in_associated_jacks[jack]; + istrings[jack] = find_string_index(p_midi_host, jack_id); + } + return nstrings; +} + +uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) +{ + uint8_t nstrings = 0; + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + nstrings = p_midi_host->num_cables_tx; + if (nstrings > max_istrings) + { + nstrings = max_istrings; + } + uint8_t jack; + for (jack=0; jackep_out_associated_jacks[jack]; + istrings[jack] = find_string_index(p_midi_host, jack_id); + } + return nstrings; +} +#endif + +uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings) +{ + midih_interface_t *p_midi_host = get_midi_host(dev_addr); + TU_VERIFY(p_midi_host != NULL); + uint8_t nstrings = p_midi_host->num_string_indices; + if (nstrings) + *istrings = p_midi_host->all_string_indices; + return nstrings; +} +#endif diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h new file mode 100644 index 000000000..fc661939a --- /dev/null +++ b/src/class/midi/midi_host.h @@ -0,0 +1,137 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef _TUSB_MIDI_HOST_H_ +#define _TUSB_MIDI_HOST_H_ + +#include "class/audio/audio.h" +#include "midi.h" + +#ifdef __cplusplus + extern "C" { +#endif + +//--------------------------------------------------------------------+ +// Class Driver Configuration +//--------------------------------------------------------------------+ + +// TODO Highspeed bulk transfer can be up to 512 bytes +#ifndef CFG_TUH_HID_EPIN_BUFSIZE +#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#endif + +#ifndef CFG_TUH_HID_EPOUT_BUFSIZE +#define CFG_TUH_HID_EPOUT_BUFSIZE 64 +#endif + + +//--------------------------------------------------------------------+ +// Application API (Single Interface) +//--------------------------------------------------------------------+ +bool tuh_midi_configured (uint8_t dev_addr); +uint32_t tuh_midi_available (uint8_t dev_addr); + +// return the number of virtual midi cables on the device's OUT endpoint +uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr); + +// return the number of virtual midi cables on the device's IN endpoint +uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr); + +// request available data from the device. tuh_midi_message_received_cb() will +// be called if the device has any data to send. Otherwise, the device will +// respond NAK. This function blocks until the transfer completes or the +// devices sends NAK. +// This function will return false if the hardware is busy. +bool tuh_midi_read_poll( uint8_t dev_addr ); + +// Queue a packet to the device. The application +// must call tuh_midi_stream_flush to actually have the +// data go out. It is up to the application to properly +// format this packet; this function does not check. +// Returns true if the packet was successfully queued. +bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]); + +// Queue a message to the device. The application +// must call tuh_midi_stream_flush to actually have the +// data go out. +uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* p_buffer, uint32_t bufsize); + +// Send any queued packets to the device if the host hardware is able to do it +// Returns the number of bytes flushed to the host hardware or 0 if +// the host hardware is busy or there is nothing in queue to send. +uint32_t tuh_midi_stream_flush( uint8_t dev_addr); + +// Get the MIDI stream from the device. Set the value pointed +// to by p_cable_num to the MIDI cable number intended to receive it. +// The MIDI stream will be stored in the buffer pointed to by p_buffer. +// Return the number of bytes added to the buffer. +// Note that this function ignores the CIN field of the MIDI packet +// because a number of commercial devices out there do not encode +// it properly. +uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); + +// Read a raw MIDI packet from the connected device +// This function does not parse the packet format +// Return true if a packet was returned +bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]); + +uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); +uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr); +#if CFG_MIDI_HOST_DEVSTRINGS +uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); +uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); +uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); +#endif +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +void midih_init (void); +bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); +bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void midih_close (uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// Callbacks (Weak is optional) +//--------------------------------------------------------------------+ + +// Invoked when device with MIDI interface is mounted. +// If the MIDI host application requires MIDI IN, it should requst an +// IN transfer here. The device will likely NAK this transfer. How the driver +// handles the NAK is hardware dependent. +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx); + +// Invoked when device with MIDI interface is un-mounted +// For now, the instance parameter is always 0 and can be ignored +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance); + +TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets); +TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t dev_addr); +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_MIDI_HOST_H_ */ diff --git a/src/host/hcd.h b/src/host/hcd.h index deebc59d4..97b668d79 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -40,7 +40,7 @@ //--------------------------------------------------------------------+ #ifndef CFG_TUH_ENDPOINT_MAX - #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3) + #define CFG_TUH_ENDPOINT_MAX (CFG_TUH_HUB + CFG_TUH_HID*2 + CFG_TUH_MSC*2 + CFG_TUH_CDC*3 + CFG_TUH_MIDI*2) // #ifdef TUP_HCD_ENDPOINT_MAX // #define CFG_TUH_ENDPPOINT_MAX TUP_HCD_ENDPOINT_MAX // #else diff --git a/src/host/usbh.c b/src/host/usbh.c index 9d618db92..c59f31596 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -166,6 +166,17 @@ static usbh_class_driver_t const usbh_class_drivers[] = }, #endif + #if CFG_TUH_MIDI + { + DRIVER_NAME("MIDI") + .init = midih_init, + .open = midih_open, + .set_config = midih_set_config, + .xfer_cb = midih_xfer_cb, + .close = midih_close + }, + #endif + #if CFG_TUH_HUB { DRIVER_NAME("HUB") diff --git a/src/tusb.h b/src/tusb.h index b776d7d01..093c053f7 100644 --- a/src/tusb.h +++ b/src/tusb.h @@ -56,6 +56,10 @@ #include "class/cdc/cdc_host.h" #endif + #if CFG_TUH_MIDI + #include "class/midi/midi_host.h" + #endif + #if CFG_TUH_VENDOR #include "class/vendor/vendor_host.h" #endif From 70eefcb849542f386a1349da7a4944d2d02dcd40 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Thu, 25 Aug 2022 15:08:00 -0700 Subject: [PATCH 02/87] Add hooks to allow cloning an attached USB device descriptor --- src/device/usbd_control.c | 2 +- src/host/usbh.c | 7 +++++-- src/host/usbh.h | 6 +++++- src/tusb_option.h | 6 +++--- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/device/usbd_control.c b/src/device/usbd_control.c index 0995ef669..187547ae3 100644 --- a/src/device/usbd_control.c +++ b/src/device/usbd_control.c @@ -56,7 +56,7 @@ typedef struct static usbd_control_xfer_t _ctrl_xfer; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN -static uint8_t _usbd_ctrl_buf[CFG_TUD_ENDPOINT0_SIZE]; +static uint8_t _usbd_ctrl_buf[/*CFG_TUD_ENDPOINT0_SIZE*/ 64]; //--------------------------------------------------------------------+ // Application API diff --git a/src/host/usbh.c b/src/host/usbh.c index c59f31596..44b4d3217 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1323,7 +1323,7 @@ static void process_enumeration(tuh_xfer_t* xfer) dev->i_product = desc_device->iProduct; dev->i_serial = desc_device->iSerialNumber; - // if (tuh_attach_cb) tuh_attach_cb((tusb_desc_device_t*) _usbh_ctrl_buf); + if (tuh_desc_device_cb) tuh_desc_device_cb(daddr, (tusb_desc_device_t const*) _usbh_ctrl_buf); // Get 9-byte for total length uint8_t const config_idx = CONFIG_NUM - 1; @@ -1350,9 +1350,12 @@ static void process_enumeration(tuh_xfer_t* xfer) break; case ENUM_SET_CONFIG: + // Got the whole configuration descriptor. Make a copy + if (tuh_desc_config_cb) tuh_desc_config_cb(daddr, (const tusb_desc_configuration_t*) _usbh_ctrl_buf); + // Parse configuration & set up drivers // Driver open aren't allowed to make any usb transfer yet - TU_ASSERT( _parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_ctrl_buf), ); + TU_ASSERT( _parse_configuration_descriptor(daddr, (const tusb_desc_configuration_t* ) _usbh_ctrl_buf), ); TU_ASSERT( tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER), ); break; diff --git a/src/host/usbh.h b/src/host/usbh.h index 560a1ea23..7355c83ee 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -78,7 +78,11 @@ enum // APPLICATION CALLBACK //--------------------------------------------------------------------+ -//TU_ATTR_WEAK uint8_t tuh_attach_cb (tusb_desc_device_t const *desc_device); +// Give the application an opportunity to grab the device descriptor +TU_ATTR_WEAK void tuh_desc_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device); + +// Give the application an opportunity to grab the configuration descriptor +TU_ATTR_WEAK void tuh_desc_config_cb(uint8_t daddr, const tusb_desc_configuration_t *desc_config); // Invoked when device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); diff --git a/src/tusb_option.h b/src/tusb_option.h index f95ae6273..b905fc7ce 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -427,9 +427,9 @@ typedef int make_iso_compilers_happy; //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -#if CFG_TUD_ENDPOINT0_SIZE > 64 - #error Control Endpoint Max Packet Size cannot be larger than 64 -#endif +//#if CFG_TUD_ENDPOINT0_SIZE > 64 +// #error Control Endpoint Max Packet Size cannot be larger than 64 +//#endif #endif /* _TUSB_OPTION_H_ */ From 3325e2613d4bc68ac2443445e62520baa4bbe6cb Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Thu, 25 Aug 2022 15:09:27 -0700 Subject: [PATCH 03/87] Make USB MIDI device code allow a device with no Audio Control interface --- src/class/midi/midi_device.c | 26 ++++++++++++++++---------- src/device/usbd.c | 10 +++++++++- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index de41706e8..c6c99db29 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -406,19 +406,25 @@ void midid_reset(uint8_t rhport) uint16_t midid_open(uint8_t rhport, tusb_desc_interface_t const * desc_itf, uint16_t max_len) { + uint16_t drv_len = 0; + uint8_t const * p_desc = (uint8_t const *)desc_itf; // 1st Interface is Audio Control v1 - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0); - - uint16_t drv_len = tu_desc_len(desc_itf); - uint8_t const * p_desc = tu_desc_next(desc_itf); - - // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { - drv_len += tu_desc_len(p_desc); - p_desc = tu_desc_next(p_desc); + drv_len = tu_desc_len(desc_itf); + p_desc = tu_desc_next(desc_itf); + // Skip Class Specific descriptors + while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) + { + drv_len += tu_desc_len(p_desc); + p_desc = tu_desc_next(p_desc); + } + } + else + { + TU_LOG1("Warning: MIDI Device has no Audio Control Interface"); } // 2nd Interface is MIDI Streaming diff --git a/src/device/usbd.c b/src/device/usbd.c index c199e647e..1cede1289 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -920,7 +920,15 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) #endif #if CFG_TUD_MIDI - if ( driver->open == midid_open ) assoc_itf_count = 2; + if ( driver->open == midid_open ) + { + // If there is a class-compliant Audio Control Class, then 2 interfaces + // Otherwise, only one + if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) + assoc_itf_count = 2; + } #endif #if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT From 4fbf99621d5a5b8b5de698a792578a2066c667f3 Mon Sep 17 00:00:00 2001 From: atok Date: Thu, 8 Sep 2022 17:51:01 +0200 Subject: [PATCH 04/87] Get rid of implicit uint conversions --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index e482f5265..a6ad1303a 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -100,7 +100,7 @@ typedef struct #define MAX_OUT_JACKS 8 struct { uint8_t jack_id; - int8_t jack_type; + uint8_t jack_type; uint8_t string_index; } in_jack_info[MAX_IN_JACKS]; uint8_t next_in_jack; From 19563b441463aed9b3d622f2d57d61082199fbdd Mon Sep 17 00:00:00 2001 From: atok Date: Thu, 8 Sep 2022 21:13:55 +0200 Subject: [PATCH 05/87] Simple MIDI rx example --- examples/host/CMakeLists.txt | 1 + examples/host/midi_rx/CMakeLists.txt | 27 +++++ examples/host/midi_rx/only.txt | 1 + examples/host/midi_rx/src/main.c | 152 ++++++++++++++++++++++++ examples/host/midi_rx/src/tusb_config.h | 96 +++++++++++++++ src/class/midi/midi_host.c | 4 +- 6 files changed, 279 insertions(+), 2 deletions(-) create mode 100644 examples/host/midi_rx/CMakeLists.txt create mode 100644 examples/host/midi_rx/only.txt create mode 100644 examples/host/midi_rx/src/main.c create mode 100644 examples/host/midi_rx/src/tusb_config.h diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt index 5c63ec0c0..39a41c4ae 100644 --- a/examples/host/CMakeLists.txt +++ b/examples/host/CMakeLists.txt @@ -8,3 +8,4 @@ family_initialize_project(tinyusb_host_examples ${CMAKE_CURRENT_LIST_DIR}) # family_add_subdirectory will filter what to actually add based on selected FAMILY family_add_subdirectory(cdc_msc_hid) family_add_subdirectory(hid_controller) +family_add_subdirectory(midi_rx) \ No newline at end of file diff --git a/examples/host/midi_rx/CMakeLists.txt b/examples/host/midi_rx/CMakeLists.txt new file mode 100644 index 000000000..4856e0a47 --- /dev/null +++ b/examples/host/midi_rx/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.5) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) + +# gets PROJECT name for the example (e.g. -) +family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) + +project(${PROJECT}) + +# Checks this example is valid for the family and initializes the project +family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(${PROJECT}) + +# Example source +target_sources(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ) + +# Example include +target_include_directories(${PROJECT} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) + +# Configure compilation flags and libraries for the example... see the corresponding function +# in hw/bsp/FAMILY/family.cmake for details. +family_configure_host_example(${PROJECT}) \ No newline at end of file diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt new file mode 100644 index 000000000..2ba4438fd --- /dev/null +++ b/examples/host/midi_rx/only.txt @@ -0,0 +1 @@ +mcu:RP2040 diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c new file mode 100644 index 000000000..64428932f --- /dev/null +++ b/examples/host/midi_rx/src/main.c @@ -0,0 +1,152 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" +#include "class/midi/midi_host.h" + + +#if CFG_TUH_MIDI + +//--------------------------------------------------------------------+ +// STATIC GLOBALS DECLARATION +//--------------------------------------------------------------------+ +static uint8_t midi_dev_addr = 0; + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ +void led_blinking_task(void); +void midi_host_rx_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + printf("TinyUSB Host MIDI Example\r\n"); + + tusb_init(); + + while (1) + { + tuh_task(); + led_blinking_task(); + midi_host_rx_task(); + } + + return 0; +} + +#endif + +//--------------------------------------------------------------------+ +// Blinking Task +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + const uint32_t interval_ms = 1000; + static uint32_t start_ms = 0; + + static bool led_state = false; + + // Blink every interval ms + if ( board_millis() - start_ms < interval_ms) return; // not enough time + start_ms += interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} + +//--------------------------------------------------------------------+ +// MIDI host receive task +//--------------------------------------------------------------------+ +void midi_host_rx_task(void) +{ + // device must be attached and have at least one endpoint ready to receive a message + if (!midi_dev_addr || !tuh_midi_configured(midi_dev_addr)) + { + return; + } + if (tuh_midih_get_num_rx_cables(midi_dev_addr) < 1) + { + return; + } + tuh_midi_read_poll(midi_dev_addr); +} + +//--------------------------------------------------------------------+ +// TinyUSB Callbacks +//--------------------------------------------------------------------+ + +// Invoked when device with hid interface is mounted +// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() +// can be used to parse common/simple enough descriptor. +// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped +// therefore report_desc = NULL, desc_len = 0 +void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) +{ + TU_LOG1("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", + dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); + + midi_dev_addr = dev_addr; +} + +// Invoked when device with hid interface is un-mounted +void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) +{ + TU_LOG1("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); + + midi_dev_addr = 0; +} + +void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) +{ + if (midi_dev_addr != dev_addr) + { + return; + } + + if(num_packets == 0) + { + return; + } + + uint8_t cable_num; + uint8_t buffer[48]; + uint32_t bytes_read = tuh_midi_stream_read(dev_addr, &cable_num, buffer, sizeof(buffer)); + + TU_LOG1("Read bytes %u cable %u", bytes_read, cable_num); + TU_LOG1_MEM(buffer, bytes_read, 2); +} + +void tuh_midi_tx_cb(uint8_t dev_addr) +{ + (void ) dev_addr; +} \ No newline at end of file diff --git a/examples/host/midi_rx/src/tusb_config.h b/examples/host/midi_rx/src/tusb_config.h new file mode 100644 index 000000000..5cc354ea9 --- /dev/null +++ b/examples/host/midi_rx/src/tusb_config.h @@ -0,0 +1,96 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU +#error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST +#endif + +#ifndef CFG_TUSB_OS +#define CFG_TUSB_OS OPT_OS_NONE +#endif + +// CFG_TUSB_DEBUG is defined by compiler in DEBUG build +// #define CFG_TUSB_DEBUG 0 + +/* 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 __attribute__ ((aligned(4))) +#endif + +//-------------------------------------------------------------------- +// CONFIGURATION +//-------------------------------------------------------------------- + +// Size of buffer to hold descriptors and other data used for enumeration +#define CFG_TUH_ENUMERATION_BUFSIZE 256 + +#define CFG_TUH_HUB 1 +#define CFG_TUH_CDC 0 +#define CFG_TUH_HID 0 // typical keyboard + mouse device can have 3-4 HID interfaces +#define CFG_TUH_MIDI 1 // there will be at most one MIDIStreaming Interface descriptor +#define CFG_TUH_MSC 0 +#define CFG_TUH_VENDOR 0 + +// max device support (excluding hub device) +#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports +#define CFG_MIDI_HOST_DEVSTRINGS 1 + +//------------- HID -------------// +#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#define CFG_TUH_HID_EPOUT_BUFSIZE 64 + +#ifdef __cplusplus +} +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index a6ad1303a..aafa340cd 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -333,10 +333,10 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_id = p_mdoj->bJackID; p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_type = p_mdoj->bJackType; p_midi_host->out_jack_info[p_midi_host->next_out_jack].num_source_ids = p_mdoj->bNrInputPins; - struct associated_jack_s { + const struct associated_jack_s { uint8_t id; uint8_t pin; - } *associated_jack = (struct associated_jack_s *)(p_desc+6); + } *associated_jack = (const struct associated_jack_s *)(p_desc+6); int jack; for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) { From 81de7f3d23ed148a661264e88e10b3bb7c1c0473 Mon Sep 17 00:00:00 2001 From: atok Date: Sun, 11 Sep 2022 18:17:22 +0200 Subject: [PATCH 06/87] Add Makefile for the midi host example --- examples/host/midi_rx/Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 examples/host/midi_rx/Makefile diff --git a/examples/host/midi_rx/Makefile b/examples/host/midi_rx/Makefile new file mode 100644 index 000000000..f830617ac --- /dev/null +++ b/examples/host/midi_rx/Makefile @@ -0,0 +1,9 @@ +include ../../../tools/top.mk +include ../../make.mk +INC += \ + src \ + $(TOP)/hw \ +# Example source +EXAMPLE_SOURCE += $(wildcard src/*.c) +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) +include ../../rules.mk \ No newline at end of file From 0763bc59794f8d8b4850399a89766e44ddcb742b Mon Sep 17 00:00:00 2001 From: atok Date: Sun, 11 Sep 2022 18:18:10 +0200 Subject: [PATCH 07/87] Fix printf statement --- examples/host/midi_rx/src/main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 64428932f..c12df33f2 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -122,7 +122,6 @@ void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { TU_LOG1("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); - midi_dev_addr = 0; } @@ -142,7 +141,7 @@ void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) uint8_t buffer[48]; uint32_t bytes_read = tuh_midi_stream_read(dev_addr, &cable_num, buffer, sizeof(buffer)); - TU_LOG1("Read bytes %u cable %u", bytes_read, cable_num); + TU_LOG1("Read bytes %lu cable %u", bytes_read, cable_num); TU_LOG1_MEM(buffer, bytes_read, 2); } From c14e3e25019b0487f84125b42f682c7dae484578 Mon Sep 17 00:00:00 2001 From: atok Date: Sun, 11 Sep 2022 18:33:43 +0200 Subject: [PATCH 08/87] Fix unused errors when LOG=0 --- examples/host/midi_rx/src/main.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index c12df33f2..6fe17255a 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -112,6 +112,11 @@ void midi_host_rx_task(void) // therefore report_desc = NULL, desc_len = 0 void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) { + (void ) in_ep; + (void ) out_ep; + (void ) num_cables_rx; + (void ) num_cables_tx; + TU_LOG1("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); @@ -121,6 +126,9 @@ void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t // Invoked when device with hid interface is un-mounted void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { + (void ) dev_addr; + (void ) instance; + TU_LOG1("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); midi_dev_addr = 0; } @@ -140,6 +148,7 @@ void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) uint8_t cable_num; uint8_t buffer[48]; uint32_t bytes_read = tuh_midi_stream_read(dev_addr, &cable_num, buffer, sizeof(buffer)); + (void ) bytes_read; TU_LOG1("Read bytes %lu cable %u", bytes_read, cable_num); TU_LOG1_MEM(buffer, bytes_read, 2); From a6d4b64beccc586d1bfb6e4c171d560762221645 Mon Sep 17 00:00:00 2001 From: atok Date: Sun, 2 Oct 2022 09:53:37 +0200 Subject: [PATCH 09/87] Removed unused function prototype --- src/class/midi/midi_host.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index fc661939a..8180e3309 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -52,7 +52,6 @@ // Application API (Single Interface) //--------------------------------------------------------------------+ bool tuh_midi_configured (uint8_t dev_addr); -uint32_t tuh_midi_available (uint8_t dev_addr); // return the number of virtual midi cables on the device's OUT endpoint uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr); From 21e003af2234b3211fb9b4da42202c79949e4caa Mon Sep 17 00:00:00 2001 From: atoktoto Date: Sun, 13 Nov 2022 14:38:33 +0100 Subject: [PATCH 10/87] Added explicit conversions --- src/class/midi/midi_host.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index aafa340cd..d242d33c5 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -592,13 +592,13 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) { // Channel Voice Messages - stream->buffer[0] = (cable_num << 4) | msg; + stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); stream->total = 4; } else if ( msg == 0xC || msg == 0xD) { // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (cable_num << 4) | msg; + stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); stream->total = 3; } else if ( msg == 0xf ) @@ -628,7 +628,7 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con else { // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = cable_num << 4 | 0xf; + stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); stream->buffer[2] = 0; stream->buffer[3] = 0; stream->index = 2; @@ -748,7 +748,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * { // ignore the CIN field; too many devices out there encode this wrong uint8_t status = p_midi_host->stream_read.buffer[1]; - uint16_t cable_mask = 1 << *p_cable_num; + uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) { if (status == MIDI_STATUS_SYSEX_START) From 0a844f2a3019df04a346232b0e54a9fc89e4c551 Mon Sep 17 00:00:00 2001 From: atoktoto Date: Sat, 19 Nov 2022 18:08:31 +0100 Subject: [PATCH 11/87] Fix usb hubs --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index d242d33c5..bc87898cc 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -490,7 +490,7 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) p_midi_host->configured = true; // TODO I don't think there are any special config things to do for MIDI - + usbh_driver_set_config_complete(dev_addr, p_midi_host->itf_num); return true; } From 34729b1dc46ef9cee3446e22c88e8484395f1fa7 Mon Sep 17 00:00:00 2001 From: atoktoto Date: Mon, 21 Nov 2022 10:29:26 +0100 Subject: [PATCH 12/87] Fix usb-hub data transfer problems by AndrewCapon --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index bc87898cc..8df1b2005 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -529,7 +529,7 @@ bool tuh_midi_read_poll( uint8_t dev_addr ) if (in_edpt_not_busy) { TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in); - TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, _midi_host->epin_buf, _midi_host->ep_in_max), 0); + TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, p_midi_host->epin_buf, p_midi_host->ep_in_max), 0); result = true; } else From 3ba03110782747dead880f334f4fd65c03cbca9d Mon Sep 17 00:00:00 2001 From: atoktoto Date: Mon, 21 Nov 2022 12:36:50 +0100 Subject: [PATCH 13/87] Explicit type conversion --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 8df1b2005..308120ea2 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -769,7 +769,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) { ++bytes_to_add_to_stream; - cable_sysex_in_progress &= ~cable_mask; + cable_sysex_in_progress &= (uint16_t) ~cable_mask; idx = 4; // force the loop to exit; I hate break statements in loops } } From 89eac75085134d570dc26dffaf3d8f204aef5359 Mon Sep 17 00:00:00 2001 From: atoktoto Date: Mon, 21 Nov 2022 13:49:43 +0100 Subject: [PATCH 14/87] Explicit type conversion --- src/class/midi/midi_host.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 308120ea2..32311556e 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -795,7 +795,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * default: break; // Should not get this } - cable_sysex_in_progress &= ~cable_mask; + cable_sysex_in_progress &= (uint16_t)~cable_mask; } else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) { @@ -814,7 +814,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * break; default: break; - cable_sysex_in_progress &= ~cable_mask; + cable_sysex_in_progress &= (uint16_t)~cable_mask; } } else From 15b1623aa3b677100cb7e81bf05f0c3b481d355b Mon Sep 17 00:00:00 2001 From: Jay <33371449+jay94ks@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:03:37 +0900 Subject: [PATCH 15/87] add hid stylus pen device. this works with android, for bypassing that absmouse does not support android. note that, to hide cursor on android for every touch signal, find cursor option in android settings menu. references: 1. https://stackoverflow.com/questions/28536602/hid-digitizer-descriptor-doesnt-perform-well-with-landscape-orientation 2. https://github.com/jonathanedgecombe/absmouse/blob/master/src/AbsMouse.cpp --- examples/device/hid_composite/src/main.c | 34 ++++++++++++++- .../hid_composite/src/usb_descriptors.c | 1 + .../hid_composite/src/usb_descriptors.h | 1 + src/class/hid/hid.h | 34 +++++++++++++++ src/class/hid/hid_device.c | 10 +++++ src/class/hid/hid_device.h | 42 +++++++++++++++++++ 6 files changed, 121 insertions(+), 1 deletion(-) diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 5302af3b8..958d8f4af 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -197,11 +197,43 @@ static void send_hid_report(uint8_t report_id, uint32_t btn) } } break; - default: break; } } +/* use this to send stylus touch signal through USB. */ +static void send_stylus_touch(uint16_t x, uint16_t y, bool state) +{ + // skip if hid is not ready yet + if ( !tud_hid_ready() ) return; + + static bool has_stylus_pen = false; + + hid_stylus_report_t report = + { + .attr = 0, + .x = 0, + .y = 0 + }; + + report.x = x; + report.y = y; + + if (state) + { + report.attr = STYLUS_ATTR_TIP_SWITCH | STYLUS_ATTR_IN_RANGE; + tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + + has_stylus_pen = true; + }else + { + report.attr = 0; + if (has_stylus_pen) tud_hid_report(REPORT_ID_STYLUS_PEN, &report, sizeof(report)); + has_stylus_pen = false; + } + +} + // Every 10ms, we will sent 1 report for each HID profile (keyboard, mouse etc ..) // tud_hid_report_complete_cb() is used to send the next report after previous one is complete void hid_task(void) diff --git a/examples/device/hid_composite/src/usb_descriptors.c b/examples/device/hid_composite/src/usb_descriptors.c index e174db46d..15c6e1f73 100644 --- a/examples/device/hid_composite/src/usb_descriptors.c +++ b/examples/device/hid_composite/src/usb_descriptors.c @@ -79,6 +79,7 @@ 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 )), + TUD_HID_REPORT_DESC_STYLUS_PEN( HID_REPORT_ID(REPORT_ID_STYLUS_PEN )), TUD_HID_REPORT_DESC_CONSUMER( HID_REPORT_ID(REPORT_ID_CONSUMER_CONTROL )), TUD_HID_REPORT_DESC_GAMEPAD ( HID_REPORT_ID(REPORT_ID_GAMEPAD )) }; diff --git a/examples/device/hid_composite/src/usb_descriptors.h b/examples/device/hid_composite/src/usb_descriptors.h index e733d31dd..18d31172b 100644 --- a/examples/device/hid_composite/src/usb_descriptors.h +++ b/examples/device/hid_composite/src/usb_descriptors.h @@ -29,6 +29,7 @@ enum { REPORT_ID_KEYBOARD = 1, REPORT_ID_MOUSE, + REPORT_ID_STYLUS_PEN, REPORT_ID_CONSUMER_CONTROL, REPORT_ID_GAMEPAD, REPORT_ID_COUNT diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index db9a500ee..fb27c0d0e 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -325,6 +325,29 @@ typedef enum /// @} +//--------------------------------------------------------------------+ +// Digitizer Stylus Pen +//--------------------------------------------------------------------+ +/** \addtogroup ClassDriver_HID_Stylus Stylus + * @{ */ + +// Standard Stylus Pen Report. +typedef struct TU_ATTR_PACKED +{ + uint8_t attr; /**< Attribute mask for describing current status of the stylus pen. */ + uint16_t x; /**< Current x position of the mouse. */ + uint16_t y; /**< Current y position of the mouse. */ +} hid_stylus_report_t; + +// Standard Stylus Pen Attributes Bitmap. +typedef enum +{ + STYLUS_ATTR_TIP_SWITCH = TU_BIT(0), ///< Tip switch + STYLUS_ATTR_IN_RANGE = TU_BIT(1), ///< In-range bit. +} hid_stylus_attr_bm_t; + +/// @} + //--------------------------------------------------------------------+ // Keyboard //--------------------------------------------------------------------+ @@ -760,7 +783,9 @@ enum { HID_USAGE_PAGE_PID = 0x0f, HID_USAGE_PAGE_UNICODE = 0x10, HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, + HID_USAGE_PAGE_IN_RANGE = 0x32, HID_USAGE_PAGE_MEDICAL = 0x40, + HID_USAGE_PAGE_TIP_SWITCH = 0x42, HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59, HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83 HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 @@ -846,6 +871,15 @@ enum { HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 }; +/// HID Usage Table: Digitizer Page (0x0D) +enum { + // Touch Screen. + HID_USAGE_DIGITIZER_TOUCH_SCREEN = 0x04, + + // Stylus Pen. + HID_USAGE_DIGITIZER_STYLUS = 0x20, +}; + /// HID Usage Table: Consumer Page (0x0C) /// Only contains controls that supported by Windows (whole list is too long) diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index eedcba984..b4f24902b 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -194,6 +194,16 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, return tud_hid_n_report(instance, report_id, &report, sizeof(report)); } +bool tud_hid_n_stylus_report(uint8_t instance, uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y) { + hid_stylus_report_t report = { + .attr = attrs, + .x = x, + .y = y, + }; + + return tud_hid_n_report(instance, report_id, &report, sizeof(report)); +} + //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index ab2e27373..513d6e996 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -79,6 +79,9 @@ bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t but // use template layout report TUD_HID_REPORT_DESC_GAMEPAD bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); +// STYLUS PEN: convenient helper to send absolute stylus pen report if application +bool tud_hid_n_stylus_report(uint8_t instance, uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y); + //--------------------------------------------------------------------+ // Application API (Single Port) //--------------------------------------------------------------------+ @@ -114,6 +117,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_gamepad_report(uint8_t report_i return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons); } +TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_stylus_report(uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y) { + return tud_hid_n_stylus_report(0, report_id, attrs, x, y); +} + //--------------------------------------------------------------------+ // Application Callbacks //--------------------------------------------------------------------+ @@ -257,6 +264,41 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u HID_COLLECTION_END , \ HID_COLLECTION_END \ +// Stylus Pen Report Descriptor Template +#define TUD_HID_REPORT_DESC_STYLUS_PEN(...) \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DIGITIZER ) , \ + HID_USAGE ( HID_USAGE_DIGITIZER_TOUCH_SCREEN ) , \ + HID_COLLECTION ( HID_COLLECTION_APPLICATION ) , \ + /* Report ID if any */\ + __VA_ARGS__ \ + HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ) , \ + HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) , \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_TIP_SWITCH ) , \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_IN_RANGE ) , \ + HID_LOGICAL_MIN ( 0 ), \ + HID_LOGICAL_MAX ( 1 ), \ + HID_REPORT_SIZE ( 1 ), \ + HID_REPORT_COUNT( 2 ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \ + HID_REPORT_SIZE ( 1 ), \ + HID_REPORT_COUNT( 6 ), \ + HID_INPUT ( HID_CONSTANT | HID_ARRAY | HID_ABSOLUTE), \ + HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ), \ + HID_PHYSICAL_MAX( 0x7fff ), \ + HID_LOGICAL_MAX ( 0x7fff ), \ + HID_REPORT_SIZE ( 16 ), \ + HID_REPORT_COUNT( 1 ), \ + HID_UNIT_EXPONENT( -1 ), \ + HID_UNIT ( HID_VARIABLE | HID_NONLINEAR ), \ + HID_PHYSICAL_MIN( 0 ), \ + HID_PHYSICAL_MAX( 0 ), \ + HID_USAGE ( HID_USAGE_DESKTOP_X ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \ + HID_USAGE ( HID_USAGE_DESKTOP_Y ), \ + HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \ + HID_COLLECTION_END , \ + HID_COLLECTION_END \ + // Absolute Mouse Report Descriptor Template #define TUD_HID_REPORT_DESC_ABSMOUSE(...) \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\ From 7e59b595f43c906e4bf207861762bf93e772d4f8 Mon Sep 17 00:00:00 2001 From: Jay <33371449+jay94ks@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:09:59 +0900 Subject: [PATCH 16/87] Update hid_device.h --- src/class/hid/hid_device.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 513d6e996..79b8a695e 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -284,8 +284,8 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u HID_REPORT_COUNT( 6 ), \ HID_INPUT ( HID_CONSTANT | HID_ARRAY | HID_ABSOLUTE), \ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ), \ - HID_PHYSICAL_MAX( 0x7fff ), \ - HID_LOGICAL_MAX ( 0x7fff ), \ + HID_PHYSICAL_MAX_N( 0x7fff, 2 ), \ + HID_LOGICAL_MAX_N ( 0x7fff, 2 ), \ HID_REPORT_SIZE ( 16 ), \ HID_REPORT_COUNT( 1 ), \ HID_UNIT_EXPONENT( -1 ), \ From b029c940356de3645fc224e429d9ec59acf62606 Mon Sep 17 00:00:00 2001 From: Jay <33371449+jay94ks@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:15:01 +0900 Subject: [PATCH 17/87] Modified example app. --- examples/device/hid_composite/src/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index 958d8f4af..bc12d2a93 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -241,6 +241,14 @@ void hid_task(void) // Poll every 10ms const uint32_t interval_ms = 10; static uint32_t start_ms = 0; + static uint32_t touch_ms = 0; + static bool touch_state = false; + + if (board_millis() - touch_ms < 100) { + touch_ms = board_millis(); + send_stylus_touch(0, 0, touch_state = !touch_state); + return; + } if ( board_millis() - start_ms < interval_ms) return; // not enough time start_ms += interval_ms; From eb1c2b83ef09e87964d1d801c3b78caf924af63b Mon Sep 17 00:00:00 2001 From: Jay <33371449+jay94ks@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:19:35 +0900 Subject: [PATCH 18/87] trimed trailing whitespaces. --- examples/device/hid_composite/src/main.c | 2 +- src/class/hid/hid.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/device/hid_composite/src/main.c b/examples/device/hid_composite/src/main.c index bc12d2a93..a58107b6f 100644 --- a/examples/device/hid_composite/src/main.c +++ b/examples/device/hid_composite/src/main.c @@ -209,7 +209,7 @@ static void send_stylus_touch(uint16_t x, uint16_t y, bool state) static bool has_stylus_pen = false; - hid_stylus_report_t report = + hid_stylus_report_t report = { .attr = 0, .x = 0, diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index fb27c0d0e..b179fc72a 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -340,7 +340,7 @@ typedef struct TU_ATTR_PACKED } hid_stylus_report_t; // Standard Stylus Pen Attributes Bitmap. -typedef enum +typedef enum { STYLUS_ATTR_TIP_SWITCH = TU_BIT(0), ///< Tip switch STYLUS_ATTR_IN_RANGE = TU_BIT(1), ///< In-range bit. From 5c4e4b1bc273b771411660e1b6fbe81c2e8fd90b Mon Sep 17 00:00:00 2001 From: Jay <33371449+jay94ks@users.noreply.github.com> Date: Mon, 23 Dec 2024 22:26:08 +0900 Subject: [PATCH 19/87] modified invalid marked unit exponent. --- src/class/hid/hid_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index 79b8a695e..f6704c51a 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -288,7 +288,7 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u HID_LOGICAL_MAX_N ( 0x7fff, 2 ), \ HID_REPORT_SIZE ( 16 ), \ HID_REPORT_COUNT( 1 ), \ - HID_UNIT_EXPONENT( -1 ), \ + HID_UNIT_EXPONENT( 0x0f ), \ HID_UNIT ( HID_VARIABLE | HID_NONLINEAR ), \ HID_PHYSICAL_MIN( 0 ), \ HID_PHYSICAL_MAX( 0 ), \ From 80224770316966e4339d414c60aea6a5020caa16 Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 00:36:31 +0800 Subject: [PATCH 20/87] dcd_pic: add readme --- src/portable/microchip/pic/README.md | 51 ++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/portable/microchip/pic/README.md diff --git a/src/portable/microchip/pic/README.md b/src/portable/microchip/pic/README.md new file mode 100644 index 000000000..7ba6a4a96 --- /dev/null +++ b/src/portable/microchip/pic/README.md @@ -0,0 +1,51 @@ +# Microchip PIC Chipidea FS Driver + +This driver adds support for Microchip PIC microcontrollers with full-speed Chipidea USB peripheral to the TinyUSB stack. It supports the following families: + +- PIC32MX (untested) +- PIC32MM +- PIC32MK (untested) +- PIC24FJ +- PIC24EP (untested) +- dsPIC33EP (untested) + +Currently only the device mode is supported. + + +## Important Notes + +### Handling of shared VBUS & GPIO pin + +Some PICs have the USB VBUS pin bonded with a GPIO pin in the chip package. This driver does **NOT** handle the potential conflict between the VBUS and GPIO functionalities. + +Developers must ensure that the GPIO pin is tristated when the VBUS pin is managed by the USB peripheral in order to prevent damaging the chip. + +This design choice allows developers the flexibility to use the GPIO functionality for controlling VBUS in device mode if desired. + + +## TODO + +### Handle USB remote wakeup timing correctly + +The Chipidea FS IP doesn't handle the RESUME signal automatically and it must be managed in software. It needs to be asserted for exactly 10ms, and this is impossible to do without per-device support due to BSP differences. For now, a simple for-based loop is used. + +### 8-bit PIC support + +The 8-bit PICs also uses the Chipidea FS IP. Technically it's possible to support them as well. + +Possible difficulties: +- Memory size constraints (1KB/8KB ballpark) +- A third BDT layout (now we have two) +- Different compiler-specific directives +- Compiler bugs if you use SDCC + + +## Author +[ReimuNotMoe](https://github.com/ReimuNotMoe) at SudoMaker, Ltd. + + +## Credits + +This driver is based on: +- Microchip's USB driver (usb_device.c) +- TinyUSB's NXP KHCI driver (dcd_khci.c) From 99e6b32a7da695f16a2fed93c59bfa0d5a1952dc Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 00:36:42 +0800 Subject: [PATCH 21/87] dcd_pic: change license header and credit people accordingly --- src/portable/microchip/pic/dcd_pic.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index d40c4794a..461c65259 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -1,8 +1,11 @@ /* * The MIT License (MIT) * - * Copyright (c) 2020 Koji Kitayama - * Copyright (c) 2022 Reimu NotMoe + * Copyright (c) 2022-2024 SudoMaker, Ltd. + * Author: Mike Yang (Reimu NotMoe) + * + * Based on usb_device.c - Copyright (c) 2015 Microchip Technology Inc. + * Based on dcd_khci.c - Copyright (c) 2020 Koji Kitayama * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal From 8907a817a2a782423bf8d6db2136147b6e334225 Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 00:50:32 +0800 Subject: [PATCH 22/87] dcd_pic: handle bus resume correctly --- src/portable/microchip/pic/dcd_pic.c | 58 +++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 9 deletions(-) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index 461c65259..0dac18523 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -741,8 +741,11 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) //--------------------------------------------------------------------+ void dcd_int_handler(uint8_t rhport) { - uint32_t is = U1IR; - uint32_t msk = U1IE; + uint32_t is, msk; + + // Part 1 - "USB interrupts" + is = U1IR; + msk = U1IE; U1IR = is & ~msk; is &= msk; @@ -750,7 +753,7 @@ void dcd_int_handler(uint8_t rhport) if (is & _U1IR_UERRIF_MASK) { uint32_t es = U1EIR; U1EIR = es; - U1IR = is; /* discard any pending events */ + U1IR = is; /* discard any pending events */ } if (is & _U1IR_URSTIF_MASK) { @@ -761,29 +764,66 @@ void dcd_int_handler(uint8_t rhport) if (is & _U1IR_IDLEIF_MASK) { // Note Host usually has extra delay after bus reset (without SOF), which could falsely // detected as Sleep event. Though usbd has debouncing logic so we are good + + /* + * NOTE: Do not clear U1OTGIRbits.ACTVIF here! + * Reason: + * ACTVIF is only generated once an IDLEIF has been generated. + * This is a 1:1 ratio interrupt generation. + * For every IDLEIF, there will be only one ACTVIF regardless of + * the number of subsequent bus transitions. + * + * If the ACTIF is cleared here, a problem could occur when: + * [ IDLE ][bus activity -> + * <--- 3 ms -----> ^ + * ^ ACTVIF=1 + * IDLEIF=1 + * # # # # (#=Program polling flags) + * ^ + * This polling loop will see both + * IDLEIF=1 and ACTVIF=1. + * However, the program services IDLEIF first + * because ACTIVIE=0. + * If this routine clears the only ACTIVIF, + * then it can never get out of the suspend + * mode. + */ + U1OTGIESET = _U1OTGIE_ACTVIE_MASK; U1IR = _U1IR_IDLEIF_MASK; process_bus_sleep(rhport); } - if (is & _U1IR_RESUMEIF_MASK) { - U1IR = _U1IR_RESUMEIF_MASK; - process_bus_resume(rhport); - } - if (is & _U1IR_SOFIF_MASK) { U1IR = _U1IR_SOFIF_MASK; dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true); } if (is & _U1IR_STALLIF_MASK) { - U1IR = _U1IR_STALLIF_MASK; process_stall(rhport); + U1IR = _U1IR_STALLIF_MASK; } if (is & _U1IR_TRNIF_MASK) { process_tokdne(rhport); } + // Part 2 - "USB OTG interrupts" + is = U1OTGIR; + msk = U1OTGIE; + + U1OTGIR = is & ~msk; + is &= msk; + + if (is & _U1OTGIR_ACTVIF_MASK) { +#if TU_PIC_INT_SIZE == 4 + U1OTGIECLR = _U1OTGIE_ACTVIE_MASK; +#else + U1OTGIE &= ~_U1OTGIE_ACTVIE_MASK; +#endif + U1OTGIR = _U1OTGIR_ACTVIF_MASK; + process_bus_resume(rhport); + } + intr_clear(rhport); } From f409472998cfba4f6be0534912c1afd48e0d6816 Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 00:57:22 +0800 Subject: [PATCH 23/87] dcd_pic: handle remote wakeup more correctly --- src/portable/microchip/pic/dcd_pic.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index 0dac18523..9ffeb0811 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -532,8 +532,25 @@ void dcd_remote_wakeup(uint8_t rhport) #else U1CONbits.RESUME = 1; #endif - unsigned cnt = 25000000 / 1000; + + // FIXME: Assert RESUME signal correctly, requires device-specific handling + // For now we use a hardcoded cycle-based delay which attempts to delay 10ms + // at the most common CPU frequencies. On PIC32s we assume the loop body + // takes 3 cycles. On 16-bit PICs we assume the XC16 compiler is in use and + // use its `__delay_ms' function. + +#if CFG_TUSB_MCU == OPT_MCU_PIC32MM + uint32_t cnt = 24000000 / 1000 / 3; while (cnt--) asm volatile("nop"); +#elif CFG_TUSB_MCU == OPT_MCU_PIC32MX + uint32_t cnt = 40000000 / 1000 / 3; + while (cnt--) asm volatile("nop"); +#elif CFG_TUSB_MCU == OPT_MCU_PIC32MK + uint32_t cnt = 120000000 / 1000 / 3; + while (cnt--) asm volatile("nop"); +#else + __delay_ms(10); +#endif #if TU_PIC_INT_SIZE == 4 U1CONCLR = _U1CON_RESUME_MASK; From 0192b2a9b0a8a7a300326c27ebd59f15cb34790e Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 00:59:45 +0800 Subject: [PATCH 24/87] dcd_pic: implement dcd_deinit() --- src/portable/microchip/pic/dcd_pic.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index 9ffeb0811..04c54059f 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -508,6 +508,19 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { return true; } +bool dcd_deinit(uint8_t rhport) +{ + U1CON = 0; + U1IE = 0; + U1OTGIE = 0; +#if TU_PIC_INT_SIZE == 4 + U1PWRCCLR = _U1PWRC_USUSPEND_MASK | _U1PWRC_USBPWR_MASK; +#else + U1PWRC &= ~(_U1PWRC_USUSPEND_MASK | _U1PWRC_USBPWR_MASK); +#endif + return true; +} + void dcd_int_enable(uint8_t rhport) { intr_enable(rhport); From 6e1140683140eb7bb80dfae0d207a920dec6d12c Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 01:02:10 +0800 Subject: [PATCH 25/87] dcd_pic: handle EP0 timeout/stall correctly --- src/portable/microchip/pic/dcd_pic.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index 04c54059f..4e0bd735e 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -316,12 +316,23 @@ static void prepare_next_setup_packet(uint8_t rhport) { const unsigned out_odd = _dcd.endpoint[0][0].odd; const unsigned in_odd = _dcd.endpoint[0][1].odd; - TU_ASSERT(0 == _dcd.bdt[0][0][out_odd].own, ); + + // Abandon any previous control transfers that might have been using EP0. + // Ordinarily, nothing actually needs abandoning, since the previous control + // transfer would have completed successfully prior to the host sending the + // next SETUP packet. However, in a timeout error case, or after an EP0 + // STALL event, one or more UOWN bits might still be set. If so, we should + // clear the UOWN bits, so the EP0 IN/OUT endpoints are in a known inactive + // state, ready for re-arming by the `dcd_edpt_xfer' function that will be + // called next. _dcd.bdt[0][0][out_odd].data = 0; + _dcd.bdt[0][0][out_odd].own = 0; _dcd.bdt[0][0][out_odd ^ 1].data = 1; _dcd.bdt[0][1][in_odd].data = 1; + _dcd.bdt[0][1][in_odd].own = 0; _dcd.bdt[0][1][in_odd ^ 1].data = 0; + _dcd.bdt[0][1][in_odd ^ 1].own = 0; dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT), _dcd.setup_packet, sizeof(_dcd.setup_packet)); } From a4169114ec6acb07cf8e26a1718e61c0c7af69fa Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 01:04:29 +0800 Subject: [PATCH 26/87] dcd_pic: let the user manage shared GPIO/VBUS pin --- src/portable/microchip/pic/dcd_pic.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index 4e0bd735e..a4fa0e840 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -489,10 +489,6 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { intr_disable(rhport); intr_clear(rhport); -#if CFG_TUSB_MCU == OPT_MCU_PIC32MM - TRISBbits.TRISB6 = 1; -#endif - tu_memclr(&_dcd, sizeof(_dcd)); #if TU_PIC_INT_SIZE == 4 From 655092d568720188a3a34b9376a7ebcf274dab79 Mon Sep 17 00:00:00 2001 From: Reimu NotMoe Date: Fri, 27 Dec 2024 04:17:26 +0800 Subject: [PATCH 27/87] dcd_pic: check USBBUSY bit on PIC32s --- src/portable/microchip/pic/dcd_pic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c index a4fa0e840..b4a698199 100644 --- a/src/portable/microchip/pic/dcd_pic.c +++ b/src/portable/microchip/pic/dcd_pic.c @@ -492,6 +492,9 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { tu_memclr(&_dcd, sizeof(_dcd)); #if TU_PIC_INT_SIZE == 4 + // The USBBUSY bit is present on PIC32s and we're required to check it + // prior to powering on the USB peripheral (see DS61126F page 27) + while (U1PWRCbits.USBBUSY); U1PWRCSET = _U1PWRC_USBPWR_MASK; #else U1PWRCbits.USBPWR = 1; From b91d5ebb4509d02d108e249197884913698aac1c Mon Sep 17 00:00:00 2001 From: pschatzmann Date: Sat, 4 Jan 2025 22:20:46 +0100 Subject: [PATCH 28/87] rp2040 correct dcd_edpt_iso_activate --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index af08b549d..b91dd38d5 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -496,6 +496,12 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; const uint8_t ep_addr = ep_desc->bEndpointAddress; + + // init w/o allocate + const uint16_t mps = ep_desc->wMaxPacketSize; + uint16_t size = (uint16_t)tu_div_ceil(mps, 64) * 64u; + hw_endpoint_init(ep_addr, size, TUSB_XFER_ISOCHRONOUS); + // Fill in endpoint control register with buffer offset struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and buffer allocated From f7fa4d0edb2eccfe494d1499a6fc4ef3e039309b Mon Sep 17 00:00:00 2001 From: Jannis Konrad Date: Wed, 5 Feb 2025 17:35:02 +0100 Subject: [PATCH 29/87] ch32v3 fs: signal bus speed --- src/portable/wch/dcd_ch32_usbfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index 4e8e25a00..d7674b5a3 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -192,7 +192,8 @@ void dcd_int_handler(uint8_t rhport) { data.xfer[0][TUSB_DIR_OUT].max_size = 64; data.xfer[0][TUSB_DIR_IN].max_size = 64; - dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true); + //dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? 1 : 0, true); + dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? 1 : 0, true); USBOTG_FS->DEV_ADDR = 0x00; EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; From efd29349191b5124d8f998417d31919fec49a4a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 6 Feb 2025 12:19:29 +0700 Subject: [PATCH 30/87] fix build for 407blackvet --- hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk b/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk index 2593978ec..c46a78f81 100644 --- a/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk +++ b/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk @@ -1,12 +1,12 @@ CFLAGS += -DSTM32F407xx # GCC -GCC_SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f407xx.s -GCC_LD_FILE = $(BOARD_PATH)/STM32F407VETX_FLASH.ld +SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f407xx.s +LD_FILE_GCC = $(BOARD_PATH)/STM32F407VETx_FLASH.ld # IAR -IAR_SRC_S += $(ST_CMSIS)/Source/Templates/iar/startup_stm32f407xx.s -IAR_LD_FILE = $(ST_CMSIS)/Source/Templates/iar/linker/stm32f407xx_flash.icf +SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_stm32f407xx.s +LD_FILE_IAR = $(ST_CMSIS)/Source/Templates/iar/linker/stm32f407xx_flash.icf # For flash-jlink target From 169d2d7a1fd120d8d0267eaf0a7dcc5e47059100 Mon Sep 17 00:00:00 2001 From: Jannis Konrad Date: Thu, 6 Feb 2025 08:50:25 +0100 Subject: [PATCH 31/87] use speed enum --- src/portable/wch/dcd_ch32_usbfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c index d7674b5a3..c248ba14e 100644 --- a/src/portable/wch/dcd_ch32_usbfs.c +++ b/src/portable/wch/dcd_ch32_usbfs.c @@ -192,8 +192,8 @@ void dcd_int_handler(uint8_t rhport) { data.xfer[0][TUSB_DIR_OUT].max_size = 64; data.xfer[0][TUSB_DIR_IN].max_size = 64; - //dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? 1 : 0, true); - dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? 1 : 0, true); + //dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true); + dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true); USBOTG_FS->DEV_ADDR = 0x00; EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK; From 7282572a56c774c1f523474c29965b321f6cc6c1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 6 Feb 2025 17:11:13 +0700 Subject: [PATCH 32/87] skip iar build for forked PR --- .github/workflows/build.yml | 1 + .github/workflows/hil_test.yml | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 355b6b5c4..4c54efeaf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -111,6 +111,7 @@ jobs: # --------------------------------------- # Build IAR on HFP self-hosted + # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo # --------------------------------------- arm-iar: if: github.repository_owner == 'hathach' && github.event_name == 'push' diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index 3f32bdb5d..6e9ba924b 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -90,9 +90,10 @@ jobs: # --------------------------------------- # Hardware in the loop (HIL) # self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json + # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo # --------------------------------------- hil-hfp: - if: github.repository_owner == 'hathach' + if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false runs-on: [self-hosted, Linux, X64, hifiphile] env: IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} From 3ffe8dbfee001e9591025f9dcc121fa2f5ef550c Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2025 12:33:22 +0700 Subject: [PATCH 33/87] fix stringop-overread warning for msc device with memmove --- src/class/msc/msc_device.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index dd66bfb6f..6670045aa 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -365,7 +365,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t memcpy(p_cbw, _mscd_epbuf.buf, sizeof(msc_cbw_t)); TU_LOG_DRV(" SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0])); - //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2); + // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, p_cbw, xferred_bytes, 2); p_csw->signature = MSC_CSW_SIGNATURE; p_csw->tag = p_cbw->tag; @@ -422,7 +422,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } else if (resplen == 0) { if (p_cbw->total_bytes) { // 6.7 The 13 Cases: case 4 (Hi > Dn) - // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); + // TU_LOG_DRV(" SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes); fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); } else { // case 1 Hn = Dn: all good @@ -431,7 +431,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t } else { if (p_cbw->total_bytes == 0) { // 6.7 The 13 Cases: case 2 (Hn < Di) - // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); + // TU_LOG_DRV(" SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes); fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); } else { // cannot return more than host expect @@ -445,7 +445,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t case MSC_STAGE_DATA: TU_LOG_DRV(" SCSI Data [Lun%u]\r\n", p_cbw->lun); - //TU_LOG_MEM(MSC_DEBUG, _mscd_epbuf.buf, xferred_bytes, 2); + TU_ASSERT(xferred_bytes <= CFG_TUD_MSC_EP_BUFSIZE); // sanity check to avoid buffer overflow + // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, _mscd_epbuf.buf, xferred_bytes, 2); if (SCSI_CMD_READ_10 == p_cbw->command[0]) { p_msc->xferred_len += xferred_bytes; @@ -492,7 +493,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t // Wait for the Status phase to complete if ((ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t))) { TU_LOG_DRV(" SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status); - // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2); + // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, p_csw, xferred_bytes, 2); // Invoke complete callback if defined // Note: There is racing issue with samd51 + qspi flash testing with arduino @@ -532,7 +533,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) { if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) { // 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status - // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); + // TU_LOG_DRV(" SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len); usbd_edpt_stall(rhport, p_msc->ep_in); } else { TU_ASSERT(send_csw(rhport, p_msc)); @@ -827,20 +828,18 @@ static void proc_write10_new_data(uint8_t rhport, mscd_interface_t* p_msc, uint3 // update actual byte before failed p_msc->xferred_len += xferred_bytes; - // Set sense set_sense_medium_not_present(p_cbw->lun); - fail_scsi_op(rhport, p_msc, MSC_CSW_STATUS_FAILED); } else { - // Application consume less than what we got (including zero) if ((uint32_t)nbytes < xferred_bytes) { - uint32_t const left_over = xferred_bytes - (uint32_t)nbytes; + // Application consume less than what we got (including zero) + const uint32_t left_over = xferred_bytes - (uint32_t)nbytes; if (nbytes > 0) { p_msc->xferred_len += (uint16_t)nbytes; memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over); } - // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter + // simulate a transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false); } else { // Application consume all bytes in our buffer From a232644cbd62db681ba8b285290c9b1d00a1fdb7 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 7 Feb 2025 16:38:14 +0700 Subject: [PATCH 34/87] add full hid usage for Digitizer Page (0x0D), move thing around a bit. --- src/class/hid/hid.h | 238 ++++++++++++++++++++++++++++--------- src/class/hid/hid_device.h | 4 +- 2 files changed, 186 insertions(+), 56 deletions(-) diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h index b179fc72a..c2434c20d 100644 --- a/src/class/hid/hid.h +++ b/src/class/hid/hid.h @@ -763,6 +763,21 @@ enum { //--------------------------------------------------------------------+ // Usage Table +/* Usage Types Data + Sel Selector Array + SV Static Value Constant, Variable, Absolute + SF Static Flag Constant, Variable, Absolute + DV Dynamic Value Constant, Variable, Absolute + DF Dynamic Flag Constant, Variable, Absolute +*/ +/* Usage Types Collection + NAry Named Array Logical + CA Collection Application Application + CL Collection Logical Logical + CP Collection Physical Physical + US Usage Switch Logical + UM Usage Modifier Logical +*/ //--------------------------------------------------------------------+ /// HID Usage Table - Table 1: Usage Page Summary @@ -782,10 +797,14 @@ enum { HID_USAGE_PAGE_DIGITIZER = 0x0d, HID_USAGE_PAGE_PID = 0x0f, HID_USAGE_PAGE_UNICODE = 0x10, - HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14, - HID_USAGE_PAGE_IN_RANGE = 0x32, - HID_USAGE_PAGE_MEDICAL = 0x40, - HID_USAGE_PAGE_TIP_SWITCH = 0x42, + HID_USAGE_PAGE_SOC = 0x11, + HID_USAGE_PAGE_EYE_AND_HEAD_TRACKERS = 0x12, + // 0x13 is reserved + HID_USAGE_PAGE_AUXILIARY_DISPLAY = 0x14, + // 0x15 - 0x1f is reserved + HID_USAGE_PAGE_SENSORS = 0x20, + // 0x21 - 0x3f is reserved + HID_USAGE_PAGE_MEDICAL_INSTRUMENT = 0x40, HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59, HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83 HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87 @@ -871,16 +890,6 @@ enum { HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7 }; -/// HID Usage Table: Digitizer Page (0x0D) -enum { - // Touch Screen. - HID_USAGE_DIGITIZER_TOUCH_SCREEN = 0x04, - - // Stylus Pen. - HID_USAGE_DIGITIZER_STYLUS = 0x20, -}; - - /// HID Usage Table: Consumer Page (0x0C) /// Only contains controls that supported by Windows (whole list is too long) enum { @@ -939,48 +948,125 @@ enum { HID_USAGE_CONSUMER_AC_PAN = 0x0238, }; -/// HID Usage Table - Lighting And Illumination Page (0x59) +/// HID Usage Table: Digitizer Page (0x0D) enum { - HID_USAGE_LIGHTING_LAMP_ARRAY = 0x01, - HID_USAGE_LIGHTING_LAMP_ARRAY_ATTRIBUTES_REPORT = 0x02, - HID_USAGE_LIGHTING_LAMP_COUNT = 0x03, - HID_USAGE_LIGHTING_BOUNDING_BOX_WIDTH_IN_MICROMETERS = 0x04, - HID_USAGE_LIGHTING_BOUNDING_BOX_HEIGHT_IN_MICROMETERS = 0x05, - HID_USAGE_LIGHTING_BOUNDING_BOX_DEPTH_IN_MICROMETERS = 0x06, - HID_USAGE_LIGHTING_LAMP_ARRAY_KIND = 0x07, - HID_USAGE_LIGHTING_MIN_UPDATE_INTERVAL_IN_MICROSECONDS = 0x08, - HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_REQUEST_REPORT = 0x20, - HID_USAGE_LIGHTING_LAMP_ID = 0x21, - HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_RESPONSE_REPORT = 0x22, - HID_USAGE_LIGHTING_POSITION_X_IN_MICROMETERS = 0x23, - HID_USAGE_LIGHTING_POSITION_Y_IN_MICROMETERS = 0x24, - HID_USAGE_LIGHTING_POSITION_Z_IN_MICROMETERS = 0x25, - HID_USAGE_LIGHTING_LAMP_PURPOSES = 0x26, - HID_USAGE_LIGHTING_UPDATE_LATENCY_IN_MICROSECONDS = 0x27, - HID_USAGE_LIGHTING_RED_LEVEL_COUNT = 0x28, - HID_USAGE_LIGHTING_GREEN_LEVEL_COUNT = 0x29, - HID_USAGE_LIGHTING_BLUE_LEVEL_COUNT = 0x2A, - HID_USAGE_LIGHTING_INTENSITY_LEVEL_COUNT = 0x2B, - HID_USAGE_LIGHTING_IS_PROGRAMMABLE = 0x2C, - HID_USAGE_LIGHTING_INPUT_BINDING = 0x2D, - HID_USAGE_LIGHTING_LAMP_MULTI_UPDATE_REPORT = 0x50, - HID_USAGE_LIGHTING_RED_UPDATE_CHANNEL = 0x51, - HID_USAGE_LIGHTING_GREEN_UPDATE_CHANNEL = 0x52, - HID_USAGE_LIGHTING_BLUE_UPDATE_CHANNEL = 0x53, - HID_USAGE_LIGHTING_INTENSITY_UPDATE_CHANNEL = 0x54, - HID_USAGE_LIGHTING_LAMP_UPDATE_FLAGS = 0x55, - HID_USAGE_LIGHTING_LAMP_RANGE_UPDATE_REPORT = 0x60, - HID_USAGE_LIGHTING_LAMP_ID_START = 0x61, - HID_USAGE_LIGHTING_LAMP_ID_END = 0x62, - HID_USAGE_LIGHTING_LAMP_ARRAY_CONTROL_REPORT = 0x70, - HID_USAGE_LIGHTING_AUTONOMOUS_MODE = 0x71, -}; + HID_USAGE_DIGITIZER_UNDEFINED = 0x00, + HID_USAGE_DIGITIZER_DIGITIZER = 0x01, // CA + HID_USAGE_DIGITIZER_PEN = 0x02, // CA + HID_USAGE_DIGITIZER_LIGHT_PEN = 0x03, // CA + HID_USAGE_DIGITIZER_TOUCH_SCREEN = 0x04, // CA + HID_USAGE_DIGITIZER_TOUCH_PAD = 0x05, // CA + HID_USAGE_DIGITIZER_WHITEBOARD = 0x06, // CA + HID_USAGE_DIGITIZER_COORDINATE_MEASURING_MACHINE = 0x07, // CA + HID_USAGE_DIGITIZER_3D_DIGITIZER = 0x08, // CA + HID_USAGE_DIGITIZER_STEREO_PLOTTER = 0x09, // CA + HID_USAGE_DIGITIZER_ARTICULATED_ARM = 0x0A, // CA + HID_USAGE_DIGITIZER_ARMATURE = 0x0B, // CA + HID_USAGE_DIGITIZER_MULTIPLE_POINT_DIGITIZER = 0x0C, // CA + HID_USAGE_DIGITIZER_FREE_SPACE_WAND = 0x0D, // CA + HID_USAGE_DIGITIZER_DEVICE_CONFIGURATION = 0x0E, // CA + HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_DIGITIZER = 0x0F, // CA + // Reserved (0x10 - 0x1F) + HID_USAGE_DIGITIZER_STYLUS = 0x20, // CA/CL + HID_USAGE_DIGITIZER_PUCK = 0x21, // CL + HID_USAGE_DIGITIZER_FINGER = 0x22, // CL + HID_USAGE_DIGITIZER_DEVICE_SETTINGS = 0x23, // CL + HID_USAGE_DIGITIZER_CHARACTER_GESTURE = 0x24, // CL + // Reserved (0x25 - 0x2F) + HID_USAGE_DIGITIZER_TIP_PRESSURE = 0x30, // DV + HID_USAGE_DIGITIZER_BARREL_PRESSURE = 0x31, // DV + HID_USAGE_DIGITIZER_IN_RANGE = 0x32, // MC + HID_USAGE_DIGITIZER_TOUCH = 0x33, // MC + HID_USAGE_DIGITIZER_UNTOUCH = 0x34, // OSC + HID_USAGE_DIGITIZER_TAP = 0x35, // OSC + HID_USAGE_DIGITIZER_QUALITY = 0x36, // DV + HID_USAGE_DIGITIZER_DATA_VALID = 0x37, // MC + HID_USAGE_DIGITIZER_TRANSDUCER_INDEX = 0x38, // DV + HID_USAGE_DIGITIZER_TABLET_FUNCTION_KEYS = 0x39, // CL + HID_USAGE_DIGITIZER_PROGRAM_CHANGE_KEYS = 0x3A, // CL + HID_USAGE_DIGITIZER_BATTERY_STRENGTH = 0x3B, // DV + HID_USAGE_DIGITIZER_INVERT = 0x3C, // MC + HID_USAGE_DIGITIZER_X_TILT = 0x3D, // DV + HID_USAGE_DIGITIZER_Y_TILT = 0x3E, // DV + HID_USAGE_DIGITIZER_AZIMUTH = 0x3F, // DV + HID_USAGE_DIGITIZER_ALTITUDE = 0x40, // DV + HID_USAGE_DIGITIZER_TWIST = 0x41, // DV + HID_USAGE_DIGITIZER_TIP_SWITCH = 0x42, // MC + HID_USAGE_DIGITIZER_SECONDARY_TIP_SWITCH = 0x43, // MC + HID_USAGE_DIGITIZER_BARREL_SWITCH = 0x44, // MC + HID_USAGE_DIGITIZER_ERASER = 0x45, // MC + HID_USAGE_DIGITIZER_TABLET_PICK = 0x46, // MC + HID_USAGE_DIGITIZER_TOUCH_VALID = 0x47, // MC + HID_USAGE_DIGITIZER_WIDTH = 0x48, // DV + HID_USAGE_DIGITIZER_HEIGHT = 0x49, // DV + // Reserved (0x4A - 0x50) + HID_USAGE_DIGITIZER_CONTACT_IDENTIFIER = 0x51, // DV + HID_USAGE_DIGITIZER_DEVICE_MODE = 0x52, // DV + HID_USAGE_DIGITIZER_DEVICE_IDENTIFIER = 0x53, // DV/SV + HID_USAGE_DIGITIZER_CONTACT_COUNT = 0x54, // DV + HID_USAGE_DIGITIZER_CONTACT_COUNT_MAXIMUM = 0x55, // SV + HID_USAGE_DIGITIZER_SCAN_TIME = 0x56, // DV + HID_USAGE_DIGITIZER_SURFACE_SWITCH = 0x57, // DF + HID_USAGE_DIGITIZER_BUTTON_SWITCH = 0x58, // DF + HID_USAGE_DIGITIZER_PAD_TYPE = 0x59, // SF + HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_NUMBER = 0x5B, // SV + HID_USAGE_DIGITIZER_PREFERRED_COLOR = 0x5C, // DV + HID_USAGE_DIGITIZER_PREFERRED_COLOR_LOCKED = 0x5D, // MC + HID_USAGE_DIGITIZER_PREFERRED_LINE_WIDTH = 0x5E, // DV + HID_USAGE_DIGITIZER_PREFERRED_LINE_WIDTH_LOCKED = 0x5F, // MC + HID_USAGE_DIGITIZER_LATENCY_MODE = 0x60, // DF + HID_USAGE_DIGITIZER_GESTURE_CHARACTER_QUALITY = 0x61, // DV + HID_USAGE_DIGITIZER_CHARACTER_GESTURE_DATA_LENGTH = 0x62, // DV + HID_USAGE_DIGITIZER_CHARACTER_GESTURE_DATA = 0x63, // DV + HID_USAGE_DIGITIZER_GESTURE_CHARACTER_ENCODING = 0x64, // NAry + HID_USAGE_DIGITIZER_UTF8_CHARACTER_GESTURE_ENCODING = 0x65, // Sel + HID_USAGE_DIGITIZER_UTF16_LE_CHARACTER_GESTURE_ENCODING = 0x66, // Sel + HID_USAGE_DIGITIZER_UTF16_BE_CHARACTER_GESTURE_ENCODING = 0x67, // Sel + HID_USAGE_DIGITIZER_UTF32_LE_CHARACTER_GESTURE_ENCODING = 0x68, // Sel + HID_USAGE_DIGITIZER_UTF32_BE_CHARACTER_GESTURE_ENCODING = 0x69, // Sel + HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_VENDOR_ID = 0x6A, // SV + HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_VERSION = 0x6B, // SV + HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_FRAME_DATA = 0x6C, // DV + HID_USAGE_DIGITIZER_GESTURE_CHARACTER_ENABLE = 0x6D, // DF + HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_NUMBER_PART2 = 0x6E, // SV + HID_USAGE_DIGITIZER_NO_PREFERRED_COLOR = 0x6F, // DF + HID_USAGE_DIGITIZER_PREFERRED_LINE_STYLE = 0x70, // NAry + HID_USAGE_DIGITIZER_PREFERRED_LINE_STYLE_LOCKED = 0x71, // MC + HID_USAGE_DIGITIZER_INK = 0x72, // Sel + HID_USAGE_DIGITIZER_PENCIL = 0x73, // Sel + HID_USAGE_DIGITIZER_HIGHLIGHTER = 0x74, // Sel + HID_USAGE_DIGITIZER_CHISEL_MARKER = 0x75, // Sel + HID_USAGE_DIGITIZER_BRUSH = 0x76, // Sel + HID_USAGE_DIGITIZER_NO_PREFERENCE = 0x77, // Sel + // Reserved (0x78 - 0x7F) + HID_USAGE_DIGITIZER_DIGITIZER_DIAGNOSTIC = 0x80, // CL + HID_USAGE_DIGITIZER_DIGITIZER_ERROR = 0x81, // NAry + HID_USAGE_DIGITIZER_ERR_NORMAL_STATUS = 0x82, // Sel + HID_USAGE_DIGITIZER_ERR_TRANSDUCERS_EXCEEDED = 0x83, // Sel + HID_USAGE_DIGITIZER_ERR_FULL_TRANS_FEATURES_UNAVAILABLE = 0x84, // Sel + HID_USAGE_DIGITIZER_ERR_CHARGE_LOW = 0x85, // Sel + // Reserved (0x86 - 0x8F) + HID_USAGE_DIGITIZER_TRANSDUCER_SOFTWARE_INFO = 0x90, // CL + HID_USAGE_DIGITIZER_TRANSDUCER_VENDOR_ID = 0x91, // SV + HID_USAGE_DIGITIZER_TRANSDUCER_PRODUCT_ID = 0x92, // SV + HID_USAGE_DIGITIZER_DEVICE_SUPPORTED_PROTOCOLS = 0x93, // NAry/CL + HID_USAGE_DIGITIZER_TRANSDUCER_SUPPORTED_PROTOCOLS = 0x94, // NAry/CL + HID_USAGE_DIGITIZER_NO_PROTOCOL = 0x95, // Sel + HID_USAGE_DIGITIZER_WACOM_AES_PROTOCOL = 0x96, // Sel + HID_USAGE_DIGITIZER_USI_PROTOCOL = 0x97, // Sel + HID_USAGE_DIGITIZER_MICROSOFT_PEN_PROTOCOL = 0x98, // Sel + // Reserved (0x99 - 0x9F) + HID_USAGE_DIGITIZER_SUPPORTED_REPORT_RATES = 0xA0, // SV/CL + HID_USAGE_DIGITIZER_REPORT_RATE = 0xA1, // DV + HID_USAGE_DIGITIZER_TRANSDUCER_CONNECTED = 0xA2, // SF + HID_USAGE_DIGITIZER_SWITCH_DISABLED = 0xA3, // Sel + HID_USAGE_DIGITIZER_SWITCH_UNIMPLEMENTED = 0xA4, // Sel + HID_USAGE_DIGITIZER_TRANSDUCER_SWITCHES = 0xA5, // CL + HID_USAGE_DIGITIZER_TRANSDUCER_INDEX_SELECTOR = 0xA6, // DV + // Reserved (0xA7 - 0xAF) + HID_USAGE_DIGITIZER_BUTTON_PRESS_THRESHOLD = 0xB0, // DV -/// HID Usage Table: FIDO Alliance Page (0xF1D0) -enum { - HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection - HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report - HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report + // Reserved (0xB1 - 0xFFFF) }; /// HID Usage Table: Physical Input Device Page (0x0F) @@ -1093,6 +1179,50 @@ enum { HID_USAGE_PID_RAM_POOL_AVAILABLE = 0xac, }; +/// HID Usage Table - Lighting And Illumination Page (0x59) +enum { + HID_USAGE_LIGHTING_LAMP_ARRAY = 0x01, + HID_USAGE_LIGHTING_LAMP_ARRAY_ATTRIBUTES_REPORT = 0x02, + HID_USAGE_LIGHTING_LAMP_COUNT = 0x03, + HID_USAGE_LIGHTING_BOUNDING_BOX_WIDTH_IN_MICROMETERS = 0x04, + HID_USAGE_LIGHTING_BOUNDING_BOX_HEIGHT_IN_MICROMETERS = 0x05, + HID_USAGE_LIGHTING_BOUNDING_BOX_DEPTH_IN_MICROMETERS = 0x06, + HID_USAGE_LIGHTING_LAMP_ARRAY_KIND = 0x07, + HID_USAGE_LIGHTING_MIN_UPDATE_INTERVAL_IN_MICROSECONDS = 0x08, + HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_REQUEST_REPORT = 0x20, + HID_USAGE_LIGHTING_LAMP_ID = 0x21, + HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_RESPONSE_REPORT = 0x22, + HID_USAGE_LIGHTING_POSITION_X_IN_MICROMETERS = 0x23, + HID_USAGE_LIGHTING_POSITION_Y_IN_MICROMETERS = 0x24, + HID_USAGE_LIGHTING_POSITION_Z_IN_MICROMETERS = 0x25, + HID_USAGE_LIGHTING_LAMP_PURPOSES = 0x26, + HID_USAGE_LIGHTING_UPDATE_LATENCY_IN_MICROSECONDS = 0x27, + HID_USAGE_LIGHTING_RED_LEVEL_COUNT = 0x28, + HID_USAGE_LIGHTING_GREEN_LEVEL_COUNT = 0x29, + HID_USAGE_LIGHTING_BLUE_LEVEL_COUNT = 0x2A, + HID_USAGE_LIGHTING_INTENSITY_LEVEL_COUNT = 0x2B, + HID_USAGE_LIGHTING_IS_PROGRAMMABLE = 0x2C, + HID_USAGE_LIGHTING_INPUT_BINDING = 0x2D, + HID_USAGE_LIGHTING_LAMP_MULTI_UPDATE_REPORT = 0x50, + HID_USAGE_LIGHTING_RED_UPDATE_CHANNEL = 0x51, + HID_USAGE_LIGHTING_GREEN_UPDATE_CHANNEL = 0x52, + HID_USAGE_LIGHTING_BLUE_UPDATE_CHANNEL = 0x53, + HID_USAGE_LIGHTING_INTENSITY_UPDATE_CHANNEL = 0x54, + HID_USAGE_LIGHTING_LAMP_UPDATE_FLAGS = 0x55, + HID_USAGE_LIGHTING_LAMP_RANGE_UPDATE_REPORT = 0x60, + HID_USAGE_LIGHTING_LAMP_ID_START = 0x61, + HID_USAGE_LIGHTING_LAMP_ID_END = 0x62, + HID_USAGE_LIGHTING_LAMP_ARRAY_CONTROL_REPORT = 0x70, + HID_USAGE_LIGHTING_AUTONOMOUS_MODE = 0x71, +}; + +/// HID Usage Table: FIDO Alliance Page (0xF1D0) +enum { + HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection + HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report + HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report +}; + /*-------------------------------------------------------------------- * ASCII to KEYCODE Conversion * Expand to array of [128][2] (shift, keycode) diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f6704c51a..fc1dbcbd8 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -273,8 +273,8 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u __VA_ARGS__ \ HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ) , \ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) , \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_TIP_SWITCH ) , \ - HID_USAGE_PAGE ( HID_USAGE_PAGE_IN_RANGE ) , \ + HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_TIP_SWITCH ) , \ + HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_IN_RANGE ) , \ HID_LOGICAL_MIN ( 0 ), \ HID_LOGICAL_MAX ( 1 ), \ HID_REPORT_SIZE ( 1 ), \ From 09bce3532c9279b54f5dc1e48c51959344df6c56 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 9 Feb 2025 00:04:16 +0100 Subject: [PATCH 35/87] Add CMake presets. Signed-off-by: HiFiPhile --- .gitignore | 8 +- examples/CMakePresets.json | 6 + examples/device/CMakePresets.json | 6 + .../audio_4_channel_mic/CMakePresets.json | 6 + .../CMakePresets.json | 6 + .../src/CMakePresets.json | 6 + examples/device/audio_test/CMakePresets.json | 6 + .../audio_test_freertos/CMakePresets.json | 6 + .../audio_test_freertos/src/CMakePresets.json | 6 + .../audio_test_multi_rate/CMakePresets.json | 6 + examples/device/board_test/CMakePresets.json | 6 + .../device/board_test/src/CMakePresets.json | 6 + .../device/cdc_dual_ports/CMakePresets.json | 6 + examples/device/cdc_msc/CMakePresets.json | 6 + .../device/cdc_msc_freertos/CMakePresets.json | 6 + .../cdc_msc_freertos/src/CMakePresets.json | 6 + examples/device/cdc_uac2/CMakePresets.json | 6 + examples/device/dfu/CMakePresets.json | 6 + examples/device/dfu_runtime/CMakePresets.json | 6 + .../dynamic_configuration/CMakePresets.json | 6 + .../hid_boot_interface/CMakePresets.json | 6 + .../device/hid_composite/CMakePresets.json | 6 + .../hid_composite_freertos/CMakePresets.json | 6 + .../src/CMakePresets.json | 6 + .../hid_generic_inout/CMakePresets.json | 6 + .../hid_multiple_interface/CMakePresets.json | 6 + examples/device/midi_test/CMakePresets.json | 6 + .../midi_test_freertos/CMakePresets.json | 6 + .../midi_test_freertos/src/CMakePresets.json | 6 + .../device/msc_dual_lun/CMakePresets.json | 6 + .../net_lwip_webserver/CMakePresets.json | 6 + .../device/uac2_headset/CMakePresets.json | 6 + .../device/uac2_speaker_fb/CMakePresets.json | 6 + examples/device/usbtmc/CMakePresets.json | 6 + .../device/video_capture/CMakePresets.json | 6 + .../video_capture/src/CMakePresets.json | 6 + .../video_capture_2ch/CMakePresets.json | 6 + .../video_capture_2ch/src/CMakePresets.json | 6 + .../device/webusb_serial/CMakePresets.json | 6 + examples/dual/CMakePresets.json | 6 + .../host_hid_to_device_cdc/CMakePresets.json | 6 + .../host_info_to_device_cdc/CMakePresets.json | 6 + examples/host/CMakePresets.json | 6 + examples/host/bare_api/CMakePresets.json | 6 + examples/host/cdc_msc_hid/CMakePresets.json | 6 + .../cdc_msc_hid_freertos/CMakePresets.json | 6 + .../src/CMakePresets.json | 6 + examples/host/device_info/CMakePresets.json | 6 + .../host/device_info/src/CMakePresets.json | 6 + .../host/hid_controller/CMakePresets.json | 6 + .../host/msc_file_explorer/CMakePresets.json | 6 + examples/typec/CMakePresets.json | 6 + .../typec/power_delivery/CMakePresets.json | 6 + hw/bsp/BoardPresets.json | 4002 +++++++++++++++++ hw/bsp/family_support.cmake | 6 +- tools/gen_presets.py | 91 + 56 files changed, 4417 insertions(+), 2 deletions(-) create mode 100644 examples/CMakePresets.json create mode 100644 examples/device/CMakePresets.json create mode 100644 examples/device/audio_4_channel_mic/CMakePresets.json create mode 100644 examples/device/audio_4_channel_mic_freertos/CMakePresets.json create mode 100644 examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json create mode 100644 examples/device/audio_test/CMakePresets.json create mode 100644 examples/device/audio_test_freertos/CMakePresets.json create mode 100644 examples/device/audio_test_freertos/src/CMakePresets.json create mode 100644 examples/device/audio_test_multi_rate/CMakePresets.json create mode 100644 examples/device/board_test/CMakePresets.json create mode 100644 examples/device/board_test/src/CMakePresets.json create mode 100644 examples/device/cdc_dual_ports/CMakePresets.json create mode 100644 examples/device/cdc_msc/CMakePresets.json create mode 100644 examples/device/cdc_msc_freertos/CMakePresets.json create mode 100644 examples/device/cdc_msc_freertos/src/CMakePresets.json create mode 100644 examples/device/cdc_uac2/CMakePresets.json create mode 100644 examples/device/dfu/CMakePresets.json create mode 100644 examples/device/dfu_runtime/CMakePresets.json create mode 100644 examples/device/dynamic_configuration/CMakePresets.json create mode 100644 examples/device/hid_boot_interface/CMakePresets.json create mode 100644 examples/device/hid_composite/CMakePresets.json create mode 100644 examples/device/hid_composite_freertos/CMakePresets.json create mode 100644 examples/device/hid_composite_freertos/src/CMakePresets.json create mode 100644 examples/device/hid_generic_inout/CMakePresets.json create mode 100644 examples/device/hid_multiple_interface/CMakePresets.json create mode 100644 examples/device/midi_test/CMakePresets.json create mode 100644 examples/device/midi_test_freertos/CMakePresets.json create mode 100644 examples/device/midi_test_freertos/src/CMakePresets.json create mode 100644 examples/device/msc_dual_lun/CMakePresets.json create mode 100644 examples/device/net_lwip_webserver/CMakePresets.json create mode 100644 examples/device/uac2_headset/CMakePresets.json create mode 100644 examples/device/uac2_speaker_fb/CMakePresets.json create mode 100644 examples/device/usbtmc/CMakePresets.json create mode 100644 examples/device/video_capture/CMakePresets.json create mode 100644 examples/device/video_capture/src/CMakePresets.json create mode 100644 examples/device/video_capture_2ch/CMakePresets.json create mode 100644 examples/device/video_capture_2ch/src/CMakePresets.json create mode 100644 examples/device/webusb_serial/CMakePresets.json create mode 100644 examples/dual/CMakePresets.json create mode 100644 examples/dual/host_hid_to_device_cdc/CMakePresets.json create mode 100644 examples/dual/host_info_to_device_cdc/CMakePresets.json create mode 100644 examples/host/CMakePresets.json create mode 100644 examples/host/bare_api/CMakePresets.json create mode 100644 examples/host/cdc_msc_hid/CMakePresets.json create mode 100644 examples/host/cdc_msc_hid_freertos/CMakePresets.json create mode 100644 examples/host/cdc_msc_hid_freertos/src/CMakePresets.json create mode 100644 examples/host/device_info/CMakePresets.json create mode 100644 examples/host/device_info/src/CMakePresets.json create mode 100644 examples/host/hid_controller/CMakePresets.json create mode 100644 examples/host/msc_file_explorer/CMakePresets.json create mode 100644 examples/typec/CMakePresets.json create mode 100644 examples/typec/power_delivery/CMakePresets.json create mode 100644 hw/bsp/BoardPresets.json create mode 100755 tools/gen_presets.py diff --git a/.gitignore b/.gitignore index 010b5c9ed..f981110b2 100644 --- a/.gitignore +++ b/.gitignore @@ -37,4 +37,10 @@ cmake-build-* sdkconfig .PVS-Studio .vscode/ -build/ +build +CMakeFiles +Debug +RelWithDebInfo +Release +BrowseInfo +.cmake_build diff --git a/examples/CMakePresets.json b/examples/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/CMakePresets.json b/examples/device/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_4_channel_mic/CMakePresets.json b/examples/device/audio_4_channel_mic/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_4_channel_mic/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_4_channel_mic_freertos/CMakePresets.json b/examples/device/audio_4_channel_mic_freertos/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json b/examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_test/CMakePresets.json b/examples/device/audio_test/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_test/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_test_freertos/CMakePresets.json b/examples/device/audio_test_freertos/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_test_freertos/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_test_freertos/src/CMakePresets.json b/examples/device/audio_test_freertos/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_test_freertos/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/audio_test_multi_rate/CMakePresets.json b/examples/device/audio_test_multi_rate/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/audio_test_multi_rate/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/board_test/CMakePresets.json b/examples/device/board_test/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/board_test/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/board_test/src/CMakePresets.json b/examples/device/board_test/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/board_test/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/cdc_dual_ports/CMakePresets.json b/examples/device/cdc_dual_ports/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/cdc_dual_ports/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/cdc_msc/CMakePresets.json b/examples/device/cdc_msc/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/cdc_msc/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/cdc_msc_freertos/CMakePresets.json b/examples/device/cdc_msc_freertos/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/cdc_msc_freertos/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/cdc_msc_freertos/src/CMakePresets.json b/examples/device/cdc_msc_freertos/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/cdc_msc_freertos/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/cdc_uac2/CMakePresets.json b/examples/device/cdc_uac2/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/cdc_uac2/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/dfu/CMakePresets.json b/examples/device/dfu/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/dfu/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/dfu_runtime/CMakePresets.json b/examples/device/dfu_runtime/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/dfu_runtime/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/dynamic_configuration/CMakePresets.json b/examples/device/dynamic_configuration/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/dynamic_configuration/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/hid_boot_interface/CMakePresets.json b/examples/device/hid_boot_interface/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/hid_boot_interface/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/hid_composite/CMakePresets.json b/examples/device/hid_composite/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/hid_composite/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/hid_composite_freertos/CMakePresets.json b/examples/device/hid_composite_freertos/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/hid_composite_freertos/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/hid_composite_freertos/src/CMakePresets.json b/examples/device/hid_composite_freertos/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/hid_composite_freertos/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/hid_generic_inout/CMakePresets.json b/examples/device/hid_generic_inout/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/hid_generic_inout/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/hid_multiple_interface/CMakePresets.json b/examples/device/hid_multiple_interface/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/hid_multiple_interface/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/midi_test/CMakePresets.json b/examples/device/midi_test/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/midi_test/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/midi_test_freertos/CMakePresets.json b/examples/device/midi_test_freertos/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/midi_test_freertos/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/midi_test_freertos/src/CMakePresets.json b/examples/device/midi_test_freertos/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/midi_test_freertos/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/msc_dual_lun/CMakePresets.json b/examples/device/msc_dual_lun/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/msc_dual_lun/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/net_lwip_webserver/CMakePresets.json b/examples/device/net_lwip_webserver/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/net_lwip_webserver/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/uac2_headset/CMakePresets.json b/examples/device/uac2_headset/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/uac2_headset/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/uac2_speaker_fb/CMakePresets.json b/examples/device/uac2_speaker_fb/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/uac2_speaker_fb/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/usbtmc/CMakePresets.json b/examples/device/usbtmc/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/usbtmc/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/video_capture/CMakePresets.json b/examples/device/video_capture/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/video_capture/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/video_capture/src/CMakePresets.json b/examples/device/video_capture/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/video_capture/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/video_capture_2ch/CMakePresets.json b/examples/device/video_capture_2ch/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/video_capture_2ch/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/video_capture_2ch/src/CMakePresets.json b/examples/device/video_capture_2ch/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/video_capture_2ch/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/device/webusb_serial/CMakePresets.json b/examples/device/webusb_serial/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/device/webusb_serial/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/dual/CMakePresets.json b/examples/dual/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/dual/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/dual/host_hid_to_device_cdc/CMakePresets.json b/examples/dual/host_hid_to_device_cdc/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/dual/host_hid_to_device_cdc/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/dual/host_info_to_device_cdc/CMakePresets.json b/examples/dual/host_info_to_device_cdc/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/dual/host_info_to_device_cdc/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/CMakePresets.json b/examples/host/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/bare_api/CMakePresets.json b/examples/host/bare_api/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/bare_api/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/cdc_msc_hid/CMakePresets.json b/examples/host/cdc_msc_hid/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/cdc_msc_hid/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/cdc_msc_hid_freertos/CMakePresets.json b/examples/host/cdc_msc_hid_freertos/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/cdc_msc_hid_freertos/src/CMakePresets.json b/examples/host/cdc_msc_hid_freertos/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/cdc_msc_hid_freertos/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/device_info/CMakePresets.json b/examples/host/device_info/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/device_info/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/device_info/src/CMakePresets.json b/examples/host/device_info/src/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/device_info/src/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/hid_controller/CMakePresets.json b/examples/host/hid_controller/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/hid_controller/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/host/msc_file_explorer/CMakePresets.json b/examples/host/msc_file_explorer/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/host/msc_file_explorer/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/typec/CMakePresets.json b/examples/typec/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/typec/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/examples/typec/power_delivery/CMakePresets.json b/examples/typec/power_delivery/CMakePresets.json new file mode 100644 index 000000000..5cd8971e9 --- /dev/null +++ b/examples/typec/power_delivery/CMakePresets.json @@ -0,0 +1,6 @@ +{ + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] +} diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json new file mode 100644 index 000000000..c295efbdd --- /dev/null +++ b/hw/bsp/BoardPresets.json @@ -0,0 +1,4002 @@ +{ + "version": 6, + "configurePresets": [ + { + "name": "default", + "hidden": true, + "description": "Configure preset for the ${presetName} board", + "generator": "Ninja", + "binaryDir": "${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "BOARD": "${presetName}" + } + }, + { + "name": "raspberrypi_zero", + "inherits": "default" + }, + { + "name": "raspberrypi_cm4", + "inherits": "default" + }, + { + "name": "raspberrypi_zero2", + "inherits": "default" + }, + { + "name": "ch32v103r_r1_1v0", + "inherits": "default" + }, + { + "name": "ch32v203c_r0_1v0", + "inherits": "default" + }, + { + "name": "ch32v203g_r0_1v0", + "inherits": "default" + }, + { + "name": "nanoch32v203", + "inherits": "default" + }, + { + "name": "ch32v307v_r1_1v0", + "inherits": "default" + }, + { + "name": "da14695_dk_usb", + "inherits": "default" + }, + { + "name": "da1469x_dk_pro", + "inherits": "default" + }, + { + "name": "adafruit_feather_esp32s2", + "inherits": "default" + }, + { + "name": "adafruit_feather_esp32s3", + "inherits": "default" + }, + { + "name": "adafruit_feather_esp32_v2", + "inherits": "default" + }, + { + "name": "adafruit_magtag_29gray", + "inherits": "default" + }, + { + "name": "adafruit_metro_esp32s2", + "inherits": "default" + }, + { + "name": "espressif_addax_1", + "inherits": "default" + }, + { + "name": "espressif_c3_devkitc", + "inherits": "default" + }, + { + "name": "espressif_c6_devkitc", + "inherits": "default" + }, + { + "name": "espressif_kaluga_1", + "inherits": "default" + }, + { + "name": "espressif_p4_function_ev", + "inherits": "default" + }, + { + "name": "espressif_s2_devkitc", + "inherits": "default" + }, + { + "name": "espressif_s3_devkitc", + "inherits": "default" + }, + { + "name": "espressif_s3_devkitm", + "inherits": "default" + }, + { + "name": "espressif_saola_1", + "inherits": "default" + }, + { + "name": "f1c100s", + "inherits": "default" + }, + { + "name": "fomu", + "inherits": "default" + }, + { + "name": "sipeed_longan_nano", + "inherits": "default" + }, + { + "name": "metro_m7_1011", + "inherits": "default" + }, + { + "name": "metro_m7_1011_sd", + "inherits": "default" + }, + { + "name": "mimxrt1010_evk", + "inherits": "default" + }, + { + "name": "mimxrt1015_evk", + "inherits": "default" + }, + { + "name": "mimxrt1020_evk", + "inherits": "default" + }, + { + "name": "mimxrt1024_evk", + "inherits": "default" + }, + { + "name": "mimxrt1050_evkb", + "inherits": "default" + }, + { + "name": "mimxrt1060_evk", + "inherits": "default" + }, + { + "name": "mimxrt1064_evk", + "inherits": "default" + }, + { + "name": "mimxrt1170_evkb", + "inherits": "default" + }, + { + "name": "teensy_40", + "inherits": "default" + }, + { + "name": "teensy_41", + "inherits": "default" + }, + { + "name": "frdm_k64f", + "inherits": "default" + }, + { + "name": "teensy_35", + "inherits": "default" + }, + { + "name": "frdm_k32l2a4s", + "inherits": "default" + }, + { + "name": "frdm_k32l2b", + "inherits": "default" + }, + { + "name": "kuiic", + "inherits": "default" + }, + { + "name": "frdm_kl25z", + "inherits": "default" + }, + { + "name": "lpcxpresso11u37", + "inherits": "default" + }, + { + "name": "lpcxpresso11u68", + "inherits": "default" + }, + { + "name": "lpcxpresso1347", + "inherits": "default" + }, + { + "name": "lpcxpresso1549", + "inherits": "default" + }, + { + "name": "lpcxpresso1769", + "inherits": "default" + }, + { + "name": "mbed1768", + "inherits": "default" + }, + { + "name": "lpcxpresso18s37", + "inherits": "default" + }, + { + "name": "mcb1800", + "inherits": "default" + }, + { + "name": "ea4088_quickstart", + "inherits": "default" + }, + { + "name": "ea4357", + "inherits": "default" + }, + { + "name": "lpcxpresso43s67", + "inherits": "default" + }, + { + "name": "lpcxpresso51u68", + "inherits": "default" + }, + { + "name": "lpcxpresso54114", + "inherits": "default" + }, + { + "name": "lpcxpresso54608", + "inherits": "default" + }, + { + "name": "lpcxpresso54628", + "inherits": "default" + }, + { + "name": "double_m33_express", + "inherits": "default" + }, + { + "name": "lpcxpresso55s28", + "inherits": "default" + }, + { + "name": "lpcxpresso55s69", + "inherits": "default" + }, + { + "name": "mcu_link", + "inherits": "default" + }, + { + "name": "max32650evkit", + "inherits": "default" + }, + { + "name": "max32650fthr", + "inherits": "default" + }, + { + "name": "max32651evkit", + "inherits": "default" + }, + { + "name": "max32666evkit", + "inherits": "default" + }, + { + "name": "max32666fthr", + "inherits": "default" + }, + { + "name": "apard32690", + "inherits": "default" + }, + { + "name": "max32690evkit", + "inherits": "default" + }, + { + "name": "max78002evkit", + "inherits": "default" + }, + { + "name": "frdm_mcxa153", + "inherits": "default" + }, + { + "name": "frdm_mcxn947", + "inherits": "default" + }, + { + "name": "mcxn947brk", + "inherits": "default" + }, + { + "name": "mm32f327x_mb39", + "inherits": "default" + }, + { + "name": "mm32f327x_pitaya_lite", + "inherits": "default" + }, + { + "name": "msp_exp430f5529lp", + "inherits": "default" + }, + { + "name": "msp_exp432e401y", + "inherits": "default" + }, + { + "name": "adafruit_clue", + "inherits": "default" + }, + { + "name": "arduino_nano33_ble", + "inherits": "default" + }, + { + "name": "circuitplayground_bluefruit", + "inherits": "default" + }, + { + "name": "feather_nrf52840_express", + "inherits": "default" + }, + { + "name": "feather_nrf52840_sense", + "inherits": "default" + }, + { + "name": "itsybitsy_nrf52840", + "inherits": "default" + }, + { + "name": "pca10056", + "inherits": "default" + }, + { + "name": "pca10059", + "inherits": "default" + }, + { + "name": "pca10095", + "inherits": "default" + }, + { + "name": "pca10100", + "inherits": "default" + }, + { + "name": "portenta_c33", + "inherits": "default" + }, + { + "name": "ra2a1_ek", + "inherits": "default" + }, + { + "name": "ra4m1_ek", + "inherits": "default" + }, + { + "name": "ra4m3_ek", + "inherits": "default" + }, + { + "name": "ra6m1_ek", + "inherits": "default" + }, + { + "name": "ra6m5_ek", + "inherits": "default" + }, + { + "name": "ra8m1_ek", + "inherits": "default" + }, + { + "name": "uno_r4", + "inherits": "default" + }, + { + "name": "feather_rp2040_max3421", + "inherits": "default" + }, + { + "name": "pico_sdk", + "inherits": "default" + }, + { + "name": "raspberry_pi_pico", + "inherits": "default" + }, + { + "name": "raspberry_pi_pico2", + "inherits": "default" + }, + { + "name": "cynthion_d11", + "inherits": "default" + }, + { + "name": "samd11_xplained", + "inherits": "default" + }, + { + "name": "atsamd21_xpro", + "inherits": "default" + }, + { + "name": "circuitplayground_express", + "inherits": "default" + }, + { + "name": "curiosity_nano", + "inherits": "default" + }, + { + "name": "cynthion_d21", + "inherits": "default" + }, + { + "name": "feather_m0_express", + "inherits": "default" + }, + { + "name": "itsybitsy_m0", + "inherits": "default" + }, + { + "name": "metro_m0_express", + "inherits": "default" + }, + { + "name": "qtpy", + "inherits": "default" + }, + { + "name": "seeeduino_xiao", + "inherits": "default" + }, + { + "name": "sparkfun_samd21_mini_usb", + "inherits": "default" + }, + { + "name": "trinket_m0", + "inherits": "default" + }, + { + "name": "d5035_01", + "inherits": "default" + }, + { + "name": "feather_m4_express", + "inherits": "default" + }, + { + "name": "itsybitsy_m4", + "inherits": "default" + }, + { + "name": "metro_m4_express", + "inherits": "default" + }, + { + "name": "pybadge", + "inherits": "default" + }, + { + "name": "pyportal", + "inherits": "default" + }, + { + "name": "same54_xplained", + "inherits": "default" + }, + { + "name": "samg55_xplained", + "inherits": "default" + }, + { + "name": "atsaml21_xpro", + "inherits": "default" + }, + { + "name": "saml22_feather", + "inherits": "default" + }, + { + "name": "sensorwatch_m0", + "inherits": "default" + }, + { + "name": "stm32c071nucleo", + "inherits": "default" + }, + { + "name": "stm32f070rbnucleo", + "inherits": "default" + }, + { + "name": "stm32f072disco", + "inherits": "default" + }, + { + "name": "stm32f072eval", + "inherits": "default" + }, + { + "name": "stm32f103ze_iar", + "inherits": "default" + }, + { + "name": "stm32f103_bluepill", + "inherits": "default" + }, + { + "name": "stm32f103_mini_2", + "inherits": "default" + }, + { + "name": "stm32f207nucleo", + "inherits": "default" + }, + { + "name": "stm32f303disco", + "inherits": "default" + }, + { + "name": "feather_stm32f405", + "inherits": "default" + }, + { + "name": "pyboardv11", + "inherits": "default" + }, + { + "name": "stm32f401blackpill", + "inherits": "default" + }, + { + "name": "stm32f407blackvet", + "inherits": "default" + }, + { + "name": "stm32f407disco", + "inherits": "default" + }, + { + "name": "stm32f411blackpill", + "inherits": "default" + }, + { + "name": "stm32f411disco", + "inherits": "default" + }, + { + "name": "stm32f412disco", + "inherits": "default" + }, + { + "name": "stm32f412nucleo", + "inherits": "default" + }, + { + "name": "stm32f439nucleo", + "inherits": "default" + }, + { + "name": "stlinkv3mini", + "inherits": "default" + }, + { + "name": "stm32f723disco", + "inherits": "default" + }, + { + "name": "stm32f746disco", + "inherits": "default" + }, + { + "name": "stm32f746nucleo", + "inherits": "default" + }, + { + "name": "stm32f767nucleo", + "inherits": "default" + }, + { + "name": "stm32f769disco", + "inherits": "default" + }, + { + "name": "stm32g0b1nucleo", + "inherits": "default" + }, + { + "name": "b_g474e_dpow1", + "inherits": "default" + }, + { + "name": "stm32g474nucleo", + "inherits": "default" + }, + { + "name": "stm32g491nucleo", + "inherits": "default" + }, + { + "name": "stm32h503nucleo", + "inherits": "default" + }, + { + "name": "stm32h563nucleo", + "inherits": "default" + }, + { + "name": "stm32h573i_dk", + "inherits": "default" + }, + { + "name": "daisyseed", + "inherits": "default" + }, + { + "name": "stm32h723nucleo", + "inherits": "default" + }, + { + "name": "stm32h743eval", + "inherits": "default" + }, + { + "name": "stm32h743nucleo", + "inherits": "default" + }, + { + "name": "stm32h745disco", + "inherits": "default" + }, + { + "name": "stm32h750bdk", + "inherits": "default" + }, + { + "name": "stm32h750_weact", + "inherits": "default" + }, + { + "name": "waveshare_openh743i", + "inherits": "default" + }, + { + "name": "stm32h7s3nucleo", + "inherits": "default" + }, + { + "name": "stm32l052dap52", + "inherits": "default" + }, + { + "name": "stm32l0538disco", + "inherits": "default" + }, + { + "name": "stm32l412nucleo", + "inherits": "default" + }, + { + "name": "stm32l476disco", + "inherits": "default" + }, + { + "name": "stm32l4p5nucleo", + "inherits": "default" + }, + { + "name": "stm32l4r5nucleo", + "inherits": "default" + }, + { + "name": "b_u585i_iot2a", + "inherits": "default" + }, + { + "name": "stm32u545nucleo", + "inherits": "default" + }, + { + "name": "stm32u575eval", + "inherits": "default" + }, + { + "name": "stm32u575nucleo", + "inherits": "default" + }, + { + "name": "stm32u5a5nucleo", + "inherits": "default" + }, + { + "name": "stm32wb55nucleo", + "inherits": "default" + }, + { + "name": "ek_tm4c123gxl", + "inherits": "default" + }, + { + "name": "xmc4500_relax", + "inherits": "default" + }, + { + "name": "xmc4700_relax", + "inherits": "default" + } + ], + "buildPresets": [ + { + "name": "raspberrypi_zero", + "description": "Build preset for the raspberrypi_zero board", + "configurePreset": "raspberrypi_zero" + }, + { + "name": "raspberrypi_cm4", + "description": "Build preset for the raspberrypi_cm4 board", + "configurePreset": "raspberrypi_cm4" + }, + { + "name": "raspberrypi_zero2", + "description": "Build preset for the raspberrypi_zero2 board", + "configurePreset": "raspberrypi_zero2" + }, + { + "name": "ch32v103r_r1_1v0", + "description": "Build preset for the ch32v103r_r1_1v0 board", + "configurePreset": "ch32v103r_r1_1v0" + }, + { + "name": "ch32v203c_r0_1v0", + "description": "Build preset for the ch32v203c_r0_1v0 board", + "configurePreset": "ch32v203c_r0_1v0" + }, + { + "name": "ch32v203g_r0_1v0", + "description": "Build preset for the ch32v203g_r0_1v0 board", + "configurePreset": "ch32v203g_r0_1v0" + }, + { + "name": "nanoch32v203", + "description": "Build preset for the nanoch32v203 board", + "configurePreset": "nanoch32v203" + }, + { + "name": "ch32v307v_r1_1v0", + "description": "Build preset for the ch32v307v_r1_1v0 board", + "configurePreset": "ch32v307v_r1_1v0" + }, + { + "name": "da14695_dk_usb", + "description": "Build preset for the da14695_dk_usb board", + "configurePreset": "da14695_dk_usb" + }, + { + "name": "da1469x_dk_pro", + "description": "Build preset for the da1469x_dk_pro board", + "configurePreset": "da1469x_dk_pro" + }, + { + "name": "adafruit_feather_esp32s2", + "description": "Build preset for the adafruit_feather_esp32s2 board", + "configurePreset": "adafruit_feather_esp32s2" + }, + { + "name": "adafruit_feather_esp32s3", + "description": "Build preset for the adafruit_feather_esp32s3 board", + "configurePreset": "adafruit_feather_esp32s3" + }, + { + "name": "adafruit_feather_esp32_v2", + "description": "Build preset for the adafruit_feather_esp32_v2 board", + "configurePreset": "adafruit_feather_esp32_v2" + }, + { + "name": "adafruit_magtag_29gray", + "description": "Build preset for the adafruit_magtag_29gray board", + "configurePreset": "adafruit_magtag_29gray" + }, + { + "name": "adafruit_metro_esp32s2", + "description": "Build preset for the adafruit_metro_esp32s2 board", + "configurePreset": "adafruit_metro_esp32s2" + }, + { + "name": "espressif_addax_1", + "description": "Build preset for the espressif_addax_1 board", + "configurePreset": "espressif_addax_1" + }, + { + "name": "espressif_c3_devkitc", + "description": "Build preset for the espressif_c3_devkitc board", + "configurePreset": "espressif_c3_devkitc" + }, + { + "name": "espressif_c6_devkitc", + "description": "Build preset for the espressif_c6_devkitc board", + "configurePreset": "espressif_c6_devkitc" + }, + { + "name": "espressif_kaluga_1", + "description": "Build preset for the espressif_kaluga_1 board", + "configurePreset": "espressif_kaluga_1" + }, + { + "name": "espressif_p4_function_ev", + "description": "Build preset for the espressif_p4_function_ev board", + "configurePreset": "espressif_p4_function_ev" + }, + { + "name": "espressif_s2_devkitc", + "description": "Build preset for the espressif_s2_devkitc board", + "configurePreset": "espressif_s2_devkitc" + }, + { + "name": "espressif_s3_devkitc", + "description": "Build preset for the espressif_s3_devkitc board", + "configurePreset": "espressif_s3_devkitc" + }, + { + "name": "espressif_s3_devkitm", + "description": "Build preset for the espressif_s3_devkitm board", + "configurePreset": "espressif_s3_devkitm" + }, + { + "name": "espressif_saola_1", + "description": "Build preset for the espressif_saola_1 board", + "configurePreset": "espressif_saola_1" + }, + { + "name": "f1c100s", + "description": "Build preset for the f1c100s board", + "configurePreset": "f1c100s" + }, + { + "name": "fomu", + "description": "Build preset for the fomu board", + "configurePreset": "fomu" + }, + { + "name": "sipeed_longan_nano", + "description": "Build preset for the sipeed_longan_nano board", + "configurePreset": "sipeed_longan_nano" + }, + { + "name": "metro_m7_1011", + "description": "Build preset for the metro_m7_1011 board", + "configurePreset": "metro_m7_1011" + }, + { + "name": "metro_m7_1011_sd", + "description": "Build preset for the metro_m7_1011_sd board", + "configurePreset": "metro_m7_1011_sd" + }, + { + "name": "mimxrt1010_evk", + "description": "Build preset for the mimxrt1010_evk board", + "configurePreset": "mimxrt1010_evk" + }, + { + "name": "mimxrt1015_evk", + "description": "Build preset for the mimxrt1015_evk board", + "configurePreset": "mimxrt1015_evk" + }, + { + "name": "mimxrt1020_evk", + "description": "Build preset for the mimxrt1020_evk board", + "configurePreset": "mimxrt1020_evk" + }, + { + "name": "mimxrt1024_evk", + "description": "Build preset for the mimxrt1024_evk board", + "configurePreset": "mimxrt1024_evk" + }, + { + "name": "mimxrt1050_evkb", + "description": "Build preset for the mimxrt1050_evkb board", + "configurePreset": "mimxrt1050_evkb" + }, + { + "name": "mimxrt1060_evk", + "description": "Build preset for the mimxrt1060_evk board", + "configurePreset": "mimxrt1060_evk" + }, + { + "name": "mimxrt1064_evk", + "description": "Build preset for the mimxrt1064_evk board", + "configurePreset": "mimxrt1064_evk" + }, + { + "name": "mimxrt1170_evkb", + "description": "Build preset for the mimxrt1170_evkb board", + "configurePreset": "mimxrt1170_evkb" + }, + { + "name": "teensy_40", + "description": "Build preset for the teensy_40 board", + "configurePreset": "teensy_40" + }, + { + "name": "teensy_41", + "description": "Build preset for the teensy_41 board", + "configurePreset": "teensy_41" + }, + { + "name": "frdm_k64f", + "description": "Build preset for the frdm_k64f board", + "configurePreset": "frdm_k64f" + }, + { + "name": "teensy_35", + "description": "Build preset for the teensy_35 board", + "configurePreset": "teensy_35" + }, + { + "name": "frdm_k32l2a4s", + "description": "Build preset for the frdm_k32l2a4s board", + "configurePreset": "frdm_k32l2a4s" + }, + { + "name": "frdm_k32l2b", + "description": "Build preset for the frdm_k32l2b board", + "configurePreset": "frdm_k32l2b" + }, + { + "name": "kuiic", + "description": "Build preset for the kuiic board", + "configurePreset": "kuiic" + }, + { + "name": "frdm_kl25z", + "description": "Build preset for the frdm_kl25z board", + "configurePreset": "frdm_kl25z" + }, + { + "name": "lpcxpresso11u37", + "description": "Build preset for the lpcxpresso11u37 board", + "configurePreset": "lpcxpresso11u37" + }, + { + "name": "lpcxpresso11u68", + "description": "Build preset for the lpcxpresso11u68 board", + "configurePreset": "lpcxpresso11u68" + }, + { + "name": "lpcxpresso1347", + "description": "Build preset for the lpcxpresso1347 board", + "configurePreset": "lpcxpresso1347" + }, + { + "name": "lpcxpresso1549", + "description": "Build preset for the lpcxpresso1549 board", + "configurePreset": "lpcxpresso1549" + }, + { + "name": "lpcxpresso1769", + "description": "Build preset for the lpcxpresso1769 board", + "configurePreset": "lpcxpresso1769" + }, + { + "name": "mbed1768", + "description": "Build preset for the mbed1768 board", + "configurePreset": "mbed1768" + }, + { + "name": "lpcxpresso18s37", + "description": "Build preset for the lpcxpresso18s37 board", + "configurePreset": "lpcxpresso18s37" + }, + { + "name": "mcb1800", + "description": "Build preset for the mcb1800 board", + "configurePreset": "mcb1800" + }, + { + "name": "ea4088_quickstart", + "description": "Build preset for the ea4088_quickstart board", + "configurePreset": "ea4088_quickstart" + }, + { + "name": "ea4357", + "description": "Build preset for the ea4357 board", + "configurePreset": "ea4357" + }, + { + "name": "lpcxpresso43s67", + "description": "Build preset for the lpcxpresso43s67 board", + "configurePreset": "lpcxpresso43s67" + }, + { + "name": "lpcxpresso51u68", + "description": "Build preset for the lpcxpresso51u68 board", + "configurePreset": "lpcxpresso51u68" + }, + { + "name": "lpcxpresso54114", + "description": "Build preset for the lpcxpresso54114 board", + "configurePreset": "lpcxpresso54114" + }, + { + "name": "lpcxpresso54608", + "description": "Build preset for the lpcxpresso54608 board", + "configurePreset": "lpcxpresso54608" + }, + { + "name": "lpcxpresso54628", + "description": "Build preset for the lpcxpresso54628 board", + "configurePreset": "lpcxpresso54628" + }, + { + "name": "double_m33_express", + "description": "Build preset for the double_m33_express board", + "configurePreset": "double_m33_express" + }, + { + "name": "lpcxpresso55s28", + "description": "Build preset for the lpcxpresso55s28 board", + "configurePreset": "lpcxpresso55s28" + }, + { + "name": "lpcxpresso55s69", + "description": "Build preset for the lpcxpresso55s69 board", + "configurePreset": "lpcxpresso55s69" + }, + { + "name": "mcu_link", + "description": "Build preset for the mcu_link board", + "configurePreset": "mcu_link" + }, + { + "name": "max32650evkit", + "description": "Build preset for the max32650evkit board", + "configurePreset": "max32650evkit" + }, + { + "name": "max32650fthr", + "description": "Build preset for the max32650fthr board", + "configurePreset": "max32650fthr" + }, + { + "name": "max32651evkit", + "description": "Build preset for the max32651evkit board", + "configurePreset": "max32651evkit" + }, + { + "name": "max32666evkit", + "description": "Build preset for the max32666evkit board", + "configurePreset": "max32666evkit" + }, + { + "name": "max32666fthr", + "description": "Build preset for the max32666fthr board", + "configurePreset": "max32666fthr" + }, + { + "name": "apard32690", + "description": "Build preset for the apard32690 board", + "configurePreset": "apard32690" + }, + { + "name": "max32690evkit", + "description": "Build preset for the max32690evkit board", + "configurePreset": "max32690evkit" + }, + { + "name": "max78002evkit", + "description": "Build preset for the max78002evkit board", + "configurePreset": "max78002evkit" + }, + { + "name": "frdm_mcxa153", + "description": "Build preset for the frdm_mcxa153 board", + "configurePreset": "frdm_mcxa153" + }, + { + "name": "frdm_mcxn947", + "description": "Build preset for the frdm_mcxn947 board", + "configurePreset": "frdm_mcxn947" + }, + { + "name": "mcxn947brk", + "description": "Build preset for the mcxn947brk board", + "configurePreset": "mcxn947brk" + }, + { + "name": "mm32f327x_mb39", + "description": "Build preset for the mm32f327x_mb39 board", + "configurePreset": "mm32f327x_mb39" + }, + { + "name": "mm32f327x_pitaya_lite", + "description": "Build preset for the mm32f327x_pitaya_lite board", + "configurePreset": "mm32f327x_pitaya_lite" + }, + { + "name": "msp_exp430f5529lp", + "description": "Build preset for the msp_exp430f5529lp board", + "configurePreset": "msp_exp430f5529lp" + }, + { + "name": "msp_exp432e401y", + "description": "Build preset for the msp_exp432e401y board", + "configurePreset": "msp_exp432e401y" + }, + { + "name": "adafruit_clue", + "description": "Build preset for the adafruit_clue board", + "configurePreset": "adafruit_clue" + }, + { + "name": "arduino_nano33_ble", + "description": "Build preset for the arduino_nano33_ble board", + "configurePreset": "arduino_nano33_ble" + }, + { + "name": "circuitplayground_bluefruit", + "description": "Build preset for the circuitplayground_bluefruit board", + "configurePreset": "circuitplayground_bluefruit" + }, + { + "name": "feather_nrf52840_express", + "description": "Build preset for the feather_nrf52840_express board", + "configurePreset": "feather_nrf52840_express" + }, + { + "name": "feather_nrf52840_sense", + "description": "Build preset for the feather_nrf52840_sense board", + "configurePreset": "feather_nrf52840_sense" + }, + { + "name": "itsybitsy_nrf52840", + "description": "Build preset for the itsybitsy_nrf52840 board", + "configurePreset": "itsybitsy_nrf52840" + }, + { + "name": "pca10056", + "description": "Build preset for the pca10056 board", + "configurePreset": "pca10056" + }, + { + "name": "pca10059", + "description": "Build preset for the pca10059 board", + "configurePreset": "pca10059" + }, + { + "name": "pca10095", + "description": "Build preset for the pca10095 board", + "configurePreset": "pca10095" + }, + { + "name": "pca10100", + "description": "Build preset for the pca10100 board", + "configurePreset": "pca10100" + }, + { + "name": "portenta_c33", + "description": "Build preset for the portenta_c33 board", + "configurePreset": "portenta_c33" + }, + { + "name": "ra2a1_ek", + "description": "Build preset for the ra2a1_ek board", + "configurePreset": "ra2a1_ek" + }, + { + "name": "ra4m1_ek", + "description": "Build preset for the ra4m1_ek board", + "configurePreset": "ra4m1_ek" + }, + { + "name": "ra4m3_ek", + "description": "Build preset for the ra4m3_ek board", + "configurePreset": "ra4m3_ek" + }, + { + "name": "ra6m1_ek", + "description": "Build preset for the ra6m1_ek board", + "configurePreset": "ra6m1_ek" + }, + { + "name": "ra6m5_ek", + "description": "Build preset for the ra6m5_ek board", + "configurePreset": "ra6m5_ek" + }, + { + "name": "ra8m1_ek", + "description": "Build preset for the ra8m1_ek board", + "configurePreset": "ra8m1_ek" + }, + { + "name": "uno_r4", + "description": "Build preset for the uno_r4 board", + "configurePreset": "uno_r4" + }, + { + "name": "feather_rp2040_max3421", + "description": "Build preset for the feather_rp2040_max3421 board", + "configurePreset": "feather_rp2040_max3421" + }, + { + "name": "pico_sdk", + "description": "Build preset for the pico_sdk board", + "configurePreset": "pico_sdk" + }, + { + "name": "raspberry_pi_pico", + "description": "Build preset for the raspberry_pi_pico board", + "configurePreset": "raspberry_pi_pico" + }, + { + "name": "raspberry_pi_pico2", + "description": "Build preset for the raspberry_pi_pico2 board", + "configurePreset": "raspberry_pi_pico2" + }, + { + "name": "cynthion_d11", + "description": "Build preset for the cynthion_d11 board", + "configurePreset": "cynthion_d11" + }, + { + "name": "samd11_xplained", + "description": "Build preset for the samd11_xplained board", + "configurePreset": "samd11_xplained" + }, + { + "name": "atsamd21_xpro", + "description": "Build preset for the atsamd21_xpro board", + "configurePreset": "atsamd21_xpro" + }, + { + "name": "circuitplayground_express", + "description": "Build preset for the circuitplayground_express board", + "configurePreset": "circuitplayground_express" + }, + { + "name": "curiosity_nano", + "description": "Build preset for the curiosity_nano board", + "configurePreset": "curiosity_nano" + }, + { + "name": "cynthion_d21", + "description": "Build preset for the cynthion_d21 board", + "configurePreset": "cynthion_d21" + }, + { + "name": "feather_m0_express", + "description": "Build preset for the feather_m0_express board", + "configurePreset": "feather_m0_express" + }, + { + "name": "itsybitsy_m0", + "description": "Build preset for the itsybitsy_m0 board", + "configurePreset": "itsybitsy_m0" + }, + { + "name": "metro_m0_express", + "description": "Build preset for the metro_m0_express board", + "configurePreset": "metro_m0_express" + }, + { + "name": "qtpy", + "description": "Build preset for the qtpy board", + "configurePreset": "qtpy" + }, + { + "name": "seeeduino_xiao", + "description": "Build preset for the seeeduino_xiao board", + "configurePreset": "seeeduino_xiao" + }, + { + "name": "sparkfun_samd21_mini_usb", + "description": "Build preset for the sparkfun_samd21_mini_usb board", + "configurePreset": "sparkfun_samd21_mini_usb" + }, + { + "name": "trinket_m0", + "description": "Build preset for the trinket_m0 board", + "configurePreset": "trinket_m0" + }, + { + "name": "d5035_01", + "description": "Build preset for the d5035_01 board", + "configurePreset": "d5035_01" + }, + { + "name": "feather_m4_express", + "description": "Build preset for the feather_m4_express board", + "configurePreset": "feather_m4_express" + }, + { + "name": "itsybitsy_m4", + "description": "Build preset for the itsybitsy_m4 board", + "configurePreset": "itsybitsy_m4" + }, + { + "name": "metro_m4_express", + "description": "Build preset for the metro_m4_express board", + "configurePreset": "metro_m4_express" + }, + { + "name": "pybadge", + "description": "Build preset for the pybadge board", + "configurePreset": "pybadge" + }, + { + "name": "pyportal", + "description": "Build preset for the pyportal board", + "configurePreset": "pyportal" + }, + { + "name": "same54_xplained", + "description": "Build preset for the same54_xplained board", + "configurePreset": "same54_xplained" + }, + { + "name": "samg55_xplained", + "description": "Build preset for the samg55_xplained board", + "configurePreset": "samg55_xplained" + }, + { + "name": "atsaml21_xpro", + "description": "Build preset for the atsaml21_xpro board", + "configurePreset": "atsaml21_xpro" + }, + { + "name": "saml22_feather", + "description": "Build preset for the saml22_feather board", + "configurePreset": "saml22_feather" + }, + { + "name": "sensorwatch_m0", + "description": "Build preset for the sensorwatch_m0 board", + "configurePreset": "sensorwatch_m0" + }, + { + "name": "stm32c071nucleo", + "description": "Build preset for the stm32c071nucleo board", + "configurePreset": "stm32c071nucleo" + }, + { + "name": "stm32f070rbnucleo", + "description": "Build preset for the stm32f070rbnucleo board", + "configurePreset": "stm32f070rbnucleo" + }, + { + "name": "stm32f072disco", + "description": "Build preset for the stm32f072disco board", + "configurePreset": "stm32f072disco" + }, + { + "name": "stm32f072eval", + "description": "Build preset for the stm32f072eval board", + "configurePreset": "stm32f072eval" + }, + { + "name": "stm32f103ze_iar", + "description": "Build preset for the stm32f103ze_iar board", + "configurePreset": "stm32f103ze_iar" + }, + { + "name": "stm32f103_bluepill", + "description": "Build preset for the stm32f103_bluepill board", + "configurePreset": "stm32f103_bluepill" + }, + { + "name": "stm32f103_mini_2", + "description": "Build preset for the stm32f103_mini_2 board", + "configurePreset": "stm32f103_mini_2" + }, + { + "name": "stm32f207nucleo", + "description": "Build preset for the stm32f207nucleo board", + "configurePreset": "stm32f207nucleo" + }, + { + "name": "stm32f303disco", + "description": "Build preset for the stm32f303disco board", + "configurePreset": "stm32f303disco" + }, + { + "name": "feather_stm32f405", + "description": "Build preset for the feather_stm32f405 board", + "configurePreset": "feather_stm32f405" + }, + { + "name": "pyboardv11", + "description": "Build preset for the pyboardv11 board", + "configurePreset": "pyboardv11" + }, + { + "name": "stm32f401blackpill", + "description": "Build preset for the stm32f401blackpill board", + "configurePreset": "stm32f401blackpill" + }, + { + "name": "stm32f407blackvet", + "description": "Build preset for the stm32f407blackvet board", + "configurePreset": "stm32f407blackvet" + }, + { + "name": "stm32f407disco", + "description": "Build preset for the stm32f407disco board", + "configurePreset": "stm32f407disco" + }, + { + "name": "stm32f411blackpill", + "description": "Build preset for the stm32f411blackpill board", + "configurePreset": "stm32f411blackpill" + }, + { + "name": "stm32f411disco", + "description": "Build preset for the stm32f411disco board", + "configurePreset": "stm32f411disco" + }, + { + "name": "stm32f412disco", + "description": "Build preset for the stm32f412disco board", + "configurePreset": "stm32f412disco" + }, + { + "name": "stm32f412nucleo", + "description": "Build preset for the stm32f412nucleo board", + "configurePreset": "stm32f412nucleo" + }, + { + "name": "stm32f439nucleo", + "description": "Build preset for the stm32f439nucleo board", + "configurePreset": "stm32f439nucleo" + }, + { + "name": "stlinkv3mini", + "description": "Build preset for the stlinkv3mini board", + "configurePreset": "stlinkv3mini" + }, + { + "name": "stm32f723disco", + "description": "Build preset for the stm32f723disco board", + "configurePreset": "stm32f723disco" + }, + { + "name": "stm32f746disco", + "description": "Build preset for the stm32f746disco board", + "configurePreset": "stm32f746disco" + }, + { + "name": "stm32f746nucleo", + "description": "Build preset for the stm32f746nucleo board", + "configurePreset": "stm32f746nucleo" + }, + { + "name": "stm32f767nucleo", + "description": "Build preset for the stm32f767nucleo board", + "configurePreset": "stm32f767nucleo" + }, + { + "name": "stm32f769disco", + "description": "Build preset for the stm32f769disco board", + "configurePreset": "stm32f769disco" + }, + { + "name": "stm32g0b1nucleo", + "description": "Build preset for the stm32g0b1nucleo board", + "configurePreset": "stm32g0b1nucleo" + }, + { + "name": "b_g474e_dpow1", + "description": "Build preset for the b_g474e_dpow1 board", + "configurePreset": "b_g474e_dpow1" + }, + { + "name": "stm32g474nucleo", + "description": "Build preset for the stm32g474nucleo board", + "configurePreset": "stm32g474nucleo" + }, + { + "name": "stm32g491nucleo", + "description": "Build preset for the stm32g491nucleo board", + "configurePreset": "stm32g491nucleo" + }, + { + "name": "stm32h503nucleo", + "description": "Build preset for the stm32h503nucleo board", + "configurePreset": "stm32h503nucleo" + }, + { + "name": "stm32h563nucleo", + "description": "Build preset for the stm32h563nucleo board", + "configurePreset": "stm32h563nucleo" + }, + { + "name": "stm32h573i_dk", + "description": "Build preset for the stm32h573i_dk board", + "configurePreset": "stm32h573i_dk" + }, + { + "name": "daisyseed", + "description": "Build preset for the daisyseed board", + "configurePreset": "daisyseed" + }, + { + "name": "stm32h723nucleo", + "description": "Build preset for the stm32h723nucleo board", + "configurePreset": "stm32h723nucleo" + }, + { + "name": "stm32h743eval", + "description": "Build preset for the stm32h743eval board", + "configurePreset": "stm32h743eval" + }, + { + "name": "stm32h743nucleo", + "description": "Build preset for the stm32h743nucleo board", + "configurePreset": "stm32h743nucleo" + }, + { + "name": "stm32h745disco", + "description": "Build preset for the stm32h745disco board", + "configurePreset": "stm32h745disco" + }, + { + "name": "stm32h750bdk", + "description": "Build preset for the stm32h750bdk board", + "configurePreset": "stm32h750bdk" + }, + { + "name": "stm32h750_weact", + "description": "Build preset for the stm32h750_weact board", + "configurePreset": "stm32h750_weact" + }, + { + "name": "waveshare_openh743i", + "description": "Build preset for the waveshare_openh743i board", + "configurePreset": "waveshare_openh743i" + }, + { + "name": "stm32h7s3nucleo", + "description": "Build preset for the stm32h7s3nucleo board", + "configurePreset": "stm32h7s3nucleo" + }, + { + "name": "stm32l052dap52", + "description": "Build preset for the stm32l052dap52 board", + "configurePreset": "stm32l052dap52" + }, + { + "name": "stm32l0538disco", + "description": "Build preset for the stm32l0538disco board", + "configurePreset": "stm32l0538disco" + }, + { + "name": "stm32l412nucleo", + "description": "Build preset for the stm32l412nucleo board", + "configurePreset": "stm32l412nucleo" + }, + { + "name": "stm32l476disco", + "description": "Build preset for the stm32l476disco board", + "configurePreset": "stm32l476disco" + }, + { + "name": "stm32l4p5nucleo", + "description": "Build preset for the stm32l4p5nucleo board", + "configurePreset": "stm32l4p5nucleo" + }, + { + "name": "stm32l4r5nucleo", + "description": "Build preset for the stm32l4r5nucleo board", + "configurePreset": "stm32l4r5nucleo" + }, + { + "name": "b_u585i_iot2a", + "description": "Build preset for the b_u585i_iot2a board", + "configurePreset": "b_u585i_iot2a" + }, + { + "name": "stm32u545nucleo", + "description": "Build preset for the stm32u545nucleo board", + "configurePreset": "stm32u545nucleo" + }, + { + "name": "stm32u575eval", + "description": "Build preset for the stm32u575eval board", + "configurePreset": "stm32u575eval" + }, + { + "name": "stm32u575nucleo", + "description": "Build preset for the stm32u575nucleo board", + "configurePreset": "stm32u575nucleo" + }, + { + "name": "stm32u5a5nucleo", + "description": "Build preset for the stm32u5a5nucleo board", + "configurePreset": "stm32u5a5nucleo" + }, + { + "name": "stm32wb55nucleo", + "description": "Build preset for the stm32wb55nucleo board", + "configurePreset": "stm32wb55nucleo" + }, + { + "name": "ek_tm4c123gxl", + "description": "Build preset for the ek_tm4c123gxl board", + "configurePreset": "ek_tm4c123gxl" + }, + { + "name": "xmc4500_relax", + "description": "Build preset for the xmc4500_relax board", + "configurePreset": "xmc4500_relax" + }, + { + "name": "xmc4700_relax", + "description": "Build preset for the xmc4700_relax board", + "configurePreset": "xmc4700_relax" + } + ], + "workflowPresets": [ + { + "name": "raspberrypi_zero", + "steps": [ + { + "type": "configure", + "name": "raspberrypi_zero" + }, + { + "type": "build", + "name": "raspberrypi_zero" + } + ] + }, + { + "name": "raspberrypi_cm4", + "steps": [ + { + "type": "configure", + "name": "raspberrypi_cm4" + }, + { + "type": "build", + "name": "raspberrypi_cm4" + } + ] + }, + { + "name": "raspberrypi_zero2", + "steps": [ + { + "type": "configure", + "name": "raspberrypi_zero2" + }, + { + "type": "build", + "name": "raspberrypi_zero2" + } + ] + }, + { + "name": "ch32v103r_r1_1v0", + "steps": [ + { + "type": "configure", + "name": "ch32v103r_r1_1v0" + }, + { + "type": "build", + "name": "ch32v103r_r1_1v0" + } + ] + }, + { + "name": "ch32v203c_r0_1v0", + "steps": [ + { + "type": "configure", + "name": "ch32v203c_r0_1v0" + }, + { + "type": "build", + "name": "ch32v203c_r0_1v0" + } + ] + }, + { + "name": "ch32v203g_r0_1v0", + "steps": [ + { + "type": "configure", + "name": "ch32v203g_r0_1v0" + }, + { + "type": "build", + "name": "ch32v203g_r0_1v0" + } + ] + }, + { + "name": "nanoch32v203", + "steps": [ + { + "type": "configure", + "name": "nanoch32v203" + }, + { + "type": "build", + "name": "nanoch32v203" + } + ] + }, + { + "name": "ch32v307v_r1_1v0", + "steps": [ + { + "type": "configure", + "name": "ch32v307v_r1_1v0" + }, + { + "type": "build", + "name": "ch32v307v_r1_1v0" + } + ] + }, + { + "name": "da14695_dk_usb", + "steps": [ + { + "type": "configure", + "name": "da14695_dk_usb" + }, + { + "type": "build", + "name": "da14695_dk_usb" + } + ] + }, + { + "name": "da1469x_dk_pro", + "steps": [ + { + "type": "configure", + "name": "da1469x_dk_pro" + }, + { + "type": "build", + "name": "da1469x_dk_pro" + } + ] + }, + { + "name": "adafruit_feather_esp32s2", + "steps": [ + { + "type": "configure", + "name": "adafruit_feather_esp32s2" + }, + { + "type": "build", + "name": "adafruit_feather_esp32s2" + } + ] + }, + { + "name": "adafruit_feather_esp32s3", + "steps": [ + { + "type": "configure", + "name": "adafruit_feather_esp32s3" + }, + { + "type": "build", + "name": "adafruit_feather_esp32s3" + } + ] + }, + { + "name": "adafruit_feather_esp32_v2", + "steps": [ + { + "type": "configure", + "name": "adafruit_feather_esp32_v2" + }, + { + "type": "build", + "name": "adafruit_feather_esp32_v2" + } + ] + }, + { + "name": "adafruit_magtag_29gray", + "steps": [ + { + "type": "configure", + "name": "adafruit_magtag_29gray" + }, + { + "type": "build", + "name": "adafruit_magtag_29gray" + } + ] + }, + { + "name": "adafruit_metro_esp32s2", + "steps": [ + { + "type": "configure", + "name": "adafruit_metro_esp32s2" + }, + { + "type": "build", + "name": "adafruit_metro_esp32s2" + } + ] + }, + { + "name": "espressif_addax_1", + "steps": [ + { + "type": "configure", + "name": "espressif_addax_1" + }, + { + "type": "build", + "name": "espressif_addax_1" + } + ] + }, + { + "name": "espressif_c3_devkitc", + "steps": [ + { + "type": "configure", + "name": "espressif_c3_devkitc" + }, + { + "type": "build", + "name": "espressif_c3_devkitc" + } + ] + }, + { + "name": "espressif_c6_devkitc", + "steps": [ + { + "type": "configure", + "name": "espressif_c6_devkitc" + }, + { + "type": "build", + "name": "espressif_c6_devkitc" + } + ] + }, + { + "name": "espressif_kaluga_1", + "steps": [ + { + "type": "configure", + "name": "espressif_kaluga_1" + }, + { + "type": "build", + "name": "espressif_kaluga_1" + } + ] + }, + { + "name": "espressif_p4_function_ev", + "steps": [ + { + "type": "configure", + "name": "espressif_p4_function_ev" + }, + { + "type": "build", + "name": "espressif_p4_function_ev" + } + ] + }, + { + "name": "espressif_s2_devkitc", + "steps": [ + { + "type": "configure", + "name": "espressif_s2_devkitc" + }, + { + "type": "build", + "name": "espressif_s2_devkitc" + } + ] + }, + { + "name": "espressif_s3_devkitc", + "steps": [ + { + "type": "configure", + "name": "espressif_s3_devkitc" + }, + { + "type": "build", + "name": "espressif_s3_devkitc" + } + ] + }, + { + "name": "espressif_s3_devkitm", + "steps": [ + { + "type": "configure", + "name": "espressif_s3_devkitm" + }, + { + "type": "build", + "name": "espressif_s3_devkitm" + } + ] + }, + { + "name": "espressif_saola_1", + "steps": [ + { + "type": "configure", + "name": "espressif_saola_1" + }, + { + "type": "build", + "name": "espressif_saola_1" + } + ] + }, + { + "name": "f1c100s", + "steps": [ + { + "type": "configure", + "name": "f1c100s" + }, + { + "type": "build", + "name": "f1c100s" + } + ] + }, + { + "name": "fomu", + "steps": [ + { + "type": "configure", + "name": "fomu" + }, + { + "type": "build", + "name": "fomu" + } + ] + }, + { + "name": "sipeed_longan_nano", + "steps": [ + { + "type": "configure", + "name": "sipeed_longan_nano" + }, + { + "type": "build", + "name": "sipeed_longan_nano" + } + ] + }, + { + "name": "metro_m7_1011", + "steps": [ + { + "type": "configure", + "name": "metro_m7_1011" + }, + { + "type": "build", + "name": "metro_m7_1011" + } + ] + }, + { + "name": "metro_m7_1011_sd", + "steps": [ + { + "type": "configure", + "name": "metro_m7_1011_sd" + }, + { + "type": "build", + "name": "metro_m7_1011_sd" + } + ] + }, + { + "name": "mimxrt1010_evk", + "steps": [ + { + "type": "configure", + "name": "mimxrt1010_evk" + }, + { + "type": "build", + "name": "mimxrt1010_evk" + } + ] + }, + { + "name": "mimxrt1015_evk", + "steps": [ + { + "type": "configure", + "name": "mimxrt1015_evk" + }, + { + "type": "build", + "name": "mimxrt1015_evk" + } + ] + }, + { + "name": "mimxrt1020_evk", + "steps": [ + { + "type": "configure", + "name": "mimxrt1020_evk" + }, + { + "type": "build", + "name": "mimxrt1020_evk" + } + ] + }, + { + "name": "mimxrt1024_evk", + "steps": [ + { + "type": "configure", + "name": "mimxrt1024_evk" + }, + { + "type": "build", + "name": "mimxrt1024_evk" + } + ] + }, + { + "name": "mimxrt1050_evkb", + "steps": [ + { + "type": "configure", + "name": "mimxrt1050_evkb" + }, + { + "type": "build", + "name": "mimxrt1050_evkb" + } + ] + }, + { + "name": "mimxrt1060_evk", + "steps": [ + { + "type": "configure", + "name": "mimxrt1060_evk" + }, + { + "type": "build", + "name": "mimxrt1060_evk" + } + ] + }, + { + "name": "mimxrt1064_evk", + "steps": [ + { + "type": "configure", + "name": "mimxrt1064_evk" + }, + { + "type": "build", + "name": "mimxrt1064_evk" + } + ] + }, + { + "name": "mimxrt1170_evkb", + "steps": [ + { + "type": "configure", + "name": "mimxrt1170_evkb" + }, + { + "type": "build", + "name": "mimxrt1170_evkb" + } + ] + }, + { + "name": "teensy_40", + "steps": [ + { + "type": "configure", + "name": "teensy_40" + }, + { + "type": "build", + "name": "teensy_40" + } + ] + }, + { + "name": "teensy_41", + "steps": [ + { + "type": "configure", + "name": "teensy_41" + }, + { + "type": "build", + "name": "teensy_41" + } + ] + }, + { + "name": "frdm_k64f", + "steps": [ + { + "type": "configure", + "name": "frdm_k64f" + }, + { + "type": "build", + "name": "frdm_k64f" + } + ] + }, + { + "name": "teensy_35", + "steps": [ + { + "type": "configure", + "name": "teensy_35" + }, + { + "type": "build", + "name": "teensy_35" + } + ] + }, + { + "name": "frdm_k32l2a4s", + "steps": [ + { + "type": "configure", + "name": "frdm_k32l2a4s" + }, + { + "type": "build", + "name": "frdm_k32l2a4s" + } + ] + }, + { + "name": "frdm_k32l2b", + "steps": [ + { + "type": "configure", + "name": "frdm_k32l2b" + }, + { + "type": "build", + "name": "frdm_k32l2b" + } + ] + }, + { + "name": "kuiic", + "steps": [ + { + "type": "configure", + "name": "kuiic" + }, + { + "type": "build", + "name": "kuiic" + } + ] + }, + { + "name": "frdm_kl25z", + "steps": [ + { + "type": "configure", + "name": "frdm_kl25z" + }, + { + "type": "build", + "name": "frdm_kl25z" + } + ] + }, + { + "name": "lpcxpresso11u37", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso11u37" + }, + { + "type": "build", + "name": "lpcxpresso11u37" + } + ] + }, + { + "name": "lpcxpresso11u68", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso11u68" + }, + { + "type": "build", + "name": "lpcxpresso11u68" + } + ] + }, + { + "name": "lpcxpresso1347", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso1347" + }, + { + "type": "build", + "name": "lpcxpresso1347" + } + ] + }, + { + "name": "lpcxpresso1549", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso1549" + }, + { + "type": "build", + "name": "lpcxpresso1549" + } + ] + }, + { + "name": "lpcxpresso1769", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso1769" + }, + { + "type": "build", + "name": "lpcxpresso1769" + } + ] + }, + { + "name": "mbed1768", + "steps": [ + { + "type": "configure", + "name": "mbed1768" + }, + { + "type": "build", + "name": "mbed1768" + } + ] + }, + { + "name": "lpcxpresso18s37", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso18s37" + }, + { + "type": "build", + "name": "lpcxpresso18s37" + } + ] + }, + { + "name": "mcb1800", + "steps": [ + { + "type": "configure", + "name": "mcb1800" + }, + { + "type": "build", + "name": "mcb1800" + } + ] + }, + { + "name": "ea4088_quickstart", + "steps": [ + { + "type": "configure", + "name": "ea4088_quickstart" + }, + { + "type": "build", + "name": "ea4088_quickstart" + } + ] + }, + { + "name": "ea4357", + "steps": [ + { + "type": "configure", + "name": "ea4357" + }, + { + "type": "build", + "name": "ea4357" + } + ] + }, + { + "name": "lpcxpresso43s67", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso43s67" + }, + { + "type": "build", + "name": "lpcxpresso43s67" + } + ] + }, + { + "name": "lpcxpresso51u68", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso51u68" + }, + { + "type": "build", + "name": "lpcxpresso51u68" + } + ] + }, + { + "name": "lpcxpresso54114", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso54114" + }, + { + "type": "build", + "name": "lpcxpresso54114" + } + ] + }, + { + "name": "lpcxpresso54608", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso54608" + }, + { + "type": "build", + "name": "lpcxpresso54608" + } + ] + }, + { + "name": "lpcxpresso54628", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso54628" + }, + { + "type": "build", + "name": "lpcxpresso54628" + } + ] + }, + { + "name": "double_m33_express", + "steps": [ + { + "type": "configure", + "name": "double_m33_express" + }, + { + "type": "build", + "name": "double_m33_express" + } + ] + }, + { + "name": "lpcxpresso55s28", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso55s28" + }, + { + "type": "build", + "name": "lpcxpresso55s28" + } + ] + }, + { + "name": "lpcxpresso55s69", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso55s69" + }, + { + "type": "build", + "name": "lpcxpresso55s69" + } + ] + }, + { + "name": "mcu_link", + "steps": [ + { + "type": "configure", + "name": "mcu_link" + }, + { + "type": "build", + "name": "mcu_link" + } + ] + }, + { + "name": "max32650evkit", + "steps": [ + { + "type": "configure", + "name": "max32650evkit" + }, + { + "type": "build", + "name": "max32650evkit" + } + ] + }, + { + "name": "max32650fthr", + "steps": [ + { + "type": "configure", + "name": "max32650fthr" + }, + { + "type": "build", + "name": "max32650fthr" + } + ] + }, + { + "name": "max32651evkit", + "steps": [ + { + "type": "configure", + "name": "max32651evkit" + }, + { + "type": "build", + "name": "max32651evkit" + } + ] + }, + { + "name": "max32666evkit", + "steps": [ + { + "type": "configure", + "name": "max32666evkit" + }, + { + "type": "build", + "name": "max32666evkit" + } + ] + }, + { + "name": "max32666fthr", + "steps": [ + { + "type": "configure", + "name": "max32666fthr" + }, + { + "type": "build", + "name": "max32666fthr" + } + ] + }, + { + "name": "apard32690", + "steps": [ + { + "type": "configure", + "name": "apard32690" + }, + { + "type": "build", + "name": "apard32690" + } + ] + }, + { + "name": "max32690evkit", + "steps": [ + { + "type": "configure", + "name": "max32690evkit" + }, + { + "type": "build", + "name": "max32690evkit" + } + ] + }, + { + "name": "max78002evkit", + "steps": [ + { + "type": "configure", + "name": "max78002evkit" + }, + { + "type": "build", + "name": "max78002evkit" + } + ] + }, + { + "name": "frdm_mcxa153", + "steps": [ + { + "type": "configure", + "name": "frdm_mcxa153" + }, + { + "type": "build", + "name": "frdm_mcxa153" + } + ] + }, + { + "name": "frdm_mcxn947", + "steps": [ + { + "type": "configure", + "name": "frdm_mcxn947" + }, + { + "type": "build", + "name": "frdm_mcxn947" + } + ] + }, + { + "name": "mcxn947brk", + "steps": [ + { + "type": "configure", + "name": "mcxn947brk" + }, + { + "type": "build", + "name": "mcxn947brk" + } + ] + }, + { + "name": "mm32f327x_mb39", + "steps": [ + { + "type": "configure", + "name": "mm32f327x_mb39" + }, + { + "type": "build", + "name": "mm32f327x_mb39" + } + ] + }, + { + "name": "mm32f327x_pitaya_lite", + "steps": [ + { + "type": "configure", + "name": "mm32f327x_pitaya_lite" + }, + { + "type": "build", + "name": "mm32f327x_pitaya_lite" + } + ] + }, + { + "name": "msp_exp430f5529lp", + "steps": [ + { + "type": "configure", + "name": "msp_exp430f5529lp" + }, + { + "type": "build", + "name": "msp_exp430f5529lp" + } + ] + }, + { + "name": "msp_exp432e401y", + "steps": [ + { + "type": "configure", + "name": "msp_exp432e401y" + }, + { + "type": "build", + "name": "msp_exp432e401y" + } + ] + }, + { + "name": "adafruit_clue", + "steps": [ + { + "type": "configure", + "name": "adafruit_clue" + }, + { + "type": "build", + "name": "adafruit_clue" + } + ] + }, + { + "name": "arduino_nano33_ble", + "steps": [ + { + "type": "configure", + "name": "arduino_nano33_ble" + }, + { + "type": "build", + "name": "arduino_nano33_ble" + } + ] + }, + { + "name": "circuitplayground_bluefruit", + "steps": [ + { + "type": "configure", + "name": "circuitplayground_bluefruit" + }, + { + "type": "build", + "name": "circuitplayground_bluefruit" + } + ] + }, + { + "name": "feather_nrf52840_express", + "steps": [ + { + "type": "configure", + "name": "feather_nrf52840_express" + }, + { + "type": "build", + "name": "feather_nrf52840_express" + } + ] + }, + { + "name": "feather_nrf52840_sense", + "steps": [ + { + "type": "configure", + "name": "feather_nrf52840_sense" + }, + { + "type": "build", + "name": "feather_nrf52840_sense" + } + ] + }, + { + "name": "itsybitsy_nrf52840", + "steps": [ + { + "type": "configure", + "name": "itsybitsy_nrf52840" + }, + { + "type": "build", + "name": "itsybitsy_nrf52840" + } + ] + }, + { + "name": "pca10056", + "steps": [ + { + "type": "configure", + "name": "pca10056" + }, + { + "type": "build", + "name": "pca10056" + } + ] + }, + { + "name": "pca10059", + "steps": [ + { + "type": "configure", + "name": "pca10059" + }, + { + "type": "build", + "name": "pca10059" + } + ] + }, + { + "name": "pca10095", + "steps": [ + { + "type": "configure", + "name": "pca10095" + }, + { + "type": "build", + "name": "pca10095" + } + ] + }, + { + "name": "pca10100", + "steps": [ + { + "type": "configure", + "name": "pca10100" + }, + { + "type": "build", + "name": "pca10100" + } + ] + }, + { + "name": "portenta_c33", + "steps": [ + { + "type": "configure", + "name": "portenta_c33" + }, + { + "type": "build", + "name": "portenta_c33" + } + ] + }, + { + "name": "ra2a1_ek", + "steps": [ + { + "type": "configure", + "name": "ra2a1_ek" + }, + { + "type": "build", + "name": "ra2a1_ek" + } + ] + }, + { + "name": "ra4m1_ek", + "steps": [ + { + "type": "configure", + "name": "ra4m1_ek" + }, + { + "type": "build", + "name": "ra4m1_ek" + } + ] + }, + { + "name": "ra4m3_ek", + "steps": [ + { + "type": "configure", + "name": "ra4m3_ek" + }, + { + "type": "build", + "name": "ra4m3_ek" + } + ] + }, + { + "name": "ra6m1_ek", + "steps": [ + { + "type": "configure", + "name": "ra6m1_ek" + }, + { + "type": "build", + "name": "ra6m1_ek" + } + ] + }, + { + "name": "ra6m5_ek", + "steps": [ + { + "type": "configure", + "name": "ra6m5_ek" + }, + { + "type": "build", + "name": "ra6m5_ek" + } + ] + }, + { + "name": "ra8m1_ek", + "steps": [ + { + "type": "configure", + "name": "ra8m1_ek" + }, + { + "type": "build", + "name": "ra8m1_ek" + } + ] + }, + { + "name": "uno_r4", + "steps": [ + { + "type": "configure", + "name": "uno_r4" + }, + { + "type": "build", + "name": "uno_r4" + } + ] + }, + { + "name": "feather_rp2040_max3421", + "steps": [ + { + "type": "configure", + "name": "feather_rp2040_max3421" + }, + { + "type": "build", + "name": "feather_rp2040_max3421" + } + ] + }, + { + "name": "pico_sdk", + "steps": [ + { + "type": "configure", + "name": "pico_sdk" + }, + { + "type": "build", + "name": "pico_sdk" + } + ] + }, + { + "name": "raspberry_pi_pico", + "steps": [ + { + "type": "configure", + "name": "raspberry_pi_pico" + }, + { + "type": "build", + "name": "raspberry_pi_pico" + } + ] + }, + { + "name": "raspberry_pi_pico2", + "steps": [ + { + "type": "configure", + "name": "raspberry_pi_pico2" + }, + { + "type": "build", + "name": "raspberry_pi_pico2" + } + ] + }, + { + "name": "cynthion_d11", + "steps": [ + { + "type": "configure", + "name": "cynthion_d11" + }, + { + "type": "build", + "name": "cynthion_d11" + } + ] + }, + { + "name": "samd11_xplained", + "steps": [ + { + "type": "configure", + "name": "samd11_xplained" + }, + { + "type": "build", + "name": "samd11_xplained" + } + ] + }, + { + "name": "atsamd21_xpro", + "steps": [ + { + "type": "configure", + "name": "atsamd21_xpro" + }, + { + "type": "build", + "name": "atsamd21_xpro" + } + ] + }, + { + "name": "circuitplayground_express", + "steps": [ + { + "type": "configure", + "name": "circuitplayground_express" + }, + { + "type": "build", + "name": "circuitplayground_express" + } + ] + }, + { + "name": "curiosity_nano", + "steps": [ + { + "type": "configure", + "name": "curiosity_nano" + }, + { + "type": "build", + "name": "curiosity_nano" + } + ] + }, + { + "name": "cynthion_d21", + "steps": [ + { + "type": "configure", + "name": "cynthion_d21" + }, + { + "type": "build", + "name": "cynthion_d21" + } + ] + }, + { + "name": "feather_m0_express", + "steps": [ + { + "type": "configure", + "name": "feather_m0_express" + }, + { + "type": "build", + "name": "feather_m0_express" + } + ] + }, + { + "name": "itsybitsy_m0", + "steps": [ + { + "type": "configure", + "name": "itsybitsy_m0" + }, + { + "type": "build", + "name": "itsybitsy_m0" + } + ] + }, + { + "name": "metro_m0_express", + "steps": [ + { + "type": "configure", + "name": "metro_m0_express" + }, + { + "type": "build", + "name": "metro_m0_express" + } + ] + }, + { + "name": "qtpy", + "steps": [ + { + "type": "configure", + "name": "qtpy" + }, + { + "type": "build", + "name": "qtpy" + } + ] + }, + { + "name": "seeeduino_xiao", + "steps": [ + { + "type": "configure", + "name": "seeeduino_xiao" + }, + { + "type": "build", + "name": "seeeduino_xiao" + } + ] + }, + { + "name": "sparkfun_samd21_mini_usb", + "steps": [ + { + "type": "configure", + "name": "sparkfun_samd21_mini_usb" + }, + { + "type": "build", + "name": "sparkfun_samd21_mini_usb" + } + ] + }, + { + "name": "trinket_m0", + "steps": [ + { + "type": "configure", + "name": "trinket_m0" + }, + { + "type": "build", + "name": "trinket_m0" + } + ] + }, + { + "name": "d5035_01", + "steps": [ + { + "type": "configure", + "name": "d5035_01" + }, + { + "type": "build", + "name": "d5035_01" + } + ] + }, + { + "name": "feather_m4_express", + "steps": [ + { + "type": "configure", + "name": "feather_m4_express" + }, + { + "type": "build", + "name": "feather_m4_express" + } + ] + }, + { + "name": "itsybitsy_m4", + "steps": [ + { + "type": "configure", + "name": "itsybitsy_m4" + }, + { + "type": "build", + "name": "itsybitsy_m4" + } + ] + }, + { + "name": "metro_m4_express", + "steps": [ + { + "type": "configure", + "name": "metro_m4_express" + }, + { + "type": "build", + "name": "metro_m4_express" + } + ] + }, + { + "name": "pybadge", + "steps": [ + { + "type": "configure", + "name": "pybadge" + }, + { + "type": "build", + "name": "pybadge" + } + ] + }, + { + "name": "pyportal", + "steps": [ + { + "type": "configure", + "name": "pyportal" + }, + { + "type": "build", + "name": "pyportal" + } + ] + }, + { + "name": "same54_xplained", + "steps": [ + { + "type": "configure", + "name": "same54_xplained" + }, + { + "type": "build", + "name": "same54_xplained" + } + ] + }, + { + "name": "samg55_xplained", + "steps": [ + { + "type": "configure", + "name": "samg55_xplained" + }, + { + "type": "build", + "name": "samg55_xplained" + } + ] + }, + { + "name": "atsaml21_xpro", + "steps": [ + { + "type": "configure", + "name": "atsaml21_xpro" + }, + { + "type": "build", + "name": "atsaml21_xpro" + } + ] + }, + { + "name": "saml22_feather", + "steps": [ + { + "type": "configure", + "name": "saml22_feather" + }, + { + "type": "build", + "name": "saml22_feather" + } + ] + }, + { + "name": "sensorwatch_m0", + "steps": [ + { + "type": "configure", + "name": "sensorwatch_m0" + }, + { + "type": "build", + "name": "sensorwatch_m0" + } + ] + }, + { + "name": "stm32c071nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32c071nucleo" + }, + { + "type": "build", + "name": "stm32c071nucleo" + } + ] + }, + { + "name": "stm32f070rbnucleo", + "steps": [ + { + "type": "configure", + "name": "stm32f070rbnucleo" + }, + { + "type": "build", + "name": "stm32f070rbnucleo" + } + ] + }, + { + "name": "stm32f072disco", + "steps": [ + { + "type": "configure", + "name": "stm32f072disco" + }, + { + "type": "build", + "name": "stm32f072disco" + } + ] + }, + { + "name": "stm32f072eval", + "steps": [ + { + "type": "configure", + "name": "stm32f072eval" + }, + { + "type": "build", + "name": "stm32f072eval" + } + ] + }, + { + "name": "stm32f103ze_iar", + "steps": [ + { + "type": "configure", + "name": "stm32f103ze_iar" + }, + { + "type": "build", + "name": "stm32f103ze_iar" + } + ] + }, + { + "name": "stm32f103_bluepill", + "steps": [ + { + "type": "configure", + "name": "stm32f103_bluepill" + }, + { + "type": "build", + "name": "stm32f103_bluepill" + } + ] + }, + { + "name": "stm32f103_mini_2", + "steps": [ + { + "type": "configure", + "name": "stm32f103_mini_2" + }, + { + "type": "build", + "name": "stm32f103_mini_2" + } + ] + }, + { + "name": "stm32f207nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32f207nucleo" + }, + { + "type": "build", + "name": "stm32f207nucleo" + } + ] + }, + { + "name": "stm32f303disco", + "steps": [ + { + "type": "configure", + "name": "stm32f303disco" + }, + { + "type": "build", + "name": "stm32f303disco" + } + ] + }, + { + "name": "feather_stm32f405", + "steps": [ + { + "type": "configure", + "name": "feather_stm32f405" + }, + { + "type": "build", + "name": "feather_stm32f405" + } + ] + }, + { + "name": "pyboardv11", + "steps": [ + { + "type": "configure", + "name": "pyboardv11" + }, + { + "type": "build", + "name": "pyboardv11" + } + ] + }, + { + "name": "stm32f401blackpill", + "steps": [ + { + "type": "configure", + "name": "stm32f401blackpill" + }, + { + "type": "build", + "name": "stm32f401blackpill" + } + ] + }, + { + "name": "stm32f407blackvet", + "steps": [ + { + "type": "configure", + "name": "stm32f407blackvet" + }, + { + "type": "build", + "name": "stm32f407blackvet" + } + ] + }, + { + "name": "stm32f407disco", + "steps": [ + { + "type": "configure", + "name": "stm32f407disco" + }, + { + "type": "build", + "name": "stm32f407disco" + } + ] + }, + { + "name": "stm32f411blackpill", + "steps": [ + { + "type": "configure", + "name": "stm32f411blackpill" + }, + { + "type": "build", + "name": "stm32f411blackpill" + } + ] + }, + { + "name": "stm32f411disco", + "steps": [ + { + "type": "configure", + "name": "stm32f411disco" + }, + { + "type": "build", + "name": "stm32f411disco" + } + ] + }, + { + "name": "stm32f412disco", + "steps": [ + { + "type": "configure", + "name": "stm32f412disco" + }, + { + "type": "build", + "name": "stm32f412disco" + } + ] + }, + { + "name": "stm32f412nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32f412nucleo" + }, + { + "type": "build", + "name": "stm32f412nucleo" + } + ] + }, + { + "name": "stm32f439nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32f439nucleo" + }, + { + "type": "build", + "name": "stm32f439nucleo" + } + ] + }, + { + "name": "stlinkv3mini", + "steps": [ + { + "type": "configure", + "name": "stlinkv3mini" + }, + { + "type": "build", + "name": "stlinkv3mini" + } + ] + }, + { + "name": "stm32f723disco", + "steps": [ + { + "type": "configure", + "name": "stm32f723disco" + }, + { + "type": "build", + "name": "stm32f723disco" + } + ] + }, + { + "name": "stm32f746disco", + "steps": [ + { + "type": "configure", + "name": "stm32f746disco" + }, + { + "type": "build", + "name": "stm32f746disco" + } + ] + }, + { + "name": "stm32f746nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32f746nucleo" + }, + { + "type": "build", + "name": "stm32f746nucleo" + } + ] + }, + { + "name": "stm32f767nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32f767nucleo" + }, + { + "type": "build", + "name": "stm32f767nucleo" + } + ] + }, + { + "name": "stm32f769disco", + "steps": [ + { + "type": "configure", + "name": "stm32f769disco" + }, + { + "type": "build", + "name": "stm32f769disco" + } + ] + }, + { + "name": "stm32g0b1nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32g0b1nucleo" + }, + { + "type": "build", + "name": "stm32g0b1nucleo" + } + ] + }, + { + "name": "b_g474e_dpow1", + "steps": [ + { + "type": "configure", + "name": "b_g474e_dpow1" + }, + { + "type": "build", + "name": "b_g474e_dpow1" + } + ] + }, + { + "name": "stm32g474nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32g474nucleo" + }, + { + "type": "build", + "name": "stm32g474nucleo" + } + ] + }, + { + "name": "stm32g491nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32g491nucleo" + }, + { + "type": "build", + "name": "stm32g491nucleo" + } + ] + }, + { + "name": "stm32h503nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32h503nucleo" + }, + { + "type": "build", + "name": "stm32h503nucleo" + } + ] + }, + { + "name": "stm32h563nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32h563nucleo" + }, + { + "type": "build", + "name": "stm32h563nucleo" + } + ] + }, + { + "name": "stm32h573i_dk", + "steps": [ + { + "type": "configure", + "name": "stm32h573i_dk" + }, + { + "type": "build", + "name": "stm32h573i_dk" + } + ] + }, + { + "name": "daisyseed", + "steps": [ + { + "type": "configure", + "name": "daisyseed" + }, + { + "type": "build", + "name": "daisyseed" + } + ] + }, + { + "name": "stm32h723nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32h723nucleo" + }, + { + "type": "build", + "name": "stm32h723nucleo" + } + ] + }, + { + "name": "stm32h743eval", + "steps": [ + { + "type": "configure", + "name": "stm32h743eval" + }, + { + "type": "build", + "name": "stm32h743eval" + } + ] + }, + { + "name": "stm32h743nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32h743nucleo" + }, + { + "type": "build", + "name": "stm32h743nucleo" + } + ] + }, + { + "name": "stm32h745disco", + "steps": [ + { + "type": "configure", + "name": "stm32h745disco" + }, + { + "type": "build", + "name": "stm32h745disco" + } + ] + }, + { + "name": "stm32h750bdk", + "steps": [ + { + "type": "configure", + "name": "stm32h750bdk" + }, + { + "type": "build", + "name": "stm32h750bdk" + } + ] + }, + { + "name": "stm32h750_weact", + "steps": [ + { + "type": "configure", + "name": "stm32h750_weact" + }, + { + "type": "build", + "name": "stm32h750_weact" + } + ] + }, + { + "name": "waveshare_openh743i", + "steps": [ + { + "type": "configure", + "name": "waveshare_openh743i" + }, + { + "type": "build", + "name": "waveshare_openh743i" + } + ] + }, + { + "name": "stm32h7s3nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32h7s3nucleo" + }, + { + "type": "build", + "name": "stm32h7s3nucleo" + } + ] + }, + { + "name": "stm32l052dap52", + "steps": [ + { + "type": "configure", + "name": "stm32l052dap52" + }, + { + "type": "build", + "name": "stm32l052dap52" + } + ] + }, + { + "name": "stm32l0538disco", + "steps": [ + { + "type": "configure", + "name": "stm32l0538disco" + }, + { + "type": "build", + "name": "stm32l0538disco" + } + ] + }, + { + "name": "stm32l412nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32l412nucleo" + }, + { + "type": "build", + "name": "stm32l412nucleo" + } + ] + }, + { + "name": "stm32l476disco", + "steps": [ + { + "type": "configure", + "name": "stm32l476disco" + }, + { + "type": "build", + "name": "stm32l476disco" + } + ] + }, + { + "name": "stm32l4p5nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32l4p5nucleo" + }, + { + "type": "build", + "name": "stm32l4p5nucleo" + } + ] + }, + { + "name": "stm32l4r5nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32l4r5nucleo" + }, + { + "type": "build", + "name": "stm32l4r5nucleo" + } + ] + }, + { + "name": "b_u585i_iot2a", + "steps": [ + { + "type": "configure", + "name": "b_u585i_iot2a" + }, + { + "type": "build", + "name": "b_u585i_iot2a" + } + ] + }, + { + "name": "stm32u545nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32u545nucleo" + }, + { + "type": "build", + "name": "stm32u545nucleo" + } + ] + }, + { + "name": "stm32u575eval", + "steps": [ + { + "type": "configure", + "name": "stm32u575eval" + }, + { + "type": "build", + "name": "stm32u575eval" + } + ] + }, + { + "name": "stm32u575nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32u575nucleo" + }, + { + "type": "build", + "name": "stm32u575nucleo" + } + ] + }, + { + "name": "stm32u5a5nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32u5a5nucleo" + }, + { + "type": "build", + "name": "stm32u5a5nucleo" + } + ] + }, + { + "name": "stm32wb55nucleo", + "steps": [ + { + "type": "configure", + "name": "stm32wb55nucleo" + }, + { + "type": "build", + "name": "stm32wb55nucleo" + } + ] + }, + { + "name": "ek_tm4c123gxl", + "steps": [ + { + "type": "configure", + "name": "ek_tm4c123gxl" + }, + { + "type": "build", + "name": "ek_tm4c123gxl" + } + ] + }, + { + "name": "xmc4500_relax", + "steps": [ + { + "type": "configure", + "name": "xmc4500_relax" + }, + { + "type": "build", + "name": "xmc4500_relax" + } + ] + }, + { + "name": "xmc4700_relax", + "steps": [ + { + "type": "configure", + "name": "xmc4700_relax" + }, + { + "type": "build", + "name": "xmc4700_relax" + } + ] + } + ] +} diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 04d537376..409fb9c75 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -399,7 +399,11 @@ endfunction() # Add flash jlink target function(family_flash_jlink TARGET) if (NOT DEFINED JLINKEXE) - set(JLINKEXE JLinkExe) + if(CMAKE_HOST_WIN32) + set(JLINKEXE JLink.exe) + else() + set(JLINKEXE JLinkExe) + endif() endif () if (NOT DEFINED JLINK_IF) diff --git a/tools/gen_presets.py b/tools/gen_presets.py new file mode 100755 index 000000000..98b1a7d46 --- /dev/null +++ b/tools/gen_presets.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +import os +import json + + +def main(): + board_list = [] + + # Find all board.cmake files + for root, dirs, files in os.walk("hw/bsp"): + for file in files: + if file == "board.cmake": + board_list.append(os.path.basename(root)) + + print('Generating presets for the following boards:') + print(board_list) + + # Generate the presets + presets = {} + presets['version'] = 6 + + # Configure presets + presets['configurePresets'] = [ + {"name": "default", + "hidden": True, + "description": r"Configure preset for the ${presetName} board", + "generator": "Ninja", + "binaryDir": r"${sourceDir}/build/${presetName}", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "BOARD": r"${presetName}" + } + }] + + presets['configurePresets'].extend( + [{'name': board, 'inherits': 'default'} for board in board_list] + ) + + # Build presets + # no inheritance since 'name' doesn't support macro expansion + presets['buildPresets'] = [ + { + 'name': board, + 'description': "Build preset for the " + board + " board", + 'configurePreset': board + } + for board in board_list + ] + + # Workflow presets + presets['workflowPresets'] = [ + { + "name": board, + "steps": [ + { + "type": "configure", + "name": board + }, + { + "type": "build", + "name": board + } + ] + } + for board in board_list + ] + + with open("hw/bsp/BoardPresets.json", "w") as f: + f.write('{}\n'.format(json.dumps(presets, indent=2))) + + # Generate presets for examples + presets = { + "version": 6, + "include": [ + "../../../hw/bsp/BoardPresets.json" + ] + } + + example_list = [] + for root, dirs, files in os.walk("examples"): + for file in files: + if file == "CMakeLists.txt": + with open(os.path.join(root, 'CMakePresets.json'), 'w') as f: + f.write('{}\n'.format(json.dumps(presets, indent=2))) + example_list.append(os.path.basename(root)) + + print('Generating presets for the following examples:') + print(example_list) + +if __name__ == "__main__": + main() From 1208f88b6ecc899bfac908aaf90a8be0997efb5d Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 9 Feb 2025 18:40:30 +0100 Subject: [PATCH 36/87] Sort list (bettter for Clion) Signed-off-by: HiFiPhile --- hw/bsp/BoardPresets.json | 3394 +++++++++++++++++++------------------- tools/gen_presets.py | 70 +- 2 files changed, 1738 insertions(+), 1726 deletions(-) diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json index c295efbdd..fee8f2c97 100644 --- a/hw/bsp/BoardPresets.json +++ b/hw/bsp/BoardPresets.json @@ -5,23 +5,59 @@ "name": "default", "hidden": true, "description": "Configure preset for the ${presetName} board", - "generator": "Ninja", + "generator": "Ninja Multi-Config", "binaryDir": "${sourceDir}/build/${presetName}", "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_DEFAULT_BUILD_TYPE": "RelWithDebInfo", "BOARD": "${presetName}" } }, { - "name": "raspberrypi_zero", + "name": "adafruit_clue", "inherits": "default" }, { - "name": "raspberrypi_cm4", + "name": "adafruit_feather_esp32_v2", "inherits": "default" }, { - "name": "raspberrypi_zero2", + "name": "adafruit_feather_esp32s2", + "inherits": "default" + }, + { + "name": "adafruit_feather_esp32s3", + "inherits": "default" + }, + { + "name": "adafruit_magtag_29gray", + "inherits": "default" + }, + { + "name": "adafruit_metro_esp32s2", + "inherits": "default" + }, + { + "name": "apard32690", + "inherits": "default" + }, + { + "name": "arduino_nano33_ble", + "inherits": "default" + }, + { + "name": "atsamd21_xpro", + "inherits": "default" + }, + { + "name": "atsaml21_xpro", + "inherits": "default" + }, + { + "name": "b_g474e_dpow1", + "inherits": "default" + }, + { + "name": "b_u585i_iot2a", "inherits": "default" }, { @@ -37,11 +73,31 @@ "inherits": "default" }, { - "name": "nanoch32v203", + "name": "ch32v307v_r1_1v0", "inherits": "default" }, { - "name": "ch32v307v_r1_1v0", + "name": "circuitplayground_bluefruit", + "inherits": "default" + }, + { + "name": "circuitplayground_express", + "inherits": "default" + }, + { + "name": "curiosity_nano", + "inherits": "default" + }, + { + "name": "cynthion_d11", + "inherits": "default" + }, + { + "name": "cynthion_d21", + "inherits": "default" + }, + { + "name": "d5035_01", "inherits": "default" }, { @@ -53,23 +109,23 @@ "inherits": "default" }, { - "name": "adafruit_feather_esp32s2", + "name": "daisyseed", "inherits": "default" }, { - "name": "adafruit_feather_esp32s3", + "name": "double_m33_express", "inherits": "default" }, { - "name": "adafruit_feather_esp32_v2", + "name": "ea4088_quickstart", "inherits": "default" }, { - "name": "adafruit_magtag_29gray", + "name": "ea4357", "inherits": "default" }, { - "name": "adafruit_metro_esp32s2", + "name": "ek_tm4c123gxl", "inherits": "default" }, { @@ -112,12 +168,176 @@ "name": "f1c100s", "inherits": "default" }, + { + "name": "feather_m0_express", + "inherits": "default" + }, + { + "name": "feather_m4_express", + "inherits": "default" + }, + { + "name": "feather_nrf52840_express", + "inherits": "default" + }, + { + "name": "feather_nrf52840_sense", + "inherits": "default" + }, + { + "name": "feather_rp2040_max3421", + "inherits": "default" + }, + { + "name": "feather_stm32f405", + "inherits": "default" + }, { "name": "fomu", "inherits": "default" }, { - "name": "sipeed_longan_nano", + "name": "frdm_k32l2a4s", + "inherits": "default" + }, + { + "name": "frdm_k32l2b", + "inherits": "default" + }, + { + "name": "frdm_k64f", + "inherits": "default" + }, + { + "name": "frdm_kl25z", + "inherits": "default" + }, + { + "name": "frdm_mcxa153", + "inherits": "default" + }, + { + "name": "frdm_mcxn947", + "inherits": "default" + }, + { + "name": "itsybitsy_m0", + "inherits": "default" + }, + { + "name": "itsybitsy_m4", + "inherits": "default" + }, + { + "name": "itsybitsy_nrf52840", + "inherits": "default" + }, + { + "name": "kuiic", + "inherits": "default" + }, + { + "name": "lpcxpresso11u37", + "inherits": "default" + }, + { + "name": "lpcxpresso11u68", + "inherits": "default" + }, + { + "name": "lpcxpresso1347", + "inherits": "default" + }, + { + "name": "lpcxpresso1549", + "inherits": "default" + }, + { + "name": "lpcxpresso1769", + "inherits": "default" + }, + { + "name": "lpcxpresso18s37", + "inherits": "default" + }, + { + "name": "lpcxpresso43s67", + "inherits": "default" + }, + { + "name": "lpcxpresso51u68", + "inherits": "default" + }, + { + "name": "lpcxpresso54114", + "inherits": "default" + }, + { + "name": "lpcxpresso54608", + "inherits": "default" + }, + { + "name": "lpcxpresso54628", + "inherits": "default" + }, + { + "name": "lpcxpresso55s28", + "inherits": "default" + }, + { + "name": "lpcxpresso55s69", + "inherits": "default" + }, + { + "name": "max32650evkit", + "inherits": "default" + }, + { + "name": "max32650fthr", + "inherits": "default" + }, + { + "name": "max32651evkit", + "inherits": "default" + }, + { + "name": "max32666evkit", + "inherits": "default" + }, + { + "name": "max32666fthr", + "inherits": "default" + }, + { + "name": "max32690evkit", + "inherits": "default" + }, + { + "name": "max78002evkit", + "inherits": "default" + }, + { + "name": "mbed1768", + "inherits": "default" + }, + { + "name": "mcb1800", + "inherits": "default" + }, + { + "name": "mcu_link", + "inherits": "default" + }, + { + "name": "mcxn947brk", + "inherits": "default" + }, + { + "name": "metro_m0_express", + "inherits": "default" + }, + { + "name": "metro_m4_express", "inherits": "default" }, { @@ -160,158 +380,6 @@ "name": "mimxrt1170_evkb", "inherits": "default" }, - { - "name": "teensy_40", - "inherits": "default" - }, - { - "name": "teensy_41", - "inherits": "default" - }, - { - "name": "frdm_k64f", - "inherits": "default" - }, - { - "name": "teensy_35", - "inherits": "default" - }, - { - "name": "frdm_k32l2a4s", - "inherits": "default" - }, - { - "name": "frdm_k32l2b", - "inherits": "default" - }, - { - "name": "kuiic", - "inherits": "default" - }, - { - "name": "frdm_kl25z", - "inherits": "default" - }, - { - "name": "lpcxpresso11u37", - "inherits": "default" - }, - { - "name": "lpcxpresso11u68", - "inherits": "default" - }, - { - "name": "lpcxpresso1347", - "inherits": "default" - }, - { - "name": "lpcxpresso1549", - "inherits": "default" - }, - { - "name": "lpcxpresso1769", - "inherits": "default" - }, - { - "name": "mbed1768", - "inherits": "default" - }, - { - "name": "lpcxpresso18s37", - "inherits": "default" - }, - { - "name": "mcb1800", - "inherits": "default" - }, - { - "name": "ea4088_quickstart", - "inherits": "default" - }, - { - "name": "ea4357", - "inherits": "default" - }, - { - "name": "lpcxpresso43s67", - "inherits": "default" - }, - { - "name": "lpcxpresso51u68", - "inherits": "default" - }, - { - "name": "lpcxpresso54114", - "inherits": "default" - }, - { - "name": "lpcxpresso54608", - "inherits": "default" - }, - { - "name": "lpcxpresso54628", - "inherits": "default" - }, - { - "name": "double_m33_express", - "inherits": "default" - }, - { - "name": "lpcxpresso55s28", - "inherits": "default" - }, - { - "name": "lpcxpresso55s69", - "inherits": "default" - }, - { - "name": "mcu_link", - "inherits": "default" - }, - { - "name": "max32650evkit", - "inherits": "default" - }, - { - "name": "max32650fthr", - "inherits": "default" - }, - { - "name": "max32651evkit", - "inherits": "default" - }, - { - "name": "max32666evkit", - "inherits": "default" - }, - { - "name": "max32666fthr", - "inherits": "default" - }, - { - "name": "apard32690", - "inherits": "default" - }, - { - "name": "max32690evkit", - "inherits": "default" - }, - { - "name": "max78002evkit", - "inherits": "default" - }, - { - "name": "frdm_mcxa153", - "inherits": "default" - }, - { - "name": "frdm_mcxn947", - "inherits": "default" - }, - { - "name": "mcxn947brk", - "inherits": "default" - }, { "name": "mm32f327x_mb39", "inherits": "default" @@ -329,27 +397,7 @@ "inherits": "default" }, { - "name": "adafruit_clue", - "inherits": "default" - }, - { - "name": "arduino_nano33_ble", - "inherits": "default" - }, - { - "name": "circuitplayground_bluefruit", - "inherits": "default" - }, - { - "name": "feather_nrf52840_express", - "inherits": "default" - }, - { - "name": "feather_nrf52840_sense", - "inherits": "default" - }, - { - "name": "itsybitsy_nrf52840", + "name": "nanoch32v203", "inherits": "default" }, { @@ -368,10 +416,30 @@ "name": "pca10100", "inherits": "default" }, + { + "name": "pico_sdk", + "inherits": "default" + }, { "name": "portenta_c33", "inherits": "default" }, + { + "name": "pybadge", + "inherits": "default" + }, + { + "name": "pyboardv11", + "inherits": "default" + }, + { + "name": "pyportal", + "inherits": "default" + }, + { + "name": "qtpy", + "inherits": "default" + }, { "name": "ra2a1_ek", "inherits": "default" @@ -396,18 +464,6 @@ "name": "ra8m1_ek", "inherits": "default" }, - { - "name": "uno_r4", - "inherits": "default" - }, - { - "name": "feather_rp2040_max3421", - "inherits": "default" - }, - { - "name": "pico_sdk", - "inherits": "default" - }, { "name": "raspberry_pi_pico", "inherits": "default" @@ -417,81 +473,21 @@ "inherits": "default" }, { - "name": "cynthion_d11", + "name": "raspberrypi_cm4", + "inherits": "default" + }, + { + "name": "raspberrypi_zero", + "inherits": "default" + }, + { + "name": "raspberrypi_zero2", "inherits": "default" }, { "name": "samd11_xplained", "inherits": "default" }, - { - "name": "atsamd21_xpro", - "inherits": "default" - }, - { - "name": "circuitplayground_express", - "inherits": "default" - }, - { - "name": "curiosity_nano", - "inherits": "default" - }, - { - "name": "cynthion_d21", - "inherits": "default" - }, - { - "name": "feather_m0_express", - "inherits": "default" - }, - { - "name": "itsybitsy_m0", - "inherits": "default" - }, - { - "name": "metro_m0_express", - "inherits": "default" - }, - { - "name": "qtpy", - "inherits": "default" - }, - { - "name": "seeeduino_xiao", - "inherits": "default" - }, - { - "name": "sparkfun_samd21_mini_usb", - "inherits": "default" - }, - { - "name": "trinket_m0", - "inherits": "default" - }, - { - "name": "d5035_01", - "inherits": "default" - }, - { - "name": "feather_m4_express", - "inherits": "default" - }, - { - "name": "itsybitsy_m4", - "inherits": "default" - }, - { - "name": "metro_m4_express", - "inherits": "default" - }, - { - "name": "pybadge", - "inherits": "default" - }, - { - "name": "pyportal", - "inherits": "default" - }, { "name": "same54_xplained", "inherits": "default" @@ -500,18 +496,30 @@ "name": "samg55_xplained", "inherits": "default" }, - { - "name": "atsaml21_xpro", - "inherits": "default" - }, { "name": "saml22_feather", "inherits": "default" }, + { + "name": "seeeduino_xiao", + "inherits": "default" + }, { "name": "sensorwatch_m0", "inherits": "default" }, + { + "name": "sipeed_longan_nano", + "inherits": "default" + }, + { + "name": "sparkfun_samd21_mini_usb", + "inherits": "default" + }, + { + "name": "stlinkv3mini", + "inherits": "default" + }, { "name": "stm32c071nucleo", "inherits": "default" @@ -528,10 +536,6 @@ "name": "stm32f072eval", "inherits": "default" }, - { - "name": "stm32f103ze_iar", - "inherits": "default" - }, { "name": "stm32f103_bluepill", "inherits": "default" @@ -540,6 +544,10 @@ "name": "stm32f103_mini_2", "inherits": "default" }, + { + "name": "stm32f103ze_iar", + "inherits": "default" + }, { "name": "stm32f207nucleo", "inherits": "default" @@ -548,14 +556,6 @@ "name": "stm32f303disco", "inherits": "default" }, - { - "name": "feather_stm32f405", - "inherits": "default" - }, - { - "name": "pyboardv11", - "inherits": "default" - }, { "name": "stm32f401blackpill", "inherits": "default" @@ -588,10 +588,6 @@ "name": "stm32f439nucleo", "inherits": "default" }, - { - "name": "stlinkv3mini", - "inherits": "default" - }, { "name": "stm32f723disco", "inherits": "default" @@ -616,10 +612,6 @@ "name": "stm32g0b1nucleo", "inherits": "default" }, - { - "name": "b_g474e_dpow1", - "inherits": "default" - }, { "name": "stm32g474nucleo", "inherits": "default" @@ -640,10 +632,6 @@ "name": "stm32h573i_dk", "inherits": "default" }, - { - "name": "daisyseed", - "inherits": "default" - }, { "name": "stm32h723nucleo", "inherits": "default" @@ -660,16 +648,12 @@ "name": "stm32h745disco", "inherits": "default" }, - { - "name": "stm32h750bdk", - "inherits": "default" - }, { "name": "stm32h750_weact", "inherits": "default" }, { - "name": "waveshare_openh743i", + "name": "stm32h750bdk", "inherits": "default" }, { @@ -700,10 +684,6 @@ "name": "stm32l4r5nucleo", "inherits": "default" }, - { - "name": "b_u585i_iot2a", - "inherits": "default" - }, { "name": "stm32u545nucleo", "inherits": "default" @@ -725,7 +705,27 @@ "inherits": "default" }, { - "name": "ek_tm4c123gxl", + "name": "teensy_35", + "inherits": "default" + }, + { + "name": "teensy_40", + "inherits": "default" + }, + { + "name": "teensy_41", + "inherits": "default" + }, + { + "name": "trinket_m0", + "inherits": "default" + }, + { + "name": "uno_r4", + "inherits": "default" + }, + { + "name": "waveshare_openh743i", "inherits": "default" }, { @@ -739,19 +739,64 @@ ], "buildPresets": [ { - "name": "raspberrypi_zero", - "description": "Build preset for the raspberrypi_zero board", - "configurePreset": "raspberrypi_zero" + "name": "adafruit_clue", + "description": "Build preset for the adafruit_clue board", + "configurePreset": "adafruit_clue" }, { - "name": "raspberrypi_cm4", - "description": "Build preset for the raspberrypi_cm4 board", - "configurePreset": "raspberrypi_cm4" + "name": "adafruit_feather_esp32_v2", + "description": "Build preset for the adafruit_feather_esp32_v2 board", + "configurePreset": "adafruit_feather_esp32_v2" }, { - "name": "raspberrypi_zero2", - "description": "Build preset for the raspberrypi_zero2 board", - "configurePreset": "raspberrypi_zero2" + "name": "adafruit_feather_esp32s2", + "description": "Build preset for the adafruit_feather_esp32s2 board", + "configurePreset": "adafruit_feather_esp32s2" + }, + { + "name": "adafruit_feather_esp32s3", + "description": "Build preset for the adafruit_feather_esp32s3 board", + "configurePreset": "adafruit_feather_esp32s3" + }, + { + "name": "adafruit_magtag_29gray", + "description": "Build preset for the adafruit_magtag_29gray board", + "configurePreset": "adafruit_magtag_29gray" + }, + { + "name": "adafruit_metro_esp32s2", + "description": "Build preset for the adafruit_metro_esp32s2 board", + "configurePreset": "adafruit_metro_esp32s2" + }, + { + "name": "apard32690", + "description": "Build preset for the apard32690 board", + "configurePreset": "apard32690" + }, + { + "name": "arduino_nano33_ble", + "description": "Build preset for the arduino_nano33_ble board", + "configurePreset": "arduino_nano33_ble" + }, + { + "name": "atsamd21_xpro", + "description": "Build preset for the atsamd21_xpro board", + "configurePreset": "atsamd21_xpro" + }, + { + "name": "atsaml21_xpro", + "description": "Build preset for the atsaml21_xpro board", + "configurePreset": "atsaml21_xpro" + }, + { + "name": "b_g474e_dpow1", + "description": "Build preset for the b_g474e_dpow1 board", + "configurePreset": "b_g474e_dpow1" + }, + { + "name": "b_u585i_iot2a", + "description": "Build preset for the b_u585i_iot2a board", + "configurePreset": "b_u585i_iot2a" }, { "name": "ch32v103r_r1_1v0", @@ -768,16 +813,41 @@ "description": "Build preset for the ch32v203g_r0_1v0 board", "configurePreset": "ch32v203g_r0_1v0" }, - { - "name": "nanoch32v203", - "description": "Build preset for the nanoch32v203 board", - "configurePreset": "nanoch32v203" - }, { "name": "ch32v307v_r1_1v0", "description": "Build preset for the ch32v307v_r1_1v0 board", "configurePreset": "ch32v307v_r1_1v0" }, + { + "name": "circuitplayground_bluefruit", + "description": "Build preset for the circuitplayground_bluefruit board", + "configurePreset": "circuitplayground_bluefruit" + }, + { + "name": "circuitplayground_express", + "description": "Build preset for the circuitplayground_express board", + "configurePreset": "circuitplayground_express" + }, + { + "name": "curiosity_nano", + "description": "Build preset for the curiosity_nano board", + "configurePreset": "curiosity_nano" + }, + { + "name": "cynthion_d11", + "description": "Build preset for the cynthion_d11 board", + "configurePreset": "cynthion_d11" + }, + { + "name": "cynthion_d21", + "description": "Build preset for the cynthion_d21 board", + "configurePreset": "cynthion_d21" + }, + { + "name": "d5035_01", + "description": "Build preset for the d5035_01 board", + "configurePreset": "d5035_01" + }, { "name": "da14695_dk_usb", "description": "Build preset for the da14695_dk_usb board", @@ -789,29 +859,29 @@ "configurePreset": "da1469x_dk_pro" }, { - "name": "adafruit_feather_esp32s2", - "description": "Build preset for the adafruit_feather_esp32s2 board", - "configurePreset": "adafruit_feather_esp32s2" + "name": "daisyseed", + "description": "Build preset for the daisyseed board", + "configurePreset": "daisyseed" }, { - "name": "adafruit_feather_esp32s3", - "description": "Build preset for the adafruit_feather_esp32s3 board", - "configurePreset": "adafruit_feather_esp32s3" + "name": "double_m33_express", + "description": "Build preset for the double_m33_express board", + "configurePreset": "double_m33_express" }, { - "name": "adafruit_feather_esp32_v2", - "description": "Build preset for the adafruit_feather_esp32_v2 board", - "configurePreset": "adafruit_feather_esp32_v2" + "name": "ea4088_quickstart", + "description": "Build preset for the ea4088_quickstart board", + "configurePreset": "ea4088_quickstart" }, { - "name": "adafruit_magtag_29gray", - "description": "Build preset for the adafruit_magtag_29gray board", - "configurePreset": "adafruit_magtag_29gray" + "name": "ea4357", + "description": "Build preset for the ea4357 board", + "configurePreset": "ea4357" }, { - "name": "adafruit_metro_esp32s2", - "description": "Build preset for the adafruit_metro_esp32s2 board", - "configurePreset": "adafruit_metro_esp32s2" + "name": "ek_tm4c123gxl", + "description": "Build preset for the ek_tm4c123gxl board", + "configurePreset": "ek_tm4c123gxl" }, { "name": "espressif_addax_1", @@ -863,15 +933,220 @@ "description": "Build preset for the f1c100s board", "configurePreset": "f1c100s" }, + { + "name": "feather_m0_express", + "description": "Build preset for the feather_m0_express board", + "configurePreset": "feather_m0_express" + }, + { + "name": "feather_m4_express", + "description": "Build preset for the feather_m4_express board", + "configurePreset": "feather_m4_express" + }, + { + "name": "feather_nrf52840_express", + "description": "Build preset for the feather_nrf52840_express board", + "configurePreset": "feather_nrf52840_express" + }, + { + "name": "feather_nrf52840_sense", + "description": "Build preset for the feather_nrf52840_sense board", + "configurePreset": "feather_nrf52840_sense" + }, + { + "name": "feather_rp2040_max3421", + "description": "Build preset for the feather_rp2040_max3421 board", + "configurePreset": "feather_rp2040_max3421" + }, + { + "name": "feather_stm32f405", + "description": "Build preset for the feather_stm32f405 board", + "configurePreset": "feather_stm32f405" + }, { "name": "fomu", "description": "Build preset for the fomu board", "configurePreset": "fomu" }, { - "name": "sipeed_longan_nano", - "description": "Build preset for the sipeed_longan_nano board", - "configurePreset": "sipeed_longan_nano" + "name": "frdm_k32l2a4s", + "description": "Build preset for the frdm_k32l2a4s board", + "configurePreset": "frdm_k32l2a4s" + }, + { + "name": "frdm_k32l2b", + "description": "Build preset for the frdm_k32l2b board", + "configurePreset": "frdm_k32l2b" + }, + { + "name": "frdm_k64f", + "description": "Build preset for the frdm_k64f board", + "configurePreset": "frdm_k64f" + }, + { + "name": "frdm_kl25z", + "description": "Build preset for the frdm_kl25z board", + "configurePreset": "frdm_kl25z" + }, + { + "name": "frdm_mcxa153", + "description": "Build preset for the frdm_mcxa153 board", + "configurePreset": "frdm_mcxa153" + }, + { + "name": "frdm_mcxn947", + "description": "Build preset for the frdm_mcxn947 board", + "configurePreset": "frdm_mcxn947" + }, + { + "name": "itsybitsy_m0", + "description": "Build preset for the itsybitsy_m0 board", + "configurePreset": "itsybitsy_m0" + }, + { + "name": "itsybitsy_m4", + "description": "Build preset for the itsybitsy_m4 board", + "configurePreset": "itsybitsy_m4" + }, + { + "name": "itsybitsy_nrf52840", + "description": "Build preset for the itsybitsy_nrf52840 board", + "configurePreset": "itsybitsy_nrf52840" + }, + { + "name": "kuiic", + "description": "Build preset for the kuiic board", + "configurePreset": "kuiic" + }, + { + "name": "lpcxpresso11u37", + "description": "Build preset for the lpcxpresso11u37 board", + "configurePreset": "lpcxpresso11u37" + }, + { + "name": "lpcxpresso11u68", + "description": "Build preset for the lpcxpresso11u68 board", + "configurePreset": "lpcxpresso11u68" + }, + { + "name": "lpcxpresso1347", + "description": "Build preset for the lpcxpresso1347 board", + "configurePreset": "lpcxpresso1347" + }, + { + "name": "lpcxpresso1549", + "description": "Build preset for the lpcxpresso1549 board", + "configurePreset": "lpcxpresso1549" + }, + { + "name": "lpcxpresso1769", + "description": "Build preset for the lpcxpresso1769 board", + "configurePreset": "lpcxpresso1769" + }, + { + "name": "lpcxpresso18s37", + "description": "Build preset for the lpcxpresso18s37 board", + "configurePreset": "lpcxpresso18s37" + }, + { + "name": "lpcxpresso43s67", + "description": "Build preset for the lpcxpresso43s67 board", + "configurePreset": "lpcxpresso43s67" + }, + { + "name": "lpcxpresso51u68", + "description": "Build preset for the lpcxpresso51u68 board", + "configurePreset": "lpcxpresso51u68" + }, + { + "name": "lpcxpresso54114", + "description": "Build preset for the lpcxpresso54114 board", + "configurePreset": "lpcxpresso54114" + }, + { + "name": "lpcxpresso54608", + "description": "Build preset for the lpcxpresso54608 board", + "configurePreset": "lpcxpresso54608" + }, + { + "name": "lpcxpresso54628", + "description": "Build preset for the lpcxpresso54628 board", + "configurePreset": "lpcxpresso54628" + }, + { + "name": "lpcxpresso55s28", + "description": "Build preset for the lpcxpresso55s28 board", + "configurePreset": "lpcxpresso55s28" + }, + { + "name": "lpcxpresso55s69", + "description": "Build preset for the lpcxpresso55s69 board", + "configurePreset": "lpcxpresso55s69" + }, + { + "name": "max32650evkit", + "description": "Build preset for the max32650evkit board", + "configurePreset": "max32650evkit" + }, + { + "name": "max32650fthr", + "description": "Build preset for the max32650fthr board", + "configurePreset": "max32650fthr" + }, + { + "name": "max32651evkit", + "description": "Build preset for the max32651evkit board", + "configurePreset": "max32651evkit" + }, + { + "name": "max32666evkit", + "description": "Build preset for the max32666evkit board", + "configurePreset": "max32666evkit" + }, + { + "name": "max32666fthr", + "description": "Build preset for the max32666fthr board", + "configurePreset": "max32666fthr" + }, + { + "name": "max32690evkit", + "description": "Build preset for the max32690evkit board", + "configurePreset": "max32690evkit" + }, + { + "name": "max78002evkit", + "description": "Build preset for the max78002evkit board", + "configurePreset": "max78002evkit" + }, + { + "name": "mbed1768", + "description": "Build preset for the mbed1768 board", + "configurePreset": "mbed1768" + }, + { + "name": "mcb1800", + "description": "Build preset for the mcb1800 board", + "configurePreset": "mcb1800" + }, + { + "name": "mcu_link", + "description": "Build preset for the mcu_link board", + "configurePreset": "mcu_link" + }, + { + "name": "mcxn947brk", + "description": "Build preset for the mcxn947brk board", + "configurePreset": "mcxn947brk" + }, + { + "name": "metro_m0_express", + "description": "Build preset for the metro_m0_express board", + "configurePreset": "metro_m0_express" + }, + { + "name": "metro_m4_express", + "description": "Build preset for the metro_m4_express board", + "configurePreset": "metro_m4_express" }, { "name": "metro_m7_1011", @@ -923,196 +1198,6 @@ "description": "Build preset for the mimxrt1170_evkb board", "configurePreset": "mimxrt1170_evkb" }, - { - "name": "teensy_40", - "description": "Build preset for the teensy_40 board", - "configurePreset": "teensy_40" - }, - { - "name": "teensy_41", - "description": "Build preset for the teensy_41 board", - "configurePreset": "teensy_41" - }, - { - "name": "frdm_k64f", - "description": "Build preset for the frdm_k64f board", - "configurePreset": "frdm_k64f" - }, - { - "name": "teensy_35", - "description": "Build preset for the teensy_35 board", - "configurePreset": "teensy_35" - }, - { - "name": "frdm_k32l2a4s", - "description": "Build preset for the frdm_k32l2a4s board", - "configurePreset": "frdm_k32l2a4s" - }, - { - "name": "frdm_k32l2b", - "description": "Build preset for the frdm_k32l2b board", - "configurePreset": "frdm_k32l2b" - }, - { - "name": "kuiic", - "description": "Build preset for the kuiic board", - "configurePreset": "kuiic" - }, - { - "name": "frdm_kl25z", - "description": "Build preset for the frdm_kl25z board", - "configurePreset": "frdm_kl25z" - }, - { - "name": "lpcxpresso11u37", - "description": "Build preset for the lpcxpresso11u37 board", - "configurePreset": "lpcxpresso11u37" - }, - { - "name": "lpcxpresso11u68", - "description": "Build preset for the lpcxpresso11u68 board", - "configurePreset": "lpcxpresso11u68" - }, - { - "name": "lpcxpresso1347", - "description": "Build preset for the lpcxpresso1347 board", - "configurePreset": "lpcxpresso1347" - }, - { - "name": "lpcxpresso1549", - "description": "Build preset for the lpcxpresso1549 board", - "configurePreset": "lpcxpresso1549" - }, - { - "name": "lpcxpresso1769", - "description": "Build preset for the lpcxpresso1769 board", - "configurePreset": "lpcxpresso1769" - }, - { - "name": "mbed1768", - "description": "Build preset for the mbed1768 board", - "configurePreset": "mbed1768" - }, - { - "name": "lpcxpresso18s37", - "description": "Build preset for the lpcxpresso18s37 board", - "configurePreset": "lpcxpresso18s37" - }, - { - "name": "mcb1800", - "description": "Build preset for the mcb1800 board", - "configurePreset": "mcb1800" - }, - { - "name": "ea4088_quickstart", - "description": "Build preset for the ea4088_quickstart board", - "configurePreset": "ea4088_quickstart" - }, - { - "name": "ea4357", - "description": "Build preset for the ea4357 board", - "configurePreset": "ea4357" - }, - { - "name": "lpcxpresso43s67", - "description": "Build preset for the lpcxpresso43s67 board", - "configurePreset": "lpcxpresso43s67" - }, - { - "name": "lpcxpresso51u68", - "description": "Build preset for the lpcxpresso51u68 board", - "configurePreset": "lpcxpresso51u68" - }, - { - "name": "lpcxpresso54114", - "description": "Build preset for the lpcxpresso54114 board", - "configurePreset": "lpcxpresso54114" - }, - { - "name": "lpcxpresso54608", - "description": "Build preset for the lpcxpresso54608 board", - "configurePreset": "lpcxpresso54608" - }, - { - "name": "lpcxpresso54628", - "description": "Build preset for the lpcxpresso54628 board", - "configurePreset": "lpcxpresso54628" - }, - { - "name": "double_m33_express", - "description": "Build preset for the double_m33_express board", - "configurePreset": "double_m33_express" - }, - { - "name": "lpcxpresso55s28", - "description": "Build preset for the lpcxpresso55s28 board", - "configurePreset": "lpcxpresso55s28" - }, - { - "name": "lpcxpresso55s69", - "description": "Build preset for the lpcxpresso55s69 board", - "configurePreset": "lpcxpresso55s69" - }, - { - "name": "mcu_link", - "description": "Build preset for the mcu_link board", - "configurePreset": "mcu_link" - }, - { - "name": "max32650evkit", - "description": "Build preset for the max32650evkit board", - "configurePreset": "max32650evkit" - }, - { - "name": "max32650fthr", - "description": "Build preset for the max32650fthr board", - "configurePreset": "max32650fthr" - }, - { - "name": "max32651evkit", - "description": "Build preset for the max32651evkit board", - "configurePreset": "max32651evkit" - }, - { - "name": "max32666evkit", - "description": "Build preset for the max32666evkit board", - "configurePreset": "max32666evkit" - }, - { - "name": "max32666fthr", - "description": "Build preset for the max32666fthr board", - "configurePreset": "max32666fthr" - }, - { - "name": "apard32690", - "description": "Build preset for the apard32690 board", - "configurePreset": "apard32690" - }, - { - "name": "max32690evkit", - "description": "Build preset for the max32690evkit board", - "configurePreset": "max32690evkit" - }, - { - "name": "max78002evkit", - "description": "Build preset for the max78002evkit board", - "configurePreset": "max78002evkit" - }, - { - "name": "frdm_mcxa153", - "description": "Build preset for the frdm_mcxa153 board", - "configurePreset": "frdm_mcxa153" - }, - { - "name": "frdm_mcxn947", - "description": "Build preset for the frdm_mcxn947 board", - "configurePreset": "frdm_mcxn947" - }, - { - "name": "mcxn947brk", - "description": "Build preset for the mcxn947brk board", - "configurePreset": "mcxn947brk" - }, { "name": "mm32f327x_mb39", "description": "Build preset for the mm32f327x_mb39 board", @@ -1134,34 +1219,9 @@ "configurePreset": "msp_exp432e401y" }, { - "name": "adafruit_clue", - "description": "Build preset for the adafruit_clue board", - "configurePreset": "adafruit_clue" - }, - { - "name": "arduino_nano33_ble", - "description": "Build preset for the arduino_nano33_ble board", - "configurePreset": "arduino_nano33_ble" - }, - { - "name": "circuitplayground_bluefruit", - "description": "Build preset for the circuitplayground_bluefruit board", - "configurePreset": "circuitplayground_bluefruit" - }, - { - "name": "feather_nrf52840_express", - "description": "Build preset for the feather_nrf52840_express board", - "configurePreset": "feather_nrf52840_express" - }, - { - "name": "feather_nrf52840_sense", - "description": "Build preset for the feather_nrf52840_sense board", - "configurePreset": "feather_nrf52840_sense" - }, - { - "name": "itsybitsy_nrf52840", - "description": "Build preset for the itsybitsy_nrf52840 board", - "configurePreset": "itsybitsy_nrf52840" + "name": "nanoch32v203", + "description": "Build preset for the nanoch32v203 board", + "configurePreset": "nanoch32v203" }, { "name": "pca10056", @@ -1183,11 +1243,36 @@ "description": "Build preset for the pca10100 board", "configurePreset": "pca10100" }, + { + "name": "pico_sdk", + "description": "Build preset for the pico_sdk board", + "configurePreset": "pico_sdk" + }, { "name": "portenta_c33", "description": "Build preset for the portenta_c33 board", "configurePreset": "portenta_c33" }, + { + "name": "pybadge", + "description": "Build preset for the pybadge board", + "configurePreset": "pybadge" + }, + { + "name": "pyboardv11", + "description": "Build preset for the pyboardv11 board", + "configurePreset": "pyboardv11" + }, + { + "name": "pyportal", + "description": "Build preset for the pyportal board", + "configurePreset": "pyportal" + }, + { + "name": "qtpy", + "description": "Build preset for the qtpy board", + "configurePreset": "qtpy" + }, { "name": "ra2a1_ek", "description": "Build preset for the ra2a1_ek board", @@ -1218,21 +1303,6 @@ "description": "Build preset for the ra8m1_ek board", "configurePreset": "ra8m1_ek" }, - { - "name": "uno_r4", - "description": "Build preset for the uno_r4 board", - "configurePreset": "uno_r4" - }, - { - "name": "feather_rp2040_max3421", - "description": "Build preset for the feather_rp2040_max3421 board", - "configurePreset": "feather_rp2040_max3421" - }, - { - "name": "pico_sdk", - "description": "Build preset for the pico_sdk board", - "configurePreset": "pico_sdk" - }, { "name": "raspberry_pi_pico", "description": "Build preset for the raspberry_pi_pico board", @@ -1244,100 +1314,25 @@ "configurePreset": "raspberry_pi_pico2" }, { - "name": "cynthion_d11", - "description": "Build preset for the cynthion_d11 board", - "configurePreset": "cynthion_d11" + "name": "raspberrypi_cm4", + "description": "Build preset for the raspberrypi_cm4 board", + "configurePreset": "raspberrypi_cm4" + }, + { + "name": "raspberrypi_zero", + "description": "Build preset for the raspberrypi_zero board", + "configurePreset": "raspberrypi_zero" + }, + { + "name": "raspberrypi_zero2", + "description": "Build preset for the raspberrypi_zero2 board", + "configurePreset": "raspberrypi_zero2" }, { "name": "samd11_xplained", "description": "Build preset for the samd11_xplained board", "configurePreset": "samd11_xplained" }, - { - "name": "atsamd21_xpro", - "description": "Build preset for the atsamd21_xpro board", - "configurePreset": "atsamd21_xpro" - }, - { - "name": "circuitplayground_express", - "description": "Build preset for the circuitplayground_express board", - "configurePreset": "circuitplayground_express" - }, - { - "name": "curiosity_nano", - "description": "Build preset for the curiosity_nano board", - "configurePreset": "curiosity_nano" - }, - { - "name": "cynthion_d21", - "description": "Build preset for the cynthion_d21 board", - "configurePreset": "cynthion_d21" - }, - { - "name": "feather_m0_express", - "description": "Build preset for the feather_m0_express board", - "configurePreset": "feather_m0_express" - }, - { - "name": "itsybitsy_m0", - "description": "Build preset for the itsybitsy_m0 board", - "configurePreset": "itsybitsy_m0" - }, - { - "name": "metro_m0_express", - "description": "Build preset for the metro_m0_express board", - "configurePreset": "metro_m0_express" - }, - { - "name": "qtpy", - "description": "Build preset for the qtpy board", - "configurePreset": "qtpy" - }, - { - "name": "seeeduino_xiao", - "description": "Build preset for the seeeduino_xiao board", - "configurePreset": "seeeduino_xiao" - }, - { - "name": "sparkfun_samd21_mini_usb", - "description": "Build preset for the sparkfun_samd21_mini_usb board", - "configurePreset": "sparkfun_samd21_mini_usb" - }, - { - "name": "trinket_m0", - "description": "Build preset for the trinket_m0 board", - "configurePreset": "trinket_m0" - }, - { - "name": "d5035_01", - "description": "Build preset for the d5035_01 board", - "configurePreset": "d5035_01" - }, - { - "name": "feather_m4_express", - "description": "Build preset for the feather_m4_express board", - "configurePreset": "feather_m4_express" - }, - { - "name": "itsybitsy_m4", - "description": "Build preset for the itsybitsy_m4 board", - "configurePreset": "itsybitsy_m4" - }, - { - "name": "metro_m4_express", - "description": "Build preset for the metro_m4_express board", - "configurePreset": "metro_m4_express" - }, - { - "name": "pybadge", - "description": "Build preset for the pybadge board", - "configurePreset": "pybadge" - }, - { - "name": "pyportal", - "description": "Build preset for the pyportal board", - "configurePreset": "pyportal" - }, { "name": "same54_xplained", "description": "Build preset for the same54_xplained board", @@ -1348,21 +1343,36 @@ "description": "Build preset for the samg55_xplained board", "configurePreset": "samg55_xplained" }, - { - "name": "atsaml21_xpro", - "description": "Build preset for the atsaml21_xpro board", - "configurePreset": "atsaml21_xpro" - }, { "name": "saml22_feather", "description": "Build preset for the saml22_feather board", "configurePreset": "saml22_feather" }, + { + "name": "seeeduino_xiao", + "description": "Build preset for the seeeduino_xiao board", + "configurePreset": "seeeduino_xiao" + }, { "name": "sensorwatch_m0", "description": "Build preset for the sensorwatch_m0 board", "configurePreset": "sensorwatch_m0" }, + { + "name": "sipeed_longan_nano", + "description": "Build preset for the sipeed_longan_nano board", + "configurePreset": "sipeed_longan_nano" + }, + { + "name": "sparkfun_samd21_mini_usb", + "description": "Build preset for the sparkfun_samd21_mini_usb board", + "configurePreset": "sparkfun_samd21_mini_usb" + }, + { + "name": "stlinkv3mini", + "description": "Build preset for the stlinkv3mini board", + "configurePreset": "stlinkv3mini" + }, { "name": "stm32c071nucleo", "description": "Build preset for the stm32c071nucleo board", @@ -1383,11 +1393,6 @@ "description": "Build preset for the stm32f072eval board", "configurePreset": "stm32f072eval" }, - { - "name": "stm32f103ze_iar", - "description": "Build preset for the stm32f103ze_iar board", - "configurePreset": "stm32f103ze_iar" - }, { "name": "stm32f103_bluepill", "description": "Build preset for the stm32f103_bluepill board", @@ -1398,6 +1403,11 @@ "description": "Build preset for the stm32f103_mini_2 board", "configurePreset": "stm32f103_mini_2" }, + { + "name": "stm32f103ze_iar", + "description": "Build preset for the stm32f103ze_iar board", + "configurePreset": "stm32f103ze_iar" + }, { "name": "stm32f207nucleo", "description": "Build preset for the stm32f207nucleo board", @@ -1408,16 +1418,6 @@ "description": "Build preset for the stm32f303disco board", "configurePreset": "stm32f303disco" }, - { - "name": "feather_stm32f405", - "description": "Build preset for the feather_stm32f405 board", - "configurePreset": "feather_stm32f405" - }, - { - "name": "pyboardv11", - "description": "Build preset for the pyboardv11 board", - "configurePreset": "pyboardv11" - }, { "name": "stm32f401blackpill", "description": "Build preset for the stm32f401blackpill board", @@ -1458,11 +1458,6 @@ "description": "Build preset for the stm32f439nucleo board", "configurePreset": "stm32f439nucleo" }, - { - "name": "stlinkv3mini", - "description": "Build preset for the stlinkv3mini board", - "configurePreset": "stlinkv3mini" - }, { "name": "stm32f723disco", "description": "Build preset for the stm32f723disco board", @@ -1493,11 +1488,6 @@ "description": "Build preset for the stm32g0b1nucleo board", "configurePreset": "stm32g0b1nucleo" }, - { - "name": "b_g474e_dpow1", - "description": "Build preset for the b_g474e_dpow1 board", - "configurePreset": "b_g474e_dpow1" - }, { "name": "stm32g474nucleo", "description": "Build preset for the stm32g474nucleo board", @@ -1523,11 +1513,6 @@ "description": "Build preset for the stm32h573i_dk board", "configurePreset": "stm32h573i_dk" }, - { - "name": "daisyseed", - "description": "Build preset for the daisyseed board", - "configurePreset": "daisyseed" - }, { "name": "stm32h723nucleo", "description": "Build preset for the stm32h723nucleo board", @@ -1548,20 +1533,15 @@ "description": "Build preset for the stm32h745disco board", "configurePreset": "stm32h745disco" }, - { - "name": "stm32h750bdk", - "description": "Build preset for the stm32h750bdk board", - "configurePreset": "stm32h750bdk" - }, { "name": "stm32h750_weact", "description": "Build preset for the stm32h750_weact board", "configurePreset": "stm32h750_weact" }, { - "name": "waveshare_openh743i", - "description": "Build preset for the waveshare_openh743i board", - "configurePreset": "waveshare_openh743i" + "name": "stm32h750bdk", + "description": "Build preset for the stm32h750bdk board", + "configurePreset": "stm32h750bdk" }, { "name": "stm32h7s3nucleo", @@ -1598,11 +1578,6 @@ "description": "Build preset for the stm32l4r5nucleo board", "configurePreset": "stm32l4r5nucleo" }, - { - "name": "b_u585i_iot2a", - "description": "Build preset for the b_u585i_iot2a board", - "configurePreset": "b_u585i_iot2a" - }, { "name": "stm32u545nucleo", "description": "Build preset for the stm32u545nucleo board", @@ -1629,9 +1604,34 @@ "configurePreset": "stm32wb55nucleo" }, { - "name": "ek_tm4c123gxl", - "description": "Build preset for the ek_tm4c123gxl board", - "configurePreset": "ek_tm4c123gxl" + "name": "teensy_35", + "description": "Build preset for the teensy_35 board", + "configurePreset": "teensy_35" + }, + { + "name": "teensy_40", + "description": "Build preset for the teensy_40 board", + "configurePreset": "teensy_40" + }, + { + "name": "teensy_41", + "description": "Build preset for the teensy_41 board", + "configurePreset": "teensy_41" + }, + { + "name": "trinket_m0", + "description": "Build preset for the trinket_m0 board", + "configurePreset": "trinket_m0" + }, + { + "name": "uno_r4", + "description": "Build preset for the uno_r4 board", + "configurePreset": "uno_r4" + }, + { + "name": "waveshare_openh743i", + "description": "Build preset for the waveshare_openh743i board", + "configurePreset": "waveshare_openh743i" }, { "name": "xmc4500_relax", @@ -1646,41 +1646,158 @@ ], "workflowPresets": [ { - "name": "raspberrypi_zero", + "name": "adafruit_clue", "steps": [ { "type": "configure", - "name": "raspberrypi_zero" + "name": "adafruit_clue" }, { "type": "build", - "name": "raspberrypi_zero" + "name": "adafruit_clue" } ] }, { - "name": "raspberrypi_cm4", + "name": "adafruit_feather_esp32_v2", "steps": [ { "type": "configure", - "name": "raspberrypi_cm4" + "name": "adafruit_feather_esp32_v2" }, { "type": "build", - "name": "raspberrypi_cm4" + "name": "adafruit_feather_esp32_v2" } ] }, { - "name": "raspberrypi_zero2", + "name": "adafruit_feather_esp32s2", "steps": [ { "type": "configure", - "name": "raspberrypi_zero2" + "name": "adafruit_feather_esp32s2" }, { "type": "build", - "name": "raspberrypi_zero2" + "name": "adafruit_feather_esp32s2" + } + ] + }, + { + "name": "adafruit_feather_esp32s3", + "steps": [ + { + "type": "configure", + "name": "adafruit_feather_esp32s3" + }, + { + "type": "build", + "name": "adafruit_feather_esp32s3" + } + ] + }, + { + "name": "adafruit_magtag_29gray", + "steps": [ + { + "type": "configure", + "name": "adafruit_magtag_29gray" + }, + { + "type": "build", + "name": "adafruit_magtag_29gray" + } + ] + }, + { + "name": "adafruit_metro_esp32s2", + "steps": [ + { + "type": "configure", + "name": "adafruit_metro_esp32s2" + }, + { + "type": "build", + "name": "adafruit_metro_esp32s2" + } + ] + }, + { + "name": "apard32690", + "steps": [ + { + "type": "configure", + "name": "apard32690" + }, + { + "type": "build", + "name": "apard32690" + } + ] + }, + { + "name": "arduino_nano33_ble", + "steps": [ + { + "type": "configure", + "name": "arduino_nano33_ble" + }, + { + "type": "build", + "name": "arduino_nano33_ble" + } + ] + }, + { + "name": "atsamd21_xpro", + "steps": [ + { + "type": "configure", + "name": "atsamd21_xpro" + }, + { + "type": "build", + "name": "atsamd21_xpro" + } + ] + }, + { + "name": "atsaml21_xpro", + "steps": [ + { + "type": "configure", + "name": "atsaml21_xpro" + }, + { + "type": "build", + "name": "atsaml21_xpro" + } + ] + }, + { + "name": "b_g474e_dpow1", + "steps": [ + { + "type": "configure", + "name": "b_g474e_dpow1" + }, + { + "type": "build", + "name": "b_g474e_dpow1" + } + ] + }, + { + "name": "b_u585i_iot2a", + "steps": [ + { + "type": "configure", + "name": "b_u585i_iot2a" + }, + { + "type": "build", + "name": "b_u585i_iot2a" } ] }, @@ -1723,19 +1840,6 @@ } ] }, - { - "name": "nanoch32v203", - "steps": [ - { - "type": "configure", - "name": "nanoch32v203" - }, - { - "type": "build", - "name": "nanoch32v203" - } - ] - }, { "name": "ch32v307v_r1_1v0", "steps": [ @@ -1749,6 +1853,84 @@ } ] }, + { + "name": "circuitplayground_bluefruit", + "steps": [ + { + "type": "configure", + "name": "circuitplayground_bluefruit" + }, + { + "type": "build", + "name": "circuitplayground_bluefruit" + } + ] + }, + { + "name": "circuitplayground_express", + "steps": [ + { + "type": "configure", + "name": "circuitplayground_express" + }, + { + "type": "build", + "name": "circuitplayground_express" + } + ] + }, + { + "name": "curiosity_nano", + "steps": [ + { + "type": "configure", + "name": "curiosity_nano" + }, + { + "type": "build", + "name": "curiosity_nano" + } + ] + }, + { + "name": "cynthion_d11", + "steps": [ + { + "type": "configure", + "name": "cynthion_d11" + }, + { + "type": "build", + "name": "cynthion_d11" + } + ] + }, + { + "name": "cynthion_d21", + "steps": [ + { + "type": "configure", + "name": "cynthion_d21" + }, + { + "type": "build", + "name": "cynthion_d21" + } + ] + }, + { + "name": "d5035_01", + "steps": [ + { + "type": "configure", + "name": "d5035_01" + }, + { + "type": "build", + "name": "d5035_01" + } + ] + }, { "name": "da14695_dk_usb", "steps": [ @@ -1776,67 +1958,67 @@ ] }, { - "name": "adafruit_feather_esp32s2", + "name": "daisyseed", "steps": [ { "type": "configure", - "name": "adafruit_feather_esp32s2" + "name": "daisyseed" }, { "type": "build", - "name": "adafruit_feather_esp32s2" + "name": "daisyseed" } ] }, { - "name": "adafruit_feather_esp32s3", + "name": "double_m33_express", "steps": [ { "type": "configure", - "name": "adafruit_feather_esp32s3" + "name": "double_m33_express" }, { "type": "build", - "name": "adafruit_feather_esp32s3" + "name": "double_m33_express" } ] }, { - "name": "adafruit_feather_esp32_v2", + "name": "ea4088_quickstart", "steps": [ { "type": "configure", - "name": "adafruit_feather_esp32_v2" + "name": "ea4088_quickstart" }, { "type": "build", - "name": "adafruit_feather_esp32_v2" + "name": "ea4088_quickstart" } ] }, { - "name": "adafruit_magtag_29gray", + "name": "ea4357", "steps": [ { "type": "configure", - "name": "adafruit_magtag_29gray" + "name": "ea4357" }, { "type": "build", - "name": "adafruit_magtag_29gray" + "name": "ea4357" } ] }, { - "name": "adafruit_metro_esp32s2", + "name": "ek_tm4c123gxl", "steps": [ { "type": "configure", - "name": "adafruit_metro_esp32s2" + "name": "ek_tm4c123gxl" }, { "type": "build", - "name": "adafruit_metro_esp32s2" + "name": "ek_tm4c123gxl" } ] }, @@ -1970,6 +2152,84 @@ } ] }, + { + "name": "feather_m0_express", + "steps": [ + { + "type": "configure", + "name": "feather_m0_express" + }, + { + "type": "build", + "name": "feather_m0_express" + } + ] + }, + { + "name": "feather_m4_express", + "steps": [ + { + "type": "configure", + "name": "feather_m4_express" + }, + { + "type": "build", + "name": "feather_m4_express" + } + ] + }, + { + "name": "feather_nrf52840_express", + "steps": [ + { + "type": "configure", + "name": "feather_nrf52840_express" + }, + { + "type": "build", + "name": "feather_nrf52840_express" + } + ] + }, + { + "name": "feather_nrf52840_sense", + "steps": [ + { + "type": "configure", + "name": "feather_nrf52840_sense" + }, + { + "type": "build", + "name": "feather_nrf52840_sense" + } + ] + }, + { + "name": "feather_rp2040_max3421", + "steps": [ + { + "type": "configure", + "name": "feather_rp2040_max3421" + }, + { + "type": "build", + "name": "feather_rp2040_max3421" + } + ] + }, + { + "name": "feather_stm32f405", + "steps": [ + { + "type": "configure", + "name": "feather_stm32f405" + }, + { + "type": "build", + "name": "feather_stm32f405" + } + ] + }, { "name": "fomu", "steps": [ @@ -1984,15 +2244,470 @@ ] }, { - "name": "sipeed_longan_nano", + "name": "frdm_k32l2a4s", "steps": [ { "type": "configure", - "name": "sipeed_longan_nano" + "name": "frdm_k32l2a4s" }, { "type": "build", - "name": "sipeed_longan_nano" + "name": "frdm_k32l2a4s" + } + ] + }, + { + "name": "frdm_k32l2b", + "steps": [ + { + "type": "configure", + "name": "frdm_k32l2b" + }, + { + "type": "build", + "name": "frdm_k32l2b" + } + ] + }, + { + "name": "frdm_k64f", + "steps": [ + { + "type": "configure", + "name": "frdm_k64f" + }, + { + "type": "build", + "name": "frdm_k64f" + } + ] + }, + { + "name": "frdm_kl25z", + "steps": [ + { + "type": "configure", + "name": "frdm_kl25z" + }, + { + "type": "build", + "name": "frdm_kl25z" + } + ] + }, + { + "name": "frdm_mcxa153", + "steps": [ + { + "type": "configure", + "name": "frdm_mcxa153" + }, + { + "type": "build", + "name": "frdm_mcxa153" + } + ] + }, + { + "name": "frdm_mcxn947", + "steps": [ + { + "type": "configure", + "name": "frdm_mcxn947" + }, + { + "type": "build", + "name": "frdm_mcxn947" + } + ] + }, + { + "name": "itsybitsy_m0", + "steps": [ + { + "type": "configure", + "name": "itsybitsy_m0" + }, + { + "type": "build", + "name": "itsybitsy_m0" + } + ] + }, + { + "name": "itsybitsy_m4", + "steps": [ + { + "type": "configure", + "name": "itsybitsy_m4" + }, + { + "type": "build", + "name": "itsybitsy_m4" + } + ] + }, + { + "name": "itsybitsy_nrf52840", + "steps": [ + { + "type": "configure", + "name": "itsybitsy_nrf52840" + }, + { + "type": "build", + "name": "itsybitsy_nrf52840" + } + ] + }, + { + "name": "kuiic", + "steps": [ + { + "type": "configure", + "name": "kuiic" + }, + { + "type": "build", + "name": "kuiic" + } + ] + }, + { + "name": "lpcxpresso11u37", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso11u37" + }, + { + "type": "build", + "name": "lpcxpresso11u37" + } + ] + }, + { + "name": "lpcxpresso11u68", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso11u68" + }, + { + "type": "build", + "name": "lpcxpresso11u68" + } + ] + }, + { + "name": "lpcxpresso1347", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso1347" + }, + { + "type": "build", + "name": "lpcxpresso1347" + } + ] + }, + { + "name": "lpcxpresso1549", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso1549" + }, + { + "type": "build", + "name": "lpcxpresso1549" + } + ] + }, + { + "name": "lpcxpresso1769", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso1769" + }, + { + "type": "build", + "name": "lpcxpresso1769" + } + ] + }, + { + "name": "lpcxpresso18s37", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso18s37" + }, + { + "type": "build", + "name": "lpcxpresso18s37" + } + ] + }, + { + "name": "lpcxpresso43s67", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso43s67" + }, + { + "type": "build", + "name": "lpcxpresso43s67" + } + ] + }, + { + "name": "lpcxpresso51u68", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso51u68" + }, + { + "type": "build", + "name": "lpcxpresso51u68" + } + ] + }, + { + "name": "lpcxpresso54114", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso54114" + }, + { + "type": "build", + "name": "lpcxpresso54114" + } + ] + }, + { + "name": "lpcxpresso54608", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso54608" + }, + { + "type": "build", + "name": "lpcxpresso54608" + } + ] + }, + { + "name": "lpcxpresso54628", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso54628" + }, + { + "type": "build", + "name": "lpcxpresso54628" + } + ] + }, + { + "name": "lpcxpresso55s28", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso55s28" + }, + { + "type": "build", + "name": "lpcxpresso55s28" + } + ] + }, + { + "name": "lpcxpresso55s69", + "steps": [ + { + "type": "configure", + "name": "lpcxpresso55s69" + }, + { + "type": "build", + "name": "lpcxpresso55s69" + } + ] + }, + { + "name": "max32650evkit", + "steps": [ + { + "type": "configure", + "name": "max32650evkit" + }, + { + "type": "build", + "name": "max32650evkit" + } + ] + }, + { + "name": "max32650fthr", + "steps": [ + { + "type": "configure", + "name": "max32650fthr" + }, + { + "type": "build", + "name": "max32650fthr" + } + ] + }, + { + "name": "max32651evkit", + "steps": [ + { + "type": "configure", + "name": "max32651evkit" + }, + { + "type": "build", + "name": "max32651evkit" + } + ] + }, + { + "name": "max32666evkit", + "steps": [ + { + "type": "configure", + "name": "max32666evkit" + }, + { + "type": "build", + "name": "max32666evkit" + } + ] + }, + { + "name": "max32666fthr", + "steps": [ + { + "type": "configure", + "name": "max32666fthr" + }, + { + "type": "build", + "name": "max32666fthr" + } + ] + }, + { + "name": "max32690evkit", + "steps": [ + { + "type": "configure", + "name": "max32690evkit" + }, + { + "type": "build", + "name": "max32690evkit" + } + ] + }, + { + "name": "max78002evkit", + "steps": [ + { + "type": "configure", + "name": "max78002evkit" + }, + { + "type": "build", + "name": "max78002evkit" + } + ] + }, + { + "name": "mbed1768", + "steps": [ + { + "type": "configure", + "name": "mbed1768" + }, + { + "type": "build", + "name": "mbed1768" + } + ] + }, + { + "name": "mcb1800", + "steps": [ + { + "type": "configure", + "name": "mcb1800" + }, + { + "type": "build", + "name": "mcb1800" + } + ] + }, + { + "name": "mcu_link", + "steps": [ + { + "type": "configure", + "name": "mcu_link" + }, + { + "type": "build", + "name": "mcu_link" + } + ] + }, + { + "name": "mcxn947brk", + "steps": [ + { + "type": "configure", + "name": "mcxn947brk" + }, + { + "type": "build", + "name": "mcxn947brk" + } + ] + }, + { + "name": "metro_m0_express", + "steps": [ + { + "type": "configure", + "name": "metro_m0_express" + }, + { + "type": "build", + "name": "metro_m0_express" + } + ] + }, + { + "name": "metro_m4_express", + "steps": [ + { + "type": "configure", + "name": "metro_m4_express" + }, + { + "type": "build", + "name": "metro_m4_express" } ] }, @@ -2126,500 +2841,6 @@ } ] }, - { - "name": "teensy_40", - "steps": [ - { - "type": "configure", - "name": "teensy_40" - }, - { - "type": "build", - "name": "teensy_40" - } - ] - }, - { - "name": "teensy_41", - "steps": [ - { - "type": "configure", - "name": "teensy_41" - }, - { - "type": "build", - "name": "teensy_41" - } - ] - }, - { - "name": "frdm_k64f", - "steps": [ - { - "type": "configure", - "name": "frdm_k64f" - }, - { - "type": "build", - "name": "frdm_k64f" - } - ] - }, - { - "name": "teensy_35", - "steps": [ - { - "type": "configure", - "name": "teensy_35" - }, - { - "type": "build", - "name": "teensy_35" - } - ] - }, - { - "name": "frdm_k32l2a4s", - "steps": [ - { - "type": "configure", - "name": "frdm_k32l2a4s" - }, - { - "type": "build", - "name": "frdm_k32l2a4s" - } - ] - }, - { - "name": "frdm_k32l2b", - "steps": [ - { - "type": "configure", - "name": "frdm_k32l2b" - }, - { - "type": "build", - "name": "frdm_k32l2b" - } - ] - }, - { - "name": "kuiic", - "steps": [ - { - "type": "configure", - "name": "kuiic" - }, - { - "type": "build", - "name": "kuiic" - } - ] - }, - { - "name": "frdm_kl25z", - "steps": [ - { - "type": "configure", - "name": "frdm_kl25z" - }, - { - "type": "build", - "name": "frdm_kl25z" - } - ] - }, - { - "name": "lpcxpresso11u37", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso11u37" - }, - { - "type": "build", - "name": "lpcxpresso11u37" - } - ] - }, - { - "name": "lpcxpresso11u68", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso11u68" - }, - { - "type": "build", - "name": "lpcxpresso11u68" - } - ] - }, - { - "name": "lpcxpresso1347", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso1347" - }, - { - "type": "build", - "name": "lpcxpresso1347" - } - ] - }, - { - "name": "lpcxpresso1549", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso1549" - }, - { - "type": "build", - "name": "lpcxpresso1549" - } - ] - }, - { - "name": "lpcxpresso1769", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso1769" - }, - { - "type": "build", - "name": "lpcxpresso1769" - } - ] - }, - { - "name": "mbed1768", - "steps": [ - { - "type": "configure", - "name": "mbed1768" - }, - { - "type": "build", - "name": "mbed1768" - } - ] - }, - { - "name": "lpcxpresso18s37", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso18s37" - }, - { - "type": "build", - "name": "lpcxpresso18s37" - } - ] - }, - { - "name": "mcb1800", - "steps": [ - { - "type": "configure", - "name": "mcb1800" - }, - { - "type": "build", - "name": "mcb1800" - } - ] - }, - { - "name": "ea4088_quickstart", - "steps": [ - { - "type": "configure", - "name": "ea4088_quickstart" - }, - { - "type": "build", - "name": "ea4088_quickstart" - } - ] - }, - { - "name": "ea4357", - "steps": [ - { - "type": "configure", - "name": "ea4357" - }, - { - "type": "build", - "name": "ea4357" - } - ] - }, - { - "name": "lpcxpresso43s67", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso43s67" - }, - { - "type": "build", - "name": "lpcxpresso43s67" - } - ] - }, - { - "name": "lpcxpresso51u68", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso51u68" - }, - { - "type": "build", - "name": "lpcxpresso51u68" - } - ] - }, - { - "name": "lpcxpresso54114", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso54114" - }, - { - "type": "build", - "name": "lpcxpresso54114" - } - ] - }, - { - "name": "lpcxpresso54608", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso54608" - }, - { - "type": "build", - "name": "lpcxpresso54608" - } - ] - }, - { - "name": "lpcxpresso54628", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso54628" - }, - { - "type": "build", - "name": "lpcxpresso54628" - } - ] - }, - { - "name": "double_m33_express", - "steps": [ - { - "type": "configure", - "name": "double_m33_express" - }, - { - "type": "build", - "name": "double_m33_express" - } - ] - }, - { - "name": "lpcxpresso55s28", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso55s28" - }, - { - "type": "build", - "name": "lpcxpresso55s28" - } - ] - }, - { - "name": "lpcxpresso55s69", - "steps": [ - { - "type": "configure", - "name": "lpcxpresso55s69" - }, - { - "type": "build", - "name": "lpcxpresso55s69" - } - ] - }, - { - "name": "mcu_link", - "steps": [ - { - "type": "configure", - "name": "mcu_link" - }, - { - "type": "build", - "name": "mcu_link" - } - ] - }, - { - "name": "max32650evkit", - "steps": [ - { - "type": "configure", - "name": "max32650evkit" - }, - { - "type": "build", - "name": "max32650evkit" - } - ] - }, - { - "name": "max32650fthr", - "steps": [ - { - "type": "configure", - "name": "max32650fthr" - }, - { - "type": "build", - "name": "max32650fthr" - } - ] - }, - { - "name": "max32651evkit", - "steps": [ - { - "type": "configure", - "name": "max32651evkit" - }, - { - "type": "build", - "name": "max32651evkit" - } - ] - }, - { - "name": "max32666evkit", - "steps": [ - { - "type": "configure", - "name": "max32666evkit" - }, - { - "type": "build", - "name": "max32666evkit" - } - ] - }, - { - "name": "max32666fthr", - "steps": [ - { - "type": "configure", - "name": "max32666fthr" - }, - { - "type": "build", - "name": "max32666fthr" - } - ] - }, - { - "name": "apard32690", - "steps": [ - { - "type": "configure", - "name": "apard32690" - }, - { - "type": "build", - "name": "apard32690" - } - ] - }, - { - "name": "max32690evkit", - "steps": [ - { - "type": "configure", - "name": "max32690evkit" - }, - { - "type": "build", - "name": "max32690evkit" - } - ] - }, - { - "name": "max78002evkit", - "steps": [ - { - "type": "configure", - "name": "max78002evkit" - }, - { - "type": "build", - "name": "max78002evkit" - } - ] - }, - { - "name": "frdm_mcxa153", - "steps": [ - { - "type": "configure", - "name": "frdm_mcxa153" - }, - { - "type": "build", - "name": "frdm_mcxa153" - } - ] - }, - { - "name": "frdm_mcxn947", - "steps": [ - { - "type": "configure", - "name": "frdm_mcxn947" - }, - { - "type": "build", - "name": "frdm_mcxn947" - } - ] - }, - { - "name": "mcxn947brk", - "steps": [ - { - "type": "configure", - "name": "mcxn947brk" - }, - { - "type": "build", - "name": "mcxn947brk" - } - ] - }, { "name": "mm32f327x_mb39", "steps": [ @@ -2673,80 +2894,15 @@ ] }, { - "name": "adafruit_clue", + "name": "nanoch32v203", "steps": [ { "type": "configure", - "name": "adafruit_clue" + "name": "nanoch32v203" }, { "type": "build", - "name": "adafruit_clue" - } - ] - }, - { - "name": "arduino_nano33_ble", - "steps": [ - { - "type": "configure", - "name": "arduino_nano33_ble" - }, - { - "type": "build", - "name": "arduino_nano33_ble" - } - ] - }, - { - "name": "circuitplayground_bluefruit", - "steps": [ - { - "type": "configure", - "name": "circuitplayground_bluefruit" - }, - { - "type": "build", - "name": "circuitplayground_bluefruit" - } - ] - }, - { - "name": "feather_nrf52840_express", - "steps": [ - { - "type": "configure", - "name": "feather_nrf52840_express" - }, - { - "type": "build", - "name": "feather_nrf52840_express" - } - ] - }, - { - "name": "feather_nrf52840_sense", - "steps": [ - { - "type": "configure", - "name": "feather_nrf52840_sense" - }, - { - "type": "build", - "name": "feather_nrf52840_sense" - } - ] - }, - { - "name": "itsybitsy_nrf52840", - "steps": [ - { - "type": "configure", - "name": "itsybitsy_nrf52840" - }, - { - "type": "build", - "name": "itsybitsy_nrf52840" + "name": "nanoch32v203" } ] }, @@ -2802,6 +2958,19 @@ } ] }, + { + "name": "pico_sdk", + "steps": [ + { + "type": "configure", + "name": "pico_sdk" + }, + { + "type": "build", + "name": "pico_sdk" + } + ] + }, { "name": "portenta_c33", "steps": [ @@ -2815,6 +2984,58 @@ } ] }, + { + "name": "pybadge", + "steps": [ + { + "type": "configure", + "name": "pybadge" + }, + { + "type": "build", + "name": "pybadge" + } + ] + }, + { + "name": "pyboardv11", + "steps": [ + { + "type": "configure", + "name": "pyboardv11" + }, + { + "type": "build", + "name": "pyboardv11" + } + ] + }, + { + "name": "pyportal", + "steps": [ + { + "type": "configure", + "name": "pyportal" + }, + { + "type": "build", + "name": "pyportal" + } + ] + }, + { + "name": "qtpy", + "steps": [ + { + "type": "configure", + "name": "qtpy" + }, + { + "type": "build", + "name": "qtpy" + } + ] + }, { "name": "ra2a1_ek", "steps": [ @@ -2893,45 +3114,6 @@ } ] }, - { - "name": "uno_r4", - "steps": [ - { - "type": "configure", - "name": "uno_r4" - }, - { - "type": "build", - "name": "uno_r4" - } - ] - }, - { - "name": "feather_rp2040_max3421", - "steps": [ - { - "type": "configure", - "name": "feather_rp2040_max3421" - }, - { - "type": "build", - "name": "feather_rp2040_max3421" - } - ] - }, - { - "name": "pico_sdk", - "steps": [ - { - "type": "configure", - "name": "pico_sdk" - }, - { - "type": "build", - "name": "pico_sdk" - } - ] - }, { "name": "raspberry_pi_pico", "steps": [ @@ -2959,15 +3141,41 @@ ] }, { - "name": "cynthion_d11", + "name": "raspberrypi_cm4", "steps": [ { "type": "configure", - "name": "cynthion_d11" + "name": "raspberrypi_cm4" }, { "type": "build", - "name": "cynthion_d11" + "name": "raspberrypi_cm4" + } + ] + }, + { + "name": "raspberrypi_zero", + "steps": [ + { + "type": "configure", + "name": "raspberrypi_zero" + }, + { + "type": "build", + "name": "raspberrypi_zero" + } + ] + }, + { + "name": "raspberrypi_zero2", + "steps": [ + { + "type": "configure", + "name": "raspberrypi_zero2" + }, + { + "type": "build", + "name": "raspberrypi_zero2" } ] }, @@ -2984,227 +3192,6 @@ } ] }, - { - "name": "atsamd21_xpro", - "steps": [ - { - "type": "configure", - "name": "atsamd21_xpro" - }, - { - "type": "build", - "name": "atsamd21_xpro" - } - ] - }, - { - "name": "circuitplayground_express", - "steps": [ - { - "type": "configure", - "name": "circuitplayground_express" - }, - { - "type": "build", - "name": "circuitplayground_express" - } - ] - }, - { - "name": "curiosity_nano", - "steps": [ - { - "type": "configure", - "name": "curiosity_nano" - }, - { - "type": "build", - "name": "curiosity_nano" - } - ] - }, - { - "name": "cynthion_d21", - "steps": [ - { - "type": "configure", - "name": "cynthion_d21" - }, - { - "type": "build", - "name": "cynthion_d21" - } - ] - }, - { - "name": "feather_m0_express", - "steps": [ - { - "type": "configure", - "name": "feather_m0_express" - }, - { - "type": "build", - "name": "feather_m0_express" - } - ] - }, - { - "name": "itsybitsy_m0", - "steps": [ - { - "type": "configure", - "name": "itsybitsy_m0" - }, - { - "type": "build", - "name": "itsybitsy_m0" - } - ] - }, - { - "name": "metro_m0_express", - "steps": [ - { - "type": "configure", - "name": "metro_m0_express" - }, - { - "type": "build", - "name": "metro_m0_express" - } - ] - }, - { - "name": "qtpy", - "steps": [ - { - "type": "configure", - "name": "qtpy" - }, - { - "type": "build", - "name": "qtpy" - } - ] - }, - { - "name": "seeeduino_xiao", - "steps": [ - { - "type": "configure", - "name": "seeeduino_xiao" - }, - { - "type": "build", - "name": "seeeduino_xiao" - } - ] - }, - { - "name": "sparkfun_samd21_mini_usb", - "steps": [ - { - "type": "configure", - "name": "sparkfun_samd21_mini_usb" - }, - { - "type": "build", - "name": "sparkfun_samd21_mini_usb" - } - ] - }, - { - "name": "trinket_m0", - "steps": [ - { - "type": "configure", - "name": "trinket_m0" - }, - { - "type": "build", - "name": "trinket_m0" - } - ] - }, - { - "name": "d5035_01", - "steps": [ - { - "type": "configure", - "name": "d5035_01" - }, - { - "type": "build", - "name": "d5035_01" - } - ] - }, - { - "name": "feather_m4_express", - "steps": [ - { - "type": "configure", - "name": "feather_m4_express" - }, - { - "type": "build", - "name": "feather_m4_express" - } - ] - }, - { - "name": "itsybitsy_m4", - "steps": [ - { - "type": "configure", - "name": "itsybitsy_m4" - }, - { - "type": "build", - "name": "itsybitsy_m4" - } - ] - }, - { - "name": "metro_m4_express", - "steps": [ - { - "type": "configure", - "name": "metro_m4_express" - }, - { - "type": "build", - "name": "metro_m4_express" - } - ] - }, - { - "name": "pybadge", - "steps": [ - { - "type": "configure", - "name": "pybadge" - }, - { - "type": "build", - "name": "pybadge" - } - ] - }, - { - "name": "pyportal", - "steps": [ - { - "type": "configure", - "name": "pyportal" - }, - { - "type": "build", - "name": "pyportal" - } - ] - }, { "name": "same54_xplained", "steps": [ @@ -3231,19 +3218,6 @@ } ] }, - { - "name": "atsaml21_xpro", - "steps": [ - { - "type": "configure", - "name": "atsaml21_xpro" - }, - { - "type": "build", - "name": "atsaml21_xpro" - } - ] - }, { "name": "saml22_feather", "steps": [ @@ -3257,6 +3231,19 @@ } ] }, + { + "name": "seeeduino_xiao", + "steps": [ + { + "type": "configure", + "name": "seeeduino_xiao" + }, + { + "type": "build", + "name": "seeeduino_xiao" + } + ] + }, { "name": "sensorwatch_m0", "steps": [ @@ -3270,6 +3257,45 @@ } ] }, + { + "name": "sipeed_longan_nano", + "steps": [ + { + "type": "configure", + "name": "sipeed_longan_nano" + }, + { + "type": "build", + "name": "sipeed_longan_nano" + } + ] + }, + { + "name": "sparkfun_samd21_mini_usb", + "steps": [ + { + "type": "configure", + "name": "sparkfun_samd21_mini_usb" + }, + { + "type": "build", + "name": "sparkfun_samd21_mini_usb" + } + ] + }, + { + "name": "stlinkv3mini", + "steps": [ + { + "type": "configure", + "name": "stlinkv3mini" + }, + { + "type": "build", + "name": "stlinkv3mini" + } + ] + }, { "name": "stm32c071nucleo", "steps": [ @@ -3322,19 +3348,6 @@ } ] }, - { - "name": "stm32f103ze_iar", - "steps": [ - { - "type": "configure", - "name": "stm32f103ze_iar" - }, - { - "type": "build", - "name": "stm32f103ze_iar" - } - ] - }, { "name": "stm32f103_bluepill", "steps": [ @@ -3361,6 +3374,19 @@ } ] }, + { + "name": "stm32f103ze_iar", + "steps": [ + { + "type": "configure", + "name": "stm32f103ze_iar" + }, + { + "type": "build", + "name": "stm32f103ze_iar" + } + ] + }, { "name": "stm32f207nucleo", "steps": [ @@ -3387,32 +3413,6 @@ } ] }, - { - "name": "feather_stm32f405", - "steps": [ - { - "type": "configure", - "name": "feather_stm32f405" - }, - { - "type": "build", - "name": "feather_stm32f405" - } - ] - }, - { - "name": "pyboardv11", - "steps": [ - { - "type": "configure", - "name": "pyboardv11" - }, - { - "type": "build", - "name": "pyboardv11" - } - ] - }, { "name": "stm32f401blackpill", "steps": [ @@ -3517,19 +3517,6 @@ } ] }, - { - "name": "stlinkv3mini", - "steps": [ - { - "type": "configure", - "name": "stlinkv3mini" - }, - { - "type": "build", - "name": "stlinkv3mini" - } - ] - }, { "name": "stm32f723disco", "steps": [ @@ -3608,19 +3595,6 @@ } ] }, - { - "name": "b_g474e_dpow1", - "steps": [ - { - "type": "configure", - "name": "b_g474e_dpow1" - }, - { - "type": "build", - "name": "b_g474e_dpow1" - } - ] - }, { "name": "stm32g474nucleo", "steps": [ @@ -3686,19 +3660,6 @@ } ] }, - { - "name": "daisyseed", - "steps": [ - { - "type": "configure", - "name": "daisyseed" - }, - { - "type": "build", - "name": "daisyseed" - } - ] - }, { "name": "stm32h723nucleo", "steps": [ @@ -3751,19 +3712,6 @@ } ] }, - { - "name": "stm32h750bdk", - "steps": [ - { - "type": "configure", - "name": "stm32h750bdk" - }, - { - "type": "build", - "name": "stm32h750bdk" - } - ] - }, { "name": "stm32h750_weact", "steps": [ @@ -3778,15 +3726,15 @@ ] }, { - "name": "waveshare_openh743i", + "name": "stm32h750bdk", "steps": [ { "type": "configure", - "name": "waveshare_openh743i" + "name": "stm32h750bdk" }, { "type": "build", - "name": "waveshare_openh743i" + "name": "stm32h750bdk" } ] }, @@ -3881,19 +3829,6 @@ } ] }, - { - "name": "b_u585i_iot2a", - "steps": [ - { - "type": "configure", - "name": "b_u585i_iot2a" - }, - { - "type": "build", - "name": "b_u585i_iot2a" - } - ] - }, { "name": "stm32u545nucleo", "steps": [ @@ -3960,15 +3895,80 @@ ] }, { - "name": "ek_tm4c123gxl", + "name": "teensy_35", "steps": [ { "type": "configure", - "name": "ek_tm4c123gxl" + "name": "teensy_35" }, { "type": "build", - "name": "ek_tm4c123gxl" + "name": "teensy_35" + } + ] + }, + { + "name": "teensy_40", + "steps": [ + { + "type": "configure", + "name": "teensy_40" + }, + { + "type": "build", + "name": "teensy_40" + } + ] + }, + { + "name": "teensy_41", + "steps": [ + { + "type": "configure", + "name": "teensy_41" + }, + { + "type": "build", + "name": "teensy_41" + } + ] + }, + { + "name": "trinket_m0", + "steps": [ + { + "type": "configure", + "name": "trinket_m0" + }, + { + "type": "build", + "name": "trinket_m0" + } + ] + }, + { + "name": "uno_r4", + "steps": [ + { + "type": "configure", + "name": "uno_r4" + }, + { + "type": "build", + "name": "uno_r4" + } + ] + }, + { + "name": "waveshare_openh743i", + "steps": [ + { + "type": "configure", + "name": "waveshare_openh743i" + }, + { + "type": "build", + "name": "waveshare_openh743i" } ] }, diff --git a/tools/gen_presets.py b/tools/gen_presets.py index 98b1a7d46..7542cfdf5 100755 --- a/tools/gen_presets.py +++ b/tools/gen_presets.py @@ -24,46 +24,57 @@ def main(): {"name": "default", "hidden": True, "description": r"Configure preset for the ${presetName} board", - "generator": "Ninja", + "generator": "Ninja Multi-Config", "binaryDir": r"${sourceDir}/build/${presetName}", "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo", + "CMAKE_DEFAULT_BUILD_TYPE": "RelWithDebInfo", "BOARD": r"${presetName}" - } - }] + }}] presets['configurePresets'].extend( - [{'name': board, 'inherits': 'default'} for board in board_list] + sorted( + [ + { + 'name': board, + 'inherits': 'default' + } + for board in board_list + ], key=lambda x: x['name'] + ) ) # Build presets # no inheritance since 'name' doesn't support macro expansion - presets['buildPresets'] = [ - { - 'name': board, - 'description': "Build preset for the " + board + " board", - 'configurePreset': board - } - for board in board_list - ] + presets['buildPresets'] = sorted( + [ + { + 'name': board, + 'description': "Build preset for the " + board + " board", + 'configurePreset': board + } + for board in board_list + ], key=lambda x: x['name'] + ) # Workflow presets - presets['workflowPresets'] = [ - { - "name": board, - "steps": [ - { - "type": "configure", - "name": board - }, - { - "type": "build", - "name": board - } - ] - } - for board in board_list - ] + presets['workflowPresets'] = sorted( + [ + { + "name": board, + "steps": [ + { + "type": "configure", + "name": board + }, + { + "type": "build", + "name": board + } + ] + } + for board in board_list + ], key=lambda x: x['name'] + ) with open("hw/bsp/BoardPresets.json", "w") as f: f.write('{}\n'.format(json.dumps(presets, indent=2))) @@ -87,5 +98,6 @@ def main(): print('Generating presets for the following examples:') print(example_list) + if __name__ == "__main__": main() From f23bef5fd872b9f1fa273c2c03c3288dac4777e5 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Feb 2025 18:36:05 +0700 Subject: [PATCH 37/87] update IAR LMS CLOUD --- .circleci/config2.yml | 1 + .github/workflows/build.yml | 5 ++++- .github/workflows/hil_test.yml | 5 ++++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.circleci/config2.yml b/.circleci/config2.yml index d33307445..3b0294168 100644 --- a/.circleci/config2.yml +++ b/.circleci/config2.yml @@ -121,6 +121,7 @@ commands: TOOLCHAIN_OPTION="--toolchain clang" elif [ << parameters.toolchain >> == arm-iar ]; then TOOLCHAIN_OPTION="--toolchain iar" + echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL iccarm --version elif [ << parameters.toolchain >> == arm-gcc ]; then TOOLCHAIN_OPTION="--toolchain gcc" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4c54efeaf..547763bd8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -119,6 +119,7 @@ jobs: runs-on: [self-hosted, Linux, X64, hifiphile] env: BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }} + IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }} IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} steps: - name: Clean workspace @@ -128,7 +129,9 @@ jobs: mkdir -p "${{ github.workspace }}" - name: Toolchain version - run: iccarm --version + run: | + echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL + iccarm --version - name: Checkout TinyUSB uses: actions/checkout@v4 diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml index 6e9ba924b..c890933ec 100644 --- a/.github/workflows/hil_test.yml +++ b/.github/workflows/hil_test.yml @@ -96,6 +96,7 @@ jobs: if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false runs-on: [self-hosted, Linux, X64, hifiphile] env: + IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }} IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }} steps: - name: Clean workspace @@ -105,7 +106,9 @@ jobs: mkdir -p "${{ github.workspace }}" - name: Toolchain version - run: iccarm --version + run: | + echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL + iccarm --version - name: Checkout TinyUSB uses: actions/checkout@v4 From 5a39bcf79ce564ce2b53b59223f9f384cba89d15 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Feb 2025 17:53:58 +0700 Subject: [PATCH 38/87] remove freeeRTOSConfig in examples --- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 ------------------ src/osal/osal_none.h | 24 +-- 2 files changed, 6 insertions(+), 209 deletions(-) delete mode 100644 examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h diff --git a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index 902a54f08..000000000 --- a/examples/device/cdc_msc_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * FreeRTOS Kernel V10.0.0 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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. If you wish to use our Amazon - * FreeRTOS name, please do so in a fair use way that does not cause confusion. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -// skip if included from IAR assembler -#ifndef __IASMARM__ - -// Include MCU header -#include "bsp/board_mcu.h" - -#if TUSB_MCU_VENDOR_ESPRESSIF - #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" -#endif - -// TODO fix later -#if CFG_TUSB_MCU == OPT_MCU_MM32F327X - extern u32 SystemCoreClock; -#else - // FIXME cause redundant-decls warnings - extern uint32_t SystemCoreClock; -#endif - -#endif - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) -#define configRUN_FREERTOS_SECURE_ONLY 1 - -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ ( 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 4 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 -#define configCHECK_HANDLER_INSTALLATION 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 0 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -#ifdef __RX__ -/* Renesas RX series */ -#define vSoftwareInterruptISR INT_Excep_ICU_SWINT -#define vTickISR INT_Excep_CMT0_CMI0 -#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) -#define configKERNEL_INTERRUPT_PRIORITY 1 -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 - -#else - -/* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler - -//--------------------------------------------------------------------+ -// Interrupt nesting behavior configuration. -//--------------------------------------------------------------------+ -#if defined(__NVIC_PRIO_BITS) - // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h - #define configPRIO_BITS __NVIC_PRIO_BITS - -#elif defined(__ECLIC_INTCTLBITS) - // RISC-V Bumblebee core from nuclei - #define configPRIO_BITS __ECLIC_INTCTLBITS - -#elif defined(__IASMARM__) - // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. - // Therefore we will hard coded it to minimum value of 2 to get pass ci build. - // IAR user must update this to correct value of the target MCU - #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" - #define configPRIO_BITS 2 - -#else - #error "FreeRTOS configPRIO_BITS to be defined" -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<interrupt_set(false); -} - -// unlock queue -TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) { - // enable dcd/hcd interrupt - qhdl->interrupt_set(true); -} - TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) { tu_fifo_clear(&qdef->ff); return (osal_queue_t) qdef; @@ -162,22 +150,22 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) { TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) { (void) msec; // not used, always behave as msec = 0 - _osal_q_lock(qhdl); - bool success = tu_fifo_read(&qhdl->ff, data); - _osal_q_unlock(qhdl); + qhdl->interrupt_set(false); + const bool success = tu_fifo_read(&qhdl->ff, data); + qhdl->interrupt_set(true); return success; } TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) { if (!in_isr) { - _osal_q_lock(qhdl); + qhdl->interrupt_set(false); } - bool success = tu_fifo_write(&qhdl->ff, data); + const bool success = tu_fifo_write(&qhdl->ff, data); if (!in_isr) { - _osal_q_unlock(qhdl); + qhdl->interrupt_set(true); } return success; From f1ce4918c2282a352ca532406c9b1c54c30668e2 Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 11 Feb 2025 21:18:07 +0700 Subject: [PATCH 39/87] update make to use FreeRTOSConfig in family instead of examples --- examples/build_system/make/make.mk | 39 +++- .../audio_4_channel_mic_freertos/Makefile | 24 +-- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 ----------------- examples/device/audio_test_freertos/Makefile | 24 +-- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 ----------------- examples/device/cdc_msc_freertos/Makefile | 31 +-- .../device/hid_composite_freertos/Makefile | 33 +-- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 191 ----------------- examples/device/midi_test_freertos/Makefile | 27 +-- examples/host/cdc_msc_hid_freertos/Makefile | 18 +- .../src/FreeRTOSConfig/FreeRTOSConfig.h | 199 ------------------ 11 files changed, 41 insertions(+), 927 deletions(-) delete mode 100644 examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 examples/device/audio_test_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 examples/device/hid_composite_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h delete mode 100644 examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index 1500a51e0..206516eaf 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -6,7 +6,6 @@ # Toolchain # Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang #------------------------------------------------------------- - ifneq (,$(findstring clang,$(CC))) TOOLCHAIN = clang else ifneq (,$(findstring iccarm,$(CC))) @@ -65,7 +64,9 @@ BUILD := _build/$(BOARD) PROJECT := $(notdir $(CURDIR)) BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR)) -#-------------- Select the board to build for. ------------ +#------------------------------------------------------------- +# Board / Family +#------------------------------------------------------------- # Board without family ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),) @@ -93,7 +94,9 @@ else SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c)) endif -#-------------- Source files and compiler flags -------------- +#------------------------------------------------------------- +# Source files and compiler flags +#------------------------------------------------------------- # tinyusb makefile include $(TOP)/src/tinyusb.mk SRC_C += $(TINYUSB_SRC_C) @@ -148,7 +151,35 @@ endif # toolchain specific include ${TOP}/examples/build_system/make/toolchain/arm_$(TOOLCHAIN).mk -# Handy check parameter function +#---------------------- FreeRTOS ----------------------- +FREERTOS_SRC = lib/FreeRTOS-Kernel +FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) + +ifeq ($(RTOS),freertos) + SRC_C += \ + $(FREERTOS_SRC)/list.c \ + $(FREERTOS_SRC)/queue.c \ + $(FREERTOS_SRC)/tasks.c \ + $(FREERTOS_SRC)/timers.c \ + $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) + + SRC_S += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) + INC += \ + $(TOP)/hw/bsp/$(FAMILY)/FreeRTOSConfig \ + $(TOP)/$(FREERTOS_SRC)/include \ + $(TOP)/$(FREERTOS_PORTABLE_SRC) + + # Suppress FreeRTOSConfig.h warnings + CFLAGS_GCC += -Wno-error=redundant-decls + + # Suppress FreeRTOS source warnings + CFLAGS_GCC += -Wno-error=cast-qual + + # FreeRTOS (lto + Os) linker issue + LDFLAGS_GCC += -Wl,--undefined=vTaskSwitchContext +endif + +#---------------- Helper ---------------- check_defined = \ $(strip $(foreach 1,$1, \ $(call __check_defined,$1,$(strip $(value 2))))) diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile index 0202f631c..bd625b345 100644 --- a/examples/device/audio_4_channel_mic_freertos/Makefile +++ b/examples/device/audio_4_channel_mic_freertos/Makefile @@ -1,14 +1,9 @@ +RTOS = freertos include ../../build_system/make/make.mk -FREERTOS_SRC = lib/FreeRTOS-Kernel -FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC) - INC += \ src \ - src/FreeRTOSConfig \ $(TOP)/hw \ - $(TOP)/$(FREERTOS_SRC)/include \ - $(TOP)/$(FREERTOS_PORTABLE_SRC) \ # Example source EXAMPLE_SOURCE = \ @@ -17,21 +12,4 @@ EXAMPLE_SOURCE = \ SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -# FreeRTOS source, all files in port folder -SRC_C += \ - $(FREERTOS_SRC)/list.c \ - $(FREERTOS_SRC)/queue.c \ - $(FREERTOS_SRC)/tasks.c \ - $(FREERTOS_SRC)/timers.c \ - $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c)) - -SRC_S += \ - $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s)) - -# Suppress FreeRTOS warnings -CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls - -# FreeRTOS (lto + Os) linker issue -LDFLAGS += -Wl,--undefined=vTaskSwitchContext - include ../../build_system/make/rules.mk diff --git a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h deleted file mode 100644 index 902a54f08..000000000 --- a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * FreeRTOS Kernel V10.0.0 - * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. - * - * 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. If you wish to use our Amazon - * FreeRTOS name, please do so in a fair use way that does not cause confusion. - * - * 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. - * - * http://www.FreeRTOS.org - * http://aws.amazon.com/freertos - * - * 1 tab == 4 spaces! - */ - - -#ifndef FREERTOS_CONFIG_H -#define FREERTOS_CONFIG_H - -/*----------------------------------------------------------- - * Application specific definitions. - * - * These definitions should be adjusted for your particular hardware and - * application requirements. - * - * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE - * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. - * - * See http://www.freertos.org/a00110.html. - *----------------------------------------------------------*/ - -// skip if included from IAR assembler -#ifndef __IASMARM__ - -// Include MCU header -#include "bsp/board_mcu.h" - -#if TUSB_MCU_VENDOR_ESPRESSIF - #error "ESP32-Sx should use IDF's FreeRTOSConfig.h" -#endif - -// TODO fix later -#if CFG_TUSB_MCU == OPT_MCU_MM32F327X - extern u32 SystemCoreClock; -#else - // FIXME cause redundant-decls warnings - extern uint32_t SystemCoreClock; -#endif - -#endif - -/* Cortex M23/M33 port configuration. */ -#define configENABLE_MPU 0 -#define configENABLE_FPU 1 -#define configENABLE_TRUSTZONE 0 -#define configMINIMAL_SECURE_STACK_SIZE ( 1024 ) -#define configRUN_FREERTOS_SECURE_ONLY 1 - -#define configUSE_PREEMPTION 1 -#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 -#define configCPU_CLOCK_HZ SystemCoreClock -#define configTICK_RATE_HZ ( 1000 ) -#define configMAX_PRIORITIES ( 5 ) -#define configMINIMAL_STACK_SIZE ( 128 ) -#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 ) -#define configMAX_TASK_NAME_LEN 16 -#define configUSE_16_BIT_TICKS 0 -#define configIDLE_SHOULD_YIELD 1 -#define configUSE_MUTEXES 1 -#define configUSE_RECURSIVE_MUTEXES 1 -#define configUSE_COUNTING_SEMAPHORES 1 -#define configQUEUE_REGISTRY_SIZE 4 -#define configUSE_QUEUE_SETS 0 -#define configUSE_TIME_SLICING 0 -#define configUSE_NEWLIB_REENTRANT 0 -#define configENABLE_BACKWARD_COMPATIBILITY 1 -#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0 - -#define configSUPPORT_STATIC_ALLOCATION 1 -#define configSUPPORT_DYNAMIC_ALLOCATION 0 - -/* Hook function related definitions. */ -#define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 -#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning -#define configCHECK_FOR_STACK_OVERFLOW 2 -#define configCHECK_HANDLER_INSTALLATION 0 - -/* Run time and task stats gathering related definitions. */ -#define configGENERATE_RUN_TIME_STATS 0 -#define configUSE_TRACE_FACILITY 1 // legacy trace -#define configUSE_STATS_FORMATTING_FUNCTIONS 0 - -/* Co-routine definitions. */ -#define configUSE_CO_ROUTINES 0 -#define configMAX_CO_ROUTINE_PRIORITIES 2 - -/* Software timer related definitions. */ -#define configUSE_TIMERS 1 -#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2) -#define configTIMER_QUEUE_LENGTH 32 -#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE - -/* Optional functions - most linkers will remove unused functions anyway. */ -#define INCLUDE_vTaskPrioritySet 0 -#define INCLUDE_uxTaskPriorityGet 0 -#define INCLUDE_vTaskDelete 0 -#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY -#define INCLUDE_xResumeFromISR 0 -#define INCLUDE_vTaskDelayUntil 1 -#define INCLUDE_vTaskDelay 1 -#define INCLUDE_xTaskGetSchedulerState 0 -#define INCLUDE_xTaskGetCurrentTaskHandle 0 -#define INCLUDE_uxTaskGetStackHighWaterMark 0 -#define INCLUDE_xTaskGetIdleTaskHandle 0 -#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0 -#define INCLUDE_pcTaskGetTaskName 0 -#define INCLUDE_eTaskGetState 0 -#define INCLUDE_xEventGroupSetBitFromISR 0 -#define INCLUDE_xTimerPendFunctionCall 0 - -#ifdef __RX__ -/* Renesas RX series */ -#define vSoftwareInterruptISR INT_Excep_ICU_SWINT -#define vTickISR INT_Excep_CMT0_CMI0 -#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2) -#define configKERNEL_INTERRUPT_PRIORITY 1 -#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4 - -#else - -/* FreeRTOS hooks to NVIC vectors */ -#define xPortPendSVHandler PendSV_Handler -#define xPortSysTickHandler SysTick_Handler -#define vPortSVCHandler SVC_Handler - -//--------------------------------------------------------------------+ -// Interrupt nesting behavior configuration. -//--------------------------------------------------------------------+ -#if defined(__NVIC_PRIO_BITS) - // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h - #define configPRIO_BITS __NVIC_PRIO_BITS - -#elif defined(__ECLIC_INTCTLBITS) - // RISC-V Bumblebee core from nuclei - #define configPRIO_BITS __ECLIC_INTCTLBITS - -#elif defined(__IASMARM__) - // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS. - // Therefore we will hard coded it to minimum value of 2 to get pass ci build. - // IAR user must update this to correct value of the target MCU - #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU" - #define configPRIO_BITS 2 - -#else - #error "FreeRTOS configPRIO_BITS to be defined" -#endif - -/* The lowest interrupt priority that can be used in a call to a "set priority" function. */ -#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< Date: Tue, 11 Feb 2025 21:55:28 +0700 Subject: [PATCH 40/87] remove board_mcu.h --- examples/build_system/make/make.mk | 2 + hw/bsp/board.c | 4 +- hw/bsp/board_mcu.h | 193 ----------------------------- 3 files changed, 3 insertions(+), 196 deletions(-) delete mode 100644 hw/bsp/board_mcu.h diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk index 206516eaf..3101b66b9 100644 --- a/examples/build_system/make/make.mk +++ b/examples/build_system/make/make.mk @@ -169,6 +169,8 @@ ifeq ($(RTOS),freertos) $(TOP)/$(FREERTOS_SRC)/include \ $(TOP)/$(FREERTOS_PORTABLE_SRC) + CFLAGS += -DCFG_TUSB_OS=OPT_OS_FREERTOS + # Suppress FreeRTOSConfig.h warnings CFLAGS_GCC += -Wno-error=redundant-decls diff --git a/hw/bsp/board.c b/hw/bsp/board.c index 5bcdb7f15..0e0fa4ac6 100644 --- a/hw/bsp/board.c +++ b/hw/bsp/board.c @@ -64,9 +64,7 @@ int sys_read(int fhdl, char *buf, size_t count) { #endif #elif defined(LOGGER_SWO) -// Logging with SWO for ARM Cortex -#include "board_mcu.h" - +// Logging with SWO for ARM Cortex-M int sys_write (int fhdl, const char *buf, size_t count) { (void) fhdl; uint8_t const* buf8 = (uint8_t const*) buf; diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h deleted file mode 100644 index e720cd747..000000000 --- a/hw/bsp/board_mcu.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2020, Ha Thach (tinyusb.org) - * - * 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. - * - * This file is part of the TinyUSB stack. - */ - - -#ifndef BOARD_MCU_H_ -#define BOARD_MCU_H_ - -#include "tusb_option.h" - -//--------------------------------------------------------------------+ -// Low Level MCU header include. Example should be -// platform independent and mostly doesn't need to include this file. -// However there are still certain situation where this file is needed: -// - FreeRTOSConfig.h to set up correct clock and NVIC interrupts for ARM Cortex -// - SWO logging for Cortex M with ITM_SendChar() / ITM_ReceiveChar() -//--------------------------------------------------------------------+ - -// Include order follows OPT_MCU_ number -#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) || \ - TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC18XX) || \ - TU_CHECK_MCU(OPT_MCU_LPC40XX, OPT_MCU_LPC43XX) - #include "chip.h" - -#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX, OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX, OPT_MCU_MCXN9) - #include "fsl_device_registers.h" - -#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K) - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NRF5X - #include "nrf.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \ - CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \ - CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21 - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_SAMG - #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined - #include "sam.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F0 - #include "stm32f0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F1 - #include "stm32f1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F2 - #include "stm32f2xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F3 - #include "stm32f3xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F4 - #include "stm32f4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32F7 - #include "stm32f7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G4 - #include "stm32g4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H5 - #include "stm32h5xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32H7 - #include "stm32h7xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L0 - #include "stm32l0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L1 - #include "stm32l1xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32L4 - #include "stm32l4xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32WB - #include "stm32wbxx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32U5 - #include "stm32u5xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32G0 - #include "stm32g0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_STM32C0 - #include "stm32c0xx.h" - -#elif CFG_TUSB_MCU == OPT_MCU_CXD56 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MSP430x5xx - #include "msp430.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4 - #include "msp.h" - -#elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX - #include "fsl_device_registers.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC120 - #include "NUC100Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126 - #include "NuMicro.h" - -#elif CFG_TUSB_MCU == OPT_MCU_NUC505 - #include "NUC505Series.h" - -#elif CFG_TUSB_MCU == OPT_MCU_ESP32S2 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_ESP32S3 - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_DA1469X - #include "DA1469xAB.h" - -#elif CFG_TUSB_MCU == OPT_MCU_RP2040 - #include "pico.h" - -#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG - #include "em_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_RAXXX - #include "bsp_api.h" - -#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103 - #include "gd32vf103.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MM32F327X - #include "mm32_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_XMC4000 - #include "xmc_device.h" - -#elif CFG_TUSB_MCU == OPT_MCU_TM4C123 - #include "TM4C123.h" - -#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X - #include "ch32f20x.h" - -#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837) - // no header needed - -#elif CFG_TUSB_MCU == OPT_MCU_MAX32690 - #include "max32690.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MAX32650 - #include "max32650.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MAX32666 - #include "max32665.h" - -#elif CFG_TUSB_MCU == OPT_MCU_MAX78002 - #include "max78002.h" - -#else - #error "Missing MCU header" -#endif - - -#endif /* BOARD_MCU_H_ */ From 14f1feac8412668206e69a1178bd29d569f01994 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Tue, 11 Feb 2025 20:56:41 +0100 Subject: [PATCH 41/87] Fix path. Signed-off-by: HiFiPhile --- examples/CMakePresets.json | 2 +- examples/device/CMakePresets.json | 2 +- .../audio_4_channel_mic_freertos/src/CMakePresets.json | 6 ------ .../device/audio_test_freertos/src/CMakePresets.json | 6 ------ examples/device/board_test/src/CMakePresets.json | 6 ------ examples/device/cdc_msc_freertos/src/CMakePresets.json | 6 ------ .../hid_composite_freertos/src/CMakePresets.json | 6 ------ .../device/midi_test_freertos/src/CMakePresets.json | 6 ------ examples/device/video_capture/src/CMakePresets.json | 6 ------ .../device/video_capture_2ch/src/CMakePresets.json | 6 ------ examples/dual/CMakePresets.json | 2 +- examples/host/CMakePresets.json | 2 +- .../host/cdc_msc_hid_freertos/src/CMakePresets.json | 6 ------ examples/host/device_info/src/CMakePresets.json | 6 ------ examples/typec/CMakePresets.json | 2 +- tools/gen_presets.py | 10 ++++++---- 16 files changed, 11 insertions(+), 69 deletions(-) delete mode 100644 examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json delete mode 100644 examples/device/audio_test_freertos/src/CMakePresets.json delete mode 100644 examples/device/board_test/src/CMakePresets.json delete mode 100644 examples/device/cdc_msc_freertos/src/CMakePresets.json delete mode 100644 examples/device/hid_composite_freertos/src/CMakePresets.json delete mode 100644 examples/device/midi_test_freertos/src/CMakePresets.json delete mode 100644 examples/device/video_capture/src/CMakePresets.json delete mode 100644 examples/device/video_capture_2ch/src/CMakePresets.json delete mode 100644 examples/host/cdc_msc_hid_freertos/src/CMakePresets.json delete mode 100644 examples/host/device_info/src/CMakePresets.json diff --git a/examples/CMakePresets.json b/examples/CMakePresets.json index 5cd8971e9..2f904a269 100644 --- a/examples/CMakePresets.json +++ b/examples/CMakePresets.json @@ -1,6 +1,6 @@ { "version": 6, "include": [ - "../../../hw/bsp/BoardPresets.json" + "../hw/bsp/BoardPresets.json" ] } diff --git a/examples/device/CMakePresets.json b/examples/device/CMakePresets.json index 5cd8971e9..c22e8c0ec 100644 --- a/examples/device/CMakePresets.json +++ b/examples/device/CMakePresets.json @@ -1,6 +1,6 @@ { "version": 6, "include": [ - "../../../hw/bsp/BoardPresets.json" + "../../hw/bsp/BoardPresets.json" ] } diff --git a/examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json b/examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/audio_4_channel_mic_freertos/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/audio_test_freertos/src/CMakePresets.json b/examples/device/audio_test_freertos/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/audio_test_freertos/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/board_test/src/CMakePresets.json b/examples/device/board_test/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/board_test/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/cdc_msc_freertos/src/CMakePresets.json b/examples/device/cdc_msc_freertos/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/cdc_msc_freertos/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/hid_composite_freertos/src/CMakePresets.json b/examples/device/hid_composite_freertos/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/hid_composite_freertos/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/midi_test_freertos/src/CMakePresets.json b/examples/device/midi_test_freertos/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/midi_test_freertos/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/video_capture/src/CMakePresets.json b/examples/device/video_capture/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/video_capture/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/device/video_capture_2ch/src/CMakePresets.json b/examples/device/video_capture_2ch/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/device/video_capture_2ch/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/dual/CMakePresets.json b/examples/dual/CMakePresets.json index 5cd8971e9..c22e8c0ec 100644 --- a/examples/dual/CMakePresets.json +++ b/examples/dual/CMakePresets.json @@ -1,6 +1,6 @@ { "version": 6, "include": [ - "../../../hw/bsp/BoardPresets.json" + "../../hw/bsp/BoardPresets.json" ] } diff --git a/examples/host/CMakePresets.json b/examples/host/CMakePresets.json index 5cd8971e9..c22e8c0ec 100644 --- a/examples/host/CMakePresets.json +++ b/examples/host/CMakePresets.json @@ -1,6 +1,6 @@ { "version": 6, "include": [ - "../../../hw/bsp/BoardPresets.json" + "../../hw/bsp/BoardPresets.json" ] } diff --git a/examples/host/cdc_msc_hid_freertos/src/CMakePresets.json b/examples/host/cdc_msc_hid_freertos/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/host/cdc_msc_hid_freertos/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/host/device_info/src/CMakePresets.json b/examples/host/device_info/src/CMakePresets.json deleted file mode 100644 index 5cd8971e9..000000000 --- a/examples/host/device_info/src/CMakePresets.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "version": 6, - "include": [ - "../../../hw/bsp/BoardPresets.json" - ] -} diff --git a/examples/typec/CMakePresets.json b/examples/typec/CMakePresets.json index 5cd8971e9..c22e8c0ec 100644 --- a/examples/typec/CMakePresets.json +++ b/examples/typec/CMakePresets.json @@ -1,6 +1,6 @@ { "version": 6, "include": [ - "../../../hw/bsp/BoardPresets.json" + "../../hw/bsp/BoardPresets.json" ] } diff --git a/tools/gen_presets.py b/tools/gen_presets.py index 7542cfdf5..94b8d16b0 100755 --- a/tools/gen_presets.py +++ b/tools/gen_presets.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import os import json - +from pathlib import Path def main(): board_list = [] @@ -76,21 +76,23 @@ def main(): ], key=lambda x: x['name'] ) - with open("hw/bsp/BoardPresets.json", "w") as f: + path_boardpresets = "hw/bsp/BoardPresets.json" + with open(path_boardpresets, "w") as f: f.write('{}\n'.format(json.dumps(presets, indent=2))) # Generate presets for examples presets = { "version": 6, "include": [ - "../../../hw/bsp/BoardPresets.json" ] } example_list = [] for root, dirs, files in os.walk("examples"): for file in files: - if file == "CMakeLists.txt": + # Filter out ESP-IDF CMakeLists.txt in src folder + if file == "CMakeLists.txt" and os.path.basename(root) != 'src': + presets['include'] = [os.path.relpath(path_boardpresets, root).replace(os.sep, '/')] with open(os.path.join(root, 'CMakePresets.json'), 'w') as f: f.write('{}\n'.format(json.dumps(presets, indent=2))) example_list.append(os.path.basename(root)) From 85247e50ddc17347fca1f6c9b9fedb1227eda25f Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Feb 2025 11:34:32 +0700 Subject: [PATCH 42/87] clean up --- hw/bsp/rp2040/family.cmake | 30 +++++++++++++++--------------- src/class/midi/midi_device.c | 2 +- src/device/usbd.c | 13 ++++++------- src/host/usbh.c | 8 ++++++-- src/tusb_option.h | 6 +++--- 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index cf5295f22..1cbc0742c 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -100,21 +100,21 @@ target_sources(tinyusb_device_base INTERFACE ${TOP}/src/class/video/video_device.c ) - #------------------------------------ - # Base config for host mode; wrapped by SDK's tinyusb_host - #------------------------------------ - add_library(tinyusb_host_base INTERFACE) - target_sources(tinyusb_host_base INTERFACE - ${TOP}/src/portable/raspberrypi/rp2040/hcd_rp2040.c - ${TOP}/src/portable/raspberrypi/rp2040/rp2040_usb.c - ${TOP}/src/host/usbh.c - ${TOP}/src/host/hub.c - ${TOP}/src/class/cdc/cdc_host.c - ${TOP}/src/class/hid/hid_host.c - ${TOP}/src/class/midi/midi_host.c - ${TOP}/src/class/msc/msc_host.c - ${TOP}/src/class/vendor/vendor_host.c - ) +#------------------------------------ +# Base config for host mode; wrapped by SDK's tinyusb_host +#------------------------------------ +add_library(tinyusb_host_base INTERFACE) +target_sources(tinyusb_host_base INTERFACE + ${TOP}/src/portable/raspberrypi/rp2040/hcd_rp2040.c + ${TOP}/src/portable/raspberrypi/rp2040/rp2040_usb.c + ${TOP}/src/host/usbh.c + ${TOP}/src/host/hub.c + ${TOP}/src/class/cdc/cdc_host.c + ${TOP}/src/class/hid/hid_host.c + ${TOP}/src/class/midi/midi_host.c + ${TOP}/src/class/msc/msc_host.c + ${TOP}/src/class/vendor/vendor_host.c + ) # Sometimes have to do host specific actions in mostly common functions target_compile_definitions(tinyusb_host_base INTERFACE diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 4ae8ea8fa..dd1883e37 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -440,7 +440,7 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint1 drv_len = tu_desc_len(desc_itf); p_desc = tu_desc_next(desc_itf); // Skip Class Specific descriptors - while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len ) { + while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) { drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } diff --git a/src/device/usbd.c b/src/device/usbd.c index 20f803563..faf926855 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1032,14 +1032,13 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num) #endif #if CFG_TUD_MIDI - if ( driver->open == midid_open ) - { - // If there is a class-compliant Audio Control Class, then 2 interfaces - // Otherwise, only one + if (driver->open == midid_open) { + // If there is a class-compliant Audio Control Class, then 2 interfaces. Otherwise, only one if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass && - AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && - AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) - assoc_itf_count = 2; + AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass && + AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) { + assoc_itf_count = 2; + } } #endif diff --git a/src/host/usbh.c b/src/host/usbh.c index 6f7a8b8bf..30a4f5f63 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1488,7 +1488,9 @@ static void process_enumeration(tuh_xfer_t* xfer) { dev->i_product = desc_device->iProduct; dev->i_serial = desc_device->iSerialNumber; - if (tuh_desc_device_cb) tuh_desc_device_cb(daddr, (tusb_desc_device_t const*) _usbh_ctrl_buf); + if (tuh_desc_device_cb) { + tuh_desc_device_cb(daddr, (tusb_desc_device_t const*) _usbh_ctrl_buf); + } // Get 9-byte for total length uint8_t const config_idx = CONFIG_NUM - 1; @@ -1517,7 +1519,9 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_SET_CONFIG: - if (tuh_desc_config_cb) tuh_desc_config_cb(daddr, (const tusb_desc_configuration_t*) _usbh_ctrl_buf); + if (tuh_desc_config_cb) { + tuh_desc_config_cb(daddr, (const tusb_desc_configuration_t*) _usbh_ctrl_buf); + } TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),); break; diff --git a/src/tusb_option.h b/src/tusb_option.h index 84319939a..29fdcb0d6 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -657,9 +657,9 @@ //------------------------------------------------------------------ // Configuration Validation //------------------------------------------------------------------ -//#if CFG_TUD_ENDPOINT0_SIZE > 64 -// #error Control Endpoint Max Packet Size cannot be larger than 64 -//#endif +#if CFG_TUD_ENDPOINT0_SIZE > 64 + #error Control Endpoint Max Packet Size cannot be larger than 64 +#endif // To avoid GCC compiler warnings when -pedantic option is used (strict ISO C) typedef int make_iso_compilers_happy; From 294fb268d7bf36d163363fa669f3984fc95bfd32 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Feb 2025 11:39:26 +0700 Subject: [PATCH 43/87] pre-commit fix --- examples/host/midi_rx/CMakeLists.txt | 2 +- examples/host/midi_rx/Makefile | 2 +- examples/host/midi_rx/src/main.c | 2 +- src/class/midi/README_midi_host.md | 14 +++++++------- src/class/midi/midi_host.c | 14 +++++++------- src/class/midi/midi_host.h | 4 ++-- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/examples/host/midi_rx/CMakeLists.txt b/examples/host/midi_rx/CMakeLists.txt index 4856e0a47..b5e5f6bc8 100644 --- a/examples/host/midi_rx/CMakeLists.txt +++ b/examples/host/midi_rx/CMakeLists.txt @@ -24,4 +24,4 @@ target_include_directories(${PROJECT} PUBLIC # Configure compilation flags and libraries for the example... see the corresponding function # in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT}) \ No newline at end of file +family_configure_host_example(${PROJECT}) diff --git a/examples/host/midi_rx/Makefile b/examples/host/midi_rx/Makefile index f830617ac..af8ef4275 100644 --- a/examples/host/midi_rx/Makefile +++ b/examples/host/midi_rx/Makefile @@ -6,4 +6,4 @@ INC += \ # Example source EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk \ No newline at end of file +include ../../rules.mk diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 6fe17255a..6c3311043 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -157,4 +157,4 @@ void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) void tuh_midi_tx_cb(uint8_t dev_addr) { (void ) dev_addr; -} \ No newline at end of file +} diff --git a/src/class/midi/README_midi_host.md b/src/class/midi/README_midi_host.md index 9df2249b3..efaf7a13d 100644 --- a/src/class/midi/README_midi_host.md +++ b/src/class/midi/README_midi_host.md @@ -9,7 +9,7 @@ constraint may change in the future. # MAXIMUM NUMBER OF ENDPOINTS Although the USB MIDI 1.0 Class specification allows an arbitrary number of endpoints, this driver supports at most one USB BULK DATA IN endpoint -and one USB BULK DATA OUT endpoint. Each endpoint can support up to 16 +and one USB BULK DATA OUT endpoint. Each endpoint can support up to 16 virtual cables. If a device has multiple IN endpoints or multiple OUT endpoints, it will fail to enumerate. @@ -51,9 +51,9 @@ pointer points to a MIDI interface descriptor, call midih_open() with that descriptor pointer. # CLASS SPECIFIC INTERFACE AND REQUESTS -The host driver does not make use of the informaton in the class specific +The host driver does not make use of the information in the class specific interface descriptors. In the future, a public API could be created to -retrieve the string descriptors for the names of each ELEMENT, +retrieve the string descriptors for the names of each ELEMENT, IN JACK and OUT JACK, and how the device describes the connections. This driver also does not support class specific requests to control @@ -68,18 +68,18 @@ Descriptors. This is wrong per my reading of the specification. # MESSAGE BUFFER DETAILS Messages buffers composed from USB data received on the IN endpoint will never contain running status because USB MIDI 1.0 class does not support that. Messages -buffers to be sent to the device on the OUT endpont may contain running status +buffers to be sent to the device on the OUT endpoint may contain running status (the message might come from a UART data stream from a 5-pin DIN MIDI IN -cable on the host, for example). The driver may in the future correctly compose +cable on the host, for example). The driver may in the future correctly compose 4-byte USB MIDI Class packets using the running status if need be. However, it does not currently do that. Also, use of running status is not a good idea overall because a single byte error can really mess up the data stream with no way to recover until the next non-real time status byte is in the message buffer. Message buffers to be sent to the device may contain Real time messages -such as MIDI clock. Real time messages may be inserted in the message +such as MIDI clock. Real time messages may be inserted in the message byte stream between status and data bytes of another message without disrupting -the running status. However, because MIDI 1.0 class messages are sent +the running status. However, because MIDI 1.0 class messages are sent as four byte packets, a real-time message so inserted will be re-ordered to be sent to the device in a new 4-byte packet immediately before the interrupted data stream. diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 32311556e..061e17fee 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -76,7 +76,7 @@ typedef struct // Endpoint FIFOs tu_fifo_t rx_ff; tu_fifo_t tx_ff; - + uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; @@ -280,17 +280,17 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d // assume it is an interface header midi_desc_header_t const *p_mdh = (midi_desc_header_t const *)p_desc; - TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || + TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); - uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descrptor + uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descriptor p_midi_host->itf_num = desc_itf->bInterfaceNumber; tusb_desc_endpoint_t const* in_desc = NULL; tusb_desc_endpoint_t const* out_desc = NULL; while (len_parsed < max_len) { - TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || + TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); @@ -306,7 +306,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) { - // Then it is an in jack. + // Then it is an in jack. TU_LOG2("Found in jack\r\n"); #if CFG_MIDI_HOST_DEVSTRINGS if (p_midi_host->next_in_jack < MAX_IN_JACKS) @@ -370,7 +370,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG2("found CS_ENDPOINT Descriptor for %u\r\n", prev_ep_addr); TU_VERIFY(prev_ep_addr != 0); // parse out the mapping between the device's embedded jacks and the endpoints - // Each embedded IN jack is assocated with an OUT endpoint + // Each embedded IN jack is associated with an OUT endpoint midi_cs_desc_endpoint_t const* p_csep = (midi_cs_desc_endpoint_t const*)p_mdh; if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) { diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 8180e3309..292c596e4 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -118,7 +118,7 @@ void midih_close (uint8_t dev_addr); //--------------------------------------------------------------------+ // Invoked when device with MIDI interface is mounted. -// If the MIDI host application requires MIDI IN, it should requst an +// If the MIDI host application requires MIDI IN, it should request an // IN transfer here. The device will likely NAK this transfer. How the driver // handles the NAK is hardware dependent. TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx); From 7c405236cfcf0850032ec0190eea1f01fb631ef9 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Feb 2025 11:50:57 +0700 Subject: [PATCH 44/87] fix host midi build --- examples/host/midi_rx/CMakeLists.txt | 25 +++++++++++++++---------- examples/host/midi_rx/Makefile | 12 ++++++++---- examples/host/midi_rx/only.txt | 19 +++++++++++++++++++ examples/host/midi_rx/src/main.c | 4 +--- src/CMakeLists.txt | 1 + src/class/midi/midi_host.c | 5 +++-- src/class/midi/midi_host.h | 2 +- src/host/usbh.c | 4 ++-- src/tinyusb.mk | 1 + 9 files changed, 51 insertions(+), 22 deletions(-) diff --git a/examples/host/midi_rx/CMakeLists.txt b/examples/host/midi_rx/CMakeLists.txt index b5e5f6bc8..33953233d 100644 --- a/examples/host/midi_rx/CMakeLists.txt +++ b/examples/host/midi_rx/CMakeLists.txt @@ -1,27 +1,32 @@ -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.20) include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake) -# gets PROJECT name for the example (e.g. -) +# gets PROJECT name for the example family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR}) -project(${PROJECT}) +project(${PROJECT} C CXX ASM) # Checks this example is valid for the family and initializes the project family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR}) +# Espressif has its own cmake build system +if(FAMILY STREQUAL "espressif") + return() +endif() + add_executable(${PROJECT}) # Example source target_sources(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c + ) # Example include target_include_directories(${PROJECT} PUBLIC - ${CMAKE_CURRENT_SOURCE_DIR}/src - ) + ${CMAKE_CURRENT_SOURCE_DIR}/src + ) -# Configure compilation flags and libraries for the example... see the corresponding function -# in hw/bsp/FAMILY/family.cmake for details. -family_configure_host_example(${PROJECT}) +# Configure compilation flags and libraries for the example without RTOS. +# See the corresponding function in hw/bsp/FAMILY/family.cmake for details. +family_configure_host_example(${PROJECT} noos) diff --git a/examples/host/midi_rx/Makefile b/examples/host/midi_rx/Makefile index af8ef4275..0235e08c3 100644 --- a/examples/host/midi_rx/Makefile +++ b/examples/host/midi_rx/Makefile @@ -1,9 +1,13 @@ -include ../../../tools/top.mk -include ../../make.mk +include ../../build_system/make/make.mk + INC += \ src \ $(TOP)/hw \ + # Example source -EXAMPLE_SOURCE += $(wildcard src/*.c) +EXAMPLE_SOURCE += \ + src/main.c + SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) -include ../../rules.mk + +include ../../build_system/make/rules.mk diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt index 2ba4438fd..b6f87f423 100644 --- a/examples/host/midi_rx/only.txt +++ b/examples/host/midi_rx/only.txt @@ -1 +1,20 @@ +mcu:ESP32S2 +mcu:ESP32S3 +mcu:ESP32P4 +mcu:KINETIS_KL +mcu:LPC175X_6X +mcu:LPC177X_8X +mcu:LPC18XX +mcu:LPC40XX +mcu:LPC43XX +mcu:MAX3421 +mcu:MIMXRT1XXX +mcu:MIMXRT10XX +mcu:MIMXRT11XX +mcu:MSP432E4 mcu:RP2040 +mcu:RX65X +mcu:RAXXX +mcu:STM32F4 +mcu:STM32F7 +mcu:STM32H7 diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 6c3311043..8b83977e2 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -27,10 +27,8 @@ #include #include -#include "bsp/board.h" +#include "bsp/board_api.h" #include "tusb.h" -#include "class/midi/midi_host.h" - #if CFG_TUH_MIDI diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7b3ab4d42..55c52033c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -29,6 +29,7 @@ function(tinyusb_target_add TARGET) ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/host/hub.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_host.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_host.c + ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_host.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_host.c ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_host.c # typec diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 061e17fee..fbb994ade 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -29,7 +29,7 @@ #if (TUSB_OPT_HOST_ENABLED && CFG_TUH_MIDI) #include "host/usbh.h" -#include "host/usbh_classdriver.h" +#include "host/usbh_pvt.h" #include "midi_host.h" @@ -131,7 +131,7 @@ static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi); //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ -void midih_init(void) +bool midih_init(void) { tu_memclr(&_midi_host, sizeof(_midi_host)); // config fifos @@ -146,6 +146,7 @@ void midih_init(void) tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL); #endif } + return true; } bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 292c596e4..edf57bfcb 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -107,7 +107,7 @@ uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ -void midih_init (void); +bool midih_init (void); bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); diff --git a/src/host/usbh.c b/src/host/usbh.c index 30a4f5f63..e38ee3187 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1489,7 +1489,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { dev->i_serial = desc_device->iSerialNumber; if (tuh_desc_device_cb) { - tuh_desc_device_cb(daddr, (tusb_desc_device_t const*) _usbh_ctrl_buf); + tuh_desc_device_cb(daddr, (tusb_desc_device_t const*) _usbh_epbuf.ctrl); } // Get 9-byte for total length @@ -1520,7 +1520,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_SET_CONFIG: if (tuh_desc_config_cb) { - tuh_desc_config_cb(daddr, (const tusb_desc_configuration_t*) _usbh_ctrl_buf); + tuh_desc_config_cb(daddr, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl); } TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),); diff --git a/src/tinyusb.mk b/src/tinyusb.mk index 89ea0212c..a9f623c24 100644 --- a/src/tinyusb.mk +++ b/src/tinyusb.mk @@ -21,6 +21,7 @@ TINYUSB_SRC_C += \ src/host/hub.c \ src/class/cdc/cdc_host.c \ src/class/hid/hid_host.c \ + src/class/midi/midi_host.c \ src/class/msc/msc_host.c \ src/class/vendor/vendor_host.c \ src/typec/usbc.c \ From 86d371fb79ca8b1ee6794c33b6a74d4319d9c1a6 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Feb 2025 13:58:01 +0700 Subject: [PATCH 45/87] more ci fix --- examples/host/device_info/src/tusb_config.h | 3 +- examples/host/midi_rx/src/main.c | 131 +++++++++----------- examples/host/midi_rx/src/tusb_config.h | 77 ++++++++---- hw/bsp/rp2040/family.c | 4 +- 4 files changed, 117 insertions(+), 98 deletions(-) diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h index 5190b5b1f..27dd07e25 100644 --- a/examples/host/device_info/src/tusb_config.h +++ b/examples/host/device_info/src/tusb_config.h @@ -109,8 +109,7 @@ // only hub class is enabled #define CFG_TUH_HUB 1 -// max device support (excluding hub device) -// 1 hub typically has 4 ports +// max device support (excluding hub device): 1 hub typically has 4 ports #define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) #ifdef __cplusplus diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 8b83977e2..a03fd588f 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -23,8 +23,8 @@ * */ -#include #include +#include #include #include "bsp/board_api.h" @@ -44,22 +44,25 @@ void led_blinking_task(void); void midi_host_rx_task(void); /*------------- MAIN -------------*/ -int main(void) -{ - board_init(); +int main(void) { + board_init(); - printf("TinyUSB Host MIDI Example\r\n"); + printf("TinyUSB Host MIDI Example\r\n"); - tusb_init(); + // init host stack on configured roothub port + tusb_rhport_init_t host_init = { + .role = TUSB_ROLE_HOST, + .speed = TUSB_SPEED_AUTO + }; + tusb_init(BOARD_TUH_RHPORT, &host_init); - while (1) - { - tuh_task(); - led_blinking_task(); - midi_host_rx_task(); - } + while (1) { + tuh_task(); + led_blinking_task(); + midi_host_rx_task(); + } - return 0; + return 0; } #endif @@ -67,36 +70,32 @@ int main(void) //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ -void led_blinking_task(void) -{ - const uint32_t interval_ms = 1000; - static uint32_t start_ms = 0; +void led_blinking_task(void) { + const uint32_t interval_ms = 1000; + static uint32_t start_ms = 0; - static bool led_state = false; + static bool led_state = false; - // Blink every interval ms - if ( board_millis() - start_ms < interval_ms) return; // not enough time - start_ms += interval_ms; + // Blink every interval ms + if (board_millis() - start_ms < interval_ms) return;// not enough time + start_ms += interval_ms; - board_led_write(led_state); - led_state = 1 - led_state; // toggle + board_led_write(led_state); + led_state = 1 - led_state;// toggle } //--------------------------------------------------------------------+ // MIDI host receive task //--------------------------------------------------------------------+ -void midi_host_rx_task(void) -{ - // device must be attached and have at least one endpoint ready to receive a message - if (!midi_dev_addr || !tuh_midi_configured(midi_dev_addr)) - { - return; - } - if (tuh_midih_get_num_rx_cables(midi_dev_addr) < 1) - { - return; - } - tuh_midi_read_poll(midi_dev_addr); +void midi_host_rx_task(void) { + // device must be attached and have at least one endpoint ready to receive a message + if (!midi_dev_addr || !tuh_midi_configured(midi_dev_addr)) { + return; + } + if (tuh_midih_get_num_rx_cables(midi_dev_addr) < 1) { + return; + } + tuh_midi_read_poll(midi_dev_addr); } //--------------------------------------------------------------------+ @@ -108,51 +107,45 @@ void midi_host_rx_task(void) // can be used to parse common/simple enough descriptor. // Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped // therefore report_desc = NULL, desc_len = 0 -void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) -{ - (void ) in_ep; - (void ) out_ep; - (void ) num_cables_rx; - (void ) num_cables_tx; +void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) { + (void) in_ep; + (void) out_ep; + (void) num_cables_rx; + (void) num_cables_tx; - TU_LOG1("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", - dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); + TU_LOG1("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", + dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); - midi_dev_addr = dev_addr; + midi_dev_addr = dev_addr; } // Invoked when device with hid interface is un-mounted -void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) -{ - (void ) dev_addr; - (void ) instance; +void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { + (void) dev_addr; + (void) instance; - TU_LOG1("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); - midi_dev_addr = 0; + TU_LOG1("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); + midi_dev_addr = 0; } -void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) -{ - if (midi_dev_addr != dev_addr) - { - return; - } +void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { + if (midi_dev_addr != dev_addr) { + return; + } - if(num_packets == 0) - { - return; - } + if (num_packets == 0) { + return; + } - uint8_t cable_num; - uint8_t buffer[48]; - uint32_t bytes_read = tuh_midi_stream_read(dev_addr, &cable_num, buffer, sizeof(buffer)); - (void ) bytes_read; + uint8_t cable_num; + uint8_t buffer[48]; + uint32_t bytes_read = tuh_midi_stream_read(dev_addr, &cable_num, buffer, sizeof(buffer)); + (void) bytes_read; - TU_LOG1("Read bytes %lu cable %u", bytes_read, cable_num); - TU_LOG1_MEM(buffer, bytes_read, 2); + TU_LOG1("Read bytes %lu cable %u", bytes_read, cable_num); + TU_LOG1_MEM(buffer, bytes_read, 2); } -void tuh_midi_tx_cb(uint8_t dev_addr) -{ - (void ) dev_addr; +void tuh_midi_tx_cb(uint8_t dev_addr) { + (void) dev_addr; } diff --git a/examples/host/midi_rx/src/tusb_config.h b/examples/host/midi_rx/src/tusb_config.h index 5cc354ea9..1afcbbd63 100644 --- a/examples/host/midi_rx/src/tusb_config.h +++ b/examples/host/midi_rx/src/tusb_config.h @@ -23,15 +23,15 @@ * */ -#ifndef _TUSB_CONFIG_H_ -#define _TUSB_CONFIG_H_ +#ifndef TUSB_CONFIG_H_ +#define TUSB_CONFIG_H_ #ifdef __cplusplus extern "C" { #endif //-------------------------------------------------------------------- -// COMMON CONFIGURATION +// Common Configuration //-------------------------------------------------------------------- // defined by compiler flags for flexibility @@ -39,18 +39,18 @@ extern "C" { #error CFG_TUSB_MCU must be defined #endif -#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX -#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_HOST | OPT_MODE_HIGH_SPEED) -#else -#define CFG_TUSB_RHPORT0_MODE OPT_MODE_HOST +// Espressif IDF requires "freertos/" prefix in include path +#if TUSB_MCU_VENDOR_ESPRESSIF +#define CFG_TUSB_OS_INC_PATH freertos/ #endif #ifndef CFG_TUSB_OS -#define CFG_TUSB_OS OPT_OS_NONE +#define CFG_TUSB_OS OPT_OS_NONE #endif -// CFG_TUSB_DEBUG is defined by compiler in DEBUG build -// #define CFG_TUSB_DEBUG 0 +#ifndef CFG_TUSB_DEBUG +#define CFG_TUSB_DEBUG 0 +#endif /* 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 @@ -59,38 +59,63 @@ extern "C" { * - 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 +#ifndef CFG_TUH_MEM_SECTION +#define CFG_TUH_MEM_SECTION #endif -#ifndef CFG_TUSB_MEM_ALIGN -#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4))) +#ifndef CFG_TUH_MEM_ALIGN +#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4))) #endif //-------------------------------------------------------------------- -// CONFIGURATION +// Host Configuration +//-------------------------------------------------------------------- + +// Enable Host stack +#define CFG_TUH_ENABLED 1 + +#if CFG_TUSB_MCU == OPT_MCU_RP2040 + // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller + // #define CFG_TUH_MAX3421 1 // use max3421 as host controller + + // host roothub port is 1 if using either pio-usb or max3421 + #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) + #define BOARD_TUH_RHPORT 1 + #endif +#endif + +// Default is max speed that hardware controller could support with on-chip PHY +#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED + +//------------------------- Board Specific -------------------------- + +// RHPort number used for host can be defined by board.mk, default to port 0 +#ifndef BOARD_TUH_RHPORT +#define BOARD_TUH_RHPORT 0 +#endif + +// RHPort max operational speed can defined by board.mk +#ifndef BOARD_TUH_MAX_SPEED +#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED +#endif + +//-------------------------------------------------------------------- +// Driver Configuration //-------------------------------------------------------------------- // Size of buffer to hold descriptors and other data used for enumeration #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 -#define CFG_TUH_CDC 0 -#define CFG_TUH_HID 0 // typical keyboard + mouse device can have 3-4 HID interfaces #define CFG_TUH_MIDI 1 // there will be at most one MIDIStreaming Interface descriptor -#define CFG_TUH_MSC 0 -#define CFG_TUH_VENDOR 0 -// max device support (excluding hub device) -#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports +// max device support (excluding hub device): 1 hub typically has 4 ports +#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) + #define CFG_MIDI_HOST_DEVSTRINGS 1 -//------------- HID -------------// -#define CFG_TUH_HID_EPIN_BUFSIZE 64 -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 - #ifdef __cplusplus } #endif -#endif /* _TUSB_CONFIG_H_ */ +#endif diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 24aa0b616..689e264bd 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -266,7 +266,9 @@ int board_getchar(void) { #if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421 void max3421_int_handler(uint gpio, uint32_t event_mask) { - if (!(gpio == MAX3421_INTR_PIN && event_mask & GPIO_IRQ_EDGE_FALL)) return; + if (!(gpio == MAX3421_INTR_PIN && event_mask & GPIO_IRQ_EDGE_FALL)) { + return; + } tuh_int_handler(BOARD_TUH_RHPORT, true); } From e0b192b633e70338ef5ac88c7f5a49f37867b289 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 12 Feb 2025 22:16:08 +0700 Subject: [PATCH 46/87] - use CFG_TUH_MIDI as number of midi host instance - comment out tuh_descriptor_device_cb/tuh_desc_configuration_cb since it is unrelated to this PR --- examples/host/midi_rx/src/tusb_config.h | 3 +- src/class/midi/midi_host.c | 289 +++++++++++------------- src/class/midi/midi_host.h | 21 +- src/host/usbh.c | 8 +- src/host/usbh.h | 8 +- 5 files changed, 152 insertions(+), 177 deletions(-) diff --git a/examples/host/midi_rx/src/tusb_config.h b/examples/host/midi_rx/src/tusb_config.h index 1afcbbd63..24b3b3ae6 100644 --- a/examples/host/midi_rx/src/tusb_config.h +++ b/examples/host/midi_rx/src/tusb_config.h @@ -107,10 +107,9 @@ extern "C" { #define CFG_TUH_ENUMERATION_BUFSIZE 256 #define CFG_TUH_HUB 1 -#define CFG_TUH_MIDI 1 // there will be at most one MIDIStreaming Interface descriptor - // max device support (excluding hub device): 1 hub typically has 4 ports #define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) +#define CFG_TUH_MIDI CFG_TUH_DEVICE_MAX #define CFG_MIDI_HOST_DEVSTRINGS 1 diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index fbb994ade..21fe09143 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -36,14 +36,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#ifndef CFG_TUH_MAX_CABLES - #define CFG_TUH_MAX_CABLES 16 -#endif -#define CFG_TUH_MIDI_RX_BUFSIZE 64 -#define CFG_TUH_MIDI_TX_BUFSIZE 64 -#ifndef CFG_TUH_MIDI_EP_BUFSIZE - #define CFG_TUH_MIDI_EP_BUFSIZE 64 -#endif // TODO: refactor to share code with the MIDI Device driver typedef struct @@ -117,34 +109,44 @@ typedef struct #endif }midih_interface_t; -static midih_interface_t _midi_host[CFG_TUH_DEVICE_MAX]; - -static midih_interface_t *get_midi_host(uint8_t dev_addr) -{ - TU_VERIFY(dev_addr >0 && dev_addr <= CFG_TUH_DEVICE_MAX); - return (_midi_host + dev_addr - 1); -} +static midih_interface_t _midi_host[CFG_TUH_MIDI]; //------------- Internal prototypes -------------// static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi); +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ + +TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_midi_by_daddr(uint8_t dev_addr) { + for (uint8_t i = 0; i < CFG_TUH_MIDI; i++) { + if (_midi_host[i].dev_addr == dev_addr) { + return &_midi_host[i]; + } + } + return NULL; +} + +TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_new_midi(void) { + return find_midi_by_daddr(0); +} + + //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ -bool midih_init(void) -{ +bool midih_init(void) { tu_memclr(&_midi_host, sizeof(_midi_host)); // config fifos - for (int inst = 0; inst < CFG_TUH_DEVICE_MAX; inst++) - { + for (int inst = 0; inst < CFG_TUH_MIDI; inst++) { midih_interface_t *p_midi_host = &_midi_host[inst]; - tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false); // OBVS. + tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false);// true, true + tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false);// OBVS. - #if CFG_FIFO_MUTEX + #if CFG_FIFO_MUTEX tu_fifo_config_mutex(&p_midi_host->rx_ff, NULL, osal_mutex_create(&p_midi_host->rx_ff_mutex)); tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL); - #endif + #endif } return true; } @@ -152,7 +154,7 @@ bool midih_init(void) bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void)result; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); if ( ep_addr == p_midi_host->ep_in) { @@ -211,13 +213,14 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint return true; } -void midih_close(uint8_t dev_addr) -{ - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - if (p_midi_host == NULL) +void midih_close(uint8_t dev_addr) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + if (p_midi_host == NULL) { return; - if (tuh_midi_umount_cb) + } + if (tuh_midi_umount_cb) { tuh_midi_umount_cb(dev_addr, 0); + } tu_fifo_clear(&p_midi_host->rx_ff); tu_fifo_clear(&p_midi_host->tx_ff); p_midi_host->ep_in = 0; @@ -240,24 +243,24 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d { (void) rhport; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - + midih_interface_t *p_midi_host = find_new_midi(); TU_VERIFY(p_midi_host != NULL); + p_midi_host->num_string_indices = 0; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); // There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface uint8_t const *p_desc = (uint8_t const *) desc_itf; uint16_t len_parsed = 0; - if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) - { + if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { // Keep track of any string descriptor that might be here - if (desc_itf->iInterface != 0) - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; + if (desc_itf->iInterface != 0) { + p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; + } // This driver does not support audio streaming. However, if this is the audio control interface // there might be a MIDI interface following it. Search through every descriptor until a MIDI // interface is found or the end of the descriptor is found - while (len_parsed < max_len && (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) - { + while (len_parsed < max_len && + (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) { len_parsed += desc_itf->bLength; p_desc = tu_desc_next(p_desc); desc_itf = (tusb_desc_interface_t const *)p_desc; @@ -269,8 +272,9 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d len_parsed += desc_itf->bLength; // Keep track of any string descriptor that might be here - if (desc_itf->iInterface != 0) - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; + if (desc_itf->iInterface != 0) { + p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; + } p_desc = tu_desc_next(p_desc); TU_LOG1("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); @@ -282,195 +286,169 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d // assume it is an interface header midi_desc_header_t const *p_mdh = (midi_desc_header_t const *)p_desc; TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || - p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); + (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || + p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descriptor p_midi_host->itf_num = desc_itf->bInterfaceNumber; tusb_desc_endpoint_t const* in_desc = NULL; tusb_desc_endpoint_t const* out_desc = NULL; - while (len_parsed < max_len) - { + while (len_parsed < max_len) { TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || - p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); + (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || + p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); if (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) { // The USB host doesn't really need this information unless it uses // the string descriptor for a jack or Element // assume it is an input jack - midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *)p_desc; - if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) - { + midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *) p_desc; + if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) { TU_LOG2("Found MIDI Interface Header\r\b"); - } - else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) - { + } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) { // Then it is an in jack. TU_LOG2("Found in jack\r\n"); -#if CFG_MIDI_HOST_DEVSTRINGS - if (p_midi_host->next_in_jack < MAX_IN_JACKS) - { + #if CFG_MIDI_HOST_DEVSTRINGS + if (p_midi_host->next_in_jack < MAX_IN_JACKS) { p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_id = p_mdij->bJackID; p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_type = p_mdij->bJackType; p_midi_host->in_jack_info[p_midi_host->next_in_jack].string_index = p_mdij->iJack; ++p_midi_host->next_in_jack; // Keep track of any string descriptor that might be here - if (p_mdij->iJack != 0) + if (p_mdij->iJack != 0) { p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdij->iJack; - + } } -#endif - } - else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) - { + #endif + } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) { // then it is an out jack TU_LOG2("Found out jack\r\n"); -#if CFG_MIDI_HOST_DEVSTRINGS - if (p_midi_host->next_out_jack < MAX_OUT_JACKS) - { - midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *)p_desc; + #if CFG_MIDI_HOST_DEVSTRINGS + if (p_midi_host->next_out_jack < MAX_OUT_JACKS) { + midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *) p_desc; p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_id = p_mdoj->bJackID; p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_type = p_mdoj->bJackType; p_midi_host->out_jack_info[p_midi_host->next_out_jack].num_source_ids = p_mdoj->bNrInputPins; const struct associated_jack_s { - uint8_t id; - uint8_t pin; - } *associated_jack = (const struct associated_jack_s *)(p_desc+6); + uint8_t id; + uint8_t pin; + } *associated_jack = (const struct associated_jack_s *) (p_desc + 6); int jack; - for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) - { + for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) { p_midi_host->out_jack_info[p_midi_host->next_out_jack].source_ids[jack] = associated_jack->id; } - p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc+6+p_mdoj->bNrInputPins*2); + p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc + 6 + p_mdoj->bNrInputPins * 2); ++p_midi_host->next_out_jack; - if (p_mdoj->iJack != 0) + if (p_mdoj->iJack != 0) { p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdoj->iJack; + } } -#endif - } - else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) - { + #endif + } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) { // the it is an element; - #if CFG_MIDI_HOST_DEVSTRINGS + #if CFG_MIDI_HOST_DEVSTRINGS TU_LOG1("Found element; strings not supported\r\n"); - #else + #else TU_LOG2("Found element\r\n"); - #endif - } - else - { + #endif + } else { TU_LOG2("Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); - TU_VERIFY(false); // unknown CS Interface sub-type + TU_VERIFY(false);// unknown CS Interface sub-type } len_parsed += p_mdij->bLength; - } - else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) - { + } else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) { TU_LOG2("found CS_ENDPOINT Descriptor for %u\r\n", prev_ep_addr); TU_VERIFY(prev_ep_addr != 0); // parse out the mapping between the device's embedded jacks and the endpoints // Each embedded IN jack is associated with an OUT endpoint - midi_cs_desc_endpoint_t const* p_csep = (midi_cs_desc_endpoint_t const*)p_mdh; - if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) - { + midi_cs_desc_endpoint_t const *p_csep = (midi_cs_desc_endpoint_t const *) p_mdh; + if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) { TU_VERIFY(p_midi_host->ep_out == prev_ep_addr); TU_VERIFY(p_midi_host->num_cables_tx == 0); p_midi_host->num_cables_tx = p_csep->bNumEmbMIDIJack; -#if CFG_MIDI_HOST_DEVSTRINGS + #if CFG_MIDI_HOST_DEVSTRINGS uint8_t jack; uint8_t max_jack = p_midi_host->num_cables_tx; - if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) - { - max_jack = sizeof(p_midi_host->ep_out_associated_jacks); + if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) { + max_jack = sizeof(p_midi_host->ep_out_associated_jacks); } - for (jack = 0; jack < max_jack; jack++) - { + for (jack = 0; jack < max_jack; jack++) { p_midi_host->ep_out_associated_jacks[jack] = p_csep->baAssocJackID[jack]; } -#endif - } - else - { + #endif + } else { TU_VERIFY(p_midi_host->ep_in == prev_ep_addr); TU_VERIFY(p_midi_host->num_cables_rx == 0); p_midi_host->num_cables_rx = p_csep->bNumEmbMIDIJack; -#if CFG_MIDI_HOST_DEVSTRINGS + #if CFG_MIDI_HOST_DEVSTRINGS uint8_t jack; uint8_t max_jack = p_midi_host->num_cables_rx; - if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) - { - max_jack = sizeof(p_midi_host->ep_in_associated_jacks); + if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) { + max_jack = sizeof(p_midi_host->ep_in_associated_jacks); } - for (jack = 0; jack < max_jack; jack++) - { + for (jack = 0; jack < max_jack; jack++) { p_midi_host->ep_in_associated_jacks[jack] = p_csep->baAssocJackID[jack]; } -#endif + #endif } len_parsed += p_csep->bLength; prev_ep_addr = 0; - } - else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { + } else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { // parse out the bulk endpoint info - tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *)p_mdh; + tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_mdh; TU_LOG2("found ENDPOINT Descriptor for %u\r\n", p_ep->bEndpointAddress); - if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) - { + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { TU_VERIFY(p_midi_host->ep_out == 0); TU_VERIFY(p_midi_host->num_cables_tx == 0); p_midi_host->ep_out = p_ep->bEndpointAddress; p_midi_host->ep_out_max = p_ep->wMaxPacketSize; - if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) + if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) { p_midi_host->ep_out_max = CFG_TUH_MIDI_TX_BUFSIZE; + } prev_ep_addr = p_midi_host->ep_out; out_desc = p_ep; - } - else - { + } else { TU_VERIFY(p_midi_host->ep_in == 0); TU_VERIFY(p_midi_host->num_cables_rx == 0); p_midi_host->ep_in = p_ep->bEndpointAddress; p_midi_host->ep_in_max = p_ep->wMaxPacketSize; - if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) + if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) { p_midi_host->ep_in_max = CFG_TUH_MIDI_RX_BUFSIZE; + } prev_ep_addr = p_midi_host->ep_in; in_desc = p_ep; } len_parsed += p_mdh->bLength; } p_desc = tu_desc_next(p_desc); - p_mdh = (midi_desc_header_t const *)p_desc; + p_mdh = (midi_desc_header_t const *) p_desc; } TU_VERIFY((p_midi_host->ep_out != 0 && p_midi_host->num_cables_tx != 0) || (p_midi_host->ep_in != 0 && p_midi_host->num_cables_rx != 0)); TU_LOG1("MIDI descriptor parsed successfully\r\n"); // remove duplicate string indices - for (int idx=0; idx < p_midi_host->num_string_indices; idx++) { - for (int jdx = idx+1; jdx < p_midi_host->num_string_indices; jdx++) { - while (jdx < p_midi_host->num_string_indices && p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { - // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 - p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices-1]; - --p_midi_host->num_string_indices; - } + for (int idx = 0; idx < p_midi_host->num_string_indices; idx++) { + for (int jdx = idx + 1; jdx < p_midi_host->num_string_indices; jdx++) { + while (jdx < p_midi_host->num_string_indices && p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { + // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 + p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices - 1]; + --p_midi_host->num_string_indices; } + } } - if (in_desc) - { + if (in_desc) { TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); // Some devices always return exactly the request length so transfers won't complete // unless you assume every transfer is the last one. // TODO usbh_edpt_force_last_buffer(dev_addr, p_midi_host->ep_in, true); } - if (out_desc) - { + if (out_desc) { TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); } p_midi_host->dev_addr = dev_addr; - if (tuh_midi_mount_cb) - { + if (tuh_midi_mount_cb) { tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); } return true; @@ -478,7 +456,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d bool tuh_midi_configured(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); return p_midi_host->configured; } @@ -486,7 +464,7 @@ bool tuh_midi_configured(uint8_t dev_addr) bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { (void) itf_num; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); p_midi_host->configured = true; @@ -498,43 +476,36 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) //--------------------------------------------------------------------+ // Stream API //--------------------------------------------------------------------+ -static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) -{ +static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) { // No data to send - if ( !tu_fifo_count(&midi->tx_ff) ) return 0; + if ( !tu_fifo_count(&midi->tx_ff) ) { return 0; } // skip if previous transfer not complete TU_VERIFY( usbh_edpt_claim(dev_addr, midi->ep_out) ); uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epout_buf, midi->ep_out_max); - if (count) - { - TU_ASSERT( usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0 ); + if (count) { + TU_ASSERT(usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0); return count; - }else - { + } else { // Release endpoint since we don't make any transfer usbh_edpt_release(dev_addr, midi->ep_out); return 0; } } -bool tuh_midi_read_poll( uint8_t dev_addr ) -{ - midih_interface_t *p_midi_host = get_midi_host(dev_addr); +bool tuh_midi_read_poll(uint8_t dev_addr) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); bool result = false; bool in_edpt_not_busy = !usbh_edpt_busy(dev_addr, p_midi_host->ep_in); - if (in_edpt_not_busy) - { + if (in_edpt_not_busy) { TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in); TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, p_midi_host->epin_buf, p_midi_host->ep_in_max), 0); result = true; - } - else - { + } else { // Maybe the IN endpoint is only busy because the RP2040 host hardware // is retrying a NAK'd IN transfer forever. Try aborting the NAK'd // transfer to allow other transfers to happen on the one shared @@ -546,7 +517,7 @@ bool tuh_midi_read_poll( uint8_t dev_addr ) uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(cable_num < p_midi_host->num_cables_tx); midi_stream_t *stream = &p_midi_host->stream_write; @@ -673,7 +644,7 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); if (tu_fifo_remaining(&p_midi_host->tx_ff) < 4) @@ -688,7 +659,7 @@ bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) uint32_t tuh_midi_stream_flush( uint8_t dev_addr ) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint32_t bytes_flushed = 0; @@ -703,7 +674,7 @@ uint32_t tuh_midi_stream_flush( uint8_t dev_addr ) //--------------------------------------------------------------------+ uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(p_midi_host->ep_out != 0); // returns 0 if fails return p_midi_host->num_cables_tx; @@ -711,7 +682,7 @@ uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr) uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(p_midi_host->ep_in != 0); // returns 0 if fails return p_midi_host->num_cables_rx; @@ -719,7 +690,7 @@ uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr) bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(tu_fifo_count(&p_midi_host->rx_ff) >= 4); return tu_fifo_read_n(&p_midi_host->rx_ff, packet, 4) == 4; @@ -727,7 +698,7 @@ bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint32_t bytes_buffered = 0; TU_ASSERT(p_cable_num); @@ -848,7 +819,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint8_t num_cables = 0; if (p_midi_host) @@ -860,7 +831,7 @@ uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint8_t num_cables = 0; if (p_midi_host) @@ -897,7 +868,7 @@ static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) { uint8_t nstrings = 0; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); nstrings = p_midi_host->num_cables_rx; if (nstrings > max_istrings) @@ -916,7 +887,7 @@ uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) { uint8_t nstrings = 0; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); nstrings = p_midi_host->num_cables_tx; if (nstrings > max_istrings) @@ -935,7 +906,7 @@ uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint8_t nstrings = p_midi_host->num_string_indices; if (nstrings) diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index edf57bfcb..bf2378168 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -37,16 +37,25 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ - -// TODO Highspeed bulk transfer can be up to 512 bytes -#ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#ifndef CFG_TUH_MAX_CABLES +#define CFG_TUH_MAX_CABLES 16 #endif -#ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 +#ifndef CFG_TUH_MIDI_RX_BUFSIZE +#define CFG_TUH_MIDI_RX_BUFSIZE 64 #endif +#ifndef CFG_TUH_MIDI_TX_BUFSIZE +#define CFG_TUH_MIDI_TX_BUFSIZE 64 +#endif + +#ifndef CFG_TUH_MIDI_EP_BUFSIZE +#define CFG_TUH_MIDI_EP_BUFSIZE 64 +#endif + +#ifndef CFG_MIDI_HOST_DEVSTRINGS +#define CFG_MIDI_HOST_DEVSTRINGS 0 +#endif //--------------------------------------------------------------------+ // Application API (Single Interface) diff --git a/src/host/usbh.c b/src/host/usbh.c index e38ee3187..f874121a3 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1488,9 +1488,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { dev->i_product = desc_device->iProduct; dev->i_serial = desc_device->iSerialNumber; - if (tuh_desc_device_cb) { - tuh_desc_device_cb(daddr, (tusb_desc_device_t const*) _usbh_epbuf.ctrl); - } + // tuh_descriptor_device_cb(daddr, (tusb_desc_device_t const*) _usbh_epbuf.ctrl); // Get 9-byte for total length uint8_t const config_idx = CONFIG_NUM - 1; @@ -1519,9 +1517,7 @@ static void process_enumeration(tuh_xfer_t* xfer) { } case ENUM_SET_CONFIG: - if (tuh_desc_config_cb) { - tuh_desc_config_cb(daddr, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl); - } + // tuh_desc_configuration_cb(daddr, CONFIG_NUM-1, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl); TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),); break; diff --git a/src/host/usbh.h b/src/host/usbh.h index 500b044f8..3bcdd3657 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -96,11 +96,11 @@ typedef union { // APPLICATION CALLBACK //--------------------------------------------------------------------+ -// Give the application an opportunity to grab the device descriptor -TU_ATTR_WEAK void tuh_desc_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device); +// Invoked when enumeration get device descriptor +// TU_ATTR_WEAK void tuh_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device); -// Give the application an opportunity to grab the configuration descriptor -TU_ATTR_WEAK void tuh_desc_config_cb(uint8_t daddr, const tusb_desc_configuration_t *desc_config); +// Invoked when enumeration get configuration descriptor +// TU_ATTR_WEAK void tuh_desc_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config); // Invoked when a device is mounted (configured) TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr); From bad6cbe48930c0c5250b8a717a46cc1f6d83de56 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 13 Feb 2025 15:52:30 +0700 Subject: [PATCH 47/87] update midi host to use endpoint stream API --- src/class/cdc/cdc_host.c | 4 +- src/class/midi/midi_host.c | 445 ++++++++++++------------------------- src/class/midi/midi_host.h | 25 ++- src/common/tusb_private.h | 10 +- src/host/usbh.c | 3 +- src/host/usbh.h | 3 + 6 files changed, 174 insertions(+), 316 deletions(-) diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c index e817ebc7e..4058857c5 100644 --- a/src/class/cdc/cdc_host.c +++ b/src/class/cdc/cdc_host.c @@ -691,10 +691,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t } } else if ( ep_addr == p_cdc->stream.rx.ep_addr ) { #if CFG_TUH_CDC_FTDI - if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) { + if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI && xferred_bytes > 2) { // FTDI reserve 2 bytes for status // uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]}; - tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2); + tu_edpt_stream_read_xfer_complete_with_buf(&p_cdc->stream.rx, p_cdc->stream.rx.ep_buf+2, xferred_bytes-2); }else #endif { diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 21fe09143..eb3f0b070 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -45,15 +45,12 @@ typedef struct uint8_t total; }midi_stream_t; -typedef struct -{ +typedef struct { uint8_t dev_addr; uint8_t itf_num; uint8_t ep_in; // IN endpoint address uint8_t ep_out; // OUT endpoint address - uint16_t ep_in_max; // min( CFG_TUH_MIDI_RX_BUFSIZE, wMaxPacketSize of the IN endpoint) - uint16_t ep_out_max; // min( CFG_TUH_MIDI_TX_BUFSIZE, wMaxPacketSize of the OUT endpoint) uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value @@ -65,22 +62,14 @@ typedef struct midi_stream_t stream_read; /*------------- From this point, data is not cleared by bus reset -------------*/ - // Endpoint FIFOs - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; + // Endpoint stream + struct { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; - - uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; - - #if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; - #endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUH_MIDI_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_MIDI_EP_BUFSIZE]; + uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; + } ep_stream; bool configured; @@ -109,15 +98,17 @@ typedef struct #endif }midih_interface_t; -static midih_interface_t _midi_host[CFG_TUH_MIDI]; +typedef struct { + TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MPS); + TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MPS); +} midih_epbuf_t; -//------------- Internal prototypes -------------// -static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi); +static midih_interface_t _midi_host[CFG_TUH_MIDI]; +CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI]; //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ - TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_midi_by_daddr(uint8_t dev_addr) { for (uint8_t i = 0; i < CFG_TUH_MIDI; i++) { if (_midi_host[i].dev_addr == dev_addr) { @@ -131,85 +122,27 @@ TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_new_midi(void) { return find_midi_by_daddr(0); } - //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ bool midih_init(void) { tu_memclr(&_midi_host, sizeof(_midi_host)); - // config fifos for (int inst = 0; inst < CFG_TUH_MIDI; inst++) { midih_interface_t *p_midi_host = &_midi_host[inst]; - tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false);// true, true - tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false);// OBVS. - - #if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_midi_host->rx_ff, NULL, osal_mutex_create(&p_midi_host->rx_ff_mutex)); - tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL); - #endif + tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false, + p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx, TUH_EPSIZE_BULK_MPS); + tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false, + p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx, TUH_EPSIZE_BULK_MPS); } return true; } -bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) -{ - (void)result; - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - if ( ep_addr == p_midi_host->ep_in) - { - if (0 == xferred_bytes) - { - return true; // No data to handle - } - - // receive new data if available - uint32_t packets_queued = 0; - if (xferred_bytes) - { - // put in the RX FIFO only non-zero MIDI IN 4-byte packets - uint8_t* buf = p_midi_host->epin_buf; - uint32_t npackets = xferred_bytes / 4; - uint32_t packet_num; - for (packet_num = 0; packet_num < npackets; packet_num++) - { - // some devices send back all zero packets even if there is no data ready - uint32_t packet = (uint32_t)((*buf)<<24) | ((uint32_t)(*(buf+1))<<16) | ((uint32_t)(*(buf+2))<<8) | ((uint32_t)(*(buf+3))); - if (packet != 0) - { - tu_fifo_write_n(&p_midi_host->rx_ff, buf, 4); - ++packets_queued; - TU_LOG3("MIDI RX=%08x\r\n", packet); - } - buf += 4; - } - } - // invoke receive callback if available - if (tuh_midi_rx_cb) - { - tuh_midi_rx_cb(dev_addr, packets_queued); - } +bool midih_deinit(void) { + for (size_t i = 0; i < CFG_TUH_MIDI; i++) { + midih_interface_t* p_midi = &_midi_host[i]; + tu_edpt_stream_deinit(&p_midi->ep_stream.rx); + tu_edpt_stream_deinit(&p_midi->ep_stream.tx); } - else if ( ep_addr == p_midi_host->ep_out ) - { - if (0 == write_flush(dev_addr, p_midi_host)) - { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if ( !tu_fifo_count(&p_midi_host->tx_ff) && xferred_bytes && (0 == (xferred_bytes % p_midi_host->ep_out_max)) ) - { - if ( usbh_edpt_claim(dev_addr, p_midi_host->ep_out) ) - { - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_midi_host->ep_out, XFER_RESULT_SUCCESS, 0)); - } - } - } - if (tuh_midi_tx_cb) - { - tuh_midi_tx_cb(dev_addr); - } - } - return true; } @@ -221,26 +154,67 @@ void midih_close(uint8_t dev_addr) { if (tuh_midi_umount_cb) { tuh_midi_umount_cb(dev_addr, 0); } - tu_fifo_clear(&p_midi_host->rx_ff); - tu_fifo_clear(&p_midi_host->tx_ff); p_midi_host->ep_in = 0; - p_midi_host->ep_in_max = 0; p_midi_host->ep_out = 0; - p_midi_host->ep_out_max = 0; p_midi_host->itf_num = 0; p_midi_host->num_cables_rx = 0; p_midi_host->num_cables_tx = 0; - p_midi_host->dev_addr = 255; // invalid + p_midi_host->dev_addr = 0; p_midi_host->configured = false; tu_memclr(&p_midi_host->stream_read, sizeof(p_midi_host->stream_read)); tu_memclr(&p_midi_host->stream_write, sizeof(p_midi_host->stream_write)); + + tu_edpt_stream_close(&p_midi_host->ep_stream.rx); + tu_edpt_stream_close(&p_midi_host->ep_stream.tx); +} + +bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { + (void) result; + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL); + if (ep_addr == p_midi_host->ep_stream.rx.ep_addr) { + // receive new data if available + if (xferred_bytes) { + // put in the RX FIFO only non-zero MIDI IN 4-byte packets + uint32_t packets_queued = 0; + uint8_t *buf = _midi_epbuf->rx; + const uint32_t npackets = xferred_bytes / 4; + for (uint32_t p = 0; p < npackets; p++) { + // some devices send back all zero packets even if there is no data ready + const uint32_t packet = tu_unaligned_read32(buf); + if (packet != 0) { + tu_edpt_stream_read_xfer_complete_with_buf(&p_midi_host->ep_stream.rx, buf, 4); + ++packets_queued; + TU_LOG3("MIDI RX=%08x\r\n", packet); + } + buf += 4; + } + + if (tuh_midi_rx_cb) { + tuh_midi_rx_cb(dev_addr, packets_queued); // invoke receive callback + } + } + + // prepare for next transfer if needed + tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); + } else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) { + if (tuh_midi_tx_cb) { + tuh_midi_tx_cb(dev_addr); + } + if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi_host->ep_stream.tx)) { + // If there is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi_host->ep_stream.tx, xferred_bytes); + } + } + + return true; } //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ -bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) -{ +bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) rhport; midih_interface_t *p_midi_host = find_new_midi(); @@ -402,20 +376,12 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_VERIFY(p_midi_host->ep_out == 0); TU_VERIFY(p_midi_host->num_cables_tx == 0); p_midi_host->ep_out = p_ep->bEndpointAddress; - p_midi_host->ep_out_max = p_ep->wMaxPacketSize; - if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) { - p_midi_host->ep_out_max = CFG_TUH_MIDI_TX_BUFSIZE; - } prev_ep_addr = p_midi_host->ep_out; out_desc = p_ep; } else { TU_VERIFY(p_midi_host->ep_in == 0); TU_VERIFY(p_midi_host->num_cables_rx == 0); p_midi_host->ep_in = p_ep->bEndpointAddress; - p_midi_host->ep_in_max = p_ep->wMaxPacketSize; - if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) { - p_midi_host->ep_in_max = CFG_TUH_MIDI_RX_BUFSIZE; - } prev_ep_addr = p_midi_host->ep_in; in_desc = p_ep; } @@ -439,36 +405,34 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d } if (in_desc) { TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); - // Some devices always return exactly the request length so transfers won't complete - // unless you assume every transfer is the last one. - // TODO usbh_edpt_force_last_buffer(dev_addr, p_midi_host->ep_in, true); + tu_edpt_stream_open(&p_midi_host->ep_stream.rx, in_desc); } if (out_desc) { TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); + tu_edpt_stream_open(&p_midi_host->ep_stream.tx, out_desc); } p_midi_host->dev_addr = dev_addr; - if (tuh_midi_mount_cb) { - tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); - } return true; } -bool tuh_midi_configured(uint8_t dev_addr) -{ +bool tuh_midi_configured(uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); return p_midi_host->configured; } -bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) -{ +bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { (void) itf_num; midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); p_midi_host->configured = true; - // TODO I don't think there are any special config things to do for MIDI + if (tuh_midi_mount_cb) { + tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); + } + + // No special config things to do for MIDI usbh_driver_set_config_complete(dev_addr, p_midi_host->itf_num); return true; } @@ -476,71 +440,32 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) //--------------------------------------------------------------------+ // Stream API //--------------------------------------------------------------------+ -static uint32_t write_flush(uint8_t dev_addr, midih_interface_t* midi) { - // No data to send - if ( !tu_fifo_count(&midi->tx_ff) ) { return 0; } - - // skip if previous transfer not complete - TU_VERIFY( usbh_edpt_claim(dev_addr, midi->ep_out) ); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epout_buf, midi->ep_out_max); - - if (count) { - TU_ASSERT(usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0); - return count; - } else { - // Release endpoint since we don't make any transfer - usbh_edpt_release(dev_addr, midi->ep_out); - return 0; - } -} - bool tuh_midi_read_poll(uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); - bool result = false; - - bool in_edpt_not_busy = !usbh_edpt_busy(dev_addr, p_midi_host->ep_in); - if (in_edpt_not_busy) { - TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in); - TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, p_midi_host->epin_buf, p_midi_host->ep_in_max), 0); - result = true; - } else { - // Maybe the IN endpoint is only busy because the RP2040 host hardware - // is retrying a NAK'd IN transfer forever. Try aborting the NAK'd - // transfer to allow other transfers to happen on the one shared - // epx endpoint. - // TODO for RP2040 USB shared endpoint: usbh_edpt_clear_in_on_nak(p_midi_host->dev_addr, p_midi_host->ep_in); - } - return result; + return tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx) > 0; } -uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* buffer, uint32_t bufsize) -{ +uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(cable_num < p_midi_host->num_cables_tx); midi_stream_t *stream = &p_midi_host->stream_write; uint32_t i = 0; - while ( (i < bufsize) && (tu_fifo_remaining(&p_midi_host->tx_ff) >= 4) ) - { + while ((i < bufsize) && (tu_edpt_stream_write_available(dev_addr, &p_midi_host->ep_stream.tx) >= 4)) { uint8_t const data = buffer[i]; i++; - if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) - { + if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { // real-time messages need to be sent right away midi_stream_t streamrt; streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; streamrt.buffer[1] = data; streamrt.index = 2; streamrt.total = 2; - uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, streamrt.buffer, 4); - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } - else if ( stream->index == 0 ) - { + uint32_t const count = tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, streamrt.buffer, 4); + TU_ASSERT(count == 4, i); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition + } else if (stream->index == 0) { //------------- New event packet -------------// uint8_t const msg = data >> 4; @@ -549,56 +474,37 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con stream->buffer[1] = data; // Check to see if we're still in a SysEx transmit. - if ( stream->buffer[0] == MIDI_CIN_SYSEX_START ) - { - if ( data == MIDI_STATUS_SYSEX_END ) - { + if (stream->buffer[0] == MIDI_CIN_SYSEX_START) { + if (data == MIDI_STATUS_SYSEX_END) { stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; stream->total = 2; - } - else - { + } else { stream->total = 4; } - } - else if ( (msg >= 0x8 && msg <= 0xB) || msg == 0xE ) - { + } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { // Channel Voice Messages stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); stream->total = 4; - } - else if ( msg == 0xC || msg == 0xD) - { + } else if (msg == 0xC || msg == 0xD) { // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); stream->total = 3; - } - else if ( msg == 0xf ) - { + } else if (msg == 0xf) { // System message - if ( data == MIDI_STATUS_SYSEX_START ) - { + if (data == MIDI_STATUS_SYSEX_START) { stream->buffer[0] = MIDI_CIN_SYSEX_START; stream->total = 4; - } - else if ( data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT ) - { + } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) { stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; stream->total = 3; - } - else if ( data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER ) - { + } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) { stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; stream->total = 4; - } - else - { + } else { stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; stream->total = 2; } - } - else - { + } else { // Pack individual bytes if we don't support packing them into words. stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); stream->buffer[2] = 0; @@ -606,30 +512,25 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con stream->index = 2; stream->total = 2; } - } - else - { + } else { //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, i); stream->buffer[stream->index] = data; stream->index++; // See if this byte ends a SysEx. - if ( stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END ) - { + if (stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); stream->total = stream->index; } } // Send out packet - if ( stream->index >= 2 && stream->index == stream->total ) - { + if (stream->index >= 2 && stream->index == stream->total) { // zeroes unused bytes - for(uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; + for (uint8_t idx = stream->total; idx < 4; idx++) { stream->buffer[idx] = 0; } TU_LOG3_MEM(stream->buffer, 4, 2); - uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, stream->buffer, 4); + uint32_t const count = tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, stream->buffer, 4); // complete current event packet, reset stream stream->index = 0; @@ -642,32 +543,16 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con return i; } -bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) -{ +bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); - - if (tu_fifo_remaining(&p_midi_host->tx_ff) < 4) - { - return false; - } - - tu_fifo_write_n(&p_midi_host->tx_ff, packet, 4); - - return true; + return 4 == tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, packet, 4); } -uint32_t tuh_midi_stream_flush( uint8_t dev_addr ) -{ - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - - uint32_t bytes_flushed = 0; - if (!usbh_edpt_busy(p_midi_host->dev_addr, p_midi_host->ep_out)) - { - bytes_flushed = write_flush(dev_addr, p_midi_host); - } - return bytes_flushed; +uint32_t tuh_midi_stream_flush(uint8_t dev_addr) { + midih_interface_t *p_midi = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi != NULL); + return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx); } //--------------------------------------------------------------------+ // Helper @@ -692,12 +577,11 @@ bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(tu_fifo_count(&p_midi_host->rx_ff) >= 4); - return tu_fifo_read_n(&p_midi_host->rx_ff, packet, 4) == 4; + TU_VERIFY(tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx) >= 4); + return 4 == tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, packet, 4); } -uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) -{ +uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint32_t bytes_buffered = 0; @@ -705,54 +589,40 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * TU_ASSERT(p_buffer); TU_ASSERT(bufsize); uint8_t one_byte; - if (!tu_fifo_peek(&p_midi_host->rx_ff, &one_byte)) - { + if (!tu_edpt_stream_peek(&p_midi_host->ep_stream.rx, &one_byte)) { return 0; } *p_cable_num = (one_byte >> 4) & 0xf; - uint32_t nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4); + uint32_t nread = tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, p_midi_host->stream_read.buffer, 4); static uint16_t cable_sysex_in_progress; // bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END - while (nread == 4 && bytes_buffered < bufsize) - { - *p_cable_num=(p_midi_host->stream_read.buffer[0] >> 4) & 0x0f; + while (nread == 4 && bytes_buffered < bufsize) { + *p_cable_num = (p_midi_host->stream_read.buffer[0] >> 4) & 0x0f; uint8_t bytes_to_add_to_stream = 0; - if (*p_cable_num < p_midi_host->num_cables_rx) - { + if (*p_cable_num < p_midi_host->num_cables_rx) { // ignore the CIN field; too many devices out there encode this wrong uint8_t status = p_midi_host->stream_read.buffer[1]; uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); - if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) - { - if (status == MIDI_STATUS_SYSEX_START) - { + if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) { + if (status == MIDI_STATUS_SYSEX_START) { cable_sysex_in_progress |= cable_mask; } // only add the packet if a sysex message is in progress - if (cable_sysex_in_progress & cable_mask) - { + if (cable_sysex_in_progress & cable_mask) { ++bytes_to_add_to_stream; - uint8_t idx; - for (idx = 2; idx < 4; idx++) - { - if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL) - { + for (uint8_t idx = 2; idx < 4; idx++) { + if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL) { ++bytes_to_add_to_stream; - } - else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) - { + } else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) { ++bytes_to_add_to_stream; cable_sysex_in_progress &= (uint16_t) ~cable_mask; - idx = 4; // force the loop to exit; I hate break statements in loops + idx = 4;// force the loop to exit; I hate break statements in loops } } } - } - else if (status < MIDI_STATUS_SYSEX_START) - { + } else if (status < MIDI_STATUS_SYSEX_START) { // then it is a channel message either three bytes or two uint8_t fake_cin = (status & 0xf0) >> 4; - switch (fake_cin) - { + switch (fake_cin) { case MIDI_CIN_NOTE_OFF: case MIDI_CIN_NOTE_ON: case MIDI_CIN_POLY_KEYPRESS: @@ -765,14 +635,11 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * bytes_to_add_to_stream = 2; break; default: - break; // Should not get this + break;// Should not get this } - cable_sysex_in_progress &= (uint16_t)~cable_mask; - } - else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) - { - switch (status) - { + cable_sysex_in_progress &= (uint16_t) ~cable_mask; + } else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) { + switch (status) { case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME: case MIDI_STATUS_SYSCOM_SONG_SELECT: bytes_to_add_to_stream = 2; @@ -786,30 +653,24 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * break; default: break; - cable_sysex_in_progress &= (uint16_t)~cable_mask; + cable_sysex_in_progress &= (uint16_t) ~cable_mask; } - } - else - { + } else { // Real-time message: can be inserted into a sysex message, // so do don't clear cable_sysex_in_progress bit bytes_to_add_to_stream = 1; } } - uint8_t idx; - for (idx = 1; idx <= bytes_to_add_to_stream; idx++) - { + for (uint8_t idx = 1; idx <= bytes_to_add_to_stream; idx++) { *p_buffer++ = p_midi_host->stream_read.buffer[idx]; } bytes_buffered += bytes_to_add_to_stream; nread = 0; - if (tu_fifo_peek(&p_midi_host->rx_ff, &one_byte)) - { + if (tu_edpt_stream_peek(&p_midi_host->ep_stream.rx, &one_byte)) { uint8_t new_cable = (one_byte >> 4) & 0xf; - if (new_cable == *p_cable_num) - { + if (new_cable == *p_cable_num) { // still on the same cable. Continue reading the stream - nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4); + nread = tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, p_midi_host->stream_read.buffer, 4); } } } @@ -865,19 +726,14 @@ static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) #endif #if CFG_MIDI_HOST_DEVSTRINGS -uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) -{ - uint8_t nstrings = 0; +uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - nstrings = p_midi_host->num_cables_rx; - if (nstrings > max_istrings) - { - nstrings = max_istrings; + TU_VERIFY(p_midi_host != NULL, 0); + uint8_t nstrings = p_midi_host->num_cables_rx; + if (nstrings > max_istrings) { + nstrings = max_istrings; } - uint8_t jack; - for (jack=0; jackep_in_associated_jacks[jack]; istrings[jack] = find_string_index(p_midi_host, jack_id); } @@ -886,17 +742,13 @@ uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) { - uint8_t nstrings = 0; midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - nstrings = p_midi_host->num_cables_tx; - if (nstrings > max_istrings) - { - nstrings = max_istrings; + TU_VERIFY(p_midi_host != NULL, 0); + uint8_t nstrings = p_midi_host->num_cables_tx; + if (nstrings > max_istrings) { + nstrings = max_istrings; } - uint8_t jack; - for (jack=0; jackep_out_associated_jacks[jack]; istrings[jack] = find_string_index(p_midi_host, jack_id); } @@ -909,8 +761,7 @@ uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings) midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); uint8_t nstrings = p_midi_host->num_string_indices; - if (nstrings) - *istrings = p_midi_host->all_string_indices; + if (nstrings) { *istrings = p_midi_host->all_string_indices; } return nstrings; } #endif diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index bf2378168..6401eb0c3 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -42,15 +42,15 @@ #endif #ifndef CFG_TUH_MIDI_RX_BUFSIZE -#define CFG_TUH_MIDI_RX_BUFSIZE 64 +#define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif #ifndef CFG_TUH_MIDI_TX_BUFSIZE -#define CFG_TUH_MIDI_TX_BUFSIZE 64 +#define CFG_TUH_MIDI_TX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif #ifndef CFG_TUH_MIDI_EP_BUFSIZE -#define CFG_TUH_MIDI_EP_BUFSIZE 64 +#define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MPS #endif #ifndef CFG_MIDI_HOST_DEVSTRINGS @@ -113,14 +113,6 @@ uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); #endif -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -bool midih_init (void); -bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); -bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void midih_close (uint8_t dev_addr); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) @@ -138,6 +130,17 @@ TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance); TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets); TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +bool midih_init (void); +bool midih_deinit (void); +bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); +bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); +bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void midih_close (uint8_t dev_addr); + #ifdef __cplusplus } #endif diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index c71775abb..445882243 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -138,7 +138,7 @@ uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, ui // Start an usb transfer if endpoint is not busy uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s); -// Must be called in the transfer complete callback +// Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback TU_ATTR_ALWAYS_INLINE static inline void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) { if (tu_fifo_depth(&s->ff)) { @@ -146,11 +146,11 @@ void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_byt } } -// Same as tu_edpt_stream_read_xfer_complete but skip the first n bytes +// Complete read transfer with provided buffer TU_ATTR_ALWAYS_INLINE static inline -void tu_edpt_stream_read_xfer_complete_offset(tu_edpt_stream_t* s, uint32_t xferred_bytes, uint32_t skip_offset) { - if (tu_fifo_depth(&s->ff) && (skip_offset < xferred_bytes)) { - tu_fifo_write_n(&s->ff, s->ep_buf + skip_offset, (uint16_t) (xferred_bytes - skip_offset)); +void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t* s, const void * buf, uint32_t xferred_bytes) { + if (tu_fifo_depth(&s->ff)) { + tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes); } } diff --git a/src/host/usbh.c b/src/host/usbh.c index f874121a3..e6b6cd91c 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -192,6 +192,7 @@ static usbh_class_driver_t const usbh_class_drivers[] = { { .name = DRIVER_NAME("MIDI"), .init = midih_init, + .deinit = midih_deinit, .open = midih_open, .set_config = midih_set_config, .xfer_cb = midih_xfer_cb, @@ -1672,7 +1673,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur if ( 0 == tu_desc_len(p_desc) ) { // A zero length descriptor indicates that the device is off spec (e.g. wrong wTotalLength). // Parsed interfaces should still be usable - TU_LOG_USBH("Encountered a zero-length descriptor after %u bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg); + TU_LOG_USBH("Encountered a zero-length descriptor after %" PRIu32 " bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg); break; } diff --git a/src/host/usbh.h b/src/host/usbh.h index 3bcdd3657..7fc8ea826 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -37,6 +37,9 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +// Endpoint Bulk size depending on host mx speed +#define TUH_EPSIZE_BULK_MPS (TUD_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) + // forward declaration struct tuh_xfer_s; typedef struct tuh_xfer_s tuh_xfer_t; From ed88fc983fcc8bd0bcc27b9982b21223a580f59d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Feb 2025 10:41:05 +0700 Subject: [PATCH 48/87] - remove tuh_midi_read_poll(), auto schedule EP in when set_config() and xfer_cb as well as ep read() - de-dup tuh_midi_get_num_rx/tx_cables - add tuh_midi_read_available() --- examples/host/midi_rx/src/main.c | 5 +-- src/class/midi/midi_host.c | 67 ++++++++++---------------------- src/class/midi/midi_host.h | 51 ++++++++++++------------ 3 files changed, 50 insertions(+), 73 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index a03fd588f..0b07ba6e7 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -38,7 +38,7 @@ static uint8_t midi_dev_addr = 0; //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF PROTYPES +// MACRO CONSTANT TYPEDEF PROTOTYPES //--------------------------------------------------------------------+ void led_blinking_task(void); void midi_host_rx_task(void); @@ -92,10 +92,9 @@ void midi_host_rx_task(void) { if (!midi_dev_addr || !tuh_midi_configured(midi_dev_addr)) { return; } - if (tuh_midih_get_num_rx_cables(midi_dev_addr) < 1) { + if (tuh_midi_get_num_rx_cables(midi_dev_addr) < 1) { return; } - tuh_midi_read_poll(midi_dev_addr); } //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index eb3f0b070..7d6eb35fa 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_MIDI) +#if (CFG_TUH_ENABLED && CFG_TUH_MIDI) #include "host/usbh.h" #include "host/usbh_pvt.h" @@ -195,8 +195,7 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint } } - // prepare for next transfer if needed - tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); + tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for next transfer } else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) { if (tuh_midi_tx_cb) { tuh_midi_tx_cb(dev_addr); @@ -416,12 +415,6 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d return true; } -bool tuh_midi_configured(uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - return p_midi_host->configured; -} - bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { (void) itf_num; midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); @@ -432,18 +425,20 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); } + tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for incoming data + // No special config things to do for MIDI usbh_driver_set_config_complete(dev_addr, p_midi_host->itf_num); return true; } //--------------------------------------------------------------------+ -// Stream API +// API //--------------------------------------------------------------------+ -bool tuh_midi_read_poll(uint8_t dev_addr) { +bool tuh_midi_configured(uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); - return tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx) > 0; + return p_midi_host->configured; } uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { @@ -557,24 +552,27 @@ uint32_t tuh_midi_stream_flush(uint8_t dev_addr) { //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ -uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr) -{ +uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(p_midi_host->ep_out != 0); // returns 0 if fails + TU_VERIFY(p_midi_host != NULL, 0); + TU_VERIFY(p_midi_host->ep_out != 0, 0); return p_midi_host->num_cables_tx; } -uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr) -{ +uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(p_midi_host->ep_in != 0); // returns 0 if fails + TU_VERIFY(p_midi_host != NULL, 0); + TU_VERIFY(p_midi_host->ep_in != 0, 0); return p_midi_host->num_cables_rx; } -bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) -{ +uint32_t tuh_midi_read_available(uint8_t dev_addr) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL); + return tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx); +} + +bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx) >= 4); @@ -661,6 +659,7 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p bytes_to_add_to_stream = 1; } } + for (uint8_t idx = 1; idx <= bytes_to_add_to_stream; idx++) { *p_buffer++ = p_midi_host->stream_read.buffer[idx]; } @@ -678,30 +677,6 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p return bytes_buffered; } -uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) -{ - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint8_t num_cables = 0; - if (p_midi_host) - { - num_cables = p_midi_host->num_cables_rx; - } - return num_cables; -} - -uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr) -{ - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint8_t num_cables = 0; - if (p_midi_host) - { - num_cables = p_midi_host->num_cables_tx; - } - return num_cables; -} - #if CFG_MIDI_HOST_DEVSTRINGS static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) { diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 6401eb0c3..6529f2bbc 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -58,22 +58,34 @@ #endif //--------------------------------------------------------------------+ -// Application API (Single Interface) +// Application API //--------------------------------------------------------------------+ bool tuh_midi_configured (uint8_t dev_addr); -// return the number of virtual midi cables on the device's OUT endpoint -uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr); - // return the number of virtual midi cables on the device's IN endpoint -uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr); +uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); -// request available data from the device. tuh_midi_message_received_cb() will -// be called if the device has any data to send. Otherwise, the device will -// respond NAK. This function blocks until the transfer completes or the -// devices sends NAK. -// This function will return false if the hardware is busy. -bool tuh_midi_read_poll( uint8_t dev_addr ); +// return the number of virtual midi cables on the device's OUT endpoint +uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr); + +#if CFG_MIDI_HOST_DEVSTRINGS +uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); +uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); +uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); +#endif + +// return the raw number of bytes available from device endpoint. +// Note: this is related but not the same as number of stream bytes available. +uint32_t tuh_midi_read_available(uint8_t dev_addr); + +//--------------------------------------------------------------------+ +// Packet API +//--------------------------------------------------------------------+ + +// Read a raw MIDI packet from the connected device +// This function does not parse the packet format +// Return true if a packet was returned +bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]); // Queue a packet to the device. The application // must call tuh_midi_stream_flush to actually have the @@ -82,6 +94,10 @@ bool tuh_midi_read_poll( uint8_t dev_addr ); // Returns true if the packet was successfully queued. bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]); +//--------------------------------------------------------------------+ +// Stream API +//--------------------------------------------------------------------+ + // Queue a message to the device. The application // must call tuh_midi_stream_flush to actually have the // data go out. @@ -101,19 +117,6 @@ uint32_t tuh_midi_stream_flush( uint8_t dev_addr); // it properly. uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); -// Read a raw MIDI packet from the connected device -// This function does not parse the packet format -// Return true if a packet was returned -bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]); - -uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); -uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr); -#if CFG_MIDI_HOST_DEVSTRINGS -uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); -uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); -uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); -#endif - //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ From 31a2696de77d4642d28086ccbe476f40b1bdea7d Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Feb 2025 11:09:50 +0700 Subject: [PATCH 49/87] - change signature of tuh_midi_mount/umount_cb() - rename midi_stream_t to midi_driver_stream_t and move to midi.h (common for device and host) --- examples/host/midi_rx/src/main.c | 22 ++++++---------------- src/class/midi/midi.h | 26 +++++++++++++++----------- src/class/midi/midi_device.c | 16 ++++++---------- src/class/midi/midi_host.c | 24 ++++++++---------------- src/class/midi/midi_host.h | 8 ++------ 5 files changed, 37 insertions(+), 59 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 0b07ba6e7..fed782947 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -101,30 +101,20 @@ void midi_host_rx_task(void) { // TinyUSB Callbacks //--------------------------------------------------------------------+ -// Invoked when device with hid interface is mounted -// Report descriptor is also available for use. tuh_hid_parse_report_descriptor() -// can be used to parse common/simple enough descriptor. -// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped -// therefore report_desc = NULL, desc_len = 0 -void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) { - (void) in_ep; - (void) out_ep; +// Invoked when device with MIDI interface is mounted. +void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx) { (void) num_cables_rx; (void) num_cables_tx; - - TU_LOG1("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", - dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); - midi_dev_addr = dev_addr; + TU_LOG1("MIDI device address = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", + dev_addr, num_cables_rx, num_cables_tx); } // Invoked when device with hid interface is un-mounted -void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { +void tuh_midi_umount_cb(uint8_t dev_addr) { (void) dev_addr; - (void) instance; - - TU_LOG1("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); midi_dev_addr = 0; + TU_LOG1("MIDI device address = %d is unmounted\r\n", dev_addr); } void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index 68a784c60..9591f13c4 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -24,13 +24,8 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_class - * \defgroup ClassDriver_CDC Communication Device Class (CDC) - * Currently only Abstract Control Model subclass is supported - * @{ */ - -#ifndef _TUSB_MIDI_H__ -#define _TUSB_MIDI_H__ +#ifndef TUSB_MIDI_H_ +#define TUSB_MIDI_H_ #include "common/tusb_common.h" @@ -39,7 +34,7 @@ #endif //--------------------------------------------------------------------+ -// Class Specific Descriptor +// Constants //--------------------------------------------------------------------+ typedef enum @@ -111,6 +106,10 @@ enum MIDI_MAX_DATA_VAL = 0x7F, }; +//--------------------------------------------------------------------+ +// Class Specific Descriptor +//--------------------------------------------------------------------+ + /// MIDI Interface Header Descriptor typedef struct TU_ATTR_PACKED { @@ -216,12 +215,17 @@ typedef struct uint8_t baAssocJackID[]; ; ///< A list of associated jacks } midi_cs_desc_endpoint_t; -/** @} */ +//--------------------------------------------------------------------+ +// For Internal Driver Use +//--------------------------------------------------------------------+ +typedef struct { + uint8_t buffer[4]; + uint8_t index; + uint8_t total; +} midi_driver_stream_t; #ifdef __cplusplus } #endif #endif - -/** @} */ diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index dd1883e37..7b6705640 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -40,11 +40,7 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef struct { - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -} midid_stream_t; + typedef struct { uint8_t itf_num; @@ -54,8 +50,8 @@ typedef struct { // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. - midid_stream_t stream_write; - midid_stream_t stream_read; + midi_driver_stream_t stream_write; + midi_driver_stream_t stream_read; /*------------- From this point, data is not cleared by bus reset -------------*/ // FIFO @@ -122,7 +118,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num) (void) cable_num; midid_interface_t* midi = &_midid_itf[itf]; - const midid_stream_t* stream = &midi->stream_read; + const midi_driver_stream_t* stream = &midi->stream_read; // when using with packet API stream total & index are both zero return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index); @@ -136,7 +132,7 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui uint8_t* buf8 = (uint8_t*) buffer; midid_interface_t* midi = &_midid_itf[itf]; - midid_stream_t* stream = &midi->stream_read; + midi_driver_stream_t* stream = &midi->stream_read; uint32_t total_read = 0; while( bufsize ) @@ -241,7 +237,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t* midid_interface_t* midi = &_midid_itf[itf]; TU_VERIFY(midi->ep_in, 0); - midid_stream_t* stream = &midi->stream_write; + midi_driver_stream_t* stream = &midi->stream_write; uint32_t i = 0; while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) ) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 7d6eb35fa..b6ebaa7a9 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -37,14 +37,6 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -// TODO: refactor to share code with the MIDI Device driver -typedef struct -{ - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -}midi_stream_t; - typedef struct { uint8_t dev_addr; uint8_t itf_num; @@ -58,8 +50,8 @@ typedef struct { // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. - midi_stream_t stream_write; - midi_stream_t stream_read; + midi_driver_stream_t stream_write; + midi_driver_stream_t stream_read; /*------------- From this point, data is not cleared by bus reset -------------*/ // Endpoint stream @@ -152,7 +144,7 @@ void midih_close(uint8_t dev_addr) { return; } if (tuh_midi_umount_cb) { - tuh_midi_umount_cb(dev_addr, 0); + tuh_midi_umount_cb(dev_addr); } p_midi_host->ep_in = 0; p_midi_host->ep_out = 0; @@ -422,7 +414,7 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { p_midi_host->configured = true; if (tuh_midi_mount_cb) { - tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); + tuh_midi_mount_cb(dev_addr, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); } tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for incoming data @@ -445,7 +437,7 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); TU_VERIFY(cable_num < p_midi_host->num_cables_tx); - midi_stream_t *stream = &p_midi_host->stream_write; + midi_driver_stream_t *stream = &p_midi_host->stream_write; uint32_t i = 0; while ((i < bufsize) && (tu_edpt_stream_write_available(dev_addr, &p_midi_host->ep_stream.tx) >= 4)) { @@ -453,7 +445,7 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons i++; if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { // real-time messages need to be sent right away - midi_stream_t streamrt; + midi_driver_stream_t streamrt; streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; streamrt.buffer[1] = data; streamrt.index = 2; @@ -555,14 +547,14 @@ uint32_t tuh_midi_stream_flush(uint8_t dev_addr) { uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL, 0); - TU_VERIFY(p_midi_host->ep_out != 0, 0); + TU_VERIFY(p_midi_host->ep_stream.tx.ep_addr != 0, 0); return p_midi_host->num_cables_tx; } uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL, 0); - TU_VERIFY(p_midi_host->ep_in != 0, 0); + TU_VERIFY(p_midi_host->ep_stream.rx.ep_addr != 0, 0); return p_midi_host->num_cables_rx; } diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 6529f2bbc..ab6c43908 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -122,14 +122,10 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * //--------------------------------------------------------------------+ // Invoked when device with MIDI interface is mounted. -// If the MIDI host application requires MIDI IN, it should request an -// IN transfer here. The device will likely NAK this transfer. How the driver -// handles the NAK is hardware dependent. -TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx); +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx); // Invoked when device with MIDI interface is un-mounted -// For now, the instance parameter is always 0 and can be ignored -TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance); +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t dev_addr); TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets); TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t dev_addr); From 997771fdbaddd4943515e8cdade00c1252b351de Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 14 Feb 2025 16:21:48 +0700 Subject: [PATCH 50/87] - rename tuh_midi_stream_flush() to tuh_midi_write_flush() - add tuh_midi_packet_read_n() and tuh_midi_packet_write_n() - add CFG_TUH_MIDI_STREAM_API to opt out stream API --- src/class/midi/midi_host.c | 102 +++++++++++++++++++++---------------- src/class/midi/midi_host.h | 63 +++++++++++++++-------- 2 files changed, 99 insertions(+), 66 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index b6ebaa7a9..55146accb 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -47,13 +47,14 @@ typedef struct { uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value + #if CFG_TUH_MIDI_STREAM_API // For Stream read()/write() API // Messages are always 4 bytes long, queue them for reading and writing so the // callers can use the Stream interface with single-byte read/write calls. midi_driver_stream_t stream_write; midi_driver_stream_t stream_read; + #endif - /*------------- From this point, data is not cleared by bus reset -------------*/ // Endpoint stream struct { tu_edpt_stream_t tx; @@ -433,6 +434,57 @@ bool tuh_midi_configured(uint8_t dev_addr) { return p_midi_host->configured; } +uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL, 0); + TU_VERIFY(p_midi_host->ep_stream.tx.ep_addr != 0, 0); + return p_midi_host->num_cables_tx; +} + +uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL, 0); + TU_VERIFY(p_midi_host->ep_stream.rx.ep_addr != 0, 0); + return p_midi_host->num_cables_rx; +} + +uint32_t tuh_midi_read_available(uint8_t dev_addr) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL); + return tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx); +} + +uint32_t tuh_midi_write_flush(uint8_t dev_addr) { + midih_interface_t *p_midi = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi != NULL); + return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx); +} + +//--------------------------------------------------------------------+ +// Packet API +//--------------------------------------------------------------------+ + +uint32_t tuh_midi_packet_read_n(uint8_t dev_addr, uint8_t* buffer, uint32_t bufsize) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL); + + uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx)); + count4 = tu_align4(count4); // round down to multiple of 4 + TU_VERIFY(count4 > 0, 0); + return tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, buffer, count4); +} + +uint32_t tuh_midi_packet_write_n(uint8_t dev_addr, const uint8_t* buffer, uint32_t bufsize) { + midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); + TU_VERIFY(p_midi_host != NULL, 0); + uint32_t bufsize4 = tu_align4(bufsize); + return tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, buffer, bufsize4); +} + +//--------------------------------------------------------------------+ +// Stream API +//--------------------------------------------------------------------+ +#if CFG_TUH_MIDI_STREAM_API uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); @@ -530,47 +582,6 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons return i; } -bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - return 4 == tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, packet, 4); -} - -uint32_t tuh_midi_stream_flush(uint8_t dev_addr) { - midih_interface_t *p_midi = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi != NULL); - return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx); -} -//--------------------------------------------------------------------+ -// Helper -//--------------------------------------------------------------------+ -uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - TU_VERIFY(p_midi_host->ep_stream.tx.ep_addr != 0, 0); - return p_midi_host->num_cables_tx; -} - -uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - TU_VERIFY(p_midi_host->ep_stream.rx.ep_addr != 0, 0); - return p_midi_host->num_cables_rx; -} - -uint32_t tuh_midi_read_available(uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - return tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx); -} - -bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx) >= 4); - return 4 == tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, packet, 4); -} - uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); @@ -669,6 +680,9 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p return bytes_buffered; } +//--------------------------------------------------------------------+ +// String API +//--------------------------------------------------------------------+ #if CFG_MIDI_HOST_DEVSTRINGS static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) { @@ -690,9 +704,7 @@ static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) } return index; } -#endif -#if CFG_MIDI_HOST_DEVSTRINGS uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL, 0); @@ -732,3 +744,5 @@ uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings) return nstrings; } #endif + +#endif diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index ab6c43908..6e2595e44 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -24,8 +24,8 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MIDI_HOST_H_ -#define _TUSB_MIDI_HOST_H_ +#ifndef TUSB_MIDI_HOST_H_ +#define TUSB_MIDI_HOST_H_ #include "class/audio/audio.h" #include "midi.h" @@ -53,6 +53,12 @@ #define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MPS #endif +// Enable the MIDI stream read/write API. Some library can work with raw USB MIDI packet +// Disable this can save driver footprint. +#ifndef CFG_TUH_MIDI_STREAM_API +#define CFG_TUH_MIDI_STREAM_API 1 +#endif + #ifndef CFG_MIDI_HOST_DEVSTRINGS #define CFG_MIDI_HOST_DEVSTRINGS 0 #endif @@ -60,7 +66,7 @@ //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -bool tuh_midi_configured (uint8_t dev_addr); +bool tuh_midi_configured (uint8_t dev_addr); // return the number of virtual midi cables on the device's IN endpoint uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); @@ -74,40 +80,51 @@ uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); #endif -// return the raw number of bytes available from device endpoint. +// return the raw number of bytes available. // Note: this is related but not the same as number of stream bytes available. uint32_t tuh_midi_read_available(uint8_t dev_addr); +// Send any queued packets to the device if the host hardware is able to do it +// Returns the number of bytes flushed to the host hardware or 0 if +// the host hardware is busy or there is nothing in queue to send. +uint32_t tuh_midi_write_flush( uint8_t dev_addr); + //--------------------------------------------------------------------+ // Packet API //--------------------------------------------------------------------+ -// Read a raw MIDI packet from the connected device -// This function does not parse the packet format -// Return true if a packet was returned -bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]); +// Read all available MIDI packets from the connected device +// Return number of bytes read (always multiple of 4) +uint32_t tuh_midi_packet_read_n(uint8_t dev_addr, uint8_t* buffer, uint32_t bufsize); -// Queue a packet to the device. The application -// must call tuh_midi_stream_flush to actually have the -// data go out. It is up to the application to properly -// format this packet; this function does not check. +// Read a raw MIDI packet from the connected device +// Return true if a packet was returned +TU_ATTR_ALWAYS_INLINE static inline +bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) { + return 4 == tuh_midi_packet_read_n(dev_addr, packet, 4); +} + +// Write all 4-byte packets, data is locally buffered and only transferred when buffered bytes +// reach the endpoint packet size or tuh_midi_write_flush() is called +uint32_t tuh_midi_packet_write_n(uint8_t dev_addr, const uint8_t* buffer, uint32_t bufsize); + +// Write a 4-bytes packet to the device. // Returns true if the packet was successfully queued. -bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]); +TU_ATTR_ALWAYS_INLINE static inline +bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) { + return 4 == tuh_midi_packet_write_n(dev_addr, packet, 4); +} //--------------------------------------------------------------------+ // Stream API //--------------------------------------------------------------------+ +#if CFG_TUH_MIDI_STREAM_API -// Queue a message to the device. The application -// must call tuh_midi_stream_flush to actually have the -// data go out. +// Queue a message to the device using stream API. data is locally buffered and only transferred when buffered bytes +// reach the endpoint packet size or tuh_midi_write_flush() is called +// Returns number of bytes was successfully queued. uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* p_buffer, uint32_t bufsize); -// Send any queued packets to the device if the host hardware is able to do it -// Returns the number of bytes flushed to the host hardware or 0 if -// the host hardware is busy or there is nothing in queue to send. -uint32_t tuh_midi_stream_flush( uint8_t dev_addr); - // Get the MIDI stream from the device. Set the value pointed // to by p_cable_num to the MIDI cable number intended to receive it. // The MIDI stream will be stored in the buffer pointed to by p_buffer. @@ -117,6 +134,8 @@ uint32_t tuh_midi_stream_flush( uint8_t dev_addr); // it properly. uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); +#endif + //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ @@ -144,4 +163,4 @@ void midih_close (uint8_t dev_addr); } #endif -#endif /* _TUSB_MIDI_HOST_H_ */ +#endif From aa860041b8cfad9b5740db93d013add03667f01c Mon Sep 17 00:00:00 2001 From: Devin Auclair Date: Fri, 14 Feb 2025 11:01:33 -0500 Subject: [PATCH 51/87] Add full/high speed compile flag for Microchip SAME70 examples Default is still high speed, but setting SPEED=high|full work as expected. `make BOARD=same70_xplained SPEED=full` Tested with examples/device/cdc_msc ```preformatted lsusb -v ... TinyUSB Device: Product ID: 0x4003 Vendor ID: 0xcafe Version: 1.00 Serial Number: 0123456789ABCDEF Speed: Up to 12 Mb/s <------ full speed here Manufacturer: TinyUSB Location ID: 0x03142130 / 12 Current Available (mA): 500 Current Required (mA): 100 Extra Operating Current (mA): 0 Media: Mass Storage: Capacity: 8 KB (8,192 bytes) Removable Media: Yes BSD Name: disk5 Logical Unit: 0 Partition Map Type: Unknown S.M.A.R.T. status: Verified USB Interface: 2 ``` --- hw/bsp/same70_xplained/board.mk | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk index 3edc128a5..60702f14a 100644 --- a/hw/bsp/same70_xplained/board.mk +++ b/hw/bsp/same70_xplained/board.mk @@ -14,6 +14,14 @@ CFLAGS += \ # suppress following warnings from mcu driver CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=redundant-decls +SPEED ?= high + +ifeq ($(SPEED), high) + CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED +else + CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED +endif + # SAM driver is flooded with -Wcast-qual which slow down complication significantly CFLAGS_SKIP += -Wcast-qual From 18d566b94c8f17d9df04914979997d589b905290 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 Feb 2025 17:06:51 +0700 Subject: [PATCH 52/87] improve hub: retry if hub interrupt endpoint failed bump up pio-usb to latest --- src/host/hub.c | 184 ++++++++++++++++++++++------------------------ src/host/hub.h | 51 ++++++------- src/host/usbh.c | 8 +- tools/get_deps.py | 9 ++- 4 files changed, 120 insertions(+), 132 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index e97014443..611bf71be 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -40,29 +40,37 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef struct -{ +typedef struct { uint8_t itf_num; uint8_t ep_in; - uint8_t port_count; + + // from hub descriptor + uint8_t bNbrPorts; + // uint8_t bPwrOn2PwrGood; + // uint16_t wHubCharacteristics; CFG_TUH_MEM_ALIGN uint8_t status_change; CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status; CFG_TUH_MEM_ALIGN hub_status_response_t hub_status; } hub_interface_t; -CFG_TUH_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB]; -CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)]; +typedef struct { + TUH_EPBUF_DEF(buf, CFG_TUH_HUB_BUFSIZE); +} hub_epbuf_t; -TU_ATTR_ALWAYS_INLINE -static inline hub_interface_t* get_itf(uint8_t dev_addr) -{ - return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX]; +CFG_TUH_MEM_SECTION static hub_interface_t hub_itfs[CFG_TUH_HUB]; +CFG_TUH_MEM_SECTION static hub_epbuf_t hub_epbufs[CFG_TUH_HUB]; + +TU_ATTR_ALWAYS_INLINE static inline hub_interface_t* get_hub_itf(uint8_t daddr) { + return &hub_itfs[daddr-1-CFG_TUH_DEVICE_MAX]; } -#if CFG_TUSB_DEBUG >= 2 -static char const* const _hub_feature_str[] = -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t* get_hub_epbuf(uint8_t daddr) { + return hub_epbufs[daddr-1-CFG_TUH_DEVICE_MAX].buf; +} + +#if CFG_TUSB_DEBUG >= HUB_DEBUG +static char const* const _hub_feature_str[] = { [HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION", [HUB_FEATURE_PORT_ENABLE ] = "PORT_ENABLE", [HUB_FEATURE_PORT_SUSPEND ] = "PORT_SUSPEND", @@ -84,12 +92,9 @@ static char const* const _hub_feature_str[] = // HUB //--------------------------------------------------------------------+ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request = { + .bmRequestType_bit = { .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT @@ -100,8 +105,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - tuh_xfer_t xfer = - { + tuh_xfer_t xfer = { .daddr = hub_addr, .ep_addr = 0, .setup = &request, @@ -110,7 +114,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .user_data = user_data }; - TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); + TU_LOG_DRV("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -142,7 +146,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .user_data = user_data }; - TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); + TU_LOG_DRV("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); TU_ASSERT( tuh_control_xfer(&xfer) ); return true; } @@ -174,7 +178,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .user_data = user_data }; - TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); + TU_LOG_DRV("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port); TU_VERIFY( tuh_control_xfer(&xfer) ); return true; } @@ -183,7 +187,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ bool hub_init(void) { - tu_memclr(hub_data, sizeof(hub_data)); + tu_memclr(hub_itfs, sizeof(hub_itfs)); return true; } @@ -191,40 +195,32 @@ bool hub_deinit(void) { return true; } -bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) -{ +bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) { (void) rhport; TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass && 0 == itf_desc->bInterfaceSubClass); + TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // not support multiple TT yet - // hub driver does not support multiple TT yet - TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); - - // msc driver length is fixed uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t); TU_ASSERT(drv_len <= max_len); - //------------- Interrupt Status endpoint -------------// + // Interrupt Status endpoint tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc); - TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType && TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0); - TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - hub_interface_t* p_hub = get_itf(dev_addr); - + hub_interface_t* p_hub = get_hub_itf(dev_addr); p_hub->itf_num = itf_desc->bInterfaceNumber; p_hub->ep_in = desc_ep->bEndpointAddress; return true; } -void hub_close(uint8_t dev_addr) -{ +void hub_close(uint8_t dev_addr) { TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, ); - hub_interface_t* p_hub = get_itf(dev_addr); + hub_interface_t* p_hub = get_hub_itf(dev_addr); if (p_hub->ep_in) { TU_LOG_DRV(" HUB close addr = %d\r\n", dev_addr); @@ -232,30 +228,24 @@ void hub_close(uint8_t dev_addr) } } -bool hub_edpt_status_xfer(uint8_t dev_addr) -{ - hub_interface_t* hub_itf = get_itf(dev_addr); +bool hub_edpt_status_xfer(uint8_t dev_addr) { + hub_interface_t* hub_itf = get_hub_itf(dev_addr); return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); } - //--------------------------------------------------------------------+ // Set Configure //--------------------------------------------------------------------+ - static void config_set_port_power (tuh_xfer_t* xfer); static void config_port_power_complete (tuh_xfer_t* xfer); -bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) -{ - hub_interface_t* p_hub = get_itf(dev_addr); +bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { + hub_interface_t* p_hub = get_hub_itf(dev_addr); TU_ASSERT(itf_num == p_hub->itf_num); // Get Hub Descriptor - tusb_control_request_t const request = - { - .bmRequestType_bit = - { + tusb_control_request_t const request = { + .bmRequestType_bit = { .recipient = TUSB_REQ_RCPT_DEVICE, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN @@ -263,34 +253,31 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) .bRequest = HUB_REQUEST_GET_DESCRIPTOR, .wValue = 0, .wIndex = 0, - .wLength = sizeof(descriptor_hub_desc_t) + .wLength = sizeof(hub_desc_cs_t) }; - tuh_xfer_t xfer = - { + tuh_xfer_t xfer = { .daddr = dev_addr, .ep_addr = 0, .setup = &request, - .buffer = _hub_buffer, + .buffer = get_hub_epbuf(dev_addr), .complete_cb = config_set_port_power, .user_data = 0 }; - TU_ASSERT( tuh_control_xfer(&xfer) ); - + TU_ASSERT(tuh_control_xfer(&xfer)); return true; } -static void config_set_port_power (tuh_xfer_t* xfer) -{ +static void config_set_port_power (tuh_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_itf(daddr); + hub_interface_t* p_hub = get_hub_itf(daddr); // only use number of ports in hub descriptor - descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer; - p_hub->port_count = desc_hub->bNbrPorts; + hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) get_hub_epbuf(daddr); + p_hub->bNbrPorts = desc_hub->bNbrPorts; // May need to GET_STATUS @@ -299,14 +286,13 @@ static void config_set_port_power (tuh_xfer_t* xfer) hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); } -static void config_port_power_complete (tuh_xfer_t* xfer) -{ +static void config_port_power_complete (tuh_xfer_t* xfer) { TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, ); uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_itf(daddr); + hub_interface_t* p_hub = get_hub_itf(daddr); - if (xfer->setup->wIndex == p_hub->port_count) + if (xfer->setup->wIndex == p_hub->bNbrPorts) { // All ports are power -> queue notification status endpoint and // complete the SET CONFIGURATION @@ -334,46 +320,48 @@ static void connection_port_reset_complete (tuh_xfer_t* xfer); bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports (void) ep_addr; - TU_VERIFY(result == XFER_RESULT_SUCCESS); - hub_interface_t* p_hub = get_itf(dev_addr); + if (result == XFER_RESULT_SUCCESS) { + hub_interface_t* p_hub = get_hub_itf(dev_addr); - uint8_t const status_change = p_hub->status_change; - TU_LOG2(" Hub Status Change = 0x%02X\r\n", status_change); + uint8_t const status_change = p_hub->status_change; + TU_LOG_DRV(" Hub Status Change = 0x%02X\r\n", status_change); - if ( status_change == 0 ) { - // The status change event was neither for the hub, nor for any of its ports. - // This shouldn't happen, but it does with some devices. - // Initiate the next interrupt poll here. - return hub_edpt_status_xfer(dev_addr); - } - - if (tu_bit_test(status_change, 0)) { - // Hub bit 0 is for the hub device events - if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) { - //Hub status control transfer failed, retry - hub_edpt_status_xfer(dev_addr); + if ( status_change == 0 ) { + // The status change event was neither for the hub, nor for any of its ports. + // This shouldn't happen, but it does with some devices. Initiate the next interrupt poll here. + return hub_edpt_status_xfer(dev_addr); } - } - else { - // Hub bits 1 to n are hub port events - for (uint8_t port=1; port <= p_hub->port_count; port++) { - if ( tu_bit_test(status_change, port) ) { - if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) { - //Hub status control transfer failed, retry - hub_edpt_status_xfer(dev_addr); - } - break; + + if (tu_bit_test(status_change, 0)) { + // Hub bit 0 is for the hub device events + if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) { + //Hub status control transfer failed, retry + hub_edpt_status_xfer(dev_addr); } } + else { + // Hub bits 1 to n are hub port events + for (uint8_t port=1; port <= p_hub->bNbrPorts; port++) { + if ( tu_bit_test(status_change, port) ) { + if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) { + //Hub status control transfer failed, retry + hub_edpt_status_xfer(dev_addr); + } + break; + } + } + } + } else { + TU_LOG_DRV(" Hub Status Change: failed, retry\r\n"); + hub_edpt_status_xfer(dev_addr); // retry } // NOTE: next status transfer is queued by usbh.c after handling this request return true; } -static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer) -{ +static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); hub_edpt_status_xfer(xfer->daddr); } @@ -383,15 +371,15 @@ static void hub_get_status_complete (tuh_xfer_t* xfer) TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_itf(daddr); + hub_interface_t* p_hub = get_hub_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); TU_ASSERT(port_num == 0 , ); - TU_LOG2("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value); + TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value); if (p_hub->hub_status.change.local_power_source) { - TU_LOG2("HUB Local Power Change, addr = %u\r\n", daddr); + TU_LOG_DRV("HUB Local Power Change, addr = %u\r\n", daddr); hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, hub_clear_feature_complete_stub, 0); } else if (p_hub->hub_status.change.over_current) @@ -406,7 +394,7 @@ static void hub_port_get_status_complete (tuh_xfer_t* xfer) TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_itf(daddr); + hub_interface_t* p_hub = get_hub_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // Connection change @@ -453,7 +441,7 @@ static void connection_clear_conn_change_complete (tuh_xfer_t* xfer) TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_itf(daddr); + hub_interface_t* p_hub = get_hub_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); if ( p_hub->port_status.status.connection ) diff --git a/src/host/hub.h b/src/host/hub.h index 385efe6b2..59097fb0a 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -24,17 +24,8 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup group_class - * \defgroup ClassDriver_Hub Hub (Host only) - * \details Like most PC's OS, Hub support is completely hidden from Application. In fact, application cannot determine whether - * a device is mounted directly via roothub or via a hub's port. All Hub-related procedures are performed and managed - * by tinyusb stack. Unless you are trying to develop the stack itself, there are nothing else can be used by Application. - * \note Due to my laziness, only 1-level of Hub is supported. In other way, the stack cannot mount a hub via another hub. - * @{ - */ - -#ifndef _TUSB_HUB_H_ -#define _TUSB_HUB_H_ +#ifndef TUSB_HUB_H_ +#define TUSB_HUB_H_ #include "common/tusb_common.h" @@ -42,6 +33,14 @@ extern "C" { #endif +//--------------------------------------------------------------------+ +// Configuration +//--------------------------------------------------------------------+ + +#ifndef CFG_TUH_HUB_BUFSIZE + #define CFG_TUH_HUB_BUFSIZE 12 +#endif + //D1...D0: Logical Power Switching Mode //00: Ganged power switching (all ports’power at //once) @@ -89,16 +88,17 @@ typedef struct TU_ATTR_PACKED{ uint8_t bHubContrCurrent; uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff -} descriptor_hub_desc_t; +} hub_desc_cs_t; -TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct"); +TU_VERIFY_STATIC(sizeof(hub_desc_cs_t) == 9, "size is not correct"); +TU_VERIFY_STATIC(CFG_TUH_HUB_BUFSIZE >= sizeof(hub_desc_cs_t), "buffer is not big enough"); enum { HUB_REQUEST_GET_STATUS = 0 , HUB_REQUEST_CLEAR_FEATURE = 1 , - + // 2 is reserved HUB_REQUEST_SET_FEATURE = 3 , - + // 4-5 are reserved HUB_REQUEST_GET_DESCRIPTOR = 6 , HUB_REQUEST_SET_DESCRIPTOR = 7 , HUB_REQUEST_CLEAR_TT_BUFFER = 8 , @@ -118,10 +118,10 @@ enum{ HUB_FEATURE_PORT_SUSPEND = 2, HUB_FEATURE_PORT_OVER_CURRENT = 3, HUB_FEATURE_PORT_RESET = 4, - + // 5-7 are reserved HUB_FEATURE_PORT_POWER = 8, HUB_FEATURE_PORT_LOW_SPEED = 9, - + // 10-15 are reserved HUB_FEATURE_PORT_CONNECTION_CHANGE = 16, HUB_FEATURE_PORT_ENABLE_CHANGE = 17, HUB_FEATURE_PORT_SUSPEND_CHANGE = 18, @@ -172,16 +172,16 @@ typedef struct { TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); // Clear feature -bool hub_port_clear_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Set feature -bool hub_port_set_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get port status -bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp, - tuh_xfer_cb_t complete_cb, uintptr_t user_data); +bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void *resp, + tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get status from Interrupt endpoint bool hub_edpt_status_xfer(uint8_t dev_addr); @@ -198,7 +198,6 @@ bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data); } - //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ @@ -213,6 +212,4 @@ void hub_close (uint8_t dev_addr); } #endif -#endif /* _TUSB_HUB_H_ */ - -/** @} */ +#endif diff --git a/src/host/usbh.c b/src/host/usbh.c index a2994cde7..5f4f17167 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -467,13 +467,11 @@ bool tuh_task_event_ready(void) { * This should be called periodically within the mainloop or rtos thread. * @code - int main(void) - { + int main(void) { application_init(); tusb_init(0, TUSB_ROLE_HOST); - while(1) // the mainloop - { + while(1) { // the mainloop application_code(); tuh_task(); // tinyusb host task } @@ -1657,7 +1655,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur if ( 0 == tu_desc_len(p_desc) ) { // A zero length descriptor indicates that the device is off spec (e.g. wrong wTotalLength). // Parsed interfaces should still be usable - TU_LOG_USBH("Encountered a zero-length descriptor after %u bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg); + TU_LOG_USBH("Encountered a zero-length descriptor after %" PRIu32 "bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg); break; } diff --git a/tools/get_deps.py b/tools/get_deps.py index c8459c1f1..3665904b3 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -59,7 +59,7 @@ deps_optional = { '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', - 'fe9133fc513b82cc3dc62c67cb51f2339cf29ef7', + '442af432568f25fb72c5784d9d67b8e85465cb28', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', @@ -217,7 +217,12 @@ TOP = Path(__file__).parent.parent.resolve() def run_cmd(cmd): - return subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + r = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + title = f'Command Error: {cmd}' + if r.returncode != 0: + print(title) + print(r.stdout.decode("utf-8")) + return r def get_a_dep(d): From 792a44640509661b11065a8d6ee038d9362a2b9f Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 17 Feb 2025 22:40:19 +0700 Subject: [PATCH 53/87] usbh always retry control transfer (max 3) in case of XFER_RESULT_FAILED. added tuh_connected() --- src/common/tusb_types.h | 6 +- src/host/hub.c | 76 ++++++++------------- src/host/hub.h | 2 +- src/host/usbh.c | 142 ++++++++++++++++++++++++---------------- src/host/usbh.h | 4 ++ src/host/usbh_pvt.h | 4 +- 6 files changed, 125 insertions(+), 109 deletions(-) diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 9e4d9380c..42ce5fc12 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -302,9 +302,9 @@ typedef enum { enum { CONTROL_STAGE_IDLE = 0, - CONTROL_STAGE_SETUP, - CONTROL_STAGE_DATA, - CONTROL_STAGE_ACK + CONTROL_STAGE_SETUP, // 1 + CONTROL_STAGE_DATA, // 2 + CONTROL_STAGE_ACK // 3 }; enum { diff --git a/src/host/hub.c b/src/host/hub.c index 611bf71be..1d3e9ae1d 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -120,12 +120,9 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, } bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request = { + .bmRequestType_bit = { .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_OUT @@ -136,8 +133,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, .wLength = 0 }; - tuh_xfer_t xfer = - { + tuh_xfer_t xfer = { .daddr = hub_addr, .ep_addr = 0, .setup = &request, @@ -152,12 +148,9 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, } bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, - tuh_xfer_cb_t complete_cb, uintptr_t user_data) -{ - tusb_control_request_t const request = - { - .bmRequestType_bit = - { + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + tusb_control_request_t const request = { + .bmRequestType_bit = { .recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER, .type = TUSB_REQ_TYPE_CLASS, .direction = TUSB_DIR_IN @@ -168,8 +161,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .wLength = 4 }; - tuh_xfer_t xfer = - { + tuh_xfer_t xfer = { .daddr = hub_addr, .ep_addr = 0, .setup = &request, @@ -228,9 +220,9 @@ void hub_close(uint8_t dev_addr) { } } -bool hub_edpt_status_xfer(uint8_t dev_addr) { - hub_interface_t* hub_itf = get_hub_itf(dev_addr); - return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1); +bool hub_edpt_status_xfer(uint8_t daddr) { + hub_interface_t* hub_itf = get_hub_itf(daddr); + return usbh_edpt_xfer(daddr, hub_itf->ep_in, &hub_itf->status_change, 1); } //--------------------------------------------------------------------+ @@ -292,15 +284,15 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; hub_interface_t* p_hub = get_hub_itf(daddr); - if (xfer->setup->wIndex == p_hub->bNbrPorts) - { + if (xfer->setup->wIndex == p_hub->bNbrPorts) { // All ports are power -> queue notification status endpoint and // complete the SET CONFIGURATION - TU_ASSERT( usbh_edpt_xfer(daddr, p_hub->ep_in, &p_hub->status_change, 1), ); - + if (!hub_edpt_status_xfer(daddr)) { + TU_MESS_FAILED(); + TU_BREAKPOINT(); + } usbh_driver_set_config_complete(daddr, p_hub->itf_num); - }else - { + } else { // power next port uint8_t const hub_port = (uint8_t) (xfer->setup->wIndex + 1); hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0); @@ -310,7 +302,6 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { //--------------------------------------------------------------------+ // Connection Changes //--------------------------------------------------------------------+ - static void hub_port_get_status_complete (tuh_xfer_t* xfer); static void hub_get_status_complete (tuh_xfer_t* xfer); static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); @@ -389,46 +380,35 @@ static void hub_get_status_complete (tuh_xfer_t* xfer) } } -static void hub_port_get_status_complete (tuh_xfer_t* xfer) -{ +static void hub_port_get_status_complete(tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_hub_itf(daddr); + hub_interface_t *p_hub = get_hub_itf(daddr); uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // Connection change - if (p_hub->port_status.change.connection) - { + if (p_hub->port_status.change.connection) { // Port is powered and enabled //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); // Acknowledge Port Connection Change hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); - }else - { + } else { // Clear other port status change interrupts. TODO Not currently handled - just cleared. - if (p_hub->port_status.change.port_enable) - { + if (p_hub->port_status.change.port_enable) { hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, hub_clear_feature_complete_stub, 0); - } - else if (p_hub->port_status.change.suspend) - { + } else if (p_hub->port_status.change.suspend) { hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, hub_clear_feature_complete_stub, 0); - } - else if (p_hub->port_status.change.over_current) - { + } else if (p_hub->port_status.change.over_current) { hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0); - } - else if (p_hub->port_status.change.reset) - { + } else if (p_hub->port_status.change.reset) { hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, hub_clear_feature_complete_stub, 0); } - // Other changes are: L1 state - // TODO clear change + else { + // Other changes are: L1 state + // TODO clear change - else - { // prepare for next hub status // TODO continue with status_change, or maybe we can do it again with status hub_edpt_status_xfer(daddr); diff --git a/src/host/hub.h b/src/host/hub.h index 59097fb0a..3b19e9838 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -184,7 +184,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void *resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data); // Get status from Interrupt endpoint -bool hub_edpt_status_xfer(uint8_t dev_addr); +bool hub_edpt_status_xfer(uint8_t daddr); // Reset a port TU_ATTR_ALWAYS_INLINE static inline diff --git a/src/host/usbh.c b/src/host/usbh.c index 5f4f17167..ac920f533 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -44,6 +44,10 @@ #define CFG_TUH_INTERFACE_MAX 8 #endif +enum { + USBH_CONTROL_RETRY_MAX = 3, +}; + //--------------------------------------------------------------------+ // Weak stubs: invoked if no strong implementation is available //--------------------------------------------------------------------+ @@ -272,9 +276,10 @@ static struct { tuh_xfer_cb_t complete_cb; uintptr_t user_data; - uint8_t daddr; volatile uint8_t stage; + uint8_t daddr; volatile uint16_t actual_len; + uint8_t failed_count; } _ctrl_xfer; typedef struct { @@ -285,7 +290,6 @@ typedef struct { CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf; //------------- Helper Function -------------// - TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) { TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL); return &_usbh_devices[dev_addr-1]; @@ -312,6 +316,15 @@ bool tuh_mounted(uint8_t dev_addr) { return dev->configured; } +bool tuh_connected(uint8_t daddr) { + if (daddr == 0) { + return _dev0.enumerating; // dev0 is connected if still enumerating + } else { + const usbh_device_t* dev = get_device(daddr); + return dev && dev->connected; + } +} + bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) { *vid = *pid = 0; @@ -421,7 +434,9 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { } bool tuh_deinit(uint8_t rhport) { - if (!tuh_rhport_is_active(rhport)) return true; + if (!tuh_rhport_is_active(rhport)) { + return true; + } // deinit host controller hcd_int_disable(rhport); @@ -482,7 +497,9 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) { (void) in_isr; // not implemented yet // Skip if stack is not initialized - if (!tuh_inited()) return; + if (!tuh_inited()) { + return; + } // Loop until there is no more events in the queue while (1) { @@ -616,17 +633,9 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) { // TODO timeout_ms is not supported yet bool tuh_control_xfer (tuh_xfer_t* xfer) { - // EP0 with setup packet - TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); - - // Check if device is still connected (enumerating for dev0) + TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet const uint8_t daddr = xfer->daddr; - if (daddr == 0) { - TU_VERIFY(_dev0.enumerating); - } else { - const usbh_device_t* dev = get_device(daddr); - TU_VERIFY(dev && dev->connected); - } + TU_VERIFY(tuh_connected(daddr)); // Check if device is still connected (enumerating for dev0) // pre-check to help reducing mutex lock TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE); @@ -634,14 +643,15 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE); if (is_idle) { - _ctrl_xfer.stage = CONTROL_STAGE_SETUP; - _ctrl_xfer.daddr = daddr; - _ctrl_xfer.actual_len = 0; + _ctrl_xfer.stage = CONTROL_STAGE_SETUP; + _ctrl_xfer.daddr = daddr; + _ctrl_xfer.actual_len = 0; + _ctrl_xfer.failed_count = 0; - _ctrl_xfer.buffer = xfer->buffer; - _ctrl_xfer.complete_cb = xfer->complete_cb; - _ctrl_xfer.user_data = xfer->user_data; - _usbh_epbuf.request = (*xfer->setup); + _ctrl_xfer.buffer = xfer->buffer; + _ctrl_xfer.complete_cb = xfer->complete_cb; + _ctrl_xfer.user_data = xfer->user_data; + _usbh_epbuf.request = (*xfer->setup); } (void) osal_mutex_unlock(_usbh_mutex); @@ -655,7 +665,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { TU_LOG_BUF_USBH(xfer->setup, 8); if (xfer->complete_cb) { - TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_usbh_epbuf.request) ); + TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t const *) &_usbh_epbuf.request)); }else { // blocking if complete callback is not provided // change callback to internal blocking, and result as user argument @@ -665,7 +675,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) { _ctrl_xfer.user_data = (uintptr_t) &result; _ctrl_xfer.complete_cb = _control_blocking_complete_cb; - TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_usbh_epbuf.request) ); + TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t *) &_usbh_epbuf.request)); while (result == XFER_RESULT_INVALID) { // Note: this can be called within an callback ie. part of tuh_task() @@ -722,28 +732,46 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t const uint8_t rhport = usbh_get_rhport(daddr); tusb_control_request_t const * request = &_usbh_epbuf.request; - if (XFER_RESULT_SUCCESS != result) { - TU_LOG_USBH("[%u:%u] Control %s, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes); - TU_LOG_BUF_USBH(request, 8); + switch (result) { + case XFER_RESULT_STALLED: + TU_LOG_USBH("[%u:%u] Control STALLED, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, xferred_bytes); + TU_LOG_BUF_USBH(request, 8); + _control_xfer_complete(daddr, result); + break; - // terminate transfer if any stage failed - _control_xfer_complete(daddr, result); - }else { - switch(_ctrl_xfer.stage) { - case CONTROL_STAGE_SETUP: - if (request->wLength) { - // DATA stage: initial data toggle is always 1 - _set_control_xfer_stage(CONTROL_STAGE_DATA); - TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) ); - return true; - } + case XFER_RESULT_FAILED: + if (tuh_connected(daddr) && _ctrl_xfer.failed_count < USBH_CONTROL_RETRY_MAX) { + TU_LOG_USBH("[%u:%u] Control FAILED %u/%u, retrying\r\n", rhport, daddr, _ctrl_xfer.failed_count+1, USBH_CONTROL_RETRY_MAX); + (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER); + _ctrl_xfer.stage = CONTROL_STAGE_SETUP; + _ctrl_xfer.failed_count++; + _ctrl_xfer.actual_len = 0; // reset actual_len + (void) osal_mutex_unlock(_usbh_mutex); + + TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t const *) request)); + } else { + TU_LOG_USBH("[%u:%u] Control FAILED, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, xferred_bytes); + TU_LOG_BUF_USBH(request, 8); + _control_xfer_complete(daddr, result); + } + break; + + case XFER_RESULT_SUCCESS: + switch(_ctrl_xfer.stage) { + case CONTROL_STAGE_SETUP: + if (request->wLength) { + // DATA stage: initial data toggle is always 1 + _set_control_xfer_stage(CONTROL_STAGE_DATA); + TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) ); + return true; + } TU_ATTR_FALLTHROUGH; - case CONTROL_STAGE_DATA: - if (request->wLength) { - TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr); - TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2); - } + case CONTROL_STAGE_DATA: + if (request->wLength) { + TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr); + TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2); + } _ctrl_xfer.actual_len = (uint16_t) xferred_bytes; @@ -752,23 +780,26 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction), NULL, 0) ); break; - case CONTROL_STAGE_ACK: { - // Abort all pending transfers if SET_CONFIGURATION request - // NOTE: should we force closing all non-control endpoints in the future? - if (request->bRequest == TUSB_REQ_SET_CONFIGURATION && request->bmRequestType == 0x00) { - for(uint8_t epnum=1; epnumbRequest == TUSB_REQ_SET_CONFIGURATION && request->bmRequestType == 0x00) { + for(uint8_t epnum=1; epnum Date: Wed, 19 Feb 2025 11:27:33 +0700 Subject: [PATCH 54/87] move status_change to epbuf improve hub_xfer_cb() rename internal complete function --- src/host/hub.c | 88 ++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index 1d3e9ae1d..1acea8828 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -49,13 +49,13 @@ typedef struct { // uint8_t bPwrOn2PwrGood; // uint16_t wHubCharacteristics; - CFG_TUH_MEM_ALIGN uint8_t status_change; CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status; CFG_TUH_MEM_ALIGN hub_status_response_t hub_status; } hub_interface_t; typedef struct { - TUH_EPBUF_DEF(buf, CFG_TUH_HUB_BUFSIZE); + TUH_EPBUF_DEF(status_change, 4); // interrupt endpoint + TUH_EPBUF_DEF(ctrl_buf, CFG_TUH_HUB_BUFSIZE); } hub_epbuf_t; CFG_TUH_MEM_SECTION static hub_interface_t hub_itfs[CFG_TUH_HUB]; @@ -65,8 +65,8 @@ TU_ATTR_ALWAYS_INLINE static inline hub_interface_t* get_hub_itf(uint8_t daddr) return &hub_itfs[daddr-1-CFG_TUH_DEVICE_MAX]; } -TU_ATTR_ALWAYS_INLINE static inline uint8_t* get_hub_epbuf(uint8_t daddr) { - return hub_epbufs[daddr-1-CFG_TUH_DEVICE_MAX].buf; +TU_ATTR_ALWAYS_INLINE static inline hub_epbuf_t* get_hub_epbuf(uint8_t daddr) { + return &hub_epbufs[daddr-1-CFG_TUH_DEVICE_MAX]; } #if CFG_TUSB_DEBUG >= HUB_DEBUG @@ -175,6 +175,10 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, return true; } +bool hub_get_status(uint8_t hub_addr, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return hub_port_get_status(hub_addr, 0, resp, complete_cb, user_data); +} + //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -222,7 +226,8 @@ void hub_close(uint8_t dev_addr) { bool hub_edpt_status_xfer(uint8_t daddr) { hub_interface_t* hub_itf = get_hub_itf(daddr); - return usbh_edpt_xfer(daddr, hub_itf->ep_in, &hub_itf->status_change, 1); + hub_epbuf_t* p_epbuf = get_hub_epbuf(daddr); + return usbh_edpt_xfer(daddr, hub_itf->ep_in, p_epbuf->status_change, 1); } //--------------------------------------------------------------------+ @@ -234,6 +239,7 @@ static void config_port_power_complete (tuh_xfer_t* xfer); bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { hub_interface_t* p_hub = get_hub_itf(dev_addr); TU_ASSERT(itf_num == p_hub->itf_num); + hub_epbuf_t* p_epbuf = get_hub_epbuf(dev_addr); // Get Hub Descriptor tusb_control_request_t const request = { @@ -252,7 +258,7 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) { .daddr = dev_addr, .ep_addr = 0, .setup = &request, - .buffer = get_hub_epbuf(dev_addr), + .buffer = p_epbuf->ctrl_buf, .complete_cb = config_set_port_power, .user_data = 0 }; @@ -266,9 +272,10 @@ static void config_set_port_power (tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; hub_interface_t* p_hub = get_hub_itf(daddr); + hub_epbuf_t* p_epbuf = get_hub_epbuf(daddr); // only use number of ports in hub descriptor - hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) get_hub_epbuf(daddr); + hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) p_epbuf->ctrl_buf; p_hub->bNbrPorts = desc_hub->bNbrPorts; // May need to GET_STATUS @@ -302,62 +309,59 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { //--------------------------------------------------------------------+ // Connection Changes //--------------------------------------------------------------------+ -static void hub_port_get_status_complete (tuh_xfer_t* xfer); -static void hub_get_status_complete (tuh_xfer_t* xfer); +static void port_get_status_complete (tuh_xfer_t* xfer); +static void get_status_complete (tuh_xfer_t* xfer); static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); static void connection_port_reset_complete (tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports + (void) xferred_bytes; (void) ep_addr; + bool processed = false; // true if new status is processed + if (result == XFER_RESULT_SUCCESS) { hub_interface_t* p_hub = get_hub_itf(dev_addr); - - uint8_t const status_change = p_hub->status_change; + hub_epbuf_t* p_epbuf = get_hub_epbuf(dev_addr); + uint8_t const status_change = p_epbuf->status_change[0]; TU_LOG_DRV(" Hub Status Change = 0x%02X\r\n", status_change); - if ( status_change == 0 ) { + if (status_change == 0) { // The status change event was neither for the hub, nor for any of its ports. - // This shouldn't happen, but it does with some devices. Initiate the next interrupt poll here. - return hub_edpt_status_xfer(dev_addr); - } - - if (tu_bit_test(status_change, 0)) { + // This shouldn't happen, but it does with some devices. Re-Initiate the interrupt poll. + processed = false; + } else if (tu_bit_test(status_change, 0)) { // Hub bit 0 is for the hub device events - if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_get_status_complete, 0) == false) { - //Hub status control transfer failed, retry - hub_edpt_status_xfer(dev_addr); - } - } - else { + processed = hub_get_status(dev_addr, &p_hub->hub_status, get_status_complete, 0); + } else { // Hub bits 1 to n are hub port events for (uint8_t port=1; port <= p_hub->bNbrPorts; port++) { - if ( tu_bit_test(status_change, port) ) { - if (hub_port_get_status(dev_addr, port, &p_hub->port_status, hub_port_get_status_complete, 0) == false) { - //Hub status control transfer failed, retry - hub_edpt_status_xfer(dev_addr); - } - break; + if (tu_bit_test(status_change, port)) { + processed = hub_port_get_status(dev_addr, port, &p_hub->port_status, port_get_status_complete, 0); + break; // after completely processed one port, we will re-queue the status poll and handle next one } } } } else { - TU_LOG_DRV(" Hub Status Change: failed, retry\r\n"); - hub_edpt_status_xfer(dev_addr); // retry + processed = false; + } + + // If new status event is processed: next status pool is queued by usbh.c after handled this request + // Otherwise re-queue the status poll here + if (!processed) { + TU_ASSERT(hub_edpt_status_xfer(dev_addr)); } - // NOTE: next status transfer is queued by usbh.c after handling this request return true; } -static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer) { +static void port_clear_feature_complete_stub(tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); hub_edpt_status_xfer(xfer->daddr); } -static void hub_get_status_complete (tuh_xfer_t* xfer) +static void get_status_complete (tuh_xfer_t* xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); @@ -371,16 +375,16 @@ static void hub_get_status_complete (tuh_xfer_t* xfer) if (p_hub->hub_status.change.local_power_source) { TU_LOG_DRV("HUB Local Power Change, addr = %u\r\n", daddr); - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, hub_clear_feature_complete_stub, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->hub_status.change.over_current) { TU_LOG1("HUB Over Current, addr = %u\r\n", daddr); - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); } } -static void hub_port_get_status_complete(tuh_xfer_t *xfer) { +static void port_get_status_complete(tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); uint8_t const daddr = xfer->daddr; @@ -397,13 +401,13 @@ static void hub_port_get_status_complete(tuh_xfer_t *xfer) { } else { // Clear other port status change interrupts. TODO Not currently handled - just cleared. if (p_hub->port_status.change.port_enable) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, hub_clear_feature_complete_stub, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.suspend) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, hub_clear_feature_complete_stub, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.over_current) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, hub_clear_feature_complete_stub, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.reset) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, hub_clear_feature_complete_stub, 0); + hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, port_clear_feature_complete_stub, 0); } else { // Other changes are: L1 state From 27a4895b79065340c031850b7031eea5b2f60a9b Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 Feb 2025 12:58:03 +0700 Subject: [PATCH 55/87] complete separate hub epbuf from itf add hub_get_status(), hub_clear_feature() --- src/host/hub.c | 59 ++++++++++++++++++++------------------------------ src/host/hub.h | 47 ++++++++++++++++++++++++++-------------- 2 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index 1acea8828..41aefc1a7 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -49,8 +49,7 @@ typedef struct { // uint8_t bPwrOn2PwrGood; // uint16_t wHubCharacteristics; - CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status; - CFG_TUH_MEM_ALIGN hub_status_response_t hub_status; + hub_port_status_response_t port_status; } hub_interface_t; typedef struct { @@ -58,7 +57,7 @@ typedef struct { TUH_EPBUF_DEF(ctrl_buf, CFG_TUH_HUB_BUFSIZE); } hub_epbuf_t; -CFG_TUH_MEM_SECTION static hub_interface_t hub_itfs[CFG_TUH_HUB]; +static hub_interface_t hub_itfs[CFG_TUH_HUB]; CFG_TUH_MEM_SECTION static hub_epbuf_t hub_epbufs[CFG_TUH_HUB]; TU_ATTR_ALWAYS_INLINE static inline hub_interface_t* get_hub_itf(uint8_t daddr) { @@ -158,7 +157,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, .bRequest = HUB_REQUEST_GET_STATUS, .wValue = 0, .wIndex = hub_port, - .wLength = 4 + .wLength = tu_htole16(4) }; tuh_xfer_t xfer = { @@ -175,10 +174,6 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp, return true; } -bool hub_get_status(uint8_t hub_addr, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { - return hub_port_get_status(hub_addr, 0, resp, complete_cb, user_data); -} - //--------------------------------------------------------------------+ // CLASS-USBH API (don't require to verify parameters) //--------------------------------------------------------------------+ @@ -309,8 +304,9 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { //--------------------------------------------------------------------+ // Connection Changes //--------------------------------------------------------------------+ -static void port_get_status_complete (tuh_xfer_t* xfer); static void get_status_complete (tuh_xfer_t* xfer); +static void port_get_status_complete (tuh_xfer_t* xfer); +static void port_clear_feature_complete_stub(tuh_xfer_t* xfer); static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); static void connection_port_reset_complete (tuh_xfer_t* xfer); @@ -323,8 +319,8 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 if (result == XFER_RESULT_SUCCESS) { hub_interface_t* p_hub = get_hub_itf(dev_addr); - hub_epbuf_t* p_epbuf = get_hub_epbuf(dev_addr); - uint8_t const status_change = p_epbuf->status_change[0]; + hub_epbuf_t *p_epbuf = get_hub_epbuf(dev_addr); + const uint8_t status_change = p_epbuf->status_change[0]; TU_LOG_DRV(" Hub Status Change = 0x%02X\r\n", status_change); if (status_change == 0) { @@ -333,12 +329,12 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 processed = false; } else if (tu_bit_test(status_change, 0)) { // Hub bit 0 is for the hub device events - processed = hub_get_status(dev_addr, &p_hub->hub_status, get_status_complete, 0); + processed = hub_get_status(dev_addr, p_epbuf->ctrl_buf, get_status_complete, 0); } else { // Hub bits 1 to n are hub port events for (uint8_t port=1; port <= p_hub->bNbrPorts; port++) { if (tu_bit_test(status_change, port)) { - processed = hub_port_get_status(dev_addr, port, &p_hub->port_status, port_get_status_complete, 0); + processed = hub_port_get_status(dev_addr, port, p_epbuf->ctrl_buf, port_get_status_complete, 0); break; // after completely processed one port, we will re-queue the status poll and handle next one } } @@ -361,38 +357,32 @@ static void port_clear_feature_complete_stub(tuh_xfer_t* xfer) { hub_edpt_status_xfer(xfer->daddr); } -static void get_status_complete (tuh_xfer_t* xfer) -{ +static void get_status_complete(tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); + const uint8_t daddr = xfer->daddr; + hub_status_response_t hub_status = *((const hub_status_response_t *) (uintptr_t) xfer->buffer); - uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_hub_itf(daddr); - uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); - TU_ASSERT(port_num == 0 , ); + TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, hub_status.change.value); - TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value); - - if (p_hub->hub_status.change.local_power_source) - { - TU_LOG_DRV("HUB Local Power Change, addr = %u\r\n", daddr); - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0); - } - else if (p_hub->hub_status.change.over_current) - { - TU_LOG1("HUB Over Current, addr = %u\r\n", daddr); - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); + if (hub_status.change.local_power_source) { + TU_LOG_DRV(" Local Power Change\r\n"); + hub_clear_feature(daddr, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0); + } else if (hub_status.change.over_current) { + TU_LOG_DRV(" Over Current\r\n"); + hub_clear_feature(daddr, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); } } static void port_get_status_complete(tuh_xfer_t *xfer) { TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - uint8_t const daddr = xfer->daddr; + const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + const uint8_t daddr = xfer->daddr; hub_interface_t *p_hub = get_hub_itf(daddr); - uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + p_hub->port_status = *((const hub_port_status_response_t *) (uintptr_t) xfer->buffer); - // Connection change if (p_hub->port_status.change.connection) { + // Connection change // Port is powered and enabled //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); @@ -408,8 +398,7 @@ static void port_get_status_complete(tuh_xfer_t *xfer) { hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.reset) { hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, port_clear_feature_complete_stub, 0); - } - else { + } else { // Other changes are: L1 state // TODO clear change diff --git a/src/host/hub.h b/src/host/hub.h index 3b19e9838..8e1852601 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -148,21 +148,21 @@ TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); // data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num typedef struct { - union { + union TU_ATTR_PACKED { struct TU_ATTR_PACKED { - uint16_t connection : 1; - uint16_t port_enable : 1; - uint16_t suspend : 1; - uint16_t over_current : 1; - uint16_t reset : 1; + uint16_t connection : 1; // [0] 0 = no device, 1 = device connected + uint16_t port_enable : 1; // [1] port is enabled + uint16_t suspend : 1; // [2] + uint16_t over_current : 1; // [3] over-current exists + uint16_t reset : 1; // [4] 0 = no reset, 1 = resetting - uint16_t : 3; - uint16_t port_power : 1; - uint16_t low_speed : 1; - uint16_t high_speed : 1; - uint16_t port_test_mode : 1; - uint16_t port_indicator_control : 1; - uint16_t TU_RESERVED : 3; + uint16_t rsv5_7 : 3; // [5..7] reserved + uint16_t port_power : 1; // [8] 0 = port is off, 1 = port is on + uint16_t low_speed : 1; // [9] low speed device attached + uint16_t high_speed : 1; // [10] high speed device attached + uint16_t port_test_mode : 1; // [11] port in test mode + uint16_t port_indicator_control : 1; // [12] 0: default color, 1: indicator is software controlled + uint16_t TU_RESERVED : 3; // [13..15] reserved }; uint16_t value; @@ -171,11 +171,15 @@ typedef struct { TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); -// Clear feature +//--------------------------------------------------------------------+ +// HUB API +//--------------------------------------------------------------------+ + +// Clear port feature bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_xfer_cb_t complete_cb, uintptr_t user_data); -// Set feature +// Set port feature bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, tuh_xfer_cb_t complete_cb, uintptr_t user_data); @@ -192,12 +196,23 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_c return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data); } -// Clear Reset Change +// Clear Port Reset Change TU_ATTR_ALWAYS_INLINE static inline bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data); } +// Get Hub status +TU_ATTR_ALWAYS_INLINE static inline +bool hub_get_status(uint8_t hub_addr, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return hub_port_get_status(hub_addr, 0, resp, complete_cb, user_data); +} + +// Clear Hub feature +TU_ATTR_ALWAYS_INLINE static inline +bool hub_clear_feature(uint8_t hub_addr, uint8_t feature, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return hub_port_clear_feature(hub_addr, 0, feature, complete_cb, user_data); +} //--------------------------------------------------------------------+ // Internal Class Driver API //--------------------------------------------------------------------+ From 70ddb7a8672bb523db79baf090469932127989d2 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 19 Feb 2025 15:50:42 +0700 Subject: [PATCH 56/87] more hub improve, handle more failed transfer with polling interrupt status endpoint --- src/host/hub.c | 156 ++++++++++++++++++++++++++---------------------- src/host/hub.h | 94 +++++++++++++---------------- src/host/usbh.c | 1 - 3 files changed, 123 insertions(+), 128 deletions(-) diff --git a/src/host/hub.c b/src/host/hub.c index 41aefc1a7..93b4a3a84 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -46,7 +46,7 @@ typedef struct { // from hub descriptor uint8_t bNbrPorts; - // uint8_t bPwrOn2PwrGood; + uint8_t bPwrOn2PwrGood; // port power on to good, in 2ms unit // uint16_t wHubCharacteristics; hub_port_status_response_t port_status; @@ -114,7 +114,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature, }; TU_LOG_DRV("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port); - TU_ASSERT( tuh_control_xfer(&xfer) ); + TU_ASSERT(tuh_control_xfer(&xfer)); return true; } @@ -220,9 +220,16 @@ void hub_close(uint8_t dev_addr) { } bool hub_edpt_status_xfer(uint8_t daddr) { - hub_interface_t* hub_itf = get_hub_itf(daddr); + hub_interface_t* p_hub = get_hub_itf(daddr); hub_epbuf_t* p_epbuf = get_hub_epbuf(daddr); - return usbh_edpt_xfer(daddr, hub_itf->ep_in, p_epbuf->status_change, 1); + + TU_VERIFY(usbh_edpt_claim(daddr, p_hub->ep_in)); + if (!usbh_edpt_xfer(daddr, p_hub->ep_in, p_epbuf->status_change, 1)) { + usbh_edpt_release(daddr, p_hub->ep_in); + return false; + } + + return true; } //--------------------------------------------------------------------+ @@ -272,6 +279,7 @@ static void config_set_port_power (tuh_xfer_t* xfer) { // only use number of ports in hub descriptor hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) p_epbuf->ctrl_buf; p_hub->bNbrPorts = desc_hub->bNbrPorts; + p_hub->bPwrOn2PwrGood = desc_hub->bPwrOn2PwrGood; // May need to GET_STATUS @@ -293,6 +301,7 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { TU_MESS_FAILED(); TU_BREAKPOINT(); } + // delay bPwrOn2PwrGood * 2 ms before set configuration complete usbh_driver_set_config_complete(daddr, p_hub->itf_num); } else { // power next port @@ -311,15 +320,15 @@ static void connection_clear_conn_change_complete (tuh_xfer_t* xfer); static void connection_port_reset_complete (tuh_xfer_t* xfer); // callback as response of interrupt endpoint polling -bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { +bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) xferred_bytes; (void) ep_addr; bool processed = false; // true if new status is processed if (result == XFER_RESULT_SUCCESS) { - hub_interface_t* p_hub = get_hub_itf(dev_addr); - hub_epbuf_t *p_epbuf = get_hub_epbuf(dev_addr); + hub_interface_t* p_hub = get_hub_itf(daddr); + hub_epbuf_t *p_epbuf = get_hub_epbuf(daddr); const uint8_t status_change = p_epbuf->status_change[0]; TU_LOG_DRV(" Hub Status Change = 0x%02X\r\n", status_change); @@ -329,136 +338,137 @@ bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32 processed = false; } else if (tu_bit_test(status_change, 0)) { // Hub bit 0 is for the hub device events - processed = hub_get_status(dev_addr, p_epbuf->ctrl_buf, get_status_complete, 0); + processed = hub_get_status(daddr, p_epbuf->ctrl_buf, get_status_complete, 0); } else { // Hub bits 1 to n are hub port events for (uint8_t port=1; port <= p_hub->bNbrPorts; port++) { if (tu_bit_test(status_change, port)) { - processed = hub_port_get_status(dev_addr, port, p_epbuf->ctrl_buf, port_get_status_complete, 0); + processed = hub_port_get_status(daddr, port, p_epbuf->ctrl_buf, port_get_status_complete, 0); break; // after completely processed one port, we will re-queue the status poll and handle next one } } } - } else { - processed = false; } // If new status event is processed: next status pool is queued by usbh.c after handled this request // Otherwise re-queue the status poll here if (!processed) { - TU_ASSERT(hub_edpt_status_xfer(dev_addr)); + TU_ASSERT(hub_edpt_status_xfer(daddr)); } return true; } static void port_clear_feature_complete_stub(tuh_xfer_t* xfer) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); hub_edpt_status_xfer(xfer->daddr); } static void get_status_complete(tuh_xfer_t *xfer) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); const uint8_t daddr = xfer->daddr; - hub_status_response_t hub_status = *((const hub_status_response_t *) (uintptr_t) xfer->buffer); - TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, hub_status.change.value); + bool processed = false; // true if new status is processed + if (xfer->result == XFER_RESULT_SUCCESS) { + hub_status_response_t hub_status = *((const hub_status_response_t *) (uintptr_t) xfer->buffer); - if (hub_status.change.local_power_source) { - TU_LOG_DRV(" Local Power Change\r\n"); - hub_clear_feature(daddr, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0); - } else if (hub_status.change.over_current) { - TU_LOG_DRV(" Over Current\r\n"); - hub_clear_feature(daddr, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); + TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, hub_status.change.value); + + if (hub_status.change.local_power_source) { + TU_LOG_DRV(" Local Power Change\r\n"); + processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0); + } else if (hub_status.change.over_current) { + TU_LOG_DRV(" Over Current\r\n"); + processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); + } + } + + if (!processed) { + TU_ASSERT(hub_edpt_status_xfer(daddr), ); } } static void port_get_status_complete(tuh_xfer_t *xfer) { - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); - - const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); const uint8_t daddr = xfer->daddr; - hub_interface_t *p_hub = get_hub_itf(daddr); - p_hub->port_status = *((const hub_port_status_response_t *) (uintptr_t) xfer->buffer); + bool processed = false; // true if new status is processed - if (p_hub->port_status.change.connection) { - // Connection change - // Port is powered and enabled - //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + if (xfer->result == XFER_RESULT_SUCCESS) { + const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + hub_interface_t *p_hub = get_hub_itf(daddr); + p_hub->port_status = *((const hub_port_status_response_t *) (uintptr_t) xfer->buffer); - // Acknowledge Port Connection Change - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); - } else { - // Clear other port status change interrupts. TODO Not currently handled - just cleared. - if (p_hub->port_status.change.port_enable) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, port_clear_feature_complete_stub, 0); + // Clear port status change interrupts + if (p_hub->port_status.change.connection) { + // Connection change + // Port is powered and enabled + //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, ); + + // Acknowledge Port Connection Change + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0); + } else if (p_hub->port_status.change.port_enable) { + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.suspend) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, port_clear_feature_complete_stub, 0); + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.over_current) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0); } else if (p_hub->port_status.change.reset) { - hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, port_clear_feature_complete_stub, 0); - } else { - // Other changes are: L1 state - // TODO clear change - - // prepare for next hub status - // TODO continue with status_change, or maybe we can do it again with status - hub_edpt_status_xfer(daddr); + processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, port_clear_feature_complete_stub, 0); } } + + if (!processed) { + TU_ASSERT(hub_edpt_status_xfer(daddr), ); + } } -static void connection_clear_conn_change_complete (tuh_xfer_t* xfer) -{ - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); +static void connection_clear_conn_change_complete (tuh_xfer_t* xfer) { + const uint8_t daddr = xfer->daddr; - uint8_t const daddr = xfer->daddr; - hub_interface_t* p_hub = get_hub_itf(daddr); - uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + if (xfer->result != XFER_RESULT_SUCCESS) { + TU_ASSERT(hub_edpt_status_xfer(daddr), ); + return; + } - if ( p_hub->port_status.status.connection ) - { + hub_interface_t *p_hub = get_hub_itf(daddr); + const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + + if (p_hub->port_status.status.connection) { // Reset port if attach event hub_port_reset(daddr, port_num, connection_port_reset_complete, 0); - }else - { + } else { // submit detach event - hcd_event_t event = - { + const hcd_event_t event = { .rhport = usbh_get_rhport(daddr), .event_id = HCD_EVENT_DEVICE_REMOVE, - .connection = - { + .connection = { .hub_addr = daddr, .hub_port = port_num } }; - hcd_event_handler(&event, false); } } -static void connection_port_reset_complete (tuh_xfer_t* xfer) -{ - TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, ); +static void connection_port_reset_complete (tuh_xfer_t* xfer) { + const uint8_t daddr = xfer->daddr; - uint8_t const daddr = xfer->daddr; - // hub_interface_t* p_hub = get_itf(daddr); - uint8_t const port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); + if (xfer->result != XFER_RESULT_SUCCESS) { + // retry port reset if failed + if (!tuh_control_xfer(xfer)) { + TU_ASSERT(hub_edpt_status_xfer(daddr), ); // back to status poll if failed to queue request + } + return; + } + + const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex); // submit attach event - hcd_event_t event = - { + hcd_event_t event = { .rhport = usbh_get_rhport(daddr), .event_id = HCD_EVENT_DEVICE_ATTACH, - .connection = - { + .connection = { .hub_addr = daddr, .hub_port = port_num } }; - hcd_event_handler(&event, false); } diff --git a/src/host/hub.h b/src/host/hub.h index 8e1852601..e4e576661 100644 --- a/src/host/hub.h +++ b/src/host/hub.h @@ -41,58 +41,9 @@ #define CFG_TUH_HUB_BUFSIZE 12 #endif -//D1...D0: Logical Power Switching Mode -//00: Ganged power switching (all ports’power at -//once) -//01: Individual port power switching -//1X: Reserved. Used only on 1.0 compliant hubs -//that implement no power switching -//D2: Identifies a Compound Device -//0: Hub is not part of a compound device. -//1: Hub is part of a compound device. -//D4...D3: Over-current Protection Mode -//00: Global Over-current Protection. The hub -//reports over-current as a summation of all -//ports’current draw, without a breakdown of -//individual port over-current status. -//01: Individual Port Over-current Protection. The -//hub reports over-current on a per-port basis. -//Each port has an over-current status. -//1X: No Over-current Protection. This option is -//allowed only for bus-powered hubs that do not -//implement over-current protection. +//--------------------------------------------------------------------+ // -//D6...D5: TT Think TIme -//00: TT requires at most 8 FS bit times of inter -//transaction gap on a full-/low-speed -//downstream bus. -//01: TT requires at most 16 FS bit times. -//10: TT requires at most 24 FS bit times. -//11: TT requires at most 32 FS bit times. -//D7: Port Indicators Supported -//0: Port Indicators are not supported on its -//downstream facing ports and the -//PORT_INDICATOR request has no effect. -//1: Port Indicators are supported on its -//downstream facing ports and the -//PORT_INDICATOR request controls the -//indicators. See Section 11.5.3. -//D15...D8: Reserved - -typedef struct TU_ATTR_PACKED{ - uint8_t bLength ; ///< Size of descriptor - uint8_t bDescriptorType ; ///< Other_speed_Configuration Type - uint8_t bNbrPorts; - uint16_t wHubCharacteristics; - uint8_t bPwrOn2PwrGood; - uint8_t bHubContrCurrent; - uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) - uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff -} hub_desc_cs_t; - -TU_VERIFY_STATIC(sizeof(hub_desc_cs_t) == 9, "size is not correct"); -TU_VERIFY_STATIC(CFG_TUH_HUB_BUFSIZE >= sizeof(hub_desc_cs_t), "buffer is not big enough"); - +//--------------------------------------------------------------------+ enum { HUB_REQUEST_GET_STATUS = 0 , HUB_REQUEST_CLEAR_FEATURE = 1 , @@ -131,6 +82,41 @@ enum{ HUB_FEATURE_PORT_INDICATOR = 22 }; +enum { + HUB_CHARS_POWER_GANGED_SWITCHING = 0, + HUB_CHARS_POWER_INDIVIDUAL_SWITCHING = 1, +}; + +enum { + HUB_CHARS_OVER_CURRENT_GLOBAL = 0, + HUB_CHARS_OVER_CURRENT_INDIVIDUAL = 1, +}; + +typedef struct TU_ATTR_PACKED{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint8_t bNbrPorts; + uint16_t wHubCharacteristics; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1) + uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff +} hub_desc_cs_t; +TU_VERIFY_STATIC(sizeof(hub_desc_cs_t) == 9, "size is not correct"); +TU_VERIFY_STATIC(CFG_TUH_HUB_BUFSIZE >= sizeof(hub_desc_cs_t), "buffer is not big enough"); + +typedef struct TU_ATTR_PACKED { + struct TU_ATTR_PACKED { + uint8_t logical_power_switching_mode : 2; // [0..1] gannged or individual power switching + uint8_t compound_device : 1; // [2] hub is part of compound device + uint8_t over_current_protect_mode : 2; // [3..4] global or individual port over-current protection + uint8_t tt_think_time : 2; // [5..6] TT think time + uint8_t port_indicator_supported : 1; // [7] port indicator supported + }; + uint8_t rsv1; +} hub_characteristics_t; +TU_VERIFY_STATIC(sizeof(hub_characteristics_t) == 2, "size is not correct"); + // data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub) typedef struct { union{ @@ -143,19 +129,20 @@ typedef struct { uint16_t value; } status, change; } hub_status_response_t; - TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct"); // data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num typedef struct { union TU_ATTR_PACKED { struct TU_ATTR_PACKED { + // Bit 0-4 are for change & status uint16_t connection : 1; // [0] 0 = no device, 1 = device connected uint16_t port_enable : 1; // [1] port is enabled uint16_t suspend : 1; // [2] uint16_t over_current : 1; // [3] over-current exists uint16_t reset : 1; // [4] 0 = no reset, 1 = resetting + // From Bit 5 are for status only uint16_t rsv5_7 : 3; // [5..7] reserved uint16_t port_power : 1; // [8] 0 = port is off, 1 = port is on uint16_t low_speed : 1; // [9] low speed device attached @@ -168,7 +155,6 @@ typedef struct { uint16_t value; } status, change; } hub_port_status_response_t; - TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct"); //--------------------------------------------------------------------+ @@ -220,7 +206,7 @@ bool hub_init (void); bool hub_deinit (void); bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len); bool hub_set_config (uint8_t dev_addr, uint8_t itf_num); -bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); +bool hub_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); void hub_close (uint8_t dev_addr); #ifdef __cplusplus diff --git a/src/host/usbh.c b/src/host/usbh.c index ac920f533..c7a9a868f 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -920,7 +920,6 @@ bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr) { } // Submit an transfer -// TODO call usbh_edpt_release if failed bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes, tuh_xfer_cb_t complete_cb, uintptr_t user_data) { (void) complete_cb; From 6572c1da0d6ad2f298ef97189ca4b288f710f49a Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Feb 2025 15:47:29 +0700 Subject: [PATCH 57/87] add fruitjam bsp --- hw/bsp/family_support.cmake | 4 + .../adafruit_feather_rp2040_usb_host/board.h | 64 ++++++++++ .../adafruit_fruit_jam/adafruit_fruit_jam.h | 113 ++++++++++++++++++ .../boards/adafruit_fruit_jam/board.cmake | 4 + .../rp2040/boards/adafruit_fruit_jam/board.h | 52 ++++++++ .../boards/feather_rp2040_max3421/board.h | 64 ++++++++++ .../{ => boards/raspberry_pi_pico}/board.h | 45 +------ .../boards/raspberry_pi_pico2/board.cmake | 1 + .../rp2040/boards/raspberry_pi_pico2/board.h | 69 +++++++++++ hw/bsp/rp2040/family.c | 38 ++++-- hw/bsp/rp2040/family.cmake | 5 +- hw/bsp/rp2040/rp2350-openocd.cfg | 3 + 12 files changed, 415 insertions(+), 47 deletions(-) create mode 100644 hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h create mode 100644 hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h create mode 100644 hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake create mode 100644 hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h create mode 100644 hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h rename hw/bsp/rp2040/{ => boards/raspberry_pi_pico}/board.h (65%) create mode 100644 hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h create mode 100644 hw/bsp/rp2040/rp2350-openocd.cfg diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 409fb9c75..562d4995b 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -476,6 +476,10 @@ function(family_flash_openocd TARGET) set(OPENOCD_OPTION2 "") endif () + if (DEFINED OPENOCD_SERIAL) + set(OPENOCD_OPTION "-c \"adapter serial ${OPENOCD_SERIAL}\" ${OPENOCD_OPTION}") + endif () + separate_arguments(OPTION_LIST UNIX_COMMAND ${OPENOCD_OPTION}) separate_arguments(OPTION_LIST2 UNIX_COMMAND ${OPENOCD_OPTION2}) diff --git a/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h new file mode 100644 index 000000000..f36ca14c9 --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +//--------------------------------------------------------------------+ +// PIO_USB +//--------------------------------------------------------------------+ + +#define PICO_DEFAULT_PIO_USB_DP_PIN 16 +#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 18 +#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 + +//-------------------------------------------------------------------- +// USB Host MAX3421E +//-------------------------------------------------------------------- + +#ifdef PICO_DEFAULT_SPI +#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2 +#else +#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1 +#endif + +#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN +#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN +#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN +#define MAX3421_CS_PIN 10 +#define MAX3421_INTR_PIN 9 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h b/hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h new file mode 100644 index 000000000..2d4c689de --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ +#ifndef BOARDS_ADAFRUIT_FRUIT_JAM_H +#define BOARDS_ADAFRUIT_FRUIT_JAM_H + +// required for board that is not part of pico-sdk + +// ----------------------------------------------------- +// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO +// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES +// ----------------------------------------------------- + +// pico_cmake_set PICO_PLATFORM=rp2350 + +// On some samples, the xosc can take longer to stabilize than is usual +#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 +#endif + +// For board detection +#define ADAFRUIT_FRUIT_JAM + +// --- RP2350 VARIANT --- +#define PICO_RP2350A 0 + +// --- UART --- +#ifndef PICO_DEFAULT_UART +#define PICO_DEFAULT_UART 1 +#endif +#ifndef PICO_DEFAULT_UART_TX_PIN +#define PICO_DEFAULT_UART_TX_PIN 8 +#endif +#ifndef PICO_DEFAULT_UART_RX_PIN +#define PICO_DEFAULT_UART_RX_PIN 9 +#endif + +// --- LED --- +#ifndef PICO_DEFAULT_LED_PIN +#define PICO_DEFAULT_LED_PIN 29 +#endif + +#ifndef PICO_DEFAULT_WS2812_PIN +#define PICO_DEFAULT_WS2812_PIN 32 +#endif + +// --- I2C --- +#ifndef PICO_DEFAULT_I2C +#define PICO_DEFAULT_I2C 0 +#endif +#ifndef PICO_DEFAULT_I2C_SDA_PIN +#define PICO_DEFAULT_I2C_SDA_PIN 20 +#endif +#ifndef PICO_DEFAULT_I2C_SCL_PIN +#define PICO_DEFAULT_I2C_SCL_PIN 21 +#endif + +// --- SPI --- +#ifndef PICO_DEFAULT_SPI +#define PICO_DEFAULT_SPI 1 +#endif +#ifndef PICO_DEFAULT_SPI_SCK_PIN +#define PICO_DEFAULT_SPI_SCK_PIN 30 +#endif +#ifndef PICO_DEFAULT_SPI_TX_PIN +#define PICO_DEFAULT_SPI_TX_PIN 31 +#endif +#ifndef PICO_DEFAULT_SPI_RX_PIN +#define PICO_DEFAULT_SPI_RX_PIN 28 +#endif + +// --- FLASH --- + +// FruitJam use w25q128 but sdk does not have .s for it, use q080 instead +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 2 +#endif + +// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024) +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024) +#endif + +// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1 +#ifndef PICO_RP2350_A2_SUPPORTED +#define PICO_RP2350_A2_SUPPORTED 1 +#endif + +#endif diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake new file mode 100644 index 000000000..4ab8a5477 --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake @@ -0,0 +1,4 @@ +set(PICO_PLATFORM rp2350-arm-s) +set(PICO_BOARD adafruit_fruit_jam) +set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}) +#set(OPENOCD_SERIAL E6614103E78E8324) diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h new file mode 100644 index 000000000..f81da3b70 --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h @@ -0,0 +1,52 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +//--------------------------------------------------------------------+ +// PIO_USB +//--------------------------------------------------------------------+ +// default to pico brain tester +#define PICO_DEFAULT_PIO_USB_DP_PIN 1 +#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 11 +#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 + +//-------------------------------------------------------------------- +// USB Host MAX3421E +//-------------------------------------------------------------------- + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h b/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h new file mode 100644 index 000000000..f36ca14c9 --- /dev/null +++ b/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h @@ -0,0 +1,64 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +//--------------------------------------------------------------------+ +// PIO_USB +//--------------------------------------------------------------------+ + +#define PICO_DEFAULT_PIO_USB_DP_PIN 16 +#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 18 +#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 + +//-------------------------------------------------------------------- +// USB Host MAX3421E +//-------------------------------------------------------------------- + +#ifdef PICO_DEFAULT_SPI +#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2 +#else +#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1 +#endif + +#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN +#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN +#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN +#define MAX3421_CS_PIN 10 +#define MAX3421_INTR_PIN 9 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/rp2040/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h similarity index 65% rename from hw/bsp/rp2040/board.h rename to hw/bsp/rp2040/boards/raspberry_pi_pico/board.h index 5dbb1dd37..12c772b84 100644 --- a/hw/bsp/rp2040/board.h +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h @@ -1,7 +1,7 @@ /* * The MIT License (MIT) * - * Copyright (c) 2021, Ha Thach (tinyusb.org) + * Copyright (c) 2025 Ha Thach (tinyusb.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -29,55 +29,22 @@ url: https://www.raspberrypi.org/products/raspberry-pi-pico/ */ -#ifndef BOARD_H_ -#define BOARD_H_ +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H #ifdef __cplusplus extern "C" { #endif -// LED -#ifdef PICO_DEFAULT_LED_PIN -#define LED_PIN PICO_DEFAULT_LED_PIN -#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED)) -#endif - -// Button pin is BOOTSEL which is flash CS pin -#define BUTTON_BOOTSEL -#define BUTTON_STATE_ACTIVE 0 - -// UART -#if defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN) && \ - defined(PICO_DEFAULT_UART) && defined(LIB_PICO_STDIO_UART) -#define UART_DEV PICO_DEFAULT_UART -#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN -#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN -#endif +// UART and LED are already defined in pico-sdk board //--------------------------------------------------------------------+ // PIO_USB -// default to pin on Adafruit Feather rp2040 USB Host or Tester if defined //--------------------------------------------------------------------+ - -// #define USE_ADAFRUIT_FEATHER_RP2040_USBHOST -#ifdef USE_ADAFRUIT_FEATHER_RP2040_USBHOST -#define PICO_DEFAULT_PIO_USB_DP_PIN 16 -#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 18 -#endif - -#ifndef PICO_DEFAULT_PIO_USB_DP_PIN +// default to pico brain tester #define PICO_DEFAULT_PIO_USB_DP_PIN 20 -#endif - -// VBUS enable pin and its active state -#ifndef PICO_DEFAULT_PIO_USB_VBUSEN_PIN #define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 22 -#endif - -// VBUS enable state -#ifndef PICO_DEFAULT_PIO_USB_VBUSEN_STATE #define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 -#endif //-------------------------------------------------------------------- // USB Host MAX3421E @@ -99,4 +66,4 @@ } #endif -#endif /* BOARD_H_ */ +#endif diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake index 3482e2674..0a7dd4d23 100644 --- a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake @@ -1,2 +1,3 @@ set(PICO_PLATFORM rp2350-arm-s) set(PICO_BOARD pico2) +#set(OPENOCD_SERIAL E6614103E77C5A24) diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h new file mode 100644 index 000000000..139b58ceb --- /dev/null +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h @@ -0,0 +1,69 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: Pico2 + url: https://www.raspberrypi.org/products/raspberry-pi-pico/ +*/ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +//--------------------------------------------------------------------+ +// PIO_USB +//--------------------------------------------------------------------+ +// default to pico brain tester +#define PICO_DEFAULT_PIO_USB_DP_PIN 20 +#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 22 +#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 + +//-------------------------------------------------------------------- +// USB Host MAX3421E +//-------------------------------------------------------------------- + +#ifdef PICO_DEFAULT_SPI +#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2 +#else +#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1 +#endif + +#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN +#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN +#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN +#define MAX3421_CS_PIN 10 +#define MAX3421_INTR_PIN 9 + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 24aa0b616..0c97d6ed0 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -42,10 +42,6 @@ #include "bsp/board_api.h" #include "board.h" -#ifdef UART_DEV -static uart_inst_t *uart_inst; -#endif - #if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB) #include "pio_usb.h" #endif @@ -55,6 +51,36 @@ static uart_inst_t *uart_inst; static void max3421_init(void); #endif +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ +// LED +#if !defined(LED_PIN) && defined(PICO_DEFAULT_LED_PIN) +#define LED_PIN PICO_DEFAULT_LED_PIN +#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED)) +#endif + +// Button, if not defined use BOOTSEL button +#ifndef BUTTON_PIN +#define BUTTON_BOOTSEL +#define BUTTON_STATE_ACTIVE 0 +#endif + +// UART +#if !defined(UART_DEV) && defined(PICO_DEFAULT_UART) && defined(LIB_PICO_STDIO_UART) && \ + defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN) +#define UART_DEV PICO_DEFAULT_UART +#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN +#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN +#endif + +#ifdef UART_DEV +static uart_inst_t *uart_inst; +#endif + +//--------------------------------------------------------------------+ +// +//--------------------------------------------------------------------+ #ifdef BUTTON_BOOTSEL // This example blinks the Picoboard LED when the BOOTSEL button is pressed. // @@ -79,7 +105,7 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)(void) { IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS); // Note we can't call into any sleep functions in flash right now - for (volatile int i = 0; i < 1000; ++i); + for (volatile int i = 0; i < 1000; ++i) {} // The HI GPIO registers in SIO can observe and control the 6 QSPI pins. // Note the button pulls the pin *low* when pressed. @@ -133,7 +159,6 @@ void stdio_rtt_init(void) { //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ - void board_init(void) { #if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB) @@ -193,7 +218,6 @@ void board_init(void) //--------------------------------------------------------------------+ // Board porting API //--------------------------------------------------------------------+ - void board_led_write(bool state) { (void) state; diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake index b2b01b1cf..384b06933 100644 --- a/hw/bsp/rp2040/family.cmake +++ b/hw/bsp/rp2040/family.cmake @@ -31,7 +31,9 @@ elseif (PICO_PLATFORM STREQUAL "rp2350-riscv") set(OPENOCD_TARGET rp2350-riscv) endif() -set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/${OPENOCD_TARGET}.cfg -c \"adapter speed 5000\"") +if (NOT OPENOCD_OPTION) + set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/${OPENOCD_TARGET}.cfg -c \"adapter speed 5000\"") +endif() if (NOT PICO_TINYUSB_PATH) set(PICO_TINYUSB_PATH ${TOP}) @@ -143,6 +145,7 @@ target_sources(tinyusb_bsp INTERFACE ) target_include_directories(tinyusb_bsp INTERFACE ${TOP}/hw + ${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD} ) target_link_libraries(tinyusb_bsp INTERFACE pico_unique_id diff --git a/hw/bsp/rp2040/rp2350-openocd.cfg b/hw/bsp/rp2040/rp2350-openocd.cfg new file mode 100644 index 000000000..52c71cd99 --- /dev/null +++ b/hw/bsp/rp2040/rp2350-openocd.cfg @@ -0,0 +1,3 @@ +source [find interface/cmsis-dap.cfg] +adapter speed 5000 +source [find target/rp2350.cfg] From cafc788508834b71248a91773a262542fc2cad37 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Feb 2025 16:01:06 +0700 Subject: [PATCH 58/87] change pio-usb to wip fork for testing --- .../boards/adafruit_feather_rp2040_usb_host/board.cmake | 2 ++ tools/get_deps.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake diff --git a/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake new file mode 100644 index 000000000..41897f644 --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake @@ -0,0 +1,2 @@ +set(PICO_PLATFORM rp2040) +set(PICO_BOARD adafruit_feather_rp2040_usb_host) diff --git a/tools/get_deps.py b/tools/get_deps.py index 3665904b3..b82abac4f 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -58,8 +58,8 @@ deps_optional = { 'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git', '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], - 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', - '442af432568f25fb72c5784d9d67b8e85465cb28', + 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', + '9c8df3083b62c0a678f3bd3d8a7e773932622d4b', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', From 61aab7a86aaaf5c254ba5d14a04ff44aec8623d3 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 20 Feb 2025 22:16:05 +0700 Subject: [PATCH 59/87] pio-usb now only need sysclk to be multiple of 12Mhz --- hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake | 1 + hw/bsp/rp2040/family.c | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake index 804cdb50a..2d739291c 100644 --- a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake @@ -1,2 +1,3 @@ set(PICO_PLATFORM rp2040) set(PICO_BOARD pico) +#set(OPENOCD_SERIAL E6614103E719612F) diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 0c97d6ed0..a6e176308 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -162,8 +162,12 @@ void stdio_rtt_init(void) { void board_init(void) { #if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB) - // Set the system clock to a multiple of 120mhz for bitbanging USB with pico-usb + // Set the system clock to a multiple of 12mhz for bit-banging USB with pico-usb set_sys_clock_khz(120000, true); + // set_sys_clock_khz(180000, true); + // set_sys_clock_khz(192000, true); + // set_sys_clock_khz(240000, true); + // set_sys_clock_khz(264000, true); #ifdef PICO_DEFAULT_PIO_USB_VBUSEN_PIN gpio_init(PICO_DEFAULT_PIO_USB_VBUSEN_PIN); From b12c8a90125b99b71ab3409c10424d3f8ad0736b Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 21 Feb 2025 17:31:13 +0700 Subject: [PATCH 60/87] remove CFG_MIDI_HOST_DEVSTRINGS support, we will leave that for application to parse/extract this information if needed rename tuh_midi_configure() to mounted() for consistency --- examples/host/midi_rx/src/main.c | 2 +- src/class/midi/midi.h | 127 +++++++-------- src/class/midi/midi_host.c | 256 ++++++------------------------- src/class/midi/midi_host.h | 18 +-- 4 files changed, 117 insertions(+), 286 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index fed782947..57e9df29e 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -89,7 +89,7 @@ void led_blinking_task(void) { //--------------------------------------------------------------------+ void midi_host_rx_task(void) { // device must be attached and have at least one endpoint ready to receive a message - if (!midi_dev_addr || !tuh_midi_configured(midi_dev_addr)) { + if (!midi_dev_addr || !tuh_midi_mounted(midi_dev_addr)) { return; } if (tuh_midi_get_num_rx_cables(midi_dev_addr) < 1) { diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index 9591f13c4..a7da98831 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -36,28 +36,29 @@ //--------------------------------------------------------------------+ // Constants //--------------------------------------------------------------------+ +enum { + MIDI_VERSION_1_0 = 0x0100, + MIDI_VERSION_2_0 = 0x0200, +}; -typedef enum -{ +typedef enum { MIDI_CS_INTERFACE_HEADER = 0x01, MIDI_CS_INTERFACE_IN_JACK = 0x02, MIDI_CS_INTERFACE_OUT_JACK = 0x03, MIDI_CS_INTERFACE_ELEMENT = 0x04, } midi_cs_interface_subtype_t; -typedef enum -{ - MIDI_CS_ENDPOINT_GENERAL = 0x01 +typedef enum { + MIDI_CS_ENDPOINT_GENERAL = 0x01, + MIDI_CS_ENDPOINT_GENERAL_2_0 = 0x02, } midi_cs_endpoint_subtype_t; -typedef enum -{ +typedef enum { MIDI_JACK_EMBEDDED = 0x01, MIDI_JACK_EXTERNAL = 0x02 } midi_jack_type_t; -typedef enum -{ +typedef enum { MIDI_CIN_MISC = 0, MIDI_CIN_CABLE_EVENT = 1, MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect @@ -77,8 +78,7 @@ typedef enum } midi_code_index_number_t; // MIDI 1.0 status byte -enum -{ +enum { //------------- System Exclusive -------------// MIDI_STATUS_SYSEX_START = 0xF0, MIDI_STATUS_SYSEX_END = 0xF7, @@ -101,8 +101,7 @@ enum MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF, }; -enum -{ +enum { MIDI_MAX_DATA_VAL = 0x7F, }; @@ -111,62 +110,48 @@ enum //--------------------------------------------------------------------+ /// MIDI Interface Header Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal - uint16_t wTotalLength ; +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType; ///< must be TUSB_DESC_CS_INTERFACE + uint8_t bDescriptorSubType;///< Descriptor SubType + uint16_t bcdMSC; ///< MidiStreaming SubClass release number in Binary-Coded Decimal + uint16_t wTotalLength; } midi_desc_header_t; +TU_VERIFY_STATIC(sizeof(midi_desc_header_t) == 7, "size is not correct"); /// MIDI In Jack Descriptor -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t iJack ; ///< string descriptor +typedef struct TU_ATTR_PACKED { + uint8_t bLength; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType;///< Descriptor SubType + uint8_t bJackType; ///< Embedded or External + uint8_t bJackID; ///< Unique ID for MIDI IN Jack + uint8_t iJack; ///< string descriptor } midi_desc_in_jack_t; +TU_VERIFY_STATIC(sizeof(midi_desc_in_jack_t) == 6, "size is not correct"); - -/// MIDI Out Jack Descriptor with single pin -typedef struct TU_ATTR_PACKED -{ - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bJackType ; ///< Embedded or External - uint8_t bJackID ; ///< Unique ID for MIDI IN Jack - uint8_t bNrInputPins; - - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t iJack ; ///< string descriptor -} midi_desc_out_jack_t ; - -/// MIDI Out Jack Descriptor with multiple pins +/// MIDI Out Jack Descriptor with multiple input pins #define midi_desc_out_jack_n_t(input_num) \ - struct TU_ATTR_PACKED { \ - uint8_t bLength ; \ - uint8_t bDescriptorType ; \ - uint8_t bDescriptorSubType ; \ - uint8_t bJackType ; \ - uint8_t bJackID ; \ - uint8_t bNrInputPins ; \ - struct TU_ATTR_PACKED { \ - uint8_t baSourceID; \ - uint8_t baSourcePin; \ - } pins[input_num]; \ - uint8_t iJack ; \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bJackType; \ + uint8_t bJackID; \ + uint8_t bNrInputPins; \ + struct TU_ATTR_PACKED { \ + uint8_t baSourceID; \ + uint8_t baSourcePin; \ + } input[input_num]; \ + uint8_t iJack; \ } +typedef midi_desc_out_jack_n_t(1) midi_desc_out_jack_1in_t; // 1 input +typedef midi_desc_out_jack_1in_t midi_desc_out_jack_t; // backward compatible +TU_VERIFY_STATIC(sizeof(midi_desc_out_jack_1in_t) == 7 + 2 * 1, "size is not correct"); + /// MIDI Element Descriptor -typedef struct TU_ATTR_PACKED -{ +typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes. uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific uint8_t bDescriptorSubType ; ///< Descriptor SubType @@ -184,6 +169,7 @@ typedef struct TU_ATTR_PACKED uint16_t bmElementCaps; uint8_t iElement; } midi_desc_element_t; +TU_VERIFY_STATIC(sizeof(midi_desc_element_t) == 14, "size is not correct"); /// MIDI Element Descriptor with multiple pins #define midi_desc_element_n_t(input_num) \ @@ -206,14 +192,19 @@ typedef struct TU_ATTR_PACKED } // This descriptor follows the standard bulk data endpoint descriptor -typedef struct -{ - uint8_t bLength ; ///< Size of this descriptor in bytes (4+bNumEmbMIDIJack) - uint8_t bDescriptorType ; ///< Descriptor Type, must be CS_ENDPOINT - uint8_t bDescriptorSubType ; ///< Descriptor SubType, must be MS_GENERAL - uint8_t bNumEmbMIDIJack; ; ///< Number of embedded MIDI jacks associated with this endpoint - uint8_t baAssocJackID[]; ; ///< A list of associated jacks -} midi_cs_desc_endpoint_t; +#define midi_desc_cs_endpoint_n_t(jack_num) \ + struct TU_ATTR_PACKED { \ + uint8_t bLength; \ + uint8_t bDescriptorType; \ + uint8_t bDescriptorSubType; \ + uint8_t bNumEmbMIDIJack; \ + uint8_t baAssocJackID[jack_num]; \ + } + +typedef midi_desc_cs_endpoint_n_t() midi_desc_cs_endpoint_t; // empty/flexible jack list +typedef midi_desc_cs_endpoint_n_t(1) midi_desc_cs_endpoint_1jack_t; + +TU_VERIFY_STATIC(sizeof(midi_desc_cs_endpoint_1jack_t) == 4+1, "size is not correct"); //--------------------------------------------------------------------+ // For Internal Driver Use diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 55146accb..810c413e3 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -33,6 +33,13 @@ #include "midi_host.h" +// Level where CFG_TUSB_DEBUG must be at least for this driver is logged +#ifndef CFG_TUH_MIDI_LOG_LEVEL + #define CFG_TUH_MIDI_LOG_LEVEL CFG_TUH_LOG_LEVEL +#endif + +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_LOG_LEVEL, __VA_ARGS__) + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -65,30 +72,6 @@ typedef struct { } ep_stream; bool configured; - -#if CFG_MIDI_HOST_DEVSTRINGS -#define MAX_STRING_INDICES 32 - uint8_t all_string_indices[MAX_STRING_INDICES]; - uint8_t num_string_indices; -#define MAX_IN_JACKS 8 -#define MAX_OUT_JACKS 8 - struct { - uint8_t jack_id; - uint8_t jack_type; - uint8_t string_index; - } in_jack_info[MAX_IN_JACKS]; - uint8_t next_in_jack; - struct { - uint8_t jack_id; - uint8_t jack_type; - uint8_t num_source_ids; - uint8_t source_ids[MAX_IN_JACKS/4]; - uint8_t string_index; - } out_jack_info[MAX_OUT_JACKS]; - uint8_t next_out_jack; - uint8_t ep_in_associated_jacks[MAX_OUT_JACKS/2]; - uint8_t ep_out_associated_jacks[MAX_IN_JACKS/2]; -#endif }midih_interface_t; typedef struct { @@ -209,19 +192,14 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) rhport; - midih_interface_t *p_midi_host = find_new_midi(); - TU_VERIFY(p_midi_host != NULL); + midih_interface_t *p_midi = find_new_midi(); + TU_VERIFY(p_midi != NULL); - p_midi_host->num_string_indices = 0; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); // There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface uint8_t const *p_desc = (uint8_t const *) desc_itf; uint16_t len_parsed = 0; if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { - // Keep track of any string descriptor that might be here - if (desc_itf->iInterface != 0) { - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; - } // This driver does not support audio streaming. However, if this is the audio control interface // there might be a MIDI interface following it. Search through every descriptor until a MIDI // interface is found or the end of the descriptor is found @@ -237,26 +215,18 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); len_parsed += desc_itf->bLength; - // Keep track of any string descriptor that might be here - if (desc_itf->iInterface != 0) { - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; - } + TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); + p_midi->itf_num = desc_itf->bInterfaceNumber; + // CS Header descriptor p_desc = tu_desc_next(p_desc); - TU_LOG1("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - // Find out if getting the MIDI class specific interface header or an endpoint descriptor - // or a class-specific endpoint descriptor - // Jack descriptors or element descriptors must follow the cs interface header, - // but this driver does not support devices that contain element descriptors - - // assume it is an interface header - midi_desc_header_t const *p_mdh = (midi_desc_header_t const *)p_desc; - TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || - p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); + midi_desc_header_t const *p_mdh = (midi_desc_header_t const *) p_desc; + TU_VERIFY(p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && + p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER); + TU_LOG_DRV(" Interface Header descriptor\r\n"); + // p_desc = tu_desc_next(p_desc); uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descriptor - p_midi_host->itf_num = desc_itf->bInterfaceNumber; tusb_desc_endpoint_t const* in_desc = NULL; tusb_desc_endpoint_t const* out_desc = NULL; while (len_parsed < max_len) { @@ -271,110 +241,53 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d // assume it is an input jack midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *) p_desc; if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) { - TU_LOG2("Found MIDI Interface Header\r\b"); + TU_LOG_DRV(" Interface Header descriptor\r\n"); } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) { // Then it is an in jack. - TU_LOG2("Found in jack\r\n"); - #if CFG_MIDI_HOST_DEVSTRINGS - if (p_midi_host->next_in_jack < MAX_IN_JACKS) { - p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_id = p_mdij->bJackID; - p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_type = p_mdij->bJackType; - p_midi_host->in_jack_info[p_midi_host->next_in_jack].string_index = p_mdij->iJack; - ++p_midi_host->next_in_jack; - // Keep track of any string descriptor that might be here - if (p_mdij->iJack != 0) { - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdij->iJack; - } - } - #endif + TU_LOG_DRV(" IN Jack %s descriptor \r\n", p_mdij->bJackType == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) { // then it is an out jack - TU_LOG2("Found out jack\r\n"); - #if CFG_MIDI_HOST_DEVSTRINGS - if (p_midi_host->next_out_jack < MAX_OUT_JACKS) { - midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *) p_desc; - p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_id = p_mdoj->bJackID; - p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_type = p_mdoj->bJackType; - p_midi_host->out_jack_info[p_midi_host->next_out_jack].num_source_ids = p_mdoj->bNrInputPins; - const struct associated_jack_s { - uint8_t id; - uint8_t pin; - } *associated_jack = (const struct associated_jack_s *) (p_desc + 6); - int jack; - for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) { - p_midi_host->out_jack_info[p_midi_host->next_out_jack].source_ids[jack] = associated_jack->id; - } - p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc + 6 + p_mdoj->bNrInputPins * 2); - ++p_midi_host->next_out_jack; - if (p_mdoj->iJack != 0) { - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdoj->iJack; - } - } - #endif + TU_LOG_DRV(" OUT Jack %s descriptor\r\n", p_mdij->bJackType == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) { // the it is an element; - #if CFG_MIDI_HOST_DEVSTRINGS - TU_LOG1("Found element; strings not supported\r\n"); - #else - TU_LOG2("Found element\r\n"); - #endif + TU_LOG_DRV("Found element\r\n"); } else { - TU_LOG2("Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); + TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); TU_VERIFY(false);// unknown CS Interface sub-type } len_parsed += p_mdij->bLength; } else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) { - TU_LOG2("found CS_ENDPOINT Descriptor for %u\r\n", prev_ep_addr); + TU_LOG_DRV(" CS_ENDPOINT descriptor\r\n"); TU_VERIFY(prev_ep_addr != 0); // parse out the mapping between the device's embedded jacks and the endpoints // Each embedded IN jack is associated with an OUT endpoint - midi_cs_desc_endpoint_t const *p_csep = (midi_cs_desc_endpoint_t const *) p_mdh; + midi_desc_cs_endpoint_t const *p_csep = (midi_desc_cs_endpoint_t const *) p_mdh; if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) { - TU_VERIFY(p_midi_host->ep_out == prev_ep_addr); - TU_VERIFY(p_midi_host->num_cables_tx == 0); - p_midi_host->num_cables_tx = p_csep->bNumEmbMIDIJack; - #if CFG_MIDI_HOST_DEVSTRINGS - uint8_t jack; - uint8_t max_jack = p_midi_host->num_cables_tx; - if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) { - max_jack = sizeof(p_midi_host->ep_out_associated_jacks); - } - for (jack = 0; jack < max_jack; jack++) { - p_midi_host->ep_out_associated_jacks[jack] = p_csep->baAssocJackID[jack]; - } - #endif + TU_VERIFY(p_midi->ep_out == prev_ep_addr); + TU_VERIFY(p_midi->num_cables_tx == 0); + p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack; } else { - TU_VERIFY(p_midi_host->ep_in == prev_ep_addr); - TU_VERIFY(p_midi_host->num_cables_rx == 0); - p_midi_host->num_cables_rx = p_csep->bNumEmbMIDIJack; - #if CFG_MIDI_HOST_DEVSTRINGS - uint8_t jack; - uint8_t max_jack = p_midi_host->num_cables_rx; - if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) { - max_jack = sizeof(p_midi_host->ep_in_associated_jacks); - } - for (jack = 0; jack < max_jack; jack++) { - p_midi_host->ep_in_associated_jacks[jack] = p_csep->baAssocJackID[jack]; - } - #endif + TU_VERIFY(p_midi->ep_in == prev_ep_addr); + TU_VERIFY(p_midi->num_cables_rx == 0); + p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack; } len_parsed += p_csep->bLength; prev_ep_addr = 0; } else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { // parse out the bulk endpoint info tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_mdh; - TU_LOG2("found ENDPOINT Descriptor for %u\r\n", p_ep->bEndpointAddress); + TU_LOG_DRV(" Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - TU_VERIFY(p_midi_host->ep_out == 0); - TU_VERIFY(p_midi_host->num_cables_tx == 0); - p_midi_host->ep_out = p_ep->bEndpointAddress; - prev_ep_addr = p_midi_host->ep_out; + TU_VERIFY(p_midi->ep_out == 0); + TU_VERIFY(p_midi->num_cables_tx == 0); + p_midi->ep_out = p_ep->bEndpointAddress; + prev_ep_addr = p_midi->ep_out; out_desc = p_ep; } else { - TU_VERIFY(p_midi_host->ep_in == 0); - TU_VERIFY(p_midi_host->num_cables_rx == 0); - p_midi_host->ep_in = p_ep->bEndpointAddress; - prev_ep_addr = p_midi_host->ep_in; + TU_VERIFY(p_midi->ep_in == 0); + TU_VERIFY(p_midi->num_cables_rx == 0); + p_midi->ep_in = p_ep->bEndpointAddress; + prev_ep_addr = p_midi->ep_in; in_desc = p_ep; } len_parsed += p_mdh->bLength; @@ -382,28 +295,22 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_desc = tu_desc_next(p_desc); p_mdh = (midi_desc_header_t const *) p_desc; } - TU_VERIFY((p_midi_host->ep_out != 0 && p_midi_host->num_cables_tx != 0) || - (p_midi_host->ep_in != 0 && p_midi_host->num_cables_rx != 0)); - TU_LOG1("MIDI descriptor parsed successfully\r\n"); - // remove duplicate string indices - for (int idx = 0; idx < p_midi_host->num_string_indices; idx++) { - for (int jdx = idx + 1; jdx < p_midi_host->num_string_indices; jdx++) { - while (jdx < p_midi_host->num_string_indices && p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { - // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 - p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices - 1]; - --p_midi_host->num_string_indices; - } - } - } + TU_VERIFY((p_midi->ep_out != 0 && p_midi->num_cables_tx != 0) || + (p_midi->ep_in != 0 && p_midi->num_cables_rx != 0)); + if (in_desc) { TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); - tu_edpt_stream_open(&p_midi_host->ep_stream.rx, in_desc); + tu_edpt_stream_open(&p_midi->ep_stream.rx, in_desc); } if (out_desc) { TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); - tu_edpt_stream_open(&p_midi_host->ep_stream.tx, out_desc); + tu_edpt_stream_open(&p_midi->ep_stream.tx, out_desc); } - p_midi_host->dev_addr = dev_addr; + p_midi->dev_addr = dev_addr; + + // if (tuh_midi_interface_descriptor_cb) { + // tuh_midi_interface_descriptor_cb(dev_addr, desc_itf, ); + // } return true; } @@ -428,7 +335,7 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { //--------------------------------------------------------------------+ // API //--------------------------------------------------------------------+ -bool tuh_midi_configured(uint8_t dev_addr) { +bool tuh_midi_mounted(uint8_t dev_addr) { midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); TU_VERIFY(p_midi_host != NULL); return p_midi_host->configured; @@ -680,69 +587,6 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p return bytes_buffered; } -//--------------------------------------------------------------------+ -// String API -//--------------------------------------------------------------------+ -#if CFG_MIDI_HOST_DEVSTRINGS -static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) -{ - uint8_t index = 0; - uint8_t assoc; - for (assoc = 0; index == 0 && assoc < ptr->next_in_jack; assoc++) - { - if (jack_id == ptr->in_jack_info[assoc].jack_id) - { - index = ptr->in_jack_info[assoc].string_index; - } - } - for (assoc = 0; index == 0 && assoc < ptr->next_out_jack; assoc++) - { - if (jack_id == ptr->out_jack_info[assoc].jack_id) - { - index = ptr->out_jack_info[assoc].string_index; - } - } - return index; -} - -uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - uint8_t nstrings = p_midi_host->num_cables_rx; - if (nstrings > max_istrings) { - nstrings = max_istrings; - } - for (uint8_t jack = 0; jackep_in_associated_jacks[jack]; - istrings[jack] = find_string_index(p_midi_host, jack_id); - } - return nstrings; -} - -uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings) -{ - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - uint8_t nstrings = p_midi_host->num_cables_tx; - if (nstrings > max_istrings) { - nstrings = max_istrings; - } - for (uint8_t jack = 0; jackep_out_associated_jacks[jack]; - istrings[jack] = find_string_index(p_midi_host, jack_id); - } - return nstrings; -} -#endif - -uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings) -{ - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint8_t nstrings = p_midi_host->num_string_indices; - if (nstrings) { *istrings = p_midi_host->all_string_indices; } - return nstrings; -} #endif #endif diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 6e2595e44..adf41d205 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -59,14 +59,12 @@ #define CFG_TUH_MIDI_STREAM_API 1 #endif -#ifndef CFG_MIDI_HOST_DEVSTRINGS -#define CFG_MIDI_HOST_DEVSTRINGS 0 -#endif - //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ -bool tuh_midi_configured (uint8_t dev_addr); + +// Check if MIDI interface is mounted +bool tuh_midi_mounted(uint8_t dev_addr); // return the number of virtual midi cables on the device's IN endpoint uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); @@ -74,12 +72,6 @@ uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); // return the number of virtual midi cables on the device's OUT endpoint uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr); -#if CFG_MIDI_HOST_DEVSTRINGS -uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); -uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); -uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); -#endif - // return the raw number of bytes available. // Note: this is related but not the same as number of stream bytes available. uint32_t tuh_midi_read_available(uint8_t dev_addr); @@ -140,6 +132,10 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * // Callbacks (Weak is optional) //--------------------------------------------------------------------+ +// Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. +// Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. +// TU_ATTR_WEAK void tuh_midi_interface_descriptor_cb(uint8_t dev_addr, const uint8_t* desc_itf, uint16_t desc_len); + // Invoked when device with MIDI interface is mounted. TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx); From 71e046d9ffb6e388052b02f8230de51bfeb5b0ed Mon Sep 17 00:00:00 2001 From: hathach Date: Sun, 23 Feb 2025 22:21:55 +0700 Subject: [PATCH 61/87] add tuh_midi_descriptor_cb() --- src/class/audio/audio.h | 1 + src/class/audio/audio_device.c | 4 - src/class/midi/midi.h | 21 ---- src/class/midi/midi_host.c | 175 +++++++++++++++------------------ src/class/midi/midi_host.h | 14 ++- src/common/tusb_types.h | 14 ++- src/tusb.c | 12 ++- 7 files changed, 113 insertions(+), 128 deletions(-) diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h index 2f97c0f23..0d1acadcc 100644 --- a/src/class/audio/audio.h +++ b/src/class/audio/audio.h @@ -661,6 +661,7 @@ typedef struct TU_ATTR_PACKED uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors. uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t. } audio_desc_cs_ac_interface_t; +TU_VERIFY_STATIC(sizeof(audio_desc_cs_ac_interface_t) == 9, "size is not correct"); /// AUDIO Clock Source Descriptor (4.7.2.1) typedef struct TU_ATTR_PACKED diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 8a130b7e2..388168424 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -628,10 +628,6 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio); #if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING) static void audiod_parse_for_AS_params(audiod_function_t *audio, uint8_t const *p_desc, uint8_t const *p_desc_end, uint8_t const as_itf); - -static inline uint8_t tu_desc_subtype(void const *desc) { - return ((uint8_t const *) desc)[2]; -} #endif #if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h index a7da98831..cd67640e4 100644 --- a/src/class/midi/midi.h +++ b/src/class/midi/midi.h @@ -150,27 +150,6 @@ typedef midi_desc_out_jack_n_t(1) midi_desc_out_jack_1in_t; // 1 input typedef midi_desc_out_jack_1in_t midi_desc_out_jack_t; // backward compatible TU_VERIFY_STATIC(sizeof(midi_desc_out_jack_1in_t) == 7 + 2 * 1, "size is not correct"); -/// MIDI Element Descriptor -typedef struct TU_ATTR_PACKED { - uint8_t bLength ; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType ; ///< Descriptor SubType - uint8_t bElementID; - - uint8_t bNrInputPins; - uint8_t baSourceID; - uint8_t baSourcePin; - - uint8_t bNrOutputPins; - uint8_t bInTerminalLink; - uint8_t bOutTerminalLink; - uint8_t bElCapsSize; - - uint16_t bmElementCaps; - uint8_t iElement; -} midi_desc_element_t; -TU_VERIFY_STATIC(sizeof(midi_desc_element_t) == 14, "size is not correct"); - /// MIDI Element Descriptor with multiple pins #define midi_desc_element_n_t(input_num) \ struct TU_ATTR_PACKED { \ diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 810c413e3..2fdf41b9d 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -194,123 +194,108 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d midih_interface_t *p_midi = find_new_midi(); TU_VERIFY(p_midi != NULL); - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); - // There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface + + // There can be just a MIDI or an Audio + MIDI interface + // const uint8_t* p_start = ((uint8_t const*) desc_itf); + const uint8_t* p_end = ((uint8_t const*) desc_itf) + max_len; uint8_t const *p_desc = (uint8_t const *) desc_itf; uint16_t len_parsed = 0; - if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { - // This driver does not support audio streaming. However, if this is the audio control interface - // there might be a MIDI interface following it. Search through every descriptor until a MIDI - // interface is found or the end of the descriptor is found - while (len_parsed < max_len && - (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) { - len_parsed += desc_itf->bLength; - p_desc = tu_desc_next(p_desc); - desc_itf = (tusb_desc_interface_t const *)p_desc; - } + tuh_midi_descriptor_cb_t desc_cb = { 0 }; + desc_cb.jack_num = 0; + + // If there is Audio Control Interface + Audio Header descriptor, skip it + if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { + TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t)); + + p_desc = tu_desc_next(p_desc); + TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && + tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_HEADER); + + p_desc = tu_desc_next(p_desc); + desc_itf = (tusb_desc_interface_t const *)p_desc; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); } TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); + desc_cb.desc_interface = desc_itf; + len_parsed += desc_itf->bLength; TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); p_midi->itf_num = desc_itf->bInterfaceNumber; - - // CS Header descriptor p_desc = tu_desc_next(p_desc); - midi_desc_header_t const *p_mdh = (midi_desc_header_t const *) p_desc; - TU_VERIFY(p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && - p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER); - TU_LOG_DRV(" Interface Header descriptor\r\n"); - // p_desc = tu_desc_next(p_desc); - uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descriptor - tusb_desc_endpoint_t const* in_desc = NULL; - tusb_desc_endpoint_t const* out_desc = NULL; - while (len_parsed < max_len) { - TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || - p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); + bool found_new_interface = false; + while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) { + switch (tu_desc_type(p_desc)) { + case TUSB_DESC_INTERFACE: + found_new_interface = true; + break; - if (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) { - // The USB host doesn't really need this information unless it uses - // the string descriptor for a jack or Element + case TUSB_DESC_CS_INTERFACE: + switch (tu_desc_subtype(p_desc)) { + case MIDI_CS_INTERFACE_HEADER: + TU_LOG_DRV(" Interface Header descriptor\r\n"); + desc_cb.desc_header = p_desc; + break; - // assume it is an input jack - midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *) p_desc; - if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) { - TU_LOG_DRV(" Interface Header descriptor\r\n"); - } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) { - // Then it is an in jack. - TU_LOG_DRV(" IN Jack %s descriptor \r\n", p_mdij->bJackType == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) { - // then it is an out jack - TU_LOG_DRV(" OUT Jack %s descriptor\r\n", p_mdij->bJackType == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) { - // the it is an element; - TU_LOG_DRV("Found element\r\n"); - } else { - TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); - TU_VERIFY(false);// unknown CS Interface sub-type + case MIDI_CS_INTERFACE_IN_JACK: + case MIDI_CS_INTERFACE_OUT_JACK: { + TU_LOG_DRV(" Jack %s %s descriptor \r\n", + tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", + p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); + desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; + break; + } + + case MIDI_CS_INTERFACE_ELEMENT: + TU_LOG_DRV(" Element descriptor\r\n"); + desc_cb.desc_element = p_desc; + break; + + default: + TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); + break; + } + break; + + case TUSB_DESC_ENDPOINT: { + tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_desc; + p_desc = tu_desc_next(p_desc); // next to CS endpoint + TU_VERIFY(p_desc < p_end && tu_desc_next(p_desc) <= p_end); + midi_desc_cs_endpoint_t const *p_csep = (midi_desc_cs_endpoint_t const *) p_desc; + + TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { + p_midi->ep_out = p_ep->bEndpointAddress; + p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack; + desc_cb.desc_epout = p_ep; + + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); + tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep); + } else { + p_midi->ep_in = p_ep->bEndpointAddress; + p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack; + desc_cb.desc_epin = p_ep; + + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); + tu_edpt_stream_open(&p_midi->ep_stream.rx, p_ep); + } + break; } - len_parsed += p_mdij->bLength; - } else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) { - TU_LOG_DRV(" CS_ENDPOINT descriptor\r\n"); - TU_VERIFY(prev_ep_addr != 0); - // parse out the mapping between the device's embedded jacks and the endpoints - // Each embedded IN jack is associated with an OUT endpoint - midi_desc_cs_endpoint_t const *p_csep = (midi_desc_cs_endpoint_t const *) p_mdh; - if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) { - TU_VERIFY(p_midi->ep_out == prev_ep_addr); - TU_VERIFY(p_midi->num_cables_tx == 0); - p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack; - } else { - TU_VERIFY(p_midi->ep_in == prev_ep_addr); - TU_VERIFY(p_midi->num_cables_rx == 0); - p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack; - } - len_parsed += p_csep->bLength; - prev_ep_addr = 0; - } else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { - // parse out the bulk endpoint info - tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_mdh; - TU_LOG_DRV(" Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); - if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - TU_VERIFY(p_midi->ep_out == 0); - TU_VERIFY(p_midi->num_cables_tx == 0); - p_midi->ep_out = p_ep->bEndpointAddress; - prev_ep_addr = p_midi->ep_out; - out_desc = p_ep; - } else { - TU_VERIFY(p_midi->ep_in == 0); - TU_VERIFY(p_midi->num_cables_rx == 0); - p_midi->ep_in = p_ep->bEndpointAddress; - prev_ep_addr = p_midi->ep_in; - in_desc = p_ep; - } - len_parsed += p_mdh->bLength; + + default: break; // skip unknown descriptor } p_desc = tu_desc_next(p_desc); - p_mdh = (midi_desc_header_t const *) p_desc; } - TU_VERIFY((p_midi->ep_out != 0 && p_midi->num_cables_tx != 0) || - (p_midi->ep_in != 0 && p_midi->num_cables_rx != 0)); + desc_cb.desc_interface_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); - if (in_desc) { - TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); - tu_edpt_stream_open(&p_midi->ep_stream.rx, in_desc); - } - if (out_desc) { - TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); - tu_edpt_stream_open(&p_midi->ep_stream.tx, out_desc); - } p_midi->dev_addr = dev_addr; - // if (tuh_midi_interface_descriptor_cb) { - // tuh_midi_interface_descriptor_cb(dev_addr, desc_itf, ); - // } + if (tuh_midi_descriptor_cb) { + tuh_midi_descriptor_cb(dev_addr, &desc_cb); + } return true; } diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index adf41d205..286e034f1 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -62,6 +62,18 @@ //--------------------------------------------------------------------+ // Application API //--------------------------------------------------------------------+ +typedef struct { + const tusb_desc_interface_t* desc_interface; // start of whole midi interface descriptor + uint16_t desc_interface_len; + + const uint8_t* desc_header; + const uint8_t* desc_element; + const tusb_desc_endpoint_t* desc_epin; // endpoint IN descriptor, CS_ENDPOINT is right after + const tusb_desc_endpoint_t* desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after + + uint8_t jack_num; + const uint8_t* desc_jack[16]; // list of jack descriptors (embedded + external) +} tuh_midi_descriptor_cb_t; // Check if MIDI interface is mounted bool tuh_midi_mounted(uint8_t dev_addr); @@ -134,7 +146,7 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * // Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. // Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. -// TU_ATTR_WEAK void tuh_midi_interface_descriptor_cb(uint8_t dev_addr, const uint8_t* desc_itf, uint16_t desc_len); +TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t dev_addr, tuh_midi_descriptor_cb_t const* desc_cb); // Invoked when device with MIDI interface is mounted. TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx); diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 42ce5fc12..95ee489a6 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -281,7 +281,8 @@ typedef enum { // TODO remove enum { DESC_OFFSET_LEN = 0, - DESC_OFFSET_TYPE = 1 + DESC_OFFSET_TYPE = 1, + DESC_OFFSET_SUBTYPE = 2 }; enum { @@ -570,14 +571,19 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* des return desc8 + desc8[DESC_OFFSET_LEN]; } +// get descriptor length +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { + return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; +} + // get descriptor type TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) { return ((uint8_t const*) desc)[DESC_OFFSET_TYPE]; } -// get descriptor length -TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) { - return ((uint8_t const*) desc)[DESC_OFFSET_LEN]; +// get descriptor subtype +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) { + return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE]; } // find descriptor that match byte1 (type) diff --git a/src/tusb.c b/src/tusb.c index 85ab1d6ae..9303e9bc4 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -142,7 +142,9 @@ void tusb_int_handler(uint8_t rhport, bool in_isr) { uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) { while (desc + 1 < end) { - if (desc[1] == byte1) return desc; + if (desc[1] == byte1) { + return desc; + } desc += desc[DESC_OFFSET_LEN]; } return NULL; @@ -150,7 +152,9 @@ uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byt uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) { while (desc + 2 < end) { - if (desc[1] == byte1 && desc[2] == byte2) return desc; + if (desc[1] == byte1 && desc[2] == byte2) { + return desc; + } desc += desc[DESC_OFFSET_LEN]; } return NULL; @@ -158,7 +162,9 @@ uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t by uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) { while (desc + 3 < end) { - if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) return desc; + if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) { + return desc; + } desc += desc[DESC_OFFSET_LEN]; } return NULL; From 8c70475c23233e70652c5852088fc539bfb337ad Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Feb 2025 12:39:02 +0700 Subject: [PATCH 62/87] change API to take index instead of dev address, this allow to support more than 1 midi per device. --- examples/host/midi_rx/src/main.c | 48 ++---- src/class/midi/midi_host.c | 275 +++++++++++++++++-------------- src/class/midi/midi_host.h | 42 ++--- 3 files changed, 189 insertions(+), 176 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 57e9df29e..a8a5b40ca 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -30,12 +30,9 @@ #include "bsp/board_api.h" #include "tusb.h" -#if CFG_TUH_MIDI - //--------------------------------------------------------------------+ // STATIC GLOBALS DECLARATION //--------------------------------------------------------------------+ -static uint8_t midi_dev_addr = 0; //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF PROTOTYPES @@ -65,8 +62,6 @@ int main(void) { return 0; } -#endif - //--------------------------------------------------------------------+ // Blinking Task //--------------------------------------------------------------------+ @@ -88,13 +83,7 @@ void led_blinking_task(void) { // MIDI host receive task //--------------------------------------------------------------------+ void midi_host_rx_task(void) { - // device must be attached and have at least one endpoint ready to receive a message - if (!midi_dev_addr || !tuh_midi_mounted(midi_dev_addr)) { - return; - } - if (tuh_midi_get_num_rx_cables(midi_dev_addr) < 1) { - return; - } + // nothing to do, we just print out received data in callback } //--------------------------------------------------------------------+ @@ -102,39 +91,32 @@ void midi_host_rx_task(void) { //--------------------------------------------------------------------+ // Invoked when device with MIDI interface is mounted. -void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx) { - (void) num_cables_rx; - (void) num_cables_tx; - midi_dev_addr = dev_addr; - TU_LOG1("MIDI device address = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", - dev_addr, num_cables_rx, num_cables_tx); +void tuh_midi_mount_cb(uint8_t idx, uint8_t num_cables_rx, uint16_t num_cables_tx) { + printf("MIDI Interface Index = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", + idx, num_cables_rx, num_cables_tx); } // Invoked when device with hid interface is un-mounted -void tuh_midi_umount_cb(uint8_t dev_addr) { - (void) dev_addr; - midi_dev_addr = 0; - TU_LOG1("MIDI device address = %d is unmounted\r\n", dev_addr); +void tuh_midi_umount_cb(uint8_t idx) { + printf("MIDI Interface Index = %u is unmounted\r\n", idx); } -void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { - if (midi_dev_addr != dev_addr) { - return; - } - +void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets) { if (num_packets == 0) { return; } uint8_t cable_num; uint8_t buffer[48]; - uint32_t bytes_read = tuh_midi_stream_read(dev_addr, &cable_num, buffer, sizeof(buffer)); - (void) bytes_read; + uint32_t bytes_read = tuh_midi_stream_read(idx, &cable_num, buffer, sizeof(buffer)); - TU_LOG1("Read bytes %lu cable %u", bytes_read, cable_num); - TU_LOG1_MEM(buffer, bytes_read, 2); + printf("Cable %u rx %lu bytes: ", cable_num, bytes_read); + for (uint32_t i = 0; i < bytes_read; i++) { + printf("%02X ", buffer[i]); + } + printf("\r\n"); } -void tuh_midi_tx_cb(uint8_t dev_addr) { - (void) dev_addr; +void tuh_midi_tx_cb(uint8_t idx) { + (void) idx; } diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 2fdf41b9d..8fb325c2b 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -45,8 +45,9 @@ //--------------------------------------------------------------------+ typedef struct { - uint8_t dev_addr; - uint8_t itf_num; + uint8_t daddr; + uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t itf_count; // number of interface including Audio Control + MIDI streaming uint8_t ep_in; // IN endpoint address uint8_t ep_out; // OUT endpoint address @@ -71,7 +72,7 @@ typedef struct { uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; } ep_stream; - bool configured; + bool mounted; }midih_interface_t; typedef struct { @@ -85,17 +86,24 @@ CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI]; //--------------------------------------------------------------------+ // Helper //--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_midi_by_daddr(uint8_t dev_addr) { - for (uint8_t i = 0; i < CFG_TUH_MIDI; i++) { - if (_midi_host[i].dev_addr == dev_addr) { - return &_midi_host[i]; +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_new_midi_index(void) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) { + if (_midi_host[idx].daddr == 0) { + return idx; } } - return NULL; + return TUSB_INDEX_INVALID_8; } -TU_ATTR_ALWAYS_INLINE static inline midih_interface_t* find_new_midi(void) { - return find_midi_by_daddr(0); +static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) { + const midih_interface_t *p_midi = &_midi_host[idx]; + if ((p_midi->daddr == daddr) && + (ep_addr == p_midi->ep_stream.rx.ep_addr || ep_addr == p_midi->ep_stream.tx.ep_addr)) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; } //--------------------------------------------------------------------+ @@ -122,32 +130,38 @@ bool midih_deinit(void) { return true; } -void midih_close(uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - if (p_midi_host == NULL) { - return; - } - if (tuh_midi_umount_cb) { - tuh_midi_umount_cb(dev_addr); - } - p_midi_host->ep_in = 0; - p_midi_host->ep_out = 0; - p_midi_host->itf_num = 0; - p_midi_host->num_cables_rx = 0; - p_midi_host->num_cables_tx = 0; - p_midi_host->dev_addr = 0; - p_midi_host->configured = false; - tu_memclr(&p_midi_host->stream_read, sizeof(p_midi_host->stream_read)); - tu_memclr(&p_midi_host->stream_write, sizeof(p_midi_host->stream_write)); +void midih_close(uint8_t daddr) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) { + midih_interface_t* p_midi = &_midi_host[idx]; + if (p_midi->daddr == daddr) { + TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); - tu_edpt_stream_close(&p_midi_host->ep_stream.rx); - tu_edpt_stream_close(&p_midi_host->ep_stream.tx); + if (tuh_midi_umount_cb) { + tuh_midi_umount_cb(idx); + } + + p_midi->ep_in = 0; + p_midi->ep_out = 0; + p_midi->bInterfaceNumber = 0; + p_midi->num_cables_rx = 0; + p_midi->num_cables_tx = 0; + p_midi->daddr = 0; + p_midi->mounted = false; + tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); + tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write)); + + tu_edpt_stream_close(&p_midi->ep_stream.rx); + tu_edpt_stream_close(&p_midi->ep_stream.tx); + } + } } bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { (void) result; - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); + const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi_host = &_midi_host[idx]; + if (ep_addr == p_midi_host->ep_stream.rx.ep_addr) { // receive new data if available if (xferred_bytes) { @@ -167,14 +181,14 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint } if (tuh_midi_rx_cb) { - tuh_midi_rx_cb(dev_addr, packets_queued); // invoke receive callback + tuh_midi_rx_cb(idx, packets_queued); } } tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for next transfer } else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) { if (tuh_midi_tx_cb) { - tuh_midi_tx_cb(dev_addr); + tuh_midi_tx_cb(idx); } if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi_host->ep_stream.tx)) { // If there is no data left, a ZLP should be sent if @@ -192,19 +206,20 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void) rhport; - midih_interface_t *p_midi = find_new_midi(); - TU_VERIFY(p_midi != NULL); TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); - - // There can be just a MIDI or an Audio + MIDI interface // const uint8_t* p_start = ((uint8_t const*) desc_itf); - const uint8_t* p_end = ((uint8_t const*) desc_itf) + max_len; - uint8_t const *p_desc = (uint8_t const *) desc_itf; - uint16_t len_parsed = 0; + const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len; + const uint8_t *p_desc = (const uint8_t *) desc_itf; + + const uint8_t idx = find_new_midi_index(); + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + p_midi->itf_count = 0; tuh_midi_descriptor_cb_t desc_cb = { 0 }; desc_cb.jack_num = 0; + // There can be just a MIDI or an Audio + MIDI interface // If there is Audio Control Interface + Audio Header descriptor, skip it if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t)); @@ -216,15 +231,16 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_desc = tu_desc_next(p_desc); desc_itf = (tusb_desc_interface_t const *)p_desc; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); + p_midi->itf_count = 1; } TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); - desc_cb.desc_interface = desc_itf; - - len_parsed += desc_itf->bLength; TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - p_midi->itf_num = desc_itf->bInterfaceNumber; - p_desc = tu_desc_next(p_desc); + p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; + p_midi->itf_count++; + desc_cb.desc_interface = desc_itf; + + p_desc = tu_desc_next(p_desc); // next to CS Header bool found_new_interface = false; while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) { @@ -291,102 +307,115 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d } desc_cb.desc_interface_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); - p_midi->dev_addr = dev_addr; + p_midi->daddr = dev_addr; if (tuh_midi_descriptor_cb) { - tuh_midi_descriptor_cb(dev_addr, &desc_cb); + tuh_midi_descriptor_cb(idx, &desc_cb); } return true; } bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { - (void) itf_num; - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - p_midi_host->configured = true; + uint8_t idx = tuh_midi_itf_get_index(dev_addr, itf_num); + TU_ASSERT(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + p_midi->mounted = true; if (tuh_midi_mount_cb) { - tuh_midi_mount_cb(dev_addr, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); + tuh_midi_mount_cb(idx, p_midi->num_cables_rx, p_midi->num_cables_tx); } - tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for incoming data + tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for incoming data // No special config things to do for MIDI - usbh_driver_set_config_complete(dev_addr, p_midi_host->itf_num); + usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber); return true; } //--------------------------------------------------------------------+ // API //--------------------------------------------------------------------+ -bool tuh_midi_mounted(uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - return p_midi_host->configured; +bool tuh_midi_mounted(uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + return p_midi->mounted; } -uint8_t tuh_midi_get_num_tx_cables (uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - TU_VERIFY(p_midi_host->ep_stream.tx.ep_addr != 0, 0); - return p_midi_host->num_cables_tx; +uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) { + const midih_interface_t *p_midi = &_midi_host[idx]; + if (p_midi->daddr == daddr && + (p_midi->bInterfaceNumber == itf_num || + p_midi->bInterfaceNumber == (uint8_t) (itf_num + p_midi->itf_count - 1))) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; } -uint8_t tuh_midi_get_num_rx_cables (uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - TU_VERIFY(p_midi_host->ep_stream.rx.ep_addr != 0, 0); - return p_midi_host->num_cables_rx; +uint8_t tuh_midi_get_num_tx_cables (uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi->ep_stream.tx.ep_addr != 0, 0); + return p_midi->num_cables_tx; } -uint32_t tuh_midi_read_available(uint8_t dev_addr) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - return tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx); +uint8_t tuh_midi_get_num_rx_cables (uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi->ep_stream.rx.ep_addr != 0, 0); + return p_midi->num_cables_rx; } -uint32_t tuh_midi_write_flush(uint8_t dev_addr) { - midih_interface_t *p_midi = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi != NULL); - return tu_edpt_stream_write_xfer(p_midi->dev_addr, &p_midi->ep_stream.tx); +uint32_t tuh_midi_read_available(uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + return tu_edpt_stream_read_available(&p_midi->ep_stream.rx); +} + +uint32_t tuh_midi_write_flush(uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI); + midih_interface_t *p_midi = &_midi_host[idx]; + return tu_edpt_stream_write_xfer(p_midi->daddr, &p_midi->ep_stream.tx); } //--------------------------------------------------------------------+ // Packet API //--------------------------------------------------------------------+ +uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0, 0); + midih_interface_t *p_midi = &_midi_host[idx]; -uint32_t tuh_midi_packet_read_n(uint8_t dev_addr, uint8_t* buffer, uint32_t bufsize) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - - uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi_host->ep_stream.rx)); + uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi->ep_stream.rx)); count4 = tu_align4(count4); // round down to multiple of 4 TU_VERIFY(count4 > 0, 0); - return tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, buffer, count4); + return tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, buffer, count4); } -uint32_t tuh_midi_packet_write_n(uint8_t dev_addr, const uint8_t* buffer, uint32_t bufsize) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL, 0); - uint32_t bufsize4 = tu_align4(bufsize); - return tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, buffer, bufsize4); +uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0, 0); + midih_interface_t *p_midi = &_midi_host[idx]; + + const uint32_t bufsize4 = tu_align4(bufsize); + TU_VERIFY(bufsize4 > 0, 0); + return tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, buffer, bufsize4); } //--------------------------------------------------------------------+ // Stream API //--------------------------------------------------------------------+ #if CFG_TUH_MIDI_STREAM_API -uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(cable_num < p_midi_host->num_cables_tx); - midi_driver_stream_t *stream = &p_midi_host->stream_write; +uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(cable_num < p_midi->num_cables_tx); + midi_driver_stream_t *stream = &p_midi->stream_write; - uint32_t i = 0; - while ((i < bufsize) && (tu_edpt_stream_write_available(dev_addr, &p_midi_host->ep_stream.tx) >= 4)) { - uint8_t const data = buffer[i]; - i++; + uint32_t byte_count = 0; + while ((byte_count < bufsize) && (tu_edpt_stream_write_available(p_midi->daddr, &p_midi->ep_stream.tx) >= 4)) { + uint8_t const data = buffer[byte_count]; + byte_count++; if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { // real-time messages need to be sent right away midi_driver_stream_t streamrt; @@ -394,8 +423,8 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons streamrt.buffer[1] = data; streamrt.index = 2; streamrt.total = 2; - uint32_t const count = tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, streamrt.buffer, 4); - TU_ASSERT(count == 4, i); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition + uint32_t const count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, streamrt.buffer, 4); + TU_ASSERT(count == 4, byte_count); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition } else if (stream->index == 0) { //------------- New event packet -------------// @@ -445,7 +474,7 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons } } else { //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, i); + TU_ASSERT(stream->index < 4, byte_count); stream->buffer[stream->index] = data; stream->index++; // See if this byte ends a SysEx. @@ -458,42 +487,41 @@ uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t cons // Send out packet if (stream->index >= 2 && stream->index == stream->total) { // zeroes unused bytes - for (uint8_t idx = stream->total; idx < 4; idx++) { stream->buffer[idx] = 0; } + for (uint8_t i = stream->total; i < 4; i++) { + stream->buffer[i] = 0; + } TU_LOG3_MEM(stream->buffer, 4, 2); - uint32_t const count = tu_edpt_stream_write(dev_addr, &p_midi_host->ep_stream.tx, stream->buffer, 4); + const uint32_t count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, stream->buffer, 4); // complete current event packet, reset stream stream->index = 0; stream->total = 0; // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); + TU_ASSERT(count == 4, byte_count); } } - return i; + return byte_count; } -uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { - midih_interface_t *p_midi_host = find_midi_by_daddr(dev_addr); - TU_VERIFY(p_midi_host != NULL); +uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI && p_cable_num && p_buffer && bufsize > 0); + midih_interface_t *p_midi = &_midi_host[idx]; uint32_t bytes_buffered = 0; - TU_ASSERT(p_cable_num); - TU_ASSERT(p_buffer); - TU_ASSERT(bufsize); uint8_t one_byte; - if (!tu_edpt_stream_peek(&p_midi_host->ep_stream.rx, &one_byte)) { + if (!tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) { return 0; } *p_cable_num = (one_byte >> 4) & 0xf; - uint32_t nread = tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, p_midi_host->stream_read.buffer, 4); - static uint16_t cable_sysex_in_progress; // bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END + uint32_t nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + static uint16_t cable_sysex_in_progress;// bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END while (nread == 4 && bytes_buffered < bufsize) { - *p_cable_num = (p_midi_host->stream_read.buffer[0] >> 4) & 0x0f; + *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f; uint8_t bytes_to_add_to_stream = 0; - if (*p_cable_num < p_midi_host->num_cables_rx) { + if (*p_cable_num < p_midi->num_cables_rx) { // ignore the CIN field; too many devices out there encode this wrong - uint8_t status = p_midi_host->stream_read.buffer[1]; + uint8_t status = p_midi->stream_read.buffer[1]; uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) { if (status == MIDI_STATUS_SYSEX_START) { @@ -502,13 +530,13 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p // only add the packet if a sysex message is in progress if (cable_sysex_in_progress & cable_mask) { ++bytes_to_add_to_stream; - for (uint8_t idx = 2; idx < 4; idx++) { - if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL) { + for (uint8_t i = 2; i < 4; i++) { + if (p_midi->stream_read.buffer[i] <= MIDI_MAX_DATA_VAL) { ++bytes_to_add_to_stream; - } else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) { + } else if (p_midi->stream_read.buffer[i] == MIDI_STATUS_SYSEX_END) { ++bytes_to_add_to_stream; cable_sysex_in_progress &= (uint16_t) ~cable_mask; - idx = 4;// force the loop to exit; I hate break statements in loops + i = 4;// force the loop to exit; I hate break statements in loops } } } @@ -555,23 +583,22 @@ uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p } } - for (uint8_t idx = 1; idx <= bytes_to_add_to_stream; idx++) { - *p_buffer++ = p_midi_host->stream_read.buffer[idx]; + for (uint8_t i = 1; i <= bytes_to_add_to_stream; i++) { + *p_buffer++ = p_midi->stream_read.buffer[i]; } bytes_buffered += bytes_to_add_to_stream; nread = 0; - if (tu_edpt_stream_peek(&p_midi_host->ep_stream.rx, &one_byte)) { + if (tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) { uint8_t new_cable = (one_byte >> 4) & 0xf; if (new_cable == *p_cable_num) { // still on the same cable. Continue reading the stream - nread = tu_edpt_stream_read(dev_addr, &p_midi_host->ep_stream.rx, p_midi_host->stream_read.buffer, 4); + nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); } } } return bytes_buffered; } - #endif #endif diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 286e034f1..c9780a9e4 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -76,22 +76,26 @@ typedef struct { } tuh_midi_descriptor_cb_t; // Check if MIDI interface is mounted -bool tuh_midi_mounted(uint8_t dev_addr); +bool tuh_midi_mounted(uint8_t idx); + +// Get Interface index from device address + interface number +// return TUSB_INDEX_INVALID_8 (0xFF) if not found +uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); // return the number of virtual midi cables on the device's IN endpoint -uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); +uint8_t tuh_midi_get_num_rx_cables(uint8_t idx); // return the number of virtual midi cables on the device's OUT endpoint -uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr); +uint8_t tuh_midi_get_num_tx_cables(uint8_t idx); // return the raw number of bytes available. // Note: this is related but not the same as number of stream bytes available. -uint32_t tuh_midi_read_available(uint8_t dev_addr); +uint32_t tuh_midi_read_available(uint8_t idx); // Send any queued packets to the device if the host hardware is able to do it // Returns the number of bytes flushed to the host hardware or 0 if // the host hardware is busy or there is nothing in queue to send. -uint32_t tuh_midi_write_flush( uint8_t dev_addr); +uint32_t tuh_midi_write_flush(uint8_t idx); //--------------------------------------------------------------------+ // Packet API @@ -99,24 +103,24 @@ uint32_t tuh_midi_write_flush( uint8_t dev_addr); // Read all available MIDI packets from the connected device // Return number of bytes read (always multiple of 4) -uint32_t tuh_midi_packet_read_n(uint8_t dev_addr, uint8_t* buffer, uint32_t bufsize); +uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize); // Read a raw MIDI packet from the connected device // Return true if a packet was returned TU_ATTR_ALWAYS_INLINE static inline -bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]) { - return 4 == tuh_midi_packet_read_n(dev_addr, packet, 4); +bool tuh_midi_packet_read (uint8_t idx, uint8_t packet[4]) { + return 4 == tuh_midi_packet_read_n(idx, packet, 4); } // Write all 4-byte packets, data is locally buffered and only transferred when buffered bytes // reach the endpoint packet size or tuh_midi_write_flush() is called -uint32_t tuh_midi_packet_write_n(uint8_t dev_addr, const uint8_t* buffer, uint32_t bufsize); +uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize); // Write a 4-bytes packet to the device. // Returns true if the packet was successfully queued. TU_ATTR_ALWAYS_INLINE static inline -bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) { - return 4 == tuh_midi_packet_write_n(dev_addr, packet, 4); +bool tuh_midi_packet_write (uint8_t idx, uint8_t const packet[4]) { + return 4 == tuh_midi_packet_write_n(idx, packet, 4); } //--------------------------------------------------------------------+ @@ -127,7 +131,7 @@ bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]) { // Queue a message to the device using stream API. data is locally buffered and only transferred when buffered bytes // reach the endpoint packet size or tuh_midi_write_flush() is called // Returns number of bytes was successfully queued. -uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* p_buffer, uint32_t bufsize); +uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *p_buffer, uint32_t bufsize); // Get the MIDI stream from the device. Set the value pointed // to by p_cable_num to the MIDI cable number intended to receive it. @@ -136,7 +140,7 @@ uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t con // Note that this function ignores the CIN field of the MIDI packet // because a number of commercial devices out there do not encode // it properly. -uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); +uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); #endif @@ -146,16 +150,16 @@ uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t * // Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. // Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. -TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t dev_addr, tuh_midi_descriptor_cb_t const* desc_cb); +TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb); // Invoked when device with MIDI interface is mounted. -TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t num_cables_rx, uint16_t num_cables_tx); +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, uint8_t num_cables_rx, uint16_t num_cables_tx); // Invoked when device with MIDI interface is un-mounted -TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx); -TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets); -TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t dev_addr); +TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets); +TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx); //--------------------------------------------------------------------+ // Internal Class Driver API @@ -165,7 +169,7 @@ bool midih_deinit (void); bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void midih_close (uint8_t dev_addr); +void midih_close (uint8_t daddr); #ifdef __cplusplus } From 56e84bd1a605e3835f29e2e7fd17f65e0f3b5431 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Feb 2025 12:42:45 +0700 Subject: [PATCH 63/87] add desc_audio_control to midi descriptor callback --- examples/host/midi_rx/src/main.c | 2 +- examples/host/midi_rx/src/tusb_config.h | 2 -- src/class/midi/midi_host.c | 7 ++++--- src/class/midi/midi_host.h | 5 +++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index a8a5b40ca..6db329ab5 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -106,8 +106,8 @@ void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets) { return; } - uint8_t cable_num; uint8_t buffer[48]; + uint8_t cable_num = 0; uint32_t bytes_read = tuh_midi_stream_read(idx, &cable_num, buffer, sizeof(buffer)); printf("Cable %u rx %lu bytes: ", cable_num, bytes_read); diff --git a/examples/host/midi_rx/src/tusb_config.h b/examples/host/midi_rx/src/tusb_config.h index 24b3b3ae6..c9b430388 100644 --- a/examples/host/midi_rx/src/tusb_config.h +++ b/examples/host/midi_rx/src/tusb_config.h @@ -111,8 +111,6 @@ extern "C" { #define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1) #define CFG_TUH_MIDI CFG_TUH_DEVICE_MAX -#define CFG_MIDI_HOST_DEVSTRINGS 1 - #ifdef __cplusplus } #endif diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 8fb325c2b..770a39a8d 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -227,9 +227,10 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d p_desc = tu_desc_next(p_desc); TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_HEADER); + desc_cb.desc_audio_control = desc_itf; p_desc = tu_desc_next(p_desc); - desc_itf = (tusb_desc_interface_t const *)p_desc; + desc_itf = (const tusb_desc_interface_t *)p_desc; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); p_midi->itf_count = 1; } @@ -238,7 +239,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; p_midi->itf_count++; - desc_cb.desc_interface = desc_itf; + desc_cb.desc_midi = desc_itf; p_desc = tu_desc_next(p_desc); // next to CS Header @@ -305,7 +306,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d } p_desc = tu_desc_next(p_desc); } - desc_cb.desc_interface_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); + desc_cb.desc_midi_total_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); p_midi->daddr = dev_addr; diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index c9780a9e4..717e6ba67 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -63,8 +63,9 @@ // Application API //--------------------------------------------------------------------+ typedef struct { - const tusb_desc_interface_t* desc_interface; // start of whole midi interface descriptor - uint16_t desc_interface_len; + const tusb_desc_interface_t* desc_audio_control; + const tusb_desc_interface_t* desc_midi; // start of whole midi interface descriptor + uint16_t desc_midi_total_len; const uint8_t* desc_header; const uint8_t* desc_element; From d132044b7587f7e846bbec6e7b897d0842a21d13 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 24 Feb 2025 15:40:48 +0700 Subject: [PATCH 64/87] add tuh_midi_mount_cb_t struct for tuh_midi_mount_cb() change tuh_midi_rx/tx_cb() to have xferred_bytes rename tuh_midi_get_num_rx/tx_cables() to tuh_midi_get_rx/tx_cable_count() use default empty callback instead of weak null to be compatible with keil compiler --- examples/host/cdc_msc_hid/src/main.c | 4 +- examples/host/midi_rx/src/main.c | 13 ++--- src/class/cdc/cdc_host.h | 8 +-- src/class/midi/midi_device.c | 5 -- src/class/midi/midi_host.c | 81 ++++++++++++---------------- src/class/midi/midi_host.h | 34 +++++++----- src/host/usbh_pvt.h | 4 -- 7 files changed, 70 insertions(+), 79 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 71257c0fe..2d5df23f9 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -82,12 +82,12 @@ int main(void) { void tuh_mount_cb(uint8_t dev_addr) { // application set-up - printf("A device with address %d is mounted\r\n", dev_addr); + printf("A device with address %u is mounted\r\n", dev_addr); } void tuh_umount_cb(uint8_t dev_addr) { // application tear-down - printf("A device with address %d is unmounted \r\n", dev_addr); + printf("A device with address %u is unmounted \r\n", dev_addr); } diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index 6db329ab5..d26321e5d 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -91,9 +91,9 @@ void midi_host_rx_task(void) { //--------------------------------------------------------------------+ // Invoked when device with MIDI interface is mounted. -void tuh_midi_mount_cb(uint8_t idx, uint8_t num_cables_rx, uint16_t num_cables_tx) { - printf("MIDI Interface Index = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", - idx, num_cables_rx, num_cables_tx); +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { + printf("MIDI Interface Index = %u, Address = %u, Number of RX cables = %u, Number of TX cables = %u\r\n", + idx, mount_cb_data->daddr, mount_cb_data->rx_cable_count, mount_cb_data->tx_cable_count); } // Invoked when device with hid interface is un-mounted @@ -101,8 +101,8 @@ void tuh_midi_umount_cb(uint8_t idx) { printf("MIDI Interface Index = %u is unmounted\r\n", idx); } -void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets) { - if (num_packets == 0) { +void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { + if (xferred_bytes == 0) { return; } @@ -117,6 +117,7 @@ void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets) { printf("\r\n"); } -void tuh_midi_tx_cb(uint8_t idx) { +void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; + (void) xferred_bytes; } diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h index df975b2f0..8c5399534 100644 --- a/src/class/cdc/cdc_host.h +++ b/src/class/cdc/cdc_host.h @@ -49,22 +49,22 @@ // RX FIFO size #ifndef CFG_TUH_CDC_RX_BUFSIZE -#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // RX Endpoint size #ifndef CFG_TUH_CDC_RX_EPSIZE -#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS #endif // TX FIFO size #ifndef CFG_TUH_CDC_TX_BUFSIZE -#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif // TX Endpoint size #ifndef CFG_TUH_CDC_TX_EPSIZE -#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX +#define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS #endif //--------------------------------------------------------------------+ diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c index 7b6705640..0bbb3caf4 100644 --- a/src/class/midi/midi_device.c +++ b/src/class/midi/midi_device.c @@ -39,9 +39,6 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ - - - typedef struct { uint8_t itf_num; uint8_t ep_in; @@ -440,8 +437,6 @@ uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint1 drv_len += tu_desc_len(p_desc); p_desc = tu_desc_next(p_desc); } - } else { - TU_LOG2("Warning: MIDI Device has no Audio Control Interface"); } // 2nd Interface is MIDI Streaming diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 770a39a8d..a4b1ebd2e 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -40,6 +40,15 @@ #define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_LOG_LEVEL, __VA_ARGS__) +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data) { (void) idx; (void) desc_cb_data; } +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { (void) idx; (void) mount_cb_data; } +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx) { (void) idx; } +TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } +TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } + //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ @@ -52,8 +61,8 @@ typedef struct { uint8_t ep_in; // IN endpoint address uint8_t ep_out; // OUT endpoint address - uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value - uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value + uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value + uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value #if CFG_TUH_MIDI_STREAM_API // For Stream read()/write() API @@ -135,16 +144,13 @@ void midih_close(uint8_t daddr) { midih_interface_t* p_midi = &_midi_host[idx]; if (p_midi->daddr == daddr) { TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); - - if (tuh_midi_umount_cb) { - tuh_midi_umount_cb(idx); - } + tuh_midi_umount_cb(idx); p_midi->ep_in = 0; p_midi->ep_out = 0; p_midi->bInterfaceNumber = 0; - p_midi->num_cables_rx = 0; - p_midi->num_cables_tx = 0; + p_midi->rx_cable_count = 0; + p_midi->tx_cable_count = 0; p_midi->daddr = 0; p_midi->mounted = false; tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); @@ -163,33 +169,16 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint midih_interface_t *p_midi_host = &_midi_host[idx]; if (ep_addr == p_midi_host->ep_stream.rx.ep_addr) { - // receive new data if available + // receive new data, put it into FIFO and invoke callback if available if (xferred_bytes) { - // put in the RX FIFO only non-zero MIDI IN 4-byte packets - uint32_t packets_queued = 0; - uint8_t *buf = _midi_epbuf->rx; - const uint32_t npackets = xferred_bytes / 4; - for (uint32_t p = 0; p < npackets; p++) { - // some devices send back all zero packets even if there is no data ready - const uint32_t packet = tu_unaligned_read32(buf); - if (packet != 0) { - tu_edpt_stream_read_xfer_complete_with_buf(&p_midi_host->ep_stream.rx, buf, 4); - ++packets_queued; - TU_LOG3("MIDI RX=%08x\r\n", packet); - } - buf += 4; - } - - if (tuh_midi_rx_cb) { - tuh_midi_rx_cb(idx, packets_queued); - } + tu_edpt_stream_read_xfer_complete(&p_midi_host->ep_stream.rx, xferred_bytes); + tuh_midi_rx_cb(idx, xferred_bytes); } tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for next transfer } else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) { - if (tuh_midi_tx_cb) { - tuh_midi_tx_cb(idx); - } + tuh_midi_tx_cb(idx, xferred_bytes); + if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi_host->ep_stream.tx)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero @@ -207,7 +196,6 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d (void) rhport; TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); - // const uint8_t* p_start = ((uint8_t const*) desc_itf); const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len; const uint8_t *p_desc = (const uint8_t *) desc_itf; @@ -286,14 +274,14 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { p_midi->ep_out = p_ep->bEndpointAddress; - p_midi->num_cables_tx = p_csep->bNumEmbMIDIJack; + p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; desc_cb.desc_epout = p_ep; TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep); } else { p_midi->ep_in = p_ep->bEndpointAddress; - p_midi->num_cables_rx = p_csep->bNumEmbMIDIJack; + p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; desc_cb.desc_epin = p_ep; TU_ASSERT(tuh_edpt_open(dev_addr, p_ep)); @@ -309,10 +297,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d desc_cb.desc_midi_total_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf); p_midi->daddr = dev_addr; - - if (tuh_midi_descriptor_cb) { - tuh_midi_descriptor_cb(idx, &desc_cb); - } + tuh_midi_descriptor_cb(idx, &desc_cb); return true; } @@ -323,9 +308,13 @@ bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { midih_interface_t *p_midi = &_midi_host[idx]; p_midi->mounted = true; - if (tuh_midi_mount_cb) { - tuh_midi_mount_cb(idx, p_midi->num_cables_rx, p_midi->num_cables_tx); - } + const tuh_midi_mount_cb_t mount_cb_data = { + .daddr = dev_addr, + .bInterfaceNumber = itf_num, + .rx_cable_count = p_midi->rx_cable_count, + .tx_cable_count = p_midi->tx_cable_count, + }; + tuh_midi_mount_cb(idx, &mount_cb_data); tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for incoming data @@ -355,18 +344,18 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { return TUSB_INDEX_INVALID_8; } -uint8_t tuh_midi_get_num_tx_cables (uint8_t idx) { +uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; TU_VERIFY(p_midi->ep_stream.tx.ep_addr != 0, 0); - return p_midi->num_cables_tx; + return p_midi->tx_cable_count; } -uint8_t tuh_midi_get_num_rx_cables (uint8_t idx) { +uint8_t tuh_midi_get_rx_cable_count (uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; TU_VERIFY(p_midi->ep_stream.rx.ep_addr != 0, 0); - return p_midi->num_cables_rx; + return p_midi->rx_cable_count; } uint32_t tuh_midi_read_available(uint8_t idx) { @@ -410,7 +399,7 @@ uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bu uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0); midih_interface_t *p_midi = &_midi_host[idx]; - TU_VERIFY(cable_num < p_midi->num_cables_tx); + TU_VERIFY(cable_num < p_midi->tx_cable_count); midi_driver_stream_t *stream = &p_midi->stream_write; uint32_t byte_count = 0; @@ -520,7 +509,7 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff while (nread == 4 && bytes_buffered < bufsize) { *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f; uint8_t bytes_to_add_to_stream = 0; - if (*p_cable_num < p_midi->num_cables_rx) { + if (*p_cable_num < p_midi->rx_cable_count) { // ignore the CIN field; too many devices out there encode this wrong uint8_t status = p_midi->stream_read.buffer[1]; uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 717e6ba67..b06bb43d7 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -37,10 +37,6 @@ //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ -#ifndef CFG_TUH_MAX_CABLES -#define CFG_TUH_MAX_CABLES 16 -#endif - #ifndef CFG_TUH_MIDI_RX_BUFSIZE #define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MPS #endif @@ -60,7 +56,7 @@ #endif //--------------------------------------------------------------------+ -// Application API +// Application Types //--------------------------------------------------------------------+ typedef struct { const tusb_desc_interface_t* desc_audio_control; @@ -76,6 +72,17 @@ typedef struct { const uint8_t* desc_jack[16]; // list of jack descriptors (embedded + external) } tuh_midi_descriptor_cb_t; +typedef struct { + uint8_t daddr; + uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t rx_cable_count; + uint8_t tx_cable_count; +} tuh_midi_mount_cb_t; + +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + // Check if MIDI interface is mounted bool tuh_midi_mounted(uint8_t idx); @@ -84,10 +91,10 @@ bool tuh_midi_mounted(uint8_t idx); uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); // return the number of virtual midi cables on the device's IN endpoint -uint8_t tuh_midi_get_num_rx_cables(uint8_t idx); +uint8_t tuh_midi_get_rx_cable_count(uint8_t idx); // return the number of virtual midi cables on the device's OUT endpoint -uint8_t tuh_midi_get_num_tx_cables(uint8_t idx); +uint8_t tuh_midi_get_tx_cable_count(uint8_t idx); // return the raw number of bytes available. // Note: this is related but not the same as number of stream bytes available. @@ -151,16 +158,19 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff // Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. // Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. -TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb); +void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data); // Invoked when device with MIDI interface is mounted. -TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, uint8_t num_cables_rx, uint16_t num_cables_tx); +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data); // Invoked when device with MIDI interface is un-mounted -TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx); +void tuh_midi_umount_cb(uint8_t idx); -TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t num_packets); -TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx); +// Invoked when received new data +void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes); + +// Invoked when a TX is complete and therefore space becomes available in TX buffer +void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes); //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h index d27c4baa2..bfa1fb2ba 100644 --- a/src/host/usbh_pvt.h +++ b/src/host/usbh_pvt.h @@ -41,10 +41,6 @@ #define TU_LOG_INT_USBH(...) TU_LOG_INT(CFG_TUH_LOG_LEVEL, __VA_ARGS__) #define TU_LOG_HEX_USBH(...) TU_LOG_HEX(CFG_TUH_LOG_LEVEL, __VA_ARGS__) -enum { - USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS) -}; - //--------------------------------------------------------------------+ // Class Driver API //--------------------------------------------------------------------+ From 720697b6ae8208b446497cc0658f3590a3694d9d Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Thu, 27 Feb 2025 12:48:31 +0100 Subject: [PATCH 65/87] fix(esp): Remove deprecated include soc/usb_pins.h header will be deprecated in IDF v6.0 --- hw/bsp/espressif/boards/family.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c index 2f9ecfe4d..7049c0415 100644 --- a/hw/bsp/espressif/boards/family.c +++ b/hw/bsp/espressif/boards/family.c @@ -162,7 +162,6 @@ int board_getchar(void) { #if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0) #include "esp_private/usb_phy.h" -#include "soc/usb_pins.h" static usb_phy_handle_t phy_hdl; From c1df796a7c463dad43e709a2df145d6e24cd96a4 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Feb 2025 12:04:54 +0700 Subject: [PATCH 66/87] add missing board.h for BOARD=pico_sdk --- .../adafruit_feather_rp2040_usb_host/board.h | 5 +++ .../rp2040/boards/adafruit_fruit_jam/board.h | 5 +++ hw/bsp/rp2040/boards/pico_sdk/board.h | 40 +++++++++++++++++++ .../rp2040/boards/raspberry_pi_pico/board.h | 2 +- .../rp2040/boards/raspberry_pi_pico2/board.h | 2 +- 5 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 hw/bsp/rp2040/boards/pico_sdk/board.h diff --git a/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h index f36ca14c9..d003ae828 100644 --- a/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h +++ b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: Adafruit Feather RP2040 with USB Type A Host + url: https://www.adafruit.com/product/5723 +*/ + #ifndef TUSB_BOARD_H #define TUSB_BOARD_H diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h index f81da3b70..0f53fd96f 100644 --- a/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h +++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h @@ -24,6 +24,11 @@ * This file is part of the TinyUSB stack. */ +/* metadata: + name: Adafruit Fruit Jam - Mini RP2350 + url: https://www.adafruit.com/product/6200 +*/ + #ifndef TUSB_BOARD_H #define TUSB_BOARD_H diff --git a/hw/bsp/rp2040/boards/pico_sdk/board.h b/hw/bsp/rp2040/boards/pico_sdk/board.h new file mode 100644 index 000000000..284edac7d --- /dev/null +++ b/hw/bsp/rp2040/boards/pico_sdk/board.h @@ -0,0 +1,40 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h index 12c772b84..88f8793f4 100644 --- a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h @@ -26,7 +26,7 @@ /* metadata: name: Pico - url: https://www.raspberrypi.org/products/raspberry-pi-pico/ + url: https://www.raspberrypi.com/products/raspberry-pi-pico/ */ #ifndef TUSB_BOARD_H diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h index 139b58ceb..b5ce8b7e1 100644 --- a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h @@ -26,7 +26,7 @@ /* metadata: name: Pico2 - url: https://www.raspberrypi.org/products/raspberry-pi-pico/ + url: https://www.raspberrypi.com/products/raspberry-pi-pico-2/ */ #ifndef TUSB_BOARD_H From 93ff3daa116471e41615b85cd7d466cc48bc2148 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 28 Feb 2025 16:41:51 +0700 Subject: [PATCH 67/87] fix(hcd_rp2040) assert/panic endpoint already active: when a device reset while having on-going control transfer --- src/portable/raspberrypi/rp2040/hcd_rp2040.c | 46 +++++++++++--------- src/portable/raspberrypi/rp2040/rp2040_usb.c | 2 +- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 2c0a3fd49..478c6e789 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -459,28 +459,33 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) } // Close all opened endpoint belong to this device -void hcd_device_close(uint8_t rhport, uint8_t dev_addr) -{ +void hcd_device_close(uint8_t rhport, uint8_t dev_addr) { pico_trace("hcd_device_close %d\n", dev_addr); (void) rhport; - if (dev_addr == 0) return; + // reset epx if it is currently active with unplugged device + if (epx.configured && epx.active && epx.dev_addr == dev_addr) { + epx.configured = false; + *epx.endpoint_control = 0; + *epx.buffer_control = 0; + hw_endpoint_reset_transfer(&epx); + } - for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) - { - hw_endpoint_t* ep = &ep_pool[i]; + // dev0 only has ep0 + if (dev_addr != 0) { + for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) { + hw_endpoint_t *ep = &ep_pool[i]; + if (ep->dev_addr == dev_addr && ep->configured) { + // in case it is an interrupt endpoint, disable it + usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1)); + usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0; - if (ep->dev_addr == dev_addr && ep->configured) - { - // in case it is an interrupt endpoint, disable it - usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1)); - usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0; - - // unconfigure the endpoint - ep->configured = false; - *ep->endpoint_control = 0; - *ep->buffer_control = 0; - hw_endpoint_reset_transfer(ep); + // unconfigure the endpoint + ep->configured = false; + *ep->endpoint_control = 0; + *ep->buffer_control = 0; + hw_endpoint_reset_transfer(ep); + } } } } @@ -557,7 +562,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * } // If a normal transfer (non-interrupt) then initiate using - // sie ctrl registers. Otherwise interrupt ep registers should + // sie ctrl registers. Otherwise, interrupt ep registers should // already be configured if ( ep == &epx ) { @@ -597,13 +602,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet (void) rhport; // Copy data into setup packet buffer - for ( uint8_t i = 0; i < 8; i++ ) - { + for (uint8_t i = 0; i < 8; i++) { usbh_dpram->setup_packet[i] = setup_packet[i]; } // Configure EP0 struct with setup info for the trans complete - struct hw_endpoint * ep = _hw_endpoint_allocate(0); + struct hw_endpoint * ep = _hw_endpoint_allocate( (uint8_t) TUSB_XFER_CONTROL); TU_ASSERT(ep); // EPX should be inactive diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 43f48da39..9d0bd762d 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -110,7 +110,7 @@ void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoi *ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL; // 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control // Don't need delay in host mode as host is in charge - if ( !is_host_mode()) { + if (!is_host_mode()) { busy_wait_at_least_cycles(12); } } From 5f447b76ad23e8c977a5167b0b4dce93cd2980de Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 3 Mar 2025 23:22:23 +0700 Subject: [PATCH 68/87] - add tuh_descriptor_get_string_langid() API - host enumeration always get language id, manufacturer, product and serial string. Which is required by some device such as 8bitdo --- examples/host/cdc_msc_hid/src/hid_app.c | 80 +++++++++------------ src/common/tusb_types.h | 2 +- src/host/hub.c | 5 +- src/host/usbh.c | 95 +++++++++++++++++++------ src/host/usbh.h | 13 ++++ 5 files changed, 123 insertions(+), 72 deletions(-) diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c index 3f98ec89f..5bae250cf 100644 --- a/examples/host/cdc_msc_hid/src/hid_app.c +++ b/examples/host/cdc_msc_hid/src/hid_app.c @@ -39,18 +39,16 @@ static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII }; // Each HID instance can has multiple reports -static struct -{ +static struct { uint8_t report_count; tuh_hid_report_info_t report_info[MAX_REPORT]; -}hid_info[CFG_TUH_HID]; +} hid_info[CFG_TUH_HID]; static void process_kbd_report(hid_keyboard_report_t const *report); static void process_mouse_report(hid_mouse_report_t const * report); static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len); -void hid_app_task(void) -{ +void hid_app_task(void) { // nothing to do } @@ -63,64 +61,57 @@ void hid_app_task(void) // can be used to parse common/simple enough descriptor. // Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped // therefore report_desc = NULL, desc_len = 0 -void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len) -{ +void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) { printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance); // Interface protocol (hid_interface_protocol_enum_t) - const char* protocol_str[] = { "None", "Keyboard", "Mouse" }; + const char *protocol_str[] = {"None", "Keyboard", "Mouse"}; uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]); // By default host stack will use activate boot protocol on supported interface. // Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser) - if ( itf_protocol == HID_ITF_PROTOCOL_NONE ) - { + if (itf_protocol == HID_ITF_PROTOCOL_NONE) { hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len); printf("HID has %u reports \r\n", hid_info[instance].report_count); } // request to receive report // tuh_hid_report_received_cb() will be invoked when report is available - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { + if (!tuh_hid_receive_report(dev_addr, instance)) { printf("Error: cannot request to receive report\r\n"); } } // Invoked when device with hid interface is un-mounted -void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) -{ +void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); } // Invoked when received report from device via interrupt endpoint -void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ +void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance); - switch (itf_protocol) - { + switch (itf_protocol) { case HID_ITF_PROTOCOL_KEYBOARD: TU_LOG2("HID receive boot keyboard report\r\n"); - process_kbd_report( (hid_keyboard_report_t const*) report ); - break; + process_kbd_report((hid_keyboard_report_t const *) report); + break; case HID_ITF_PROTOCOL_MOUSE: TU_LOG2("HID receive boot mouse report\r\n"); - process_mouse_report( (hid_mouse_report_t const*) report ); - break; + process_mouse_report((hid_mouse_report_t const *) report); + break; default: // Generic report requires matching ReportID and contents with previous parsed report info process_generic_report(dev_addr, instance, report, len); - break; + break; } // continue to request to receive report - if ( !tuh_hid_receive_report(dev_addr, instance) ) - { + if (!tuh_hid_receive_report(dev_addr, instance)) { printf("Error: cannot request to receive report\r\n"); } } @@ -231,29 +222,24 @@ static void process_mouse_report(hid_mouse_report_t const * report) //--------------------------------------------------------------------+ // Generic Report //--------------------------------------------------------------------+ -static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len) -{ +static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { (void) dev_addr; (void) len; uint8_t const rpt_count = hid_info[instance].report_count; - tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info; - tuh_hid_report_info_t* rpt_info = NULL; + tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info; + tuh_hid_report_info_t *rpt_info = NULL; - if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0) - { + if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) { // Simple report without report ID as 1st byte rpt_info = &rpt_info_arr[0]; - }else - { + } else { // Composite report, 1st byte is report ID, data starts from 2nd byte uint8_t const rpt_id = report[0]; // Find report id in the array - for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP ) - { - switch (rpt_info->usage) - { + if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) { + switch (rpt_info->usage) { case HID_USAGE_DESKTOP_KEYBOARD: TU_LOG1("HID receive keyboard report\r\n"); // Assume keyboard follow boot report layout - process_kbd_report( (hid_keyboard_report_t const*) report ); - break; + process_kbd_report((hid_keyboard_report_t const *) report); + break; case HID_USAGE_DESKTOP_MOUSE: TU_LOG1("HID receive mouse report\r\n"); // Assume mouse follow boot report layout - process_mouse_report( (hid_mouse_report_t const*) report ); - break; + process_mouse_report((hid_mouse_report_t const *) report); + break; - default: break; + default: + break; } } } diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h index 42ce5fc12..71af132af 100644 --- a/src/common/tusb_types.h +++ b/src/common/tusb_types.h @@ -462,7 +462,7 @@ TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct typedef struct TU_ATTR_PACKED { uint8_t bLength ; ///< Size of this descriptor in bytes uint8_t bDescriptorType ; ///< Descriptor Type - uint16_t unicode_string[]; + uint16_t utf16le[]; } tusb_desc_string_t; // USB Binary Device Object Store (BOS) diff --git a/src/host/hub.c b/src/host/hub.c index 93b4a3a84..61efa8ba5 100644 --- a/src/host/hub.c +++ b/src/host/hub.c @@ -46,7 +46,7 @@ typedef struct { // from hub descriptor uint8_t bNbrPorts; - uint8_t bPwrOn2PwrGood; // port power on to good, in 2ms unit + uint8_t bPwrOn2PwrGood_2ms; // port power on to good, in 2ms unit // uint16_t wHubCharacteristics; hub_port_status_response_t port_status; @@ -279,7 +279,7 @@ static void config_set_port_power (tuh_xfer_t* xfer) { // only use number of ports in hub descriptor hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) p_epbuf->ctrl_buf; p_hub->bNbrPorts = desc_hub->bNbrPorts; - p_hub->bPwrOn2PwrGood = desc_hub->bPwrOn2PwrGood; + p_hub->bPwrOn2PwrGood_2ms = desc_hub->bPwrOn2PwrGood; // May need to GET_STATUS @@ -301,7 +301,6 @@ static void config_port_power_complete (tuh_xfer_t* xfer) { TU_MESS_FAILED(); TU_BREAKPOINT(); } - // delay bPwrOn2PwrGood * 2 ms before set configuration complete usbh_driver_set_config_complete(daddr, p_hub->itf_num); } else { // power next port diff --git a/src/host/usbh.c b/src/host/usbh.c index c7a9a868f..dcd22ee31 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -1282,13 +1282,17 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu removing_hubs |= TU_BIT(dev_id - CFG_TUH_DEVICE_MAX); } else { // Invoke callback before closing driver (maybe call it later ?) - if (tuh_umount_cb) tuh_umount_cb(daddr); + if (tuh_umount_cb) { + tuh_umount_cb(daddr); + } } // Close class driver for (uint8_t drv_id = 0; drv_id < TOTAL_DRIVER_COUNT; drv_id++) { usbh_class_driver_t const* driver = get_driver(drv_id); - if (driver) driver->close(daddr); + if (driver) { + driver->close(daddr); + } } hcd_device_close(rhport, daddr); @@ -1345,8 +1349,11 @@ enum { ENUM_HUB_GET_STATUS_2, ENUM_HUB_CLEAR_RESET_2, ENUM_SET_ADDR, - ENUM_GET_DEVICE_DESC, + ENUM_GET_STRING_LANGUAGE_ID, + ENUM_GET_STRING_MANUFACTURER, + ENUM_GET_STRING_PRODUCT, + ENUM_GET_STRING_SERIAL, ENUM_GET_9BYTE_CONFIG_DESC, ENUM_GET_FULL_CONFIG_DESC, ENUM_SET_CONFIG, @@ -1359,25 +1366,25 @@ static void enum_full_complete(void); // process device enumeration static void process_enumeration(tuh_xfer_t* xfer) { - // Retry a few times with transfers in enumeration since device can be unstable when starting up - enum { - ATTEMPT_COUNT_MAX = 3, - ATTEMPT_DELAY_MS = 100 - }; + // Retry a few times while enumerating since device can be unstable when starting up static uint8_t failed_count = 0; + if (XFER_RESULT_FAILED == xfer->result) { + enum { + ATTEMPT_COUNT_MAX = 3, + ATTEMPT_DELAY_MS = 100 + }; - if (XFER_RESULT_SUCCESS != xfer->result) { // retry if not reaching max attempt + failed_count++; bool retry = _dev0.enumerating && (failed_count < ATTEMPT_COUNT_MAX); - if ( retry ) { - failed_count++; + if (retry) { tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit - TU_LOG1("Enumeration attempt %u\r\n", failed_count); + TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX); retry = tuh_control_xfer(xfer); } if (!retry) { - enum_full_complete(); + enum_full_complete(); // complete as failed } return; @@ -1386,6 +1393,8 @@ static void process_enumeration(tuh_xfer_t* xfer) { uint8_t const daddr = xfer->daddr; uintptr_t const state = xfer->user_data; + usbh_device_t* dev = get_device(daddr); + uint16_t langid = 0x0409; // default is English switch (state) { #if CFG_TUH_HUB @@ -1476,7 +1485,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { tusb_time_delay_ms_api(2); const uint8_t new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue); - usbh_device_t* new_dev = get_device(new_addr); TU_ASSERT(new_dev,); new_dev->addressed = 1; @@ -1490,21 +1498,69 @@ static void process_enumeration(tuh_xfer_t* xfer) { // Get full device descriptor TU_LOG_USBH("Get Device Descriptor\r\n"); TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t), - process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC),); + process_enumeration, ENUM_GET_STRING_LANGUAGE_ID),); break; } - case ENUM_GET_9BYTE_CONFIG_DESC: { - tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl; - usbh_device_t* dev = get_device(daddr); + case ENUM_GET_STRING_LANGUAGE_ID: { + // save the received device descriptor TU_ASSERT(dev,); - + tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl; dev->vid = desc_device->idVendor; dev->pid = desc_device->idProduct; dev->i_manufacturer = desc_device->iManufacturer; dev->i_product = desc_device->iProduct; dev->i_serial = desc_device->iSerialNumber; + tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, + process_enumeration, ENUM_GET_STRING_MANUFACTURER); + break; + } + + case ENUM_GET_STRING_MANUFACTURER: { + TU_ASSERT(dev,); + const tusb_desc_string_t* desc_langid = (tusb_desc_string_t const*) _usbh_epbuf.ctrl; + if (desc_langid->bLength >= 4) { + langid = tu_le16toh(desc_langid->utf16le[0]); + } + if (dev->i_manufacturer != 0) { + tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, + process_enumeration, ENUM_GET_STRING_PRODUCT); + break; + } else { + TU_ATTR_FALLTHROUGH; + } + } + + case ENUM_GET_STRING_PRODUCT: { + TU_ASSERT(dev,); + if (state == ENUM_GET_STRING_PRODUCT) { + langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet + } + if (dev->i_product != 0) { + tuh_descriptor_get_string(daddr, dev->i_product, 0x0409, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, + process_enumeration, ENUM_GET_STRING_SERIAL); + break; + } else { + TU_ATTR_FALLTHROUGH; + } + } + + case ENUM_GET_STRING_SERIAL: { + TU_ASSERT(dev,); + if (state == ENUM_GET_STRING_SERIAL) { + langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet + } + if (dev->i_serial != 0) { + tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE, + process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC); + break; + } else { + TU_ATTR_FALLTHROUGH; + } + } + + case ENUM_GET_9BYTE_CONFIG_DESC: { // Get 9-byte for total length uint8_t const config_idx = CONFIG_NUM - 1; TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n"); @@ -1537,7 +1593,6 @@ static void process_enumeration(tuh_xfer_t* xfer) { case ENUM_CONFIG_DRIVER: { TU_LOG_USBH("Device configured\r\n"); - usbh_device_t* dev = get_device(daddr); TU_ASSERT(dev,); dev->configured = 1; diff --git a/src/host/usbh.h b/src/host/usbh.h index c8b137173..0fbe39743 100644 --- a/src/host/usbh.h +++ b/src/host/usbh.h @@ -265,6 +265,13 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_ bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len, tuh_xfer_cb_t complete_cb, uintptr_t user_data); +// Get language id string descriptor (control transfer) +TU_ATTR_ALWAYS_INLINE static inline +bool tuh_descriptor_get_string_langid(uint8_t daddr, void* buffer, uint16_t len, + tuh_xfer_cb_t complete_cb, uintptr_t user_data) { + return tuh_descriptor_get_string(daddr, 0, 0, buffer, len, complete_cb, user_data); +} + // Get manufacturer string descriptor (control transfer) // true on success, false if there is on-going control transfer or incorrect parameters bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len, @@ -304,6 +311,12 @@ uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8 // return transfer result uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len); +// Sync (blocking) version of tuh_descriptor_get_string_langid() +TU_ATTR_ALWAYS_INLINE static inline +uint8_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) { + return tuh_descriptor_get_string_sync(daddr, 0, 0, buffer, len); +} + // Sync (blocking) version of tuh_descriptor_get_manufacturer_string() // return transfer result uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len); From 7dbad0a23e69cde6173f09357419c4257a0ed09c Mon Sep 17 00:00:00 2001 From: hathach Date: Tue, 4 Mar 2025 22:38:17 +0700 Subject: [PATCH 69/87] add adafruit metro rp2350 --- .idea/cmake.xml | 8 +- .idea/vcs.xml | 1 + .../adafruit_metro_rp2350.h | 113 ++++++++++++++++++ .../boards/adafruit_metro_rp2350/board.cmake | 4 + .../boards/adafruit_metro_rp2350/board.h | 57 +++++++++ 5 files changed, 180 insertions(+), 3 deletions(-) create mode 100644 hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h create mode 100644 hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake create mode 100644 hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h diff --git a/.idea/cmake.xml b/.idea/cmake.xml index a792b1a05..7365e13a8 100644 --- a/.idea/cmake.xml +++ b/.idea/cmake.xml @@ -12,6 +12,8 @@ + + @@ -80,14 +82,14 @@ - + - - + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 94a25f7f4..d44b5516f 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h new file mode 100644 index 000000000..9fb9658a5 --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h @@ -0,0 +1,113 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ +#ifndef BOARDS_ADAFRUIT_METRO_RP2350_H +#define BOARDS_ADAFRUIT_METRO_RP2350_H + +// required for board that is not part of pico-sdk + +// ----------------------------------------------------- +// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO +// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES +// ----------------------------------------------------- + +// pico_cmake_set PICO_PLATFORM=rp2350 + +// On some samples, the xosc can take longer to stabilize than is usual +#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER +#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64 +#endif + +// For board detection +#define ADAFRUIT_METRO_RP2350 + +// --- RP2350 VARIANT --- +#define PICO_RP2350A 0 + +// --- UART --- +#ifndef PICO_DEFAULT_UART +#define PICO_DEFAULT_UART 0 +#endif +#ifndef PICO_DEFAULT_UART_TX_PIN +#define PICO_DEFAULT_UART_TX_PIN 0 +#endif +#ifndef PICO_DEFAULT_UART_RX_PIN +#define PICO_DEFAULT_UART_RX_PIN 1 +#endif + +// --- LED --- +#ifndef PICO_DEFAULT_LED_PIN +#define PICO_DEFAULT_LED_PIN 23 +#endif + +#ifndef PICO_DEFAULT_WS2812_PIN +#define PICO_DEFAULT_WS2812_PIN 25 +#endif + +// --- I2C --- +#ifndef PICO_DEFAULT_I2C +#define PICO_DEFAULT_I2C 0 +#endif +#ifndef PICO_DEFAULT_I2C_SDA_PIN +#define PICO_DEFAULT_I2C_SDA_PIN 20 +#endif +#ifndef PICO_DEFAULT_I2C_SCL_PIN +#define PICO_DEFAULT_I2C_SCL_PIN 21 +#endif + +// --- SPI --- +#ifndef PICO_DEFAULT_SPI +#define PICO_DEFAULT_SPI 1 +#endif +#ifndef PICO_DEFAULT_SPI_SCK_PIN +#define PICO_DEFAULT_SPI_SCK_PIN 30 +#endif +#ifndef PICO_DEFAULT_SPI_TX_PIN +#define PICO_DEFAULT_SPI_TX_PIN 31 +#endif +#ifndef PICO_DEFAULT_SPI_RX_PIN +#define PICO_DEFAULT_SPI_RX_PIN 28 +#endif + +// --- FLASH --- + +// FruitJam use w25q128 but sdk does not have .s for it, use q080 instead +#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1 + +#ifndef PICO_FLASH_SPI_CLKDIV +#define PICO_FLASH_SPI_CLKDIV 2 +#endif + +// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024) +#ifndef PICO_FLASH_SIZE_BYTES +#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024) +#endif + +// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1 +#ifndef PICO_RP2350_A2_SUPPORTED +#define PICO_RP2350_A2_SUPPORTED 1 +#endif + +#endif diff --git a/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake new file mode 100644 index 000000000..9a58821a5 --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake @@ -0,0 +1,4 @@ +set(PICO_PLATFORM rp2350-arm-s) +set(PICO_BOARD adafruit_metro_rp2350) +set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}) +#set(OPENOCD_SERIAL E6614103E78E8324) diff --git a/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h new file mode 100644 index 000000000..0b8515d1f --- /dev/null +++ b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h @@ -0,0 +1,57 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2025 Ha Thach (tinyusb.org) + * + * 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. + * + * This file is part of the TinyUSB stack. + */ + +/* metadata: + name: Adafruit Metro RP2350 + url: https://www.adafruit.com/product/6003 +*/ + +#ifndef TUSB_BOARD_H +#define TUSB_BOARD_H + +#ifdef __cplusplus + extern "C" { +#endif + +// UART and LED are already defined in pico-sdk board + +//--------------------------------------------------------------------+ +// PIO_USB +//--------------------------------------------------------------------+ +// default to pico brain tester +#define PICO_DEFAULT_PIO_USB_DP_PIN 32 +#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 29 +#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1 + +//-------------------------------------------------------------------- +// USB Host MAX3421E +//-------------------------------------------------------------------- + +#ifdef __cplusplus + } +#endif + +#endif From 102c1991d0abcfba9275830c48706ac34d7734d5 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 5 Mar 2025 22:26:28 +0700 Subject: [PATCH 70/87] rp2040: abort transfer if active in iso_activate() add hw_endpoint_abort_xfer() --- src/portable/raspberrypi/rp2040/dcd_rp2040.c | 61 +++++++++++--------- 1 file changed, 34 insertions(+), 27 deletions(-) diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index b91dd38d5..358ce84bc 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -148,6 +148,32 @@ static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t* buffer, uint16_t total_by hw_endpoint_xfer_start(ep, buffer, total_bytes); } +static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) { + // Abort any pending transfer + // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). + // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. + const uint8_t dir = tu_edpt_dir(ep->ep_addr); + const uint8_t epnum = tu_edpt_number(ep->ep_addr); + const uint32_t abort_mask = TU_BIT((epnum << 1) | (dir ? 0 : 1)); + if (rp2040_chip_version() >= 2) { + usb_hw_set->abort = abort_mask; + while ((usb_hw->abort_done & abort_mask) != abort_mask) {} + } + + uint32_t buf_ctrl = USB_BUF_CTRL_SEL; // reset to buffer 0 + if (ep->next_pid) { + buf_ctrl |= USB_BUF_CTRL_DATA1_PID; + } + + _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl); + hw_endpoint_reset_transfer(ep); + + if (rp2040_chip_version() >= 2) { + usb_hw_clear->abort_done = abort_mask; + usb_hw_clear->abort = abort_mask; + } +} + static void __tusb_irq_path_func(hw_handle_buff_status)(void) { uint32_t remaining_buffers = usb_hw->buf_status; pico_trace("buf_status = 0x%08lx\r\n", remaining_buffers); @@ -178,25 +204,10 @@ TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) { // setup transfer. Also clear a stall in case for (uint8_t dir = 0; dir < 2; dir++) { struct hw_endpoint* ep = hw_endpoint_get_by_num(0, dir); - if (ep->active) { - // Abort any pending transfer from a prior control transfer per USB specs - // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1). - // Which means we are not guaranteed to safely abort pending transfer on B0 and B1. - uint32_t const abort_mask = (dir ? USB_EP_ABORT_EP0_IN_BITS : USB_EP_ABORT_EP0_OUT_BITS); - if (rp2040_chip_version() >= 2) { - usb_hw_set->abort = abort_mask; - while ((usb_hw->abort_done & abort_mask) != abort_mask) {} - } - - _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_DATA1_PID | USB_BUF_CTRL_SEL); - hw_endpoint_reset_transfer(ep); - - if (rp2040_chip_version() >= 2) { - usb_hw_clear->abort_done = abort_mask; - usb_hw_clear->abort = abort_mask; - } - } ep->next_pid = 1u; + if (ep->active) { + hw_endpoint_abort_xfer(ep); // Abort any pending transfer per USB specs + } } } @@ -495,18 +506,14 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet // New API: Configure and enable an ISO endpoint according to descriptor bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; - const uint8_t ep_addr = ep_desc->bEndpointAddress; + struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_desc->bEndpointAddress); + TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and allocated previously - // init w/o allocate - const uint16_t mps = ep_desc->wMaxPacketSize; - uint16_t size = (uint16_t)tu_div_ceil(mps, 64) * 64u; - hw_endpoint_init(ep_addr, size, TUSB_XFER_ISOCHRONOUS); + if (ep->active) { + hw_endpoint_abort_xfer(ep); // abort any pending transfer + } - // Fill in endpoint control register with buffer offset - struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr); - TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and buffer allocated ep->wMaxPacketSize = ep_desc->wMaxPacketSize; - hw_endpoint_enable(ep); return true; } From 39e6375b74b38b01e7868c283874b3a305b524e1 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 6 Mar 2025 10:26:45 +0700 Subject: [PATCH 71/87] midi host: skip rx data with all zeroes --- examples/host/midi_rx/src/main.c | 2 +- src/class/midi/midi_host.c | 17 +++++++------ src/common/tusb_common.h | 42 ++++++++++++++++++++------------ 3 files changed, 36 insertions(+), 25 deletions(-) diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c index d26321e5d..78b1a11b9 100644 --- a/examples/host/midi_rx/src/main.c +++ b/examples/host/midi_rx/src/main.c @@ -110,7 +110,7 @@ void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { uint8_t cable_num = 0; uint32_t bytes_read = tuh_midi_stream_read(idx, &cable_num, buffer, sizeof(buffer)); - printf("Cable %u rx %lu bytes: ", cable_num, bytes_read); + printf("Cable %u rx: ", cable_num); for (uint32_t i = 0; i < bytes_read; i++) { printf("%02X ", buffer[i]); } diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index a4b1ebd2e..7f7d536d8 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -166,23 +166,24 @@ bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint (void) result; const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); TU_VERIFY(idx < CFG_TUH_MIDI); - midih_interface_t *p_midi_host = &_midi_host[idx]; + midih_interface_t *p_midi = &_midi_host[idx]; - if (ep_addr == p_midi_host->ep_stream.rx.ep_addr) { + if (ep_addr == p_midi->ep_stream.rx.ep_addr) { // receive new data, put it into FIFO and invoke callback if available - if (xferred_bytes) { - tu_edpt_stream_read_xfer_complete(&p_midi_host->ep_stream.rx, xferred_bytes); + // Note: some devices send back all zero packets even if there is no data ready + if (xferred_bytes && !tu_mem_is_zero(p_midi->ep_stream.rx.ep_buf, xferred_bytes)) { + tu_edpt_stream_read_xfer_complete(&p_midi->ep_stream.rx, xferred_bytes); tuh_midi_rx_cb(idx, xferred_bytes); } - tu_edpt_stream_read_xfer(dev_addr, &p_midi_host->ep_stream.rx); // prepare for next transfer - } else if (ep_addr == p_midi_host->ep_stream.tx.ep_addr) { + tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for next transfer + } else if (ep_addr == p_midi->ep_stream.tx.ep_addr) { tuh_midi_tx_cb(idx, xferred_bytes); - if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi_host->ep_stream.tx)) { + if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi->ep_stream.tx)) { // If there is no data left, a ZLP should be sent if // xferred_bytes is multiple of EP size and not zero - tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi_host->ep_stream.tx, xferred_bytes); + tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi->ep_stream.tx, xferred_bytes); } } diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h index 74cac965d..0351a3d8f 100644 --- a/src/common/tusb_common.h +++ b/src/common/tusb_common.h @@ -120,6 +120,22 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c return 0; } +TU_ATTR_ALWAYS_INLINE static inline bool tu_mem_is_zero(const void *buffer, size_t size) { + const uint8_t* buf8 = (const uint8_t*) buffer; + for (size_t i = 0; i < size; i++) { + if (buf8[i] != 0) { return false; } + } + return true; +} + +TU_ATTR_ALWAYS_INLINE static inline bool tu_mem_is_ff(const void *buffer, size_t size) { + const uint8_t* buf8 = (const uint8_t*) buffer; + for (size_t i = 0; i < size; i++) { + if (buf8[i] != 0xff) { return false; } + } + return true; +} + //------------- Bytes -------------// TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) { @@ -181,8 +197,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_round_up(uint32_t v, uint32_t f) // log2 of a value is its MSB's position // TODO use clz TODO remove -static inline uint8_t tu_log2(uint32_t value) -{ +TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_log2(uint32_t value) { uint8_t result = 0; while (value >>= 1) { result++; } return result; @@ -193,8 +208,7 @@ static inline uint8_t tu_log2(uint32_t value) // return sizeof(uint32_t) * CHAR_BIT - __builtin_clz(x) - 1; //} -static inline bool tu_is_power_of_two(uint32_t value) -{ +TU_ATTR_ALWAYS_INLINE static inline bool tu_is_power_of_two(uint32_t value) { return (value != 0) && ((value & (value - 1)) == 0); } @@ -205,27 +219,23 @@ static inline bool tu_is_power_of_two(uint32_t value) typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t; typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t; -TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem) -{ - tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem; +TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void *mem) { + tu_unaligned_uint32_t const *ua32 = (tu_unaligned_uint32_t const *) mem; return ua32->val; } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value) -{ - tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem; +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void *mem, uint32_t value) { + tu_unaligned_uint32_t *ua32 = (tu_unaligned_uint32_t *) mem; ua32->val = value; } -TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem) -{ - tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem; +TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) { + tu_unaligned_uint16_t const *ua16 = (tu_unaligned_uint16_t const *) mem; return ua16->val; } -TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value) -{ - tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem; +TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_t value) { + tu_unaligned_uint16_t *ua16 = (tu_unaligned_uint16_t *) mem; ua16->val = value; } From ee234a84caf59d23395ed70f5e1c9d772e3f958b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 6 Mar 2025 11:03:47 +0700 Subject: [PATCH 72/87] hack: force/overwrite endpoint mps to 64 for device that incorrectly report 512 bytes for bulk in fullspeed mode. --- src/class/midi/midi_host.c | 4 ++-- src/common/tusb_private.h | 2 +- src/device/usbd.c | 4 ++-- src/host/usbh.c | 2 +- src/tusb.c | 15 ++++++++++++--- 5 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 7f7d536d8..03144eb45 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -267,10 +267,10 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d break; case TUSB_DESC_ENDPOINT: { - tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *) p_desc; + const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *) p_desc; p_desc = tu_desc_next(p_desc); // next to CS endpoint TU_VERIFY(p_desc < p_end && tu_desc_next(p_desc) <= p_end); - midi_desc_cs_endpoint_t const *p_csep = (midi_desc_cs_endpoint_t const *) p_desc; + const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc; TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h index 445882243..31aca8a31 100644 --- a/src/common/tusb_private.h +++ b/src/common/tusb_private.h @@ -67,7 +67,7 @@ typedef struct { //--------------------------------------------------------------------+ // Check if endpoint descriptor is valid per USB specs -bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed); +bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed, bool is_host); // Bind all endpoint of a interface descriptor to class driver void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id); diff --git a/src/device/usbd.c b/src/device/usbd.c index faf926855..fb5cec49d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -1296,7 +1296,7 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) { rhport = _usbd_rhport; TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed, false)); return dcd_edpt_open(rhport, desc_ep); } @@ -1497,7 +1497,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress); TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX); - TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed)); + TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed, false)); _usbd_dev.ep_status[epnum][dir].stalled = 0; _usbd_dev.ep_status[epnum][dir].busy = 0; diff --git a/src/host/usbh.c b/src/host/usbh.c index 609fe5000..c87f058cd 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -986,7 +986,7 @@ static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size) { } bool tuh_edpt_open(uint8_t dev_addr, tusb_desc_endpoint_t const* desc_ep) { - TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr))); + TU_ASSERT(tu_edpt_validate(desc_ep, tuh_speed_get(dev_addr), true)); return hcd_edpt_open(usbh_get_rhport(dev_addr), dev_addr, desc_ep); } diff --git a/src/tusb.c b/src/tusb.c index 9303e9bc4..13b89997c 100644 --- a/src/tusb.c +++ b/src/tusb.c @@ -205,7 +205,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) { return ret; } -bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) { +bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, bool is_host) { uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep); TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size); @@ -221,8 +221,17 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) { // Bulk highspeed must be EXACTLY 512 TU_ASSERT(max_packet_size == 512); } else { - // TODO Bulk fullspeed can only be 8, 16, 32, 64 - TU_ASSERT(max_packet_size <= 64); + // Bulk fullspeed can only be 8, 16, 32, 64 + if (is_host && max_packet_size == 512) { + // HACK: while in host mode, some device incorrectly always report 512 regardless of link speed + // overwrite descriptor to force 64 + TU_LOG1(" WARN: EP max packet size is 512 in fullspeed, force to 64\r\n"); + tusb_desc_endpoint_t* hacked_ep = (tusb_desc_endpoint_t*) (uintptr_t) desc_ep; + hacked_ep->wMaxPacketSize = tu_htole16(64); + } else { + TU_ASSERT(max_packet_size == 8 || max_packet_size == 16 || + max_packet_size == 32 || max_packet_size == 64); + } } break; From 65e44e0a51272f9d75719d90955f19209dbf1ea2 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 6 Mar 2025 22:46:21 +0700 Subject: [PATCH 73/87] fix(dwc2) host driver conflict with max3421e --- examples/host/bare_api/src/tusb_config.h | 3 ++- examples/host/cdc_msc_hid/src/tusb_config.h | 3 ++- examples/host/cdc_msc_hid_freertos/src/tusb_config.h | 3 ++- examples/host/device_info/src/tusb_config.h | 3 ++- examples/host/hid_controller/src/tusb_config.h | 3 ++- examples/host/msc_file_explorer/src/tusb_config.h | 3 ++- src/portable/synopsys/dwc2/hcd_dwc2.c | 2 +- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h index fab233be0..a03675c5f 100644 --- a/examples/host/bare_api/src/tusb_config.h +++ b/examples/host/bare_api/src/tusb_config.h @@ -69,9 +69,10 @@ // Enable Host stack #define CFG_TUH_ENABLED 1 +// #define CFG_TUH_MAX3421 1 // use max3421 as host controller + #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index a59a0ffb9..cc8d6e5c4 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -69,9 +69,10 @@ // Enable Host stack #define CFG_TUH_ENABLED 1 +// #define CFG_TUH_MAX3421 1 // use max3421 as host controller + #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h index 02de4197b..682265f59 100644 --- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h @@ -74,9 +74,10 @@ // Enable Host stack #define CFG_TUH_ENABLED 1 +// #define CFG_TUH_MAX3421 1 // use max3421 as host controller + #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h index 5190b5b1f..db02a97db 100644 --- a/examples/host/device_info/src/tusb_config.h +++ b/examples/host/device_info/src/tusb_config.h @@ -74,9 +74,10 @@ // Enable Host stack #define CFG_TUH_ENABLED 1 +// #define CFG_TUH_MAX3421 1 // use max3421 as host controller + #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h index 3ac591d8f..351fe0178 100644 --- a/examples/host/hid_controller/src/tusb_config.h +++ b/examples/host/hid_controller/src/tusb_config.h @@ -69,9 +69,10 @@ // Enable Host stack #define CFG_TUH_ENABLED 1 +// #define CFG_TUH_MAX3421 1 // use max3421 as host controller + #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index c798b4383..c1829c300 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -69,9 +69,10 @@ // Enable Host stack #define CFG_TUH_ENABLED 1 +// #define CFG_TUH_MAX3421 1 // use max3421 as host controller + #if CFG_TUSB_MCU == OPT_MCU_RP2040 // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller - // #define CFG_TUH_MAX3421 1 // use max3421 as host controller // host roothub port is 1 if using either pio-usb or max3421 #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421) diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c index ebbb6200a..b13479b02 100644 --- a/src/portable/synopsys/dwc2/hcd_dwc2.c +++ b/src/portable/synopsys/dwc2/hcd_dwc2.c @@ -26,7 +26,7 @@ #include "tusb_option.h" -#if CFG_TUH_ENABLED && defined(TUP_USBIP_DWC2) +#if CFG_TUH_ENABLED && defined(TUP_USBIP_DWC2) && !CFG_TUH_MAX3421 #if !(CFG_TUH_DWC2_SLAVE_ENABLE || CFG_TUH_DWC2_DMA_ENABLE) #error DWC2 require either CFG_TUH_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled From 683b1e9702f60a8093ada3b0fdd4a7a51a05a981 Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 10 Mar 2025 11:20:47 +0700 Subject: [PATCH 74/87] fix(rp2040) set RTOS as cmake cache to fix pico-example build --- hw/bsp/family_support.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake index 562d4995b..e7161eba3 100644 --- a/hw/bsp/family_support.cmake +++ b/hw/bsp/family_support.cmake @@ -12,7 +12,7 @@ set(UF2CONV_PY ${TOP}/tools/uf2/utils/uf2conv.py) # RTOS #------------------------------------------------------------- if (NOT DEFINED RTOS) - set(RTOS noos) + set(RTOS noos CACHE STRING "RTOS") endif () #------------------------------------------------------------- From cf94b3f5fc6efdfc25b7c434852f4b04af2dddc7 Mon Sep 17 00:00:00 2001 From: "Cynventria[CitRA]" <45027522+Cynventria@users.noreply.github.com> Date: Mon, 10 Mar 2025 14:22:29 +0800 Subject: [PATCH 75/87] fix desc_end in vendord_open() minor fix on calculation of desc_end in vendord_open( ) for descriptor prasing --- src/class/vendor/vendor_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c index 6f9b4853f..2fc0ac944 100644 --- a/src/class/vendor/vendor_device.c +++ b/src/class/vendor/vendor_device.c @@ -197,7 +197,7 @@ void vendord_reset(uint8_t rhport) { uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) { TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); const uint8_t* p_desc = tu_desc_next(desc_itf); - const uint8_t* desc_end = p_desc + max_len; + const uint8_t* desc_end = (uint8_t const*)desc_itf + max_len; // Find available interface vendord_interface_t* p_vendor = NULL; From b80800f18205ae23d571438d55e078a1dcc295e8 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Thu, 13 Mar 2025 10:04:56 -0700 Subject: [PATCH 76/87] Only clear stream_read & stream_write if they are defined --- src/class/midi/midi_host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 03144eb45..4d824e04c 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -153,9 +153,10 @@ void midih_close(uint8_t daddr) { p_midi->tx_cable_count = 0; p_midi->daddr = 0; p_midi->mounted = false; +#if CFG_TUH_MIDI_STREAM_API tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write)); - +#endif tu_edpt_stream_close(&p_midi->ep_stream.rx); tu_edpt_stream_close(&p_midi->ep_stream.tx); } From ca750313b26254c3fbc66152b5e0ed9dfe415630 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 15 Mar 2025 21:15:52 +0100 Subject: [PATCH 77/87] Update gitignore. Signed-off-by: HiFiPhile --- .gitignore | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitignore b/.gitignore index f981110b2..5638a09db 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,14 @@ latex *.jlink *.emSession *.ninja* +*.eww +*.ewp +*.ewt +*.ewd +*.hex +cmake_install.cmake +CMakeCache.txt +settings/ .settings/ .vscode/ .gdb_history From de45e4b01a55182f494577a8bf8b46ad51d6eb9f Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sat, 15 Mar 2025 23:49:11 +0100 Subject: [PATCH 78/87] Add ctrl buffer alignment. Signed-off-by: HiFiPhile --- src/class/audio/audio_device.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c index 388168424..7a6fd453f 100644 --- a/src/class/audio/audio_device.c +++ b/src/class/audio/audio_device.c @@ -208,15 +208,15 @@ tu_static CFG_TUD_MEM_SECTION struct { #endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING) // Control buffers -tu_static uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ]; - -#if CFG_TUD_AUDIO > 1 -tu_static uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ]; -#endif - -#if CFG_TUD_AUDIO > 2 -tu_static uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ]; -#endif +tu_static CFG_TUD_MEM_SECTION struct { + TUD_EPBUF_DEF(buf1, CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ); + #if CFG_TUD_AUDIO > 1 + TUD_EPBUF_DEF(buf2, CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ); + #endif + #if CFG_TUD_AUDIO > 2 + TUD_EPBUF_DEF(buf3, CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ); + #endif +} ctrl_buf; // Active alternate setting of interfaces tu_static uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT]; @@ -1223,18 +1223,18 @@ void audiod_init(void) { // Initialize control buffers switch (i) { case 0: - audio->ctrl_buf = ctrl_buf_1; + audio->ctrl_buf = ctrl_buf.buf1; audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ; break; #if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0 case 1: - audio->ctrl_buf = ctrl_buf_2; + audio->ctrl_buf = ctrl_buf.buf2; audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ; break; #endif #if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0 case 2: - audio->ctrl_buf = ctrl_buf_3; + audio->ctrl_buf = ctrl_buf.buf3; audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ; break; #endif From 585bcbfcdd5e24e25dd8d42b51446824b8143602 Mon Sep 17 00:00:00 2001 From: HiFiPhile Date: Sun, 16 Mar 2025 00:07:15 +0100 Subject: [PATCH 79/87] Fix 2 IAR warnings. Signed-off-by: HiFiPhile --- src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 7d5cfb5b0..7c637ce0c 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -297,7 +297,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) { dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, TU_BIT(22)); // 22-bit alignment - dcd_reg->INTSTAT |= dcd_reg->INTSTAT; // clear all pending interrupt + dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt dcd_reg->INTEN = INT_DEVICE_STATUS_MASK; dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_DEVICE_ENABLE_MASK | DEVCMDSTAT_DEVICE_CONNECT_MASK | DEVCMDSTAT_RESET_CHANGE_MASK | DEVCMDSTAT_CONNECT_CHANGE_MASK | DEVCMDSTAT_SUSPEND_CHANGE_MASK; @@ -563,7 +563,8 @@ void dcd_int_handler(uint8_t rhport) uint32_t const cmd_stat = dcd_reg->DEVCMDSTAT; - uint32_t int_status = dcd_reg->INTSTAT & dcd_reg->INTEN; + uint32_t int_status = dcd_reg->INTSTAT; + int_status &= dcd_reg->INTEN; dcd_reg->INTSTAT = int_status; // Acknowledge handled interrupt if (int_status == 0) return; From e0df20f260a6c5d5e347427e9e57e73f9327f8d0 Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Mon, 17 Mar 2025 12:20:49 +0700 Subject: [PATCH 80/87] change pio-usb to upstream --- tools/get_deps.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/get_deps.py b/tools/get_deps.py index b82abac4f..3f529bd7e 100755 --- a/tools/get_deps.py +++ b/tools/get_deps.py @@ -58,8 +58,8 @@ deps_optional = { 'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git', '144f1eb7ea8c06512e12f12b27383601c0272410', 'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'], - 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git', - '9c8df3083b62c0a678f3bd3d8a7e773932622d4b', + 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git', + '0ca3657d55ea20e7fa4483bbd21ce951bc1d6fa5', 'rp2040'], 'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git', 'edcc97d684b6f716728a60d7a6fea049d9870bd6', From 31b3a2f63bcf4f1969ada9d0c099444959b37388 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Sat, 15 Mar 2025 11:20:57 -0700 Subject: [PATCH 81/87] Fix 3031: implement tuh_midi_itf_get_info() --- src/class/midi/midi_host.c | 23 +++++++++++++++++++++++ src/class/midi/midi_host.h | 4 ++++ 2 files changed, 27 insertions(+) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 4d824e04c..9019d476b 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -346,6 +346,29 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { return TUSB_INDEX_INVALID_8; } +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) +{ + midih_interface_t* p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi && info); + + info->daddr = p_midi->daddr; + + // re-construct descriptor + tusb_desc_interface_t* desc = &info->desc; + desc->bLength = sizeof(tusb_desc_interface_t); + desc->bDescriptorType = TUSB_DESC_INTERFACE; + + desc->bInterfaceNumber = p_midi->bInterfaceNumber; + desc->bAlternateSetting = 0; + desc->bNumEndpoints = (p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0); + desc->bInterfaceClass = TUSB_CLASS_AUDIO; + desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; + desc->bInterfaceProtocol = 0; + desc->iInterface = 0; + + return true; +} + uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) { TU_VERIFY(idx < CFG_TUH_MIDI); midih_interface_t *p_midi = &_midi_host[idx]; diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index b06bb43d7..67df25a82 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -90,6 +90,10 @@ bool tuh_midi_mounted(uint8_t idx); // return TUSB_INDEX_INVALID_8 (0xFF) if not found uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); +// Get Interface information +// return true if index is correct and interface is currently mounted +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info); + // return the number of virtual midi cables on the device's IN endpoint uint8_t tuh_midi_get_rx_cable_count(uint8_t idx); From 5ecea4eefe13ea93095da710dfcf3b3fee578c8e Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Tue, 18 Mar 2025 07:41:49 -0700 Subject: [PATCH 82/87] fix tuh_midi_itf_get_info() desc->iInterface value --- src/class/midi/midi_host.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 9019d476b..d6d204b7b 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -82,6 +82,7 @@ typedef struct { } ep_stream; bool mounted; + uint8_t iInterface; // for tuh_midi_itf_get_info() }midih_interface_t; typedef struct { @@ -228,6 +229,7 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; + p_midi->iInterface = desc_itf->iInterface; p_midi->itf_count++; desc_cb.desc_midi = desc_itf; @@ -346,8 +348,7 @@ uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { return TUSB_INDEX_INVALID_8; } -bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) -{ +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { midih_interface_t* p_midi = &_midi_host[idx]; TU_VERIFY(p_midi && info); @@ -364,7 +365,7 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) desc->bInterfaceClass = TUSB_CLASS_AUDIO; desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; desc->bInterfaceProtocol = 0; - desc->iInterface = 0; + desc->iInterface = p_midi->iInterface; return true; } From 62f00bdf5d8b2a5941aed3d96865bbe24b117455 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Tue, 18 Mar 2025 07:42:47 -0700 Subject: [PATCH 83/87] Fix compiler conversion error warning --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index d6d204b7b..85253f5ca 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -361,7 +361,7 @@ bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { desc->bInterfaceNumber = p_midi->bInterfaceNumber; desc->bAlternateSetting = 0; - desc->bNumEndpoints = (p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0); + desc->bNumEndpoints = (uint8_t)((p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0)); desc->bInterfaceClass = TUSB_CLASS_AUDIO; desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; desc->bInterfaceProtocol = 0; From 05e4f8b77786a6bbc4a43e3b8574689714ca3138 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Wed, 19 Mar 2025 05:57:01 -0700 Subject: [PATCH 84/87] Move iInterface per review comment --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 85253f5ca..cfea0c080 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -56,6 +56,7 @@ TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) i typedef struct { uint8_t daddr; uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t iInterface; uint8_t itf_count; // number of interface including Audio Control + MIDI streaming uint8_t ep_in; // IN endpoint address @@ -82,7 +83,6 @@ typedef struct { } ep_stream; bool mounted; - uint8_t iInterface; // for tuh_midi_itf_get_info() }midih_interface_t; typedef struct { From 4b46493cb4f8699c95e01783eee5cf90ca7810e2 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Thu, 20 Mar 2025 06:27:23 -0700 Subject: [PATCH 85/87] Fix #3033: Increase array bounds and test for overflow --- src/class/midi/midi_host.c | 3 ++- src/class/midi/midi_host.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index cfea0c080..68e46aca3 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -254,7 +254,8 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV(" Jack %s %s descriptor \r\n", tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; + if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) + desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; break; } diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h index 67df25a82..06554a03d 100644 --- a/src/class/midi/midi_host.h +++ b/src/class/midi/midi_host.h @@ -69,7 +69,7 @@ typedef struct { const tusb_desc_endpoint_t* desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after uint8_t jack_num; - const uint8_t* desc_jack[16]; // list of jack descriptors (embedded + external) + const uint8_t* desc_jack[32]; // list of jack descriptors (embedded + external) } tuh_midi_descriptor_cb_t; typedef struct { From b0def52f45439c3dc41a0c370115deb54cd443e4 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Fri, 21 Mar 2025 07:13:01 -0700 Subject: [PATCH 86/87] Move misplaced statement --- src/class/midi/midi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index 68e46aca3..b252e8466 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -591,8 +591,8 @@ uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buff break; default: break; - cable_sysex_in_progress &= (uint16_t) ~cable_mask; } + cable_sysex_in_progress &= (uint16_t) ~cable_mask; } else { // Real-time message: can be inserted into a sysex message, // so do don't clear cable_sysex_in_progress bit From 3324a327cbd82d18305030ba2247cbbc71dc9f19 Mon Sep 17 00:00:00 2001 From: rppicomidi Date: Fri, 21 Mar 2025 07:14:10 -0700 Subject: [PATCH 87/87] Fix #3033: address review comment --- src/class/midi/midi_host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c index b252e8466..cd6e115ee 100644 --- a/src/class/midi/midi_host.c +++ b/src/class/midi/midi_host.c @@ -254,8 +254,9 @@ bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *d TU_LOG_DRV(" Jack %s %s descriptor \r\n", tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) + if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) { desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; + } break; }