@@ -10,7 +10,7 @@
|
|||||||
*/
|
*/
|
||||||
void OnProjectLoad (void) {
|
void OnProjectLoad (void) {
|
||||||
Project.AddSvdFile ("Cortex-M3.svd");
|
Project.AddSvdFile ("Cortex-M3.svd");
|
||||||
Project.AddSvdFile ("./LPC18xx.svd");
|
Project.AddSvdFile ("../../../../../../../cmsis-svd/data/NXP/LPC18xx.svd");
|
||||||
|
|
||||||
Project.SetDevice ("LPC1857");
|
Project.SetDevice ("LPC1857");
|
||||||
Project.SetHostIF ("USB", "");
|
Project.SetHostIF ("USB", "");
|
||||||
@@ -20,7 +20,8 @@ void OnProjectLoad (void) {
|
|||||||
Project.SetTraceSource ("Trace Pins");
|
Project.SetTraceSource ("Trace Pins");
|
||||||
Project.SetTracePortWidth (4);
|
Project.SetTracePortWidth (4);
|
||||||
|
|
||||||
File.Open ("../../../../../../examples/device/cdc_msc/cmake-build-mcb1800/cdc_msc.elf");
|
//File.Open ("../../../../../../examples/cmake-build-mcb1800/device/cdc_msc/cdc_msc.elf");
|
||||||
|
File.Open ("../../../../../../examples/cmake-build-mcb1800/host/cdc_msc_hid/cdc_msc_hid.elf");
|
||||||
}
|
}
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
*
|
*
|
||||||
|
@@ -421,8 +421,7 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
bool msch_set_config(uint8_t dev_addr, uint8_t itf_num) {
|
||||||
{
|
|
||||||
msch_interface_t* p_msc = get_itf(dev_addr);
|
msch_interface_t* p_msc = get_itf(dev_addr);
|
||||||
TU_ASSERT(p_msc->itf_num == itf_num);
|
TU_ASSERT(p_msc->itf_num == itf_num);
|
||||||
|
|
||||||
@@ -430,10 +429,8 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
|||||||
|
|
||||||
//------------- Get Max Lun -------------//
|
//------------- Get Max Lun -------------//
|
||||||
TU_LOG_DRV("MSC Get Max Lun\r\n");
|
TU_LOG_DRV("MSC Get Max Lun\r\n");
|
||||||
tusb_control_request_t const request =
|
tusb_control_request_t const request = {
|
||||||
{
|
.bmRequestType_bit = {
|
||||||
.bmRequestType_bit =
|
|
||||||
{
|
|
||||||
.recipient = TUSB_REQ_RCPT_INTERFACE,
|
.recipient = TUSB_REQ_RCPT_INTERFACE,
|
||||||
.type = TUSB_REQ_TYPE_CLASS,
|
.type = TUSB_REQ_TYPE_CLASS,
|
||||||
.direction = TUSB_DIR_IN
|
.direction = TUSB_DIR_IN
|
||||||
@@ -444,12 +441,11 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
|
|||||||
.wLength = 1
|
.wLength = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
tuh_xfer_t xfer =
|
tuh_xfer_t xfer = {
|
||||||
{
|
|
||||||
.daddr = dev_addr,
|
.daddr = dev_addr,
|
||||||
.ep_addr = 0,
|
.ep_addr = 0,
|
||||||
.setup = &request,
|
.setup = &request,
|
||||||
.buffer = &p_msc->max_lun,
|
.buffer = _msch_buffer,
|
||||||
.complete_cb = config_get_maxlun_complete,
|
.complete_cb = config_get_maxlun_complete,
|
||||||
.user_data = 0
|
.user_data = 0
|
||||||
};
|
};
|
||||||
@@ -467,6 +463,8 @@ static void config_get_maxlun_complete (tuh_xfer_t* xfer)
|
|||||||
p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0;
|
p_msc->max_lun = (XFER_RESULT_SUCCESS == xfer->result) ? _msch_buffer[0] : 0;
|
||||||
p_msc->max_lun++; // MAX LUN is minus 1 by specs
|
p_msc->max_lun++; // MAX LUN is minus 1 by specs
|
||||||
|
|
||||||
|
TU_LOG_DRV(" Max LUN = %u\r\n", p_msc->max_lun);
|
||||||
|
|
||||||
// TODO multiple LUN support
|
// TODO multiple LUN support
|
||||||
TU_LOG_DRV("SCSI Test Unit Ready\r\n");
|
TU_LOG_DRV("SCSI Test Unit Ready\r\n");
|
||||||
uint8_t const lun = 0;
|
uint8_t const lun = 0;
|
||||||
|
@@ -149,10 +149,11 @@ uint32_t hcd_frame_number(uint8_t rhport);
|
|||||||
// Get the current connect status of roothub port
|
// Get the current connect status of roothub port
|
||||||
bool hcd_port_connect_status(uint8_t rhport);
|
bool hcd_port_connect_status(uint8_t rhport);
|
||||||
|
|
||||||
// Reset USB bus on the port
|
// Reset USB bus on the port. Return immediately, bus reset sequence may not be complete.
|
||||||
|
// Some port would require hcd_port_reset_end() to be invoked after 10ms to complete the reset sequence.
|
||||||
void hcd_port_reset(uint8_t rhport);
|
void hcd_port_reset(uint8_t rhport);
|
||||||
|
|
||||||
// TODO implement later
|
// Complete bus reset sequence, may be required by some controllers
|
||||||
void hcd_port_reset_end(uint8_t rhport);
|
void hcd_port_reset_end(uint8_t rhport);
|
||||||
|
|
||||||
// Get port link speed
|
// Get port link speed
|
||||||
|
@@ -330,7 +330,7 @@ static void connection_port_reset_complete (tuh_xfer_t* xfer);
|
|||||||
bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
|
bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, 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;
|
(void) ep_addr;
|
||||||
TU_ASSERT(result == XFER_RESULT_SUCCESS);
|
TU_VERIFY(result == XFER_RESULT_SUCCESS);
|
||||||
|
|
||||||
hub_interface_t* p_hub = get_itf(dev_addr);
|
hub_interface_t* p_hub = get_itf(dev_addr);
|
||||||
|
|
||||||
|
118
src/host/usbh.c
118
src/host/usbh.c
@@ -181,9 +181,6 @@ static usbh_class_driver_t const usbh_class_drivers[] =
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) };
|
enum { USBH_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) };
|
||||||
|
|
||||||
enum { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer
|
|
||||||
|
|
||||||
enum { CONFIG_NUM = 1 }; // default to use configuration 1
|
enum { CONFIG_NUM = 1 }; // default to use configuration 1
|
||||||
|
|
||||||
|
|
||||||
@@ -251,40 +248,27 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t
|
|||||||
|
|
||||||
#if CFG_TUSB_OS == OPT_OS_NONE
|
#if CFG_TUSB_OS == OPT_OS_NONE
|
||||||
// TODO rework time-related function later
|
// TODO rework time-related function later
|
||||||
TU_ATTR_WEAK void osal_task_delay(uint32_t msec)
|
// weak and overridable
|
||||||
{
|
TU_ATTR_WEAK void osal_task_delay(uint32_t msec) {
|
||||||
const uint32_t start = hcd_frame_number(_usbh_controller);
|
const uint32_t start = hcd_frame_number(_usbh_controller);
|
||||||
while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {}
|
while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// PUBLIC API (Parameter Verification is required)
|
// Device API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param)
|
bool tuh_mounted(uint8_t dev_addr) {
|
||||||
{
|
usbh_device_t *dev = get_device(dev_addr);
|
||||||
if (hcd_configure)
|
|
||||||
{
|
|
||||||
return hcd_configure(rhport, cfg_id, cfg_param);
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool tuh_mounted(uint8_t dev_addr)
|
|
||||||
{
|
|
||||||
usbh_device_t* dev = get_device(dev_addr);
|
|
||||||
TU_VERIFY(dev);
|
TU_VERIFY(dev);
|
||||||
return dev->configured;
|
return dev->configured;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
|
bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) {
|
||||||
{
|
|
||||||
*vid = *pid = 0;
|
*vid = *pid = 0;
|
||||||
|
|
||||||
usbh_device_t const* dev = get_device(dev_addr);
|
usbh_device_t const *dev = get_device(dev_addr);
|
||||||
TU_VERIFY(dev && dev->addressed && dev->vid != 0);
|
TU_VERIFY(dev && dev->addressed && dev->vid != 0);
|
||||||
|
|
||||||
*vid = dev->vid;
|
*vid = dev->vid;
|
||||||
@@ -293,26 +277,48 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusb_speed_t tuh_speed_get (uint8_t dev_addr)
|
tusb_speed_t tuh_speed_get(uint8_t dev_addr) {
|
||||||
{
|
usbh_device_t *dev = get_device(dev_addr);
|
||||||
usbh_device_t* dev = get_device(dev_addr);
|
|
||||||
return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed);
|
return (tusb_speed_t) (dev ? get_device(dev_addr)->speed : _dev0.speed);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_device(usbh_device_t* dev)
|
bool tuh_rhport_is_active(uint8_t rhport) {
|
||||||
{
|
return _usbh_controller == rhport;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool tuh_rhport_reset_bus(uint8_t rhport, bool active) {
|
||||||
|
TU_VERIFY(tuh_rhport_is_active(rhport));
|
||||||
|
if ( active ) {
|
||||||
|
hcd_port_reset(rhport);
|
||||||
|
} else {
|
||||||
|
hcd_port_reset_end(rhport);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// PUBLIC API (Parameter Verification is required)
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) {
|
||||||
|
if ( hcd_configure ) {
|
||||||
|
return hcd_configure(rhport, cfg_id, cfg_param);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_device(usbh_device_t* dev) {
|
||||||
tu_memclr(dev, sizeof(usbh_device_t));
|
tu_memclr(dev, sizeof(usbh_device_t));
|
||||||
memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // invalid mapping
|
memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // invalid mapping
|
||||||
memset(dev->ep2drv , TUSB_INDEX_INVALID_8, sizeof(dev->ep2drv )); // invalid mapping
|
memset(dev->ep2drv , TUSB_INDEX_INVALID_8, sizeof(dev->ep2drv )); // invalid mapping
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tuh_inited(void)
|
bool tuh_inited(void) {
|
||||||
{
|
|
||||||
return _usbh_controller != TUSB_INDEX_INVALID_8;
|
return _usbh_controller != TUSB_INDEX_INVALID_8;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tuh_init(uint8_t controller_id)
|
bool tuh_init(uint8_t controller_id) {
|
||||||
{
|
|
||||||
// skip if already initialized
|
// skip if already initialized
|
||||||
if ( tuh_inited() ) return true;
|
if ( tuh_inited() ) return true;
|
||||||
|
|
||||||
@@ -359,8 +365,7 @@ bool tuh_init(uint8_t controller_id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tuh_task_event_ready(void)
|
bool tuh_task_event_ready(void) {
|
||||||
{
|
|
||||||
// Skip if stack is not initialized
|
// Skip if stack is not initialized
|
||||||
if ( !tuh_inited() ) return false;
|
if ( !tuh_inited() ) return false;
|
||||||
|
|
||||||
@@ -385,8 +390,7 @@ bool tuh_task_event_ready(void)
|
|||||||
}
|
}
|
||||||
@endcode
|
@endcode
|
||||||
*/
|
*/
|
||||||
void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
|
||||||
{
|
|
||||||
(void) in_isr; // not implemented yet
|
(void) in_isr; // not implemented yet
|
||||||
|
|
||||||
// Skip if stack is not initialized
|
// Skip if stack is not initialized
|
||||||
@@ -403,8 +407,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
|||||||
case HCD_EVENT_DEVICE_ATTACH:
|
case HCD_EVENT_DEVICE_ATTACH:
|
||||||
// due to the shared _usbh_ctrl_buf, we must complete enumerating
|
// due to the shared _usbh_ctrl_buf, we must complete enumerating
|
||||||
// one device before enumerating another one.
|
// one device before enumerating another one.
|
||||||
if ( _dev0.enumerating )
|
if ( _dev0.enumerating ) {
|
||||||
{
|
|
||||||
TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport);
|
TU_LOG_USBH("[%u:] USBH Defer Attach until current enumeration complete\r\n", event.rhport);
|
||||||
|
|
||||||
bool is_empty = osal_queue_empty(_usbh_q);
|
bool is_empty = osal_queue_empty(_usbh_q);
|
||||||
@@ -414,8 +417,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
|||||||
// Exit if this is the only event in the queue, otherwise we may loop forever
|
// Exit if this is the only event in the queue, otherwise we may loop forever
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}else
|
}else {
|
||||||
{
|
|
||||||
TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport);
|
TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport);
|
||||||
_dev0.enumerating = 1;
|
_dev0.enumerating = 1;
|
||||||
enum_new_device(&event);
|
enum_new_device(&event);
|
||||||
@@ -428,8 +430,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
|
|||||||
|
|
||||||
#if CFG_TUH_HUB
|
#if CFG_TUH_HUB
|
||||||
// TODO remove
|
// TODO remove
|
||||||
if ( event.connection.hub_addr != 0)
|
if ( event.connection.hub_addr != 0) {
|
||||||
{
|
|
||||||
// done with hub, waiting for next data on status pipe
|
// done with hub, waiting for next data on status pipe
|
||||||
(void) hub_edpt_status_xfer( event.connection.hub_addr );
|
(void) hub_edpt_status_xfer( event.connection.hub_addr );
|
||||||
}
|
}
|
||||||
@@ -1230,6 +1231,12 @@ static void process_removing_device(uint8_t rhport, uint8_t hub_addr, uint8_t hu
|
|||||||
// one device before enumerating another one.
|
// one device before enumerating another one.
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ENUM_RESET_DELAY = 50, // USB specs: 10 to 50ms
|
||||||
|
ENUM_CONTACT_DEBOUNCING_DELAY = 450, // when plug/unplug a device, physical connection can be bouncing and may
|
||||||
|
// generate a series of attach/detach event. This delay wait for stable connection
|
||||||
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ENUM_IDLE,
|
ENUM_IDLE,
|
||||||
ENUM_RESET_1, // 1st reset when attached
|
ENUM_RESET_1, // 1st reset when attached
|
||||||
@@ -1311,7 +1318,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ENUM_HUB_GET_STATUS_2:
|
case ENUM_HUB_GET_STATUS_2:
|
||||||
osal_task_delay(RESET_DELAY);
|
osal_task_delay(ENUM_RESET_DELAY);
|
||||||
TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2), );
|
TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, process_enumeration, ENUM_HUB_CLEAR_RESET_2), );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -1468,12 +1475,14 @@ static bool enum_new_device(hcd_event_t* event)
|
|||||||
if (_dev0.hub_addr == 0)
|
if (_dev0.hub_addr == 0)
|
||||||
{
|
{
|
||||||
// connected/disconnected directly with roothub
|
// connected/disconnected directly with roothub
|
||||||
// wait until device is stable TODO non blocking
|
|
||||||
hcd_port_reset(_dev0.rhport);
|
hcd_port_reset(_dev0.rhport);
|
||||||
osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
|
osal_task_delay(ENUM_RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
|
||||||
// sof of controller may not running while resetting
|
// sof of controller may not running while resetting
|
||||||
hcd_port_reset_end( _dev0.rhport);
|
hcd_port_reset_end( _dev0.rhport);
|
||||||
|
|
||||||
|
// wait until device connection is stable TODO non blocking
|
||||||
|
osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY);
|
||||||
|
|
||||||
// device unplugged while delaying
|
// device unplugged while delaying
|
||||||
if ( !hcd_port_connect_status(_dev0.rhport) ) {
|
if ( !hcd_port_connect_status(_dev0.rhport) ) {
|
||||||
enum_full_complete();
|
enum_full_complete();
|
||||||
@@ -1489,6 +1498,7 @@ static bool enum_new_device(hcd_event_t* event)
|
|||||||
xfer.result = XFER_RESULT_SUCCESS;
|
xfer.result = XFER_RESULT_SUCCESS;
|
||||||
xfer.user_data = ENUM_ADDR0_DEVICE_DESC;
|
xfer.user_data = ENUM_ADDR0_DEVICE_DESC;
|
||||||
|
|
||||||
|
|
||||||
process_enumeration(&xfer);
|
process_enumeration(&xfer);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1496,8 +1506,8 @@ static bool enum_new_device(hcd_event_t* event)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// connected/disconnected via external hub
|
// connected/disconnected via external hub
|
||||||
// wait until device is stable
|
// wait until device connection is stable TODO non blocking
|
||||||
osal_task_delay(RESET_DELAY);
|
osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY);
|
||||||
|
|
||||||
// ENUM_HUB_GET_STATUS
|
// ENUM_HUB_GET_STATUS
|
||||||
//TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete, 0) );
|
//TU_ASSERT( hub_port_get_status(_dev0.hub_addr, _dev0.hub_port, _usbh_ctrl_buf, enum_hub_get_status0_complete, 0) );
|
||||||
@@ -1508,23 +1518,19 @@ static bool enum_new_device(hcd_event_t* event)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t get_new_address(bool is_hub)
|
static uint8_t get_new_address(bool is_hub) {
|
||||||
{
|
|
||||||
uint8_t start;
|
uint8_t start;
|
||||||
uint8_t end;
|
uint8_t end;
|
||||||
|
|
||||||
if ( is_hub )
|
if ( is_hub ) {
|
||||||
{
|
|
||||||
start = CFG_TUH_DEVICE_MAX;
|
start = CFG_TUH_DEVICE_MAX;
|
||||||
end = start + CFG_TUH_HUB;
|
end = start + CFG_TUH_HUB;
|
||||||
}else
|
}else {
|
||||||
{
|
|
||||||
start = 0;
|
start = 0;
|
||||||
end = start + CFG_TUH_DEVICE_MAX;
|
end = start + CFG_TUH_DEVICE_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t idx = start; idx < end; idx++)
|
for (uint8_t idx = start; idx < end; idx++) {
|
||||||
{
|
|
||||||
if (!_usbh_devices[idx].connected) return (idx+1);
|
if (!_usbh_devices[idx].connected) return (idx+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -47,8 +47,7 @@ typedef void (*tuh_xfer_cb_t)(tuh_xfer_t* xfer);
|
|||||||
// it is advised to initialize it using member name
|
// it is advised to initialize it using member name
|
||||||
// Note2: not all field is available/meaningful in callback,
|
// Note2: not all field is available/meaningful in callback,
|
||||||
// some info is not saved by usbh to save SRAM
|
// some info is not saved by usbh to save SRAM
|
||||||
struct tuh_xfer_s
|
struct tuh_xfer_s {
|
||||||
{
|
|
||||||
uint8_t daddr;
|
uint8_t daddr;
|
||||||
uint8_t ep_addr;
|
uint8_t ep_addr;
|
||||||
uint8_t TU_RESERVED; // reserved
|
uint8_t TU_RESERVED; // reserved
|
||||||
@@ -56,8 +55,7 @@ struct tuh_xfer_s
|
|||||||
|
|
||||||
uint32_t actual_len; // excluding setup packet
|
uint32_t actual_len; // excluding setup packet
|
||||||
|
|
||||||
union
|
union {
|
||||||
{
|
|
||||||
tusb_control_request_t const* setup; // setup packet pointer if control transfer
|
tusb_control_request_t const* setup; // setup packet pointer if control transfer
|
||||||
uint32_t buflen; // expected length if not control transfer (not available in callback)
|
uint32_t buflen; // expected length if not control transfer (not available in callback)
|
||||||
};
|
};
|
||||||
@@ -70,15 +68,13 @@ struct tuh_xfer_s
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Subject to change
|
// Subject to change
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
uint8_t daddr;
|
uint8_t daddr;
|
||||||
tusb_desc_interface_t desc;
|
tusb_desc_interface_t desc;
|
||||||
} tuh_itf_info_t;
|
} tuh_itf_info_t;
|
||||||
|
|
||||||
// ConfigID for tuh_config()
|
// ConfigID for tuh_config()
|
||||||
enum
|
enum {
|
||||||
{
|
|
||||||
TUH_CFGID_RPI_PIO_USB_CONFIGURATION = OPT_MCU_RP2040 << 8 // cfg_param: pio_usb_configuration_t
|
TUH_CFGID_RPI_PIO_USB_CONFIGURATION = OPT_MCU_RP2040 << 8 // cfg_param: pio_usb_configuration_t
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,12 +101,12 @@ TU_ATTR_WEAK void tuh_umount_cb(uint8_t daddr);
|
|||||||
// Should be called before tuh_init()
|
// Should be called before tuh_init()
|
||||||
// - cfg_id : configure ID (TBD)
|
// - cfg_id : configure ID (TBD)
|
||||||
// - cfg_param: configure data, structure depends on the ID
|
// - cfg_param: configure data, structure depends on the ID
|
||||||
bool tuh_configure(uint8_t controller_id, uint32_t cfg_id, const void* cfg_param);
|
bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
|
||||||
|
|
||||||
// Init host stack
|
// Init host stack
|
||||||
bool tuh_init(uint8_t controller_id);
|
bool tuh_init(uint8_t rhport);
|
||||||
|
|
||||||
// Check if host stack is already initialized
|
// Check if host stack is already initialized with any roothub ports
|
||||||
bool tuh_inited(void);
|
bool tuh_inited(void);
|
||||||
|
|
||||||
// Task function should be called in main/rtos loop, extended version of tuh_task()
|
// Task function should be called in main/rtos loop, extended version of tuh_task()
|
||||||
@@ -120,8 +116,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr);
|
|||||||
|
|
||||||
// Task function should be called in main/rtos loop
|
// Task function should be called in main/rtos loop
|
||||||
TU_ATTR_ALWAYS_INLINE static inline
|
TU_ATTR_ALWAYS_INLINE static inline
|
||||||
void tuh_task(void)
|
void tuh_task(void) {
|
||||||
{
|
|
||||||
tuh_task_ext(UINT32_MAX, false);
|
tuh_task_ext(UINT32_MAX, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,8 +130,20 @@ extern void hcd_int_handler(uint8_t rhport);
|
|||||||
// Interrupt handler, name alias to HCD
|
// Interrupt handler, name alias to HCD
|
||||||
#define tuh_int_handler hcd_int_handler
|
#define tuh_int_handler hcd_int_handler
|
||||||
|
|
||||||
|
// Check if roothub port is initialized and active as a host
|
||||||
|
bool tuh_rhport_is_active(uint8_t rhport);
|
||||||
|
|
||||||
|
// Assert/de-assert Bus Reset signal to roothub port. USB specs: it should last 10-50ms
|
||||||
|
bool tuh_rhport_reset_bus(uint8_t rhport, bool active);
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
// Device API
|
||||||
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
|
// Get VID/PID of device
|
||||||
bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid);
|
bool tuh_vid_pid_get(uint8_t daddr, uint16_t* vid, uint16_t* pid);
|
||||||
|
|
||||||
|
// Get speed of device
|
||||||
tusb_speed_t tuh_speed_get(uint8_t daddr);
|
tusb_speed_t tuh_speed_get(uint8_t daddr);
|
||||||
|
|
||||||
// Check if device is connected and configured
|
// Check if device is connected and configured
|
||||||
@@ -144,8 +151,7 @@ bool tuh_mounted(uint8_t daddr);
|
|||||||
|
|
||||||
// Check if device is suspended
|
// Check if device is suspended
|
||||||
TU_ATTR_ALWAYS_INLINE static inline
|
TU_ATTR_ALWAYS_INLINE static inline
|
||||||
bool tuh_suspended(uint8_t daddr)
|
bool tuh_suspended(uint8_t daddr) {
|
||||||
{
|
|
||||||
// TODO implement suspend & resume on host
|
// TODO implement suspend & resume on host
|
||||||
(void) daddr;
|
(void) daddr;
|
||||||
return false;
|
return false;
|
||||||
@@ -153,8 +159,7 @@ bool tuh_suspended(uint8_t daddr)
|
|||||||
|
|
||||||
// Check if device is ready to communicate with
|
// Check if device is ready to communicate with
|
||||||
TU_ATTR_ALWAYS_INLINE static inline
|
TU_ATTR_ALWAYS_INLINE static inline
|
||||||
bool tuh_ready(uint8_t daddr)
|
bool tuh_ready(uint8_t daddr) {
|
||||||
{
|
|
||||||
return tuh_mounted(daddr) && !tuh_suspended(daddr);
|
return tuh_mounted(daddr) && !tuh_suspended(daddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,24 +39,27 @@
|
|||||||
#include "ci_hs_type.h"
|
#include "ci_hs_type.h"
|
||||||
|
|
||||||
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
|
#if CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
|
||||||
#include "ci_hs_imxrt.h"
|
|
||||||
|
|
||||||
bool hcd_dcache_clean(void const* addr, uint32_t data_size) {
|
#include "ci_hs_imxrt.h"
|
||||||
return imxrt_dcache_clean(addr, data_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) {
|
bool hcd_dcache_clean(void const* addr, uint32_t data_size) {
|
||||||
return imxrt_dcache_invalidate(addr, data_size);
|
return imxrt_dcache_clean(addr, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) {
|
bool hcd_dcache_invalidate(void const* addr, uint32_t data_size) {
|
||||||
return imxrt_dcache_clean_invalidate(addr, data_size);
|
return imxrt_dcache_invalidate(addr, data_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hcd_dcache_clean_invalidate(void const* addr, uint32_t data_size) {
|
||||||
|
return imxrt_dcache_clean_invalidate(addr, data_size);
|
||||||
|
}
|
||||||
|
|
||||||
#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
|
#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
|
||||||
#include "ci_hs_lpc18_43.h"
|
|
||||||
|
#include "ci_hs_lpc18_43.h"
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Unsupported MCUs"
|
#error "Unsupported MCUs"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@@ -67,25 +70,25 @@
|
|||||||
// Controller API
|
// Controller API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
bool hcd_init(uint8_t rhport)
|
bool hcd_init(uint8_t rhport) {
|
||||||
{
|
ci_hs_regs_t *hcd_reg = CI_HS_REG(rhport);
|
||||||
ci_hs_regs_t* hcd_reg = CI_HS_REG(rhport);
|
|
||||||
|
|
||||||
// Reset controller
|
// Reset controller
|
||||||
hcd_reg->USBCMD |= USBCMD_RESET;
|
hcd_reg->USBCMD |= USBCMD_RESET;
|
||||||
while( hcd_reg->USBCMD & USBCMD_RESET ) {}
|
while ( hcd_reg->USBCMD & USBCMD_RESET ) {}
|
||||||
|
|
||||||
// Set mode to device, must be set immediately after reset
|
// Set mode to device, must be set immediately after reset
|
||||||
#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
|
#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
|
||||||
// LPC18XX/43XX need to set VBUS Power Select to HIGH
|
// LPC18XX/43XX need to set VBUS Power Select to HIGH
|
||||||
// RHPORT1 is fullspeed only (need external PHY for Highspeed)
|
// RHPORT1 is fullspeed only (need external PHY for Highspeed)
|
||||||
hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
|
hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
|
||||||
if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
|
if ( rhport == 1 ) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
|
||||||
#else
|
#else
|
||||||
hcd_reg->USBMODE = USBMODE_CM_HOST;
|
hcd_reg->USBMODE = USBMODE_CM_HOST;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// FIXME force full speed, still have issue with Highspeed enumeration
|
// FIXME force full speed, still have issue with Highspeed enumeration
|
||||||
|
// probably due to physical connection bouncing when plug/unplug
|
||||||
// 1. Have issue when plug/unplug devices, maybe the port is not reset properly
|
// 1. Have issue when plug/unplug devices, maybe the port is not reset properly
|
||||||
// 2. Also does not seems to detect disconnection
|
// 2. Also does not seems to detect disconnection
|
||||||
hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
|
hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
|
||||||
@@ -93,13 +96,11 @@ bool hcd_init(uint8_t rhport)
|
|||||||
return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD);
|
return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_int_enable(uint8_t rhport)
|
void hcd_int_enable(uint8_t rhport) {
|
||||||
{
|
|
||||||
CI_HCD_INT_ENABLE(rhport);
|
CI_HCD_INT_ENABLE(rhport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_int_disable(uint8_t rhport)
|
void hcd_int_disable(uint8_t rhport) {
|
||||||
{
|
|
||||||
CI_HCD_INT_DISABLE(rhport);
|
CI_HCD_INT_DISABLE(rhport);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -188,6 +188,11 @@ void hcd_port_reset(uint8_t rhport)
|
|||||||
|
|
||||||
ehci_registers_t* regs = ehci_data.regs;
|
ehci_registers_t* regs = ehci_data.regs;
|
||||||
|
|
||||||
|
// skip if already in reset
|
||||||
|
if (regs->portsc_bm.port_reset) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// mask out Write-1-to-Clear bits
|
// mask out Write-1-to-Clear bits
|
||||||
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C;
|
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C;
|
||||||
|
|
||||||
@@ -202,16 +207,18 @@ void hcd_port_reset(uint8_t rhport)
|
|||||||
void hcd_port_reset_end(uint8_t rhport)
|
void hcd_port_reset_end(uint8_t rhport)
|
||||||
{
|
{
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
#if 0 // TODO check if this is necessary
|
|
||||||
ehci_registers_t* regs = ehci_data.regs;
|
ehci_registers_t* regs = ehci_data.regs;
|
||||||
|
|
||||||
|
// skip if reset is already complete
|
||||||
|
if (!regs->portsc_bm.port_reset) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// mask out all change bits since they are Write 1 to clear
|
// mask out all change bits since they are Write 1 to clear
|
||||||
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_CHANGE_ALL;
|
uint32_t portsc = regs->portsc & ~EHCI_PORTSC_MASK_W1C;
|
||||||
portsc &= ~(EHCI_PORTSC_MASK_PORT_RESET);
|
portsc &= ~EHCI_PORTSC_MASK_PORT_RESET;
|
||||||
|
|
||||||
regs->portsc = portsc;
|
regs->portsc = portsc;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_port_connect_status(uint8_t rhport)
|
bool hcd_port_connect_status(uint8_t rhport)
|
||||||
@@ -426,6 +433,11 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
|
|||||||
|
|
||||||
hcd_dcache_clean(setup_packet, 8);
|
hcd_dcache_clean(setup_packet, 8);
|
||||||
|
|
||||||
|
// Control endpoint never be stalled. Skip reset Data Toggle since it is fixed per stage
|
||||||
|
if (qhd->qtd_overlay.halted) {
|
||||||
|
qhd->qtd_overlay.halted = false;
|
||||||
|
}
|
||||||
|
|
||||||
// attach TD to QHD -> start transferring
|
// attach TD to QHD -> start transferring
|
||||||
qhd_attach_qtd(qhd, td);
|
qhd_attach_qtd(qhd, td);
|
||||||
|
|
||||||
@@ -662,7 +674,7 @@ void hcd_int_handler(uint8_t rhport)
|
|||||||
if (int_status & EHCI_INT_MASK_PORT_CHANGE) {
|
if (int_status & EHCI_INT_MASK_PORT_CHANGE) {
|
||||||
// Including: Force port resume, over-current change, enable/disable change and connect status change.
|
// Including: Force port resume, over-current change, enable/disable change and connect status change.
|
||||||
uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C;
|
uint32_t const port_status = regs->portsc & EHCI_PORTSC_MASK_W1C;
|
||||||
print_portsc(regs);
|
// print_portsc(regs);
|
||||||
|
|
||||||
if (regs->portsc_bm.connect_status_change) {
|
if (regs->portsc_bm.connect_status_change) {
|
||||||
port_connect_status_change_isr(rhport);
|
port_connect_status_change_isr(rhport);
|
||||||
|
@@ -48,16 +48,14 @@ static pio_usb_configuration_t pio_host_cfg = PIO_USB_DEFAULT_CONFIG;
|
|||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
// HCD API
|
// HCD API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param)
|
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void *cfg_param) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
TU_VERIFY(cfg_id == TUH_CFGID_RPI_PIO_USB_CONFIGURATION);
|
TU_VERIFY(cfg_id == TUH_CFGID_RPI_PIO_USB_CONFIGURATION);
|
||||||
memcpy(&pio_host_cfg, cfg_param, sizeof(pio_usb_configuration_t));
|
memcpy(&pio_host_cfg, cfg_param, sizeof(pio_usb_configuration_t));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_init(uint8_t rhport)
|
bool hcd_init(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
|
|
||||||
// To run USB SOF interrupt in core1, call this init in core1
|
// To run USB SOF interrupt in core1, call this init in core1
|
||||||
@@ -66,20 +64,17 @@ bool hcd_init(uint8_t rhport)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_port_reset(uint8_t rhport)
|
void hcd_port_reset(uint8_t rhport) {
|
||||||
{
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
pio_usb_host_port_reset_start(pio_rhport);
|
pio_usb_host_port_reset_start(pio_rhport);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_port_reset_end(uint8_t rhport)
|
void hcd_port_reset_end(uint8_t rhport) {
|
||||||
{
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
pio_usb_host_port_reset_end(pio_rhport);
|
pio_usb_host_port_reset_end(pio_rhport);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_port_connect_status(uint8_t rhport)
|
bool hcd_port_connect_status(uint8_t rhport) {
|
||||||
{
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
|
|
||||||
root_port_t *root = PIO_USB_ROOT_PORT(pio_rhport);
|
root_port_t *root = PIO_USB_ROOT_PORT(pio_rhport);
|
||||||
@@ -88,33 +83,28 @@ bool hcd_port_connect_status(uint8_t rhport)
|
|||||||
return line_state != PORT_PIN_SE0;
|
return line_state != PORT_PIN_SE0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusb_speed_t hcd_port_speed_get(uint8_t rhport)
|
tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
|
||||||
{
|
|
||||||
// TODO determine link speed
|
// TODO determine link speed
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
return PIO_USB_ROOT_PORT(pio_rhport)->is_fullspeed ? TUSB_SPEED_FULL : TUSB_SPEED_LOW;
|
return PIO_USB_ROOT_PORT(pio_rhport)->is_fullspeed ? TUSB_SPEED_FULL : TUSB_SPEED_LOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close all opened endpoint belong to this device
|
// Close all opened endpoint belong to this device
|
||||||
void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
|
void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
|
||||||
{
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
pio_usb_host_close_device(pio_rhport, dev_addr);
|
pio_usb_host_close_device(pio_rhport, dev_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t hcd_frame_number(uint8_t rhport)
|
uint32_t hcd_frame_number(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
return pio_usb_host_get_frame_number();
|
return pio_usb_host_get_frame_number();
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_int_enable(uint8_t rhport)
|
void hcd_int_enable(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_int_disable(uint8_t rhport)
|
void hcd_int_disable(uint8_t rhport) {
|
||||||
{
|
|
||||||
(void) rhport;
|
(void) rhport;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,18 +112,16 @@ void hcd_int_disable(uint8_t rhport)
|
|||||||
// Endpoint API
|
// Endpoint API
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
|
|
||||||
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * desc_ep)
|
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *desc_ep) {
|
||||||
{
|
|
||||||
hcd_devtree_info_t dev_tree;
|
hcd_devtree_info_t dev_tree;
|
||||||
hcd_devtree_get_info(dev_addr, &dev_tree);
|
hcd_devtree_get_info(dev_addr, &dev_tree);
|
||||||
bool const need_pre = (dev_tree.hub_addr && dev_tree.speed == TUSB_SPEED_LOW);
|
bool const need_pre = (dev_tree.hub_addr && dev_tree.speed == TUSB_SPEED_LOW);
|
||||||
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const*) desc_ep, need_pre);
|
return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const *) desc_ep, need_pre);
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
{
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
return pio_usb_host_endpoint_transfer(pio_rhport, dev_addr, ep_addr, buffer, buflen);
|
return pio_usb_host_endpoint_transfer(pio_rhport, dev_addr, ep_addr, buffer, buflen);
|
||||||
}
|
}
|
||||||
@@ -143,8 +131,7 @@ bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
|
|||||||
return pio_usb_host_endpoint_abort_transfer(pio_rhport, dev_addr, ep_addr);
|
return pio_usb_host_endpoint_abort_transfer(pio_rhport, dev_addr, 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]) {
|
||||||
{
|
|
||||||
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
uint8_t const pio_rhport = RHPORT_PIO(rhport);
|
||||||
return pio_usb_host_send_setup(pio_rhport, dev_addr, setup_packet);
|
return pio_usb_host_send_setup(pio_rhport, dev_addr, setup_packet);
|
||||||
}
|
}
|
||||||
@@ -171,18 +158,16 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t* rport, xfer_result_t result, volatile uint32_t* ep_reg)
|
static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t *rport, xfer_result_t result,
|
||||||
{
|
volatile uint32_t *ep_reg) {
|
||||||
(void) rport;
|
(void) rport;
|
||||||
const uint32_t ep_all = *ep_reg;
|
const uint32_t ep_all = *ep_reg;
|
||||||
|
|
||||||
for(uint8_t ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++)
|
for ( uint8_t ep_idx = 0; ep_idx < PIO_USB_EP_POOL_CNT; ep_idx++ ) {
|
||||||
{
|
|
||||||
uint32_t const mask = (1u << ep_idx);
|
uint32_t const mask = (1u << ep_idx);
|
||||||
|
|
||||||
if (ep_all & mask)
|
if ( ep_all & mask ) {
|
||||||
{
|
endpoint_t * ep = PIO_USB_ENDPOINT(ep_idx);
|
||||||
endpoint_t* ep = PIO_USB_ENDPOINT(ep_idx);
|
|
||||||
hcd_event_xfer_complete(ep->dev_addr, ep->ep_num, ep->actual_len, result, true);
|
hcd_event_xfer_complete(ep->dev_addr, ep->ep_num, ep->actual_len, result, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,34 +177,28 @@ static void __no_inline_not_in_flash_func(handle_endpoint_irq)(root_port_t* rpor
|
|||||||
}
|
}
|
||||||
|
|
||||||
// IRQ Handler
|
// IRQ Handler
|
||||||
void __no_inline_not_in_flash_func(pio_usb_host_irq_handler)(uint8_t root_id)
|
void __no_inline_not_in_flash_func(pio_usb_host_irq_handler)(uint8_t root_id) {
|
||||||
{
|
|
||||||
uint8_t const tu_rhport = root_id + 1;
|
uint8_t const tu_rhport = root_id + 1;
|
||||||
root_port_t* rport = PIO_USB_ROOT_PORT(root_id);
|
root_port_t *rport = PIO_USB_ROOT_PORT(root_id);
|
||||||
uint32_t const ints = rport->ints;
|
uint32_t const ints = rport->ints;
|
||||||
|
|
||||||
if ( ints & PIO_USB_INTS_CONNECT_BITS )
|
if ( ints & PIO_USB_INTS_CONNECT_BITS ) {
|
||||||
{
|
|
||||||
hcd_event_device_attach(tu_rhport, true);
|
hcd_event_device_attach(tu_rhport, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ints & PIO_USB_INTS_DISCONNECT_BITS )
|
if ( ints & PIO_USB_INTS_DISCONNECT_BITS ) {
|
||||||
{
|
|
||||||
hcd_event_device_remove(tu_rhport, true);
|
hcd_event_device_remove(tu_rhport, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ints & PIO_USB_INTS_ENDPOINT_COMPLETE_BITS )
|
if ( ints & PIO_USB_INTS_ENDPOINT_COMPLETE_BITS ) {
|
||||||
{
|
|
||||||
handle_endpoint_irq(rport, XFER_RESULT_SUCCESS, &rport->ep_complete);
|
handle_endpoint_irq(rport, XFER_RESULT_SUCCESS, &rport->ep_complete);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ints & PIO_USB_INTS_ENDPOINT_STALLED_BITS )
|
if ( ints & PIO_USB_INTS_ENDPOINT_STALLED_BITS ) {
|
||||||
{
|
|
||||||
handle_endpoint_irq(rport, XFER_RESULT_STALLED, &rport->ep_stalled);
|
handle_endpoint_irq(rport, XFER_RESULT_STALLED, &rport->ep_stalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ints & PIO_USB_INTS_ENDPOINT_ERROR_BITS )
|
if ( ints & PIO_USB_INTS_ENDPOINT_ERROR_BITS ) {
|
||||||
{
|
|
||||||
handle_endpoint_irq(rport, XFER_RESULT_FAILED, &rport->ep_error);
|
handle_endpoint_irq(rport, XFER_RESULT_FAILED, &rport->ep_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user