1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Björn Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "gcc_extensions.h"
34 #include "filetypes.h"
39 #include "powermgmt.h"
46 #include "mp3_playback.h"
49 #include "backlight.h"
51 #include "debug_menu.h"
56 #include "core_alloc.h"
59 #include "usb_screen.h"
72 #include "eeprom_settings.h"
73 #include "scrobbler.h"
76 #include "skin_engine/skin_engine.h"
77 #include "statusbar-skinned.h"
78 #include "bootchart.h"
79 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
80 #include "notification.h"
82 #include "shortcuts.h"
84 #ifdef IPOD_ACCESSORY_PROTOCOL
88 #if (CONFIG_CODEC == SWCODEC)
92 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
93 #include "pcm_record.h"
97 #define SETTINGS_RESET BUTTON_REC
98 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
99 #define SETTINGS_RESET BUTTON_A
105 #if (CONFIG_STORAGE & STORAGE_MMC)
109 #ifdef HAVE_REMOTE_LCD
110 #include "lcd-remote.h"
113 #if CONFIG_USBOTG == USBOTG_ISP1362
117 #if CONFIG_USBOTG == USBOTG_M5636
121 #ifdef HAVE_HARDWARE_CLICK
125 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
126 #define MAIN_NORETURN_ATTR NORETURN_ATTR
128 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
129 * with noreturn attribute */
130 #define MAIN_NORETURN_ATTR
133 #if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
135 #include "sim_tasks.h"
137 #include "system-sdl.h"
138 #define HAVE_ARGV_MAIN
139 /* Don't use SDL_main on windows -> no more stdio redirection */
145 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
147 static void init(void);
148 /* main(), and various functions called by main() and init() may be
149 * be INIT_ATTR. These functions must not be called after the final call
150 * to root_menu() at the end of main()
151 * see definition of INIT_ATTR in config.h */
152 #ifdef HAVE_ARGV_MAIN
153 int main(int argc
, char *argv
[]) INIT_ATTR MAIN_NORETURN_ATTR
;
154 int main(int argc
, char *argv
[])
156 sys_handle_argv(argc
, argv
);
158 int main(void) INIT_ATTR MAIN_NORETURN_ATTR
;
167 screens
[i
].clear_display();
170 #ifdef HAVE_LCD_BITMAP
174 /* Keep the order of this 3
175 * Must be done before any code uses the multi-screen API */
177 /* All threads should be created and public queues registered by now */
178 usb_start_monitoring();
183 char filename
[MAX_PATH
];
191 if(file_exists(file
)) /* no complaint if it doesn't exist */
193 plugin_load(file
, NULL
); /* start if it does */
196 #endif /* #ifdef AUTOROCK */
198 global_status
.last_volume_change
= 0;
199 /* no calls INIT_ATTR functions after this point anymore!
200 * see definition of INIT_ATTR in config.h */
205 static int init_dircache(bool preinit
) INIT_ATTR
;
206 static int init_dircache(bool preinit
)
215 if (!global_settings
.dircache
)
218 # ifdef HAVE_EEPROM_SETTINGS
219 if (firmware_settings
.initialized
&& firmware_settings
.disk_clean
222 result
= dircache_load();
226 firmware_settings
.disk_clean
= false;
227 if (global_status
.dircache_size
<= 0)
229 /* This will be in default language, settings are not
230 applied yet. Not really any easy way to fix that. */
231 splash(0, str(LANG_SCANNING_DISK
));
235 dircache_build(global_status
.dircache_size
);
244 if (!dircache_is_enabled()
245 && !dircache_is_initializing())
247 if (global_status
.dircache_size
<= 0)
249 splash(0, str(LANG_SCANNING_DISK
));
252 result
= dircache_build(global_status
.dircache_size
);
257 /* Initialization of dircache failed. Manual action is
258 * necessary to enable dircache again.
260 splashf(0, "Dircache failed, disabled. Result: %d", result
);
261 global_settings
.dircache
= false;
269 global_status
.dircache_size
= dircache_get_cache_size();
281 static void init_tagcache(void) INIT_ATTR
;
282 static void init_tagcache(void)
285 #if CONFIG_CODEC == SWCODEC
286 long talked_tick
= 0;
290 while (!tagcache_is_initialized())
292 int ret
= tagcache_get_commit_step();
296 #if CONFIG_CODEC == SWCODEC
297 /* hwcodec can't use voice here, as the database commit
298 * uses the audio buffer. */
299 if(global_settings
.talk_menu
301 || TIME_AFTER(current_tick
, talked_tick
+7*HZ
)))
303 talked_tick
= current_tick
;
304 talk_id(LANG_TAGCACHE_INIT
, false);
305 talk_number(ret
, true);
306 talk_id(VOICE_OF
, true);
307 talk_number(tagcache_get_max_commit_step(), true);
310 #ifdef HAVE_LCD_BITMAP
313 splashf(0, "[%d/%d] %s", ret
, tagcache_get_max_commit_step(),
314 str(LANG_TAGCACHE_INIT
));
318 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT
), ret
,
319 tagcache_get_max_commit_step());
322 lcd_double_height(false);
323 lcd_putsf(0, 1, " DB [%d/%d]", ret
,
324 tagcache_get_max_commit_step());
341 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
343 static void init(void)
346 core_allocator_init();
353 #ifdef HAVE_REMOTE_LCD
356 #ifdef HAVE_LCD_BITMAP
358 global_status
.font_id
[i
] = FONT_SYSFIXED
;
368 #if (CONFIG_PLATFORM & PLATFORM_ANDROID)
371 lang_init(core_language_builtin
, language_strings
,
372 LANG_LAST_INDEX_IN_ARRAY
);
376 /* Keep the order of this 3 (viewportmanager handles statusbars)
377 * Must be done before any code uses the multi-screen API */
378 gui_syncstatusbar_init(&statusbars
);
379 gui_sync_skin_init();
381 viewportmanager_init();
385 settings_load(SETTINGS_ALL
);
386 settings_apply(true);
388 init_dircache(false);
398 #if CONFIG_CODEC != SWCODEC
399 mp3_init( global_settings
.volume
,
400 global_settings
.bass
,
401 global_settings
.treble
,
402 global_settings
.balance
,
403 global_settings
.loudness
,
405 global_settings
.channel_config
,
406 global_settings
.stereo_width
,
407 global_settings
.mdb_strength
,
408 global_settings
.mdb_harmonics
,
409 global_settings
.mdb_center
,
410 global_settings
.mdb_shape
,
411 global_settings
.mdb_enable
,
412 global_settings
.superbass
);
413 #endif /* CONFIG_CODEC != SWCODEC */
419 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING)
423 settings_apply_skins();
428 static void init(void) INIT_ATTR
;
429 static void init(void)
432 bool mounted
= false;
433 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
434 /* if nobody initialized ATA before, I consider this a cold start */
435 bool coldstart
= (PACR2
& 0x4000) != 0; /* starting from Flash */
439 core_allocator_init();
442 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
443 set_cpu_frequency(CPUFREQ_NORMAL
);
445 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS
);
458 /* current_tick should be ticking by now */
462 #ifdef HAVE_REMOTE_LCD
465 #ifdef HAVE_LCD_BITMAP
467 global_status
.font_id
[i
] = FONT_SYSFIXED
;
476 lang_init(core_language_builtin
, language_strings
,
477 LANG_LAST_INDEX_IN_ARRAY
);
491 CHART(">settings_load(RTC)");
492 settings_load(SETTINGS_RTC
); /* early load parts of global_settings */
493 CHART("<settings_load(RTC)");
499 #if CONFIG_USBOTG == USBOTG_ISP1362
501 #elif CONFIG_USBOTG == USBOTG_M5636
509 /* Don't initialize power management here if it could incorrectly
510 * measure battery voltage, and it's not needed for charging. */
511 #if !defined(NEED_ATA_POWER_BATT_MEASURE) || \
512 (CONFIG_CHARGING > CHARGING_MONITOR)
520 #ifdef HAVE_HARDWARE_CLICK
524 /* Keep the order of this 3 (viewportmanager handles statusbars)
525 * Must be done before any code uses the multi-screen API */
526 CHART(">gui_syncstatusbar_init");
527 gui_syncstatusbar_init(&statusbars
);
528 CHART("<gui_syncstatusbar_init");
529 CHART(">sb_skin_init");
531 CHART("<sb_skin_init");
532 CHART(">gui_sync_wps_init");
533 gui_sync_skin_init();
534 CHART("<gui_sync_wps_init");
535 CHART(">viewportmanager_init");
536 viewportmanager_init();
537 CHART("<viewportmanager_init");
539 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
540 /* charger_inserted() can't be used here because power_thread()
541 hasn't checked power_input_status() yet */
542 if (coldstart
&& (power_input_status() & POWER_INPUT_MAIN_CHARGER
)
543 && !global_settings
.car_adapter_mode
544 #ifdef ATA_POWER_PLAYERSTYLE
545 && !ide_powered() /* relies on probing result from bootloader */
549 rc
= charging_screen(); /* display a "charging" screen */
550 if (rc
== 1) /* charger removed */
552 /* "On" pressed or USB connected: proceed */
553 show_logo(); /* again, to provide better visual feedback */
558 disk_init_subsystem();
559 CHART(">storage_init");
561 CHART("<storage_init");
564 #ifdef HAVE_LCD_BITMAP
566 lcd_putsf(0, 1, "ATA error: %d", rc
);
567 lcd_puts(0, 3, "Press ON to debug");
569 while(!(button_get(true) & BUTTON_REL
)); /* DO NOT CHANGE TO ACTION SYSTEM */
572 panicf("ata: %d", rc
);
575 #if defined(NEED_ATA_POWER_BATT_MEASURE) && \
576 (CONFIG_CHARGING <= CHARGING_MONITOR)
577 /* After storage_init(), ATA power must be on, so battery voltage
578 * can be measured. Initialize power management if it was delayed. */
581 #ifdef HAVE_EEPROM_SETTINGS
582 CHART(">eeprom_settings_init");
583 eeprom_settings_init();
584 CHART("<eeprom_settings_init");
587 #ifndef HAVE_USBSTACK
588 usb_start_monitoring();
589 while (usb_detect() == USB_INSERTED
)
591 #ifdef HAVE_EEPROM_SETTINGS
592 firmware_settings
.disk_clean
= false;
594 /* enter USB mode early, before trying to mount */
595 if (button_get_w_tmo(HZ
/10) == SYS_USB_CONNECTED
)
596 #if (CONFIG_STORAGE & STORAGE_MMC)
597 if (!mmc_touched() ||
598 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED
))
601 gui_usb_screen_run(true);
602 mounted
= true; /* mounting done @ end of USB mode */
604 #ifdef HAVE_USB_POWER
605 if (usb_powered()) /* avoid deadlock */
613 CHART(">disk_mount_all");
614 rc
= disk_mount_all();
615 CHART("<disk_mount_all");
619 lcd_puts(0, 0, "No partition");
620 lcd_puts(0, 1, "found.");
621 #ifdef HAVE_LCD_BITMAP
622 lcd_puts(0, 2, "Insert USB cable");
623 lcd_puts(0, 3, "and fix it.");
627 while(button_get(true) != SYS_USB_CONNECTED
) {};
628 gui_usb_screen_run(true);
633 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
634 (CONFIG_KEYPAD == IRIVER_H10_PAD)
635 #ifdef SETTINGS_RESET
636 /* Reset settings if holding the reset button. (Rec on Archos,
638 if ((button_status() & SETTINGS_RESET
) == SETTINGS_RESET
)
640 /* Reset settings if the hold button is turned on */
644 splash(HZ
*2, str(LANG_RESET_DONE_CLEAR
));
650 CHART(">settings_load(ALL)");
651 settings_load(SETTINGS_ALL
);
652 CHART("<settings_load(ALL)");
655 CHART(">init_dircache(true)");
656 rc
= init_dircache(true);
657 CHART("<init_dircache(true)");
661 remove(TAGCACHE_STATEFILE
);
665 CHART(">settings_apply(true)");
666 settings_apply(true);
667 CHART("<settings_apply(true)");
668 CHART(">init_dircache(false)");
669 init_dircache(false);
670 CHART("<init_dircache(false)");
672 CHART(">init_tagcache");
674 CHART("<init_tagcache");
677 #ifdef HAVE_EEPROM_SETTINGS
678 if (firmware_settings
.initialized
)
680 /* In case we crash. */
681 firmware_settings
.disk_clean
= false;
682 CHART(">eeprom_settings_store");
683 eeprom_settings_store();
684 CHART("<eeprom_settings_store");
693 #if CONFIG_CODEC != SWCODEC
694 /* No buffer allocation (see buffer.c) may take place after the call to
695 audio_init() since the mpeg thread takes the rest of the buffer space */
696 mp3_init( global_settings
.volume
,
697 global_settings
.bass
,
698 global_settings
.treble
,
699 global_settings
.balance
,
700 global_settings
.loudness
,
702 global_settings
.channel_config
,
703 global_settings
.stereo_width
,
704 global_settings
.mdb_strength
,
705 global_settings
.mdb_harmonics
,
706 global_settings
.mdb_center
,
707 global_settings
.mdb_shape
,
708 global_settings
.mdb_enable
,
709 global_settings
.superbass
);
710 #endif /* CONFIG_CODEC != SWCODEC */
712 CHART(">audio_init");
714 CHART("<audio_init");
716 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING)
720 /* runtime database has to be initialized after audio_init() */
724 car_adapter_mode_init();
726 #ifdef IPOD_ACCESSORY_PROTOCOL
727 iap_setup(global_settings
.serial_bitrate
);
729 #ifdef HAVE_ACCESSORY_SUPPLY
730 accessory_supply_set(global_settings
.accessory_supply
);
732 #ifdef HAVE_LINEOUT_POWEROFF
733 lineout_set(global_settings
.lineout_active
);
735 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
736 CHART("<check_bootfile(false)");
737 check_bootfile(false); /* remember write time and filesize */
738 CHART(">check_bootfile(false)");
740 CHART("<settings_apply_skins");
741 settings_apply_skins();
742 CHART(">settings_apply_skins");
746 void cop_main(void) MAIN_NORETURN_ATTR
;
749 /* This is the entry point for the coprocessor
750 Anyone not running an upgraded bootloader will never reach this point,
751 so it should not be assumed that the coprocessor be usable even on
752 platforms which support it.
754 A kernel thread is initially setup on the coprocessor and immediately
755 destroyed for purposes of continuity. The cop sits idle until at least
756 one thread exists on it. */
761 /* This should never be reached */
769 #endif /* SIMULATOR */