Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2009 by Jens Arnold |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 11 | * Copyright (C) 2011 by Thomas Martitz |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 12 | * |
| 13 | * Rockbox simulator specific tasks |
| 14 | * |
| 15 | * This program is free software; you can redistribute it and/or |
| 16 | * modify it under the terms of the GNU General Public License |
| 17 | * as published by the Free Software Foundation; either version 2 |
| 18 | * of the License, or (at your option) any later version. |
| 19 | * |
| 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 21 | * KIND, either express or implied. |
| 22 | * |
| 23 | ****************************************************************************/ |
| 24 | |
| 25 | #include "config.h" |
| 26 | #include "kernel.h" |
| 27 | #include "screendump.h" |
| 28 | #include "thread.h" |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 29 | #include "debug.h" |
| 30 | #include "usb.h" |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 31 | #include "mv.h" |
| 32 | #include "ata_idle_notify.h" |
| 33 | #ifdef WIN32 |
| 34 | #include <windows.h> |
| 35 | #endif |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 36 | |
| 37 | static void sim_thread(void); |
| 38 | static long sim_thread_stack[DEFAULT_STACK_SIZE/sizeof(long)]; |
| 39 | /* stack isn't actually used in the sim */ |
| 40 | static const char sim_thread_name[] = "sim"; |
| 41 | static struct event_queue sim_queue; |
| 42 | |
| 43 | /* possible events for the sim thread */ |
| 44 | enum { |
| 45 | SIM_SCREENDUMP, |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 46 | SIM_USB_INSERTED, |
| 47 | SIM_USB_EXTRACTED, |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 48 | #ifdef HAVE_MULTIDRIVE |
| 49 | SIM_EXT_INSERTED, |
| 50 | SIM_EXT_EXTRACTED, |
| 51 | #endif |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 52 | }; |
| 53 | |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 54 | #ifdef HAVE_MULTIDRIVE |
| 55 | extern void sim_ext_extracted(int drive); |
| 56 | #endif |
| 57 | |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 58 | void sim_thread(void) |
| 59 | { |
| 60 | struct queue_event ev; |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 61 | long last_broadcast_tick = current_tick; |
Thomas Martitz | e720ad0 | 2012-01-22 20:41:15 +0100 | [diff] [blame] | 62 | int num_acks_to_expect = 0; |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 63 | |
| 64 | while (1) |
| 65 | { |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 66 | queue_wait_w_tmo(&sim_queue, &ev, 5*HZ); |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 67 | switch(ev.id) |
| 68 | { |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 69 | case SYS_TIMEOUT: |
| 70 | call_storage_idle_notifys(false); |
| 71 | break; |
| 72 | |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 73 | case SIM_SCREENDUMP: |
| 74 | screen_dump(); |
| 75 | #ifdef HAVE_REMOTE_LCD |
| 76 | remote_screen_dump(); |
| 77 | #endif |
| 78 | break; |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 79 | case SIM_USB_INSERTED: |
| 80 | /* from firmware/usb.c: */ |
| 81 | /* Tell all threads that they have to back off the storage. |
| 82 | We subtract one for our own thread. Expect an ACK for every |
| 83 | listener for each broadcast they received. If it has been too |
| 84 | long, the user might have entered a screen that didn't ACK |
| 85 | when inserting the cable, such as a debugging screen. In that |
| 86 | case, reset the count or else USB would be locked out until |
| 87 | rebooting because it most likely won't ever come. Simply |
| 88 | resetting to the most recent broadcast count is racy. */ |
| 89 | if(TIME_AFTER(current_tick, last_broadcast_tick + HZ*5)) |
| 90 | { |
| 91 | num_acks_to_expect = 0; |
| 92 | last_broadcast_tick = current_tick; |
| 93 | } |
| 94 | |
| 95 | num_acks_to_expect += queue_broadcast(SYS_USB_CONNECTED, 0) - 1; |
| 96 | DEBUGF("USB inserted. Waiting for %d acks...\n", |
| 97 | num_acks_to_expect); |
| 98 | break; |
| 99 | case SYS_USB_CONNECTED_ACK: |
| 100 | if(num_acks_to_expect > 0 && --num_acks_to_expect == 0) |
| 101 | { |
| 102 | DEBUGF("All threads have acknowledged the connect.\n"); |
| 103 | } |
| 104 | else |
| 105 | { |
| 106 | DEBUGF("usb: got ack, %d to go...\n", |
| 107 | num_acks_to_expect); |
| 108 | } |
| 109 | break; |
| 110 | case SIM_USB_EXTRACTED: |
| 111 | /* in usb.c, this is only done for exclusive storage |
| 112 | * do it here anyway but don't depend on the acks */ |
| 113 | queue_broadcast(SYS_USB_DISCONNECTED, 0); |
| 114 | break; |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 115 | #ifdef HAVE_MULTIDRIVE |
| 116 | case SIM_EXT_INSERTED: |
| 117 | case SIM_EXT_EXTRACTED: |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 118 | sim_ext_extracted(ev.data); |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 119 | queue_broadcast(ev.id == SIM_EXT_INSERTED ? |
| 120 | SYS_HOTSWAP_INSERTED : SYS_HOTSWAP_EXTRACTED, 0); |
| 121 | sleep(HZ/20); |
| 122 | queue_broadcast(SYS_FS_CHANGED, 0); |
| 123 | break; |
| 124 | #endif /* HAVE_MULTIDRIVE */ |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 125 | default: |
| 126 | DEBUGF("sim_tasks: unhandled event: %ld\n", ev.id); |
| 127 | break; |
Jens Arnold | 3e67e3b | 2009-02-20 17:13:08 +0000 | [diff] [blame] | 128 | } |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | void sim_tasks_init(void) |
| 133 | { |
| 134 | queue_init(&sim_queue, false); |
| 135 | |
| 136 | create_thread(sim_thread, sim_thread_stack, sizeof(sim_thread_stack), 0, |
| 137 | sim_thread_name IF_PRIO(,PRIORITY_BACKGROUND) IF_COP(,CPU)); |
| 138 | } |
| 139 | |
| 140 | void sim_trigger_screendump(void) |
| 141 | { |
| 142 | queue_post(&sim_queue, SIM_SCREENDUMP, 0); |
| 143 | } |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 144 | |
| 145 | static bool is_usb_inserted; |
| 146 | void sim_trigger_usb(bool inserted) |
| 147 | { |
| 148 | if (inserted) |
| 149 | queue_post(&sim_queue, SIM_USB_INSERTED, 0); |
| 150 | else |
| 151 | queue_post(&sim_queue, SIM_USB_EXTRACTED, 0); |
| 152 | is_usb_inserted = inserted; |
| 153 | } |
| 154 | |
| 155 | int usb_detect(void) |
| 156 | { |
| 157 | return is_usb_inserted ? USB_INSERTED : USB_EXTRACTED; |
| 158 | } |
| 159 | |
| 160 | void usb_init(void) |
| 161 | { |
| 162 | } |
| 163 | |
| 164 | void usb_start_monitoring(void) |
| 165 | { |
| 166 | } |
| 167 | |
| 168 | void usb_acknowledge(long id) |
| 169 | { |
| 170 | queue_post(&sim_queue, id, 0); |
| 171 | } |
| 172 | |
| 173 | void usb_wait_for_disconnect(struct event_queue *q) |
| 174 | { |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 175 | struct queue_event ev; |
| 176 | |
| 177 | /* Don't return until we get SYS_USB_DISCONNECTED */ |
| 178 | while(1) |
| 179 | { |
| 180 | queue_wait(q, &ev); |
| 181 | if(ev.id == SYS_USB_DISCONNECTED) |
| 182 | return; |
| 183 | } |
Thomas Martitz | 1645c14 | 2011-11-17 18:40:00 +0000 | [diff] [blame] | 184 | } |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 185 | |
| 186 | #ifdef HAVE_MULTIDRIVE |
| 187 | static bool is_ext_inserted; |
| 188 | |
| 189 | void sim_trigger_external(bool inserted) |
| 190 | { |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 191 | is_ext_inserted = inserted; |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 192 | |
| 193 | int drive = 1; /* Can do others! */ |
| 194 | if (inserted) |
| 195 | queue_post(&sim_queue, SIM_EXT_INSERTED, drive); |
| 196 | else |
| 197 | queue_post(&sim_queue, SIM_EXT_EXTRACTED, drive); |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 198 | } |
| 199 | |
| 200 | bool hostfs_present(int drive) |
| 201 | { |
| 202 | return drive > 0 ? is_ext_inserted : true; |
| 203 | } |
| 204 | |
| 205 | bool hostfs_removable(int drive) |
| 206 | { |
| 207 | return drive > 0; |
| 208 | } |
| 209 | |
| 210 | #ifdef HAVE_MULTIVOLUME |
| 211 | bool volume_removable(int volume) |
| 212 | { |
| 213 | /* volume == drive for now */ |
| 214 | return hostfs_removable(volume); |
| 215 | } |
| 216 | |
| 217 | bool volume_present(int volume) |
| 218 | { |
| 219 | /* volume == drive for now */ |
| 220 | return hostfs_present(volume); |
| 221 | } |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 222 | |
| 223 | int volume_drive(int volume) |
| 224 | { |
| 225 | /* volume == drive for now */ |
| 226 | return volume; |
| 227 | } |
| 228 | #endif /* HAVE_MULTIVOLUME */ |
Thomas Martitz | facbaab | 2014-02-21 11:25:07 +0100 | [diff] [blame] | 229 | |
| 230 | #if (CONFIG_STORAGE & STORAGE_MMC) |
| 231 | bool mmc_touched(void) |
| 232 | { |
| 233 | return hostfs_present(1); |
| 234 | } |
| 235 | #endif |
| 236 | |
Michael Sevakis | da4938d | 2014-08-30 01:08:34 -0400 | [diff] [blame] | 237 | #ifdef CONFIG_STORAGE_MULTI |
| 238 | int hostfs_driver_type(int drive) |
| 239 | { |
| 240 | /* Hack alert */ |
| 241 | #if (CONFIG_STORAGE & STORAGE_ATA) |
| 242 | #define SIMEXT1_TYPE_NUM STORAGE_ATA_NUM |
| 243 | #elif (CONFIG_STORAGE & STORAGE_SD) |
| 244 | #define SIMEXT1_TYPE_NUM STORAGE_SD_NUM |
| 245 | #elif (CONFIG_STORAGE & STORAGE_MMC) |
| 246 | #define SIMEXT1_TYPE_NUM STORAGE_MMC_NUM |
| 247 | #elif (CONFIG_STORAGE & STORAGE_NAND) |
| 248 | #define SIMEXT1_TYPE_NUM STORAGE_NAND_NUM |
| 249 | #elif (CONFIG_STORAGE & STORAGE_RAMDISK) |
| 250 | #define SIMEXT1_TYPE_NUM STORAGE_RAMDISK_NUM |
| 251 | #else |
| 252 | #error Unknown storage driver |
| 253 | #endif /* CONFIG_STORAGE */ |
| 254 | |
| 255 | return drive > 0 ? SIMEXT1_TYPE_NUM : STORAGE_HOSTFS_NUM; |
| 256 | } |
| 257 | #endif /* CONFIG_STORAGE_MULTI */ |
| 258 | |
Michael Sevakis | 7d1a47c | 2013-08-05 22:02:45 -0400 | [diff] [blame] | 259 | #endif /* CONFIG_STORAGE & STORAGE_MMC */ |