mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-22 06:40:58 +00:00
implement hcd_pipe_close, able to plug & unplug device from ohci lpc17xx
This commit is contained in:
parent
eaacbd4a36
commit
b828aabbe4
@ -137,7 +137,18 @@ enum {
|
||||
//--------------------------------------------------------------------+
|
||||
STATIC_VAR ohci_data_t ohci_data TUSB_CFG_ATTR_USBRAM;
|
||||
|
||||
static ohci_ed_t * const p_ed_head[] =
|
||||
{
|
||||
[TUSB_XFER_CONTROL] = &ohci_data.control[0].ed,
|
||||
[TUSB_XFER_BULK ] = &ohci_data.bulk_head_ed,
|
||||
[TUSB_XFER_INTERRUPT] = NULL,
|
||||
[TUSB_XFER_ISOCHRONOUS] = NULL
|
||||
};
|
||||
|
||||
static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed);
|
||||
static void ed_list_remove(ohci_ed_t * p_head, ohci_ed_t * p_ed);
|
||||
|
||||
static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t const * p_ed);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH-HCD API
|
||||
@ -264,7 +275,7 @@ tusb_error_t hcd_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
|
||||
|
||||
if ( dev_addr != 0 )
|
||||
{ // insert to control head
|
||||
ed_list_insert( &ohci_data.control[0].ed, p_ed);
|
||||
ed_list_insert( p_ed_head[TUSB_XFER_CONTROL], p_ed);
|
||||
}else
|
||||
{
|
||||
p_ed->skip = 0; // addr0 is used as static control head --> only need to clear skip bit
|
||||
@ -325,7 +336,10 @@ tusb_error_t hcd_pipe_control_close(uint8_t dev_addr)
|
||||
p_ed->skip = 1;
|
||||
}else
|
||||
{
|
||||
return TUSB_ERROR_FAILED;
|
||||
ed_list_remove( p_ed_head[ ed_get_xfer_type(p_ed)], p_ed );
|
||||
|
||||
// TODO refractor to be USBH
|
||||
usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_UNPLUG;
|
||||
}
|
||||
|
||||
return TUSB_ERROR_NONE;
|
||||
@ -360,12 +374,41 @@ static inline ohci_ed_t * ed_find_free(uint8_t dev_addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ohci_ed_t * ed_list_find_previous(ohci_ed_t const * p_head, ohci_ed_t const * p_ed)
|
||||
{
|
||||
uint32_t max_loop = OHCI_MAX_QHD;
|
||||
|
||||
ohci_ed_t const * p_prev = p_head;
|
||||
|
||||
ASSERT_PTR(p_prev, NULL);
|
||||
|
||||
while ( align16(p_prev->next_ed) != 0 && /* not reach null */
|
||||
align16(p_prev->next_ed) != (uint32_t) p_ed && /* not found yet */
|
||||
max_loop > 0)
|
||||
{
|
||||
p_prev = (ohci_ed_t const *) align16(p_prev->next_ed);
|
||||
max_loop--;
|
||||
}
|
||||
|
||||
return ( align16(p_prev->next_ed) == (uint32_t) p_ed ) ? (ohci_ed_t*) p_prev : NULL;
|
||||
}
|
||||
|
||||
static void ed_list_insert(ohci_ed_t * p_pre, ohci_ed_t * p_ed)
|
||||
{
|
||||
p_ed->next_ed |= p_pre->next_ed; // to reserve 4 lsb bits
|
||||
p_pre->next_ed = (p_pre->next_ed & 0x0FUL) | ((uint32_t) p_ed);
|
||||
}
|
||||
|
||||
static void ed_list_remove(ohci_ed_t * p_head, ohci_ed_t * p_ed)
|
||||
{
|
||||
ohci_ed_t * const p_prev = ed_list_find_previous(p_head, p_ed);
|
||||
|
||||
p_prev->next_ed = (p_prev->next_ed & 0x0fUL) | align16(p_ed->next_ed);
|
||||
// point the removed ED's next pointer to list head to make sure HC can always safely move away from this ED
|
||||
p_ed->next_ed = (uint32_t) p_head;
|
||||
p_ed->used = 0; // free ED
|
||||
}
|
||||
|
||||
pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const * p_endpoint_desc, uint8_t class_code)
|
||||
{
|
||||
pipe_handle_t const null_handle = { .dev_addr = 0, .xfer_type = 0, .index = 0 };
|
||||
@ -381,14 +424,7 @@ pipe_handle_t hcd_pipe_open(uint8_t dev_addr, tusb_descriptor_endpoint_t const *
|
||||
p_endpoint_desc->bmAttributes.xfer, p_endpoint_desc->bInterval );
|
||||
p_ed->td_tail.class_code = class_code;
|
||||
|
||||
switch(p_endpoint_desc->bmAttributes.xfer)
|
||||
{
|
||||
case TUSB_XFER_BULK:
|
||||
ed_list_insert( &ohci_data.bulk_head_ed, p_ed );
|
||||
break;
|
||||
|
||||
default: return null_handle; break;
|
||||
}
|
||||
ed_list_insert( p_ed_head[p_endpoint_desc->bmAttributes.xfer], p_ed );
|
||||
|
||||
return (pipe_handle_t)
|
||||
{
|
||||
@ -457,18 +493,21 @@ tusb_error_t hcd_pipe_xfer(pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t t
|
||||
|
||||
tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_pipe_handle(pipe_hdl) );
|
||||
|
||||
if (TUSB_XFER_BULK == xfer_type)
|
||||
{
|
||||
OHCI_REG->command_status_bit.bulk_list_filled = 1;
|
||||
}
|
||||
if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1;
|
||||
|
||||
return TUSB_ERROR_NONE;
|
||||
}
|
||||
|
||||
/// pipe_close should only be called as a part of unmount/safe-remove process
|
||||
// endpoints are tied to an address, which only reclaim after a long delay when enumerating
|
||||
// thus there is no need to make sure ED is not in HC's cahed as it will not for sure
|
||||
tusb_error_t hcd_pipe_close(pipe_handle_t pipe_hdl)
|
||||
{
|
||||
// TODO OHCI return TUSB_ERROR_NONE;
|
||||
ohci_ed_t * const p_ed = ed_from_pipe_handle(pipe_hdl);
|
||||
|
||||
ed_list_remove( p_ed_head[ ed_get_xfer_type(p_ed)], p_ed );
|
||||
|
||||
return TUSB_ERROR_FAILED;
|
||||
}
|
||||
|
||||
bool hcd_pipe_is_busy(pipe_handle_t pipe_hdl)
|
||||
|
@ -304,13 +304,16 @@ static void usbh_device_unplugged(uint8_t hostid, uint8_t hub_addr, uint8_t hub_
|
||||
usbh_class_drivers[class_index].close(dev_addr);
|
||||
}
|
||||
}
|
||||
usbh_pipe_control_close(dev_addr);
|
||||
|
||||
// TODO refractor
|
||||
// set to REMOVING to allow HCD to clean up its cached data for this device
|
||||
// HCD must set this device's state to TUSB_DEVICE_STATE_UNPLUG when done
|
||||
usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_REMOVING;
|
||||
usbh_devices[dev_addr].flag_supported_class = 0;
|
||||
|
||||
usbh_pipe_control_close(dev_addr);
|
||||
|
||||
|
||||
is_found = true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user