From a8d98d09ca18d3caa537262dcae639225fddb9f3 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 May 2019 13:44:50 +0700 Subject: [PATCH 01/10] clean up --- examples/device/cdc_msc_hid/src/usb_descriptors.c | 2 +- examples/device/hid_generic_inout/hid_test.py | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/device/cdc_msc_hid/src/usb_descriptors.c b/examples/device/cdc_msc_hid/src/usb_descriptors.c index 72d280c2..ef3cc9ce 100644 --- a/examples/device/cdc_msc_hid/src/usb_descriptors.c +++ b/examples/device/cdc_msc_hid/src/usb_descriptors.c @@ -117,7 +117,7 @@ enum uint8_t const desc_configuration[] = { - // Inteface count, string index, total length, attribute, power in mA + // Interface count, string index, total length, attribute, power in mA TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), #if CFG_TUD_CDC diff --git a/examples/device/hid_generic_inout/hid_test.py b/examples/device/hid_generic_inout/hid_test.py index b6799687..c89d8906 100644 --- a/examples/device/hid_generic_inout/hid_test.py +++ b/examples/device/hid_generic_inout/hid_test.py @@ -3,7 +3,9 @@ import hid USB_VID = 0xcafe -for dict in hid.enumerate(0xcafe): +print("Openning HID device with VID = 0x%X" % USB_VID) + +for dict in hid.enumerate(USB_VID): print(dict) dev = hid.Device(dict['vendor_id'], dict['product_id']) if dev: From a55875522c8e39c9aadb1b7218eac985877b3f73 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 May 2019 13:56:52 +0700 Subject: [PATCH 02/10] reduce travis make thread to 2 --- .gitignore | 2 -- tools/build_all.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 4c91d52f..c2fa0f16 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,4 @@ tests/build .env /tests/lpc175x_6x/build/ /tests/lpc18xx_43xx/build/ -/demos/*/*/Board_* -/demos/*/*/KeilBuild/ /examples/*/*/build-* diff --git a/tools/build_all.py b/tools/build_all.py index d65bb073..513764e8 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -4,6 +4,7 @@ import sys import subprocess import time +PARALLEL = "-j 4" travis = False if "TRAVIS" in os.environ and os.environ["TRAVIS"] == "true": PARALLEL="-j 2" @@ -18,7 +19,7 @@ all_boards = ["metro_m0_express", "metro_m4_express", "pca10056", "feather_nrf52 def build_example(example, board): subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + return subprocess.run("make {} -C examples/device/{} BOARD={} all".format(PARALLEL, example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) total_time = time.monotonic() From 49ad6fe0ac0fc5479abac1b2d2d9174a6aedb663 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 May 2019 14:02:22 +0700 Subject: [PATCH 03/10] update travis build, make with 4 thread --- tools/build_all.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/build_all.py b/tools/build_all.py index 513764e8..002b3002 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -4,10 +4,8 @@ import sys import subprocess import time -PARALLEL = "-j 4" travis = False if "TRAVIS" in os.environ and os.environ["TRAVIS"] == "true": - PARALLEL="-j 2" travis = True success_count = 0 @@ -19,7 +17,7 @@ all_boards = ["metro_m0_express", "metro_m4_express", "pca10056", "feather_nrf52 def build_example(example, board): subprocess.run("make -C examples/device/{} BOARD={} clean".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - return subprocess.run("make {} -C examples/device/{} BOARD={} all".format(PARALLEL, example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + return subprocess.run("make -j 4 -C examples/device/{} BOARD={} all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) total_time = time.monotonic() @@ -52,6 +50,6 @@ for example in all_device_example: total_time = time.monotonic() - total_time - print("Total build time took {:.2f}s".format(total_time)) + sys.exit(exit_status) From fae9aba68f7fb2cb5309b21933bcc0d3fdc480e0 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 3 May 2019 23:46:01 +0700 Subject: [PATCH 04/10] add tud_msc_inquiry_cb() remove CFG_TUD_MSC_VENDOR/PRODUCT/PRODUCT_REV --- examples/device/cdc_msc_hid/src/msc_disk.c | 33 ++++++++++++++----- examples/device/cdc_msc_hid/src/tusb_config.h | 9 ----- .../cdc_msc_hid_freertos/src/msc_disk.c | 33 ++++++++++++++----- .../cdc_msc_hid_freertos/src/tusb_config.h | 9 ----- .../device/msc_dual_lun/src/msc_disk_dual.c | 14 ++++++++ .../device/msc_dual_lun/src/tusb_config.h | 9 ----- examples/host/cdc_msc_hid/src/tusb_config.h | 9 ----- src/class/msc/msc_device.c | 16 +++------ src/class/msc/msc_device.h | 16 +++------ 9 files changed, 72 insertions(+), 76 deletions(-) diff --git a/examples/device/cdc_msc_hid/src/msc_disk.c b/examples/device/cdc_msc_hid/src/msc_disk.c index 42e77ef7..5c91e7da 100644 --- a/examples/device/cdc_msc_hid/src/msc_disk.c +++ b/examples/device/cdc_msc_hid/src/msc_disk.c @@ -118,6 +118,30 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = README_CONTENTS }; +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ + (void) lun; + + *block_count = DISK_BLOCK_NUM; + *block_size = DISK_BLOCK_SIZE; +} + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) +{ + (void) lun; + + const char vid[] = "TinyUSB"; + const char pid[] = "Mass Storage"; + const char rev[] = "1.0"; + + memcpy(vendor_id , vid, strlen(vid)); + memcpy(product_id , pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. @@ -147,15 +171,6 @@ 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; - - *block_count = DISK_BLOCK_NUM; - *block_size = DISK_BLOCK_SIZE; -} - // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks diff --git a/examples/device/cdc_msc_hid/src/tusb_config.h b/examples/device/cdc_msc_hid/src/tusb_config.h index c1210152..e909a0d4 100644 --- a/examples/device/cdc_msc_hid/src/tusb_config.h +++ b/examples/device/cdc_msc_hid/src/tusb_config.h @@ -88,15 +88,6 @@ // 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" - //------------- HID -------------// // Should be sufficient to hold ID (if any) + Data 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 961a10b3..c60558ea 100644 --- a/examples/device/cdc_msc_hid_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c @@ -118,6 +118,31 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = README_CONTENTS }; +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ + (void) lun; + + *block_count = DISK_BLOCK_NUM; + *block_size = DISK_BLOCK_SIZE; +} + +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) +{ + (void) lun; + + const char vid[] = "TinyUSB"; + const char pid[] = "Mass Storage"; + const char rev[] = "1.0"; + + memcpy(vendor_id , vid, strlen(vid)); + memcpy(product_id , pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} + // 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) @@ -146,14 +171,6 @@ int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* return bufsize; } -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) -{ - (void) lun; - - *block_count = DISK_BLOCK_NUM; - *block_size = DISK_BLOCK_SIZE; -} - // Callback invoked when received an SCSI command not in built-in list below // - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE // - READ10 and WRITE10 has their own callbacks 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 04ffaafc..c377798c 100644 --- a/examples/device/cdc_msc_hid_freertos/src/tusb_config.h +++ b/examples/device/cdc_msc_hid_freertos/src/tusb_config.h @@ -88,15 +88,6 @@ // 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" - //------------- HID -------------// // Should be sufficient to hold ID (if any) + Data diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 48c8f240..780705db 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -219,6 +219,20 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz *block_size = DISK_BLOCK_SIZE; } +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) +{ + (void) lun; // use same ID for both LUNs + + const char vid[] = "TinyUSB"; + const char pid[] = "Mass Storage"; + const char rev[] = "1.0"; + + memcpy(vendor_id , vid, strlen(vid)); + memcpy(product_id , pid, strlen(pid)); + memcpy(product_rev, rev, strlen(rev)); +} // Callback invoked when received READ10 command. // Copy disk's data to buffer (up to bufsize) and return number of copied bytes. diff --git a/examples/device/msc_dual_lun/src/tusb_config.h b/examples/device/msc_dual_lun/src/tusb_config.h index 492eba5f..93991973 100644 --- a/examples/device/msc_dual_lun/src/tusb_config.h +++ b/examples/device/msc_dual_lun/src/tusb_config.h @@ -81,15 +81,6 @@ // 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 diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index 3d4d7a33..aa081f9d 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -101,15 +101,6 @@ // 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" - //-------------------------------------------------------------------- // HID //-------------------------------------------------------------------- diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index f980e941..5f472c39 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -242,20 +242,14 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf .is_removable = 1, .version = 2, .response_data_format = 2, - // vendor_id, product_id, product_rev is space padded string - .vendor_id = "", - .product_id = "", - .product_rev = "", }; - memset(inquiry_rsp.vendor_id, ' ', sizeof(inquiry_rsp.vendor_id)); - memcpy(inquiry_rsp.vendor_id, CFG_TUD_MSC_VENDOR, tu_min32(strlen(CFG_TUD_MSC_VENDOR), sizeof(inquiry_rsp.vendor_id))); - - memset(inquiry_rsp.product_id, ' ', sizeof(inquiry_rsp.product_id)); - memcpy(inquiry_rsp.product_id, CFG_TUD_MSC_PRODUCT, tu_min32(strlen(CFG_TUD_MSC_PRODUCT), sizeof(inquiry_rsp.product_id))); - + // vendor_id, product_id, product_rev is space padded string + memset(inquiry_rsp.vendor_id , ' ', sizeof(inquiry_rsp.vendor_id)); + memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - memcpy(inquiry_rsp.product_rev, CFG_TUD_MSC_PRODUCT_REV, tu_min32(strlen(CFG_TUD_MSC_PRODUCT_REV), sizeof(inquiry_rsp.product_rev))); + + tud_msc_inquiry_cb(p_cbw->lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); ret = sizeof(inquiry_rsp); memcpy(buffer, &inquiry_rsp, ret); diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index b1e7e8da..068bea3e 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -44,18 +44,6 @@ TU_VERIFY_STATIC(CFG_TUD_MSC_BUFSIZE < UINT16_MAX, "Size is not correct"); #error CFG_TUD_MSC_BUFSIZE must be defined, value of a block size should work well, the more the better #endif -#ifndef CFG_TUD_MSC_VENDOR - #error CFG_TUD_MSC_VENDOR 8-byte name must be defined -#endif - -#ifndef CFG_TUD_MSC_PRODUCT - #error CFG_TUD_MSC_PRODUCT 16-byte name must be defined -#endif - -#ifndef CFG_TUD_MSC_PRODUCT_REV - #error CFG_TUD_MSC_PRODUCT_REV 4-byte string must be defined -#endif - /** \addtogroup ClassDriver_MSC * @{ * \defgroup MSC_Device Device @@ -105,6 +93,10 @@ int32_t tud_msc_read10_cb (uint8_t lun, uint32_t lba, uint32_t offset, void* buf */ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* buffer, uint32_t bufsize); +// Invoked when received SCSI_CMD_INQUIRY +// Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively +void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); + // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size // Application update block count and block size void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); From efefbd3a4ef9d867d4aaa05e3c06e51b441aca6e Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 May 2019 15:01:38 +0700 Subject: [PATCH 05/10] add Test Unit Ready to builtin command, add tud_msc_test_unit_ready_cb() - rename tud_msc_maxlun_cb to tud_msc_get_maxlun_cb --- examples/device/cdc_msc_hid/src/msc_disk.c | 34 +++-- .../cdc_msc_hid_freertos/src/msc_disk.c | 34 +++-- .../device/msc_dual_lun/src/msc_disk_dual.c | 34 +++-- src/class/msc/msc_device.c | 129 +++++++++--------- src/class/msc/msc_device.h | 17 ++- 5 files changed, 133 insertions(+), 115 deletions(-) diff --git a/examples/device/cdc_msc_hid/src/msc_disk.c b/examples/device/cdc_msc_hid/src/msc_disk.c index 5c91e7da..970f0adc 100644 --- a/examples/device/cdc_msc_hid/src/msc_disk.c +++ b/examples/device/cdc_msc_hid/src/msc_disk.c @@ -118,16 +118,6 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = README_CONTENTS }; -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) -{ - (void) lun; - - *block_count = DISK_BLOCK_NUM; - *block_size = DISK_BLOCK_SIZE; -} - // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) @@ -143,6 +133,25 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 memcpy(product_rev, rev, strlen(rev)); } +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ + (void) lun; + + return true; // RAM disk is always ready +} + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ + (void) lun; + + *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) @@ -186,11 +195,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, 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; 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 c60558ea..3d9103bd 100644 --- a/examples/device/cdc_msc_hid_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c @@ -118,16 +118,6 @@ uint8_t msc_disk[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = README_CONTENTS }; -// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size -// Application update block count and block size -void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) -{ - (void) lun; - - *block_count = DISK_BLOCK_NUM; - *block_size = DISK_BLOCK_SIZE; -} - // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) @@ -143,6 +133,25 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 memcpy(product_rev, rev, strlen(rev)); } +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ + (void) lun; + + return true; // RAM disk is always ready +} + +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size +void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) +{ + (void) lun; + + *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) @@ -186,11 +195,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, 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; diff --git a/examples/device/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 780705db..48f5cfb1 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -205,20 +205,11 @@ uint8_t msc_disk1[DISK_BLOCK_NUM][DISK_BLOCK_SIZE] = }; // Invoked to determine max LUN -uint8_t tud_msc_maxlun_cb(void) +uint8_t tud_msc_get_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; -} - // Invoked when received SCSI_CMD_INQUIRY // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) @@ -234,6 +225,24 @@ void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16 memcpy(product_rev, rev, strlen(rev)); } +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun) +{ + (void) lun; + + return true; // RAM disk is always ready +} + +// 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) @@ -273,11 +282,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, 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; diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 5f472c39..fcb118a6 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -159,7 +159,7 @@ bool mscd_control_request(uint8_t rhport, tusb_control_request_t const * p_reque case MSC_REQ_GET_MAX_LUN: { uint8_t maxlun = 1; - if (tud_msc_maxlun_cb) maxlun = tud_msc_maxlun_cb(); + if (tud_msc_get_maxlun_cb) maxlun = tud_msc_get_maxlun_cb(); TU_VERIFY(maxlun); // MAX LUN is minus 1 by specs @@ -186,14 +186,27 @@ bool mscd_control_request_complete(uint8_t rhport, tusb_control_request_t const return true; } -// return length of response (copied to buffer), -1 if it is not an built-in commands -int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t bufsize) +// return response's length (copied to buffer). Negative if it is not an built-in command or indicate Failed status (CSW) +// In case of a failed status, sense key must be set for reason of failure +int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buffer, uint32_t bufsize) { (void) bufsize; // TODO refractor later - int32_t ret; + int32_t resplen; - switch ( p_cbw->command[0] ) + switch ( scsi_cmd[0] ) { + case SCSI_CMD_TEST_UNIT_READY: + resplen = 0; + if ( !tud_msc_test_unit_ready_cb(lun) ) + { + // not ready response with Failed status and sense key = not ready + resplen = - 1; + + // Logical Unit Not Ready, Cause Not Reportable + tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + break; + case SCSI_CMD_READ_CAPACITY_10: { scsi_read_capacity10_resp_t read_capa10; @@ -202,14 +215,14 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf uint32_t block_size; uint16_t block_size_u16; - tud_msc_capacity_cb(p_cbw->lun, &block_count, &block_size_u16); + tud_msc_capacity_cb(lun, &block_count, &block_size_u16); block_size = (uint32_t) block_size_u16; read_capa10.last_lba = ENDIAN_BE(block_count-1); read_capa10.block_size = ENDIAN_BE(block_size); - ret = sizeof(read_capa10); - memcpy(buffer, &read_capa10, ret); + resplen = sizeof(read_capa10); + memcpy(buffer, &read_capa10, resplen); } break; @@ -226,12 +239,12 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf uint32_t block_count; uint16_t block_size; - tud_msc_capacity_cb(p_cbw->lun, &block_count, &block_size); + tud_msc_capacity_cb(lun, &block_count, &block_size); read_fmt_capa.block_num = ENDIAN_BE(block_count); read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size); - ret = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, ret); + resplen = sizeof(read_fmt_capa); + memcpy(buffer, &read_fmt_capa, resplen); } break; @@ -249,10 +262,10 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf memset(inquiry_rsp.product_id , ' ', sizeof(inquiry_rsp.product_id)); memset(inquiry_rsp.product_rev, ' ', sizeof(inquiry_rsp.product_rev)); - tud_msc_inquiry_cb(p_cbw->lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); + tud_msc_inquiry_cb(lun, inquiry_rsp.vendor_id, inquiry_rsp.product_id, inquiry_rsp.product_rev); - ret = sizeof(inquiry_rsp); - memcpy(buffer, &inquiry_rsp, ret); + resplen = sizeof(inquiry_rsp); + memcpy(buffer, &inquiry_rsp, resplen); } break; @@ -269,12 +282,12 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf bool writable = true; if (tud_msc_is_writable_cb) { - writable = tud_msc_is_writable_cb(p_cbw->lun); + writable = tud_msc_is_writable_cb(lun); } mode_resp.write_protected = !writable; - ret = sizeof(mode_resp); - memcpy(buffer, &mode_resp, ret); + resplen = sizeof(mode_resp); + memcpy(buffer, &mode_resp, resplen); } break; @@ -292,18 +305,18 @@ int32_t proc_builtin_scsi(msc_cbw_t const * p_cbw, uint8_t* buffer, uint32_t buf sense_rsp.add_sense_code = _mscd_itf.add_sense_code; sense_rsp.add_sense_qualifier = _mscd_itf.add_sense_qualifier; - ret = sizeof(sense_rsp); - memcpy(buffer, &sense_rsp, ret); + resplen = sizeof(sense_rsp); + memcpy(buffer, &sense_rsp, resplen); // Clear sense data after copy - tud_msc_set_sense(p_cbw->lun, 0, 0, 0); + tud_msc_set_sense(lun, 0, 0, 0); } break; - default: ret = -1; break; + default: resplen = -1; break; } - return ret; + return resplen; } bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes) @@ -342,60 +355,50 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t else { // For other SCSI commands - // 1. Zero : Invoke app callback, skip DATA and move to STATUS stage - // 2. OUT : queue transfer (invoke app callback after done) - // 3. IN : invoke app callback to get response - if ( p_cbw->total_bytes == 0) + // 1. OUT : queue transfer (invoke app callback after done) + // 2. IN & Zero: Process if is built-in, else Invoke app callback. Skip DATA if zero length + if ( (p_cbw->total_bytes > 0 ) && !TU_BIT_TEST(p_cbw->dir, 7) ) { - int32_t const cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, NULL, 0); - - p_msc->total_len = 0; - p_msc->stage = MSC_STAGE_STATUS; - - if ( cb_result < 0 ) - { - p_csw->status = MSC_CSW_STATUS_FAILED; - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation - } - else - { - p_csw->status = MSC_CSW_STATUS_PASSED; - } - } - else if ( !TU_BIT_TEST(p_cbw->dir, 7) ) - { - // OUT transfer + // queue transfer TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_out, _mscd_buf, p_msc->total_len) ); - } - else + }else { - // IN Transfer - int32_t cb_result; + int32_t resplen; - // first process if it is a built-in commands - cb_result = proc_builtin_scsi(p_cbw, _mscd_buf, sizeof(_mscd_buf)); + // First process if it is a built-in commands + resplen = proc_builtin_scsi(p_cbw->lun, p_cbw->command, _mscd_buf, sizeof(_mscd_buf)); - // Not an built-in command, invoke user callback - if ( cb_result < 0 ) + // Not built-in, invoke user callback + if ( (resplen < 0) && (p_msc->sense_key == 0) ) { - cb_result = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); + resplen = tud_msc_scsi_cb(p_cbw->lun, p_cbw->command, _mscd_buf, p_msc->total_len); } - if ( cb_result > 0 ) - { - p_msc->total_len = (uint32_t) cb_result; - p_csw->status = MSC_CSW_STATUS_PASSED; - - TU_ASSERT( p_cbw->total_bytes >= p_msc->total_len ); // cannot return more than host expect - TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); - }else + if ( resplen < 0 ) { p_msc->total_len = 0; p_csw->status = MSC_CSW_STATUS_FAILED; p_msc->stage = MSC_STAGE_STATUS; - tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); // Sense = Invalid Command Operation - usbd_edpt_stall(rhport, p_msc->ep_in); + // failed but senskey is not set: default to Illegal Request + if ( p_msc->sense_key == 0 ) tud_msc_set_sense(p_cbw->lun, SCSI_SENSE_ILLEGAL_REQUEST, 0x20, 0x00); + + /// Stall bulk In if needed + if (p_cbw->total_bytes) usbd_edpt_stall(rhport, p_msc->ep_in); + } + else + { + p_msc->total_len = (uint32_t) resplen; + p_csw->status = MSC_CSW_STATUS_PASSED; + + if (p_msc->total_len) + { + TU_ASSERT( p_cbw->total_bytes >= p_msc->total_len ); // cannot return more than host expect + TU_ASSERT( dcd_edpt_xfer(rhport, p_msc->ep_in, _mscd_buf, p_msc->total_len) ); + }else + { + p_msc->stage = MSC_STAGE_STATUS; + } } } } diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index 068bea3e..cbaea4bb 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -97,12 +97,19 @@ int32_t tud_msc_write10_cb (uint8_t lun, uint32_t lba, uint32_t offset, uint8_t* // Application fill vendor id, product id and revision with string up to 8, 16, 4 characters respectively void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]); +// Invoked when received Test Unit Ready command. +// return true allowing host to read/write this LUN e.g SD card inserted +bool tud_msc_test_unit_ready_cb(uint8_t lun); + // Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size // Application update block count and block size void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size); /** - * Callback invoked when received an SCSI command not in built-in list below. + * 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 + * * \param[in] lun Logical unit number * \param[in] scsi_cmd SCSI command contents which application must examine to response accordingly * \param[out] buffer Buffer for SCSI Data Stage. @@ -113,17 +120,13 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz * \return Actual bytes processed, can be zero for no-data command. * \retval negative Indicate error e.g unsupported command, tinyusb will \b STALL the corresponding * endpoint and return failed status in command status wrapper phase. - * - * \note Following command is automatically handled by tinyusb stack, callback should not be worried: - * - 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); /*------------- Optional callbacks -------------*/ -// Invoked when received GET_MAX_LUN request -ATTR_WEAK uint8_t tud_msc_maxlun_cb(void); +// Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation +ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); // Invoked when Read10 command is complete ATTR_WEAK void tud_msc_read10_complete_cb(uint8_t lun); From 6e4dc2f23dd6fe7725b145f49b49116859916b5c Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 May 2019 16:48:50 +0700 Subject: [PATCH 06/10] adding msc Start Stop to buitin command, but not complate yet add tud_msc_start_stop_cb() as optional callback --- examples/device/cdc_msc_hid/src/msc_disk.c | 32 ++++++++++++------- .../cdc_msc_hid_freertos/src/msc_disk.c | 20 ++++++++++++ .../device/msc_dual_lun/src/msc_disk_dual.c | 25 +++++++++++++-- src/class/msc/msc_device.c | 14 ++++++-- src/class/msc/msc_device.h | 5 +++ tools/build_all.py | 2 +- 6 files changed, 81 insertions(+), 17 deletions(-) diff --git a/examples/device/cdc_msc_hid/src/msc_disk.c b/examples/device/cdc_msc_hid/src/msc_disk.c index 970f0adc..ff7cb8d5 100644 --- a/examples/device/cdc_msc_hid/src/msc_disk.c +++ b/examples/device/cdc_msc_hid/src/msc_disk.c @@ -152,6 +152,26 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz *block_size = DISK_BLOCK_SIZE; } +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +void tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) +{ + (void) lun; + (void) power_condition; + + if ( load_eject ) + { + if (start) + { + // load disk storage + }else + { + // unload disk storage + } + } +} + // 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) @@ -200,18 +220,6 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, 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); 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 3d9103bd..c2a62e03 100644 --- a/examples/device/cdc_msc_hid_freertos/src/msc_disk.c +++ b/examples/device/cdc_msc_hid_freertos/src/msc_disk.c @@ -152,6 +152,26 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz *block_size = DISK_BLOCK_SIZE; } +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +void tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) +{ + (void) lun; + (void) power_condition; + + if ( load_eject ) + { + if (start) + { + // load disk storage + }else + { + // unload disk storage + } + } +} + // 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/msc_dual_lun/src/msc_disk_dual.c b/examples/device/msc_dual_lun/src/msc_disk_dual.c index 48f5cfb1..fd634730 100644 --- a/examples/device/msc_dual_lun/src/msc_disk_dual.c +++ b/examples/device/msc_dual_lun/src/msc_disk_dual.c @@ -234,15 +234,36 @@ bool tud_msc_test_unit_ready_cb(uint8_t lun) return true; // RAM disk is always ready } -// Callback invoked to determine disk's size +// Invoked when received SCSI_CMD_READ_CAPACITY_10 and SCSI_CMD_READ_FORMAT_CAPACITY to determine the disk size +// Application update block count and block size void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) { - (void) lun; // both LUNs have same size + (void) lun; *block_count = DISK_BLOCK_NUM; *block_size = DISK_BLOCK_SIZE; } +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +void tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) +{ + (void) lun; + (void) power_condition; + + if ( load_eject ) + { + if (start) + { + // load disk storage + }else + { + // unload disk storage + } + } +} + // 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/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index fcb118a6..509f5495 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -202,8 +202,18 @@ int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buff // not ready response with Failed status and sense key = not ready resplen = - 1; - // Logical Unit Not Ready, Cause Not Reportable - tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + } + break; + + case SCSI_CMD_START_STOP_UNIT: + resplen = 0; + + if (tud_msc_start_stop_cb) + { + scsi_start_stop_unit_t const * start_stop = (scsi_start_stop_unit_t const *) scsi_cmd; + tud_msc_start_stop_cb(lun, start_stop->power_condition, start_stop->start, start_stop->load_eject); } break; diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index cbaea4bb..a05634d5 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -128,6 +128,11 @@ int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_cmd[16], void* buffer, // Invoked when received GET_MAX_LUN request, required for multiple LUNs implementation ATTR_WEAK uint8_t tud_msc_get_maxlun_cb(void); +// Invoked when received Start Stop Unit command +// - Start = 0 : stopped power mode, if load_eject = 1 : unload disk storage +// - Start = 1 : active mode, if load_eject = 1 : load disk storage +ATTR_WEAK void tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject); + // 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 002b3002..37ca1443 100644 --- a/tools/build_all.py +++ b/tools/build_all.py @@ -46,7 +46,7 @@ for example in all_device_example: # FreeRTOS example #example = 'cdc_msc_hid_freertos' #board = 'pca10056' -#subprocess.run("make -j2 -C examples/device/{} BOARD={} clean all".format(example, board), shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) +#build_example(example, board) total_time = time.monotonic() - total_time From 81cb1c9510e4b4ccb03d165b4248fdf5688dd8ba Mon Sep 17 00:00:00 2001 From: hathach Date: Mon, 6 May 2019 23:46:10 +0700 Subject: [PATCH 07/10] clean up --- src/class/msc/msc_device.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/class/msc/msc_device.h b/src/class/msc/msc_device.h index a05634d5..1baf2d19 100644 --- a/src/class/msc/msc_device.h +++ b/src/class/msc/msc_device.h @@ -107,7 +107,7 @@ void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_siz /** * Invoked when received an SCSI command not in built-in list below. - * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, MODE_SENSE6, REQUEST_SENSE + * - READ_CAPACITY10, READ_FORMAT_CAPACITY, INQUIRY, TEST_UNIT_READY, START_STOP_UNIT, MODE_SENSE6, REQUEST_SENSE * - READ10 and WRITE10 has their own callbacks * * \param[in] lun Logical unit number From 77bc421359845c2fe4591b0ae19e513b9a84c05b Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 May 2019 23:31:18 +0700 Subject: [PATCH 08/10] fix clear stall usage, fix reset data toggle with dcd_clear_stall for nrf52 --- src/device/dcd.h | 2 +- src/device/usbd.c | 2 +- src/portable/nordic/nrf5x/dcd_nrf5x.c | 5 +++++ src/tusb_option.h | 9 ++++++++- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/device/dcd.h b/src/device/dcd.h index 63f923fa..18678f15 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -107,7 +107,7 @@ void dcd_remote_wakeup(uint8_t rhport); * must be called to notify the stack * - busy : Check if endpoint transferring is complete (TODO remove) * - stall : stall endpoint - * - clear_stall : clear stall + * - clear_stall : clear stall, data toggle is also reset to DATA0 *------------------------------------------------------------------*/ bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); diff --git a/src/device/usbd.c b/src/device/usbd.c index d811c471..434a2c3d 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -456,7 +456,7 @@ static bool process_control_request(uint8_t rhport, tusb_control_request_t const case TUSB_REQ_CLEAR_FEATURE: if ( TUSB_REQ_FEATURE_EDPT_HALT == p_request->wValue ) { - dcd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); + usbd_edpt_clear_stall(rhport, tu_u16_low(p_request->wIndex)); } usbd_control_status(rhport, p_request); break; diff --git a/src/portable/nordic/nrf5x/dcd_nrf5x.c b/src/portable/nordic/nrf5x/dcd_nrf5x.c index 3e5f69f7..53f92bb1 100644 --- a/src/portable/nordic/nrf5x/dcd_nrf5x.c +++ b/src/portable/nordic/nrf5x/dcd_nrf5x.c @@ -322,7 +322,12 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) if ( tu_edpt_number(ep_addr) ) { + // clear stall NRF_USBD->EPSTALL = (USBD_EPSTALL_STALL_UnStall << USBD_EPSTALL_STALL_Pos) | ep_addr; + + // reset data toggle to DATA0 + NRF_USBD->DTOGGLE = (USBD_DTOGGLE_VALUE_Data0 << USBD_DTOGGLE_VALUE_Pos) | ep_addr; + __ISB(); __DSB(); } } diff --git a/src/tusb_option.h b/src/tusb_option.h index cb6d573e..4e55132b 100644 --- a/src/tusb_option.h +++ b/src/tusb_option.h @@ -128,7 +128,6 @@ */ #ifndef CFG_TUSB_DEBUG #define CFG_TUSB_DEBUG 0 - #warning CFG_TUSB_DEBUG is not defined, default value is 0 #endif // place data in accessible RAM for usb controller @@ -165,6 +164,14 @@ #define CFG_TUD_MSC 0 #endif +#ifndef CFG_TUD_MIDI + #define CFG_TUD_MIDI 0 +#endif + +#ifndef CFG_TUD_CUSTOM_CLASS + #define CFG_TUD_CUSTOM_CLASS 0 +#endif + #endif // TUSB_OPT_DEVICE_ENABLED //-------------------------------------------------------------------- From 7063a0dd03cf50487389eb7bc3d9bde5c9f4cb58 Mon Sep 17 00:00:00 2001 From: hathach Date: Thu, 9 May 2019 23:33:55 +0700 Subject: [PATCH 09/10] msc device will stall READ_CAPACITY & READ_FORMAT_CAPACITY if tud_msc_capacity_cb() get zero size --- src/class/msc/msc_device.c | 43 +++++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c index 509f5495..c486d5e0 100644 --- a/src/class/msc/msc_device.c +++ b/src/class/msc/msc_device.c @@ -219,8 +219,6 @@ int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buff case SCSI_CMD_READ_CAPACITY_10: { - scsi_read_capacity10_resp_t read_capa10; - uint32_t block_count; uint32_t block_size; uint16_t block_size_u16; @@ -228,11 +226,24 @@ int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buff tud_msc_capacity_cb(lun, &block_count, &block_size_u16); block_size = (uint32_t) block_size_u16; - read_capa10.last_lba = ENDIAN_BE(block_count-1); - read_capa10.block_size = ENDIAN_BE(block_size); + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; - resplen = sizeof(read_capa10); - memcpy(buffer, &read_capa10, resplen); + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + scsi_read_capacity10_resp_t read_capa10; + + read_capa10.last_lba = ENDIAN_BE(block_count-1); + read_capa10.block_size = ENDIAN_BE(block_size); + + resplen = sizeof(read_capa10); + memcpy(buffer, &read_capa10, resplen); + } } break; @@ -250,11 +261,23 @@ int32_t proc_builtin_scsi(uint8_t lun, uint8_t const scsi_cmd[16], uint8_t* buff uint16_t block_size; tud_msc_capacity_cb(lun, &block_count, &block_size); - read_fmt_capa.block_num = ENDIAN_BE(block_count); - read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size); - resplen = sizeof(read_fmt_capa); - memcpy(buffer, &read_fmt_capa, resplen); + // Invalid block size/count from callback, possibly unit is not ready + // stall this request, set sense key to NOT READY + if (block_count == 0 || block_size == 0) + { + resplen = -1; + + // If sense key is not set by callback, default to Logical Unit Not Ready, Cause Not Reportable + if ( _mscd_itf.sense_key == 0 ) tud_msc_set_sense(lun, SCSI_SENSE_NOT_READY, 0x04, 0x00); + }else + { + read_fmt_capa.block_num = ENDIAN_BE(block_count); + read_fmt_capa.block_size_u16 = ENDIAN_BE16(block_size); + + resplen = sizeof(read_fmt_capa); + memcpy(buffer, &read_fmt_capa, resplen); + } } break; From 667133304b244927defd45d86281a5653401d356 Mon Sep 17 00:00:00 2001 From: hathach Date: Fri, 10 May 2019 00:10:18 +0700 Subject: [PATCH 10/10] fix samd dcd_clear_stall also reset data toggle --- src/portable/microchip/samd21/dcd_samd21.c | 4 ++-- src/portable/microchip/samd51/dcd_samd51.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/portable/microchip/samd21/dcd_samd21.c b/src/portable/microchip/samd21/dcd_samd21.c index 8ecfd366..9a996450 100644 --- a/src/portable/microchip/samd21/dcd_samd21.c +++ b/src/portable/microchip/samd21/dcd_samd21.c @@ -223,9 +223,9 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1; + ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1 | USB_DEVICE_EPSTATUSCLR_DTGLIN; } else { - ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0; + ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0 | USB_DEVICE_EPSTATUSCLR_DTGLOUT; } } diff --git a/src/portable/microchip/samd51/dcd_samd51.c b/src/portable/microchip/samd51/dcd_samd51.c index d2e7aaf7..6a4bd0e6 100644 --- a/src/portable/microchip/samd51/dcd_samd51.c +++ b/src/portable/microchip/samd51/dcd_samd51.c @@ -227,9 +227,9 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr) UsbDeviceEndpoint* ep = &USB->DEVICE.DeviceEndpoint[epnum]; if (tu_edpt_dir(ep_addr) == TUSB_DIR_IN) { - ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1; + ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ1 | USB_DEVICE_EPSTATUSCLR_DTGLIN; } else { - ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0; + ep->EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_STALLRQ0 | USB_DEVICE_EPSTATUSCLR_DTGLOUT; } }