update repo to work with latest tinyusb and nrfx module
This commit is contained in:
parent
3d99a55940
commit
126115a2cb
5
Makefile
5
Makefile
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "nrf_nvmc.h"
|
||||
#include "nrfx_nvmc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -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);
|
||||
|
@ -2,13 +2,17 @@
|
||||
#define NRFX_CONFIG_H__
|
||||
|
||||
// Power
|
||||
#define NRFX_POWER_ENABLED 1
|
||||
#define NRFX_POWER_CONFIG_IRQ_PRIORITY 7
|
||||
#define NRFX_POWER_ENABLED 1
|
||||
#define NRFX_POWER_DEFAULT_CONFIG_IRQ_PRIORITY 7
|
||||
|
||||
#define NRFX_CLOCK_ENABLED 0
|
||||
|
||||
#define NRFX_NVMC_ENABLED 1
|
||||
|
||||
// UART
|
||||
#ifdef NRF52832_XXAA
|
||||
#define NRFX_UART_ENABLED 1
|
||||
#define NRFX_UART0_ENABLED 1
|
||||
#define NRFX_UART_ENABLED 1
|
||||
#define NRFX_UART0_ENABLED 1
|
||||
|
||||
#define NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY 7
|
||||
#define NRFX_UART_DEFAULT_CONFIG_HWFC NRF_UART_HWFC_DISABLED
|
||||
|
@ -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;
|
||||
|
||||
switch ( scsi_cmd[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) )
|
||||
{
|
||||
memcpy(buffer, response, resplen);
|
||||
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
|
||||
|
@ -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) \
|
||||
|
@ -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);
|
||||
|
@ -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 =
|
||||
// up to 32 unicode characters (header make it 33)
|
||||
static uint16_t _desc_str[33];
|
||||
|
||||
// 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)
|
||||
{
|
||||
.config =
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0)
|
||||
{
|
||||
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;
|
||||
|
||||
// Convert ASCII string into UTF-16
|
||||
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++)
|
||||
{
|
||||
.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)
|
||||
},
|
||||
|
||||
// IAD points to CDC Interfaces
|
||||
.cdc =
|
||||
{
|
||||
.iad =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_interface_assoc_t),
|
||||
.bDescriptorType = TUSB_DESC_INTERFACE_ASSOCIATION,
|
||||
|
||||
.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 =
|
||||
{
|
||||
.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
|
||||
},
|
||||
|
||||
.header =
|
||||
{
|
||||
.bLength = sizeof(cdc_desc_func_header_t),
|
||||
.bDescriptorType = TUSB_DESC_CLASS_SPECIFIC,
|
||||
.bDescriptorSubType = CDC_FUNC_DESC_HEADER,
|
||||
.bcdCDC = 0x0120
|
||||
},
|
||||
|
||||
.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,
|
||||
},
|
||||
|
||||
.acm =
|
||||
{
|
||||
.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;
|
||||
}
|
||||
|
@ -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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user