Index: firmware/export/usb_drv.h
===================================================================
--- firmware/export/usb_drv.h	(revision 31467)
+++ firmware/export/usb_drv.h	(working copy)
@@ -24,7 +24,6 @@
 #include "kernel.h"
 
 void usb_drv_startup(void);
-void usb_drv_usb_detect_event(void); /* Target implemented */
 void usb_drv_int_enable(bool enable); /* Target implemented */
 void usb_drv_init(void);
 void usb_drv_exit(void);
Index: firmware/export/config.h
===================================================================
--- firmware/export/config.h	(revision 31467)
+++ firmware/export/config.h	(working copy)
@@ -770,7 +770,7 @@
 /* Priority in bootloader is wanted */
 #define HAVE_PRIORITY_SCHEDULING
 #define USB_STATUS_BY_EVENT
-#define USB_DETECT_BY_CORE
+#define USB_DETECT_BY_REQUEST
 #if defined(HAVE_USBSTACK) && CONFIG_USBOTG == USBOTG_ARC
 #define INCLUDE_TIMEOUT_API
 #endif
@@ -797,17 +797,17 @@
 #ifdef HAVE_USBSTACK
 #if CONFIG_USBOTG == USBOTG_ARC
 #define USB_STATUS_BY_EVENT
-#define USB_DETECT_BY_CORE
+#define USB_DETECT_BY_REQUEST
 #define INCLUDE_TIMEOUT_API
 #elif CONFIG_USBOTG == USBOTG_AS3525
 #define USB_STATUS_BY_EVENT
-#define USB_DETECT_BY_CORE
+#define USB_DETECT_BY_REQUEST
 #elif CONFIG_USBOTG == USBOTG_AS3525v2
 #define USB_STATUS_BY_EVENT
-#define USB_DETECT_BY_CORE
+#define USB_DETECT_BY_REQUEST
 #elif CONFIG_USBOTG == USBOTG_RK27XX
 #define USB_STATUS_BY_EVENT
-#define USB_DETECT_BY_CORE
+#define USB_DETECT_BY_REQUEST
 #endif /* CONFIG_USB == */
 #endif /* HAVE_USBSTACK */
 
Index: firmware/export/usb.h
===================================================================
--- firmware/export/usb.h	(revision 31467)
+++ firmware/export/usb.h	(working copy)
@@ -39,9 +39,6 @@
     USB_EXTRACTED = 0,       /* Event+State */
     USB_INSERTED,            /* Event+State */
     USB_POWERED,             /* State - transitional indicator if no power */
-#ifdef USB_DETECT_BY_CORE
-    USB_HOSTED,              /* Event - host presence was detected */
-#endif
 #if (CONFIG_STORAGE & STORAGE_MMC)
     USB_REENABLE,            /* Event */
 #endif
Index: firmware/usbstack/usb_core.c
===================================================================
--- firmware/usbstack/usb_core.c	(revision 31467)
+++ firmware/usbstack/usb_core.c	(working copy)
@@ -559,11 +559,6 @@
         case USB_DT_DEVICE:
             ptr = &device_descriptor;
             size = sizeof(struct usb_device_descriptor);
-#ifdef USB_DETECT_BY_CORE
-            /* Something requested a device descriptor; consider this a legit
-               connection */
-            usb_drv_usb_detect_event();
-#endif
             break;
 
         case USB_DT_OTHER_SPEED_CONFIG:
Index: firmware/target/arm/usb-fw-pp502x.c
===================================================================
--- firmware/target/arm/usb-fw-pp502x.c	(revision 31467)
+++ firmware/target/arm/usb-fw-pp502x.c	(working copy)
@@ -225,15 +225,6 @@
     USB_GPIO_INT_CLR = USB_GPIO_MASK;
     timeout_register(&usb_oneshot, usb_timeout_event, HZ/5, val);
 }
-
-/* USB_DETECT_BY_CORE: Called when device descriptor is requested */
-void usb_drv_usb_detect_event(void)
-{
-    /* Filter for invalid bus reset when unplugging by checking the pin state. */
-    if(usb_plugged()) {
-        usb_status_event(USB_HOSTED);
-    }
-}
 #endif /* USB_STATUS_BY_EVENT */
 
 #ifdef HAVE_BOOTLOADER_USB_MODE
Index: firmware/target/arm/as3525/usb-as3525.c
===================================================================
--- firmware/target/arm/as3525/usb-as3525.c	(revision 31467)
+++ firmware/target/arm/as3525/usb-as3525.c	(working copy)
@@ -59,22 +59,6 @@
 #endif
 }
 
-void usb_drv_usb_detect_event(void)
-{
-#if (CONFIG_CPU != AS3525v2 || defined(USE_ROCKBOX_USB)) \
-    && defined (USB_STATUS_BY_EVENT)
-/* Rebooting on USB plug can crash these players in a state where
- * hardware power off (pressing the power button) doesn't work anymore
- * TODO: Implement USB in rockbox for these players */
-    int oldstatus = disable_irq_save(); /* May come via USB thread */
-
-    if (usb_status == USB_INSERTED)
-        usb_status_event(USB_HOSTED);
-
-    restore_irq(oldstatus);
-#endif
-}
-
 int usb_detect(void)
 {
     return usb_status;
Index: firmware/target/arm/imx233/usb-imx233.c
===================================================================
--- firmware/target/arm/imx233/usb-imx233.c	(revision 31467)
+++ firmware/target/arm/imx233/usb-imx233.c	(working copy)
@@ -41,11 +41,6 @@
     usb_status_event(USB_EXTRACTED);
 }
 
-void usb_drv_usb_detect_event()
-{
-    usb_status_event(USB_HOSTED);
-}
-
 void usb_attach(void)
 {
     usb_drv_attach();
Index: firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c
===================================================================
--- firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c	(revision 31467)
+++ firmware/target/arm/imx31/gigabeat-s/usb-gigabeat-s.c	(working copy)
@@ -138,13 +138,6 @@
     }
 }
 
-/* Called during the setup packet request by the host */
-void usb_drv_usb_detect_event(void)
-{
-    if (usb_drv_powered())
-        usb_status_event(USB_HOSTED);
-}
-
 /* Called when reading the MBR */
 void usb_fix_mbr(unsigned char *mbr)
 {
Index: firmware/target/arm/rk27xx/usb-rk27xx.c
===================================================================
--- firmware/target/arm/rk27xx/usb-rk27xx.c	(revision 31467)
+++ firmware/target/arm/rk27xx/usb-rk27xx.c	(working copy)
@@ -31,11 +31,6 @@
 
 int usb_status = USB_EXTRACTED;
 
-void usb_drv_usb_detect_event()
-{
-    usb_status_event(USB_INSERTED);
-}
-
 void usb_init_device(void)
 {
 }
Index: firmware/usb.c
===================================================================
--- firmware/usb.c	(revision 31467)
+++ firmware/usb.c	(working copy)
@@ -65,7 +65,9 @@
 
 /* We assume that the USB cable is extracted */
 static int usb_state = USB_EXTRACTED;
-
+static bool usb_host_present = false;
+static int usb_num_acks_to_expect = 0;
+static long usb_last_broadcast_tick = 0;
 #if (CONFIG_STORAGE & STORAGE_MMC) && defined(USB_FULL_INIT) && !defined(HAVE_USBSTACK)
 static int usb_mmc_countdown = 0;
 #endif
@@ -116,7 +118,6 @@
 #ifdef HAVE_LCD_BITMAP
     if(do_screendump_instead_of_usb)
     {
-        usb_state = USB_SCREENDUMP;
         screen_dump();
 #ifdef HAVE_REMOTE_LCD
         remote_screen_dump();
@@ -358,13 +359,69 @@
 }
 #endif /* HAVE_USBSTACK */
 
+static void usb_set_host_present(bool present)
+{
+    if(usb_host_present == present)
+        return;
 
+    usb_host_present = present;
+
+    if(!usb_host_present)
+    {
+        usb_configure_drivers(USB_EXTRACTED);
+        return;
+    }
+
+    if(usb_power_button())
+    {
+        /* Only charging is desired */
+        usb_configure_drivers(USB_POWERED);
+        return;
+    }
+
+    if(!usb_configure_drivers(USB_INSERTED))
+        return; /* Exclusive storage access not required */
+
+    /* Tell all threads that they have to back off the storage.
+       We subtract one for our own thread. Expect an ACK for every
+       listener for each broadcast they received. If it has been too
+       long, the user might have entered a screen that didn't ACK
+       when inserting the cable, such as a debugging screen. In that
+       case, reset the count or else USB would be locked out until
+       rebooting because it most likely won't ever come. Simply
+       resetting to the most recent broadcast count is racy. */
+    if(TIME_AFTER(current_tick, usb_last_broadcast_tick + HZ*5))
+    {
+        usb_num_acks_to_expect = 0;
+        usb_last_broadcast_tick = current_tick;
+    }
+
+    usb_num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
+    DEBUGF("usb: waiting for %d acks...\n", num_acks_to_expect);
+}
+
+static bool usb_handle_connected_ack(void)
+{
+    if(usb_num_acks_to_expect > 0 && --usb_num_acks_to_expect == 0)
+    {
+        DEBUGF("usb: all threads have acknowledged the connect.\n");
+        if(usb_host_present)
+        {
+            usb_slave_mode(true);
+            return true;
+        }
+    }
+    else
+    {
+        DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect);
+    }
+
+    return false;
+}
+
 /*--- General driver code ---*/
 static void NORETURN_ATTR usb_thread(void)
 {
-    int num_acks_to_expect = 0;
-    long last_broadcast_tick = current_tick;
-    bool host_detected = false;
     struct queue_event ev;
 
     while(1)
@@ -380,6 +437,10 @@
             if(usb_state <= USB_EXTRACTED)
                 break;
 
+#ifdef USB_DETECT_BY_REQUEST
+            usb_set_host_present(true);
+#endif
+
             usb_core_handle_transfer_completion(
                 (struct usb_transfer_completion_event_data*)ev.data);
             break;
@@ -390,71 +451,23 @@
                 break;
 
             if(usb_do_screendump())
+            {
+                usb_state = USB_SCREENDUMP;
                 break;
+            }
 
             usb_state = USB_POWERED;
             usb_stack_enable(true);
 
-#ifdef USB_DETECT_BY_CORE
-            /* Wait for USB core to detect the host */
+#ifndef USB_DETECT_BY_REQUEST
+            usb_set_host_present(true);
+#endif
             break;
+            /* USB_INSERTED */
 
-        case USB_HOSTED:
-            if(usb_state != USB_POWERED)
-                break;
-#endif /* USB_DETECT_BY_CORE */
-
-            if(host_detected)
-                break;
-
-            host_detected = true;
-
-            if(usb_power_button())
-            {
-                /* Only charging is desired */
-                usb_configure_drivers(USB_POWERED);
-                break;
-            }
-
-            if(!usb_configure_drivers(USB_INSERTED))
-                break; /* Exclusive storage access not required */
-
-            /* Tell all threads that they have to back off the storage.
-               We subtract one for our own thread. Expect an ACK for every
-               listener for each broadcast they received. If it has been too
-               long, the user might have entered a screen that didn't ACK
-               when inserting the cable, such as a debugging screen. In that
-               case, reset the count or else USB would be locked out until
-               rebooting because it most likely won't ever come. Simply
-               resetting to the most recent broadcast count is racy. */
-            if(TIME_AFTER(current_tick, last_broadcast_tick + HZ*5))
-            {
-                num_acks_to_expect = 0;
-                last_broadcast_tick = current_tick;
-            }
-
-            num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1;
-            DEBUGF("usb: waiting for %d acks...\n", num_acks_to_expect);
-
-            /* Leave the state as USB_POWERED until the expected number of
-               ACKS are received. */
-            break;
-            /* USB_INSERTED: or USB_HOSTED: */
-
         case SYS_USB_CONNECTED_ACK:
-            if(num_acks_to_expect > 0 && --num_acks_to_expect == 0)
-            {
-                DEBUGF("usb: all threads have acknowledged the connect.\n");
-                if(host_detected)
-                {
-                    usb_slave_mode(true);
-                    usb_state = USB_INSERTED;
-                }
-            }
-            else
-            {
-                DEBUGF("usb: got ack, %d to go...\n", num_acks_to_expect);
-            }
+            if(usb_handle_connected_ack())
+                usb_state = USB_INSERTED;
             break;
             /* SYS_USB_CONNECTED_ACK */
 
@@ -472,13 +485,7 @@
 
             usb_state = USB_EXTRACTED;
 
-            if(host_detected)
-            {
-                /* Ok to broadcast disconnect now */
-                usb_configure_drivers(USB_EXTRACTED);
-                host_detected = false;
-            }
-
+            usb_set_host_present(false);
             break;
             /* USB_EXTRACTED: */
 
@@ -532,8 +539,7 @@
 {
     /* Caller isn't expected to filter for changes in status.
      * current_status:
-     *   all:                USB_INSERTED, USB_EXTRACTED
-     *   USB_DETECT_BY_CORE: USB_HOSTED (from core)
+     *   USB_INSERTED, USB_EXTRACTED
      */
     if(usb_monitor_enabled)
     {
@@ -554,10 +560,6 @@
     /* An event may have been missed because it was sent before monitoring
      * was enabled due to the connector already having been inserted before
      * before or during boot. */
-#ifdef USB_DETECT_BY_CORE
-    /* Filter the status - USB_HOSTED may happen later */
-    status = (status == USB_INSERTED) ? : USB_EXTRACTED;
-#endif
     usb_status_event(status);
 
 #ifdef USB_FIREWIRE_HANDLING
