diff options
author | Björn Stenberg <bjorn@haxx.se> | 2007-11-23 15:02:26 +0000 |
---|---|---|
committer | Björn Stenberg <bjorn@haxx.se> | 2007-11-23 15:02:26 +0000 |
commit | 20dbc1b21f38c6caad13de485c68444c752380fc (patch) | |
tree | c8741e05cd054e4642cb2277a8bcdf8bd775601d | |
parent | f7f7967943b273b6c9b8212df1db9c3713ece013 (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.h | 1 | ||||
-rw-r--r-- | firmware/target/arm/usb-fw-pp502x.c | 110 | ||||
-rw-r--r-- | firmware/usbstack/usb_core.c | 12 |
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() */ |