diff --git a/examples/device/cdc_msc_hid/src/main.c b/examples/device/cdc_msc_hid/src/main.c index 99e9ff690..c5e7a3068 100644 --- a/examples/device/cdc_msc_hid/src/main.c +++ b/examples/device/cdc_msc_hid/src/main.c @@ -40,12 +40,18 @@ * - 1000 ms : device mounted * - 2500 ms : device is suspended */ -static uint32_t blink_interval_ms = 250; +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); -extern void virtual_com_task(void); -extern void usb_hid_task(void); +extern void cdc_task(void); +extern void hid_task(void); /*------------- MAIN -------------*/ int main(void) @@ -62,11 +68,11 @@ int main(void) led_blinking_task(); #if CFG_TUD_CDC - virtual_com_task(); + cdc_task(); #endif #if CFG_TUD_HID - usb_hid_task(); + hid_task(); #endif } @@ -77,7 +83,7 @@ int main(void) // USB CDC //--------------------------------------------------------------------+ #if CFG_TUD_CDC -void virtual_com_task(void) +void cdc_task(void) { if ( tud_cdc_connected() ) { @@ -134,7 +140,7 @@ enum REPORT_ID_MOUSE }; -void usb_hid_task(void) +void hid_task(void) { // Poll every 10ms const uint32_t interval_ms = 10; @@ -218,13 +224,13 @@ void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uin // Invoked when device is mounted void tud_mount_cb(void) { - blink_interval_ms = 1000; + blink_interval_ms = BLINK_MOUNTED; } // Invoked when device is unmounted void tud_umount_cb(void) { - blink_interval_ms = 250; + blink_interval_ms = BLINK_NOT_MOUNTED; } // Invoked when usb bus is suspended @@ -233,13 +239,13 @@ void tud_umount_cb(void) void tud_suspend_cb(bool remote_wakeup_en) { (void) remote_wakeup_en; - blink_interval_ms = 2500; + blink_interval_ms = BLINK_SUSPENDED; } // Invoked when usb bus is resumed void tud_resume_cb(void) { - blink_interval_ms = 1000; + blink_interval_ms = BLINK_MOUNTED; } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h index 13709f5d1..2614bcb6f 100644 --- a/examples/device/cdc_msc_hid/src/tusb_config.h +++ b/examples/device/cdc_msc_hid/src/tusb_config.h @@ -46,8 +46,8 @@ #define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE #endif -#define CFG_TUSB_DEBUG 2 #define CFG_TUSB_OS OPT_OS_NONE +#define CFG_TUSB_DEBUG 2 /* 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 @@ -67,6 +67,7 @@ //-------------------------------------------------------------------- // DEVICE CONFIGURATION //-------------------------------------------------------------------- + #define CFG_TUD_ENDOINT0_SIZE 64 //------------- CLASS -------------// @@ -88,6 +89,7 @@ //-------------------------------------------------------------------- // MSC //-------------------------------------------------------------------- + // Number of supported Logical Unit Number (At least 1) #define CFG_TUD_MSC_MAXLUN 1 @@ -113,7 +115,6 @@ */ #define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1 - #ifdef __cplusplus } #endif diff --git a/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject b/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject index ad236ae66..ee387958e 100644 --- a/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject +++ b/examples/device/cdc_msc_hid_freertos/ses/nrf5x/nrf5x.emProject @@ -20,7 +20,7 @@ arm_target_interface_type="SWD" build_treat_warnings_as_errors="No" c_preprocessor_definitions="NRF52840_XXAA;__nRF_FAMILY;ARM_MATH_CM4;FLASH_PLACEMENT=1;CFG_TUSB_MCU=OPT_MCU_NRF5X" - c_user_include_directories="./;../../src;$(rootDir)/hw/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(nrfxDir)/..;$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(freertosDir)/Source/include;$(freertosDir)/Source/portable/GCC/ARM_CM4F" + c_user_include_directories="./;../../src;$(rootDir)/hw/cmsis/Include;$(rootDir)/hw;$(rootDir)/src;$(nrfxDir)/..;$(nrfxDir);$(nrfxDir)/mdk;$(nrfxDir)/hal;$(nrfxDir)/drivers/include;$(nrfxDir)/drivers/src;$(freertosDir)/Source/include;$(freertosDir)/Source/portable/GCC/ARM_CM4F" debug_register_definition_file="nrf52840_Registers.xml" debug_target_connection="J-Link" gcc_enable_all_warnings="Yes" diff --git a/examples/device/cdc_msc_hid_freertos/src/main.c b/examples/device/cdc_msc_hid_freertos/src/main.c index 2014fb1a4..2877cd382 100644 --- a/examples/device/cdc_msc_hid_freertos/src/main.c +++ b/examples/device/cdc_msc_hid_freertos/src/main.c @@ -24,9 +24,6 @@ * This file is part of the TinyUSB stack. */ -//--------------------------------------------------------------------+ -// INCLUDE -//--------------------------------------------------------------------+ #include #include #include @@ -41,12 +38,22 @@ #include "tusb.h" //--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF +// MACRO CONSTANT TYPEDEF PROTYPES //--------------------------------------------------------------------+ -//--------------------------------------------------------------------+ -// INTERNAL OBJECT & FUNCTION DECLARATION -//--------------------------------------------------------------------+ +/* 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, +}; + +TimerHandle_t blink_tm; + void led_blinky_cb(TimerHandle_t xTimer); void usb_device_task(void* param); @@ -56,8 +63,8 @@ int main(void) board_init(); // soft timer for blinky - TimerHandle_t tm_hdl = xTimerCreate(NULL, pdMS_TO_TICKS(1000), true, NULL, led_blinky_cb); - xTimerStart(tm_hdl, 0); + blink_tm = xTimerCreate(NULL, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), true, NULL, led_blinky_cb); + xTimerStart(blink_tm, 0); tusb_init(); @@ -71,7 +78,8 @@ int main(void) #endif #if CFG_TUD_HID - extern void usb_hid_task(void* params); + extern void hid_task(void* params); + xTaskCreate( hid_task, "hid", 256, NULL, configMAX_PRIORITIES-2, NULL); #endif vTaskStartScheduler(); @@ -130,6 +138,7 @@ void cdc_task(void* params) } } +// Invoked when cdc when line state changed e.g connected/disconnected void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { (void) itf; @@ -141,85 +150,134 @@ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) tud_cdc_write_str("\r\nTinyUSB CDC MSC HID device with FreeRTOS example\r\n"); } } + +// Invoked when CDC interface received data from host +void tud_cdc_rx_cb(uint8_t itf) +{ + (void) itf; +} + #endif //--------------------------------------------------------------------+ // USB HID //--------------------------------------------------------------------+ #if CFG_TUD_HID -void usb_hid_task(void* params) + +// Must match with ID declared by HID Report Descriptor, better to be in header file +enum +{ + REPORT_ID_KEYBOARD = 1, + REPORT_ID_MOUSE +}; + +void hid_task(void* params) { (void) params; - // Poll every 10ms - const uint32_t interval_ms = 10; - static uint32_t start_ms = 0; - - if ( board_millis() < start_ms + interval_ms) return; // not enough time - start_ms += interval_ms; - - uint32_t const btn = board_button_read(); - - /*------------- Keyboard -------------*/ - if ( tud_hid_keyboard_ready() ) + while (1) { - if ( btn ) - { - uint8_t keycode[6] = { 0 }; + // Poll every 10ms + vTaskDelay(pdMS_TO_TICKS(10)); - for(uint8_t i=0; i < 6; i++) - { - if ( btn & (1 << i) ) keycode[i] = HID_KEY_A + i; - } + uint32_t const btn = board_button_read(); - tud_hid_keyboard_report(0, keycode); - }else + // Remote wakeup + if ( tud_suspended() && btn ) { - // Null means all zeroes keycodes - tud_hid_keyboard_report(0, NULL); + // Wake up host if we are in suspend mode + // and REMOTE_WAKEUP feature is enabled by host + tud_remote_wakeup(); } - } + /*------------- Mouse -------------*/ + if ( tud_hid_ready() ) + { + if ( btn ) + { + int8_t const delta = 5; + tud_hid_mouse_move(REPORT_ID_MOUSE, delta, delta); // right + down - /*------------- Mouse -------------*/ - if ( tud_hid_mouse_ready() ) - { - enum { DELTA = 5 }; + // delay a bit before attempt to send keyboard report + vTaskDelay(pdMS_TO_TICKS(2)); + } + } - if ( btn & 0x01 ) tud_hid_mouse_move(-DELTA, 0); // left - if ( btn & 0x02 ) tud_hid_mouse_move( DELTA, 0); // right - if ( btn & 0x04 ) tud_hid_mouse_move( 0 , -DELTA); // up - if ( btn & 0x08 ) tud_hid_mouse_move( 0 , DELTA); // down + /*------------- Keyboard -------------*/ + if ( tud_hid_ready() ) + { + // use to avoid send multiple consecutive zero report for keyboard + static bool has_key = false; + + if ( btn ) + { + uint8_t keycode[6] = { 0 }; + keycode[0] = HID_KEY_A; + + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode); + + has_key = true; + }else + { + // send empty key report if previously has key pressed + if (has_key) tud_hid_keyboard_key_release(REPORT_ID_KEYBOARD); + has_key = false; + } + } } } uint16_t tud_hid_get_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen) { // TODO not Implemented + (void) report_id; + (void) report_type; + (void) buffer; + (void) reqlen; + return 0; } void tud_hid_set_report_cb(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize) { // TODO not Implemented + (void) report_id; + (void) report_type; + (void) buffer; + (void) bufsize; } + #endif //--------------------------------------------------------------------+ -// tinyusb callbacks +// Device callbacks //--------------------------------------------------------------------+ + +// Invoked when device is mounted void tud_mount_cb(void) { - + xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); } +// Invoked when device is unmounted void tud_umount_cb(void) { + xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_NOT_MOUNTED), 0); } -void tud_cdc_rx_cb(uint8_t itf) +// 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) itf; + (void) remote_wakeup_en; + xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_SUSPENDED), 0); +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + xTimerChangePeriod(blink_tm, pdMS_TO_TICKS(BLINK_MOUNTED), 0); } //--------------------------------------------------------------------+ diff --git a/examples/device/cdc_msc_hid_freertos/src/msc_app.c b/examples/device/cdc_msc_hid_freertos/src/msc_app.c deleted file mode 100644 index d50af7810..000000000 --- a/examples/device/cdc_msc_hid_freertos/src/msc_app.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2018, hathach (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 "tusb.h" - -#if CFG_TUD_MSC - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -//--------------------------------------------------------------------+ -// tinyusb callbacks -//--------------------------------------------------------------------+ - -// 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) -{ - // read10 & write10 has their own callback and MUST not be handled here - - void const* response = NULL; - 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); - - // negative means error -> tinyusb could stall and/or response with failed status - resplen = -1; - break; - } - - // return resplen must not larger than bufsize - if ( resplen > bufsize ) resplen = bufsize; - - if ( response && (resplen > 0) ) - { - if(in_xfer) - { - memcpy(buffer, response, resplen); - }else - { - // SCSI output - } - } - - return resplen; -} - - -#endif diff --git a/examples/device/cdc_msc_hid_freertos/src/msc_disk_ram.c b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c similarity index 68% rename from examples/device/cdc_msc_hid_freertos/src/msc_disk_ram.c rename to examples/device/cdc_msc_hid_freertos/src/msc_disk.c index 1906edb8b..8bcd056e3 100644 --- a/examples/device/cdc_msc_hid_freertos/src/msc_disk_ram.c +++ b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c @@ -49,7 +49,7 @@ enum #ifdef DISK_READONLY const #endif -static uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = +uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { //------------- Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; @@ -82,7 +82,7 @@ static uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = // second entry is readme file 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , ' ' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, - sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's filesize (4 Bytes) + sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files ize (4 Bytes) }, //------------- Readme Content -------------// @@ -96,7 +96,7 @@ int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buff { (void) lun; - uint8_t* addr = msc_disk[lba] + offset; + uint8_t const* addr = msc_disk[lba] + offset; memcpy(buffer, addr, bufsize); return bufsize; @@ -111,6 +111,8 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* #ifndef DISK_READONLY uint8_t* addr = msc_disk[lba] + offset; memcpy(addr, buffer, bufsize); +#else + (void) lba; (void) offset; (void) buffer; #endif return bufsize; @@ -124,4 +126,67 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz *block_size = DISK_BLOCK_SIZE; } +// 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) +{ + // read10 & write10 has their own callback and MUST not be handled here + + void const* response = NULL; + 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); + + // negative means error -> tinyusb could stall and/or response with failed status + resplen = -1; + break; + } + + // return resplen must not larger than bufsize + if ( resplen > bufsize ) resplen = bufsize; + + if ( response && (resplen > 0) ) + { + if(in_xfer) + { + memcpy(buffer, response, resplen); + }else + { + // SCSI output + } + } + + return resplen; +} + #endif diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h index d288bf296..9444ca890 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -40,7 +40,12 @@ #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_FREERTOS #define CFG_TUSB_DEBUG 2 @@ -65,40 +70,13 @@ #define CFG_TUD_ENDOINT0_SIZE 64 -/*------------- Descriptors -------------*/ - -/* Enable auto generated descriptor, tinyusb will try its best to create - * descriptor ( device, configuration, hid ) that matches enabled CFG_* in this file - * - * Note: All CFG_TUD_DESC_* are relevant only if CFG_TUD_DESC_AUTO is enabled - */ -#define CFG_TUD_DESC_AUTO 1 - -// LPC175x_6x's endpoint type (bulk/interrupt/iso) are fixed by its number -// Therefore we need to force endpoint number to correct type on lpc17xx -#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X -#define CFG_TUD_DESC_CDC_EPNUM_NOTIF 1 -#define CFG_TUD_DESC_CDC_EPNUM 2 -#define CFG_TUD_DESC_MSC_EPNUM 5 -#define CFG_TUD_DESC_HID_KEYBOARD_EPNUM 4 -#define CFG_TUD_DESC_HID_MOUSE_EPNUM 7 -#endif - - //------------- CLASS -------------// #define CFG_TUD_CDC 1 #define CFG_TUD_MSC 1 +#define CFG_TUD_HID 1 -#define CFG_TUD_HID 0 -#define CFG_TUD_HID_KEYBOARD 0 -#define CFG_TUD_HID_MOUSE 0 - -/* Use Boot Protocol for Keyboard, Mouse. Enable this will create separated HID interface - * require more IN endpoints. If disabled, they they are all packed into a single - * multiple report interface called "Generic". */ -#define CFG_TUD_HID_KEYBOARD_BOOT 1 -#define CFG_TUD_HID_MOUSE_BOOT 1 - +#define CFG_TUD_MIDI 0 +#define CFG_TUD_CUSTOM_CLASS 0 //-------------------------------------------------------------------- // CDC @@ -131,10 +109,9 @@ // HID //-------------------------------------------------------------------- -/* Use the HID_ASCII_TO_KEYCODE lookup if CFG_TUD_HID_KEYBOARD is enabled. - * This will occupies 256 bytes of ROM. It will also enable the use of 2 extra APIs +/* Use the HID_ASCII_TO_KEYCODE lookup + * This will occupies 256 bytes of ROM. It will also enable the use of extra APIs * - tud_hid_keyboard_send_char() - * - tud_hid_keyboard_send_string() */ #define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1 diff --git a/examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c b/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c similarity index 53% rename from examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c rename to examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c index 5f6d9e032..28a4b28d1 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_descriptors.c +++ b/examples/device/cdc_msc_hid_freertos/src/usb_descriptors.c @@ -26,19 +26,14 @@ #include "tusb.h" -// If HID Generic interface is generated -#define AUTO_DESC_HID_GENERIC (CFG_TUD_HID && ((CFG_TUD_HID_KEYBOARD && !CFG_TUD_HID_KEYBOARD_BOOT) || \ - (CFG_TUD_HID_MOUSE && !CFG_TUD_HID_MOUSE_BOOT)) ) - /* 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] HID Generic | Boot Mouse | Boot Keyboard | MSC | CDC [LSB] + * [MSB] HID | MSC | CDC [LSB] */ -#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) -#define CFG_TUD_DESC_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | \ - _PID_MAP(HID_KEYBOARD, 2) | _PID_MAP(HID_MOUSE, 3) | (AUTO_DESC_HID_GENERIC << 4) ) +#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) ) //------------- Device Descriptors -------------// tusb_desc_device_t const desc_device = @@ -62,7 +57,7 @@ tusb_desc_device_t const desc_device = .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, .idVendor = 0xCafe, - .idProduct = CFG_TUD_DESC_PID, + .idProduct = USB_PID, .bcdDevice = 0x0100, .iManufacturer = 0x01, @@ -72,59 +67,105 @@ tusb_desc_device_t const desc_device = .bNumConfigurations = 0x01 }; +//------------- HID Report Descriptor -------------// +enum +{ + REPORT_ID_KEYBOARD = 1, + REPORT_ID_MOUSE +}; + +uint8_t const desc_hid_report[] = +{ + HID_REPORT_DESC_KEYBOARD( HID_REPORT_ID(REPORT_ID_KEYBOARD), ), + HID_REPORT_DESC_MOUSE ( HID_REPORT_ID(REPORT_ID_MOUSE), ) +}; + +//------------- Configuration Descriptor -------------// +enum +{ + #if CFG_TUD_CDC + ITF_NUM_CDC = 0, + ITF_NUM_CDC_DATA, + #endif + + #if CFG_TUD_MSC + ITF_NUM_MSC, + #endif + + #if CFG_TUD_HID + ITF_NUM_HID, + #endif + + ITF_NUM_TOTAL +}; + +enum +{ + CONFIG_DESC_LEN = sizeof(tusb_desc_configuration_t) + CFG_TUD_CDC*TUD_CDC_DESC_LEN + CFG_TUD_MSC*TUD_MSC_DESC_LEN + CFG_TUD_HID*TUD_HID_DESC_LEN +}; + +#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX + // 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 ... + // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force + // endpoint number for MSC to 5 + #define EPNUM_MSC 0x05 +#else + #define EPNUM_MSC 0x03 +#endif + +uint8_t const desc_configuration[] = +{ + // Config: self-powered with remote wakeup support, max power up to 100 mA + TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_DESC_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_CDC + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x81, 8, 0x02, 0x82, 64), +#endif + +#if CFG_TUD_MSC + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 +#endif + +#if CFG_TUD_HID + TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_KEYBOARD, sizeof(desc_hid_report), 0x84, 16, 10) +#endif +}; + //------------- String Descriptors -------------// // array of pointer to string descriptors uint16_t const * const string_desc_arr [] = { - // 0: is supported language = English - TUD_DESC_STRCONV(0x0409), + // 0: is supported language = English + TUD_DESC_STRCONV(0x0409), - // 1: Manufacturer - TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', '.', 'o', 'r', 'g'), + // 1: Manufacturer + TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', '.', 'o', 'r', 'g'), - // 2: Product - TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', ' ', 'd', 'e', 'v', 'i', 'c', 'e'), + // 2: Product + TUD_DESC_STRCONV('t', 'i', 'n', 'y', 'u', 's', 'b', ' ', 'd', 'e', 'v', 'i', 'c', 'e'), - // 3: Serials, should use chip ID - TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6'), + // 3: Serials, should use chip ID + TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6'), -#if CFG_TUD_CDC - // 4: CDC Interface - TUD_DESC_STRCONV('t','u','s','b',' ','c','d','c'), -#endif + // 4: CDC Interface + TUD_DESC_STRCONV('t','u','s','b',' ','c','d','c'), -#if CFG_TUD_MSC - // 5: MSC Interface - TUD_DESC_STRCONV('t','u','s','b',' ','m','s','c'), -#endif - -#if CFG_TUD_HID_KEYBOARD - // 6: Keyboard - TUD_DESC_STRCONV('t','u','s','b',' ','k','e','y','b','o','a','r','d'), -#endif - -#if CFG_TUD_HID_MOUSE - // 7: Mouse - TUD_DESC_STRCONV('t','u','s','b',' ','m', 'o','u','s','e'), -#endif + // 5: MSC Interface + TUD_DESC_STRCONV('t','u','s','b',' ','m','s','c'), + // 6: HID + TUD_DESC_STRCONV('t','u','s','b',' ','h','i','d') }; // 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 = &desc_device, - .config = NULL, + .config = desc_configuration, .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 - } + .hid_report = desc_hid_report, }; - diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c index 4f31c6d3f..1c9a5ded2 100644 --- a/examples/host/cdc_msc_hid/src/main.c +++ b/examples/host/cdc_msc_hid/src/main.c @@ -37,8 +37,8 @@ void print_greeting(void); void led_blinking_task(void); -extern void virtual_com_task(void); -extern void usb_hid_task(void); +extern void cdc_task(void); +extern void hid_task(void); /*------------- MAIN -------------*/ int main(void) @@ -56,11 +56,11 @@ int main(void) led_blinking_task(); #if CFG_TUH_CDC - virtual_com_task(); + cdc_task(); #endif #if CFG_TUD_HID - usb_hid_task(); + hid_task(); #endif } @@ -100,7 +100,7 @@ void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_i tuh_cdc_receive(dev_addr, serial_in_buffer, sizeof(serial_in_buffer), true); // waiting for next data } -void virtual_com_task(void) +void cdc_task(void) { } @@ -111,7 +111,7 @@ void virtual_com_task(void) // USB HID //--------------------------------------------------------------------+ #if CFG_TUH_HID_KEYBOARD -void usb_hid_task(void) +void hid_task(void) { }