update repo to work with latest tinyusb and nrfx module

This commit is contained in:
hathach 2019-11-11 15:27:44 +07:00
parent 3d99a55940
commit 126115a2cb
12 changed files with 213 additions and 359 deletions

View File

@ -108,7 +108,7 @@ C_SOURCE_FILES += $(SRC_PATH)/dfu_init.c
# nrfx
C_SOURCE_FILES += $(NRFX_PATH)/drivers/src/nrfx_power.c
C_SOURCE_FILES += $(NRFX_PATH)/hal/nrf_nvmc.c
C_SOURCE_FILES += $(NRFX_PATH)/drivers/src/nrfx_nvmc.c
# SDK 11 files
C_SOURCE_FILES += $(SDK11_PATH)/libraries/bootloader_dfu/bootloader.c
@ -159,13 +159,11 @@ C_SOURCE_FILES += $(NRFX_PATH)/mdk/system_nrf52840.c
# Tinyusb stack
C_SOURCE_FILES += $(TUSB_PATH)/portable/nordic/nrf5x/dcd_nrf5x.c
C_SOURCE_FILES += $(TUSB_PATH)/portable/nordic/nrf5x/hal_nrf5x.c
C_SOURCE_FILES += $(TUSB_PATH)/common/tusb_fifo.c
C_SOURCE_FILES += $(TUSB_PATH)/device/usbd.c
C_SOURCE_FILES += $(TUSB_PATH)/device/usbd_control.c
C_SOURCE_FILES += $(TUSB_PATH)/class/cdc/cdc_device.c
C_SOURCE_FILES += $(TUSB_PATH)/class/msc/msc_device.c
C_SOURCE_FILES += $(TUSB_PATH)/class/custom/custom_device.c
C_SOURCE_FILES += $(TUSB_PATH)/tusb.c
endif
@ -198,6 +196,7 @@ IPATH += $(NRFX_PATH)
IPATH += $(NRFX_PATH)/mdk
IPATH += $(NRFX_PATH)/hal
IPATH += $(NRFX_PATH)/drivers/include
IPATH += $(NRFX_PATH)/drivers/src
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu/hci_transport
IPATH += $(SDK11_PATH)/libraries/bootloader_dfu

View File

@ -119,9 +119,9 @@ static void wait_for_events(void)
// Feed all Watchdog just in case application enable it
// WDT cannot be disabled once started. It even last through soft reset (NVIC Reset)
if ( nrf_wdt_started() )
if ( nrf_wdt_started(NRF_WDT) )
{
for (uint8_t i=0; i<8; i++) nrf_wdt_reload_request_set(i);
for (uint8_t i=0; i<8; i++) nrf_wdt_reload_request_set(NRF_WDT, i);
}
// Event received. Process it from the scheduler.
@ -194,8 +194,8 @@ static void bootloader_settings_save(bootloader_settings_t * p_settings)
}
else
{
nrf_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
nrf_nvmc_write_words(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
nrfx_nvmc_page_erase(BOOTLOADER_SETTINGS_ADDRESS);
nrfx_nvmc_words_write(BOOTLOADER_SETTINGS_ADDRESS, (uint32_t *) p_settings, sizeof(bootloader_settings_t) / 4);
pstorage_callback_handler(&m_bootsettings_handle, PSTORAGE_STORE_OP_CODE, NRF_SUCCESS, (uint8_t *) p_settings, sizeof(bootloader_settings_t));
}

View File

@ -151,7 +151,7 @@ static void dfu_prepare_func_app_erase(uint32_t image_size)
for ( uint32_t i = 0; i < page_count; i++ )
{
nrf_nvmc_page_erase(DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE);
nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START + i * CODE_PAGE_SIZE);
}
// invoke complete callback

View File

@ -44,9 +44,9 @@ void flash_nrf5x_flush (bool need_erase)
// - nRF52840 dfu serial/uf2 are USB-based which are DMA and should have no problems.
//
// Note: MSC uf2 does not erase page in advance like dfu serial
if ( need_erase ) nrf_nvmc_page_erase(_fl_addr);
if ( need_erase ) nrfx_nvmc_page_erase(_fl_addr);
nrf_nvmc_write_words(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4);
nrfx_nvmc_words_write(_fl_addr, (uint32_t *) _fl_buf, FLASH_PAGE_SIZE / 4);
}
_fl_addr = FLASH_CACHE_INVALID_ADDR;

View File

@ -28,7 +28,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "nrf_nvmc.h"
#include "nrfx_nvmc.h"
#ifdef __cplusplus
extern "C" {

View File

@ -65,8 +65,8 @@
#include "pstorage_platform.h"
#include "nrf_mbr.h"
#include "pstorage.h"
#include "nrfx_nvmc.h"
#include "nrf_nvmc.h"
#ifdef NRF52840_XXAA
#include "nrf_usbd.h"
@ -275,11 +275,11 @@ void adafruit_factory_reset(void)
// clear all App Data if any
if ( DFU_APP_DATA_RESERVED )
{
nrf_nvmc_page_erase(APPDATA_ADDR_START);
nrfx_nvmc_page_erase(APPDATA_ADDR_START);
}
// Only need to erase the 1st page of Application code to make it invalid
nrf_nvmc_page_erase(DFU_BANK_0_REGION_START);
nrfx_nvmc_page_erase(DFU_BANK_0_REGION_START);
// back to normal
led_state(STATE_FACTORY_RESET_FINISHED);

View File

@ -3,7 +3,11 @@
// Power
#define NRFX_POWER_ENABLED 1
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7
#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7
#define NRFX_CLOCK_ENABLED 0
#define NRFX_NVMC_ENABLED 1
// UART
#ifdef NRF52832_XXAA

View File

@ -45,38 +45,47 @@ int write_block(uint32_t block_no, uint8_t *data, bool quiet, WriteState *state)
// tinyusb callbacks
//--------------------------------------------------------------------+
// Invoked when received SCSI_CMD_INQUIRY
// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4])
{
(void) lun;
const char vid[] = "Adafruit";
const char pid[] = "Bluefruit UF2";
const char rev[] = "1.0";
memcpy(vendor_id , vid, strlen(vid));
memcpy(product_id , pid, strlen(pid));
memcpy(product_rev, rev, strlen(rev));
}
// Invoked when received Test Unit Ready command.
// return true allowing host to read/write this LUN e.g SD card inserted
bool tud_msc_test_unit_ready_cb(uint8_t lun)
{
(void) lun;
return true;
}
// Callback invoked when received an SCSI command not in built-in list below
// - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE
// - READ10 and WRITE10 has their own callbacks
int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, uint16_t bufsize)
{
void const* response = NULL;
int32_t resplen = 0;
memset(buffer, 0, bufsize);
uint16_t resplen = 0;
// most scsi handled is input
bool in_xfer = true;
switch (scsi_cmd[0])
{
case SCSI_CMD_TEST_UNIT_READY:
// Command that host uses to check our readiness before sending other commands
resplen = 0;
break;
case SCSI_CMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
// Host is about to read/write etc ... better not to disconnect disk
resplen = 0;
break;
case SCSI_CMD_START_STOP_UNIT:
// Host try to eject/safe remove/poweroff us. We could safely disconnect with disk storage, or go into lower power
/* scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd;
// Start bit = 0 : low power mode, if load_eject = 1 : unmount disk storage as well
// Start bit = 1 : Ready mode, if load_eject = 1 : mount disk storage
start_stop->start;
start_stop->load_eject;
*/
resplen = 0;
break;
default:
// Set Sense = Invalid Command Operation
tud_msc_set_sense(lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00);
@ -86,13 +95,18 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer,
break;
}
// return len must not larger than bufsize
if ( resplen > (int32_t)bufsize ) resplen = bufsize;
// return resplen must not larger than bufsize
if ( resplen > bufsize ) resplen = bufsize;
// copy response to stack's buffer if any
if ( response && resplen )
if ( response && (resplen > 0) )
{
if(in_xfer)
{
memcpy(buffer, response, resplen);
}else
{
// SCSI output
}
}
return resplen;
@ -161,6 +175,8 @@ void tud_msc_write10_complete_cb(uint8_t lun)
}
}
// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size
// Application update block count and block size
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size)
{
(void) lun;
@ -169,4 +185,26 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz
*block_size = 512;
}
// Invoked when received Start Stop Unit command
// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage
// - Start = 1 : active mode, if load_eject = 1 : load disk storage
bool tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject)
{
(void) lun;
(void) power_condition;
if ( load_eject )
{
if (start)
{
// load disk storage
}else
{
// unload disk storage
}
}
return true;
}
#endif

View File

@ -58,11 +58,6 @@
//------------- Class enabled -------------//
#define CFG_TUD_CDC 1
#define CFG_TUD_MSC 1
#define CFG_TUD_HID_KEYBOARD 0
#define CFG_TUD_HID_MOUSE 0
#define CFG_TUD_HID_GENERIC 0 // not supported yet
#define CFG_TUD_CUSTOM_CLASS 0
/*------------------------------------------------------------------*/
/* CLASS DRIVER
@ -72,34 +67,15 @@
#define CFG_TUD_CDC_RX_BUFSIZE 1024
#define CFG_TUD_CDC_TX_BUFSIZE 1024
/* TX is sent automatically on every Start of Frame event ~ 1ms.
* If not enabled, application must call tud_cdc_flush() periodically
* Note: Enabled this could overflow device task, if it does, define
* CFG_TUD_TASK_QUEUE_SZ with large value
*/
#define CFG_TUD_CDC_FLUSH_ON_SOF 0
// Number of supported Logical Unit Number
#define CFG_TUD_MSC_MAXLUN 1
// Buffer size for each read/write transfer, the more the better
#define CFG_TUD_MSC_BUFSIZE (4*1024)
// Vendor name included in Inquiry response, max 8 bytes
#define CFG_TUD_MSC_VENDOR "Adafruit"
// Product name included in Inquiry response, max 16 bytes
#define CFG_TUD_MSC_PRODUCT "Feather nRF52840"
// Product revision string included in Inquiry response, max 4 bytes
#define CFG_TUD_MSC_PRODUCT_REV "1.0"
//--------------------------------------------------------------------+
// USB RAM PLACEMENT
//--------------------------------------------------------------------+
#define CFG_TUSB_ATTR_USBRAM
#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4)
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
#define BREAKPOINT_IGNORE_COUNT(n) \

View File

@ -40,12 +40,8 @@
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
//--------------------------------------------------------------------+
// from usb_desc.c for dynamic descriptor
extern tusb_desc_device_t usb_desc_dev;
extern usb_desc_cfg_t usb_desc_cfg;
// Serial string using unique Device ID
extern uint16_t usb_desc_str_serial[1+16];
extern char usb_desc_str_serial[1+16];
/* tinyusb function that handles power event (detected, ready, removed)
* We must call it within SD's SOC event handler, or set it as power event handler if SD is not enabled. */
@ -94,24 +90,10 @@ void usb_init(bool cdc_only)
tusb_hal_nrf_power_event(NRFX_POWER_USB_EVT_READY);
}
if ( cdc_only )
{
// Change PID to CDC only
usb_desc_dev.idProduct = USB_DESC_CDC_ONLY_PID;
// Remove MSC interface = reduce total interface + adjust config desc length
usb_desc_cfg.config.bNumInterfaces--;
usb_desc_cfg.config.wTotalLength -= sizeof(usb_desc_cfg.msc);
}
usb_desc_set_mode(cdc_only);
// Create Serial string descriptor
char tmp_serial[17];
sprintf(tmp_serial, "%08lX%08lX", NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
for(uint8_t i=0; i<16; i++)
{
usb_desc_str_serial[1+i] = tmp_serial[i];
}
sprintf(usb_desc_str_serial, "%08lX%08lX", NRF_FICR->DEVICEID[1], NRF_FICR->DEVICEID[0]);
// Init tusb stack
tusb_init();
@ -124,7 +106,7 @@ void usb_teardown(void)
// Abort all transfers
// Disable pull up
nrf_usbd_pullup_disable();
nrf_usbd_pullup_disable(NRF_USBD);
// Disable Interrupt
NVIC_DisableIRQ(USBD_IRQn);
@ -132,7 +114,7 @@ void usb_teardown(void)
// disable all interrupt
NRF_USBD->INTENCLR = NRF_USBD->INTEN;
nrf_usbd_disable();
nrf_usbd_disable(NRF_USBD);
sd_clock_hfclk_release();
sd_power_usbdetected_enable(false);

View File

@ -24,15 +24,6 @@
#include "usb_desc.h"
/*------------- Interface Numbering -------------*/
enum {
ITF_NUM_CDC = 0 ,
ITF_NUM_CDC_DATA ,
ITF_NUM_MSC ,
ITF_NUM_TOTAL
};
enum {
ITF_STR_LANGUAGE = 0 ,
ITF_STR_MANUFACTURER ,
@ -42,22 +33,95 @@ enum {
ITF_STR_MSC
};
/*------------- Endpoint Numbering & Size -------------*/
#define _EP_IN(x) (0x80 | (x))
#define _EP_OUT(x) (x)
static bool _cdc_only = false;
// CDC
#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 )
#define EP_CDC_NOTIF_SIZE 8
//--------------------------------------------------------------------+
// Device Descriptor
//--------------------------------------------------------------------+
tusb_desc_device_t desc_device =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 )
#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 )
// Use Interface Association Descriptor (IAD) for CDC
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
// Mass Storage
#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 )
#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 )
.idVendor = USB_DESC_VID,
.idProduct = USB_DESC_UF2_PID,
.bcdDevice = 0x0100,
#define EP_MSC_SIZE 64
.iManufacturer = 0x01,
.iProduct = 0x02,
.iSerialNumber = 0x03,
.bNumConfigurations = 0x01
};
// 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;
}
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
enum {
ITF_NUM_CDC = 0 ,
ITF_NUM_CDC_DATA ,
ITF_NUM_MSC ,
ITF_NUM_TOTAL
};
uint8_t const desc_configuration_cdc_msc[] =
{
// Interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, ITF_STR_CDC, 0x81, 8, 0x02, 0x82, 64),
// Interface number, string index, EP Out & EP In address, EP size
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, ITF_STR_MSC, 0x03, 0x83, 64),
};
uint8_t const desc_configuration_cdc_only[] =
{
// Interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL-1, 0, TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, ITF_STR_CDC, 0x81, 8, 0x02, 0x82, 64),
};
// 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 _cdc_only ? desc_configuration_cdc_only : desc_configuration_cdc_msc;
}
// Enumerate as CDC + MSC or CDC only
void usb_desc_set_mode(bool cdc_only)
{
_cdc_only = cdc_only;
if ( cdc_only )
{
// Change PID to CDC only
desc_device.idProduct = USB_DESC_CDC_ONLY_PID;
}
}
//--------------------------------------------------------------------+
// STRING DESCRIPTORS
@ -86,219 +150,51 @@ enum {
#endif
// Serial is 64-bit DeviceID -> 16 chars len
uint16_t usb_desc_str_serial[1+16] = { TUD_DESC_STR_HEADER(16) };
char usb_desc_str_serial[1+16];
// array of pointer to string descriptors
uint16_t const * const string_desc_arr [] = USB_STRING_DESCRIPTORS;
//--------------------------------------------------------------------+
// Device Descriptor
//--------------------------------------------------------------------+
tusb_desc_device_t usb_desc_dev =
char const* string_desc_arr [] =
{
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = 0x0200,
// Use Interface Association Descriptor (IAD) for CDC
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
.bDeviceClass = TUSB_CLASS_MISC,
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
.bDeviceProtocol = MISC_PROTOCOL_IAD,
.bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE,
.idVendor = USB_DESC_VID,
.idProduct = USB_DESC_UF2_PID,
.bcdDevice = 0x0100,
.iManufacturer = 0x01,
.iProduct = 0x02,
.iSerialNumber = 0x03,
.bNumConfigurations = 0x01
(const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
"Adafruit Industries", // 1: Manufacturer
"Bluefruit DFU", // 2: Product
usb_desc_str_serial, // 3: Serials, should use chip ID
"Bluefruit Serial", // 4: CDC Interface
"Bluefruit UF2", // 5: MSC Interface
};
//--------------------------------------------------------------------+
// Configuration Descriptor
//--------------------------------------------------------------------+
usb_desc_cfg_t usb_desc_cfg =
{
.config =
{
.bLength = sizeof(tusb_desc_configuration_t),
.bDescriptorType = TUSB_DESC_CONFIGURATION,
.wTotalLength = sizeof(usb_desc_cfg_t),
.bNumInterfaces = ITF_NUM_TOTAL,
.bConfigurationValue = 1,
.iConfiguration = 0x00,
.bmAttributes = TUSB_DESC_CONFIG_ATT_BUS_POWER,
.bMaxPower = TUSB_DESC_CONFIG_POWER_MA(100)
},
// up to 32 unicode characters (header make it 33)
static uint16_t _desc_str[33];
// IAD points to CDC Interfaces
.cdc =
// 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)
{
.iad =
{
.bLength = sizeof(tusb_desc_interface_assoc_t),
.bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION,
uint8_t chr_count;
.bFirstInterface = ITF_NUM_CDC,
.bInterfaceCount = 2,
.bFunctionClass = TUSB_CLASS_CDC,
.bFunctionSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
.bFunctionProtocol = CDC_COMM_PROTOCOL_ATCOMMAND,
.iFunction = 0
},
//------------- CDC Communication Interface -------------//
.comm_itf =
if ( index == 0)
{
.bLength = sizeof(tusb_desc_interface_t),
.bDescriptorType = TUSB_DESC_INTERFACE,
.bInterfaceNumber = ITF_NUM_CDC,
.bAlternateSetting = 0,
.bNumEndpoints = 1,
.bInterfaceClass = TUSB_CLASS_CDC,
.bInterfaceSubClass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL,
.bInterfaceProtocol = CDC_COMM_PROTOCOL_ATCOMMAND,
.iInterface = ITF_STR_CDC
},
memcpy(&_desc_str[1], string_desc_arr[0], 2);
chr_count = 1;
}else
{
if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL;
.header =
{
.bLength = sizeof(cdc_desc_func_header_t),
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_HEADER,
.bcdCDC = 0x0120
},
// Convert ASCII string into UTF-16
const char* str = string_desc_arr[index];
.call =
{
.bLength = sizeof(cdc_desc_func_call_management_t),
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_CALL_MANAGEMENT,
.bmCapabilities = { 0 },
.bDataInterface = ITF_NUM_CDC+1,
},
// Cap at max char
chr_count = strlen(str);
if ( chr_count > 31 ) chr_count = 31;
.acm =
for(uint8_t i=0; i<chr_count; i++)
{
.bLength = sizeof(cdc_desc_func_acm_t),
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_ABSTRACT_CONTROL_MANAGEMENT,
.bmCapabilities = { // 0x02
.support_line_request = 1,
}
},
.union_func =
{
.bLength = sizeof(cdc_desc_func_union_t), // plus number of
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
.bDescriptorSubType = CDC_FUNC_DESC_UNION,
.bControlInterface = ITF_NUM_CDC,
.bSubordinateInterface = ITF_NUM_CDC+1,
},
.ep_notif =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_CDC_NOTIF,
.bmAttributes = { .xfer = TUSB_XFER_INTERRUPT },
.wMaxPacketSize = { .size = EP_CDC_NOTIF_SIZE },
.bInterval = 0x10
},
//------------- CDC Data Interface -------------//
.data_itf =
{
.bLength = sizeof(tusb_desc_interface_t),
.bDescriptorType = TUSB_DESC_INTERFACE,
.bInterfaceNumber = ITF_NUM_CDC+1,
.bAlternateSetting = 0x00,
.bNumEndpoints = 2,
.bInterfaceClass = TUSB_CLASS_CDC_DATA,
.bInterfaceSubClass = 0,
.bInterfaceProtocol = 0,
.iInterface = 0x00
},
.ep_out =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_CDC_OUT,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE },
.bInterval = 0
},
.ep_in =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_CDC_IN,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = CFG_TUD_CDC_EPSIZE },
.bInterval = 0
},
},
//------------- Mass Storage-------------//
.msc =
{
.itf =
{
.bLength = sizeof(tusb_desc_interface_t),
.bDescriptorType = TUSB_DESC_INTERFACE,
.bInterfaceNumber = ITF_NUM_MSC,
.bAlternateSetting = 0x00,
.bNumEndpoints = 2,
.bInterfaceClass = TUSB_CLASS_MSC,
.bInterfaceSubClass = MSC_SUBCLASS_SCSI,
.bInterfaceProtocol = MSC_PROTOCOL_BOT,
.iInterface = ITF_STR_MSC
},
.ep_out =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_MSC_OUT,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = EP_MSC_SIZE},
.bInterval = 1
},
.ep_in =
{
.bLength = sizeof(tusb_desc_endpoint_t),
.bDescriptorType = TUSB_DESC_ENDPOINT,
.bEndpointAddress = EP_MSC_IN,
.bmAttributes = { .xfer = TUSB_XFER_BULK },
.wMaxPacketSize = { .size = EP_MSC_SIZE },
.bInterval = 1
_desc_str[1+i] = str[i];
}
}
};
// first byte is length (including header), second byte is string type
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2);
// tud_desc_set is required by tinyusb stack
// since CFG_TUD_DESC_AUTO is enabled, we only need to set string_arr
tud_desc_set_t tud_desc_set =
{
.device = &usb_desc_dev,
.config = &usb_desc_cfg,
.string_arr = (uint8_t const **) string_desc_arr,
.string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]),
.hid_report =
{
.generic = NULL,
.boot_keyboard = NULL,
.boot_mouse = NULL
return _desc_str;
}
};

View File

@ -28,9 +28,7 @@
#include "tusb.h"
#include "boards.h"
#ifdef __cplusplus
extern "C" {
#endif
void usb_desc_set_mode(bool cdc_only);
#ifndef USB_DESC_VID
#define USB_DESC_VID 0x239A
@ -44,43 +42,4 @@
#define USB_DESC_CDC_ONLY_PID 0x002A
#endif
/*------------- Configuration Descriptor -------------*/
typedef struct ATTR_PACKED
{
tusb_desc_configuration_t config;
//------------- CDC -------------//
struct ATTR_PACKED
{
tusb_desc_interface_assoc_t iad;
//CDC Control Interface
tusb_desc_interface_t comm_itf;
cdc_desc_func_header_t header;
cdc_desc_func_call_management_t call;
cdc_desc_func_acm_t acm;
cdc_desc_func_union_t union_func;
tusb_desc_endpoint_t ep_notif;
//CDC Data Interface
tusb_desc_interface_t data_itf;
tusb_desc_endpoint_t ep_out;
tusb_desc_endpoint_t ep_in;
}cdc;
//------------- Mass Storage -------------//
struct ATTR_PACKED
{
tusb_desc_interface_t itf;
tusb_desc_endpoint_t ep_out;
tusb_desc_endpoint_t ep_in;
} msc;
} usb_desc_cfg_t;
#ifdef __cplusplus
}
#endif
#endif /* USB_DESC_H_ */