Просмотр исходного кода

enhance some tests
add test for usbh_isr error invoke
fix bug if device unplugged before is set to new address
- clean up & close control addr0 in usbh_device_unplugged_isr

hathach 13 лет назад
Родитель
Сommit
44e09cc397

+ 2 - 2
tests/test/host/ehci/test_ehci_usbh_hcd_integration.c

@@ -72,13 +72,13 @@ void setUp(void)
 
 
   hcd_init();
   hcd_init();
 
 
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_port = hub_port;
     usbh_device_info_pool[i].hub_port = hub_port;
     usbh_device_info_pool[i].speed    = TUSB_SPEED_HIGH;
     usbh_device_info_pool[i].speed    = TUSB_SPEED_HIGH;
-    usbh_device_info_pool[i].state   = TUSB_DEVICE_STATE_CONFIGURED;
+    usbh_device_info_pool[i].state    = i ? TUSB_DEVICE_STATE_CONFIGURED : TUSB_DEVICE_STATE_UNPLUG;
   }
   }
 
 
   regs = get_operational_register(hostid);
   regs = get_operational_register(hostid);

+ 1 - 1
tests/test/host/ehci/test_pipe_bulk_open.c

@@ -68,7 +68,7 @@ void setUp(void)
   dev_addr = 1;
   dev_addr = 1;
 
 
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;

+ 2 - 4
tests/test/host/ehci/test_pipe_bulk_xfer.c

@@ -97,7 +97,7 @@ void setUp(void)
   dev_addr = 1;
   dev_addr = 1;
 
 
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;
@@ -210,12 +210,10 @@ void test_bulk_xfer_complete_isr(void)
   ehci_qtd_t* p_head = p_qhd_bulk->p_qtd_list_head;
   ehci_qtd_t* p_head = p_qhd_bulk->p_qtd_list_head;
   ehci_qtd_t* p_tail = p_qhd_bulk->p_qtd_list_tail;
   ehci_qtd_t* p_tail = p_qhd_bulk->p_qtd_list_tail;
 
 
-  ehci_controller_run(hostid);
-
   usbh_isr_Expect(pipe_hdl_bulk, TUSB_CLASS_MSC, BUS_EVENT_XFER_COMPLETE);
   usbh_isr_Expect(pipe_hdl_bulk, TUSB_CLASS_MSC, BUS_EVENT_XFER_COMPLETE);
 
 
   //------------- Code Under Test -------------//
   //------------- Code Under Test -------------//
-  hcd_isr(hostid);
+  ehci_controller_run(hostid);
 
 
   TEST_ASSERT_TRUE(p_qhd_bulk->qtd_overlay.next.terminate);
   TEST_ASSERT_TRUE(p_qhd_bulk->qtd_overlay.next.terminate);
   TEST_ASSERT_FALSE(p_head->used);
   TEST_ASSERT_FALSE(p_head->used);

+ 1 - 1
tests/test/host/ehci/test_pipe_control_open.c

@@ -70,7 +70,7 @@ void setUp(void)
   dev_addr = 1;
   dev_addr = 1;
 
 
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;

+ 13 - 12
tests/test/host/ehci/test_pipe_control_xfer.c

@@ -79,7 +79,7 @@ void setUp(void)
   dev_addr = 1;
   dev_addr = 1;
 
 
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;
@@ -89,6 +89,8 @@ void setUp(void)
 
 
   async_head =  get_async_head( hostid );
   async_head =  get_async_head( hostid );
 
 
+  hcd_pipe_control_open(dev_addr, control_max_packet_size);
+
   p_control_qhd = &ehci_data.device[dev_addr-1].control.qhd;
   p_control_qhd = &ehci_data.device[dev_addr-1].control.qhd;
 
 
   p_setup  = &ehci_data.device[dev_addr-1].control.qtd[0];
   p_setup  = &ehci_data.device[dev_addr-1].control.qtd[0];
@@ -168,8 +170,6 @@ void test_control_addr0_xfer_get_check_qhd_qtd_mapping(void)
 //--------------------------------------------------------------------+
 //--------------------------------------------------------------------+
 void test_control_xfer_get(void)
 void test_control_xfer_get(void)
 {
 {
-  hcd_pipe_control_open(dev_addr, control_max_packet_size);
-
   //------------- Code Under TEST -------------//
   //------------- Code Under TEST -------------//
   hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data);
   hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data);
 
 
@@ -205,8 +205,6 @@ void test_control_xfer_get(void)
 
 
 void test_control_xfer_set(void)
 void test_control_xfer_set(void)
 {
 {
-  hcd_pipe_control_open(dev_addr, control_max_packet_size);
-
   //------------- Code Under TEST -------------//
   //------------- Code Under TEST -------------//
   hcd_pipe_control_xfer(dev_addr, &request_set_dev_addr, xfer_data);
   hcd_pipe_control_xfer(dev_addr, &request_set_dev_addr, xfer_data);
 
 
@@ -228,17 +226,11 @@ void test_control_xfer_set(void)
 
 
 void test_control_xfer_complete_isr(void)
 void test_control_xfer_complete_isr(void)
 {
 {
-  hcd_pipe_control_open(dev_addr, control_max_packet_size);
-
   hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data);
   hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data);
-  ehci_controller_run(hostid);
-
-  TEST_ASSERT_EQUAL_HEX(async_head, get_operational_register(hostid)->async_list_base);
-  TEST_ASSERT_EQUAL_HEX((uint32_t) p_control_qhd, align32(async_head->next.address));
   usbh_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, BUS_EVENT_XFER_COMPLETE);
   usbh_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, BUS_EVENT_XFER_COMPLETE);
 
 
   //------------- Code Under TEST -------------//
   //------------- Code Under TEST -------------//
-  hcd_isr(hostid);
+  ehci_controller_run(hostid);
 
 
   TEST_ASSERT_NULL(p_control_qhd->p_qtd_list_head);
   TEST_ASSERT_NULL(p_control_qhd->p_qtd_list_head);
   TEST_ASSERT_NULL(p_control_qhd->p_qtd_list_tail);
   TEST_ASSERT_NULL(p_control_qhd->p_qtd_list_tail);
@@ -248,3 +240,12 @@ void test_control_xfer_complete_isr(void)
   TEST_ASSERT_FALSE(p_status->used);
   TEST_ASSERT_FALSE(p_status->used);
 
 
 }
 }
+
+void test_control_xfer_error_isr(void)
+{
+  hcd_pipe_control_xfer(dev_addr, &request_get_dev_desc, xfer_data);
+  usbh_isr_Expect(((pipe_handle_t){.dev_addr = dev_addr}), 0, BUS_EVENT_XFER_ERROR);
+
+  //------------- Code Under TEST -------------//
+  ehci_controller_run_error(hostid);
+}

+ 1 - 1
tests/test/host/ehci/test_pipe_interrupt_open.c

@@ -68,7 +68,7 @@ void setUp(void)
   dev_addr = 1;
   dev_addr = 1;
 
 
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;

+ 1 - 1
tests/test/host/ehci/test_pipe_isochronous_open.c

@@ -67,7 +67,7 @@ void setUp(void)
   dev_addr = 1;
   dev_addr = 1;
 
 
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
   hostid = RANDOM(CONTROLLER_HOST_NUMBER) + TEST_CONTROLLER_HOST_START_INDEX;
-  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX; i++)
+  for (uint8_t i=0; i<TUSB_CFG_HOST_DEVICE_MAX+1; i++)
   {
   {
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].core_id  = hostid;
     usbh_device_info_pool[i].hub_addr = hub_addr;
     usbh_device_info_pool[i].hub_addr = hub_addr;

+ 7 - 0
tests/test/host/test_enum_task.c

@@ -171,6 +171,9 @@ void test_addr0_failed_dev_desc(void)
   tusbh_device_mount_failed_cb_Expect(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL);
   tusbh_device_mount_failed_cb_Expect(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL);
 
 
   usbh_enumeration_task();
   usbh_enumeration_task();
+
+  TEST_ASSERT_EQUAL(TUSB_DEVICE_STATE_ADDRESSED, usbh_device_info_pool[0].state);
+
 }
 }
 
 
 void test_addr0_failed_set_address(void)
 void test_addr0_failed_set_address(void)
@@ -180,6 +183,7 @@ void test_addr0_failed_set_address(void)
 
 
   usbh_enumeration_task();
   usbh_enumeration_task();
 
 
+  TEST_ASSERT_EQUAL(TUSB_DEVICE_STATE_ADDRESSED, usbh_device_info_pool[0].state);
   TEST_ASSERT_EQUAL_MEMORY(&desc_device, enum_data_buffer, 8);
   TEST_ASSERT_EQUAL_MEMORY(&desc_device, enum_data_buffer, 8);
 }
 }
 
 
@@ -188,12 +192,15 @@ void test_enum_failed_get_full_dev_desc(void)
   osal_semaphore_wait_StubWithCallback(semaphore_wait_timeout_stub(2));
   osal_semaphore_wait_StubWithCallback(semaphore_wait_timeout_stub(2));
 
 
   hcd_pipe_control_close_ExpectAndReturn(0, TUSB_ERROR_NONE);
   hcd_pipe_control_close_ExpectAndReturn(0, TUSB_ERROR_NONE);
+
   osal_semaphore_reset_Expect( usbh_device_info_pool[0].sem_hdl );
   osal_semaphore_reset_Expect( usbh_device_info_pool[0].sem_hdl );
   hcd_pipe_control_open_ExpectAndReturn(1, desc_device.bMaxPacketSize0, TUSB_ERROR_NONE);
   hcd_pipe_control_open_ExpectAndReturn(1, desc_device.bMaxPacketSize0, TUSB_ERROR_NONE);
   tusbh_device_mount_failed_cb_Expect(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL);
   tusbh_device_mount_failed_cb_Expect(TUSB_ERROR_USBH_MOUNT_DEVICE_NOT_RESPOND, NULL);
 
 
   usbh_enumeration_task();
   usbh_enumeration_task();
 
 
+  TEST_ASSERT_EQUAL(TUSB_DEVICE_STATE_UNPLUG, usbh_device_info_pool[0].state);
+
   TEST_ASSERT_EQUAL(TUSB_DEVICE_STATE_ADDRESSED, usbh_device_info_pool[1].state);
   TEST_ASSERT_EQUAL(TUSB_DEVICE_STATE_ADDRESSED, usbh_device_info_pool[1].state);
   TEST_ASSERT_EQUAL(TUSB_SPEED_FULL, usbh_device_info_pool[1].speed);
   TEST_ASSERT_EQUAL(TUSB_SPEED_FULL, usbh_device_info_pool[1].speed);
   TEST_ASSERT_EQUAL(enum_connect.core_id, usbh_device_info_pool[1].core_id);
   TEST_ASSERT_EQUAL(enum_connect.core_id, usbh_device_info_pool[1].core_id);

+ 28 - 0
tests/test/support/ehci_controller.c

@@ -77,6 +77,34 @@ void ehci_controller_run(uint8_t hostid)
   //------------- Period List -------------//
   //------------- Period List -------------//
 
 
   regs->usb_sts = EHCI_INT_MASK_NXP_ASYNC;
   regs->usb_sts = EHCI_INT_MASK_NXP_ASYNC;
+  hcd_isr(hostid);
+}
+
+void ehci_controller_run_error(uint8_t hostid)
+{
+  //------------- Async List -------------//
+  ehci_registers_t* const regs = get_operational_register(hostid);
+
+  ehci_qhd_t *p_qhd = (ehci_qhd_t*) regs->async_list_base;
+  do
+  {
+    if ( !p_qhd->qtd_overlay.halted )
+    {
+      if(!p_qhd->qtd_overlay.next.terminate)
+      {
+        ehci_qtd_t* p_qtd = (ehci_qtd_t*) align32(p_qhd->qtd_overlay.next.address);
+        p_qtd->active = 0;
+        p_qtd->babble_err = p_qtd->buffer_err = p_qtd->xact_err = 1;
+        p_qhd->qtd_overlay = *p_qtd;
+      }
+    }
+    p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address);
+  }while(p_qhd != get_async_head(hostid)); // stop if loop around
+  //------------- Period List -------------//
+
+  regs->usb_sts = EHCI_INT_MASK_ERROR;
+
+  hcd_isr(hostid);
 }
 }
 
 
 void ehci_controller_device_plug(uint8_t hostid, tusb_speed_t speed)
 void ehci_controller_device_plug(uint8_t hostid, tusb_speed_t speed)

+ 2 - 2
tinyusb/core/tusb_types.h

@@ -154,7 +154,7 @@ enum {
 #define TUSB_DESC_CONFIG_POWER_MA(x)  ((x)/2)
 #define TUSB_DESC_CONFIG_POWER_MA(x)  ((x)/2)
 
 
 /// Device State
 /// Device State
-enum tusb_device_state_{
+typedef enum {
   TUSB_DEVICE_STATE_UNPLUG = 0  ,
   TUSB_DEVICE_STATE_UNPLUG = 0  ,
   TUSB_DEVICE_STATE_ADDRESSED   ,
   TUSB_DEVICE_STATE_ADDRESSED   ,
 
 
@@ -162,7 +162,7 @@ enum tusb_device_state_{
 
 
   TUSB_DEVICE_STATE_REMOVING    ,
   TUSB_DEVICE_STATE_REMOVING    ,
   TUSB_DEVICE_STATE_SAFE_REMOVE ,
   TUSB_DEVICE_STATE_SAFE_REMOVE ,
-};
+}tusb_device_state_t;
 
 
 typedef enum {
 typedef enum {
   BUS_EVENT_XFER_COMPLETE,
   BUS_EVENT_XFER_COMPLETE,

+ 31 - 4
tinyusb/host/ehci/ehci.c

@@ -135,7 +135,7 @@ void hcd_port_reset(uint8_t hostid)
 
 
 #ifndef _TEST_
 #ifndef _TEST_
   // NXP specific, port reset will automatically be 0 when reset sequence complete
   // NXP specific, port reset will automatically be 0 when reset sequence complete
-  while( regs->portsc_bit.port_reset || !regs->portsc_bit.port_enable){}
+  while( regs->portsc_bit.port_reset || !regs->portsc_bit.port_enable){} // FIXME trapped here once
 #endif
 #endif
 }
 }
 
 
@@ -205,7 +205,7 @@ void port_connect_status_change_isr(uint8_t hostid)
 
 
 }
 }
 
 
-void async_list_process_isr(ehci_qhd_t * const async_head, ehci_registers_t * const regs)
+void async_list_process_isr(ehci_qhd_t * const async_head)
 {
 {
   ehci_qhd_t *p_qhd = async_head;
   ehci_qhd_t *p_qhd = async_head;
   do
   do
@@ -235,6 +235,33 @@ void async_list_process_isr(ehci_qhd_t * const async_head, ehci_registers_t * co
   }while(p_qhd != async_head); // async list traversal, stop if loop around
   }while(p_qhd != async_head); // async list traversal, stop if loop around
 }
 }
 
 
+void xfer_error_isr(uint8_t hostid)
+{
+  //------------- async list -------------//
+  ehci_qhd_t * const async_head = get_async_head(hostid);
+  ehci_qhd_t *p_qhd = async_head;
+  do
+  {
+    // current qhd has error in transaction
+    if (p_qhd->qtd_overlay.buffer_err || p_qhd->qtd_overlay.babble_err || p_qhd->qtd_overlay.xact_err ||
+        //p_qhd->qtd_overlay.non_hs_period_missed_uframe || p_qhd->qtd_overlay.pingstate_err TODO split transaction error
+        (p_qhd->device_address != 0 && p_qhd->qtd_overlay.halted) ) // addr0 cannot be protocol STALL
+    {
+      pipe_handle_t pipe_hdl = { .dev_addr = p_qhd->device_address };
+      if (p_qhd->endpoint_number) // if not Control, can only be Bulk
+      {
+        pipe_hdl.xfer_type = TUSB_XFER_BULK;
+        pipe_hdl.index = qhd_get_index(p_qhd);
+      }
+      usbh_isr( pipe_hdl, p_qhd->class_code, BUS_EVENT_XFER_ERROR); // call USBH callback
+    }
+
+    p_qhd = (ehci_qhd_t*) align32(p_qhd->next.address);
+  }while(p_qhd != async_head); // async list traversal, stop if loop around
+
+  //------------- TODO period list -------------//
+}
+
 //------------- Host Controller Driver's Interrupt Handler -------------//
 //------------- Host Controller Driver's Interrupt Handler -------------//
 void hcd_isr(uint8_t hostid)
 void hcd_isr(uint8_t hostid)
 {
 {
@@ -249,14 +276,14 @@ void hcd_isr(uint8_t hostid)
   if (int_status & EHCI_INT_MASK_ERROR)
   if (int_status & EHCI_INT_MASK_ERROR)
   {
   {
     // TODO handle Queue Head halted
     // TODO handle Queue Head halted
-    // TODO invoke some error callback if not async head
     hal_debugger_breakpoint();
     hal_debugger_breakpoint();
+    xfer_error_isr(hostid);
   }
   }
 
 
   //------------- some QTD/SITD/ITD with IOC set is completed -------------//
   //------------- some QTD/SITD/ITD with IOC set is completed -------------//
   if (int_status & EHCI_INT_MASK_NXP_ASYNC)
   if (int_status & EHCI_INT_MASK_NXP_ASYNC)
   {
   {
-    async_list_process_isr(get_async_head(hostid), regs);
+    async_list_process_isr(get_async_head(hostid));
   }
   }
 
 
   if (int_status & EHCI_INT_MASK_NXP_PERIODIC)
   if (int_status & EHCI_INT_MASK_NXP_PERIODIC)

+ 13 - 6
tinyusb/host/usbh.c

@@ -203,25 +203,29 @@ void usbh_device_plugged_isr(uint8_t hostid, tusb_speed_t speed)
 void usbh_device_unplugged_isr(uint8_t hostid)
 void usbh_device_unplugged_isr(uint8_t hostid)
 {
 {
   //------------- find the device address that is unplugged -------------//
   //------------- find the device address that is unplugged -------------//
-  uint8_t dev_addr=1;
+  uint8_t dev_addr = 0;
   while ( dev_addr <= TUSB_CFG_HOST_DEVICE_MAX &&
   while ( dev_addr <= TUSB_CFG_HOST_DEVICE_MAX &&
           !(usbh_device_info_pool[dev_addr].core_id  == hostid &&
           !(usbh_device_info_pool[dev_addr].core_id  == hostid &&
             usbh_device_info_pool[dev_addr].hub_addr == 0 &&
             usbh_device_info_pool[dev_addr].hub_addr == 0 &&
             usbh_device_info_pool[dev_addr].hub_port == 0 &&
             usbh_device_info_pool[dev_addr].hub_port == 0 &&
-            usbh_device_info_pool[dev_addr].state   != TUSB_DEVICE_STATE_UNPLUG
+            usbh_device_info_pool[dev_addr].state    != TUSB_DEVICE_STATE_UNPLUG
           )
           )
   )
   )
   {
   {
     dev_addr++;
     dev_addr++;
   }
   }
 
 
+  // TODO close addr0 pipe (when get 8-byte desc, set addr failed)
   ASSERT(dev_addr <= TUSB_CFG_HOST_DEVICE_MAX, (void) 0 );
   ASSERT(dev_addr <= TUSB_CFG_HOST_DEVICE_MAX, (void) 0 );
 
 
-  // if device unplugged is not a hub TODO handle hub unplugged
-  for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++)
+  if (dev_addr > 0) // device can still be unplugged when not set new address
   {
   {
-    if (usbh_class_drivers[class_code].close)
-      usbh_class_drivers[class_code].close(dev_addr);
+    // if device unplugged is not a hub TODO handle hub unplugged
+    for (uint8_t class_code = 1; class_code < TUSB_CLASS_MAX_CONSEC_NUMBER; class_code++)
+    {
+      if (usbh_class_drivers[class_code].close)
+        usbh_class_drivers[class_code].close(dev_addr);
+    }
   }
   }
 
 
   usbh_pipe_control_close(dev_addr);
   usbh_pipe_control_close(dev_addr);
@@ -256,6 +260,7 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
   usbh_device_info_pool[0].speed    = enum_entry.speed;
   usbh_device_info_pool[0].speed    = enum_entry.speed;
 
 
   TASK_ASSERT_STATUS( usbh_pipe_control_open(0, 8) );
   TASK_ASSERT_STATUS( usbh_pipe_control_open(0, 8) );
+  usbh_device_info_pool[0].state = TUSB_DEVICE_STATE_ADDRESSED;
 
 
   //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------//
   //------------- Get first 8 bytes of device descriptor to get Control Endpoint Size -------------//
   OSAL_SUBTASK_INVOKED_AND_WAIT(
   OSAL_SUBTASK_INVOKED_AND_WAIT(
@@ -295,7 +300,9 @@ OSAL_TASK_DECLARE(usbh_enumeration_task)
   usbh_device_info_pool[new_addr].hub_port = usbh_device_info_pool[0].hub_port;
   usbh_device_info_pool[new_addr].hub_port = usbh_device_info_pool[0].hub_port;
   usbh_device_info_pool[new_addr].speed    = usbh_device_info_pool[0].speed;
   usbh_device_info_pool[new_addr].speed    = usbh_device_info_pool[0].speed;
   usbh_device_info_pool[new_addr].state   = TUSB_DEVICE_STATE_ADDRESSED;
   usbh_device_info_pool[new_addr].state   = TUSB_DEVICE_STATE_ADDRESSED;
+
   usbh_pipe_control_close(0);
   usbh_pipe_control_close(0);
+  usbh_device_info_pool[0].state = TUSB_DEVICE_STATE_UNPLUG;
 
 
 //  hcd_port_reset( usbh_device_info_pool[new_addr].core_id ); TODO verified
 //  hcd_port_reset( usbh_device_info_pool[new_addr].core_id ); TODO verified