Kaynağa Gözat

Merge pull request #674 from hathach/host-msc

Enhance Host MSC
Ha Thach 5 yıl önce
ebeveyn
işleme
656673fb58

+ 0 - 0
examples/host/cdc_msc_hid/.only.MCU_MIMXRT10XX


+ 3 - 3
examples/host/cdc_msc_hid/Makefile

@@ -19,9 +19,9 @@ SRC_C += \
 	src/host/hub.c \
 	src/host/usbh.c \
 	src/host/usbh_control.c \
-	src/host/ehci/ehci.c \
-	src/host/ohci/ohci.c \
-	src/portable/nxp/lpc18_43/hcd_lpc18_43.c \
+	src/portable/ehci/ehci.c \
+	src/portable/ohci/ohci.c \
+	src/portable/nxp/transdimension/hcd_transdimension.c \
 	src/portable/nxp/lpc17_40/hcd_lpc17_40.c
 
 include ../../rules.mk

+ 9 - 46
examples/host/cdc_msc_hid/src/msc_app.c

@@ -31,31 +31,6 @@
 // MACRO TYPEDEF CONSTANT ENUM DECLARATION
 //--------------------------------------------------------------------+
 static scsi_inquiry_resp_t inquiry_resp;
-static scsi_read_capacity10_resp_t capacity_resp;
-
-uint32_t block_size;
-uint32_t block_count;
-
-bool capacity_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
-{
-  (void) dev_addr;
-  (void) cbw;
-
-  if (csw->status != 0)
-  {
-    printf("Read Capacity (10) failed\r\n");
-    return false;
-  }
-
-  // Capacity response field: Block size and Last LBA are both Big-Endian
-  block_count = tu_ntohl(capacity_resp.last_lba) + 1;
-  block_size = tu_ntohl(capacity_resp.block_size);
-
-  printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
-  printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
-
-  return true;
-}
 
 bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
 {
@@ -68,21 +43,23 @@ bool inquiry_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const
   // Print out Vendor ID, Product ID and Rev
   printf("%.8s %.16s rev %.4s\r\n", inquiry_resp.vendor_id, inquiry_resp.product_id, inquiry_resp.product_rev);
 
-  // Read capacity of device
-  tuh_msc_read_capacity(dev_addr, cbw->lun, &capacity_resp, capacity_complete_cb);
+  // Get capacity of device
+  uint32_t const block_count = tuh_msc_get_block_count(dev_addr, cbw->lun);
+  uint32_t const block_size = tuh_msc_get_block_size(dev_addr, cbw->lun);
+
+  printf("Disk Size: %lu MB\r\n", block_count / ((1024*1024)/block_size));
+  printf("Block Count = %lu, Block Size: %lu\r\n", block_count, block_size);
 
   return true;
 }
 
 //------------- IMPLEMENTATION -------------//
-void tuh_msc_mounted_cb(uint8_t dev_addr)
+void tuh_msc_mount_cb(uint8_t dev_addr)
 {
   printf("A MassStorage device is mounted\r\n");
 
-  block_size = block_count = 0;
-
   uint8_t const lun = 0;
-  tuh_msc_scsi_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
+  tuh_msc_inquiry(dev_addr, lun, &inquiry_resp, inquiry_complete_cb);
 //
 //  //------------- file system (only 1 LUN support) -------------//
 //  uint8_t phy_disk = dev_addr-1;
@@ -96,13 +73,6 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
 //      return;
 //    }
 //
-//    puts("---------------------------------------------------------------------");
-//    puts("- MASSSTORAGE CLASS CLI IS A IMMATURE CODE. DISK-WRITING COMMANDS");
-//    puts("- SUCH AS cp(COPY), mkdir(MAKE DIRECTORY) ARE POTENTIAL TO DAMAGE");
-//    puts("- YOUR USB THUMBDRIVE. USING THOSE COMMANDS ARE AT YOUR OWN RISK.");
-//    puts("- THE AUTHOR HAS NO RESPONSIBILITY WITH YOUR DEVICE NOR ITS DATA");
-//    puts("---------------------------------------------------------------------");
-//
 //    f_chdrive(phy_disk); // change to newly mounted drive
 //    f_chdir("/"); // root as current dir
 //
@@ -110,7 +80,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
 //  }
 }
 
-void tuh_msc_unmounted_cb(uint8_t dev_addr)
+void tuh_msc_unmount_cb(uint8_t dev_addr)
 {
   (void) dev_addr;
   printf("A MassStorage device is unmounted\r\n");
@@ -133,11 +103,4 @@ void tuh_msc_unmounted_cb(uint8_t dev_addr)
 //  }
 }
 
-//void tuh_msc_scsi_complete_cb(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
-//{
-//  (void) dev_addr;
-//  (void) cbw;
-//  (void) csw;
-//}
-
 #endif

+ 2 - 2
examples/obsolete/host/src/msc_host_app.c

@@ -48,7 +48,7 @@ CFG_TUSB_MEM_SECTION static FATFS fatfs[CFG_TUSB_HOST_DEVICE_MAX];
 //--------------------------------------------------------------------+
 // tinyusb callbacks
 //--------------------------------------------------------------------+
-void tuh_msc_mounted_cb(uint8_t dev_addr)
+void tuh_msc_mount_cb(uint8_t dev_addr)
 {
   puts("\na MassStorage device is mounted");
 
@@ -94,7 +94,7 @@ void tuh_msc_mounted_cb(uint8_t dev_addr)
   }
 }
 
-void tuh_msc_unmounted_cb(uint8_t dev_addr)
+void tuh_msc_unmount_cb(uint8_t dev_addr)
 {
   puts("\na MassStorage device is unmounted");
 

+ 5 - 4
hw/bsp/imxrt/family.c

@@ -82,10 +82,15 @@ void board_init(void)
   LPUART_Init(UART_PORT, &uart_config, (CLOCK_GetPllFreq(kCLOCK_PllUsb1) / 6U) / (CLOCK_GetDiv(kCLOCK_UartDiv) + 1U));
 
   //------------- USB0 -------------//
+
   // Clock
   CLOCK_EnableUsbhs0PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
   CLOCK_EnableUsbhs0Clock(kCLOCK_Usb480M, 480000000U);
 
+  // USB1
+//  CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
+//  CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
+
   USBPHY_Type* usb_phy;
 
   // RT105x RT106x have dual USB controller. TODO support USB2
@@ -106,10 +111,6 @@ void board_init(void)
   phytx &= ~(USBPHY_TX_D_CAL_MASK | USBPHY_TX_TXCAL45DM_MASK | USBPHY_TX_TXCAL45DP_MASK);
   phytx |= USBPHY_TX_D_CAL(0x0C) | USBPHY_TX_TXCAL45DP(0x06) | USBPHY_TX_TXCAL45DM(0x06);
   usb_phy->TX = phytx;
-
-  // USB1
-//  CLOCK_EnableUsbhs1PhyPllClock(kCLOCK_Usbphy480M, 480000000U);
-//  CLOCK_EnableUsbhs1Clock(kCLOCK_Usb480M, 480000000U);
 }
 
 //--------------------------------------------------------------------+

+ 0 - 39
hw/bsp/mcb1800/mcb1800.c

@@ -157,51 +157,12 @@ void board_init(void)
   Chip_UART_TXEnable(UART_DEV);
 
   //------------- USB -------------//
-  enum {
-    USBMODE_DEVICE = 2,
-    USBMODE_HOST   = 3
-  };
-
-  enum {
-    USBMODE_VBUS_LOW  = 0,
-    USBMODE_VBUS_HIGH = 1
-  };
-
-  // USB0
 #if CFG_TUSB_RHPORT0_MODE
   Chip_USB0_Init();
-
-  // Host/Device mode can only be set right after controller reset
-  LPC_USB0->USBCMD_D |= 0x02;
-  while( LPC_USB0->USBCMD_D & 0x02 ) {}
-
-  // Set mode
-  #if CFG_TUSB_RHPORT0_MODE & OPT_MODE_HOST
-    LPC_USB0->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
-    LPC_USB0->PORTSC1_H |= (1<<24); // FIXME force full speed for debugging
-  #else // TODO OTG
-    LPC_USB0->USBMODE_D = USBMODE_DEVICE;
-    LPC_USB0->OTGSC = (1<<3) | (1<<0) /*| (1<<16)| (1<<24)| (1<<25)| (1<<26)| (1<<27)| (1<<28)| (1<<29)| (1<<30)*/;
-  #endif
 #endif
 
-  // USB1
 #if CFG_TUSB_RHPORT1_MODE
   Chip_USB1_Init();
-
-//  // Reset controller
-//  LPC_USB1->USBCMD_D |= 0x02;
-//  while( LPC_USB1->USBCMD_D & 0x02 ) {}
-//
-//  // Set mode
-//  #if CFG_TUSB_RHPORT1_MODE & OPT_MODE_HOST
-//    LPC_USB1->USBMODE_H = USBMODE_HOST | (USBMODE_VBUS_HIGH << 5);
-//  #else // TODO OTG
-//    LPC_USB1->USBMODE_D = USBMODE_DEVICE;
-//  #endif
-//
-//  // USB1 as fullspeed
-//  LPC_USB1->PORTSC1_D |= (1<<24);
 #endif
 }
 

+ 1 - 1
lib/fatfs/diskio.c

@@ -48,7 +48,7 @@ static DSTATUS disk_state[CFG_TUSB_HOST_DEVICE_MAX];
 static DRESULT wait_for_io_complete(uint8_t usb_addr)
 {
   // TODO with RTOS, this should use semaphore instead of blocking
-  while ( tuh_msc_is_busy(usb_addr) )
+  while ( !tuh_msc_ready(usb_addr) )
   {
     // TODO should have timeout here
     #if CFG_TUSB_OS != OPT_OS_NONE

+ 128 - 89
src/class/msc/msc_host.c

@@ -47,14 +47,21 @@ enum
 
 typedef struct
 {
-  uint8_t  itf_num;
-  uint8_t  ep_in;
-  uint8_t  ep_out;
+  uint8_t itf_num;
+  uint8_t ep_in;
+  uint8_t ep_out;
 
-  uint8_t  max_lun;
+  uint8_t max_lun;
 
-  volatile bool mounted;
+  volatile bool configured; // Receive SET_CONFIGURE
+  volatile bool mounted;    // Enumeration is complete
 
+  struct {
+    uint32_t block_size;
+    uint32_t block_count;
+  } capacity[CFG_TUH_MSC_MAXLUN];
+
+  //------------- SCSI -------------//
   uint8_t stage;
   void*   buffer;
   tuh_msc_complete_cb_t complete_cb;
@@ -63,14 +70,15 @@ typedef struct
   msc_csw_t csw;
 }msch_interface_t;
 
-CFG_TUSB_MEM_SECTION static msch_interface_t msch_data[CFG_TUSB_HOST_DEVICE_MAX];
+CFG_TUSB_MEM_SECTION static msch_interface_t _msch_itf[CFG_TUSB_HOST_DEVICE_MAX];
 
-// buffer used to read scsi information when mounted, largest response data currently is inquiry
-CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t msch_buffer[sizeof(scsi_inquiry_resp_t)];
+// buffer used to read scsi information when mounted
+// largest response data currently is inquiry TODO Inquiry is not part of enum anymore
+CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4) static uint8_t _msch_buffer[sizeof(scsi_inquiry_resp_t)];
 
 static inline msch_interface_t* get_itf(uint8_t dev_addr)
 {
-  return &msch_data[dev_addr-1];
+  return &_msch_itf[dev_addr-1];
 }
 
 //--------------------------------------------------------------------+
@@ -82,34 +90,45 @@ uint8_t tuh_msc_get_maxlun(uint8_t dev_addr)
   return p_msc->max_lun;
 }
 
-bool tuh_msc_mounted(uint8_t dev_addr)
+uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun)
 {
   msch_interface_t* p_msc = get_itf(dev_addr);
+  return p_msc->capacity[lun].block_count;
+}
 
-  // is configured can be omitted
-  return tuh_device_is_configured(dev_addr) && p_msc->mounted;
+uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun)
+{
+  msch_interface_t* p_msc = get_itf(dev_addr);
+  return p_msc->capacity[lun].block_size;
 }
 
-bool tuh_msc_is_busy(uint8_t dev_addr)
+bool tuh_msc_mounted(uint8_t dev_addr)
 {
   msch_interface_t* p_msc = get_itf(dev_addr);
-  return p_msc->mounted && hcd_edpt_busy(dev_addr, p_msc->ep_in);
+  return p_msc->mounted;
+}
+
+bool tuh_msc_ready(uint8_t dev_addr)
+{
+  msch_interface_t* p_msc = get_itf(dev_addr);
+  return p_msc->mounted && !hcd_edpt_busy(dev_addr, p_msc->ep_in);
 }
 
 //--------------------------------------------------------------------+
 // PUBLIC API: SCSI COMMAND
 //--------------------------------------------------------------------+
-static inline void msc_cbw_add_signature(msc_cbw_t *p_cbw, uint8_t lun)
+static inline void cbw_init(msc_cbw_t *cbw, uint8_t lun)
 {
-  p_cbw->signature  = MSC_CBW_SIGNATURE;
-  p_cbw->tag        = 0x54555342; // TUSB
-  p_cbw->lun        = lun;
+  tu_memclr(cbw, sizeof(msc_cbw_t));
+  cbw->signature = MSC_CBW_SIGNATURE;
+  cbw->tag       = 0x54555342; // TUSB
+  cbw->lun       = lun;
 }
 
 bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb)
 {
   msch_interface_t* p_msc = get_itf(dev_addr);
-  // TU_VERIFY(p_msc->mounted); // TODO part of the enumeration also use scsi command
+  TU_VERIFY(p_msc->configured);
 
   // TODO claim endpoint
 
@@ -125,12 +144,12 @@ bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tu
 
 bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb)
 {
-  msch_interface_t* p_msc = get_itf(dev_addr);
-  if ( !p_msc->mounted ) return false;
+   msch_interface_t* p_msc = get_itf(dev_addr);
+   TU_VERIFY(p_msc->configured);
 
-  msc_cbw_t cbw = { 0 };
+  msc_cbw_t cbw;
+  cbw_init(&cbw, lun);
 
-  msc_cbw_add_signature(&cbw, lun);
   cbw.total_bytes = sizeof(scsi_read_capacity10_resp_t);
   cbw.dir        = TUSB_DIR_IN_MASK;
   cbw.cmd_len    = sizeof(scsi_read_capacity10_t);
@@ -139,11 +158,14 @@ bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_r
   return tuh_msc_scsi_command(dev_addr, &cbw, response, complete_cb);
 }
 
-bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
+bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb)
 {
-  msc_cbw_t cbw = { 0 };
+  msch_interface_t* p_msc = get_itf(dev_addr);
+  TU_VERIFY(p_msc->mounted);
+
+  msc_cbw_t cbw;
+  cbw_init(&cbw, lun);
 
-  msc_cbw_add_signature(&cbw, lun);
   cbw.total_bytes = sizeof(scsi_inquiry_resp_t);
   cbw.dir         = TUSB_DIR_IN_MASK;
   cbw.cmd_len     = sizeof(scsi_inquiry_t);
@@ -160,26 +182,29 @@ bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* re
 
 bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb)
 {
-  msc_cbw_t cbw = { 0 };
-  msc_cbw_add_signature(&cbw, lun);
+  msch_interface_t* p_msc = get_itf(dev_addr);
+  TU_VERIFY(p_msc->configured);
 
-  cbw.total_bytes = 0; // Number of bytes
-  cbw.dir        = TUSB_DIR_OUT;
-  cbw.cmd_len    = sizeof(scsi_test_unit_ready_t);
-  cbw.command[0] = SCSI_CMD_TEST_UNIT_READY;
-  cbw.command[1] = lun; // according to wiki TODO need verification
+  msc_cbw_t cbw;
+  cbw_init(&cbw, lun);
+
+  cbw.total_bytes = 0;
+  cbw.dir         = TUSB_DIR_OUT;
+  cbw.cmd_len     = sizeof(scsi_test_unit_ready_t);
+  cbw.command[0]  = SCSI_CMD_TEST_UNIT_READY;
+  cbw.command[1]  = lun; // according to wiki TODO need verification
 
   return tuh_msc_scsi_command(dev_addr, &cbw, NULL, complete_cb);
 }
 
 bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb)
 {
-  msc_cbw_t cbw = { 0 };
-  msc_cbw_add_signature(&cbw, lun);
+  msc_cbw_t cbw;
+  cbw_init(&cbw, lun);
 
   cbw.total_bytes = 18; // TODO sense response
-  cbw.dir        = TUSB_DIR_IN_MASK;
-  cbw.cmd_len    = sizeof(scsi_request_sense_t);
+  cbw.dir         = TUSB_DIR_IN_MASK;
+  cbw.cmd_len     = sizeof(scsi_request_sense_t);
 
   scsi_request_sense_t const cmd_request_sense =
   {
@@ -192,60 +217,53 @@ bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_ms
   return tuh_msc_scsi_command(dev_addr, &cbw, resposne, complete_cb);
 }
 
-#if 0
-
-tusb_error_t  tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count)
+bool tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb)
 {
-  msch_interface_t* p_msch = &msch_data[dev_addr-1];
-
-  //------------- Command Block Wrapper -------------//
-  msc_cbw_add_signature(&p_msch->cbw, lun);
-
-  p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes
-  p_msch->cbw.dir        = TUSB_DIR_IN_MASK;
-  p_msch->cbw.cmd_len    = sizeof(scsi_read10_t);
+  msch_interface_t* p_msc = get_itf(dev_addr);
+  TU_VERIFY(p_msc->mounted);
 
-  //------------- SCSI command -------------//
-  scsi_read10_t cmd_read10 =msch_sem_hdl
+  msc_cbw_t cbw;
+  cbw_init(&cbw, lun);
+ 
+  cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
+  cbw.dir         = TUSB_DIR_IN_MASK;
+  cbw.cmd_len     = sizeof(scsi_read10_t);
+ 
+  scsi_read10_t const cmd_read10 =
   {
-      .cmd_code    = SCSI_CMD_READ_10,
-      .lba         = tu_htonl(lba),
-      .block_count = tu_htons(block_count)
+    .cmd_code    = SCSI_CMD_READ_10,
+    .lba         = tu_htonl(lba),
+    .block_count = tu_htons(block_count)
   };
-
-  memcpy(p_msch->cbw.command, &cmd_read10, p_msch->cbw.cmd_len);
-
-  TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, p_buffer));
-
-  return TUSB_ERROR_NONE;
+ 
+  memcpy(cbw.command, &cmd_read10, cbw.cmd_len);
+ 
+  return tuh_msc_scsi_command(dev_addr, &cbw, buffer, complete_cb);
 }
-
-tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count)
+ 
+bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb)
 {
-  msch_interface_t* p_msch = &msch_data[dev_addr-1];
+  msch_interface_t* p_msc = get_itf(dev_addr);
+  TU_VERIFY(p_msc->mounted);
 
-  //------------- Command Block Wrapper -------------//
-  msc_cbw_add_signature(&p_msch->cbw, lun);
+  msc_cbw_t cbw;
+  cbw_init(&cbw, lun);
 
-  p_msch->cbw.total_bytes = p_msch->block_size*block_count; // Number of bytes
-  p_msch->cbw.dir        = TUSB_DIR_OUT;
-  p_msch->cbw.cmd_len    = sizeof(scsi_write10_t);
+  cbw.total_bytes = block_count*p_msc->capacity[lun].block_size;
+  cbw.dir         = TUSB_DIR_OUT;
+  cbw.cmd_len     = sizeof(scsi_write10_t);
 
-  //------------- SCSI command -------------//
-  scsi_write10_t cmd_write10 =
+  scsi_write10_t const cmd_write10 =
   {
-      .cmd_code    = SCSI_CMD_WRITE_10,
-      .lba         = tu_htonl(lba),
-      .block_count = tu_htons(block_count)
+    .cmd_code    = SCSI_CMD_WRITE_10,
+    .lba         = tu_htonl(lba),
+    .block_count = tu_htons(block_count)
   };
 
-  memcpy(p_msch->cbw.command, &cmd_write10, p_msch->cbw.cmd_len);
-
-  TU_ASSERT_ERR ( send_cbw(dev_addr, p_msch, (void*) p_buffer));
+  memcpy(cbw.command, &cmd_write10, cbw.cmd_len);
 
-  return TUSB_ERROR_NONE;
+  return tuh_msc_scsi_command(dev_addr, &cbw, (void*) buffer, complete_cb);
 }
-#endif
 
 #if 0
 // MSC interface Reset (not used now)
@@ -273,14 +291,14 @@ bool tuh_msc_reset(uint8_t dev_addr)
 //--------------------------------------------------------------------+
 void msch_init(void)
 {
-  tu_memclr(msch_data, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
+  tu_memclr(_msch_itf, sizeof(msch_interface_t)*CFG_TUSB_HOST_DEVICE_MAX);
 }
 
 void msch_close(uint8_t dev_addr)
 {
   msch_interface_t* p_msc = get_itf(dev_addr);
   tu_memclr(p_msc, sizeof(msch_interface_t));
-  tuh_msc_unmounted_cb(dev_addr); // invoke Application Callback
+  tuh_msc_unmount_cb(dev_addr); // invoke Application Callback
 }
 
 bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
@@ -337,6 +355,7 @@ bool msch_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32
 static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t const * request, xfer_result_t result);
 static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
 static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
+static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw);
 
 bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length)
 {
@@ -375,6 +394,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
   msch_interface_t* p_msc = get_itf(dev_addr);
   TU_ASSERT(p_msc->itf_num == itf_num);
 
+  p_msc->configured = true;
+
   //------------- Get Max Lun -------------//
   TU_LOG2("MSC Get Max Lun\r\n");
   tusb_control_request_t request =
@@ -402,12 +423,13 @@ static bool config_get_maxlun_complete (uint8_t dev_addr, tusb_control_request_t
   msch_interface_t* p_msc = get_itf(dev_addr);
 
   // STALL means zero
-  p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? msch_buffer[0] : 0;
+  p_msc->max_lun = (XFER_RESULT_SUCCESS == result) ? _msch_buffer[0] : 0;
   p_msc->max_lun++; // MAX LUN is minus 1 by specs
 
   // TODO multiple LUN support
   TU_LOG2("SCSI Test Unit Ready\r\n");
-  tuh_msc_test_unit_ready(dev_addr, 0, config_test_unit_ready_complete);
+  uint8_t const lun = 0;
+  tuh_msc_test_unit_ready(dev_addr, lun, config_test_unit_ready_complete);
 
   return true;
 }
@@ -416,19 +438,16 @@ static bool config_test_unit_ready_complete(uint8_t dev_addr, msc_cbw_t const* c
 {
   if (csw->status == 0)
   {
-    msch_interface_t* p_msc = get_itf(dev_addr);
-
-    usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
-
-    // Unit is ready, Enumeration is complete
-    p_msc->mounted = true;
-    tuh_msc_mounted_cb(dev_addr);
+    // Unit is ready, read its capacity
+    TU_LOG2("SCSI Read Capacity\r\n");
+    tuh_msc_read_capacity(dev_addr, cbw->lun, (scsi_read_capacity10_resp_t*) _msch_buffer, config_read_capacity_complete);
   }else
   {
     // Note: During enumeration, some device fails Test Unit Ready and require a few retries
     // with Request Sense to start working !!
     // TODO limit number of retries
-    TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, msch_buffer, config_request_sense_complete));
+    TU_LOG2("SCSI Request Sense\r\n");
+    TU_ASSERT(tuh_msc_request_sense(dev_addr, cbw->lun, _msch_buffer, config_request_sense_complete));
   }
 
   return true;
@@ -441,4 +460,24 @@ static bool config_request_sense_complete(uint8_t dev_addr, msc_cbw_t const* cbw
   return true;
 }
 
+static bool config_read_capacity_complete(uint8_t dev_addr, msc_cbw_t const* cbw, msc_csw_t const* csw)
+{
+  TU_ASSERT(csw->status == 0);
+
+  msch_interface_t* p_msc = get_itf(dev_addr);
+
+  // Capacity response field: Block size and Last LBA are both Big-Endian
+  scsi_read_capacity10_resp_t* resp = (scsi_read_capacity10_resp_t*) _msch_buffer;
+  p_msc->capacity[cbw->lun].block_count = tu_ntohl(resp->last_lba) + 1;
+  p_msc->capacity[cbw->lun].block_size = tu_ntohl(resp->block_size);
+
+  // Mark enumeration is complete
+  p_msc->mounted = true;
+  tuh_msc_mount_cb(dev_addr);
+
+  usbh_driver_set_config_complete(dev_addr, p_msc->itf_num);
+
+  return true;
+}
+
 #endif

+ 40 - 48
src/class/msc/msc_host.h

@@ -35,6 +35,15 @@
  extern "C" {
 #endif
 
+//--------------------------------------------------------------------+
+// Class Driver Configuration
+//--------------------------------------------------------------------+
+
+#ifndef CFG_TUH_MSC_MAXLUN
+#define CFG_TUH_MSC_MAXLUN  4
+#endif
+
+
 /** \addtogroup ClassDriver_MSC
  *  @{
  * \defgroup MSC_Host Host
@@ -51,73 +60,56 @@ typedef bool (*tuh_msc_complete_cb_t)(uint8_t dev_addr, msc_cbw_t const* cbw, ms
 // This function true after tuh_msc_mounted_cb() and false after tuh_msc_unmounted_cb()
 bool tuh_msc_mounted(uint8_t dev_addr);
 
-/** \brief      Check if the interface is currently busy or not
- * \param[in]   dev_addr device address
- * \retval      true if the interface is busy meaning the stack is still transferring/waiting data from/to device
- * \retval      false if the interface is not busy meaning the stack successfully transferred data from/to device
- * \note        This function is used to check if previous transfer is complete (success or error), so that the next transfer
- *              can be scheduled. User needs to make sure the corresponding interface is mounted (by \ref tuh_msc_is_mounted)
- *              before calling this function
- */
-bool          tuh_msc_is_busy(uint8_t dev_addr);
+// Check if the interface is currently ready or busy transferring data
+bool tuh_msc_ready(uint8_t dev_addr);
 
 // Get Max Lun
 uint8_t tuh_msc_get_maxlun(uint8_t dev_addr);
 
-// Carry out a full SCSI command (cbw, data, csw) in non-blocking manner.
-// `complete_cb` callback is invoked when SCSI op is complete.
+// Get number of block
+uint32_t tuh_msc_get_block_count(uint8_t dev_addr, uint8_t lun);
+
+// Get block size in bytes
+uint32_t tuh_msc_get_block_size(uint8_t dev_addr, uint8_t lun);
+
+// Perform a full SCSI command (cbw, data, csw) in non-blocking manner.
+// Complete callback is invoked when SCSI op is complete.
 // return true if success, false if there is already pending operation.
 bool tuh_msc_scsi_command(uint8_t dev_addr, msc_cbw_t const* cbw, void* data, tuh_msc_complete_cb_t complete_cb);
 
-// Carry out SCSI INQUIRY command in non-blocking manner.
-bool tuh_msc_scsi_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb);
+// Perform SCSI Inquiry command
+// Complete callback is invoked when SCSI op is complete.
+bool tuh_msc_inquiry(uint8_t dev_addr, uint8_t lun, scsi_inquiry_resp_t* response, tuh_msc_complete_cb_t complete_cb);
 
-// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner.
+// Perform SCSI Test Unit Ready command
+// Complete callback is invoked when SCSI op is complete.
 bool tuh_msc_test_unit_ready(uint8_t dev_addr, uint8_t lun, tuh_msc_complete_cb_t complete_cb);
 
-// Carry out SCSI REQUEST SENSE (10) command in non-blocking manner.
+// Perform SCSI Request Sense 10 command
+// Complete callback is invoked when SCSI op is complete.
 bool tuh_msc_request_sense(uint8_t dev_addr, uint8_t lun, void *resposne, tuh_msc_complete_cb_t complete_cb);
 
-// Carry out SCSI READ CAPACITY (10) command in non-blocking manner.
-bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb);
+// Perform SCSI Read 10 command. Read n blocks starting from LBA to buffer
+// Complete callback is invoked when SCSI op is complete.
+bool  tuh_msc_read10(uint8_t dev_addr, uint8_t lun, void * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
 
-#if 0
-/** \brief 			Perform SCSI READ 10 command to read data from MassStorage device
- * \param[in]		dev_addr	device address
- * \param[in]		lun       Targeted Logical Unit
- * \param[out]	p_buffer  Buffer used to store data read from device. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
- * \param[in]		lba       Starting Logical Block Address to be read
- * \param[in]		block_count Number of Block to be read
- * \retval      TUSB_ERROR_NONE on success
- * \retval      TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
- * \retval      TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
- * \retval      TUSB_ERROR_INVALID_PARA if input parameters are not correct
- * \note        This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function
- */
-tusb_error_t tuh_msc_read10 (uint8_t dev_addr, uint8_t lun, void * p_buffer, uint32_t lba, uint16_t block_count);
-
-/** \brief 			Perform SCSI WRITE 10 command to write data to MassStorage device
- * \param[in]		dev_addr	device address
- * \param[in]		lun       Targeted Logical Unit
- * \param[in]	  p_buffer  Buffer containing data. Must be accessible by USB controller (see \ref CFG_TUSB_MEM_SECTION)
- * \param[in]		lba       Starting Logical Block Address to be written
- * \param[in]		block_count Number of Block to be written
- * \retval      TUSB_ERROR_NONE on success
- * \retval      TUSB_ERROR_INTERFACE_IS_BUSY if the interface is already transferring data with device
- * \retval      TUSB_ERROR_DEVICE_NOT_READY if device is not yet configured (by SET CONFIGURED request)
- * \retval      TUSB_ERROR_INVALID_PARA if input parameters are not correct
- * \note        This function is non-blocking and returns immediately. The result of USB transfer will be reported by the interface's callback function
- */
-tusb_error_t tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * p_buffer, uint32_t lba, uint16_t block_count);
-#endif
+// Perform SCSI Write 10 command. Write n blocks starting from LBA to device
+// Complete callback is invoked when SCSI op is complete.
+bool tuh_msc_write10(uint8_t dev_addr, uint8_t lun, void const * buffer, uint32_t lba, uint16_t block_count, tuh_msc_complete_cb_t complete_cb);
+
+// Perform SCSI Read Capacity 10 command
+// Complete callback is invoked when SCSI op is complete.
+// Note: during enumeration, host stack already carried out this request. Application can retrieve capacity by
+// simply call tuh_msc_get_block_count() and tuh_msc_get_block_size()
+bool tuh_msc_read_capacity(uint8_t dev_addr, uint8_t lun, scsi_read_capacity10_resp_t* response, tuh_msc_complete_cb_t complete_cb);
 
 //------------- Application Callback -------------//
 
 // Invoked when a device with MassStorage interface is mounted
-void tuh_msc_mounted_cb(uint8_t dev_addr);
+void tuh_msc_mount_cb(uint8_t dev_addr);
 
 // Invoked when a device with MassStorage interface is unmounted
-void tuh_msc_unmounted_cb(uint8_t dev_addr);
+void tuh_msc_unmount_cb(uint8_t dev_addr);
 
 //--------------------------------------------------------------------+
 // Internal Class Driver API

+ 1 - 1
src/host/hcd.h

@@ -98,7 +98,7 @@ enum {
 //--------------------------------------------------------------------+
 // Controller & Port API
 //--------------------------------------------------------------------+
-bool hcd_init(void);
+bool hcd_init(uint8_t rhport);
 void hcd_int_handler(uint8_t rhport);
 void hcd_int_enable (uint8_t rhport);
 void hcd_int_disable(uint8_t rhport);

+ 1 - 1
src/host/usbh.c

@@ -197,7 +197,7 @@ bool tuh_init(void)
     usbh_class_drivers[drv_id].init();
   }
 
-  TU_ASSERT(hcd_init());
+  TU_ASSERT(hcd_init(TUH_OPT_RHPORT));
   hcd_int_enable(TUH_OPT_RHPORT);
 
   return true;

+ 10 - 11
src/host/ehci/ehci.c → src/portable/ehci/ehci.c

@@ -26,14 +26,17 @@
 
 #include "common/tusb_common.h"
 
-#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX)
+#if TUSB_OPT_HOST_ENABLED && \
+   (CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
+    CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX )
+
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
 #include "osal/osal.h"
 
-#include "../hcd.h"
-#include "../usbh_hcd.h"
+#include "host/hcd.h"
+#include "host/usbh_hcd.h"
 #include "ehci.h"
 
 //--------------------------------------------------------------------+
@@ -48,6 +51,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(4096) static ehci_data_t ehci_data;
 
 // EHCI portable
 uint32_t hcd_ehci_register_addr(uint8_t rhport);
+bool hcd_ehci_init (uint8_t rhport); // TODO move later
 
 //--------------------------------------------------------------------+
 // PROTOTYPE
@@ -97,16 +101,9 @@ static void qtd_init (ehci_qtd_t* p_qtd, void* buffer, uint16_t total_bytes);
 static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
 static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer);
 
-static bool ehci_init (uint8_t rhport);
-
 //--------------------------------------------------------------------+
 // HCD API
 //--------------------------------------------------------------------+
-bool hcd_init(void)
-{
-  tu_memclr(&ehci_data, sizeof(ehci_data_t));
-  return ehci_init(TUH_OPT_RHPORT);
-}
 
 uint32_t hcd_uframe_number(uint8_t rhport)
 {
@@ -203,8 +200,10 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
 }
 
 // EHCI controller init
-static bool ehci_init(uint8_t rhport)
+bool hcd_ehci_init(uint8_t rhport)
 {
+  tu_memclr(&ehci_data, sizeof(ehci_data_t));
+
   ehci_data.regs = (ehci_registers_t* ) hcd_ehci_register_addr(rhport);
 
   ehci_registers_t* regs = ehci_data.regs;

+ 0 - 2
src/host/ehci/ehci.h → src/portable/ehci/ehci.h

@@ -33,8 +33,6 @@
 #ifndef _TUSB_EHCI_H_
 #define _TUSB_EHCI_H_
 
-#include "common/tusb_common.h"
-#include "../hcd.h"
 
 /* Abbreviation
  * HC: Host Controller

+ 0 - 50
src/portable/nxp/lpc18_43/hcd_lpc18_43.c

@@ -1,50 +0,0 @@
-/* 
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * This file is part of the TinyUSB stack.
- */
-
-#include "tusb_option.h"
-
-#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX)
-
-#include "chip.h"
-
-// LPC18xx and 43xx use EHCI driver
-
-void hcd_int_enable(uint8_t rhport)
-{
-  NVIC_EnableIRQ(rhport ? USB1_IRQn : USB0_IRQn);
-}
-
-void hcd_int_disable(uint8_t rhport)
-{
-  NVIC_DisableIRQ(rhport ? USB1_IRQn : USB0_IRQn);
-}
-
-uint32_t hcd_ehci_register_addr(uint8_t rhport)
-{
-  return (uint32_t) (rhport ? &LPC_USB1->USBCMD_H : &LPC_USB0->USBCMD_H );
-}
-
-#endif

+ 136 - 0
src/portable/nxp/transdimension/common_transdimension.h

@@ -0,0 +1,136 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#ifndef COMMON_TRANSDIMENSION_H_
+#define COMMON_TRANSDIMENSION_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// USBCMD
+enum {
+  USBCMD_RUN_STOP         = TU_BIT(0),
+  USBCMD_RESET            = TU_BIT(1),
+  USBCMD_SETUP_TRIPWIRE   = TU_BIT(13),
+  USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14)  ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD
+// Interrupt Threshold bit 23:16
+};
+
+// PORTSC1
+#define PORTSC1_PORT_SPEED_POS    26
+
+enum {
+  PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
+  PORTSC1_FORCE_PORT_RESUME      = TU_BIT(6),
+  PORTSC1_SUSPEND                = TU_BIT(7),
+  PORTSC1_FORCE_FULL_SPEED       = TU_BIT(24),
+  PORTSC1_PORT_SPEED             = TU_BIT(26) | TU_BIT(27)
+};
+
+// OTGSC
+enum {
+  OTGSC_VBUS_DISCHARGE          = TU_BIT(0),
+  OTGSC_VBUS_CHARGE             = TU_BIT(1),
+//  OTGSC_HWASSIST_AUTORESET    = TU_BIT(2),
+  OTGSC_OTG_TERMINATION         = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
+  OTGSC_DATA_PULSING            = TU_BIT(4),
+  OTGSC_ID_PULLUP               = TU_BIT(5),
+//  OTGSC_HWASSIT_DATA_PULSE    = TU_BIT(6),
+//  OTGSC_HWASSIT_BDIS_ACONN    = TU_BIT(7),
+  OTGSC_ID                      = TU_BIT(8), ///< 0 = A device, 1 = B Device
+  OTGSC_A_VBUS_VALID            = TU_BIT(9),
+  OTGSC_A_SESSION_VALID         = TU_BIT(10),
+  OTGSC_B_SESSION_VALID         = TU_BIT(11),
+  OTGSC_B_SESSION_END           = TU_BIT(12),
+  OTGSC_1MS_TOGGLE              = TU_BIT(13),
+  OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
+};
+
+// USBMode
+enum {
+  USBMODE_CM_DEVICE = 2,
+  USBMODE_CM_HOST   = 3,
+
+  USBMODE_SLOM = TU_BIT(3),
+  USBMODE_SDIS = TU_BIT(4),
+
+  USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode
+};
+
+// Device Registers
+typedef struct
+{
+  //------------- ID + HW Parameter Registers-------------//
+  __I  uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
+
+  //------------- Capability Registers-------------//
+  __I  uint8_t  CAPLENGTH;       ///< Capability Registers Length
+  __I  uint8_t  TU_RESERVED[1];
+  __I  uint16_t HCIVERSION;      ///< Host Controller Interface Version
+
+  __I  uint32_t HCSPARAMS;       ///< Host Controller Structural Parameters
+  __I  uint32_t HCCPARAMS;       ///< Host Controller Capability Parameters
+  __I  uint32_t TU_RESERVED[5];
+
+  __I  uint16_t DCIVERSION;      ///< Device Controller Interface Version
+  __I  uint8_t  TU_RESERVED[2];
+
+  __I  uint32_t DCCPARAMS;       ///< Device Controller Capability Parameters
+  __I  uint32_t TU_RESERVED[6];
+
+  //------------- Operational Registers -------------//
+  __IO uint32_t USBCMD;          ///< USB Command Register
+  __IO uint32_t USBSTS;          ///< USB Status Register
+  __IO uint32_t USBINTR;         ///< Interrupt Enable Register
+  __IO uint32_t FRINDEX;         ///< USB Frame Index
+  __I  uint32_t TU_RESERVED;
+  __IO uint32_t DEVICEADDR;      ///< Device Address
+  __IO uint32_t ENDPTLISTADDR;   ///< Endpoint List Address
+  __I  uint32_t TU_RESERVED;
+  __IO uint32_t BURSTSIZE;       ///< Programmable Burst Size
+  __IO uint32_t TXFILLTUNING;    ///< TX FIFO Fill Tuning
+       uint32_t TU_RESERVED[4];
+  __IO uint32_t ENDPTNAK;        ///< Endpoint NAK
+  __IO uint32_t ENDPTNAKEN;      ///< Endpoint NAK Enable
+  __I  uint32_t TU_RESERVED;
+  __IO uint32_t PORTSC1;         ///< Port Status & Control
+  __I  uint32_t TU_RESERVED[7];
+  __IO uint32_t OTGSC;           ///< On-The-Go Status & control
+  __IO uint32_t USBMODE;         ///< USB Device Mode
+  __IO uint32_t ENDPTSETUPSTAT;  ///< Endpoint Setup Status
+  __IO uint32_t ENDPTPRIME;      ///< Endpoint Prime
+  __IO uint32_t ENDPTFLUSH;      ///< Endpoint Flush
+  __I  uint32_t ENDPTSTAT;       ///< Endpoint Status
+  __IO uint32_t ENDPTCOMPLETE;   ///< Endpoint Complete
+  __IO uint32_t ENDPTCTRL[8];    ///< Endpoint Control 0 - 7
+} dcd_registers_t;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* COMMON_TRANSDIMENSION_H_ */

+ 7 - 106
src/portable/nxp/transdimension/dcd_transdimension.c

@@ -26,16 +26,12 @@
 
 #include "tusb_option.h"
 
-#if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC18XX || \
-                                CFG_TUSB_MCU == OPT_MCU_LPC43XX || \
-                                CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
+#if TUSB_OPT_DEVICE_ENABLED && \
+    (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
 
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
-#include "common/tusb_common.h"
-#include "device/dcd.h"
-
 #if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
   #include "fsl_device_registers.h"
 #else
@@ -43,6 +39,10 @@
   #include "chip.h"
 #endif
 
+#include "common/tusb_common.h"
+#include "device/dcd.h"
+#include "common_transdimension.h"
+
 #if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1
   #define CleanInvalidateDCache_by_Addr   SCB_CleanInvalidateDCache_by_Addr
 #else
@@ -61,15 +61,6 @@ enum {
   ENDPTCTRL_ENABLE         = TU_BIT(7)
 };
 
-// USBCMD
-enum {
-  USBCMD_RUN_STOP         = TU_BIT(0),
-  USBCMD_RESET            = TU_BIT(1),
-  USBCMD_SETUP_TRIPWIRE   = TU_BIT(13),
-  USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14)  ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD
-};
-// Interrupt Threshold bit 23:16
-
 // USBSTS, USBINTR
 enum {
   INTR_USB         = TU_BIT(0),
@@ -81,96 +72,6 @@ enum {
   INTR_NAK         = TU_BIT(16)
 };
 
-// PORTSC1
-#define PORTSC1_PORT_SPEED_POS    26
-
-enum {
-  PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
-  PORTSC1_FORCE_PORT_RESUME      = TU_BIT(6),
-  PORTSC1_SUSPEND                = TU_BIT(7),
-  PORTSC1_FORCE_FULL_SPEED       = TU_BIT(24),
-  PORTSC1_PORT_SPEED             = TU_BIT(26) | TU_BIT(27)
-};
-
-// OTGSC
-enum {
-  OTGSC_VBUS_DISCHARGE          = TU_BIT(0),
-  OTGSC_VBUS_CHARGE             = TU_BIT(1),
-//  OTGSC_HWASSIST_AUTORESET    = TU_BIT(2),
-  OTGSC_OTG_TERMINATION         = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
-  OTGSC_DATA_PULSING            = TU_BIT(4),
-  OTGSC_ID_PULLUP               = TU_BIT(5),
-//  OTGSC_HWASSIT_DATA_PULSE    = TU_BIT(6),
-//  OTGSC_HWASSIT_BDIS_ACONN    = TU_BIT(7),
-  OTGSC_ID                      = TU_BIT(8), ///< 0 = A device, 1 = B Device
-  OTGSC_A_VBUS_VALID            = TU_BIT(9),
-  OTGSC_A_SESSION_VALID         = TU_BIT(10),
-  OTGSC_B_SESSION_VALID         = TU_BIT(11),
-  OTGSC_B_SESSION_END           = TU_BIT(12),
-  OTGSC_1MS_TOGGLE              = TU_BIT(13),
-  OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
-};
-
-// USBMode
-enum {
-  USBMODE_CM_DEVICE = 2,
-  USBMODE_CM_HOST   = 3,
-
-  USBMODE_SLOM = TU_BIT(3),
-  USBMODE_SDIS = TU_BIT(4),
-
-  USBMODE_VBUS_POWER_SELCT = TU_BIT(5), // Enable for LPC18XX/43XX in host most only
-};
-
-// Device Registers
-typedef struct
-{
-  //------------- ID + HW Parameter Registers-------------//
-  __I  uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
-
-  //------------- Capability Registers-------------//
-  __I  uint8_t  CAPLENGTH;       ///< Capability Registers Length
-  __I  uint8_t  TU_RESERVED[1];
-  __I  uint16_t HCIVERSION;      ///< Host Controller Interface Version
-
-  __I  uint32_t HCSPARAMS;       ///< Host Controller Structural Parameters
-  __I  uint32_t HCCPARAMS;       ///< Host Controller Capability Parameters
-  __I  uint32_t TU_RESERVED[5];
-
-  __I  uint16_t DCIVERSION;      ///< Device Controller Interface Version
-  __I  uint8_t  TU_RESERVED[2];
-
-  __I  uint32_t DCCPARAMS;       ///< Device Controller Capability Parameters
-  __I  uint32_t TU_RESERVED[6];
-
-  //------------- Operational Registers -------------//
-  __IO uint32_t USBCMD;          ///< USB Command Register
-  __IO uint32_t USBSTS;          ///< USB Status Register
-  __IO uint32_t USBINTR;         ///< Interrupt Enable Register
-  __IO uint32_t FRINDEX;         ///< USB Frame Index
-  __I  uint32_t TU_RESERVED;
-  __IO uint32_t DEVICEADDR;      ///< Device Address
-  __IO uint32_t ENDPTLISTADDR;   ///< Endpoint List Address
-  __I  uint32_t TU_RESERVED;
-  __IO uint32_t BURSTSIZE;       ///< Programmable Burst Size
-  __IO uint32_t TXFILLTUNING;    ///< TX FIFO Fill Tuning
-       uint32_t TU_RESERVED[4];
-  __IO uint32_t ENDPTNAK;        ///< Endpoint NAK
-  __IO uint32_t ENDPTNAKEN;      ///< Endpoint NAK Enable
-  __I  uint32_t TU_RESERVED;
-  __IO uint32_t PORTSC1;         ///< Port Status & Control
-  __I  uint32_t TU_RESERVED[7];
-  __IO uint32_t OTGSC;           ///< On-The-Go Status & control
-  __IO uint32_t USBMODE;         ///< USB Device Mode
-  __IO uint32_t ENDPTSETUPSTAT;  ///< Endpoint Setup Status
-  __IO uint32_t ENDPTPRIME;      ///< Endpoint Prime
-  __IO uint32_t ENDPTFLUSH;      ///< Endpoint Flush
-  __I  uint32_t ENDPTSTAT;       ///< Endpoint Status
-  __IO uint32_t ENDPTCOMPLETE;   ///< Endpoint Complete
-  __IO uint32_t ENDPTCTRL[8];    ///< Endpoint Control 0 - 7
-} dcd_registers_t;
-
-
 // Queue Transfer Descriptor
 typedef struct
 {
@@ -280,7 +181,7 @@ CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
 static dcd_data_t _dcd_data;
 
 //--------------------------------------------------------------------+
-// CONTROLLER API
+// Controller API
 //--------------------------------------------------------------------+
 
 /// follows LPC43xx User Manual 23.10.3

+ 127 - 0
src/portable/nxp/transdimension/hcd_transdimension.c

@@ -0,0 +1,127 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * This file is part of the TinyUSB stack.
+ */
+
+#include "tusb_option.h"
+
+// NXP Trans-Dimension USB IP implement EHCI for host functionality
+
+#if TUSB_OPT_HOST_ENABLED && \
+    (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
+
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
+  #include "fsl_device_registers.h"
+#else
+  // LPCOpen for 18xx & 43xx
+  #include "chip.h"
+#endif
+
+#include "common/tusb_common.h"
+#include "common_transdimension.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+// TODO can be merged with dcd_controller_t
+typedef struct
+{
+  uint32_t regs_base;     // registers base
+  const IRQn_Type irqnum; // IRQ number
+}hcd_controller_t;
+
+#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
+  static const hcd_controller_t _hcd_controller[] =
+  {
+    // RT1010 and RT1020 only has 1 USB controller
+    #if FSL_FEATURE_SOC_USBHS_COUNT == 1
+      { .regs_base = USB_BASE , .irqnum = USB_OTG1_IRQn }
+    #else
+      { .regs_base = USB1_BASE, .irqnum = USB_OTG1_IRQn },
+      { .regs_base = USB2_BASE, .irqnum = USB_OTG2_IRQn }
+    #endif
+  };
+
+#else
+  static const hcd_controller_t _hcd_controller[] =
+  {
+    { .regs_base = LPC_USB0_BASE, .irqnum = USB0_IRQn },
+    { .regs_base = LPC_USB1_BASE, .irqnum = USB1_IRQn }
+  };
+#endif
+
+// TODO better prototype later
+extern bool hcd_ehci_init (uint8_t rhport); // from ehci.c
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+
+bool hcd_init(uint8_t rhport)
+{
+  dcd_registers_t* dcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
+
+  // Reset controller
+  dcd_reg->USBCMD |= USBCMD_RESET;
+  while( dcd_reg->USBCMD & USBCMD_RESET ) {}
+
+  // Set mode to device, must be set immediately after reset
+#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
+  // LPC18XX/43XX need to set VBUS Power Select to HIGH
+  // RHPORT1 is fullspeed only (need external PHY for Highspeed)
+  dcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
+  if (rhport == 1) dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+#else
+  dcd_reg->USBMODE = USBMODE_CM_HOST;
+#endif
+
+  // FIXME force full speed, still have issue with Highspeed enumeration
+  dcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+
+  return hcd_ehci_init(rhport);
+}
+
+void hcd_int_enable(uint8_t rhport)
+{
+  NVIC_EnableIRQ(_hcd_controller[rhport].irqnum);
+}
+
+void hcd_int_disable(uint8_t rhport)
+{
+  NVIC_DisableIRQ(_hcd_controller[rhport].irqnum);
+}
+
+uint32_t hcd_ehci_register_addr(uint8_t rhport)
+{
+  dcd_registers_t* hcd_reg = (dcd_registers_t*) _hcd_controller[rhport].regs_base;
+
+  // EHCI USBCMD has same address within dcd_register_t
+  return (uint32_t) &hcd_reg->USBCMD;
+}
+
+#endif

+ 8 - 4
src/host/ohci/ohci.c → src/portable/ohci/ohci.c

@@ -26,14 +26,16 @@
 
 #include <common/tusb_common.h>
 
-#if TUSB_OPT_HOST_ENABLED && (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
+#if TUSB_OPT_HOST_ENABLED && \
+    (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX)
+
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+
 #include "osal/osal.h"
 
-#include "../hcd.h"
-#include "../usbh_hcd.h"
+#include "host/hcd.h"
+#include "host/usbh_hcd.h"
 #include "ohci.h"
 
 // TODO remove
@@ -141,8 +143,10 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr);
 // USBH-HCD API
 //--------------------------------------------------------------------+
 // Initialization according to 5.1.1.4
-bool hcd_init(void)
+bool hcd_init(uint8_t rhport)
 {
+  (void) rhport;
+
   //------------- Data Structure init -------------//
   tu_memclr(&ohci_data, sizeof(ohci_data_t));
   for(uint8_t i=0; i<32; i++)

+ 0 - 2
src/host/ohci/ohci.h → src/portable/ohci/ohci.h

@@ -37,8 +37,6 @@
  extern "C" {
 #endif
 
-#include "common/tusb_common.h"
-
 //--------------------------------------------------------------------+
 // OHCI CONFIGURATION & CONSTANTS
 //--------------------------------------------------------------------+