diff --git a/.travis.yml b/.travis.yml index 274d05722..1ee7b8723 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,8 +17,4 @@ before_script: - (! var_search "${TRAVIS_SDK-}" arm || arm-none-eabi-gcc --version) script: - - make -j2 -C examples/device/cdc_msc_hid BOARD=metro_m0_express - - make -j2 -C examples/device/cdc_msc_hid BOARD=metro_m4_express - - make -j2 -C examples/device/cdc_msc_hid BOARD=stm32f407g_disc1 - - make -j2 -C examples/device/cdc_msc_hid BOARD=pca10056 - + - python3 tools/build_all.py diff --git a/README.md b/README.md index 15d387197..ab288cbec 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Support multiple device configurations by dynamically changing usb descriptors. - Communication Class (CDC) - Human Interface Device (HID): Keyboard, Mouse, Gamepad etc ... -- Mass Storage Class (MSC) +- Mass Storage Class (MSC): with multiple LUNs - Musical Instrument Digital Interface (MIDI) ## Host Stack diff --git a/examples/device/cdc_msc_hid/Makefile b/examples/device/cdc_msc_hid/Makefile index fc89b0fa7..69bffaace 100644 --- a/examples/device/cdc_msc_hid/Makefile +++ b/examples/device/cdc_msc_hid/Makefile @@ -83,11 +83,7 @@ endif LIBS = -lgcc -lc -lm -lnosys -EXAMPLE_SOURCE += \ - src/main.c \ - src/msc_disk.c \ - src/usb_descriptors.c - +EXAMPLE_SOURCE += $(wildcard src/*.c) SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) LIB_SOURCE += \ diff --git a/examples/device/cdc_msc_hid/src/msc_disk.c b/examples/device/cdc_msc_hid/src/msc_disk.c index f8f4f3cbe..42e77ef76 100644 --- a/examples/device/cdc_msc_hid/src/msc_disk.c +++ b/examples/device/cdc_msc_hid/src/msc_disk.c @@ -50,42 +50,72 @@ const #endif uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { - //------------- Boot Sector -------------// + //------------- Block0: Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; // sector_per_cluster = 1; reserved_sectors = 1; // fat_num = 1; fat12_root_entry_num = 16; // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; - // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "tinyusb msc"; - [0] = + // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC"; + // FAT magic code at offset 510-511 { 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 0x74, 0x69, 0x6E, 0x79, 0x75, - 0x73, 0x62, 0x20, 0x6D, 0x73, 0x63, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, - [510] = 0x55, [511] = 0xAA // FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , + 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, + + // Zero up to 2 last bytes of FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA }, - //------------- FAT12 Table -------------// - [1] = + //------------- Block1: FAT12 Table -------------// { 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file }, - //------------- Root Directory -------------// - [2] = + //------------- Block2: Root Directory -------------// { // first entry is volume label - 0x54, 0x49, 0x4E, 0x59, 0x55, 0x53, 0x42, 0x20, 0x4D, 0x53, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, + 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 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 files ize (4 Bytes) + sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) }, - //------------- Readme Content -------------// - [3] = README_CONTENTS + //------------- Block3: Readme Content -------------// + README_CONTENTS }; @@ -117,6 +147,7 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* return bufsize; } +// Callback invoked to determine disk's size void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { (void) lun; diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h index 7cea8b78f..400afb620 100644 --- a/examples/device/cdc_msc_hid/src/tusb_config.h +++ b/examples/device/cdc_msc_hid/src/tusb_config.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2018, hathach (tinyusb.org) @@ -89,9 +89,6 @@ // MSC //-------------------------------------------------------------------- -// Number of supported Logical Unit Number (At least 1) -#define CFG_TUD_MSC_MAXLUN 1 - // Buffer size of Device Mass storage #define CFG_TUD_MSC_BUFSIZE 512 @@ -108,12 +105,6 @@ // HID //-------------------------------------------------------------------- -/* 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() - */ -#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 0 - #ifdef __cplusplus } #endif diff --git a/examples/device/cdc_msc_hid_freertos/src/msc_disk.c b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c index f8f4f3cbe..961a10b30 100644 --- a/examples/device/cdc_msc_hid_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c @@ -50,45 +50,74 @@ const #endif uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = { - //------------- Boot Sector -------------// + //------------- Block0: Boot Sector -------------// // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; // sector_per_cluster = 1; reserved_sectors = 1; // fat_num = 1; fat12_root_entry_num = 16; // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; - // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "tinyusb msc"; - [0] = + // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB MSC"; + // FAT magic code at offset 510-511 { 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 0x74, 0x69, 0x6E, 0x79, 0x75, - 0x73, 0x62, 0x20, 0x6D, 0x73, 0x63, 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, - [510] = 0x55, [511] = 0xAA // FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , + 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, + + // Zero up to 2 last bytes of FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA }, - //------------- FAT12 Table -------------// - [1] = + //------------- Block1: FAT12 Table -------------// { 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file }, - //------------- Root Directory -------------// - [2] = + //------------- Block2: Root Directory -------------// { // first entry is volume label - 0x54, 0x49, 0x4E, 0x59, 0x55, 0x53, 0x42, 0x20, 0x4D, 0x53, 0x43, 0x08, 0x00, 0x00, 0x00, 0x00, + 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , 'M' , 'S' , 'C' , 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 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 files ize (4 Bytes) + sizeof(README_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) }, - //------------- Readme Content -------------// - [3] = README_CONTENTS + //------------- Block3: Readme Content -------------// + README_CONTENTS }; - // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) 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 15f099548..834d01216 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -89,9 +89,6 @@ // MSC //-------------------------------------------------------------------- -// Number of supported Logical Unit Number (At least 1) -#define CFG_TUD_MSC_MAXLUN 1 - // Buffer size of Device Mass storage #define CFG_TUD_MSC_BUFSIZE 512 @@ -108,12 +105,6 @@ // HID //-------------------------------------------------------------------- -/* 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() - */ -#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 0 - #ifdef __cplusplus } #endif diff --git a/examples/device/msc_dual_lun/Makefile b/examples/device/msc_dual_lun/Makefile new file mode 100644 index 000000000..1a9f9d135 --- /dev/null +++ b/examples/device/msc_dual_lun/Makefile @@ -0,0 +1,186 @@ +include ../../../tools/top.mk + +# Select the board to build for. +ifeq ($(BOARD),) + $(info You must provide a BOARD parameter with 'BOARD=') + $(info Possible values are:) + $(info $(sort $(subst /.,,$(subst $(TOP)/hw/bsp/,,$(wildcard $(TOP)/hw/bsp/*/.))))) + $(error BOARD not defined) +else + ifeq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/.),) + $(error Invalid BOARD specified) + endif +endif + +# Verbose mode (V=). 0: default, 1: print out CFLAG, LDFLAG 2: print all compile command +ifeq ("$(V)","2") + QUIET = +else + QUIET = @ +endif + +# If the build directory is not given, make it reflect the board name. +BUILD ?= build-$(BOARD) + +CROSS_COMPILE = arm-none-eabi- + +include $(TOP)/hw/bsp/$(BOARD)/board.mk + +CC = $(CROSS_COMPILE)gcc +CXX = $(CROSS_COMPILE)g++ +OBJCOPY = $(CROSS_COMPILE)objcopy +SIZE = $(CROSS_COMPILE)size +MKDIR = mkdir +SED = sed +CP = cp +RM = rm + +INC += -Isrc \ + -I$(TOP)/hw \ + -I$(TOP)/src + +CFLAGS += \ + -fsingle-precision-constant \ + -fno-strict-aliasing \ + -Wdouble-promotion \ + -Wno-endif-labels \ + -Wstrict-prototypes \ + -Werror-implicit-function-declaration \ + -Wfloat-equal \ + -Wundef \ + -Wshadow \ + -Wwrite-strings \ + -Wsign-compare \ + -Wmissing-format-attribute \ + -Wno-deprecated-declarations \ + -Wnested-externs \ + -Wunreachable-code \ + -Wno-error=lto-type-mismatch \ + -ffunction-sections \ + -fdata-sections + +# This causes lots of warning with nrf5x build due to nrfx code +# CFLAGS += -Wcast-align + +#Debugging/Optimization +ifeq ($(DEBUG), 1) + CFLAGS += -O0 -ggdb +else + CFLAGS += -flto -Os +endif + +CFLAGS += $(INC) -Wall -Werror -std=gnu11 -DBOARD_$(shell echo $(BOARD) | tr '[:lower:]' '[:upper:]') +LDFLAGS += $(CFLAGS) -fshort-enums -Wl,-T,$(TOP)/$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections -specs=nosys.specs -specs=nano.specs + +ifeq ("$(V)","1") +$(info CFLAGS $(CFLAGS)) +$(info ) +$(info LDFLAGS $(LDFLAGS)) +$(info ) +$(info ASFLAGS $(ASFLAGS)) +$(info ) +endif + +LIBS = -lgcc -lc -lm -lnosys + +EXAMPLE_SOURCE += $(wildcard src/*.c) + +SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) + +LIB_SOURCE += \ + hw/bsp/$(BOARD)/board_$(BOARD).c \ + src/common/tusb_fifo.c \ + src/device/usbd.c \ + src/device/usbd_control.c \ + src/class/msc/msc_device.c \ + src/class/cdc/cdc_device.c \ + src/class/hid/hid_device.c \ + src/tusb.c \ + src/portable/$(VENDOR)/$(CHIP_FAMILY)/dcd_$(CHIP_FAMILY).c + +SRC_C += $(LIB_SOURCE) + +# Assembly files can be name with upper case .S, convert it to .s +SRC_S := $(SRC_S:.S=.s) + +# Due to GCC LTO bug https://bugs.launchpad.net/gcc-arm-embedded/+bug/1747966 +# assembly file should be placed first in linking order +OBJ += $(addprefix $(BUILD)/obj/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/obj/, $(SRC_C:.c=.o)) + +# Set all as default goal +.DEFAULT_GOAL := all +all: $(BUILD)/$(BOARD)-firmware.bin size + +OBJ_DIRS = $(sort $(dir $(OBJ))) +$(OBJ): | $(OBJ_DIRS) +$(OBJ_DIRS): + @$(MKDIR) -p $@ + +$(BUILD)/$(BOARD)-firmware.elf: $(OBJ) + @echo LINK $@ + $(QUIET)$(CC) -o $@ $(LDFLAGS) $^ -Wl,--start-group $(LIBS) -Wl,--end-group + +$(BUILD)/$(BOARD)-firmware.bin: $(BUILD)/$(BOARD)-firmware.elf + @echo CREATE $@ + @$(OBJCOPY) -O binary -j .vectors -j .text -j .data $^ $@ + +$(BUILD)/$(BOARD)-firmware.hex: $(BUILD)/$(BOARD)-firmware.elf + @echo CREATE $@ + @$(OBJCOPY) -O ihex $^ $@ + +# We set vpath to point to the top of the tree so that the source files +# can be located. By following this scheme, it allows a single build rule +# to be used to compile all .c files. +vpath %.c . $(TOP) +$(BUILD)/obj/%.o: %.c + @echo CC $(notdir $@) + $(QUIET)$(CC) $(CFLAGS) -c -MD -o $@ $< + @# The following fixes the dependency file. + @# See http://make.paulandlesley.org/autodep.html for details. + @# Regex adjusted from the above to play better with Windows paths, etc. + @$(CP) $(@:.o=.d) $(@:.o=.P); \ + $(SED) -e 's/#.*//' -e 's/^.*: *//' -e 's/ *\\$$//' \ + -e '/^$$/ d' -e 's/$$/ :/' < $(@:.o=.d) >> $(@:.o=.P); \ + $(RM) $(@:.o=.d) + +# ASM sources lower case .s +vpath %.s . $(TOP) +$(BUILD)/obj/%.o: %.s + @echo AS $(notdir $@) + $(QUIET)$(CC) -x assembler-with-cpp $(ASFLAGS) -c -o $@ $< + +# ASM sources upper case .S +vpath %.S . $(TOP) +$(BUILD)/obj/%.o: %.S + @echo AS $(notdir $@) + $(QUIET)$(CC) -x assembler-with-cpp $(ASFLAGS) -c -o $@ $< + +# Flash binary using Jlink, should be added into system path +ifeq ($(OS),Windows_NT) + JLINKEXE = JLink.exe +else + JLINKEXE = JLinkExe +endif + +# default jlink interface is swd +ifeq ($(JLINK_IF),) + JLINK_IF = swd +endif + +# Flash using jlink +flash-jlink: $(BUILD)/$(BOARD)-firmware.hex + @echo halt > $(BUILD)/$(BOARD).jlink + @echo loadfile $^ >> $(BUILD)/$(BOARD).jlink + @echo r >> $(BUILD)/$(BOARD).jlink + @echo go >> $(BUILD)/$(BOARD).jlink + @echo exit >> $(BUILD)/$(BOARD).jlink + $(JLINKEXE) -device $(JLINK_DEVICE) -if $(JLINK_IF) -speed auto -CommandFile $(BUILD)/$(BOARD).jlink + +size: $(BUILD)/$(BOARD)-firmware.elf + -@echo '' + @$(SIZE) $< + -@echo '' + +clean: + rm -rf build-$(BOARD) diff --git a/examples/device/msc_dual_lun/src/main.c b/examples/device/msc_dual_lun/src/main.c new file mode 100644 index 000000000..39a8b4725 --- /dev/null +++ b/examples/device/msc_dual_lun/src/main.c @@ -0,0 +1,115 @@ +/* + * 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. + * + */ + +#include +#include +#include + +#include "bsp/board.h" +#include "tusb.h" + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF PROTYPES +//--------------------------------------------------------------------+ + +/* Blink pattern + * - 250 ms : device not mounted + * - 1000 ms : device mounted + * - 2500 ms : device is suspended + */ +enum { + BLINK_NOT_MOUNTED = 250, + BLINK_MOUNTED = 1000, + BLINK_SUSPENDED = 2500, +}; + +static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; + +void led_blinking_task(void); + +/*------------- MAIN -------------*/ +int main(void) +{ + board_init(); + + tusb_init(); + + while (1) + { + // tinyusb device task + tud_task(); + + led_blinking_task(); + } + + return 0; +} + +//--------------------------------------------------------------------+ +// Device callbacks +//--------------------------------------------------------------------+ + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + blink_interval_ms = BLINK_NOT_MOUNTED; +} + +// Invoked when usb bus is suspended +// remote_wakeup_en : if host allow us to perform remote wakeup +// Within 7ms, device must draw an average of current less than 2.5 mA from bus +void tud_suspend_cb(bool remote_wakeup_en) +{ + (void) remote_wakeup_en; + blink_interval_ms = BLINK_SUSPENDED; +} + +// Invoked when usb bus is resumed +void tud_resume_cb(void) +{ + blink_interval_ms = BLINK_MOUNTED; +} + +//--------------------------------------------------------------------+ +// BLINKING TASK +//--------------------------------------------------------------------+ +void led_blinking_task(void) +{ + static uint32_t start_ms = 0; + static bool led_state = false; + + // Blink every 1000 ms + if ( board_millis() < start_ms + blink_interval_ms) return; // not enough time + start_ms += blink_interval_ms; + + board_led_write(led_state); + led_state = 1 - led_state; // toggle +} diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c new file mode 100644 index 000000000..48c8f2409 --- /dev/null +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -0,0 +1,310 @@ +/* + * 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. + * + */ + +#include "bsp/board.h" +#include "tusb.h" + +#if CFG_TUD_MSC + +// Some MCU doesn't have enough 8KB SRAM to store the whole disk +// We will use Flash as read-only disk +#if CFG_TUSB_MCU == OPT_MCU_LPC13XX +#define DISK_READONLY +#endif + +enum +{ + DISK_BLOCK_NUM = 16, // 8KB is the smallest size that windows allow to mount + DISK_BLOCK_SIZE = 512 +}; + + +//--------------------------------------------------------------------+ +// LUN 0 +//--------------------------------------------------------------------+ +#define README0_CONTENTS \ +"LUN0: This is tinyusb's MassStorage Class demo.\r\n\r\n\ +If you find any bugs or get any questions, feel free to file an\r\n\ +issue at github.com/hathach/tinyusb" + + +#ifdef DISK_READONLY +const +#endif +uint8_t msc_disk0[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = +{ + //------------- Block0: Boot Sector -------------// + // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; + // sector_per_cluster = 1; reserved_sectors = 1; + // fat_num = 1; fat12_root_entry_num = 16; + // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; + // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; + // filesystem_type = "FAT12 "; volume_serial_number = 0x1234; volume_label = "TinyUSB 0 "; + // FAT magic code at offset 510-511 + { + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x34, 0x12, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , + 'S' , 'B' , ' ' , '0' , ' ' , ' ' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, + + // Zero up to 2 last bytes of FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA + }, + + //------------- Block1: FAT12 Table -------------// + { + 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file + }, + + //------------- Block2: Root Directory -------------// + { + // first entry is volume label + 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , '0' , ' ' , ' ' , 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // second entry is readme file + 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , '0' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, + 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, + sizeof(README0_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) + }, + + //------------- Block3: Readme Content -------------// + README0_CONTENTS +}; + +//--------------------------------------------------------------------+ +// LUN 1 +//--------------------------------------------------------------------+ +#define README1_CONTENTS \ +"LUN1: This is tinyusb's MassStorage Class demo.\r\n\r\n\ +If you find any bugs or get any questions, feel free to file an\r\n\ +issue at github.com/hathach/tinyusb" + +#ifdef DISK_READONLY +const +#endif +uint8_t msc_disk1[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = +{ + //------------- Block0: Boot Sector -------------// + // byte_per_sector = DISK_BLOCK_SIZE; fat12_sector_num_16 = DISK_BLOCK_NUM; + // sector_per_cluster = 1; reserved_sectors = 1; + // fat_num = 1; fat12_root_entry_num = 16; + // sector_per_fat = 1; sector_per_track = 1; head_num = 1; hidden_sectors = 0; + // drive_number = 0x80; media_type = 0xf8; extended_boot_signature = 0x29; + // filesystem_type = "FAT12 "; volume_serial_number = 0x5678; volume_label = "TinyUSB 1 "; + // FAT magic code at offset 510-511 + { + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x01, 0x01, 0x00, + 0x01, 0x10, 0x00, 0x10, 0x00, 0xF8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0x78, 0x56, 0x00, 0x00, 'T' , 'i' , 'n' , 'y' , 'U' , + 'S' , 'B' , ' ' , '1' , ' ' , ' ' , 0x46, 0x41, 0x54, 0x31, 0x32, 0x20, 0x20, 0x20, 0x00, 0x00, + + // Zero up to 2 last bytes of FAT magic code + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xAA + }, + + //------------- Block1: FAT12 Table -------------// + { + 0xF8, 0xFF, 0xFF, 0xFF, 0x0F // // first 2 entries must be F8FF, third entry is cluster end of readme file + }, + + //------------- Block2: Root Directory -------------// + { + // first entry is volume label + 'T' , 'i' , 'n' , 'y' , 'U' , 'S' , 'B' , ' ' , '1' , ' ' , ' ' , 0x08, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4F, 0x6D, 0x65, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // second entry is readme file + 'R' , 'E' , 'A' , 'D' , 'M' , 'E' , '1' , ' ' , 'T' , 'X' , 'T' , 0x20, 0x00, 0xC6, 0x52, 0x6D, + 0x65, 0x43, 0x65, 0x43, 0x00, 0x00, 0x88, 0x6D, 0x65, 0x43, 0x02, 0x00, + sizeof(README1_CONTENTS)-1, 0x00, 0x00, 0x00 // readme's files size (4 Bytes) + }, + + //------------- Block3: Readme Content -------------// + README1_CONTENTS +}; + +// Invoked to determine max LUN +uint8_t tud_msc_maxlun_cb(void) +{ + return 2; // dual LUN +} + +// Callback invoked to determine disk's size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ + (void) lun; // both LUNs have same size + + *block_count = DISK_BLOCK_NUM; + *block_size = DISK_BLOCK_SIZE; +} + + +// Callback invoked when received READ10 command. +// Copy disk's data to buffer (up to bufsize) and return number of copied bytes. +int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, uint32_t offset, void* buffer, uint32_t bufsize) +{ + uint8_t const* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset; + memcpy(buffer, addr, bufsize); + + return bufsize; +} + +// Callback invoked when received WRITE10 command. +// Process data in buffer to disk's storage and return number of written bytes +int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize) +{ +#ifndef DISK_READONLY + uint8_t* addr = (lun ? msc_disk1[lba] : msc_disk0[lba]) + offset; + memcpy(addr, buffer, bufsize); +#else + (void) lun; (void) lba; (void) offset; (void) buffer; +#endif + + return bufsize; +} + +// 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/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h new file mode 100644 index 000000000..b25510f25 --- /dev/null +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -0,0 +1,99 @@ +/* + * 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. + * + */ + +#ifndef _TUSB_CONFIG_H_ +#define _TUSB_CONFIG_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +//-------------------------------------------------------------------- +// COMMON CONFIGURATION +//-------------------------------------------------------------------- + +// defined by compiler flags for flexibility +#ifndef CFG_TUSB_MCU + #error CFG_TUSB_MCU must be defined +#endif + +#if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) +#else +#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE +#endif + +#define CFG_TUSB_OS OPT_OS_NONE +#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 + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN ATTR_ALIGNED(4) +#endif + +//-------------------------------------------------------------------- +// DEVICE CONFIGURATION +//-------------------------------------------------------------------- + +#define CFG_TUD_ENDOINT0_SIZE 64 + +//------------- CLASS -------------// +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 1 +#define CFG_TUD_HID 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_CUSTOM_CLASS 0 + +//-------------------------------------------------------------------- +// MSC +//-------------------------------------------------------------------- + +// Buffer size of Device Mass storage +#define CFG_TUD_MSC_BUFSIZE 512 + +// Vendor name included in Inquiry response, max 8 bytes +#define CFG_TUD_MSC_VENDOR "tinyusb" + +// Product name included in Inquiry response, max 16 bytes +#define CFG_TUD_MSC_PRODUCT "tusb msc" + +// Product revision string included in Inquiry response, max 4 bytes +#define CFG_TUD_MSC_PRODUCT_REV "1.0" + +#ifdef __cplusplus + } +#endif + +#endif /* _TUSB_CONFIG_H_ */ diff --git a/examples/device/msc_dual_lun/src/usb_descriptors.c b/examples/device/msc_dual_lun/src/usb_descriptors.c new file mode 100644 index 000000000..ede516eb1 --- /dev/null +++ b/examples/device/msc_dual_lun/src/usb_descriptors.c @@ -0,0 +1,112 @@ +/* + * 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. + * + */ + +#include "tusb.h" + +/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. + * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. + * + * Auto ProductID layout's Bitmap: + * [MSB] HID | MSC | CDC [LSB] + */ +#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) +#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) ) + +//------------- Device Descriptors -------------// +tusb_desc_device_t const desc_device = +{ + .bLength = sizeof(tusb_desc_device_t), + .bDescriptorType = TUSB_DESC_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0x00, + .bDeviceSubClass = 0x00, + .bDeviceProtocol = 0x00, + + .bMaxPacketSize0 = CFG_TUD_ENDOINT0_SIZE, + + .idVendor = 0xCafe, + .idProduct = USB_PID, + .bcdDevice = 0x0100, + + .iManufacturer = 0x01, + .iProduct = 0x02, + .iSerialNumber = 0x03, + + .bNumConfigurations = 0x01 +}; + +//------------- Configuration Descriptor -------------// +enum +{ + ITF_NUM_MSC, + ITF_NUM_TOTAL +}; + +enum +{ + CONFIG_TOTAL_LEN = TUD_CONFIG_DESC_LEN + TUD_MSC_DESC_LEN +}; + +// Use Endpoint 2 instead of 1 due to NXP MCU +// LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number +// 0 control, 1 In, 2 Bulk, 3 Iso, 4 In etc ... +#define EPNUM_MSC 0x02 + +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_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), + +#if CFG_TUD_MSC + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 +#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), + + // 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'), + + // 3: Serials, should use chip ID + TUD_DESC_STRCONV('1', '2', '3', '4', '5', '6') +}; + +// tud_desc_set is required by tinyusb stack +tud_desc_set_t tud_desc_set = +{ + .device = &desc_device, + .config = desc_configuration, + .string_arr = (uint8_t const **) string_desc_arr, + .string_count = sizeof(string_desc_arr)/sizeof(string_desc_arr[0]), + .hid_report = NULL, +}; diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 693ce5ac9..3d4d7a333 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -97,8 +97,6 @@ //-------------------------------------------------------------------- // MSC //-------------------------------------------------------------------- -// Number of supported Logical Unit Number (At least 1) -#define CFG_TUD_MSC_MAXLUN 1 // Buffer size of Device Mass storage #define CFG_TUD_MSC_BUFSIZE 512 @@ -116,14 +114,6 @@ // 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 - * - tud_hid_keyboard_send_char() - * - tud_hid_keyboard_send_string() - */ -#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 1 - - #ifdef __cplusplus } #endif diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c index 38ad99a35..78def53f0 100644 --- a/src/class/hid/hid_device.c +++ b/src/class/hid/hid_device.c @@ -129,19 +129,6 @@ bool tud_hid_keyboard_report(uint8_t report_id, uint8_t modifier, uint8_t keycod return tud_hid_report(report_id, &report, sizeof(report)); } -#if CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP -bool tud_hid_keyboard_key_press(uint8_t report_id, char ch) -{ - uint8_t keycode[6] = { 0 }; - uint8_t modifier = 0; - - if ( HID_ASCII_TO_KEYCODE[(uint8_t)ch].shift ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; - keycode[0] = HID_ASCII_TO_KEYCODE[(uint8_t)ch].keycode; - - return tud_hid_keyboard_report(report_id, modifier, keycode); -} -#endif // CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP - //--------------------------------------------------------------------+ // MOUSE APPLICATION API //--------------------------------------------------------------------+ @@ -337,143 +324,4 @@ bool hidd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t return true; } - -//------------- Ascii to Keycode Lookup -------------// -#if CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP -const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128] = -{ - {0, 0 }, // 0x00 Null - {0, 0 }, // 0x01 - {0, 0 }, // 0x02 - {0, 0 }, // 0x03 - {0, 0 }, // 0x04 - {0, 0 }, // 0x05 - {0, 0 }, // 0x06 - {0, 0 }, // 0x07 - {0, HID_KEY_BACKSPACE }, // 0x08 Backspace - {0, HID_KEY_TAB }, // 0x09 Horizontal Tab - {0, HID_KEY_RETURN }, // 0x0A Line Feed - {0, 0 }, // 0x0B - {0, 0 }, // 0x0C - {0, HID_KEY_RETURN }, // 0x0D Carriage return - {0, 0 }, // 0x0E - {0, 0 }, // 0x0F - {0, 0 }, // 0x10 - {0, 0 }, // 0x11 - {0, 0 }, // 0x12 - {0, 0 }, // 0x13 - {0, 0 }, // 0x14 - {0, 0 }, // 0x15 - {0, 0 }, // 0x16 - {0, 0 }, // 0x17 - {0, 0 }, // 0x18 - {0, 0 }, // 0x19 - {0, 0 }, // 0x1A - {0, HID_KEY_ESCAPE }, // 0x1B Escape - {0, 0 }, // 0x1C - {0, 0 }, // 0x1D - {0, 0 }, // 0x1E - {0, 0 }, // 0x1F - - {0, HID_KEY_SPACE }, // 0x20 - {1, HID_KEY_1 }, // 0x21 ! - {1, HID_KEY_APOSTROPHE }, // 0x22 " - {1, HID_KEY_3 }, // 0x23 # - {1, HID_KEY_4 }, // 0x24 $ - {1, HID_KEY_5 }, // 0x25 % - {1, HID_KEY_7 }, // 0x26 & - {0, HID_KEY_APOSTROPHE }, // 0x27 ' - {1, HID_KEY_9 }, // 0x28 ( - {1, HID_KEY_0 }, // 0x29 ) - {1, HID_KEY_8 }, // 0x2A * - {1, HID_KEY_EQUAL }, // 0x2B + - {0, HID_KEY_COMMA }, // 0x2C , - {0, HID_KEY_MINUS }, // 0x2D - - {0, HID_KEY_PERIOD }, // 0x2E . - {0, HID_KEY_SLASH }, // 0x2F / - {0, HID_KEY_0 }, // 0x30 0 - {0, HID_KEY_1 }, // 0x31 1 - {0, HID_KEY_2 }, // 0x32 2 - {0, HID_KEY_3 }, // 0x33 3 - {0, HID_KEY_4 }, // 0x34 4 - {0, HID_KEY_5 }, // 0x35 5 - {0, HID_KEY_6 }, // 0x36 6 - {0, HID_KEY_7 }, // 0x37 7 - {0, HID_KEY_8 }, // 0x38 8 - {0, HID_KEY_9 }, // 0x39 9 - {1, HID_KEY_SEMICOLON }, // 0x3A : - {0, HID_KEY_SEMICOLON }, // 0x3B ; - {1, HID_KEY_COMMA }, // 0x3C < - {0, HID_KEY_EQUAL }, // 0x3D = - {1, HID_KEY_PERIOD }, // 0x3E > - {1, HID_KEY_SLASH }, // 0x3F ? - - {1, HID_KEY_2 }, // 0x40 @ - {1, HID_KEY_A }, // 0x41 A - {1, HID_KEY_B }, // 0x42 B - {1, HID_KEY_C }, // 0x43 C - {1, HID_KEY_D }, // 0x44 D - {1, HID_KEY_E }, // 0x45 E - {1, HID_KEY_F }, // 0x46 F - {1, HID_KEY_G }, // 0x47 G - {1, HID_KEY_H }, // 0x48 H - {1, HID_KEY_I }, // 0x49 I - {1, HID_KEY_J }, // 0x4A J - {1, HID_KEY_K }, // 0x4B K - {1, HID_KEY_L }, // 0x4C L - {1, HID_KEY_M }, // 0x4D M - {1, HID_KEY_N }, // 0x4E N - {1, HID_KEY_O }, // 0x4F O - {1, HID_KEY_P }, // 0x50 P - {1, HID_KEY_Q }, // 0x51 Q - {1, HID_KEY_R }, // 0x52 R - {1, HID_KEY_S }, // 0x53 S - {1, HID_KEY_T }, // 0x55 T - {1, HID_KEY_U }, // 0x55 U - {1, HID_KEY_V }, // 0x56 V - {1, HID_KEY_W }, // 0x57 W - {1, HID_KEY_X }, // 0x58 X - {1, HID_KEY_Y }, // 0x59 Y - {1, HID_KEY_Z }, // 0x5A Z - {0, HID_KEY_BRACKET_LEFT }, // 0x5B [ - {0, HID_KEY_BACKSLASH }, // 0x5C '\' - {0, HID_KEY_BRACKET_RIGHT }, // 0x5D ] - {1, HID_KEY_6 }, // 0x5E ^ - {1, HID_KEY_MINUS }, // 0x5F _ - - {0, HID_KEY_GRAVE }, // 0x60 ` - {0, HID_KEY_A }, // 0x61 a - {0, HID_KEY_B }, // 0x62 b - {0, HID_KEY_C }, // 0x63 c - {0, HID_KEY_D }, // 0x66 d - {0, HID_KEY_E }, // 0x65 e - {0, HID_KEY_F }, // 0x66 f - {0, HID_KEY_G }, // 0x67 g - {0, HID_KEY_H }, // 0x68 h - {0, HID_KEY_I }, // 0x69 i - {0, HID_KEY_J }, // 0x6A j - {0, HID_KEY_K }, // 0x6B k - {0, HID_KEY_L }, // 0x6C l - {0, HID_KEY_M }, // 0x6D m - {0, HID_KEY_N }, // 0x6E n - {0, HID_KEY_O }, // 0x6F o - {0, HID_KEY_P }, // 0x70 p - {0, HID_KEY_Q }, // 0x71 q - {0, HID_KEY_R }, // 0x72 r - {0, HID_KEY_S }, // 0x73 s - {0, HID_KEY_T }, // 0x75 t - {0, HID_KEY_U }, // 0x75 u - {0, HID_KEY_V }, // 0x76 v - {0, HID_KEY_W }, // 0x77 w - {0, HID_KEY_X }, // 0x78 x - {0, HID_KEY_Y }, // 0x79 y - {0, HID_KEY_Z }, // 0x7A z - {1, HID_KEY_BRACKET_LEFT }, // 0x7B { - {1, HID_KEY_BACKSLASH }, // 0x7C | - {1, HID_KEY_BRACKET_RIGHT }, // 0x7D } - {1, HID_KEY_GRAVE }, // 0x7E ~ - {0, HID_KEY_DELETE } // 0x7F Delete -}; -#endif // CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP - #endif diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h index f72be61e2..13a213277 100644 --- a/src/class/hid/hid_device.h +++ b/src/class/hid/hid_device.h @@ -38,9 +38,7 @@ //--------------------------------------------------------------------+ // Class Driver Default Configure & Validation //--------------------------------------------------------------------+ -#ifndef CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP -#define CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP 0 -#endif + //--------------------------------------------------------------------+ // Application API @@ -81,16 +79,6 @@ static inline bool tud_hid_keyboard_key_release(uint8_t report_id) return tud_hid_keyboard_report(report_id, 0, NULL); } -#if CFG_TUD_HID_ASCII_TO_KEYCODE_LOOKUP -bool tud_hid_keyboard_key_press(uint8_t report_id, char ch); - -typedef struct{ - uint8_t shift; - uint8_t keycode; -}hid_ascii_to_keycode_entry_t; -extern const hid_ascii_to_keycode_entry_t HID_ASCII_TO_KEYCODE[128]; -#endif - //--------------------------------------------------------------------+ // MOUSE API // Convenient helper to send mouse report if application use standard/boot @@ -281,8 +269,154 @@ static inline bool tud_hid_mouse_button_release(uint8_t report_id) HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\ HID_COLLECTION_END \ -/** @} */ -/** @} */ +/*-------------------------------------------------------------------- + * ASCII to KEYCODE Conversion + * Expand to array of [128][2] (shift, keycode) + * + * Usage: example to convert input char into keyboard report (modifier + keycode) + * + * uint8_t const conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; + * + * uint8_t keycode[6] = { 0 }; + * uint8_t modifier = 0; + * + * if ( conv_table[chr][0] ) modifier = KEYBOARD_MODIFIER_LEFTSHIFT; + * keycode[0] = conv_table[chr][1]; + * tud_hid_keyboard_report(report_id, modifier, keycode); + * + *--------------------------------------------------------------------*/ +#define HID_ASCII_TO_KEYCODE \ + {0, 0 }, /* 0x00 Null */ \ + {0, 0 }, /* 0x01 */ \ + {0, 0 }, /* 0x02 */ \ + {0, 0 }, /* 0x03 */ \ + {0, 0 }, /* 0x04 */ \ + {0, 0 }, /* 0x05 */ \ + {0, 0 }, /* 0x06 */ \ + {0, 0 }, /* 0x07 */ \ + {0, HID_KEY_BACKSPACE }, /* 0x08 Backspace */ \ + {0, HID_KEY_TAB }, /* 0x09 Tab */ \ + {0, HID_KEY_RETURN }, /* 0x0A Line Feed */ \ + {0, 0 }, /* 0x0B */ \ + {0, 0 }, /* 0x0C */ \ + {0, HID_KEY_RETURN }, /* 0x0D CR */ \ + {0, 0 }, /* 0x0E */ \ + {0, 0 }, /* 0x0F */ \ + {0, 0 }, /* 0x10 */ \ + {0, 0 }, /* 0x11 */ \ + {0, 0 }, /* 0x12 */ \ + {0, 0 }, /* 0x13 */ \ + {0, 0 }, /* 0x14 */ \ + {0, 0 }, /* 0x15 */ \ + {0, 0 }, /* 0x16 */ \ + {0, 0 }, /* 0x17 */ \ + {0, 0 }, /* 0x18 */ \ + {0, 0 }, /* 0x19 */ \ + {0, 0 }, /* 0x1A */ \ + {0, HID_KEY_ESCAPE }, /* 0x1B Escape */ \ + {0, 0 }, /* 0x1C */ \ + {0, 0 }, /* 0x1D */ \ + {0, 0 }, /* 0x1E */ \ + {0, 0 }, /* 0x1F */ \ + \ + {0, HID_KEY_SPACE }, /* 0x20 */ \ + {1, HID_KEY_1 }, /* 0x21 ! */ \ + {1, HID_KEY_APOSTROPHE }, /* 0x22 " */ \ + {1, HID_KEY_3 }, /* 0x23 # */ \ + {1, HID_KEY_4 }, /* 0x24 $ */ \ + {1, HID_KEY_5 }, /* 0x25 % */ \ + {1, HID_KEY_7 }, /* 0x26 & */ \ + {0, HID_KEY_APOSTROPHE }, /* 0x27 ' */ \ + {1, HID_KEY_9 }, /* 0x28 ( */ \ + {1, HID_KEY_0 }, /* 0x29 ) */ \ + {1, HID_KEY_8 }, /* 0x2A * */ \ + {1, HID_KEY_EQUAL }, /* 0x2B + */ \ + {0, HID_KEY_COMMA }, /* 0x2C , */ \ + {0, HID_KEY_MINUS }, /* 0x2D - */ \ + {0, HID_KEY_PERIOD }, /* 0x2E . */ \ + {0, HID_KEY_SLASH }, /* 0x2F / */ \ + {0, HID_KEY_0 }, /* 0x30 0 */ \ + {0, HID_KEY_1 }, /* 0x31 1 */ \ + {0, HID_KEY_2 }, /* 0x32 2 */ \ + {0, HID_KEY_3 }, /* 0x33 3 */ \ + {0, HID_KEY_4 }, /* 0x34 4 */ \ + {0, HID_KEY_5 }, /* 0x35 5 */ \ + {0, HID_KEY_6 }, /* 0x36 6 */ \ + {0, HID_KEY_7 }, /* 0x37 7 */ \ + {0, HID_KEY_8 }, /* 0x38 8 */ \ + {0, HID_KEY_9 }, /* 0x39 9 */ \ + {1, HID_KEY_SEMICOLON }, /* 0x3A : */ \ + {0, HID_KEY_SEMICOLON }, /* 0x3B ; */ \ + {1, HID_KEY_COMMA }, /* 0x3C < */ \ + {0, HID_KEY_EQUAL }, /* 0x3D = */ \ + {1, HID_KEY_PERIOD }, /* 0x3E > */ \ + {1, HID_KEY_SLASH }, /* 0x3F ? */ \ + \ + {1, HID_KEY_2 }, /* 0x40 @ */ \ + {1, HID_KEY_A }, /* 0x41 A */ \ + {1, HID_KEY_B }, /* 0x42 B */ \ + {1, HID_KEY_C }, /* 0x43 C */ \ + {1, HID_KEY_D }, /* 0x44 D */ \ + {1, HID_KEY_E }, /* 0x45 E */ \ + {1, HID_KEY_F }, /* 0x46 F */ \ + {1, HID_KEY_G }, /* 0x47 G */ \ + {1, HID_KEY_H }, /* 0x48 H */ \ + {1, HID_KEY_I }, /* 0x49 I */ \ + {1, HID_KEY_J }, /* 0x4A J */ \ + {1, HID_KEY_K }, /* 0x4B K */ \ + {1, HID_KEY_L }, /* 0x4C L */ \ + {1, HID_KEY_M }, /* 0x4D M */ \ + {1, HID_KEY_N }, /* 0x4E N */ \ + {1, HID_KEY_O }, /* 0x4F O */ \ + {1, HID_KEY_P }, /* 0x50 P */ \ + {1, HID_KEY_Q }, /* 0x51 Q */ \ + {1, HID_KEY_R }, /* 0x52 R */ \ + {1, HID_KEY_S }, /* 0x53 S */ \ + {1, HID_KEY_T }, /* 0x55 T */ \ + {1, HID_KEY_U }, /* 0x55 U */ \ + {1, HID_KEY_V }, /* 0x56 V */ \ + {1, HID_KEY_W }, /* 0x57 W */ \ + {1, HID_KEY_X }, /* 0x58 X */ \ + {1, HID_KEY_Y }, /* 0x59 Y */ \ + {1, HID_KEY_Z }, /* 0x5A Z */ \ + {0, HID_KEY_BRACKET_LEFT }, /* 0x5B [ */ \ + {0, HID_KEY_BACKSLASH }, /* 0x5C '\' */ \ + {0, HID_KEY_BRACKET_RIGHT }, /* 0x5D ] */ \ + {1, HID_KEY_6 }, /* 0x5E ^ */ \ + {1, HID_KEY_MINUS }, /* 0x5F _ */ \ + \ + {0, HID_KEY_GRAVE }, /* 0x60 ` */ \ + {0, HID_KEY_A }, /* 0x61 a */ \ + {0, HID_KEY_B }, /* 0x62 b */ \ + {0, HID_KEY_C }, /* 0x63 c */ \ + {0, HID_KEY_D }, /* 0x66 d */ \ + {0, HID_KEY_E }, /* 0x65 e */ \ + {0, HID_KEY_F }, /* 0x66 f */ \ + {0, HID_KEY_G }, /* 0x67 g */ \ + {0, HID_KEY_H }, /* 0x68 h */ \ + {0, HID_KEY_I }, /* 0x69 i */ \ + {0, HID_KEY_J }, /* 0x6A j */ \ + {0, HID_KEY_K }, /* 0x6B k */ \ + {0, HID_KEY_L }, /* 0x6C l */ \ + {0, HID_KEY_M }, /* 0x6D m */ \ + {0, HID_KEY_N }, /* 0x6E n */ \ + {0, HID_KEY_O }, /* 0x6F o */ \ + {0, HID_KEY_P }, /* 0x70 p */ \ + {0, HID_KEY_Q }, /* 0x71 q */ \ + {0, HID_KEY_R }, /* 0x72 r */ \ + {0, HID_KEY_S }, /* 0x73 s */ \ + {0, HID_KEY_T }, /* 0x75 t */ \ + {0, HID_KEY_U }, /* 0x75 u */ \ + {0, HID_KEY_V }, /* 0x76 v */ \ + {0, HID_KEY_W }, /* 0x77 w */ \ + {0, HID_KEY_X }, /* 0x78 x */ \ + {0, HID_KEY_Y }, /* 0x79 y */ \ + {0, HID_KEY_Z }, /* 0x7A z */ \ + {1, HID_KEY_BRACKET_LEFT }, /* 0x7B { */ \ + {1, HID_KEY_BACKSLASH }, /* 0x7C | */ \ + {1, HID_KEY_BRACKET_RIGHT }, /* 0x7D } */ \ + {1, HID_KEY_GRAVE }, /* 0x7E ~ */ \ + {0, HID_KEY_DELETE } /* 0x7F Delete */ \ //--------------------------------------------------------------------+ // Internal Class Driver API diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index a6b65557c..e2cf92324 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -163,8 +163,10 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque case MSC_REQ_GET_MAX_LUN: { - // returned MAX LUN is minus 1 by specs - uint8_t maxlun = CFG_TUD_MSC_MAXLUN-1; + // MAX LUN is minus 1 by specs + uint8_t maxlun = 0; + if (tud_msc_maxlun_cb) maxlun = tud_msc_maxlun_cb() -1; + usbd_control_xfer(rhport, p_request, &maxlun, 1); } break; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 3ed223509..6e3aef8bb 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -40,12 +40,6 @@ //--------------------------------------------------------------------+ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); -#ifndef CFG_TUD_MSC_MAXLUN - #define CFG_TUD_MSC_MAXLUN 1 -#elif CFG_TUD_MSC_MAXLUN == 0 || CFG_TUD_MSC_MAXLUN > 16 - #error MSC Device: Incorrect setting of MAX LUN -#endif - #ifndef CFG_TUD_MSC_BUFSIZE #error CFG_TUD_MSC_BUFSIZE must be defined, value of a block size should work well, the more the better #endif @@ -134,6 +128,9 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, /*------------- Optional callbacks -------------*/ +// Invoked to determine max LUN +ATTR_WEAK uint8_t tud_msc_maxlun_cb(void); + // Invoked when Read10 command is complete ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); diff --git a/tools/build_all.py b/tools/build_all.py index 4b6fa5775..e3439cb5b 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -4,8 +4,10 @@ import sys import subprocess import time +all_device_example = ["cdc_msc_hid", "msc_dual_lun"] all_boards = ["metro_m0_express", "metro_m4_express", "pca10056", "stm32f407g_disc1"] -for board in all_boards: - subprocess.run("make -j2 -C examples/device/cdc_msc_hid BOARD={} clean".format(board), shell=True) - subprocess.run("make -j2 -C examples/device/cdc_msc_hid BOARD={} all".format(board), shell=True) +for example in all_device_example: + for board in all_boards: + subprocess.run("make -j2 -C examples/device/{} BOARD={} clean".format(example, board), shell=True) + subprocess.run("make -j2 -C examples/device/{} BOARD={} all".format(example, board), shell=True)