mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-31 05:52:55 +08:00
commit
2dd8dba4a7
@ -50,8 +50,8 @@ The stack supports the following MCUs
|
||||
|
||||
- **Nordic:** nRF52840
|
||||
- **NXP:** LPC11Uxx, LPC13xx, LPC175x_6x, LPC177x_8x, LPC18xx, LPC40xx, LPC43xx
|
||||
- **MicroChip:** SAMD21, SAMD51
|
||||
- **ST:** STM32F4
|
||||
- **MicroChip:** SAMD21, SAMD51 (device only)
|
||||
- **ST:** STM32F4 (device only)
|
||||
|
||||
[Here is the list of supported Boards](docs/boards.md)
|
||||
|
||||
|
@ -25,6 +25,7 @@ This code base already had supported for a handful of following boards
|
||||
|
||||
### MicroChip SAMD
|
||||
|
||||
- [Adafruit Feather M4 Express](https://www.adafruit.com/product/3857)
|
||||
- [Adafruit Metro M0 Express](https://www.adafruit.com/product/3505)
|
||||
- [Adafruit Metro M4 Express](https://www.adafruit.com/product/3382)
|
||||
|
||||
|
@ -263,7 +263,7 @@ void led_blinking_task(void)
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every 1000 ms
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
|
||||
start_ms += blink_interval_ms;
|
||||
|
||||
|
@ -79,25 +79,16 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_CUSTOM_CLASS 0
|
||||
|
||||
//------------- CDC -------------//
|
||||
|
||||
// FIFO size of CDC TX and RX
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE 64
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE 64
|
||||
|
||||
//------------- MSC -------------//
|
||||
|
||||
// Buffer size of Device Mass storage
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_BUFSIZE 512
|
||||
|
||||
//------------- HID -------------//
|
||||
|
||||
// Should be sufficient to hold ID (if any) + Data
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_BUFSIZE 16
|
||||
|
||||
#define CFG_TUD_MIDI_RX_BUFSIZE 512
|
||||
#define CFG_TUD_MIDI_TX_BUFSIZE 512
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -32,7 +32,7 @@
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) )
|
||||
|
||||
//------------- Device Descriptors -------------//
|
||||
tusb_desc_device_t const desc_device =
|
||||
@ -188,6 +188,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
@ -79,20 +79,14 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_CUSTOM_CLASS 0
|
||||
|
||||
//------------- CDC -------------//
|
||||
|
||||
// FIFO size of CDC TX and RX
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE 64
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE 64
|
||||
|
||||
//------------- MSC -------------//
|
||||
|
||||
// Buffer size of Device Mass storage
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_BUFSIZE 512
|
||||
|
||||
//------------- HID -------------//
|
||||
|
||||
// Should be sufficient to hold ID (if any) + Data
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_BUFSIZE 16
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -32,7 +32,7 @@
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) )
|
||||
|
||||
//------------- Device Descriptors -------------//
|
||||
tusb_desc_device_t const desc_device =
|
||||
@ -126,7 +126,7 @@ enum
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Inteface count, string index, total length, attribute, power in mA
|
||||
// interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
#if CFG_TUD_CDC
|
||||
@ -189,6 +189,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
@ -154,7 +154,7 @@ void led_blinking_task(void)
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every 1000 ms
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
|
||||
start_ms += blink_interval_ms;
|
||||
|
||||
|
@ -78,9 +78,7 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_CUSTOM_CLASS 0
|
||||
|
||||
//------------- HID -------------//
|
||||
|
||||
// Should be sufficient to hold ID (if any) + Data
|
||||
// HID buffer size Should be sufficient to hold ID (if any) + Data
|
||||
#define CFG_TUD_HID_BUFSIZE 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -32,7 +32,7 @@
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) )
|
||||
|
||||
//------------- Device Descriptors -------------//
|
||||
tusb_desc_device_t const desc_device =
|
||||
@ -81,7 +81,7 @@ enum
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Inteface count, string index, total length, attribute, power in mA
|
||||
// interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||
@ -138,6 +138,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
12
examples/device/midi_test/Makefile
Normal file
12
examples/device/midi_test/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
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
|
167
examples/device/midi_test/src/main.c
Normal file
167
examples/device/midi_test/src/main.c
Normal file
@ -0,0 +1,167 @@
|
||||
/*
|
||||
* 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 <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bsp/board.h"
|
||||
#include "tusb.h"
|
||||
|
||||
/* This MIDI example send sequence of note (on/off) repeatedly. To test on PC, you need to install
|
||||
* synth software and midi connection management software. On
|
||||
* - Linux (Ubuntu) : install qsynth, qjackctl. Then connect TinyUSB output port to FLUID Synth input port
|
||||
*
|
||||
*/
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF PROTYPES
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/* Blink pattern
|
||||
* - 250 ms : device not mounted
|
||||
* - 1000 ms : device mounted
|
||||
* - 2500 ms : device is suspended
|
||||
*/
|
||||
enum {
|
||||
BLINK_NOT_MOUNTED = 250,
|
||||
BLINK_MOUNTED = 1000,
|
||||
BLINK_SUSPENDED = 2500,
|
||||
};
|
||||
|
||||
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
|
||||
void led_blinking_task(void);
|
||||
void midi_task(void);
|
||||
|
||||
/*------------- MAIN -------------*/
|
||||
int main(void)
|
||||
{
|
||||
board_init();
|
||||
|
||||
tusb_init();
|
||||
|
||||
while (1)
|
||||
{
|
||||
// tinyusb device task
|
||||
tud_task();
|
||||
|
||||
led_blinking_task();
|
||||
|
||||
midi_task();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Device callbacks
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when device is mounted
|
||||
void tud_mount_cb(void)
|
||||
{
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
// Invoked when device is unmounted
|
||||
void tud_umount_cb(void)
|
||||
{
|
||||
blink_interval_ms = BLINK_NOT_MOUNTED;
|
||||
}
|
||||
|
||||
// Invoked when usb bus is suspended
|
||||
// remote_wakeup_en : if host allow us to perform remote wakeup
|
||||
// Within 7ms, device must draw an average of current less than 2.5 mA from bus
|
||||
void tud_suspend_cb(bool remote_wakeup_en)
|
||||
{
|
||||
(void) remote_wakeup_en;
|
||||
blink_interval_ms = BLINK_SUSPENDED;
|
||||
}
|
||||
|
||||
// Invoked when usb bus is resumed
|
||||
void tud_resume_cb(void)
|
||||
{
|
||||
blink_interval_ms = BLINK_MOUNTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MIDI Task
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Variable that holds the current position in the sequence.
|
||||
uint32_t note_pos = 0;
|
||||
|
||||
// Store example melody as an array of note values
|
||||
uint8_t note_sequence[] =
|
||||
{
|
||||
74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78,
|
||||
74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61,
|
||||
56,61,64,68,74,78,81,86,90,93,98,102
|
||||
};
|
||||
|
||||
void midi_task(void)
|
||||
{
|
||||
static uint32_t start_ms = 0;
|
||||
|
||||
// send note every 1000 ms
|
||||
if (board_millis() - start_ms < 286) return; // not enough time
|
||||
start_ms += 286;
|
||||
|
||||
// Previous positions in the note sequence.
|
||||
int previous = note_pos - 1;
|
||||
|
||||
// If we currently are at position 0, set the
|
||||
// previous position to the last note in the sequence.
|
||||
if (previous < 0) previous = sizeof(note_sequence) - 1;
|
||||
|
||||
// Send Note On for current position at full velocity (127) on channel 1.
|
||||
tudi_midi_write24(0, 0x90, note_sequence[note_pos], 127);
|
||||
|
||||
// Send Note Off for previous note.
|
||||
tudi_midi_write24(0, 0x80, note_sequence[previous], 0);
|
||||
|
||||
// Increment position
|
||||
note_pos++;
|
||||
|
||||
// If we are at the end of the sequence, start over.
|
||||
if (note_pos >= sizeof(note_sequence)) note_pos = 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// BLINKING TASK
|
||||
//--------------------------------------------------------------------+
|
||||
void led_blinking_task(void)
|
||||
{
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
|
||||
start_ms += blink_interval_ms;
|
||||
|
||||
board_led_write(led_state);
|
||||
led_state = 1 - led_state; // toggle
|
||||
}
|
89
examples/device/midi_test/src/tusb_config.h
Normal file
89
examples/device/midi_test/src/tusb_config.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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
|
||||
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED)
|
||||
#else
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE
|
||||
#endif
|
||||
|
||||
#define CFG_TUSB_OS OPT_OS_NONE
|
||||
|
||||
// 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 TU_ATTR_ALIGNED(4)
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// DEVICE CONFIGURATION
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
#define CFG_TUD_ENDOINT0_SIZE 64
|
||||
|
||||
//------------- CLASS -------------//
|
||||
#define CFG_TUD_CDC 0
|
||||
#define CFG_TUD_MSC 0
|
||||
#define CFG_TUD_HID 0
|
||||
#define CFG_TUD_MIDI 1
|
||||
#define CFG_TUD_CUSTOM_CLASS 0
|
||||
|
||||
// MIDI FIFO size of TX and RX
|
||||
#define CFG_TUD_MIDI_RX_BUFSIZE 64
|
||||
#define CFG_TUD_MIDI_TX_BUFSIZE 64
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_CONFIG_H_ */
|
149
examples/device/midi_test/src/usb_descriptors.c
Normal file
149
examples/device/midi_test/src/usb_descriptors.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 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 "tusb.h"
|
||||
|
||||
/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||
*
|
||||
* Auto ProductID layout's Bitmap:
|
||||
* [MSB] MIDI | HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) )
|
||||
|
||||
//------------- Device Descriptors -------------//
|
||||
tusb_desc_device_t const desc_device =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_device_t),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
// Use Interface Association Descriptor (IAD) for Audio
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idProduct = USB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
//------------- Configuration Descriptor -------------//
|
||||
enum
|
||||
{
|
||||
ITF_NUM_MIDI = 0,
|
||||
ITF_NUM_MIDI_STREAMING,
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CONFIG_TOTAL_LEN = TUD_CONFIG_DESC_LEN + TUD_MIDI_DESC_LEN
|
||||
};
|
||||
|
||||
// Use Endpoint 2 instead of 1 due to NXP MCU
|
||||
// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
|
||||
// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ...
|
||||
#define EPNUM_MIDI 0x02
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64)
|
||||
};
|
||||
|
||||
// Invoked when received GET DEVICE DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
uint8_t const * tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *) &desc_device;
|
||||
}
|
||||
|
||||
// Invoked when received GET CONFIGURATION DESCRIPTOR
|
||||
// Application return pointer to descriptor
|
||||
// Descriptor contents must exist long enough for transfer to complete
|
||||
uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void) index; // for multiple configurations
|
||||
return desc_configuration;
|
||||
}
|
||||
|
||||
//------------- String Descriptors -------------//
|
||||
|
||||
// array of pointer to string descriptors
|
||||
char const* string_desc_arr [] =
|
||||
{
|
||||
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
"123456", // 3: Serials, should use chip ID
|
||||
};
|
||||
|
||||
static uint16_t _desc_str[32];
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint16_t const* tud_descriptor_string_cb(uint8_t index)
|
||||
{
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0)
|
||||
{
|
||||
memcpy(&_desc_str[1], string_desc_arr[0], 2);
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
||||
// Cap at max char
|
||||
chr_count = strlen(str);
|
||||
if ( chr_count > 31 ) chr_count = 31;
|
||||
|
||||
for(uint8_t i=0; i<chr_count; i++)
|
||||
{
|
||||
_desc_str[1+i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is len, second byte is string type
|
||||
_desc_str[0] = TUD_DESC_STR_HEADER(chr_count);
|
||||
|
||||
return _desc_str;
|
||||
}
|
@ -106,7 +106,7 @@ void led_blinking_task(void)
|
||||
static uint32_t start_ms = 0;
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every 1000 ms
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time
|
||||
start_ms += blink_interval_ms;
|
||||
|
||||
|
@ -78,9 +78,7 @@
|
||||
#define CFG_TUD_MIDI 0
|
||||
#define CFG_TUD_CUSTOM_CLASS 0
|
||||
|
||||
//------------- MSC -------------//
|
||||
|
||||
// Buffer size of Device Mass storage
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_BUFSIZE 512
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -32,7 +32,7 @@
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) )
|
||||
#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) )
|
||||
|
||||
//------------- Device Descriptors -------------//
|
||||
tusb_desc_device_t const desc_device =
|
||||
@ -75,7 +75,7 @@ enum
|
||||
|
||||
uint8_t const desc_configuration[] =
|
||||
{
|
||||
// Inteface count, string index, total length, attribute, power in mA
|
||||
// interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
@ -123,6 +123,8 @@ uint16_t const* tud_descriptor_string_cb(uint8_t index)
|
||||
chr_count = 1;
|
||||
}else
|
||||
{
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
|
||||
|
||||
const char* str = string_desc_arr[index];
|
||||
|
@ -169,7 +169,7 @@ void led_blinking_task(void)
|
||||
|
||||
static bool led_state = false;
|
||||
|
||||
// Blink every 1000 ms
|
||||
// Blink every interval ms
|
||||
if ( board_millis() - start_ms < interval_ms) return; // not enough time
|
||||
start_ms += interval_ms;
|
||||
|
||||
|
47
hw/bsp/feather_m4_express/board.mk
Normal file
47
hw/bsp/feather_m4_express/board.mk
Normal file
@ -0,0 +1,47 @@
|
||||
CFLAGS += \
|
||||
-D__SAMD51J19A__ \
|
||||
-mthumb \
|
||||
-mabi=aapcs-linux \
|
||||
-mcpu=cortex-m4 \
|
||||
-mfloat-abi=hard \
|
||||
-mfpu=fpv4-sp-d16 \
|
||||
-nostdlib -nostartfiles \
|
||||
-DCFG_TUSB_MCU=OPT_MCU_SAMD51
|
||||
|
||||
CFLAGS += -Wno-error=undef
|
||||
|
||||
# All source paths should be relative to the top level.
|
||||
LD_FILE = hw/bsp/metro_m4_express/samd51g19a_flash.ld
|
||||
|
||||
SRC_C += \
|
||||
hw/mcu/microchip/samd/asf4/samd51/gcc/gcc/startup_samd51.c \
|
||||
hw/mcu/microchip/samd/asf4/samd51/gcc/system_samd51.c \
|
||||
hw/mcu/microchip/samd/asf4/samd51/hpl/gclk/hpl_gclk.c \
|
||||
hw/mcu/microchip/samd/asf4/samd51/hpl/mclk/hpl_mclk.c \
|
||||
hw/mcu/microchip/samd/asf4/samd51/hpl/osc32kctrl/hpl_osc32kctrl.c \
|
||||
hw/mcu/microchip/samd/asf4/samd51/hpl/oscctrl/hpl_oscctrl.c \
|
||||
hw/mcu/microchip/samd/asf4/samd51/hal/src/hal_atomic.c
|
||||
|
||||
INC += \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/ \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/config \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/include \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hal/include \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hal/utils/include \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hpl/port \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/hri \
|
||||
$(TOP)/hw/mcu/microchip/samd/asf4/samd51/CMSIS/Include
|
||||
|
||||
# For TinyUSB port source
|
||||
VENDOR = microchip
|
||||
CHIP_FAMILY = samd51
|
||||
|
||||
# For freeRTOS port source
|
||||
FREERTOS_PORT = ARM_CM4F
|
||||
|
||||
# For flash-jlink target
|
||||
JLINK_DEVICE = ATSAMD51J19
|
||||
JLINK_IF = swd
|
||||
|
||||
# flash using jlink
|
||||
flash: flash-jlink
|
120
hw/bsp/feather_m4_express/board_feather_m4_express.c
Normal file
120
hw/bsp/feather_m4_express/board_feather_m4_express.c
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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 "bsp/board.h"
|
||||
|
||||
#include "sam.h"
|
||||
#include "hal/include/hal_gpio.h"
|
||||
#include "hal/include/hal_init.h"
|
||||
#include "hpl/gclk/hpl_gclk_base.h"
|
||||
#include "hpl_mclk_config.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#define LED_PIN 23
|
||||
#define BUTTON_PIN 22 // pin D12
|
||||
|
||||
/* Referenced GCLKs, should be initialized firstly */
|
||||
#define _GCLK_INIT_1ST 0xFFFFFFFF
|
||||
|
||||
/* Not referenced GCLKs, initialized last */
|
||||
#define _GCLK_INIT_LAST (~_GCLK_INIT_1ST)
|
||||
|
||||
void board_init(void)
|
||||
{
|
||||
// Clock init ( follow hpl_init.c )
|
||||
hri_nvmctrl_set_CTRLA_RWS_bf(NVMCTRL, 0);
|
||||
|
||||
_osc32kctrl_init_sources();
|
||||
_oscctrl_init_sources();
|
||||
_mclk_init();
|
||||
#if _GCLK_INIT_1ST
|
||||
_gclk_init_generators_by_fref(_GCLK_INIT_1ST);
|
||||
#endif
|
||||
_oscctrl_init_referenced_generators();
|
||||
_gclk_init_generators_by_fref(_GCLK_INIT_LAST);
|
||||
|
||||
// Led init
|
||||
gpio_set_pin_direction(LED_PIN, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(LED_PIN, 0);
|
||||
|
||||
// Button init
|
||||
gpio_set_pin_direction(BUTTON_PIN, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BUTTON_PIN, GPIO_PULL_UP);
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
// 1ms tick timer (samd SystemCoreClock may not correct)
|
||||
SysTick_Config(CONF_CPU_FREQUENCY / 1000);
|
||||
#endif
|
||||
|
||||
/* USB Clock init
|
||||
* The USB module requires a GCLK_USB of 48 MHz ~ 0.25% clock
|
||||
* for low speed and full speed operation. */
|
||||
hri_gclk_write_PCHCTRL_reg(GCLK, USB_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK1_Val | GCLK_PCHCTRL_CHEN);
|
||||
hri_mclk_set_AHBMASK_USB_bit(MCLK);
|
||||
hri_mclk_set_APBBMASK_USB_bit(MCLK);
|
||||
|
||||
// USB Pin Init
|
||||
gpio_set_pin_direction(PIN_PA24, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA24, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA24, GPIO_PULL_OFF);
|
||||
gpio_set_pin_direction(PIN_PA25, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(PIN_PA25, false);
|
||||
gpio_set_pin_pull_mode(PIN_PA25, GPIO_PULL_OFF);
|
||||
|
||||
gpio_set_pin_function(PIN_PA24, PINMUX_PA24H_USB_DM);
|
||||
gpio_set_pin_function(PIN_PA25, PINMUX_PA25H_USB_DP);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Board porting API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
void board_led_write(bool state)
|
||||
{
|
||||
gpio_set_pin_level(LED_PIN, state);
|
||||
}
|
||||
|
||||
uint32_t board_button_read(void)
|
||||
{
|
||||
// button is active low
|
||||
return gpio_get_pin_level(BUTTON_PIN) ? 0 : 1;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||
volatile uint32_t system_ticks = 0;
|
||||
|
||||
void SysTick_Handler (void)
|
||||
{
|
||||
system_ticks++;
|
||||
}
|
||||
|
||||
uint32_t board_millis(void)
|
||||
{
|
||||
return system_ticks;
|
||||
}
|
||||
#endif
|
164
hw/bsp/feather_m4_express/samd51g19a_flash.ld
Normal file
164
hw/bsp/feather_m4_express/samd51g19a_flash.ld
Normal file
@ -0,0 +1,164 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Linker script for running in internal FLASH on the SAMD51G19A
|
||||
*
|
||||
* Copyright (c) 2017 Microchip Technology Inc.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the Licence at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
SEARCH_DIR(.)
|
||||
|
||||
/* Memory Spaces Definitions */
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x00000000 + 16K, LENGTH = 0x00080000 - 16K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00030000
|
||||
bkupram (rwx) : ORIGIN = 0x47000000, LENGTH = 0x00002000
|
||||
qspi (rwx) : ORIGIN = 0x04000000, LENGTH = 0x01000000
|
||||
}
|
||||
|
||||
/* The stack size used by the application. NOTE: you need to adjust according to your application. */
|
||||
STACK_SIZE = DEFINED(STACK_SIZE) ? STACK_SIZE : DEFINED(__stack_size__) ? __stack_size__ : 0xC000;
|
||||
|
||||
/* Section Definitions */
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sfixed = .;
|
||||
KEEP(*(.vectors .vectors.*))
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
*(.glue_7t) *(.glue_7)
|
||||
*(.rodata .rodata* .gnu.linkonce.r.*)
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
|
||||
/* Support C constructors, and C destructors in both user code
|
||||
and the C library. This also provides support for C++ code. */
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.init))
|
||||
. = ALIGN(4);
|
||||
__preinit_array_start = .;
|
||||
KEEP (*(.preinit_array))
|
||||
__preinit_array_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
__init_array_start = .;
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
__init_array_end = .;
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP (*crtbegin.o(.ctors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*crtend.o(.ctors))
|
||||
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.fini))
|
||||
|
||||
. = ALIGN(4);
|
||||
__fini_array_start = .;
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
__fini_array_end = .;
|
||||
|
||||
KEEP (*crtbegin.o(.dtors))
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
|
||||
. = ALIGN(4);
|
||||
_efixed = .; /* End of text section */
|
||||
} > rom
|
||||
|
||||
/* .ARM.exidx is sorted, so has to go in its own output section. */
|
||||
PROVIDE_HIDDEN (__exidx_start = .);
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > rom
|
||||
PROVIDE_HIDDEN (__exidx_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .;
|
||||
|
||||
.relocate : AT (_etext)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_srelocate = .;
|
||||
*(.ramfunc .ramfunc.*);
|
||||
*(.data .data.*);
|
||||
. = ALIGN(4);
|
||||
_erelocate = .;
|
||||
} > ram
|
||||
|
||||
.bkupram (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sbkupram = .;
|
||||
*(.bkupram .bkupram.*);
|
||||
. = ALIGN(8);
|
||||
_ebkupram = .;
|
||||
} > bkupram
|
||||
|
||||
.qspi (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sqspi = .;
|
||||
*(.qspi .qspi.*);
|
||||
. = ALIGN(8);
|
||||
_eqspi = .;
|
||||
} > qspi
|
||||
|
||||
/* .bss section which is used for uninitialized data */
|
||||
.bss (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
_sbss = . ;
|
||||
_szero = .;
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
_ebss = . ;
|
||||
_ezero = .;
|
||||
end = .;
|
||||
} > ram
|
||||
|
||||
/* stack section */
|
||||
.stack (NOLOAD):
|
||||
{
|
||||
. = ALIGN(8);
|
||||
_sstack = .;
|
||||
. = . + STACK_SIZE;
|
||||
. = ALIGN(8);
|
||||
_estack = .;
|
||||
} > ram
|
||||
|
||||
. = ALIGN(4);
|
||||
_end = . ;
|
||||
}
|
@ -36,7 +36,7 @@
|
||||
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
|
||||
//--------------------------------------------------------------------+
|
||||
#define LED_PIN 16
|
||||
#define BUTTON_PIN (32 + 17) // pin D2
|
||||
#define BUTTON_PIN 17 // pin D12
|
||||
|
||||
/* Referenced GCLKs, should be initialized firstly */
|
||||
#define _GCLK_INIT_1ST 0xFFFFFFFF
|
||||
|
@ -29,8 +29,8 @@
|
||||
* Currently only MIDI subclass is supported
|
||||
* @{ */
|
||||
|
||||
#ifndef _TUSB_CDC_H__
|
||||
#define _TUSB_CDC_H__
|
||||
#ifndef _TUSB_AUDIO_H__
|
||||
#define _TUSB_AUDIO_H__
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
|
||||
@ -41,9 +41,9 @@
|
||||
/// Audio Interface Subclass Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_SUBCLASS_AUDIO_CONTROL = 0x01 , ///< Audio Control
|
||||
AUDIO_SUBCLASS_AUDIO_STREAMING , ///< Audio Streaming
|
||||
AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming
|
||||
AUDIO_SUBCLASS_CONTROL = 0x01 , ///< Audio Control
|
||||
AUDIO_SUBCLASS_STREAMING , ///< Audio Streaming
|
||||
AUDIO_SUBCLASS_MIDI_STREAMING , ///< MIDI Streaming
|
||||
} audio_subclass_type_t;
|
||||
|
||||
/// Audio Protocol Codes
|
||||
@ -54,6 +54,40 @@ typedef enum
|
||||
AUDIO_PROTOCOL_V3 = 0x30, ///< Version 3.0
|
||||
} audio_protocol_type_t;
|
||||
|
||||
/// Audio Function Category Codes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_FUNC_DESKTOP_SPEAKER = 0x01,
|
||||
AUDIO_FUNC_HOME_THEATER = 0x02,
|
||||
AUDIO_FUNC_MICROPHONE = 0x03,
|
||||
AUDIO_FUNC_HEADSET = 0x04,
|
||||
AUDIO_FUNC_TELEPHONE = 0x05,
|
||||
AUDIO_FUNC_CONVERTER = 0x06,
|
||||
AUDIO_FUNC_SOUND_RECODER = 0x07,
|
||||
AUDIO_FUNC_IO_BOX = 0x08,
|
||||
AUDIO_FUNC_MUSICAL_INSTRUMENT = 0x09,
|
||||
AUDIO_FUNC_PRO_AUDIO = 0x0A,
|
||||
AUDIO_FUNC_AUDIO_VIDEO = 0x0B,
|
||||
AUDIO_FUNC_CONTROL_PANEL = 0x0C
|
||||
} audio_function_t;
|
||||
|
||||
/// Audio Class-Specific AC Interface Descriptor Subtypes
|
||||
typedef enum
|
||||
{
|
||||
AUDIO_CS_INTERFACE_HEADER = 0x01,
|
||||
AUDIO_CS_INTERFACE_INPUT_TERMINAL = 0x02,
|
||||
AUDIO_CS_INTERFACE_OUTPUT_TERMINAL = 0x03,
|
||||
AUDIO_CS_INTERFACE_MIXER_UNIT = 0x04,
|
||||
AUDIO_CS_INTERFACE_SELECTOR_UNIT = 0x05,
|
||||
AUDIO_CS_INTERFACE_FEATURE_UNIT = 0x06,
|
||||
AUDIO_CS_INTERFACE_EFFECT_UNIT = 0x07,
|
||||
AUDIO_CS_INTERFACE_PROCESSING_UNIT = 0x08,
|
||||
AUDIO_CS_INTERFACE_EXTENSION_UNIT = 0x09,
|
||||
AUDIO_CS_INTERFACE_CLOCK_SOURCE = 0x0A,
|
||||
AUDIO_CS_INTERFACE_CLOCK_SELECTOR = 0x0B,
|
||||
AUDIO_CS_INTERFACE_CLOCK_MULTIPLIER = 0x0C,
|
||||
AUDIO_CS_INTERFACE_SAMPLE_RATE_CONVERTER = 0x0D,
|
||||
} audio_cs_interface_subtype_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -41,7 +41,7 @@
|
||||
/** \defgroup ClassDriver_CDC_Common Common Definitions
|
||||
* @{ */
|
||||
|
||||
|
||||
// TODO remove
|
||||
/// CDC Pipe ID, used to indicate which pipe the API is addressing to (Notification, Out, In)
|
||||
typedef enum
|
||||
{
|
||||
@ -52,8 +52,9 @@ typedef enum
|
||||
}cdc_pipeid_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CDC COMMUNICATION INTERFACE CLASS
|
||||
// CDC Communication Interface Class
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/// Communication Interface Subclass Codes
|
||||
typedef enum
|
||||
{
|
||||
@ -117,7 +118,7 @@ typedef enum
|
||||
}cdc_func_desc_type_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// CDC DATA INTERFACE CLASS
|
||||
// CDC Data Interface Class
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// SUBCLASS code of Data Interface is not used and should/must be zero
|
||||
@ -138,8 +139,9 @@ typedef enum{
|
||||
}cdc_data_protocol_type_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MANAGEMENT ELEMENT REQUEST (CONTROL ENDPOINT)
|
||||
// Management Element Request (Control Endpoint)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/// Communication Interface Management Element Request Codes
|
||||
typedef enum
|
||||
{
|
||||
@ -189,8 +191,9 @@ typedef enum
|
||||
}cdc_management_request_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MANAGEMENT ELEMENENT NOTIFICATION (NOTIFICATION ENDPOINT)
|
||||
// Management Elemenent Notification (Notification Endpoint)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/// Communication Interface Management Element Notification Codes
|
||||
typedef enum
|
||||
{
|
||||
@ -209,14 +212,15 @@ typedef enum
|
||||
}cdc_notification_request_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// FUNCTIONAL DESCRIPTOR (COMMUNICATION INTERFACE)
|
||||
// Class Specific Functional Descriptor (Communication Interface)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
/// Header Functional Descriptor (Communication Interface)
|
||||
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 one of above CDC_FUCN_DESC_
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUNC_DESC_
|
||||
uint16_t bcdCDC ; ///< CDC release number in Binary-Coded Decimal
|
||||
}cdc_desc_func_header_t;
|
||||
|
||||
@ -246,7 +250,7 @@ typedef struct TU_ATTR_PACKED
|
||||
uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType one of above CDC_FUCN_DESC_
|
||||
uint8_t iCountryCodeRelDate ; ///< Index of a string giving the release date for the implemented ISO 3166 Country Codes.
|
||||
uint16_t wCountryCode[] ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
|
||||
uint16_t wCountryCode ; ///< Country code in the format as defined in [ISO3166], release date as specified inoffset 3 for the first supported country.
|
||||
}cdc_desc_func_country_selection_t;
|
||||
|
||||
#define cdc_desc_func_country_selection_n_t(no_country) \
|
||||
|
@ -73,21 +73,18 @@ typedef struct
|
||||
//--------------------------------------------------------------------+
|
||||
CFG_TUSB_MEM_SECTION static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
|
||||
|
||||
//bool pending_read_from_host; TODO remove
|
||||
static void _prep_out_transaction (uint8_t itf)
|
||||
{
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
|
||||
// skip if previous transfer not complete
|
||||
if ( usbd_edpt_busy(TUD_OPT_RHPORT, p_cdc->ep_out) ) return;
|
||||
//if (pending_read_from_host) return;
|
||||
|
||||
// Prepare for incoming data but only allow what we can store in the ring buffer.
|
||||
uint16_t max_read = tu_fifo_remaining(&p_cdc->rx_ff);
|
||||
if ( max_read >= CFG_TUD_CDC_EPSIZE )
|
||||
{
|
||||
usbd_edpt_xfer(TUD_OPT_RHPORT, p_cdc->ep_out, p_cdc->epout_buf, CFG_TUD_CDC_EPSIZE);
|
||||
// pending_read_from_host = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,7 +262,7 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
|
||||
// Communication Functional Descriptors
|
||||
while ( TUSB_DESC_CLASS_SPECIFIC == tu_desc_type(p_desc) )
|
||||
while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) )
|
||||
{
|
||||
(*p_length) += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
@ -296,7 +293,6 @@ bool cdcd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t
|
||||
}
|
||||
|
||||
// Prepare for incoming data
|
||||
// pending_read_from_host = false;
|
||||
_prep_out_transaction(cdc_id);
|
||||
|
||||
return true;
|
||||
@ -374,7 +370,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
uint8_t const itf = 0;
|
||||
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
|
||||
|
||||
// receive new data
|
||||
// Received new data
|
||||
if ( ep_addr == p_cdc->ep_out )
|
||||
{
|
||||
for(uint32_t i=0; i<xferred_bytes; i++)
|
||||
@ -392,11 +388,18 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
|
||||
if (tud_cdc_rx_cb && tu_fifo_count(&p_cdc->rx_ff) ) tud_cdc_rx_cb(itf);
|
||||
|
||||
// prepare for OUT transaction
|
||||
// pending_read_from_host = false;
|
||||
_prep_out_transaction(itf);
|
||||
}
|
||||
|
||||
// nothing to do with in and notif endpoint for now
|
||||
// Data sent to host, we could continue to fetch data tx fifo to send.
|
||||
// But it will cause incorrect baudrate set in line coding.
|
||||
// Though maybe the baudrate is not really important !!!
|
||||
// if ( ep_addr == p_cdc->ep_in )
|
||||
// {
|
||||
//
|
||||
// }
|
||||
|
||||
// nothing to do with notif endpoint for now
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@
|
||||
* @{ */
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API (Multiple Interfaces)
|
||||
// Application API (Multiple Interfaces)
|
||||
// CFG_TUD_CDC > 1
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_cdc_n_connected (uint8_t itf);
|
||||
@ -68,26 +68,26 @@ uint32_t tud_cdc_n_write_str (uint8_t itf, char const* str);
|
||||
bool tud_cdc_n_write_flush (uint8_t itf);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API (Interface0)
|
||||
// Application API (Interface0)
|
||||
//--------------------------------------------------------------------+
|
||||
static inline bool tud_cdc_connected (void) { return tud_cdc_n_connected(0); }
|
||||
static inline uint8_t tud_cdc_get_line_state (void) { return tud_cdc_n_get_line_state(0); }
|
||||
static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding) { return tud_cdc_n_get_line_coding(0, coding);}
|
||||
static inline void tud_cdc_set_wanted_char (char wanted) { tud_cdc_n_set_wanted_char(0, wanted); }
|
||||
static inline bool tud_cdc_connected (void);
|
||||
static inline uint8_t tud_cdc_get_line_state (void);
|
||||
static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding);
|
||||
static inline void tud_cdc_set_wanted_char (char wanted);
|
||||
|
||||
static inline uint32_t tud_cdc_available (void) { return tud_cdc_n_available(0); }
|
||||
static inline signed char tud_cdc_read_char (void) { return tud_cdc_n_read_char(0); }
|
||||
static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize) { return tud_cdc_n_read(0, buffer, bufsize); }
|
||||
static inline void tud_cdc_read_flush (void) { tud_cdc_n_read_flush(0); }
|
||||
static inline signed char tud_cdc_peek (int pos) { return tud_cdc_n_peek(0, pos); }
|
||||
static inline uint32_t tud_cdc_available (void);
|
||||
static inline signed char tud_cdc_read_char (void);
|
||||
static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize);
|
||||
static inline void tud_cdc_read_flush (void);
|
||||
static inline signed char tud_cdc_peek (int pos);
|
||||
|
||||
static inline uint32_t tud_cdc_write_char (char ch) { return tud_cdc_n_write_char(0, ch); }
|
||||
static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize) { return tud_cdc_n_write(0, buffer, bufsize); }
|
||||
static inline uint32_t tud_cdc_write_str (char const* str) { return tud_cdc_n_write_str(0, str); }
|
||||
static inline bool tud_cdc_write_flush (void) { return tud_cdc_n_write_flush(0); }
|
||||
static inline uint32_t tud_cdc_write_char (char ch);
|
||||
static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize);
|
||||
static inline uint32_t tud_cdc_write_str (char const* str);
|
||||
static inline bool tud_cdc_write_flush (void);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION CALLBACK API (WEAK is optional)
|
||||
// Application Callback API (weak is optional)
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Invoked when received new data
|
||||
@ -102,6 +102,74 @@ TU_ATTR_WEAK void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts);
|
||||
// Invoked when line coding is change via SET_LINE_CODING
|
||||
TU_ATTR_WEAK void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const* p_line_coding);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Inline Functions
|
||||
//--------------------------------------------------------------------+
|
||||
static inline bool tud_cdc_connected (void)
|
||||
{
|
||||
return tud_cdc_n_connected(0);
|
||||
}
|
||||
|
||||
static inline uint8_t tud_cdc_get_line_state (void)
|
||||
{
|
||||
return tud_cdc_n_get_line_state(0);
|
||||
}
|
||||
|
||||
static inline void tud_cdc_get_line_coding (cdc_line_coding_t* coding)
|
||||
{
|
||||
return tud_cdc_n_get_line_coding(0, coding);
|
||||
}
|
||||
|
||||
static inline void tud_cdc_set_wanted_char (char wanted)
|
||||
{
|
||||
tud_cdc_n_set_wanted_char(0, wanted);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_cdc_available (void)
|
||||
{
|
||||
return tud_cdc_n_available(0);
|
||||
}
|
||||
|
||||
static inline signed char tud_cdc_read_char (void)
|
||||
{
|
||||
return tud_cdc_n_read_char(0);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_cdc_read (void* buffer, uint32_t bufsize)
|
||||
{
|
||||
return tud_cdc_n_read(0, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline void tud_cdc_read_flush (void)
|
||||
{
|
||||
tud_cdc_n_read_flush(0);
|
||||
}
|
||||
|
||||
static inline signed char tud_cdc_peek (int pos)
|
||||
{
|
||||
return tud_cdc_n_peek(0, pos);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_cdc_write_char (char ch)
|
||||
{
|
||||
return tud_cdc_n_write_char(0, ch);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_cdc_write (void const* buffer, uint32_t bufsize)
|
||||
{
|
||||
return tud_cdc_n_write(0, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_cdc_write_str (char const* str)
|
||||
{
|
||||
return tud_cdc_n_write_str(0, str);
|
||||
}
|
||||
|
||||
static inline bool tud_cdc_write_flush (void)
|
||||
{
|
||||
return tud_cdc_n_write_flush(0);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
||||
|
||||
|
@ -142,7 +142,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
|
||||
// Communication Functional Descriptors
|
||||
while( TUSB_DESC_CLASS_SPECIFIC == p_desc[DESC_OFFSET_TYPE] )
|
||||
while( TUSB_DESC_CS_INTERFACE == p_desc[DESC_OFFSET_TYPE] )
|
||||
{
|
||||
if ( CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT == cdc_functional_desc_typeof(p_desc) )
|
||||
{
|
||||
|
@ -39,27 +39,122 @@
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// FUNCTIONAL DESCRIPTOR (COMMUNICATION INTERFACE)
|
||||
// Class Specific Descriptor
|
||||
//--------------------------------------------------------------------+
|
||||
/// Header Functional Descriptor (Communication Interface)
|
||||
|
||||
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
|
||||
} midi_cs_endpoint_subtype_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MIDI_JACK_EMBEDDED = 0x01,
|
||||
MIDI_JACK_EXTERNAL = 0x02
|
||||
} midi_jack_type_t;
|
||||
|
||||
/// 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 one of above MIDI_FUCN_DESC_
|
||||
uint8_t bDescriptorSubType ; ///< Descriptor SubType
|
||||
uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal
|
||||
uint16_t wTotalLength ;
|
||||
}midi_desc_func_header_t;
|
||||
} midi_desc_header_t;
|
||||
|
||||
/// Union Functional Descriptor (Communication Interface)
|
||||
/// 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 one of above CDC_FUCN_DESC_
|
||||
uint8_t bControlInterface ; ///< Interface number of Communication Interface
|
||||
uint8_t bSubordinateInterface ; ///< Array of Interface number of Data Interface
|
||||
}cdc_desc_func_union_t;
|
||||
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;
|
||||
|
||||
|
||||
/// 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
|
||||
#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 ; \
|
||||
}
|
||||
|
||||
/// 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;
|
||||
|
||||
/// MIDI Element Descriptor with multiple pins
|
||||
#define midi_desc_element_n_t(input_num) \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t bLength; \
|
||||
uint8_t bDescriptorType; \
|
||||
uint8_t bDescriptorSubType; \
|
||||
uint8_t bElementID; \
|
||||
uint8_t bNrInputPins; \
|
||||
struct TU_ATTR_PACKED { \
|
||||
uint8_t baSourceID; \
|
||||
uint8_t baSourcePin; \
|
||||
} pins[input_num]; \
|
||||
uint8_t bNrOutputPins; \
|
||||
uint8_t bInTerminalLink; \
|
||||
uint8_t bOutTerminalLink; \
|
||||
uint8_t bElCapsSize; \
|
||||
uint16_t bmElementCaps; \
|
||||
uint8_t iElement; \
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
|
@ -74,7 +74,8 @@ typedef struct
|
||||
//--------------------------------------------------------------------+
|
||||
CFG_TUSB_MEM_SECTION midid_interface_t _midid_itf[CFG_TUD_MIDI];
|
||||
|
||||
bool tud_midi_n_connected(uint8_t itf) {
|
||||
bool tud_midi_n_mounted (uint8_t itf)
|
||||
{
|
||||
midid_interface_t* midi = &_midid_itf[itf];
|
||||
return midi->itf_num != 0;
|
||||
}
|
||||
@ -87,12 +88,6 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t jack_id)
|
||||
return tu_fifo_count(&_midid_itf[itf].rx_ff);
|
||||
}
|
||||
|
||||
char tud_midi_n_read_char(uint8_t itf, uint8_t jack_id)
|
||||
{
|
||||
char ch;
|
||||
return tu_fifo_read(&_midid_itf[itf].rx_ff, &ch) ? ch : (-1);
|
||||
}
|
||||
|
||||
uint32_t tud_midi_n_read(uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize)
|
||||
{
|
||||
return tu_fifo_read_n(&_midid_itf[itf].rx_ff, buffer, bufsize);
|
||||
@ -103,7 +98,6 @@ void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id)
|
||||
tu_fifo_clear(&_midid_itf[itf].rx_ff);
|
||||
}
|
||||
|
||||
|
||||
void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bufsize) {
|
||||
if (bufsize % 4 != 0) {
|
||||
return;
|
||||
@ -133,15 +127,14 @@ void midi_rx_done_cb(midid_interface_t* midi, uint8_t const* buffer, uint32_t bu
|
||||
|
||||
static bool maybe_transmit(midid_interface_t* midi, uint8_t itf_index)
|
||||
{
|
||||
TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); // skip if previous transfer not complete
|
||||
TU_VERIFY( !usbd_edpt_busy(TUD_OPT_RHPORT, midi->ep_in) ); // skip if previous transfer not complete
|
||||
|
||||
uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EPSIZE);
|
||||
if (count > 0)
|
||||
{
|
||||
TU_VERIFY( tud_midi_n_connected(itf_index) ); // fifo is empty if not connected
|
||||
TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) );
|
||||
}
|
||||
return true;
|
||||
uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epin_buf, CFG_TUD_MIDI_EPSIZE);
|
||||
if (count > 0)
|
||||
{
|
||||
TU_ASSERT( usbd_edpt_xfer(TUD_OPT_RHPORT, midi->ep_in, midi->epin_buf, count) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t tud_midi_n_write(uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize)
|
||||
@ -252,7 +245,7 @@ void midid_reset(uint8_t rhport)
|
||||
bool midid_open(uint8_t rhport, tusb_desc_interface_t const * p_interface_desc, uint16_t *p_length)
|
||||
{
|
||||
// For now handle the audio control interface as well.
|
||||
if ( AUDIO_SUBCLASS_AUDIO_CONTROL == p_interface_desc->bInterfaceSubClass) {
|
||||
if ( AUDIO_SUBCLASS_CONTROL == p_interface_desc->bInterfaceSubClass) {
|
||||
uint8_t const * p_desc = tu_desc_next ( (uint8_t const *) p_interface_desc );
|
||||
(*p_length) = sizeof(tusb_desc_interface_t);
|
||||
|
||||
|
@ -29,7 +29,9 @@
|
||||
|
||||
#include "common/tusb_common.h"
|
||||
#include "device/usbd.h"
|
||||
|
||||
#include "class/audio/audio.h"
|
||||
#include "midi.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Class Driver Configuration
|
||||
@ -38,7 +40,6 @@
|
||||
#define CFG_TUD_MIDI_EPSIZE 64
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -49,41 +50,74 @@
|
||||
* @{ */
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API (Multiple Interfaces)
|
||||
// Application API (Multiple Interfaces)
|
||||
// CFG_TUD_MIDI > 1
|
||||
//--------------------------------------------------------------------+
|
||||
bool tud_midi_n_connected (uint8_t itf);
|
||||
bool tud_midi_n_mounted (uint8_t itf);
|
||||
uint32_t tud_midi_n_available (uint8_t itf, uint8_t jack_id);
|
||||
uint32_t tud_midi_n_read (uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize);
|
||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id);
|
||||
uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
||||
|
||||
uint32_t tud_midi_n_available (uint8_t itf, uint8_t jack_id);
|
||||
char tud_midi_n_read_char (uint8_t itf, uint8_t jack_id);
|
||||
uint32_t tud_midi_n_read (uint8_t itf, uint8_t jack_id, void* buffer, uint32_t bufsize);
|
||||
void tud_midi_n_read_flush (uint8_t itf, uint8_t jack_id);
|
||||
char tud_midi_n_peek (uint8_t itf, uint8_t jack_id, int pos);
|
||||
|
||||
uint32_t tud_midi_n_write_char (uint8_t itf, char ch);
|
||||
uint32_t tud_midi_n_write (uint8_t itf, uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
||||
bool tud_midi_n_write_flush (uint8_t itf);
|
||||
static inline
|
||||
uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION API (Interface0)
|
||||
// Application API (Interface0)
|
||||
//--------------------------------------------------------------------+
|
||||
static inline bool tud_midi_connected (void) { return tud_midi_n_connected(0); }
|
||||
|
||||
static inline uint32_t tud_midi_available (void) { return tud_midi_n_available(0, 0); }
|
||||
static inline char tud_midi_read_char (void) { return tud_midi_n_read_char(0, 0); }
|
||||
static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize) { return tud_midi_n_read(0, 0, buffer, bufsize); }
|
||||
static inline void tud_midi_read_flush (void) { tud_midi_n_read_flush(0, 0); }
|
||||
static inline char tud_midi_peek (int pos) { return tud_midi_n_peek(0, 0, pos); }
|
||||
|
||||
static inline uint32_t tud_midi_write_char (char ch) { return tud_midi_n_write_char(0, ch); }
|
||||
static inline uint32_t tud_midi_write (uint8_t jack_id, void const* buffer, uint32_t bufsize) { return tud_midi_n_write(0, jack_id, buffer, bufsize); }
|
||||
static inline bool tud_midi_write_flush (void) { return tud_midi_n_write_flush(0); }
|
||||
static inline bool tud_midi_mounted (void);
|
||||
static inline uint32_t tud_midi_available (void);
|
||||
static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize);
|
||||
static inline void tud_midi_read_flush (void);
|
||||
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize);
|
||||
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// APPLICATION CALLBACK API (WEAK is optional)
|
||||
// Application Callback API (weak is optional)
|
||||
//--------------------------------------------------------------------+
|
||||
TU_ATTR_WEAK void tud_midi_rx_cb(uint8_t itf);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Inline Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
static inline uint32_t tud_midi_n_write24 (uint8_t itf, uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3)
|
||||
{
|
||||
uint8_t msg[3] = { b1, b2, b3 };
|
||||
return tud_midi_n_write(itf, jack_id, msg, 3);
|
||||
}
|
||||
|
||||
static inline bool tud_midi_mounted (void)
|
||||
{
|
||||
return tud_midi_n_mounted(0);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_midi_available (void)
|
||||
{
|
||||
return tud_midi_n_available(0, 0);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_midi_read (void* buffer, uint32_t bufsize)
|
||||
{
|
||||
return tud_midi_n_read(0, 0, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline void tud_midi_read_flush (void)
|
||||
{
|
||||
tud_midi_n_read_flush(0, 0);
|
||||
}
|
||||
|
||||
static inline uint32_t tud_midi_write (uint8_t jack_id, uint8_t const* buffer, uint32_t bufsize)
|
||||
{
|
||||
return tud_midi_n_write(0, jack_id, buffer, bufsize);
|
||||
}
|
||||
|
||||
static inline uint32_t tudi_midi_write24 (uint8_t jack_id, uint8_t b1, uint8_t b2, uint8_t b3)
|
||||
{
|
||||
uint8_t msg[3] = { b1, b2, b3 };
|
||||
return tud_midi_write(jack_id, msg, 3);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Class Driver API
|
||||
//--------------------------------------------------------------------+
|
||||
|
@ -72,18 +72,24 @@ typedef enum
|
||||
/// USB Descriptor Types (section 9.4 table 9-5)
|
||||
typedef enum
|
||||
{
|
||||
TUSB_DESC_DEVICE = 0x01 ,
|
||||
TUSB_DESC_CONFIGURATION = 0x02 ,
|
||||
TUSB_DESC_STRING = 0x03 ,
|
||||
TUSB_DESC_INTERFACE = 0x04 ,
|
||||
TUSB_DESC_ENDPOINT = 0x05 ,
|
||||
TUSB_DESC_DEVICE_QUALIFIER = 0x06 ,
|
||||
TUSB_DESC_OTHER_SPEED_CONFIG = 0x07 ,
|
||||
TUSB_DESC_INTERFACE_POWER = 0x08 ,
|
||||
TUSB_DESC_OTG = 0x09 ,
|
||||
TUSB_DESC_DEBUG = 0x0A ,
|
||||
TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B ,
|
||||
TUSB_DESC_CLASS_SPECIFIC = 0x24
|
||||
TUSB_DESC_DEVICE = 0x01,
|
||||
TUSB_DESC_CONFIGURATION = 0x02,
|
||||
TUSB_DESC_STRING = 0x03,
|
||||
TUSB_DESC_INTERFACE = 0x04,
|
||||
TUSB_DESC_ENDPOINT = 0x05,
|
||||
TUSB_DESC_DEVICE_QUALIFIER = 0x06,
|
||||
TUSB_DESC_OTHER_SPEED_CONFIG = 0x07,
|
||||
TUSB_DESC_INTERFACE_POWER = 0x08,
|
||||
TUSB_DESC_OTG = 0x09,
|
||||
TUSB_DESC_DEBUG = 0x0A,
|
||||
TUSB_DESC_INTERFACE_ASSOCIATION = 0x0B,
|
||||
|
||||
// Class Specific Descriptor
|
||||
TUSB_DESC_CS_DEVICE = 0x21,
|
||||
TUSB_DESC_CS_CONFIGURATION = 0x22,
|
||||
TUSB_DESC_CS_STRING = 0x23,
|
||||
TUSB_DESC_CS_INTERFACE = 0x24,
|
||||
TUSB_DESC_CS_ENDPOINT = 0x25,
|
||||
}tusb_desc_type_t;
|
||||
|
||||
typedef enum
|
||||
@ -105,9 +111,9 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TUSB_REQ_FEATURE_EDPT_HALT = 0,
|
||||
TUSB_REQ_FEATURE_EDPT_HALT = 0,
|
||||
TUSB_REQ_FEATURE_REMOTE_WAKEUP = 1,
|
||||
TUSB_REQ_FEATURE_TEST_MODE = 2
|
||||
TUSB_REQ_FEATURE_TEST_MODE = 2
|
||||
}tusb_request_feature_selector_t;
|
||||
|
||||
typedef enum
|
||||
|
@ -110,9 +110,6 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoi
|
||||
// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes);
|
||||
|
||||
// Check if endpoint transferring is complete (TODO remove)
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
// Stall endpoint
|
||||
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr);
|
||||
|
||||
|
@ -111,13 +111,13 @@ TU_ATTR_WEAK void tud_resume_cb(void);
|
||||
/* CDC Control Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 1, TUSB_CLASS_CDC, CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL, CDC_COMM_PROTOCOL_ATCOMMAND, _stridx,\
|
||||
/* CDC Header */\
|
||||
5, TUSB_DESC_CLASS_SPECIFIC, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\
|
||||
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_HEADER, U16_TO_U8S_LE(0x0120),\
|
||||
/* CDC Call */\
|
||||
5, TUSB_DESC_CLASS_SPECIFIC, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (_itfnum) + 1,\
|
||||
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_CALL_MANAGEMENT, 0, (_itfnum) + 1,\
|
||||
/* CDC ACM: support line request */\
|
||||
4, TUSB_DESC_CLASS_SPECIFIC, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\
|
||||
4, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT, 2,\
|
||||
/* CDC Union */\
|
||||
5, TUSB_DESC_CLASS_SPECIFIC, CDC_FUNC_DESC_UNION, _itfnum, (_itfnum) + 1,\
|
||||
5, TUSB_DESC_CS_INTERFACE, CDC_FUNC_DESC_UNION, _itfnum, (_itfnum) + 1,\
|
||||
/* Endpoint Notification */\
|
||||
7, TUSB_DESC_ENDPOINT, _ep_notif, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_ep_notif_size), 16,\
|
||||
/* CDC Data Interface */\
|
||||
@ -171,6 +171,43 @@ TU_ATTR_WEAK void tud_resume_cb(void);
|
||||
/* Endpoint Out */\
|
||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_INTERRUPT, U16_TO_U8S_LE(_epsize), _ep_interval
|
||||
|
||||
//------------- MIDI -------------//
|
||||
|
||||
// Length of template descriptor (96 bytes)
|
||||
#define TUD_MIDI_DESC_LEN (8 + 9 + 9 + 9 + 7 + 6 + 6 + 9 + 9 + 7 + 5 + 7 + 5)
|
||||
|
||||
// MIDI simple descriptor
|
||||
// - 1 Embedded Jack In connected to 1 External Jack Out
|
||||
// - 1 Embedded Jack out connected to 1 External Jack In
|
||||
#define TUD_MIDI_DESCRIPTOR(_itfnum, _stridx, _epin, _epout, _epsize) \
|
||||
/* Interface Associate */\
|
||||
8, TUSB_DESC_INTERFACE_ASSOCIATION, _itfnum, 2, TUSB_CLASS_AUDIO, 0x00, AUDIO_PROTOCOL_V1, 0,\
|
||||
/* Audio Control (AC) Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_CONTROL, AUDIO_PROTOCOL_V1, _stridx,\
|
||||
/* AC Header */\
|
||||
9, TUSB_DESC_CS_INTERFACE, AUDIO_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0009), 1, _itfnum+1,\
|
||||
/* MIDI Streaming (MS) Interface */\
|
||||
9, TUSB_DESC_INTERFACE, _itfnum+1, 0, 2, TUSB_CLASS_AUDIO, AUDIO_SUBCLASS_MIDI_STREAMING, AUDIO_PROTOCOL_V1, 0,\
|
||||
/* MS Header */\
|
||||
7, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_HEADER, U16_TO_U8S_LE(0x0100), U16_TO_U8S_LE(0x0025),\
|
||||
/* MS In Jack (Embedded) */\
|
||||
6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EMBEDDED, 1, 0,\
|
||||
/* MS In Jack (External) */\
|
||||
6, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_IN_JACK, MIDI_JACK_EXTERNAL, 2, 0,\
|
||||
/* MS Out Jack (Embedded), connected to In Jack External */\
|
||||
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EMBEDDED, 3, 1, 2, 1, 0,\
|
||||
/* MS Out Jack (External), connected to In Jack Embedded */\
|
||||
9, TUSB_DESC_CS_INTERFACE, MIDI_CS_INTERFACE_OUT_JACK, MIDI_JACK_EXTERNAL, 4, 1, 1, 1, 0,\
|
||||
/* Endpoint Out */\
|
||||
7, TUSB_DESC_ENDPOINT, _epout, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
|
||||
/* MS Endpoint (connected to embedded jack in) */\
|
||||
5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 1,\
|
||||
/* Endpoint In */\
|
||||
7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0,\
|
||||
/* MS Endpoint (connected to embedded jack out) */\
|
||||
5, TUSB_DESC_CS_ENDPOINT, MIDI_CS_ENDPOINT_GENERAL, 1, 3
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -229,22 +229,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
}
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// USBD shouldn't check control endpoint state
|
||||
if ( 0 == ep_addr ) return false;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
|
||||
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
|
||||
return ep->EPINTFLAG.bit.TRCPT1 == 0 && ep->EPSTATUS.bit.BK1RDY == 1;
|
||||
}
|
||||
return ep->EPINTFLAG.bit.TRCPT0 == 0 && ep->EPSTATUS.bit.BK0RDY == 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static bool maybe_handle_setup_packet(void) {
|
||||
|
@ -233,22 +233,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
}
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// USBD shouldn't check control endpoint state
|
||||
if ( 0 == ep_addr ) return false;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum];
|
||||
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
|
||||
return ep->EPINTFLAG.bit.TRCPT1 == 0 && ep->EPSTATUS.bit.BK1RDY == 1;
|
||||
}
|
||||
return ep->EPINTFLAG.bit.TRCPT0 == 0 && ep->EPSTATUS.bit.BK0RDY == 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
static bool maybe_handle_setup_packet(void) {
|
||||
|
@ -332,21 +332,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
}
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
// USBD shouldn't check control endpoint state
|
||||
if ( 0 == tu_edpt_number(ep_addr) ) return false;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
xfer_td_t* xfer = get_td(epnum, dir);
|
||||
|
||||
return xfer->actual_len < xfer->total_len;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Interrupt Handler
|
||||
*------------------------------------------------------------------*/
|
||||
|
@ -218,14 +218,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
uint8_t const ep_id = ep_addr2id(ep_addr);
|
||||
return _dcd.ep[ep_id][0].active;
|
||||
}
|
||||
|
||||
static void prepare_ep_xfer(uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes)
|
||||
{
|
||||
uint16_t const nbytes = tu_min16(total_bytes, DMA_NBYTES_MAX);
|
||||
|
@ -316,14 +316,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
||||
uint8_t ep_id = ep_addr2idx( ep_addr );
|
||||
return (_dcd.udca[ep_id] != NULL && !_dcd.udca[ep_id]->retired);
|
||||
}
|
||||
|
||||
void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
|
@ -240,18 +240,6 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy(uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
uint8_t const ep_idx = 2*epnum + dir;
|
||||
|
||||
dcd_qtd_t * p_qtd = &dcd_data_ptr[rhport]->qtd[ep_idx];
|
||||
|
||||
return p_qtd->active;
|
||||
// return !p_qhd->qtd_overlay.halted && p_qhd->qtd_overlay.active;
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
|
@ -67,15 +67,19 @@ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{ return false;}
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||
{ return false;}
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -397,32 +397,6 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
|
||||
}
|
||||
}
|
||||
|
||||
bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr)
|
||||
{
|
||||
(void) rhport;
|
||||
USB_OTG_OUTEndpointTypeDef * out_ep = OUT_EP_BASE;
|
||||
USB_OTG_INEndpointTypeDef * in_ep = IN_EP_BASE;
|
||||
|
||||
// USBD shouldn't check control endpoint state
|
||||
if ( 0 == ep_addr ) return false;
|
||||
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
|
||||
bool enabled = false;
|
||||
bool xferring = true;
|
||||
|
||||
if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) {
|
||||
enabled = (in_ep[epnum].DIEPCTL & USB_OTG_DIEPCTL_EPENA_Msk);
|
||||
xferring = (in_ep[epnum].DIEPTSIZ & USB_OTG_DIEPTSIZ_PKTCNT_Msk);
|
||||
} else {
|
||||
enabled = (out_ep[epnum].DOEPCTL & USB_OTG_DOEPCTL_EPENA_Msk);
|
||||
xferring = (out_ep[epnum].DOEPTSIZ & USB_OTG_DOEPTSIZ_PKTCNT_Msk);
|
||||
}
|
||||
|
||||
// TODO: Also check that endpoint is active (not just enabled)?
|
||||
return (enabled && xferring);
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
|
||||
// TODO: Split into "receive on endpoint 0" and "receive generic"; endpoint 0's
|
||||
|
@ -12,7 +12,7 @@ success_count = 0
|
||||
fail_count = 0
|
||||
exit_status = 0
|
||||
|
||||
all_device_example = ["cdc_msc_hid", "msc_dual_lun", "hid_generic_inout"]
|
||||
all_device_example = ["cdc_msc_hid", "hid_generic_inout", "midi_test", "msc_dual_lun"]
|
||||
|
||||
all_boards = []
|
||||
for entry in os.scandir("hw/bsp"):
|
||||
|
Loading…
x
Reference in New Issue
Block a user