diff --git a/Makefile b/Makefile index 3cf3bbe..ea55342 100644 --- a/Makefile +++ b/Makefile @@ -156,7 +156,7 @@ C_SOURCE_FILES += $(SDK_PATH)/libraries/util/nrf_assert.c ifneq ($(IS_NRF52840),) # src -C_SOURCE_FILES += $(SRC_PATH)/usb/tusb_descriptors.c +C_SOURCE_FILES += $(SRC_PATH)/usb/usb_desc.c C_SOURCE_FILES += $(SRC_PATH)/usb/usb.c C_SOURCE_FILES += $(SRC_PATH)/usb/msc_uf2.c C_SOURCE_FILES += $(SRC_PATH)/usb/uf2/ghostfat.c @@ -169,7 +169,6 @@ 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_auto_desc.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 diff --git a/src/main.c b/src/main.c index fd1b2dc..b3d6689 100644 --- a/src/main.c +++ b/src/main.c @@ -66,7 +66,7 @@ #include "nrf_usbd.h" #include "tusb.h" -void usb_init(void); +void usb_init(bool cdc_only); void usb_teardown(void); #else @@ -96,7 +96,7 @@ void usb_teardown(void); #define DFU_MAGIC_OTA_APPJUM BOOTLOADER_DFU_START // 0xB1 #define DFU_MAGIC_OTA_RESET 0xA8 #define DFU_MAGIC_SERIAL_ONLY_RESET 0x4e -#define DFU_MAGIC_UF2_SERIAL_RESET 0x57 +#define DFU_MAGIC_UF2_RESET 0x57 #define BOOTLOADER_VERSION_REGISTER NRF_TIMER2->CC[0] #define DFU_SERIAL_STARTUP_INTERVAL 1000 @@ -124,6 +124,7 @@ STATIC_ASSERT( APPDATA_ADDR_START == 0x6D000); void adafruit_factory_reset(void); +static uint32_t softdev_init(bool init_softdevice); // true if ble, false if serial bool _ota_dfu = false; @@ -140,6 +141,131 @@ void softdev_mbr_init(void) sd_mbr_command(&com); } +int main(void) +{ + // SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC + bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM); + + // Start Bootloader in BLE OTA mode + _ota_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM) || (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_RESET); + + // Serial only mode + bool serial_only_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET); + + // start either serial, uf2 or ble + bool dfu_start = _ota_dfu || serial_only_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_UF2_RESET); + + // Clear GPREGRET if it is our values + if (dfu_start) NRF_POWER->GPREGRET = 0; + + // Save bootloader version to pre-defined register, retrieved by application + BOOTLOADER_VERSION_REGISTER = (MK_BOOTLOADER_VERSION); + + // This check ensures that the defined fields in the bootloader corresponds with actual setting in the chip. + APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); + + board_init(); + bootloader_init(); + + // When updating SoftDevice, bootloader will reset before swapping SD + if (bootloader_dfu_sd_in_progress()) + { + APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() ); + APP_ERROR_CHECK( bootloader_dfu_sd_update_finalize() ); + } + + /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ + // DFU button pressed + dfu_start = dfu_start || button_pressed(BUTTON_DFU); + + // DFU + FRESET are pressed --> OTA + _ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ; + + if ( dfu_start || !bootloader_app_is_valid(DFU_BANK_0_REGION_START) ) + { + if ( _ota_dfu ) + { + // Enable BLE if in OTA + led_pwm_init(NRF_PWM1, LED_BLUE); + + softdev_init(!sd_inited); + sd_inited = true; + } + else + { + // otherwise USB for Serial & UF2 + usb_init(serial_only_dfu); + } + + // Initiate an update of the firmware. + APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0) ); + + if ( _ota_dfu ) + { + led_pwm_teardown(NRF_PWM1); + led_off(LED_BLUE); + + sd_softdevice_disable(); + }else + { + usb_teardown(); + } + } +#ifdef NRF52832_XXAA + else + { + /* Adafruit Modification + * Even DFU is not active, we still force an 1000 ms dfu serial mode when startup + * to support auto programming from Arduino IDE */ + bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL); + } +#endif + + // Adafruit Factory reset + if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) + { + adafruit_factory_reset(); + } + + // Reset Board + board_teardown(); + + // Jump to application if valid + if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress()) + { + // MBR must be init before start application + if ( !sd_inited ) softdev_mbr_init(); + + // Select a bank region to use as application region. + // @note: Only applications running from DFU_BANK_0_REGION_START is supported. + bootloader_app_start(DFU_BANK_0_REGION_START); + } + + NVIC_SystemReset(); +} + + +// Perform factory reset to erase Application + Data +void adafruit_factory_reset(void) +{ + // Blink fast RED and turn on BLUE when erasing + led_blink_fast(true); + led_on(LED_BLUE); + + // clear all App Data if any + if ( DFU_APP_DATA_RESERVED ) + { + nrf_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); + + // back to normal + led_blink_fast(false); + led_off(LED_BLUE); +} + /** * Initializes the SoftDevice and the BLE event interrupt. * @param[in] init_softdevice true if SoftDevice should be initialized. The SoftDevice must only @@ -218,130 +344,6 @@ static uint32_t softdev_init(bool init_softdevice) return NRF_SUCCESS; } -int main(void) -{ - // SD is already Initialized in case of BOOTLOADER_DFU_OTA_MAGIC - bool sd_inited = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM); - - // Start Bootloader in BLE OTA mode - _ota_dfu = (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_APPJUM) || - (NRF_POWER->GPREGRET == DFU_MAGIC_OTA_RESET); - - // - - // start bootloader either serial or ble - bool dfu_start = _ota_dfu || (NRF_POWER->GPREGRET == DFU_MAGIC_SERIAL_ONLY_RESET); - - // Clear GPREGRET if it is our values - if (dfu_start) NRF_POWER->GPREGRET = 0; - - // Save bootloader version to pre-defined register, retrieved by application - BOOTLOADER_VERSION_REGISTER = (MK_BOOTLOADER_VERSION); - - // This check ensures that the defined fields in the bootloader corresponds with actual setting in the chip. - APP_ERROR_CHECK_BOOL(*((uint32_t *)NRF_UICR_BOOT_START_ADDRESS) == BOOTLOADER_REGION_START); - - board_init(); - bootloader_init(); - - // When updating SoftDevice, bootloader will reset before swapping SD - if (bootloader_dfu_sd_in_progress()) - { - APP_ERROR_CHECK( bootloader_dfu_sd_update_continue() ); - APP_ERROR_CHECK( bootloader_dfu_sd_update_finalize() ); - } - - /*------------- Determine DFU mode (Serial, OTA, FRESET or normal) -------------*/ - // DFU button pressed - dfu_start = dfu_start || button_pressed(BUTTON_DFU); - - // DFU + FRESET are pressed --> OTA - _ota_dfu = _ota_dfu || ( button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) ; - - if ( dfu_start || !bootloader_app_is_valid(DFU_BANK_0_REGION_START) ) - { - if ( _ota_dfu ) - { - // Enable BLE if in OTA - led_pwm_init(NRF_PWM1, LED_BLUE); - - softdev_init(!sd_inited); - sd_inited = true; - } - else - { - // otherwise USB for Serial & UF2 - usb_init(); - } - - // Initiate an update of the firmware. - APP_ERROR_CHECK( bootloader_dfu_start(_ota_dfu, 0) ); - - if ( _ota_dfu ) - { - led_pwm_teardown(NRF_PWM1); - led_off(LED_BLUE); - - sd_softdevice_disable(); - }else - { - usb_teardown(); - } - } -#ifdef NRF52832_XXAA - else - { - /* Adafruit Modification - * Even DFU is not active, we still force an 1000 ms dfu serial mode when startup - * to support auto programming from Arduino IDE */ - bootloader_dfu_start(false, DFU_SERIAL_STARTUP_INTERVAL); - } -#endif - - // Adafruit Factory reset - if ( !button_pressed(BUTTON_DFU) && button_pressed(BUTTON_FRESET) ) - { - adafruit_factory_reset(); - } - - // Reset Board - board_teardown(); - - // Jump to application if valid - if (bootloader_app_is_valid(DFU_BANK_0_REGION_START) && !bootloader_dfu_sd_in_progress()) - { - // MBR must be init before start application - if ( !sd_inited ) softdev_mbr_init(); - - // Select a bank region to use as application region. - // @note: Only applications running from DFU_BANK_0_REGION_START is supported. - bootloader_app_start(DFU_BANK_0_REGION_START); - } - - NVIC_SystemReset(); -} - - -// Perform factory reset to erase Application + Data -void adafruit_factory_reset(void) -{ - // Blink fast RED and turn on BLUE when erasing - led_blink_fast(true); - led_on(LED_BLUE); - - // clear all App Data if any - if ( DFU_APP_DATA_RESERVED ) - { - nrf_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); - - // back to normal - led_blink_fast(false); - led_off(LED_BLUE); -} //--------------------------------------------------------------------+ // Error Handler diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h index 03b647d..6681ef8 100644 --- a/src/usb/tusb_config.h +++ b/src/usb/tusb_config.h @@ -68,10 +68,7 @@ //--------------------------------------------------------------------+ /*------------- Core -------------*/ -#define CFG_TUD_DESC_AUTO 1 -#define CFG_TUD_DESC_VID 0x239A -#define CFG_TUD_DESC_PID 0x0029 - +#define CFG_TUD_DESC_AUTO 0 #define CFG_TUD_ENDOINT0_SIZE 64 //------------- Class enabled -------------// diff --git a/src/usb/tusb_descriptors.c b/src/usb/tusb_descriptors.c deleted file mode 100644 index 302cc7b..0000000 --- a/src/usb/tusb_descriptors.c +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************/ -/*! - @file tusb_descriptors.c - @author hathach (tinyusb.org) - - @section LICENSE - - Software License Agreement (BSD License) - - Copyright (c) 2013, hathach (tinyusb.org) - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of the copyright holders nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - This file is part of the tinyusb stack. -*/ -/**************************************************************************/ - -#include "tusb.h" - -//--------------------------------------------------------------------+ -// STRING DESCRIPTORS -//--------------------------------------------------------------------+ - -// array of pointer to string descriptors -uint16_t const * const string_desc_arr [] = -{ - // 0: is supported language = English - TUD_DESC_STRCONV(0x0409), - - // 1: Manufacturer - TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'), - - // 2: Product - TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','n','R','F','5','2','8','4','0'), - - // 3: Serials TODO use chip ID - TUD_DESC_STRCONV('1', '2', '3', '4'), - - // 4: CDC Interface - TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','e','r','i','a','l'), - - // 5: MSC Interface - TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','t','o','r','a','g','e'), - - // 6: Custom Interface - TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','C','u','s','t','o','m') -}; - - -// 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 = NULL, - .config = NULL, - .string_arr = (uint8_t const **) string_desc_arr, - .hid_report = - { - .generic = NULL, - .boot_keyboard = NULL, - .boot_mouse = NULL - } -}; diff --git a/src/usb/usb.c b/src/usb/usb.c index 16ec6a6..0dba4b4 100644 --- a/src/usb/usb.c +++ b/src/usb/usb.c @@ -55,7 +55,7 @@ extern void tusb_hal_nrf_power_event(uint32_t event); //------------- IMPLEMENTATION -------------// -void usb_init(void) +void usb_init(bool cdc_only) { // USB power may already be ready at this time -> no event generated // We need to invoke the handler based on the status initially diff --git a/src/usb/usb_desc.c b/src/usb/usb_desc.c new file mode 100644 index 0000000..1f2b687 --- /dev/null +++ b/src/usb/usb_desc.c @@ -0,0 +1,312 @@ +/**************************************************************************/ +/*! + @file usb_desc.c + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This file is part of the tinyusb stack. +*/ +/**************************************************************************/ + +#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 , + ITF_STR_PRODUCT , + ITF_STR_SERIAL , + ITF_STR_CDC , + ITF_STR_MSC +}; + +/*------------- Endpoint Numbering & Size -------------*/ +#define _EP_IN(x) (0x80 | (x)) +#define _EP_OUT(x) (x) + +// CDC +#define EP_CDC_NOTIF _EP_IN ( ITF_NUM_CDC+1 ) +#define EP_CDC_NOTIF_SIZE 8 + +#define EP_CDC_OUT _EP_OUT( ITF_NUM_CDC+2 ) +#define EP_CDC_IN _EP_IN ( ITF_NUM_CDC+2 ) + +// Mass Storage +#define EP_MSC_OUT _EP_OUT( ITF_NUM_MSC+1 ) +#define EP_MSC_IN _EP_IN ( ITF_NUM_MSC+1 ) + +//--------------------------------------------------------------------+ +// STRING DESCRIPTORS +//--------------------------------------------------------------------+ + +// array of pointer to string descriptors +uint16_t const * const string_desc_arr [] = +{ + // 0: is supported language = English + TUD_DESC_STRCONV(0x0409), + + // 1: Manufacturer + TUD_DESC_STRCONV('A','d','a','f','r','u','i','t',' ','I','n','d','u','s','t','r','i','e','s'), + + // 2: Product + TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','n','R','F','5','2','8','4','0', ' ', 'D','F','U'), + + // 3: Serials TODO use chip ID + TUD_DESC_STRCONV('1', '2', '3', '4'), + + // 4: CDC Interface + TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','S','e','r','i','a','l'), + + // 5: MSC Interface + TUD_DESC_STRCONV('B','l','u','e','f','r','u','i','t',' ','U','F','2'), +}; + +//--------------------------------------------------------------------+ +// Device Descriptor +//--------------------------------------------------------------------+ +tusb_desc_device_t usb_desc_dev = +{ + .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 +}; + +//--------------------------------------------------------------------+ +// 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) + }, + + // 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 = CFG_TUD_MSC_EPSIZE}, + .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 = CFG_TUD_MSC_EPSIZE}, + .bInterval = 1 + } + } +}; + + +// 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 + } +}; diff --git a/src/usb/usb_desc.h b/src/usb/usb_desc.h new file mode 100644 index 0000000..c5e66cc --- /dev/null +++ b/src/usb/usb_desc.h @@ -0,0 +1,95 @@ +/**************************************************************************/ +/*! + @file usb_desc.h + @author hathach (tinyusb.org) + + @section LICENSE + + Software License Agreement (BSD License) + + Copyright (c) 2013, hathach (tinyusb.org) + Copyright (c) 2018, Adafruit Industries (adafruit.com) + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holders nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +/**************************************************************************/ + +#ifndef USB_DESC_H_ +#define USB_DESC_H_ + +#include "tusb.h" + +#ifdef __cplusplus + extern "C" { +#endif + +#define USB_DESC_VID 0x239A + +#define USB_DESC_UF2_PID 0x0029 +#define USB_DESC_SERIAL_ONLY_PID 0x002A + + +/*------------- 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; + + +extern tusb_desc_device_t usb_desc_dev; +extern usb_desc_cfg_t usb_desc_cfg; + +#ifdef __cplusplus + } +#endif + +#endif /* USB_DESC_H_ */