Skip to content

Commit

Permalink
Merge pull request #2211 from hathach/host-usb-reset
Browse files Browse the repository at this point in the history
Host usb reset
  • Loading branch information
hathach authored Aug 7, 2023
2 parents 1b92108 + 4938971 commit 51a0889
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 161 deletions.
5 changes: 3 additions & 2 deletions hw/bsp/lpc18/boards/mcb1800/ozone/lpc1857.jdebug
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/
void OnProjectLoad (void) {
Project.AddSvdFile ("Cortex-M3.svd");
Project.AddSvdFile ("./LPC18xx.svd");
Project.AddSvdFile ("../../../../../../../cmsis-svd/data/NXP/LPC18xx.svd");

Project.SetDevice ("LPC1857");
Project.SetHostIF ("USB", "");
Expand All @@ -20,7 +20,8 @@ void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
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");
}
/*********************************************************************
*
Expand Down
16 changes: 7 additions & 9 deletions src/class/msc/msc_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,19 +421,16 @@ bool msch_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
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);
TU_ASSERT(p_msc->itf_num == itf_num);

p_msc->configured = true;

//------------- Get Max Lun -------------//
TU_LOG_DRV("MSC Get Max Lun\r\n");
tusb_control_request_t const request =
{
.bmRequestType_bit =
{
tusb_control_request_t const request = {
.bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_INTERFACE,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_IN
Expand All @@ -444,12 +441,11 @@ bool msch_set_config(uint8_t dev_addr, uint8_t itf_num)
.wLength = 1
};

tuh_xfer_t xfer =
{
tuh_xfer_t xfer = {
.daddr = dev_addr,
.ep_addr = 0,
.setup = &request,
.buffer = &p_msc->max_lun,
.buffer = _msch_buffer,
.complete_cb = config_get_maxlun_complete,
.user_data = 0
};
Expand All @@ -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++; // MAX LUN is minus 1 by specs

TU_LOG_DRV(" Max LUN = %u\r\n", p_msc->max_lun);

// TODO multiple LUN support
TU_LOG_DRV("SCSI Test Unit Ready\r\n");
uint8_t const lun = 0;
Expand Down
5 changes: 3 additions & 2 deletions src/host/hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,11 @@ uint32_t hcd_frame_number(uint8_t rhport);
// Get the current connect status of roothub port
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);

// TODO implement later
// Complete bus reset sequence, may be required by some controllers
void hcd_port_reset_end(uint8_t rhport);

// Get port link speed
Expand Down
2 changes: 1 addition & 1 deletion src/host/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
(void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
(void) ep_addr;
TU_ASSERT(result == XFER_RESULT_SUCCESS);
TU_VERIFY(result == XFER_RESULT_SUCCESS);

hub_interface_t* p_hub = get_itf(dev_addr);

Expand Down
118 changes: 62 additions & 56 deletions src/host/usbh.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 { RESET_DELAY = 500 }; // 200 USB specs say only 50ms but many devices require much longer

enum { CONFIG_NUM = 1 }; // default to use configuration 1


Expand Down Expand Up @@ -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
// 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);
while ( ( hcd_frame_number(_usbh_controller) - start ) < msec ) {}
}
#endif

//--------------------------------------------------------------------+
// PUBLIC API (Parameter Verification is required)
// Device API
//--------------------------------------------------------------------+

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;
}
}

bool tuh_mounted(uint8_t dev_addr)
{
usbh_device_t* dev = get_device(dev_addr);
bool tuh_mounted(uint8_t dev_addr) {
usbh_device_t *dev = get_device(dev_addr);
TU_VERIFY(dev);
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;

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);

*vid = dev->vid;
Expand All @@ -293,26 +277,48 @@ bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t* vid, uint16_t* pid)
return true;
}

tusb_speed_t tuh_speed_get (uint8_t dev_addr)
{
usbh_device_t* dev = get_device(dev_addr);
tusb_speed_t tuh_speed_get(uint8_t dev_addr) {
usbh_device_t *dev = get_device(dev_addr);
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));
memset(dev->itf2drv, TUSB_INDEX_INVALID_8, sizeof(dev->itf2drv)); // 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;
}

bool tuh_init(uint8_t controller_id)
{
bool tuh_init(uint8_t controller_id) {
// skip if already initialized
if ( tuh_inited() ) return true;

Expand Down Expand Up @@ -359,8 +365,7 @@ bool tuh_init(uint8_t controller_id)
return true;
}

bool tuh_task_event_ready(void)
{
bool tuh_task_event_ready(void) {
// Skip if stack is not initialized
if ( !tuh_inited() ) return false;

Expand All @@ -385,8 +390,7 @@ bool tuh_task_event_ready(void)
}
@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

// Skip if stack is not initialized
Expand All @@ -403,8 +407,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)
case HCD_EVENT_DEVICE_ATTACH:
// due to the shared _usbh_ctrl_buf, we must complete enumerating
// 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);

bool is_empty = osal_queue_empty(_usbh_q);
Expand All @@ -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
return;
}
}else
{
}else {
TU_LOG_USBH("[%u:] USBH DEVICE ATTACH\r\n", event.rhport);
_dev0.enumerating = 1;
enum_new_device(&event);
Expand All @@ -428,8 +430,7 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr)

#if CFG_TUH_HUB
// TODO remove
if ( event.connection.hub_addr != 0)
{
if ( event.connection.hub_addr != 0) {
// done with hub, waiting for next data on status pipe
(void) hub_edpt_status_xfer( event.connection.hub_addr );
}
Expand Down Expand Up @@ -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.
//--------------------------------------------------------------------+

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_IDLE,
ENUM_RESET_1, // 1st reset when attached
Expand Down Expand Up @@ -1311,7 +1318,7 @@ static void process_enumeration(tuh_xfer_t* xfer)
break;

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), );
break;

Expand Down Expand Up @@ -1468,12 +1475,14 @@ static bool enum_new_device(hcd_event_t* event)
if (_dev0.hub_addr == 0)
{
// connected/disconnected directly with roothub
// wait until device is stable TODO non blocking
hcd_port_reset(_dev0.rhport);
osal_task_delay(RESET_DELAY); // TODO may not work for no-OS on MCU that require reset_end() since
// sof of controller may not running while resetting
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
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
if ( !hcd_port_connect_status(_dev0.rhport) ) {
enum_full_complete();
Expand All @@ -1489,15 +1498,16 @@ static bool enum_new_device(hcd_event_t* event)
xfer.result = XFER_RESULT_SUCCESS;
xfer.user_data = ENUM_ADDR0_DEVICE_DESC;


process_enumeration(&xfer);

}
#if CFG_TUH_HUB
else
{
// connected/disconnected via external hub
// wait until device is stable
osal_task_delay(RESET_DELAY);
// wait until device connection is stable TODO non blocking
osal_task_delay(ENUM_CONTACT_DEBOUNCING_DELAY);

// 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) );
Expand All @@ -1508,23 +1518,19 @@ static bool enum_new_device(hcd_event_t* event)
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 end;

if ( is_hub )
{
if ( is_hub ) {
start = CFG_TUH_DEVICE_MAX;
end = start + CFG_TUH_HUB;
}else
{
}else {
start = 0;
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);
}

Expand Down
Loading

0 comments on commit 51a0889

Please sign in to comment.