summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBjörn Stenberg <bjorn@haxx.se>2007-11-23 15:02:26 +0000
committerBjörn Stenberg <bjorn@haxx.se>2007-11-23 15:02:26 +0000
commit20dbc1b21f38c6caad13de485c68444c752380fc (patch)
treec8741e05cd054e4642cb2277a8bcdf8bd775601d
parentf7f7967943b273b6c9b8212df1db9c3713ece013 (diff)
Re-added USB charger detection and auto reboot on host connect.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@15774 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/export/usb_core.h1
-rw-r--r--firmware/target/arm/usb-fw-pp502x.c110
-rw-r--r--firmware/usbstack/usb_core.c12
3 files changed, 110 insertions, 13 deletions
diff --git a/firmware/export/usb_core.h b/firmware/export/usb_core.h
index be3e4789d9..2027cca5e8 100644
--- a/firmware/export/usb_core.h
+++ b/firmware/export/usb_core.h
@@ -50,6 +50,7 @@ void usb_core_exit(void);
void usb_core_control_request(struct usb_ctrlrequest* req);
void usb_core_transfer_complete(int endpoint, bool in);
void usb_core_bus_reset(void);
+bool usb_core_data_connection(void);
#endif
diff --git a/firmware/target/arm/usb-fw-pp502x.c b/firmware/target/arm/usb-fw-pp502x.c
index cff3089ae0..768368d575 100644
--- a/firmware/target/arm/usb-fw-pp502x.c
+++ b/firmware/target/arm/usb-fw-pp502x.c
@@ -56,34 +56,118 @@ void usb_init_device(void)
void usb_enable(bool on)
{
- if (on)
- usb_core_init();
+ if (on) {
+ /* until we have native mass-storage mode, we want to reboot on
+ usb host connect */
+#if defined(IRIVER_H10) || defined (IRIVER_H10_5GB)
+ if (button_status()==BUTTON_RIGHT)
+#endif /* defined(IRIVER_H10) || defined (IRIVER_H10_5GB) */
+ {
+#ifndef HAVE_FLASH_STORAGE
+ ata_sleepnow(); /* Immediately spindown the disk. */
+ sleep(HZ*2);
+#endif
+
+#ifdef IPOD_ARCH /* The following code is based on ipodlinux */
+#if CONFIG_CPU == PP5020
+ memcpy((void *)0x40017f00, "diskmode\0\0hotstuff\0\0\1", 21);
+#elif CONFIG_CPU == PP5022
+ memcpy((void *)0x4001ff00, "diskmode\0\0hotstuff\0\0\1", 21);
+#endif /* CONFIG_CPU */
+#endif /* IPOD_ARCH */
+
+ system_reboot(); /* Reboot */
+ }
+ }
else
usb_core_exit();
}
-int usb_detect(void)
+bool usb_pin_detect(void)
{
-#if defined(IPOD_COLOR) || defined(IPOD_4G) \
- || defined(IPOD_MINI) || defined(IPOD_MINI2G)
- /* GPIO C bit 1 is firewire detect */
- if (!(GPIOC_INPUT_VAL & 0x02))
- return USB_INSERTED;
+#if defined(IPOD_ARCH)
+ /* GPIO L bit 4 is usb detect */
+ if (GPIOL_INPUT_VAL & 0x10)
+ return true;
+
#elif defined(SANSA_C200)
/* GPIO H bit 1 is usb detect */
if (GPIOH_INPUT_VAL & 0x02)
- return USB_INSERTED;
+ return true;
+
#elif defined(SANSA_E200)
/* GPIO B bit 4 is usb detect */
if (GPIOB_INPUT_VAL & 0x10)
- return USB_INSERTED;
+ return true;
+
#elif defined(IRIVER_H10) || defined(IRIVER_H10_5GB)
/* GPIO L bit 2 is usb detect */
if (GPIOL_INPUT_VAL & 0x4)
- return USB_INSERTED;
+ return true;
#endif
- if (usb_drv_powered())
+ return false;
+}
+
+/* detect host or charger (INSERTED or POWERED) */
+int usb_detect(void)
+{
+ static int countdown = 0;
+ static int status = USB_EXTRACTED;
+ static bool prev_usbstatus1 = false;
+ bool usbstatus1, usbstatus2;
+
+#if defined(IPOD_COLOR) || defined(IPOD_4G) \
+ || defined(IPOD_MINI) || defined(IPOD_MINI2G)
+ /* GPIO C bit 1 is firewire detect */
+ if (!(GPIOC_INPUT_VAL & 0x02))
+ /* no charger detection needed for firewire */
return USB_INSERTED;
+#endif
+
+ if (countdown > 0)
+ {
+ countdown--;
+
+ usbstatus2 = usb_core_data_connection();
+ if ((countdown == 0) || usbstatus2)
+ {
+ /* We now know that we have been connected to either a charger
+ or a computer */
+ countdown = 0;
+ status = usbstatus2 ? USB_INSERTED : USB_POWERED;
+ }
+ return status;
+ }
+
+ usbstatus1 = usb_pin_detect();
+
+ if (usbstatus1 == prev_usbstatus1)
+ {
+ /* Nothing has changed, so just return previous status */
+ return status;
+ }
+ prev_usbstatus1 = usbstatus1;
+
+ if (!usbstatus1)
+ { /* We have just been disconnected */
+ status = USB_EXTRACTED;
+ return status;
+ }
+
+ /* Run the USB stack to request full bus power */
+ usb_core_init();
+
+ if((button_status() & ~USBPOWER_BTN_IGNORE) == USBPOWER_BUTTON)
+ {
+ /* The user wants to charge, so it doesn't matter what we are
+ connected to. */
+ status = USB_POWERED;
+ return status;
+ }
+
+ /* Wait up to 50 ticks (500ms) before deciding there is no computer
+ attached. */
+ countdown = 50;
- return USB_EXTRACTED;
+ return status;
}
diff --git a/firmware/usbstack/usb_core.c b/firmware/usbstack/usb_core.c
index 7f610ff83a..8e71c77ed7 100644
--- a/firmware/usbstack/usb_core.c
+++ b/firmware/usbstack/usb_core.c
@@ -292,6 +292,7 @@ static const struct {
static int usb_address = 0;
static bool initialized = false;
+static bool data_connection = false;
static struct event_queue usbcore_queue;
#ifdef USB_STORAGE
@@ -305,6 +306,9 @@ static void ack_control(struct usb_ctrlrequest* req);
void usb_core_init(void)
{
+ if (initialized)
+ return;
+
queue_init(&usbcore_queue, false);
usb_drv_init();
#ifdef USB_STORAGE
@@ -331,10 +335,16 @@ void usb_core_exit(void)
#ifdef USB_STORAGE
remove_thread(usbcore_thread);
#endif
+ data_connection = false;
}
logf("usb_core_exit() finished");
}
+bool usb_core_data_connection(void)
+{
+ return data_connection;
+}
+
#ifdef USB_STORAGE
void usb_core_thread(void)
{
@@ -352,6 +362,7 @@ void usb_core_thread(void)
void usb_core_control_request(struct usb_ctrlrequest* req)
{
/* note: interrupt context */
+ data_connection = true;
#ifdef USB_BENCHMARK
if ((req->bRequestType & 0x60) == USB_TYPE_VENDOR) {
@@ -499,6 +510,7 @@ void usb_core_control_request(struct usb_ctrlrequest* req)
void usb_core_bus_reset(void)
{
usb_address = 0;
+ data_connection = false;
}
/* called by usb_drv_transfer_completed() */