summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2021-03-02 23:24:36 +0700
committerhathach <[email protected]>2021-03-02 23:24:36 +0700
commit9d5e3691706f3f17edd701310b967c729240a507 (patch)
treefe8491897c08e74a991776973aa6e7bc14b834b6 /src
parentd91979cfef477e43a19e43b7f56847f207feb385 (diff)
rp2040 add disconnection detection
- also use dcd_event_bus_reset() - Add TODO for suspend, resume later on (need to test with/without vbus detection).
Diffstat (limited to 'src')
-rw-r--r--src/device/usbd.c21
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c43
2 files changed, 53 insertions, 11 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 4fc221888..911977eb0 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -992,11 +992,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
switch (event->event_id)
{
case DCD_EVENT_UNPLUGGED:
- _usbd_dev.connected = 0;
- _usbd_dev.addressed = 0;
- _usbd_dev.cfg_num = 0;
- _usbd_dev.suspended = 0;
- osal_queue_send(_usbd_q, event, in_isr);
+ // UNPLUGGED event can be bouncing, only processing if we are currently connected
+ if ( _usbd_dev.connected )
+ {
+ _usbd_dev.connected = 0;
+ _usbd_dev.addressed = 0;
+ _usbd_dev.cfg_num = 0;
+ _usbd_dev.suspended = 0;
+ osal_queue_send(_usbd_q, event, in_isr);
+ }
break;
case DCD_EVENT_SOF:
@@ -1004,9 +1008,10 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
break;
case DCD_EVENT_SUSPEND:
- // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the
- // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well.
- // We will skip handling SUSPEND/RESUME event if not currently connected
+ // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
+ // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ).
+ // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish
+ // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected
if ( _usbd_dev.connected )
{
_usbd_dev.suspended = 1;
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index d32870439..84dce0248 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -317,13 +317,45 @@ static void dcd_rp2040_irq(void)
pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0);
usb_hw->dev_addr_ctrl = 0;
handled |= USB_INTS_BUS_RESET_BITS;
- dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
+ dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
rp2040_usb_device_enumeration_fix();
#endif
}
+ if (status & USB_INTS_DEV_CONN_DIS_BITS)
+ {
+ handled |= USB_INTS_DEV_CONN_DIS_BITS;
+
+ if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS )
+ {
+ // Connected: nothing to do
+ }else
+ {
+ // Disconnected
+ dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
+ }
+
+ usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
+ }
+
+#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection
+ if (status & USB_INTS_DEV_SUSPEND_BITS)
+ {
+ handled |= USB_INTS_DEV_SUSPEND_BITS;
+ dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
+ usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
+ }
+
+ if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS)
+ {
+ handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
+ dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
+ usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
+ }
+#endif
+
if (status ^ handled)
{
panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled));
@@ -364,8 +396,10 @@ void dcd_init (uint8_t rhport)
// Enable individual controller IRQS here. Processor interrupt enable will be used
// for the global interrupt enable...
+ // TODO Enable SUSPEND & RESUME interrupt
usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS;
- usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS;
+ usb_hw->inte = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
+ USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */ ;
dcd_connect(rhport);
}
@@ -393,8 +427,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
void dcd_remote_wakeup(uint8_t rhport)
{
- pico_info("dcd_remote_wakeup %d is not supported yet\n", rhport);
+ pico_info("dcd_remote_wakeup %d\n", rhport);
assert(rhport == 0);
+ usb_hw_set->sie_ctrl = USB_SIE_CTRL_RESUME_BITS;
}
// disconnect by disabling internal pull-up resistor on D+/D-
@@ -402,6 +437,7 @@ void dcd_disconnect(uint8_t rhport)
{
pico_info("dcd_disconnect %d\n", rhport);
assert(rhport == 0);
+ //TU_LOG2("dcd_disconnect\n");
usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
}
@@ -410,6 +446,7 @@ void dcd_connect(uint8_t rhport)
{
pico_info("dcd_connect %d\n", rhport);
assert(rhport == 0);
+ //TU_LOG2("dcd_connect\n");
usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
}