summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2019-04-26 16:21:39 +0700
committerGitHub <[email protected]>2019-04-26 16:21:39 +0700
commite4be6dd95eba53388b713d6c3f59b4ba7c7886f2 (patch)
tree31b7bd3279d58cb4b10caf95143d6a62a4c61645
parentcfd2d995d2e74d81aee49ae9fb7949cf7d0fe540 (diff)
parent25bd3fef47114bba845d3dbf397a50efb0ee777c (diff)
Merge pull request #59 from hathach/develop
add multiple Lun support along with msc_dual_lun example
-rw-r--r--.travis.yml6
-rw-r--r--README.md2
-rw-r--r--examples/device/cdc_msc_hid/Makefile6
-rw-r--r--examples/device/cdc_msc_hid/src/msc_disk.c59
-rw-r--r--examples/device/cdc_msc_hid/src/tusb_config.h11
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/msc_disk.c59
-rw-r--r--examples/device/cdc_msc_hid_freertos/src/tusb_config.h9
-rw-r--r--examples/device/msc_dual_lun/Makefile186
-rw-r--r--examples/device/msc_dual_lun/src/main.c115
-rw-r--r--examples/device/msc_dual_lun/src/msc_disk_dual.c310
-rw-r--r--examples/device/msc_dual_lun/src/tusb_config.h99
-rw-r--r--examples/device/msc_dual_lun/src/usb_descriptors.c112
-rw-r--r--examples/host/cdc_msc_hid/src/tusb_config.h10
-rw-r--r--src/class/hid/hid_device.c152
-rw-r--r--src/class/hid/hid_device.h164
-rw-r--r--src/class/msc/msc_device.c6
-rw-r--r--src/class/msc/msc_device.h9
-rw-r--r--tools/build_all.py8
18 files changed, 1076 insertions, 247 deletions
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,[email protected] -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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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)