tinyusb/src/host/ehci/ehci.c
static void async_advance_isr(ehci_qhd_t * const async_head)
{
  // TODO do we need to close addr0
  if (async_head->is_removing) // closing control pipe of addr0
  {
    async_head->is_removing        = 0;
    async_head->p_qtd_list_head    = async_head->p_qtd_list_tail = NULL;
    async_head->qtd_overlay.halted = 1;

    _usbh_devices[0].state          = TUSB_DEVICE_STATE_UNPLUG;
  }

  for(uint8_t relative_dev_addr=0; relative_dev_addr < CFG_TUSB_HOST_DEVICE_MAX; relative_dev_addr++)
  {
    // check if control endpoint is removing
    ehci_qhd_t *p_control_qhd = &ehci_data.device[relative_dev_addr].control.qhd;
    if ( p_control_qhd->is_removing )
    {
      p_control_qhd->is_removing = 0;
      p_control_qhd->used        = 0;

      // Host Controller has cleaned up its cached data for this device, set state to unplug
      _usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;

      for (uint8_t i=0; i<HCD_MAX_ENDPOINT; i++) // free all qhd
      {
        ehci_data.device[relative_dev_addr].qhd[i].used        = 0;
        ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
      }
      for (uint8_t i=0; i<HCD_MAX_XFER; i++) // free all qtd
      {
        ehci_data.device[relative_dev_addr].qtd[i].used = 0;
      }
      // TODO free all itd & sitd
    }
  } // end for device[] loop
}
// async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
// In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing

async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
In tinyusb, queue head is only removed when device is unplugged. So only control queue head is checked if removing
async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head . In tinyusb queue head is only removed when device is unplugged . So only control queue head is checked if removing
static void async_advance_isr(ehci_qhd_t * const async_head)
{
  if (async_head->is_removing) 
  {
    async_head->is_removing        = 0;
    async_head->p_qtd_list_head    = async_head->p_qtd_list_tail = NULL;
    async_head->qtd_overlay.halted = 1;
    _usbh_devices[0].state          = TUSB_DEVICE_STATE_UNPLUG;
  }
  for(uint8_t relative_dev_addr=0; relative_dev_addr < CFG_TUSB_HOST_DEVICE_MAX; relative_dev_addr++)
  {
    ehci_qhd_t *p_control_qhd = &ehci_data.device[relative_dev_addr].control.qhd;
    if ( p_control_qhd->is_removing )
    {
      p_control_qhd->is_removing = 0;
      p_control_qhd->used        = 0;
      _usbh_devices[relative_dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
      for (uint8_t i=0; i<HCD_MAX_ENDPOINT; i++) 
      {
        ehci_data.device[relative_dev_addr].qhd[i].used        = 0;
        ehci_data.device[relative_dev_addr].qhd[i].is_removing = 0;
      }
      for (uint8_t i=0; i<HCD_MAX_XFER; i++) 
      {
        ehci_data.device[relative_dev_addr].qtd[i].used = 0;
      }
    }
  } 
}
static void async_advance_isr ( ehci_qhd_t * const async_head ) { if ( async_head -> is_removing ) { async_head -> is_removing = 0 ; async_head -> p_qtd_list_head = async_head -> p_qtd_list_tail = NULL ; async_head -> qtd_overlay . halted = 1 ; _usbh_devices [ 0 ] . state = TUSB_DEVICE_STATE_UNPLUG ; } for ( uint8_t relative_dev_addr = 0 ; relative_dev_addr < CFG_TUSB_HOST_DEVICE_MAX ; relative_dev_addr ++ ) { ehci_qhd_t * p_control_qhd = & ehci_data . device [ relative_dev_addr ] . control . qhd ; if ( p_control_qhd -> is_removing ) { p_control_qhd -> is_removing = 0 ; p_control_qhd -> used = 0 ; _usbh_devices [ relative_dev_addr + 1 ] . state = TUSB_DEVICE_STATE_UNPLUG ; for ( uint8_t i = 0 ; i < HCD_MAX_ENDPOINT ; i ++ ) { ehci_data . device [ relative_dev_addr ] . qhd [ i ] . used = 0 ; ehci_data . device [ relative_dev_addr ] . qhd [ i ] . is_removing = 0 ; } for ( uint8_t i = 0 ; i < HCD_MAX_XFER ; i ++ ) { ehci_data . device [ relative_dev_addr ] . qtd [ i ] . used = 0 ; } } } }
async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head.
async_advance is handshake between sw stack & ehci controller where ehci free all memory from an deleted queue head .
// TODO do we need to close addr0
 // closing control pipe of addr0
 // check if control endpoint is removing
 // Host Controller has cleaned up its cached data for this device, set state to unplug
 // free all qhd
 // free all qtd
 // TODO free all itd & sitd
 // end for device[] loop
