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"
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"
80 #ifdef IPOD_ACCESSORY_PROTOCOL
84 #if (CONFIG_CODEC == SWCODEC)
88 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
89 #include "pcm_record.h"
93 #define SETTINGS_RESET BUTTON_REC
94 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
95 #define SETTINGS_RESET BUTTON_A
101 #if (CONFIG_STORAGE & STORAGE_MMC)
105 #ifdef HAVE_REMOTE_LCD
106 #include "lcd-remote.h"
109 #if CONFIG_USBOTG == USBOTG_ISP1362
113 #if CONFIG_USBOTG == USBOTG_M5636
117 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
118 #define MAIN_NORETURN_ATTR NORETURN_ATTR
120 /* gcc adds an implicit 'return 0;' at the end of main(), causing a warning
121 * with noreturn attribute */
122 #define MAIN_NORETURN_ATTR
125 #if (CONFIG_PLATFORM & PLATFORM_SDL)
126 #include "sim_tasks.h"
127 #include "system-sdl.h"
128 #define HAVE_ARGV_MAIN
129 /* Don't use SDL_main on windows -> no more stdio redirection */
135 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
137 static void init(void);
138 /* main(), and various functions called by main() and init() may be
139 * be INIT_ATTR. These functions must not be called after the final call
140 * to root_menu() at the end of main()
141 * see definition of INIT_ATTR in config.h */
142 #ifdef HAVE_ARGV_MAIN
143 int main(int argc
, char *argv
[]) INIT_ATTR MAIN_NORETURN_ATTR
;
144 int main(int argc
, char *argv
[])
146 sys_handle_argv(argc
, argv
);
148 int main(void) INIT_ATTR MAIN_NORETURN_ATTR
;
158 screens
[i
].clear_display();
161 #ifdef HAVE_LCD_BITMAP
165 /* Keep the order of this 3
166 * Must be done before any code uses the multi-screen API */
168 /* All threads should be created and public queues registered by now */
169 usb_start_monitoring();
174 char filename
[MAX_PATH
];
175 const char *file
= get_user_file_path(
181 "/autostart.rock", NEED_WRITE
|IS_FILE
, filename
, sizeof(filename
));
182 if(file_exists(file
)) /* no complaint if it doesn't exist */
184 plugin_load(file
, NULL
); /* start if it does */
187 #endif /* #ifdef AUTOROCK */
189 global_status
.last_volume_change
= 0;
190 /* no calls INIT_ATTR functions after this point anymore!
191 * see definition of INIT_ATTR in config.h */
196 static int init_dircache(bool preinit
) INIT_ATTR
;
197 static int init_dircache(bool preinit
)
206 if (!global_settings
.dircache
)
209 # ifdef HAVE_EEPROM_SETTINGS
210 if (firmware_settings
.initialized
&& firmware_settings
.disk_clean
213 result
= dircache_load();
217 firmware_settings
.disk_clean
= false;
218 if (global_status
.dircache_size
<= 0)
220 /* This will be in default language, settings are not
221 applied yet. Not really any easy way to fix that. */
222 splash(0, str(LANG_SCANNING_DISK
));
226 dircache_build(global_status
.dircache_size
);
235 if (!dircache_is_enabled()
236 && !dircache_is_initializing())
238 if (global_status
.dircache_size
<= 0)
240 splash(0, str(LANG_SCANNING_DISK
));
243 result
= dircache_build(global_status
.dircache_size
);
248 /* Initialization of dircache failed. Manual action is
249 * necessary to enable dircache again.
251 splashf(0, "Dircache failed, disabled. Result: %d", result
);
252 global_settings
.dircache
= false;
260 global_status
.dircache_size
= dircache_get_cache_size();
272 static void init_tagcache(void) INIT_ATTR
;
273 static void init_tagcache(void)
276 #if CONFIG_CODEC == SWCODEC
277 long talked_tick
= 0;
281 while (!tagcache_is_initialized())
283 int ret
= tagcache_get_commit_step();
287 #if CONFIG_CODEC == SWCODEC
288 /* hwcodec can't use voice here, as the database commit
289 * uses the audio buffer. */
290 if(global_settings
.talk_menu
292 || TIME_AFTER(current_tick
, talked_tick
+7*HZ
)))
294 talked_tick
= current_tick
;
295 talk_id(LANG_TAGCACHE_INIT
, false);
296 talk_number(ret
, true);
297 talk_id(VOICE_OF
, true);
298 talk_number(tagcache_get_max_commit_step(), true);
301 #ifdef HAVE_LCD_BITMAP
304 splashf(0, "[%d/%d] %s", ret
, tagcache_get_max_commit_step(),
305 str(LANG_TAGCACHE_INIT
));
309 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT
), ret
,
310 tagcache_get_max_commit_step());
313 lcd_double_height(false);
314 lcd_putsf(0, 1, " DB [%d/%d]", ret
,
315 tagcache_get_max_commit_step());
332 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
334 static void init(void)
344 #ifdef HAVE_REMOTE_LCD
351 #if (CONFIG_PLATFORM & PLATFORM_SDL)
354 lang_init(core_language_builtin
, language_strings
,
355 LANG_LAST_INDEX_IN_ARRAY
);
359 /* Keep the order of this 3 (viewportmanager handles statusbars)
360 * Must be done before any code uses the multi-screen API */
361 gui_syncstatusbar_init(&statusbars
);
362 gui_sync_skin_init();
364 viewportmanager_init();
368 settings_load(SETTINGS_ALL
);
369 settings_apply(true);
371 init_dircache(false);
381 #if CONFIG_CODEC != SWCODEC
382 mp3_init( global_settings
.volume
,
383 global_settings
.bass
,
384 global_settings
.treble
,
385 global_settings
.balance
,
386 global_settings
.loudness
,
388 global_settings
.channel_config
,
389 global_settings
.stereo_width
,
390 global_settings
.mdb_strength
,
391 global_settings
.mdb_harmonics
,
392 global_settings
.mdb_center
,
393 global_settings
.mdb_shape
,
394 global_settings
.mdb_enable
,
395 global_settings
.superbass
);
397 /* audio_init must to know the size of voice buffer so init voice first */
399 #endif /* CONFIG_CODEC != SWCODEC */
402 #if CONFIG_CODEC == SWCODEC && defined (HAVE_PITCHSCREEN)
404 #endif /* CONFIG_CODEC == SWCODEC */
407 button_clear_queue(); /* Empty the keyboard buffer */
409 settings_apply_skins();
414 static void init(void) INIT_ATTR
;
415 static void init(void)
418 bool mounted
= false;
419 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
420 /* if nobody initialized ATA before, I consider this a cold start */
421 bool coldstart
= (PACR2
& 0x4000) != 0; /* starting from Flash */
425 #if defined(IPOD_VIDEO)
426 audiobufend
=(unsigned char *)audiobufend_lds
;
427 if(MEM
==64 && probed_ramsize
!=64)
429 audiobufend
-= (32<<20);
434 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
435 set_cpu_frequency(CPUFREQ_NORMAL
);
437 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS
);
454 /* current_tick should be ticking by now */
458 #ifdef HAVE_REMOTE_LCD
466 lang_init(core_language_builtin
, language_strings
,
467 LANG_LAST_INDEX_IN_ARRAY
);
481 CHART(">settings_load(RTC)");
482 settings_load(SETTINGS_RTC
); /* early load parts of global_settings */
483 CHART("<settings_load(RTC)");
489 #if CONFIG_USBOTG == USBOTG_ISP1362
491 #elif CONFIG_USBOTG == USBOTG_M5636
505 /* Keep the order of this 3 (viewportmanager handles statusbars)
506 * Must be done before any code uses the multi-screen API */
507 CHART(">gui_syncstatusbar_init");
508 gui_syncstatusbar_init(&statusbars
);
509 CHART("<gui_syncstatusbar_init");
510 CHART(">sb_skin_init");
512 CHART("<sb_skin_init");
513 CHART(">gui_sync_wps_init");
514 gui_sync_skin_init();
515 CHART("<gui_sync_wps_init");
516 CHART(">viewportmanager_init");
517 viewportmanager_init();
518 CHART("<viewportmanager_init");
520 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
521 /* charger_inserted() can't be used here because power_thread()
522 hasn't checked power_input_status() yet */
523 if (coldstart
&& (power_input_status() & POWER_INPUT_MAIN_CHARGER
)
524 && !global_settings
.car_adapter_mode
525 #ifdef ATA_POWER_PLAYERSTYLE
526 && !ide_powered() /* relies on probing result from bootloader */
530 rc
= charging_screen(); /* display a "charging" screen */
531 if (rc
== 1) /* charger removed */
533 /* "On" pressed or USB connected: proceed */
534 show_logo(); /* again, to provide better visual feedback */
539 disk_init_subsystem();
540 CHART(">storage_init");
542 CHART("<storage_init");
545 #ifdef HAVE_LCD_BITMAP
547 lcd_putsf(0, 1, "ATA error: %d", rc
);
548 lcd_puts(0, 3, "Press ON to debug");
550 while(!(button_get(true) & BUTTON_REL
)); /*DO NOT CHANGE TO ACTION SYSTEM */
553 panicf("ata: %d", rc
);
556 #ifdef HAVE_EEPROM_SETTINGS
557 CHART(">eeprom_settings_init");
558 eeprom_settings_init();
559 CHART("<eeprom_settings_init");
562 #ifndef HAVE_USBSTACK
563 usb_start_monitoring();
564 while (usb_detect() == USB_INSERTED
)
566 #ifdef HAVE_EEPROM_SETTINGS
567 firmware_settings
.disk_clean
= false;
569 /* enter USB mode early, before trying to mount */
570 if (button_get_w_tmo(HZ
/10) == SYS_USB_CONNECTED
)
571 #if (CONFIG_STORAGE & STORAGE_MMC)
572 if (!mmc_touched() ||
573 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED
))
576 gui_usb_screen_run(true);
577 mounted
= true; /* mounting done @ end of USB mode */
579 #ifdef HAVE_USB_POWER
580 if (usb_powered()) /* avoid deadlock */
588 CHART(">disk_mount_all");
589 rc
= disk_mount_all();
590 CHART("<disk_mount_all");
594 lcd_puts(0, 0, "No partition");
595 lcd_puts(0, 1, "found.");
596 #ifdef HAVE_LCD_BITMAP
597 lcd_puts(0, 2, "Insert USB cable");
598 lcd_puts(0, 3, "and fix it.");
602 while(button_get(true) != SYS_USB_CONNECTED
) {};
603 gui_usb_screen_run(true);
608 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
609 (CONFIG_KEYPAD == IRIVER_H10_PAD)
610 #ifdef SETTINGS_RESET
611 /* Reset settings if holding the reset button. (Rec on Archos,
613 if ((button_status() & SETTINGS_RESET
) == SETTINGS_RESET
)
615 /* Reset settings if the hold button is turned on */
619 splash(HZ
*2, str(LANG_RESET_DONE_CLEAR
));
625 CHART(">settings_load(ALL)");
626 settings_load(SETTINGS_ALL
);
627 CHART("<settings_load(ALL)");
630 CHART(">init_dircache(true)");
631 rc
= init_dircache(true);
632 CHART("<init_dircache(true)");
636 remove(TAGCACHE_STATEFILE
);
640 CHART(">settings_apply(true)");
641 settings_apply(true);
642 CHART("<settings_apply(true)");
643 CHART(">init_dircache(false)");
644 init_dircache(false);
645 CHART("<init_dircache(false)");
647 CHART(">init_tagcache");
649 CHART("<init_tagcache");
652 #ifdef HAVE_EEPROM_SETTINGS
653 if (firmware_settings
.initialized
)
655 /* In case we crash. */
656 firmware_settings
.disk_clean
= false;
657 CHART(">eeprom_settings_store");
658 eeprom_settings_store();
659 CHART("<eeprom_settings_store");
666 #if CONFIG_CODEC == SWCODEC && defined (HAVE_PITCHSCREEN)
668 #endif /* CONFIG_CODEC == SWCODEC */
671 #if CONFIG_CODEC != SWCODEC
672 /* No buffer allocation (see buffer.c) may take place after the call to
673 audio_init() since the mpeg thread takes the rest of the buffer space */
674 mp3_init( global_settings
.volume
,
675 global_settings
.bass
,
676 global_settings
.treble
,
677 global_settings
.balance
,
678 global_settings
.loudness
,
680 global_settings
.channel_config
,
681 global_settings
.stereo_width
,
682 global_settings
.mdb_strength
,
683 global_settings
.mdb_harmonics
,
684 global_settings
.mdb_center
,
685 global_settings
.mdb_shape
,
686 global_settings
.mdb_enable
,
687 global_settings
.superbass
);
689 /* audio_init must to know the size of voice buffer so init voice first */
691 #endif /* CONFIG_CODEC != SWCODEC */
693 CHART(">audio_init");
695 CHART("<audio_init");
697 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
701 /* runtime database has to be initialized after audio_init() */
705 car_adapter_mode_init();
707 #ifdef IPOD_ACCESSORY_PROTOCOL
708 iap_setup(global_settings
.serial_bitrate
);
710 #ifdef HAVE_ACCESSORY_SUPPLY
711 accessory_supply_set(global_settings
.accessory_supply
);
713 #ifdef HAVE_LINEOUT_POWEROFF
714 lineout_set(global_settings
.lineout_active
);
716 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
717 CHART("<check_bootfile(false)");
718 check_bootfile(false); /* remember write time and filesize */
719 CHART(">check_bootfile(false)");
721 CHART("<settings_apply_skins");
722 settings_apply_skins();
723 CHART(">settings_apply_skins");
727 void cop_main(void) MAIN_NORETURN_ATTR
;
730 /* This is the entry point for the coprocessor
731 Anyone not running an upgraded bootloader will never reach this point,
732 so it should not be assumed that the coprocessor be usable even on
733 platforms which support it.
735 A kernel thread is initially setup on the coprocessor and immediately
736 destroyed for purposes of continuity. The cop sits idle until at least
737 one thread exists on it. */
742 /* This should never be reached */
750 #endif /* SIMULATOR */