completely remove pipe handle for cdc/hub/ehci
This commit is contained in:
parent
e863c99a6f
commit
7a626dbc8b
|
@ -52,14 +52,12 @@ typedef struct {
|
||||||
uint8_t itf_num;
|
uint8_t itf_num;
|
||||||
uint8_t itf_protocol;
|
uint8_t itf_protocol;
|
||||||
|
|
||||||
cdc_acm_capability_t acm_capability;
|
|
||||||
|
|
||||||
pipe_handle_t pipe_notification, pipe_out, pipe_in;
|
|
||||||
|
|
||||||
uint8_t ep_notif;
|
uint8_t ep_notif;
|
||||||
uint8_t ep_in;
|
uint8_t ep_in;
|
||||||
uint8_t ep_out;
|
uint8_t ep_out;
|
||||||
|
|
||||||
|
cdc_acm_capability_t acm_capability;
|
||||||
|
|
||||||
} cdch_data_t;
|
} cdch_data_t;
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -82,13 +80,13 @@ bool tuh_cdc_is_busy(uint8_t dev_addr, cdc_pipeid_t pipeid)
|
||||||
switch (pipeid)
|
switch (pipeid)
|
||||||
{
|
{
|
||||||
case CDC_PIPE_NOTIFICATION:
|
case CDC_PIPE_NOTIFICATION:
|
||||||
return hcd_pipe_is_busy(dev_addr, p_cdc->pipe_notification );
|
return hcd_pipe_is_busy(dev_addr, p_cdc->ep_notif );
|
||||||
|
|
||||||
case CDC_PIPE_DATA_IN:
|
case CDC_PIPE_DATA_IN:
|
||||||
return hcd_pipe_is_busy(dev_addr, p_cdc->pipe_in );
|
return hcd_pipe_is_busy(dev_addr, p_cdc->ep_in );
|
||||||
|
|
||||||
case CDC_PIPE_DATA_OUT:
|
case CDC_PIPE_DATA_OUT:
|
||||||
return hcd_pipe_is_busy(dev_addr, p_cdc->pipe_out );
|
return hcd_pipe_is_busy(dev_addr, p_cdc->ep_out );
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -111,10 +109,10 @@ bool tuh_cdc_send(uint8_t dev_addr, void const * p_data, uint32_t length, bool i
|
||||||
TU_VERIFY( tuh_cdc_mounted(dev_addr) );
|
TU_VERIFY( tuh_cdc_mounted(dev_addr) );
|
||||||
TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
|
TU_VERIFY( p_data != NULL && length, TUSB_ERROR_INVALID_PARA);
|
||||||
|
|
||||||
pipe_handle_t pipe_out = cdch_data[dev_addr-1].pipe_out;
|
uint8_t const ep_out = cdch_data[dev_addr-1].ep_out;
|
||||||
if ( hcd_pipe_is_busy(dev_addr, pipe_out) ) return false;
|
if ( hcd_pipe_is_busy(dev_addr, ep_out) ) return false;
|
||||||
|
|
||||||
return hcd_pipe_xfer(dev_addr, pipe_out, (void *) p_data, length, is_notify);
|
return hcd_pipe_xfer(dev_addr, ep_out, (void *) p_data, length, is_notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify)
|
bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is_notify)
|
||||||
|
@ -122,10 +120,10 @@ bool tuh_cdc_receive(uint8_t dev_addr, void * p_buffer, uint32_t length, bool is
|
||||||
TU_VERIFY( tuh_cdc_mounted(dev_addr) );
|
TU_VERIFY( tuh_cdc_mounted(dev_addr) );
|
||||||
TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
|
TU_VERIFY( p_buffer != NULL && length, TUSB_ERROR_INVALID_PARA);
|
||||||
|
|
||||||
pipe_handle_t pipe_in = cdch_data[dev_addr-1].pipe_in;
|
uint8_t const ep_in = cdch_data[dev_addr-1].ep_in;
|
||||||
if ( hcd_pipe_is_busy(dev_addr, pipe_in) ) return false;
|
if ( hcd_pipe_is_busy(dev_addr, ep_in) ) return false;
|
||||||
|
|
||||||
return hcd_pipe_xfer(dev_addr, pipe_in, p_buffer, length, is_notify);
|
return hcd_pipe_xfer(dev_addr, ep_in, p_buffer, length, is_notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -172,16 +170,14 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
|
||||||
|
|
||||||
if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
|
if ( TUSB_DESC_ENDPOINT == p_desc[DESC_OFFSET_TYPE])
|
||||||
{
|
{
|
||||||
// notification endpoint if any
|
// notification endpoint
|
||||||
tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc;
|
tusb_desc_endpoint_t const * ep_desc = (tusb_desc_endpoint_t const *) p_desc;
|
||||||
p_cdc->pipe_notification = hcd_pipe_open(rhport, dev_addr, ep_desc);
|
|
||||||
|
|
||||||
|
TU_ASSERT( hcd_pipe_open(rhport, dev_addr, ep_desc) );
|
||||||
p_cdc->ep_notif = ep_desc->bEndpointAddress;
|
p_cdc->ep_notif = ep_desc->bEndpointAddress;
|
||||||
|
|
||||||
(*p_length) += p_desc[DESC_OFFSET_LEN];
|
(*p_length) += p_desc[DESC_OFFSET_LEN];
|
||||||
p_desc = descriptor_next(p_desc);
|
p_desc = descriptor_next(p_desc);
|
||||||
|
|
||||||
TU_ASSERT(pipehandle_is_valid(p_cdc->pipe_notification));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------- Data Interface (if any) -------------//
|
//------------- Data Interface (if any) -------------//
|
||||||
|
@ -198,11 +194,7 @@ bool cdch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *it
|
||||||
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
|
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
|
||||||
TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
|
TU_ASSERT(TUSB_XFER_BULK == ep_desc->bmAttributes.xfer);
|
||||||
|
|
||||||
pipe_handle_t * p_pipe_hdl = ( ep_desc->bEndpointAddress & TUSB_DIR_IN_MASK ) ?
|
TU_ASSERT(hcd_pipe_open(rhport, dev_addr, ep_desc));
|
||||||
&p_cdc->pipe_in : &p_cdc->pipe_out;
|
|
||||||
|
|
||||||
(*p_pipe_hdl) = hcd_pipe_open(rhport, dev_addr, ep_desc);
|
|
||||||
TU_ASSERT ( pipehandle_is_valid(*p_pipe_hdl) );
|
|
||||||
|
|
||||||
if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
|
if ( edpt_dir(ep_desc->bEndpointAddress) == TUSB_DIR_IN )
|
||||||
{
|
{
|
||||||
|
@ -241,9 +233,9 @@ void cdch_close(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
cdch_data_t * p_cdc = &cdch_data[dev_addr-1];
|
cdch_data_t * p_cdc = &cdch_data[dev_addr-1];
|
||||||
|
|
||||||
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->pipe_notification);
|
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_notif);
|
||||||
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->pipe_in);
|
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_in);
|
||||||
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->pipe_out);
|
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, p_cdc->ep_out);
|
||||||
|
|
||||||
tu_memclr(p_cdc, sizeof(cdch_data_t));
|
tu_memclr(p_cdc, sizeof(cdch_data_t));
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,9 +77,9 @@ static inline ehci_qtd_t* get_control_qtds(uint8_t dev_addr) ATTR_ALWAYS_INLINE
|
||||||
|
|
||||||
static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
|
static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
|
||||||
static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
|
static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
|
||||||
static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr) ATTR_PURE ATTR_ALWAYS_INLINE;
|
static inline ehci_qhd_t* qhd_find_free (void);
|
||||||
static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
|
static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd) ATTR_ALWAYS_INLINE ATTR_PURE;
|
||||||
static inline ehci_qhd_t* qhd_get_from_pipe_handle(uint8_t dev_addr, pipe_handle_t pipe_hdl);
|
static inline ehci_qhd_t* qhd_get_from_pipe_handle(uint8_t dev_addr, uint8_t ep_addr);
|
||||||
|
|
||||||
// determine if a queue head has bus-related error
|
// determine if a queue head has bus-related error
|
||||||
static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd)
|
static inline bool qhd_has_xact_error(ehci_qhd_t * p_qhd)
|
||||||
|
@ -321,15 +321,6 @@ bool hcd_pipe_control_close(uint8_t dev_addr)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc)
|
|
||||||
{
|
|
||||||
// FIXME control only for now
|
|
||||||
(void) rhport;
|
|
||||||
hcd_pipe_open(rhport, dev_addr, ep_desc);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
|
bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
// FIXME control only for now
|
// FIXME control only for now
|
||||||
|
@ -389,12 +380,10 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// BULK/INT/ISO PIPE API
|
// BULK/INT/ISO PIPE API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
pipe_handle_t hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
|
bool hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
|
||||||
{
|
{
|
||||||
pipe_handle_t const null_handle = { .index = 0 };
|
|
||||||
|
|
||||||
// TODO not support ISO yet
|
// TODO not support ISO yet
|
||||||
if (ep_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS) return null_handle;
|
TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
|
||||||
|
|
||||||
//------------- Prepare Queue Head -------------//
|
//------------- Prepare Queue Head -------------//
|
||||||
ehci_qhd_t * p_qhd;
|
ehci_qhd_t * p_qhd;
|
||||||
|
@ -404,11 +393,11 @@ pipe_handle_t hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint
|
||||||
p_qhd = get_control_qhd(dev_addr);
|
p_qhd = get_control_qhd(dev_addr);
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
p_qhd = qhd_find_free(dev_addr);
|
p_qhd = qhd_find_free();
|
||||||
}
|
}
|
||||||
TU_ASSERT(p_qhd, null_handle);
|
TU_ASSERT(p_qhd);
|
||||||
|
|
||||||
qhd_init( p_qhd, dev_addr, ep_desc);
|
qhd_init(p_qhd, dev_addr, ep_desc);
|
||||||
|
|
||||||
//------------- Insert to Async List -------------//
|
//------------- Insert to Async List -------------//
|
||||||
ehci_link_t * list_head;
|
ehci_link_t * list_head;
|
||||||
|
@ -440,15 +429,13 @@ pipe_handle_t hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint
|
||||||
// TODO might need to disable async/period list
|
// TODO might need to disable async/period list
|
||||||
list_insert( list_head, (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
|
list_insert( list_head, (ehci_link_t*) p_qhd, EHCI_QUEUE_ELEMENT_QHD);
|
||||||
|
|
||||||
return (pipe_handle_t) { .index = qhd_get_index(p_qhd) };
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_pipe_queue_xfer(uint8_t dev_addr, pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes)
|
bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes)
|
||||||
{
|
{
|
||||||
//------------- TODO pipe handle validate -------------//
|
|
||||||
|
|
||||||
//------------- set up QTD -------------//
|
//------------- set up QTD -------------//
|
||||||
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, pipe_hdl);
|
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, ep_addr);
|
||||||
ehci_qtd_t *p_qtd = qtd_find_free(dev_addr);
|
ehci_qtd_t *p_qtd = qtd_find_free(dev_addr);
|
||||||
|
|
||||||
TU_ASSERT(p_qtd);
|
TU_ASSERT(p_qtd);
|
||||||
|
@ -462,11 +449,11 @@ bool hcd_pipe_queue_xfer(uint8_t dev_addr, pipe_handle_t pipe_hdl, uint8_t buffe
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_pipe_xfer(uint8_t dev_addr, pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
|
bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete)
|
||||||
{
|
{
|
||||||
TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, pipe_hdl, buffer, total_bytes) );
|
TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) );
|
||||||
|
|
||||||
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, pipe_hdl);
|
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, ep_addr);
|
||||||
|
|
||||||
if ( int_on_complete )
|
if ( int_on_complete )
|
||||||
{ // the just added qtd is pointed by list_tail
|
{ // the just added qtd is pointed by list_tail
|
||||||
|
@ -478,9 +465,9 @@ bool hcd_pipe_xfer(uint8_t dev_addr, pipe_handle_t pipe_hdl, uint8_t buffer[], u
|
||||||
}
|
}
|
||||||
|
|
||||||
/// pipe_close should only be called as a part of unmount/safe-remove process
|
/// pipe_close should only be called as a part of unmount/safe-remove process
|
||||||
bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, pipe_handle_t pipe_hdl)
|
bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, pipe_hdl);
|
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, ep_addr);
|
||||||
|
|
||||||
// async list needs async advance handshake to make sure host controller has released cached data
|
// async list needs async advance handshake to make sure host controller has released cached data
|
||||||
// non-control does not use async advance, it will eventually free by control pipe close
|
// non-control does not use async advance, it will eventually free by control pipe close
|
||||||
|
@ -505,21 +492,21 @@ bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, pipe_handle_t pipe_hdl)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_pipe_is_busy(uint8_t dev_addr, pipe_handle_t pipe_hdl)
|
bool hcd_pipe_is_busy(uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, pipe_hdl);
|
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, ep_addr);
|
||||||
return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
|
return !p_qhd->qtd_overlay.halted && (p_qhd->p_qtd_list_head != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_pipe_is_stalled(uint8_t dev_addr, pipe_handle_t pipe_hdl)
|
bool hcd_pipe_is_stalled(uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, pipe_hdl);
|
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, ep_addr);
|
||||||
return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd);
|
return p_qhd->qtd_overlay.halted && !qhd_has_xact_error(p_qhd);
|
||||||
}
|
}
|
||||||
|
|
||||||
tusb_error_t hcd_pipe_clear_stall(uint8_t dev_addr, pipe_handle_t pipe_hdl)
|
tusb_error_t hcd_pipe_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, pipe_hdl);
|
ehci_qhd_t *p_qhd = qhd_get_from_pipe_handle(dev_addr, ep_addr);
|
||||||
p_qhd->qtd_overlay.halted = 0;
|
p_qhd->qtd_overlay.halted = 0;
|
||||||
// TODO reset data toggle ?
|
// TODO reset data toggle ?
|
||||||
return TUSB_ERROR_NONE;
|
return TUSB_ERROR_NONE;
|
||||||
|
@ -553,18 +540,22 @@ static void async_advance_isr(ehci_qhd_t * const async_head)
|
||||||
p_control_qhd->used = 0;
|
p_control_qhd->used = 0;
|
||||||
|
|
||||||
// Host Controller has cleaned up its cached data for this device, set state to unplug
|
// Host Controller has cleaned up its cached data for this device, set state to unplug
|
||||||
_usbh_devices[dev_addr+1].state = TUSB_DEVICE_STATE_UNPLUG;
|
_usbh_devices[dev_addr].state = TUSB_DEVICE_STATE_UNPLUG;
|
||||||
|
|
||||||
for (uint8_t i=0; i<HCD_MAX_ENDPOINT; i++) // free all qhd
|
for (uint8_t i=0; i<HCD_MAX_ENDPOINT; i++) // free all qhd
|
||||||
{
|
{
|
||||||
ehci_data.device[dev_addr].qhd[i].used = 0;
|
if (ehci_data.qhd_pool[i].device_address == dev_addr)
|
||||||
ehci_data.device[dev_addr].qhd[i].is_removing = 0;
|
|
||||||
}
|
|
||||||
for (uint8_t i=0; i<HCD_MAX_XFER; i++) // free all qtd
|
|
||||||
{
|
{
|
||||||
ehci_data.device[dev_addr].qtd[i].used = 0;
|
ehci_data.qhd_pool[i].used = 0;
|
||||||
|
ehci_data.qhd_pool[i].is_removing = 0;
|
||||||
}
|
}
|
||||||
// TODO free all itd & sitd
|
}
|
||||||
|
|
||||||
|
// for (uint8_t i=0; i<HCD_MAX_XFER; i++) // free all qtd
|
||||||
|
// {
|
||||||
|
// ehci_data.device[dev_addr].qtd[i].used = 0;
|
||||||
|
// }
|
||||||
|
// // TODO free all itd & sitd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -827,20 +818,14 @@ static inline ehci_qtd_t* get_control_qtds(uint8_t dev_addr)
|
||||||
return &ehci_data.control[dev_addr].qtd;
|
return &ehci_data.control[dev_addr].qtd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ehci_qhd_t* qhd_find_free (uint8_t dev_addr)
|
static inline ehci_qhd_t* qhd_find_free (void)
|
||||||
{
|
{
|
||||||
uint8_t relative_addr = dev_addr-1;
|
for (uint32_t i=0; i<HCD_MAX_ENDPOINT; i++)
|
||||||
uint8_t index=0;
|
|
||||||
while( index<HCD_MAX_ENDPOINT && ehci_data.device[relative_addr].qhd[index].used )
|
|
||||||
{
|
{
|
||||||
index++;
|
if ( !ehci_data.qhd_pool[i].used ) return &ehci_data.qhd_pool[i];
|
||||||
}
|
}
|
||||||
return (index < HCD_MAX_ENDPOINT) ? &ehci_data.device[relative_addr].qhd[index] : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint8_t qhd_get_index(ehci_qhd_t const * p_qhd)
|
return NULL;
|
||||||
{
|
|
||||||
return p_qhd - ehci_data.device[p_qhd->device_address-1].qhd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
|
static inline tusb_xfer_type_t qhd_get_xfer_type(ehci_qhd_t const * p_qhd)
|
||||||
|
@ -854,21 +839,31 @@ static inline ehci_qhd_t* qhd_next(ehci_qhd_t const * p_qhd)
|
||||||
return (ehci_qhd_t*) tu_align32(p_qhd->next.address);
|
return (ehci_qhd_t*) tu_align32(p_qhd->next.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ehci_qhd_t* qhd_get_from_pipe_handle(uint8_t dev_addr, pipe_handle_t pipe_hdl)
|
static inline ehci_qhd_t* qhd_get_from_pipe_handle(uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
return &ehci_data.device[dev_addr-1].qhd[pipe_hdl.index];
|
ehci_qhd_t* qhd_pool = ehci_data.qhd_pool;
|
||||||
|
|
||||||
|
for(uint32_t i=0; i<HCD_MAX_ENDPOINT; i++)
|
||||||
|
{
|
||||||
|
if ( (qhd_pool[i].device_address == dev_addr) &&
|
||||||
|
ep_addr == edpt_addr(qhd_pool[i].endpoint_number, qhd_pool[i].pid_non_control) )
|
||||||
|
{
|
||||||
|
return &qhd_pool[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------- TD helper -------------//
|
//------------- TD helper -------------//
|
||||||
static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
|
static inline ehci_qtd_t* qtd_find_free(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
uint8_t index=0;
|
for (uint32_t i=0; i<HCD_MAX_XFER; i++)
|
||||||
while( index<HCD_MAX_XFER && ehci_data.device[dev_addr-1].qtd[index].used )
|
|
||||||
{
|
{
|
||||||
index++;
|
if ( !ehci_data.qtd_pool[i].used ) return &ehci_data.qtd_pool[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (index < HCD_MAX_XFER) ? &ehci_data.device[dev_addr-1].qtd[index] : NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
|
static inline ehci_qtd_t* qtd_next(ehci_qtd_t const * p_qtd )
|
||||||
|
|
|
@ -462,12 +462,8 @@ typedef struct
|
||||||
ehci_qtd_t qtd;
|
ehci_qtd_t qtd;
|
||||||
}control[CFG_TUSB_HOST_DEVICE_MAX+1];
|
}control[CFG_TUSB_HOST_DEVICE_MAX+1];
|
||||||
|
|
||||||
struct {
|
ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT];
|
||||||
ehci_qhd_t qhd[HCD_MAX_ENDPOINT] ; ///< Queue Head Pool
|
ehci_qtd_t qtd_pool[HCD_MAX_XFER] ATTR_ALIGNED(32);
|
||||||
ehci_qtd_t qtd[HCD_MAX_XFER] ATTR_ALIGNED(32) ; ///< Queue Element Transfer Pool
|
|
||||||
// ehci_itd_t itd[EHCI_MAX_ITD] ; ///< Iso Transfer Pool
|
|
||||||
// ehci_sitd_t sitd[EHCI_MAX_SITD] ; ///< Split (FS) Isochronous Transfer Pool
|
|
||||||
}device[CFG_TUSB_HOST_DEVICE_MAX];
|
|
||||||
|
|
||||||
ehci_registers_t* regs;
|
ehci_registers_t* regs;
|
||||||
}ehci_data_t;
|
}ehci_data_t;
|
||||||
|
|
|
@ -82,8 +82,8 @@ typedef struct
|
||||||
#if TUSB_OPT_HOST_ENABLED
|
#if TUSB_OPT_HOST_ENABLED
|
||||||
// Max number of endpoints per device
|
// Max number of endpoints per device
|
||||||
enum {
|
enum {
|
||||||
HCD_MAX_ENDPOINT = CFG_TUH_HUB + CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC +
|
HCD_MAX_ENDPOINT = CFG_TUSB_HOST_DEVICE_MAX*(CFG_TUH_HUB + CFG_TUH_HID_KEYBOARD + CFG_TUH_HID_MOUSE + CFG_TUSB_HOST_HID_GENERIC +
|
||||||
CFG_TUH_MSC*2 + CFG_TUH_CDC*3,
|
CFG_TUH_MSC*2 + CFG_TUH_CDC*3),
|
||||||
|
|
||||||
HCD_MAX_XFER = HCD_MAX_ENDPOINT*2,
|
HCD_MAX_XFER = HCD_MAX_ENDPOINT*2,
|
||||||
};
|
};
|
||||||
|
@ -96,20 +96,9 @@ enum {
|
||||||
// MACRO CONSTANT TYPEDEF
|
// MACRO CONSTANT TYPEDEF
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t index;
|
uint8_t reserved[4];
|
||||||
uint8_t reserved[3];
|
|
||||||
} pipe_handle_t;
|
} pipe_handle_t;
|
||||||
|
|
||||||
static inline bool pipehandle_is_valid(pipe_handle_t pipe_hdl)
|
|
||||||
{
|
|
||||||
return true ; // pipe_hdl.dev_addr > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool pipehandle_is_equal(pipe_handle_t x, pipe_handle_t y)
|
|
||||||
{
|
|
||||||
return (x.index == y.index);
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// USBH-HCD API
|
// USBH-HCD API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
@ -134,7 +123,6 @@ void hcd_event_xfer_complete(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t ev
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// Endpoints API
|
// Endpoints API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const* ep_desc);
|
|
||||||
bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
|
bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr);
|
||||||
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
|
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]);
|
||||||
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
|
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
|
||||||
|
@ -144,14 +132,14 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// TODO control xfer should be used via usbh layer
|
// TODO control xfer should be used via usbh layer
|
||||||
|
|
||||||
pipe_handle_t hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
|
bool hcd_pipe_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
|
||||||
bool hcd_pipe_queue_xfer(uint8_t dev_addr, pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes) ATTR_WARN_UNUSED_RESULT; // only queue, not transferring yet
|
bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes); // only queue, not transferring yet
|
||||||
bool hcd_pipe_xfer(uint8_t dev_addr, pipe_handle_t pipe_hdl, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) ATTR_WARN_UNUSED_RESULT;
|
bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete);
|
||||||
bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, pipe_handle_t pipe_hdl);
|
bool hcd_pipe_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr); // TODO remove
|
||||||
|
|
||||||
bool hcd_pipe_is_busy(uint8_t dev_addr, pipe_handle_t pipe_hdl);
|
bool hcd_pipe_is_busy(uint8_t dev_addr, uint8_t ep_addr);
|
||||||
bool hcd_pipe_is_stalled(uint8_t dev_addr, pipe_handle_t pipe_hdl); // stalled also counted as error
|
bool hcd_pipe_is_stalled(uint8_t dev_addr, uint8_t ep_addr); // stalled also counted as error
|
||||||
tusb_error_t hcd_pipe_clear_stall(uint8_t dev_addr, pipe_handle_t pipe_hdl);
|
tusb_error_t hcd_pipe_clear_stall(uint8_t dev_addr, uint8_t ep_addr);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT;
|
tusb_error_t hcd_pipe_cancel()ATTR_WARN_UNUSED_RESULT;
|
||||||
|
|
|
@ -50,9 +50,10 @@
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// MACRO CONSTANT TYPEDEF
|
// MACRO CONSTANT TYPEDEF
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
typedef struct {
|
typedef struct
|
||||||
pipe_handle_t pipe_status;
|
{
|
||||||
uint8_t interface_number;
|
uint8_t itf_num;
|
||||||
|
uint8_t ep_status;
|
||||||
uint8_t port_number;
|
uint8_t port_number;
|
||||||
uint8_t status_change; // data from status change interrupt endpoint
|
uint8_t status_change; // data from status change interrupt endpoint
|
||||||
}usbh_hub_t;
|
}usbh_hub_t;
|
||||||
|
@ -161,15 +162,16 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_i
|
||||||
if ( p_interface_desc->bInterfaceProtocol > 1 ) return false;
|
if ( p_interface_desc->bInterfaceProtocol > 1 ) return false;
|
||||||
|
|
||||||
//------------- Open Interrupt Status Pipe -------------//
|
//------------- Open Interrupt Status Pipe -------------//
|
||||||
tusb_desc_endpoint_t const *p_endpoint;
|
tusb_desc_endpoint_t const *ep_desc;
|
||||||
p_endpoint = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
|
ep_desc = (tusb_desc_endpoint_t const *) descriptor_next( (uint8_t const*) p_interface_desc );
|
||||||
|
|
||||||
TU_ASSERT(TUSB_DESC_ENDPOINT == p_endpoint->bDescriptorType);
|
TU_ASSERT(TUSB_DESC_ENDPOINT == ep_desc->bDescriptorType);
|
||||||
TU_ASSERT(TUSB_XFER_INTERRUPT == p_endpoint->bmAttributes.xfer);
|
TU_ASSERT(TUSB_XFER_INTERRUPT == ep_desc->bmAttributes.xfer);
|
||||||
|
|
||||||
hub_data[dev_addr-1].pipe_status = hcd_pipe_open(rhport, dev_addr, p_endpoint);
|
TU_ASSERT(hcd_pipe_open(rhport, dev_addr, ep_desc));
|
||||||
TU_ASSERT( pipehandle_is_valid(hub_data[dev_addr-1].pipe_status) );
|
|
||||||
hub_data[dev_addr-1].interface_number = p_interface_desc->bInterfaceNumber;
|
hub_data[dev_addr-1].itf_num = p_interface_desc->bInterfaceNumber;
|
||||||
|
hub_data[dev_addr-1].ep_status = ep_desc->bEndpointAddress;
|
||||||
|
|
||||||
(*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t);
|
(*p_length) = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t);
|
||||||
|
|
||||||
|
@ -204,16 +206,17 @@ bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *p_i
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------- Queue the initial Status endpoint transfer -------------//
|
//------------- Queue the initial Status endpoint transfer -------------//
|
||||||
TU_ASSERT( hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true) );
|
TU_ASSERT( hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1, true) );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// is the response of interrupt endpoint polling
|
// is the response of interrupt endpoint polling
|
||||||
#include "usbh_hcd.h" // FIXME remove
|
#include "usbh_hcd.h" // FIXME remove
|
||||||
void hub_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes)
|
void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes)
|
||||||
{
|
{
|
||||||
(void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
|
(void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
|
||||||
|
(void) ep_addr;
|
||||||
|
|
||||||
usbh_hub_t * p_hub = &hub_data[dev_addr-1];
|
usbh_hub_t * p_hub = &hub_data[dev_addr-1];
|
||||||
|
|
||||||
|
@ -248,7 +251,7 @@ void hub_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes)
|
||||||
|
|
||||||
void hub_close(uint8_t dev_addr)
|
void hub_close(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, hub_data[dev_addr-1].pipe_status);
|
hcd_pipe_close(TUH_OPT_RHPORT, dev_addr, hub_data[dev_addr-1].ep_status);
|
||||||
tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t));
|
tu_memclr(&hub_data[dev_addr-1], sizeof(usbh_hub_t));
|
||||||
|
|
||||||
// osal_semaphore_reset(hub_enum_sem_hdl);
|
// osal_semaphore_reset(hub_enum_sem_hdl);
|
||||||
|
@ -256,7 +259,7 @@ void hub_close(uint8_t dev_addr)
|
||||||
|
|
||||||
bool hub_status_pipe_queue(uint8_t dev_addr)
|
bool hub_status_pipe_queue(uint8_t dev_addr)
|
||||||
{
|
{
|
||||||
return hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].pipe_status, &hub_data[dev_addr-1].status_change, 1, true);
|
return hcd_pipe_xfer(dev_addr, hub_data[dev_addr-1].ep_status, &hub_data[dev_addr-1].status_change, 1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -196,7 +196,7 @@ bool hub_status_pipe_queue(uint8_t dev_addr);
|
||||||
|
|
||||||
void hub_init(void);
|
void hub_init(void);
|
||||||
bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
|
bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t *p_length) ATTR_WARN_UNUSED_RESULT;
|
||||||
void hub_isr(uint8_t dev_addr, xfer_result_t event, uint32_t xferred_bytes);
|
void hub_isr(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
|
||||||
void hub_close(uint8_t dev_addr);
|
void hub_close(uint8_t dev_addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -236,7 +236,7 @@ tusb_error_t usbh_pipe_control_open(uint8_t dev_addr, uint8_t max_packet_size)
|
||||||
.bInterval = 0
|
.bInterval = 0
|
||||||
};
|
};
|
||||||
|
|
||||||
hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc);
|
hcd_pipe_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc);
|
||||||
|
|
||||||
return TUSB_ERROR_NONE;
|
return TUSB_ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue