mirror of
https://github.com/hathach/tinyusb.git
synced 2025-02-19 15:40:41 +00:00
extra common edpt helper for device and host stack
tu_edpt_validate() and tu_edpt_bind_driver()
This commit is contained in:
parent
aab133ac69
commit
1cef2b6a42
@ -73,6 +73,20 @@
|
||||
#include "tusb_error.h" // TODO remove
|
||||
#include "tusb_timeout.h" // TODO remove
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Helper used by Host and Device Stack
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// Check if endpoint descriptor is valid per USB specs
|
||||
bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);
|
||||
|
||||
// Bind all endpoint of a interface descriptor to class driver
|
||||
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Inline Functions
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//------------- Mem -------------//
|
||||
#define tu_memclr(buffer, size) memset((buffer), 0, (size))
|
||||
#define tu_varclr(_var) tu_memclr(_var, sizeof(*(_var)))
|
||||
|
@ -274,7 +274,6 @@ static osal_mutex_t _usbd_mutex;
|
||||
//--------------------------------------------------------------------+
|
||||
// Prototypes
|
||||
//--------------------------------------------------------------------+
|
||||
static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
|
||||
static bool process_control_request(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
static bool process_set_config(uint8_t rhport, uint8_t cfg_num);
|
||||
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request);
|
||||
@ -901,7 +900,8 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
|
||||
}
|
||||
}
|
||||
|
||||
mark_interface_endpoint(_usbd_dev.ep2drv, p_desc, drv_len, drv_id); // TODO refactor
|
||||
// bind all endpoints for this driver
|
||||
tu_edpt_bind_driver(_usbd_dev.ep2drv, desc_itf, drv_len, drv_id);
|
||||
|
||||
p_desc += drv_len; // next interface
|
||||
|
||||
@ -919,25 +919,6 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Helper marking endpoint of interface belongs to class driver
|
||||
static void mark_interface_endpoint(uint8_t ep2drv[][2], uint8_t const* p_desc, uint16_t desc_len, uint8_t driver_id)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
|
||||
while( len < desc_len )
|
||||
{
|
||||
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
|
||||
{
|
||||
uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
|
||||
|
||||
ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
|
||||
}
|
||||
|
||||
len = (uint16_t)(len + tu_desc_len(p_desc));
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
}
|
||||
|
||||
// return descriptor's buffer and update desc_len
|
||||
static bool process_get_descriptor(uint8_t rhport, tusb_control_request_t const * p_request)
|
||||
{
|
||||
@ -1177,41 +1158,8 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr)
|
||||
|
||||
bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * desc_ep)
|
||||
{
|
||||
uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size);
|
||||
|
||||
TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size);
|
||||
TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX);
|
||||
|
||||
switch (desc_ep->bmAttributes.xfer)
|
||||
{
|
||||
case TUSB_XFER_ISOCHRONOUS:
|
||||
{
|
||||
uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 1023);
|
||||
TU_ASSERT(max_packet_size <= spec_size);
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_XFER_BULK:
|
||||
if (_usbd_dev.speed == TUSB_SPEED_HIGH)
|
||||
{
|
||||
// Bulk highspeed must be EXACTLY 512
|
||||
TU_ASSERT(max_packet_size == 512);
|
||||
}else
|
||||
{
|
||||
// TODO Bulk fullspeed can only be 8, 16, 32, 64
|
||||
TU_ASSERT(max_packet_size <= 64);
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_XFER_INTERRUPT:
|
||||
{
|
||||
uint16_t const spec_size = (_usbd_dev.speed == TUSB_SPEED_HIGH ? 1024 : 64);
|
||||
TU_ASSERT(max_packet_size <= spec_size);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed));
|
||||
|
||||
return dcd_edpt_open(rhport, desc_ep);
|
||||
}
|
||||
|
338
src/host/usbh.c
338
src/host/usbh.c
@ -28,16 +28,23 @@
|
||||
|
||||
#if TUSB_OPT_HOST_ENABLED
|
||||
|
||||
#ifndef CFG_TUH_TASK_QUEUE_SZ
|
||||
#define CFG_TUH_TASK_QUEUE_SZ 16
|
||||
#endif
|
||||
|
||||
#include "tusb.h"
|
||||
#include "host/usbh.h"
|
||||
#include "host/usbh_classdriver.h"
|
||||
#include "hub.h"
|
||||
#include "usbh_hcd.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// USBH Configuration
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
#ifndef CFG_TUH_TASK_QUEUE_SZ
|
||||
#define CFG_TUH_TASK_QUEUE_SZ 16
|
||||
#endif
|
||||
|
||||
// Debug level of USBD
|
||||
#define USBH_DBG_LVL 2
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACRO CONSTANT TYPEDEF
|
||||
//--------------------------------------------------------------------+
|
||||
@ -135,6 +142,7 @@ CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN static uint8_t _usbh_ctrl_buf[CFG_TUH_EN
|
||||
//------------- Helper Function Prototypes -------------//
|
||||
static bool enum_new_device(hcd_event_t* event);
|
||||
static void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port);
|
||||
static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size);
|
||||
|
||||
// from usbh_control.c
|
||||
extern bool usbh_control_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
|
||||
@ -314,151 +322,6 @@ uint8_t* usbh_get_enum_buf(void)
|
||||
return _usbh_ctrl_buf;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// TODO has some duplication code with device, refactor later
|
||||
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
// pre-check to help reducing mutex lock
|
||||
TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0));
|
||||
osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
|
||||
// can only claim the endpoint if it is not busy and not claimed yet.
|
||||
bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0);
|
||||
if (ret)
|
||||
{
|
||||
dev->ep_status[epnum][dir].claimed = 1;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_unlock(dev->mutex);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO has some duplication code with device, refactor later
|
||||
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
|
||||
// can only release the endpoint if it is claimed and not busy
|
||||
bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1);
|
||||
if (ret)
|
||||
{
|
||||
dev->ep_status[epnum][dir].claimed = 0;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_unlock(dev->mutex);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO has some duplication code with device, refactor later
|
||||
bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
|
||||
|
||||
// Attempt to transfer on a busy endpoint, sound like an race condition !
|
||||
TU_ASSERT(dev->ep_status[epnum][dir].busy == 0);
|
||||
|
||||
// Set busy first since the actual transfer can be complete before hcd_edpt_xfer()
|
||||
// could return and USBH task can preempt and clear the busy
|
||||
dev->ep_status[epnum][dir].busy = true;
|
||||
|
||||
if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
|
||||
{
|
||||
TU_LOG2("OK\r\n");
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
// HCD error, mark endpoint as ready to allow next transfer
|
||||
dev->ep_status[epnum][dir].busy = false;
|
||||
dev->ep_status[epnum][dir].claimed = 0;
|
||||
TU_LOG2("failed\r\n");
|
||||
TU_BREAKPOINT();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
|
||||
{
|
||||
TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size);
|
||||
|
||||
tusb_desc_endpoint_t ep0_desc =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_endpoint_t),
|
||||
.bDescriptorType = TUSB_DESC_ENDPOINT,
|
||||
.bEndpointAddress = 0,
|
||||
.bmAttributes = { .xfer = TUSB_XFER_CONTROL },
|
||||
.wMaxPacketSize = { .size = max_packet_size },
|
||||
.bInterval = 0
|
||||
};
|
||||
|
||||
return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc);
|
||||
}
|
||||
|
||||
bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
|
||||
{
|
||||
TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, desc_ep->wMaxPacketSize.size);
|
||||
|
||||
bool ret = hcd_edpt_open(rhport, dev_addr, desc_ep);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
// new endpoints belongs to latest interface (last valid value)
|
||||
// TODO FIXME not true with ISO
|
||||
uint8_t drvid = 0xff;
|
||||
for(uint8_t i=0; i < sizeof(dev->itf2drv); i++)
|
||||
{
|
||||
if ( dev->itf2drv[i] == 0xff ) break;
|
||||
drvid = dev->itf2drv[i];
|
||||
}
|
||||
TU_ASSERT(drvid < USBH_CLASS_DRIVER_COUNT);
|
||||
|
||||
uint8_t const ep_addr = desc_ep->bEndpointAddress;
|
||||
dev->ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = drvid;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
return dev->ep_status[epnum][dir].busy;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// HCD Event Handler
|
||||
//--------------------------------------------------------------------+
|
||||
@ -841,7 +704,7 @@ static bool enum_set_address_complete(uint8_t dev_addr, tusb_control_request_t c
|
||||
dev0->state = TUSB_DEVICE_STATE_UNPLUG;
|
||||
|
||||
// open control pipe for new address
|
||||
TU_ASSERT ( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) );
|
||||
TU_ASSERT( usbh_edpt_control_open(new_addr, new_dev->ep0_packet_size) );
|
||||
|
||||
// Get full device descriptor
|
||||
TU_LOG2("Get Device Descriptor\r\n");
|
||||
@ -981,6 +844,34 @@ static bool enum_set_config_complete(uint8_t dev_addr, tusb_control_request_t co
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get total length of n interface (depending on IAD)
|
||||
static uint16_t get_interface_length(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len)
|
||||
{
|
||||
uint8_t const* p_desc = (uint8_t const*) desc_itf;
|
||||
uint16_t len = 0;
|
||||
|
||||
while (itf_count--)
|
||||
{
|
||||
// Next on interface desc
|
||||
len += tu_desc_len(desc_itf);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
|
||||
while (len < max_len)
|
||||
{
|
||||
// return on IAD regardless of itf count
|
||||
if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len;
|
||||
|
||||
if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
|
||||
((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 ) break;
|
||||
|
||||
len += tu_desc_len(p_desc);
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
|
||||
{
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
@ -992,20 +883,25 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
while( p_desc < desc_end )
|
||||
{
|
||||
// TODO Do we need to use IAD
|
||||
// tusb_desc_interface_assoc_t const * desc_itf_assoc = NULL;
|
||||
tusb_desc_interface_assoc_t const * desc_iad = NULL;
|
||||
|
||||
// Class will always starts with Interface Association (if any) and then Interface descriptor
|
||||
if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
|
||||
{
|
||||
// desc_itf_assoc = (tusb_desc_interface_assoc_t const *) p_desc;
|
||||
desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
|
||||
TU_LOG_INT(2, p_desc - (uint8_t*) desc_cfg);
|
||||
TU_LOG_INT(2, tu_desc_type(p_desc));
|
||||
TU_ASSERT( TUSB_DESC_INTERFACE == tu_desc_type(p_desc) );
|
||||
|
||||
tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
|
||||
uint16_t const remaining_len = desc_end-p_desc;
|
||||
|
||||
uint16_t const drv_len = get_interface_length(desc_itf, desc_iad ? desc_iad->bInterfaceCount : 1, remaining_len);
|
||||
TU_ASSERT(drv_len);
|
||||
|
||||
// Check if class is supported TODO drop class_code
|
||||
uint8_t drv_id;
|
||||
for (drv_id = 0; drv_id < USBH_CLASS_DRIVER_COUNT; drv_id++)
|
||||
@ -1015,8 +911,11 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
|
||||
if( drv_id >= USBH_CLASS_DRIVER_COUNT )
|
||||
{
|
||||
// skip unsupported class
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
TU_LOG(USBH_DBG_LVL, "Interface %u: class = %u subclass = %u protocol = %u is not supported\r\n",
|
||||
desc_itf->bInterfaceNumber, desc_itf->bInterfaceClass, desc_itf->bInterfaceSubClass, desc_itf->bInterfaceProtocol);
|
||||
|
||||
// skip unsupported class until next Interface or IAD descriptor
|
||||
p_desc += drv_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1038,6 +937,10 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
|
||||
uint16_t const itf_len = driver->open(dev->rhport, dev_addr, desc_itf, remaining_len);
|
||||
TU_ASSERT( sizeof(tusb_desc_interface_t) <= itf_len && itf_len <= remaining_len);
|
||||
|
||||
// bind all endpoints for this driver
|
||||
tu_edpt_bind_driver(dev->ep2drv, desc_itf, drv_len, drv_id);
|
||||
|
||||
p_desc += itf_len;
|
||||
}
|
||||
}
|
||||
@ -1046,4 +949,131 @@ static bool parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configura
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Endpoint API
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
// TODO has some duplication code with device, refactor later
|
||||
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
// pre-check to help reducing mutex lock
|
||||
TU_VERIFY((dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0));
|
||||
osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
|
||||
// can only claim the endpoint if it is not busy and not claimed yet.
|
||||
bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 0);
|
||||
if (ret)
|
||||
{
|
||||
dev->ep_status[epnum][dir].claimed = 1;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_unlock(dev->mutex);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO has some duplication code with device, refactor later
|
||||
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_lock(dev->mutex, OSAL_TIMEOUT_WAIT_FOREVER);
|
||||
#endif
|
||||
|
||||
// can only release the endpoint if it is claimed and not busy
|
||||
bool const ret = (dev->ep_status[epnum][dir].busy == 0) && (dev->ep_status[epnum][dir].claimed == 1);
|
||||
if (ret)
|
||||
{
|
||||
dev->ep_status[epnum][dir].claimed = 0;
|
||||
}
|
||||
|
||||
#if CFG_TUSB_OS != OPT_OS_NONE
|
||||
osal_mutex_unlock(dev->mutex);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO has some duplication code with device, refactor later
|
||||
bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
TU_LOG2(" Queue EP %02X with %u bytes ... ", ep_addr, total_bytes);
|
||||
|
||||
// Attempt to transfer on a busy endpoint, sound like an race condition !
|
||||
TU_ASSERT(dev->ep_status[epnum][dir].busy == 0);
|
||||
|
||||
// Set busy first since the actual transfer can be complete before hcd_edpt_xfer()
|
||||
// could return and USBH task can preempt and clear the busy
|
||||
dev->ep_status[epnum][dir].busy = true;
|
||||
|
||||
if ( hcd_edpt_xfer(dev->rhport, dev_addr, ep_addr, buffer, total_bytes) )
|
||||
{
|
||||
TU_LOG2("OK\r\n");
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
// HCD error, mark endpoint as ready to allow next transfer
|
||||
dev->ep_status[epnum][dir].busy = false;
|
||||
dev->ep_status[epnum][dir].claimed = 0;
|
||||
TU_LOG2("failed\r\n");
|
||||
TU_BREAKPOINT();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool usbh_edpt_control_open(uint8_t dev_addr, uint8_t max_packet_size)
|
||||
{
|
||||
TU_LOG2("Open EP Control with Size = %u\r\n", max_packet_size);
|
||||
|
||||
tusb_desc_endpoint_t ep0_desc =
|
||||
{
|
||||
.bLength = sizeof(tusb_desc_endpoint_t),
|
||||
.bDescriptorType = TUSB_DESC_ENDPOINT,
|
||||
.bEndpointAddress = 0,
|
||||
.bmAttributes = { .xfer = TUSB_XFER_CONTROL },
|
||||
.wMaxPacketSize = { .size = max_packet_size },
|
||||
.bInterval = 0
|
||||
};
|
||||
|
||||
return hcd_edpt_open(_usbh_devices[dev_addr].rhport, dev_addr, &ep0_desc);
|
||||
}
|
||||
|
||||
bool usbh_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
|
||||
{
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) dev->speed));
|
||||
|
||||
return hcd_edpt_open(rhport, dev_addr, desc_ep);
|
||||
}
|
||||
|
||||
bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr)
|
||||
{
|
||||
uint8_t const epnum = tu_edpt_number(ep_addr);
|
||||
uint8_t const dir = tu_edpt_dir(ep_addr);
|
||||
|
||||
usbh_device_t* dev = &_usbh_devices[dev_addr];
|
||||
|
||||
return dev->ep_status[epnum][dir].busy;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -73,6 +73,8 @@ bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_
|
||||
// If caller does not make any transfer, it must release endpoint for others.
|
||||
bool usbh_edpt_claim(uint8_t dev_addr, uint8_t ep_addr);
|
||||
|
||||
bool usbh_edpt_release(uint8_t dev_addr, uint8_t ep_addr);
|
||||
|
||||
// Check if endpoint transferring is complete
|
||||
bool usbh_edpt_busy(uint8_t dev_addr, uint8_t ep_addr);
|
||||
|
||||
|
62
src/tusb.c
62
src/tusb.c
@ -63,6 +63,68 @@ bool tusb_inited(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Internal Helper for both Host and Device stack
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed)
|
||||
{
|
||||
uint16_t const max_packet_size = tu_le16toh(desc_ep->wMaxPacketSize.size);
|
||||
TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size);
|
||||
|
||||
switch (desc_ep->bmAttributes.xfer)
|
||||
{
|
||||
case TUSB_XFER_ISOCHRONOUS:
|
||||
{
|
||||
uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 1023);
|
||||
TU_ASSERT(max_packet_size <= spec_size);
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_XFER_BULK:
|
||||
if (speed == TUSB_SPEED_HIGH)
|
||||
{
|
||||
// Bulk highspeed must be EXACTLY 512
|
||||
TU_ASSERT(max_packet_size == 512);
|
||||
}else
|
||||
{
|
||||
// TODO Bulk fullspeed can only be 8, 16, 32, 64
|
||||
TU_ASSERT(max_packet_size <= 64);
|
||||
}
|
||||
break;
|
||||
|
||||
case TUSB_XFER_INTERRUPT:
|
||||
{
|
||||
uint16_t const spec_size = (speed == TUSB_SPEED_HIGH ? 1024 : 64);
|
||||
TU_ASSERT(max_packet_size <= spec_size);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* desc_itf, uint16_t desc_len, uint8_t driver_id)
|
||||
{
|
||||
uint8_t const* p_desc = (uint8_t const*) desc_itf;
|
||||
uint16_t len = 0;
|
||||
|
||||
while( len < desc_len )
|
||||
{
|
||||
if ( TUSB_DESC_ENDPOINT == tu_desc_type(p_desc) )
|
||||
{
|
||||
uint8_t const ep_addr = ((tusb_desc_endpoint_t const*) p_desc)->bEndpointAddress;
|
||||
|
||||
ep2drv[tu_edpt_number(ep_addr)][tu_edpt_dir(ep_addr)] = driver_id;
|
||||
}
|
||||
|
||||
len = (uint16_t)(len + tu_desc_len(p_desc));
|
||||
p_desc = tu_desc_next(p_desc);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------*/
|
||||
/* Debug
|
||||
*------------------------------------------------------------------*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user