Initial commit.
[kugel-rb.git] / apps / main.c
blob056604f85717d46face8782fb7eb6a1488488986
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include "config.h"
23 #include "storage.h"
24 #include "disk.h"
25 #include "fat.h"
26 #include "lcd.h"
27 #include "rtc.h"
28 #include "debug.h"
29 #include "led.h"
30 #include "kernel.h"
31 #include "button.h"
32 #include "tree.h"
33 #include "filetypes.h"
34 #include "panic.h"
35 #include "menu.h"
36 #include "system.h"
37 #include "usb.h"
38 #include "powermgmt.h"
39 #include "adc.h"
40 #include "i2c.h"
41 #ifndef DEBUG
42 #include "serial.h"
43 #endif
44 #include "audio.h"
45 #include "mp3_playback.h"
46 #include "thread.h"
47 #include "settings.h"
48 #include "backlight.h"
49 #include "status.h"
50 #include "debug_menu.h"
51 #include "font.h"
52 #include "language.h"
53 #include "wps.h"
54 #include "playlist.h"
55 #include "buffer.h"
56 #include "rolo.h"
57 #include "screens.h"
58 #include "usb_screen.h"
59 #include "power.h"
60 #include "talk.h"
61 #include "plugin.h"
62 #include "misc.h"
63 #include "dircache.h"
64 #ifdef HAVE_TAGCACHE
65 #include "tagcache.h"
66 #include "tagtree.h"
67 #endif
68 #include "lang.h"
69 #include "string.h"
70 #include "splash.h"
71 #include "eeprom_settings.h"
72 #include "scrobbler.h"
73 #include "icon.h"
74 #include "viewport.h"
75 #include "statusbar-skinned.h"
76 #include "bootchart.h"
78 #ifdef IPOD_ACCESSORY_PROTOCOL
79 #include "iap.h"
80 #endif
82 #if (CONFIG_CODEC == SWCODEC)
83 #include "playback.h"
84 #include "tdspeed.h"
85 #endif
86 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
87 #include "pcm_record.h"
88 #endif
90 #ifdef BUTTON_REC
91 #define SETTINGS_RESET BUTTON_REC
92 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
93 #define SETTINGS_RESET BUTTON_A
94 #endif
96 #if CONFIG_TUNER
97 #include "radio.h"
98 #endif
99 #if (CONFIG_STORAGE & STORAGE_MMC)
100 #include "ata_mmc.h"
101 #endif
103 #ifdef HAVE_REMOTE_LCD
104 #include "lcd-remote.h"
105 #endif
107 #if CONFIG_USBOTG == USBOTG_ISP1362
108 #include "isp1362.h"
109 #endif
111 #if CONFIG_USBOTG == USBOTG_M5636
112 #include "m5636.h"
113 #endif
115 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
116 #include "sim_tasks.h"
117 #endif
119 #ifdef HAVE_SDL
120 #include "system-sdl.h"
121 #endif
123 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
125 static void init(void);
127 #ifdef HAVE_SDL
128 #if defined(WIN32) && defined(main)
129 /* Don't use SDL_main on windows -> no more stdio redirection */
130 #undef main
131 #endif
132 int main(int argc, char *argv[])
134 #ifdef APPLICATION
135 paths_init();
136 #endif
137 sys_handle_argv(argc, argv);
138 #else
139 /* main(), and various functions called by main() and init() may be
140 * be INIT_ATTR. These functions must not be called after the final call
141 * to root_menu() at the end of main()
142 * see definition of INIT_ATTR in config.h */
143 int main(void) INIT_ATTR __attribute__((noreturn));
144 int main(void)
146 #endif
147 int i;
148 CHART(">init");
149 init();
150 CHART("<init");
151 FOR_NB_SCREENS(i)
153 screens[i].clear_display();
154 screens[i].update();
156 #ifdef HAVE_LCD_BITMAP
157 list_init();
158 #endif
159 tree_gui_init();
160 /* Keep the order of this 3
161 * Must be done before any code uses the multi-screen API */
162 #ifdef HAVE_USBSTACK
163 /* All threads should be created and public queues registered by now */
164 usb_start_monitoring();
165 #endif
167 #ifdef AUTOROCK
169 char filename[MAX_PATH];
170 const char *file = get_user_file_path(
171 #ifdef APPLICATION
172 ROCKBOX_DIR
173 #else
174 PLUGIN_APPS_DIR
175 #endif
176 "/autostart.rock", NEED_WRITE|IS_FILE, filename, sizeof(filename));
177 if(file_exists(file)) /* no complaint if it doesn't exist */
179 plugin_load(file, NULL); /* start if it does */
182 #endif /* #ifdef AUTOROCK */
184 global_status.last_volume_change = 0;
185 /* no calls INIT_ATTR functions after this point anymore!
186 * see definition of INIT_ATTR in config.h */
187 CHART(">root_menu");
188 root_menu();
191 static int init_dircache(bool preinit) INIT_ATTR;
192 static int init_dircache(bool preinit)
194 #ifdef HAVE_DIRCACHE
195 int result = 0;
196 bool clear = false;
198 if (preinit)
199 dircache_init();
201 if (!global_settings.dircache)
202 return 0;
204 # ifdef HAVE_EEPROM_SETTINGS
205 if (firmware_settings.initialized && firmware_settings.disk_clean
206 && preinit)
208 result = dircache_load();
210 if (result < 0)
212 firmware_settings.disk_clean = false;
213 if (global_status.dircache_size <= 0)
215 /* This will be in default language, settings are not
216 applied yet. Not really any easy way to fix that. */
217 splash(0, str(LANG_SCANNING_DISK));
218 clear = true;
221 dircache_build(global_status.dircache_size);
224 else
225 # endif
227 if (preinit)
228 return -1;
230 if (!dircache_is_enabled()
231 && !dircache_is_initializing())
233 if (global_status.dircache_size <= 0)
235 splash(0, str(LANG_SCANNING_DISK));
236 clear = true;
238 result = dircache_build(global_status.dircache_size);
241 if (result < 0)
243 /* Initialization of dircache failed. Manual action is
244 * necessary to enable dircache again.
246 splashf(0, "Dircache failed, disabled. Result: %d", result);
247 global_settings.dircache = false;
251 if (clear)
253 backlight_on();
254 show_logo();
255 global_status.dircache_size = dircache_get_cache_size();
256 status_save();
259 return result;
260 #else
261 (void)preinit;
262 return 0;
263 #endif
266 #ifdef HAVE_TAGCACHE
267 static void init_tagcache(void) INIT_ATTR;
268 static void init_tagcache(void)
270 bool clear = false;
271 #if CONFIG_CODEC == SWCODEC
272 long talked_tick = 0;
273 #endif
274 tagcache_init();
276 while (!tagcache_is_initialized())
278 int ret = tagcache_get_commit_step();
280 if (ret > 0)
282 #if CONFIG_CODEC == SWCODEC
283 /* hwcodec can't use voice here, as the database commit
284 * uses the audio buffer. */
285 if(global_settings.talk_menu
286 && (talked_tick == 0
287 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
289 talked_tick = current_tick;
290 talk_id(LANG_TAGCACHE_INIT, false);
291 talk_number(ret, true);
292 talk_id(VOICE_OF, true);
293 talk_number(tagcache_get_max_commit_step(), true);
295 #endif
296 #ifdef HAVE_LCD_BITMAP
297 if (lang_is_rtl())
299 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
300 str(LANG_TAGCACHE_INIT));
302 else
304 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
305 tagcache_get_max_commit_step());
307 #else
308 lcd_double_height(false);
309 lcd_putsf(0, 1, " DB [%d/%d]", ret,
310 tagcache_get_max_commit_step());
311 lcd_update();
312 #endif
313 clear = true;
315 sleep(HZ/4);
317 tagtree_init();
319 if (clear)
321 backlight_on();
322 show_logo();
325 #endif
327 #if (CONFIG_PLATFORM & PLATFORM_HOSTED)
329 static void init(void)
331 system_init();
332 kernel_init();
333 buffer_init();
334 enable_irq();
335 lcd_init();
336 #ifdef HAVE_REMOTE_LCD
337 lcd_remote_init();
338 #endif
339 font_init();
340 show_logo();
341 button_init();
342 backlight_init();
343 sim_tasks_init();
344 lang_init(core_language_builtin, language_strings,
345 LANG_LAST_INDEX_IN_ARRAY);
346 #ifdef DEBUG
347 debug_init();
348 #endif
349 /* Keep the order of this 3 (viewportmanager handles statusbars)
350 * Must be done before any code uses the multi-screen API */
351 gui_syncstatusbar_init(&statusbars);
352 gui_sync_wps_init();
353 sb_skin_init();
354 viewportmanager_init();
356 storage_init();
357 settings_reset();
358 settings_load(SETTINGS_ALL);
359 settings_apply(true);
360 init_dircache(true);
361 init_dircache(false);
362 #ifdef HAVE_TAGCACHE
363 init_tagcache();
364 #endif
365 sleep(HZ/2);
366 tree_mem_init();
367 filetype_init();
368 playlist_init();
370 #if CONFIG_CODEC != SWCODEC
371 mp3_init( global_settings.volume,
372 global_settings.bass,
373 global_settings.treble,
374 global_settings.balance,
375 global_settings.loudness,
376 global_settings.avc,
377 global_settings.channel_config,
378 global_settings.stereo_width,
379 global_settings.mdb_strength,
380 global_settings.mdb_harmonics,
381 global_settings.mdb_center,
382 global_settings.mdb_shape,
383 global_settings.mdb_enable,
384 global_settings.superbass);
386 /* audio_init must to know the size of voice buffer so init voice first */
387 talk_init();
388 #endif /* CONFIG_CODEC != SWCODEC */
390 scrobbler_init();
391 #if CONFIG_CODEC == SWCODEC
392 tdspeed_init();
393 #endif /* CONFIG_CODEC == SWCODEC */
395 audio_init();
396 button_clear_queue(); /* Empty the keyboard buffer */
398 settings_apply_skins();
401 #else
403 static void init(void) INIT_ATTR;
404 static void init(void)
406 int rc;
407 bool mounted = false;
408 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
409 /* if nobody initialized ATA before, I consider this a cold start */
410 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
411 #endif
413 system_init();
414 kernel_init();
416 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
417 set_cpu_frequency(CPUFREQ_NORMAL);
418 #ifdef CPU_COLDFIRE
419 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
420 #endif
421 cpu_boost(true);
422 #endif
424 buffer_init();
426 settings_reset();
428 i2c_init();
430 power_init();
432 enable_irq();
433 #ifdef CPU_ARM
434 enable_fiq();
435 #endif
436 /* current_tick should be ticking by now */
437 CHART("ticking");
439 lcd_init();
440 #ifdef HAVE_REMOTE_LCD
441 lcd_remote_init();
442 #endif
443 font_init();
445 CHART(">show_logo");
446 show_logo();
447 CHART("<show_logo");
448 lang_init(core_language_builtin, language_strings,
449 LANG_LAST_INDEX_IN_ARRAY);
451 #ifdef DEBUG
452 debug_init();
453 #else
454 #ifdef HAVE_SERIAL
455 serial_setup();
456 #endif
457 #endif
459 #if CONFIG_RTC
460 rtc_init();
461 #endif
462 #ifdef HAVE_RTC_RAM
463 CHART(">settings_load(RTC)");
464 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
465 CHART("<settings_load(RTC)");
466 #endif
468 adc_init();
470 usb_init();
471 #if CONFIG_USBOTG == USBOTG_ISP1362
472 isp1362_init();
473 #elif CONFIG_USBOTG == USBOTG_M5636
474 m5636_init();
475 #endif
477 backlight_init();
479 button_init();
481 powermgmt_init();
483 #if CONFIG_TUNER
484 radio_init();
485 #endif
487 /* Keep the order of this 3 (viewportmanager handles statusbars)
488 * Must be done before any code uses the multi-screen API */
489 CHART(">gui_syncstatusbar_init");
490 gui_syncstatusbar_init(&statusbars);
491 CHART("<gui_syncstatusbar_init");
492 CHART(">sb_skin_init");
493 sb_skin_init();
494 CHART("<sb_skin_init");
495 CHART(">gui_sync_wps_init");
496 gui_sync_wps_init();
497 CHART("<gui_sync_wps_init");
498 CHART(">viewportmanager_init");
499 viewportmanager_init();
500 CHART("<viewportmanager_init");
502 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
503 /* charger_inserted() can't be used here because power_thread()
504 hasn't checked power_input_status() yet */
505 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
506 && !global_settings.car_adapter_mode
507 #ifdef ATA_POWER_PLAYERSTYLE
508 && !ide_powered() /* relies on probing result from bootloader */
509 #endif
512 rc = charging_screen(); /* display a "charging" screen */
513 if (rc == 1) /* charger removed */
514 power_off();
515 /* "On" pressed or USB connected: proceed */
516 show_logo(); /* again, to provide better visual feedback */
518 #endif
521 disk_init_subsystem();
522 CHART(">storage_init");
523 rc = storage_init();
524 CHART("<storage_init");
525 if(rc)
527 #ifdef HAVE_LCD_BITMAP
528 lcd_clear_display();
529 lcd_putsf(0, 1, "ATA error: %d", rc);
530 lcd_puts(0, 3, "Press ON to debug");
531 lcd_update();
532 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
533 dbg_ports();
534 #endif
535 panicf("ata: %d", rc);
538 #ifdef HAVE_EEPROM_SETTINGS
539 CHART(">eeprom_settings_init");
540 eeprom_settings_init();
541 CHART("<eeprom_settings_init");
542 #endif
544 #ifndef HAVE_USBSTACK
545 usb_start_monitoring();
546 while (usb_detect() == USB_INSERTED)
548 #ifdef HAVE_EEPROM_SETTINGS
549 firmware_settings.disk_clean = false;
550 #endif
551 /* enter USB mode early, before trying to mount */
552 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
553 #if (CONFIG_STORAGE & STORAGE_MMC)
554 if (!mmc_touched() ||
555 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
556 #endif
558 gui_usb_screen_run();
559 mounted = true; /* mounting done @ end of USB mode */
561 #ifdef HAVE_USB_POWER
562 if (usb_powered()) /* avoid deadlock */
563 break;
564 #endif
566 #endif
568 if (!mounted)
570 CHART(">disk_mount_all");
571 rc = disk_mount_all();
572 CHART("<disk_mount_all");
573 if (rc<=0)
575 lcd_clear_display();
576 lcd_puts(0, 0, "No partition");
577 lcd_puts(0, 1, "found.");
578 #ifdef HAVE_LCD_BITMAP
579 lcd_puts(0, 2, "Insert USB cable");
580 lcd_puts(0, 3, "and fix it.");
581 #endif
582 lcd_update();
584 while(button_get(true) != SYS_USB_CONNECTED) {};
585 gui_usb_screen_run();
586 system_reboot();
590 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
591 (CONFIG_KEYPAD == IRIVER_H10_PAD)
592 #ifdef SETTINGS_RESET
593 /* Reset settings if holding the reset button. (Rec on Archos,
594 A on Gigabeat) */
595 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
596 #else
597 /* Reset settings if the hold button is turned on */
598 if (button_hold())
599 #endif
601 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
602 settings_reset();
604 else
605 #endif
607 CHART(">settings_load(ALL)");
608 settings_load(SETTINGS_ALL);
609 CHART("<settings_load(ALL)");
612 CHART(">init_dircache(true)");
613 rc = init_dircache(true);
614 CHART("<init_dircache(true)");
615 if (rc < 0)
617 #ifdef HAVE_TAGCACHE
618 remove(TAGCACHE_STATEFILE);
619 #endif
622 CHART(">settings_apply(true)");
623 settings_apply(true);
624 CHART("<settings_apply(true)");
625 CHART(">init_dircache(false)");
626 init_dircache(false);
627 CHART("<init_dircache(false)");
628 #ifdef HAVE_TAGCACHE
629 CHART(">init_tagcache");
630 init_tagcache();
631 CHART("<init_tagcache");
632 #endif
634 #ifdef HAVE_EEPROM_SETTINGS
635 if (firmware_settings.initialized)
637 /* In case we crash. */
638 firmware_settings.disk_clean = false;
639 CHART(">eeprom_settings_store");
640 eeprom_settings_store();
641 CHART("<eeprom_settings_store");
643 #endif
644 playlist_init();
645 tree_mem_init();
646 filetype_init();
647 scrobbler_init();
648 #if CONFIG_CODEC == SWCODEC
649 tdspeed_init();
650 #endif /* CONFIG_CODEC == SWCODEC */
652 #if CONFIG_CODEC != SWCODEC
653 /* No buffer allocation (see buffer.c) may take place after the call to
654 audio_init() since the mpeg thread takes the rest of the buffer space */
655 mp3_init( global_settings.volume,
656 global_settings.bass,
657 global_settings.treble,
658 global_settings.balance,
659 global_settings.loudness,
660 global_settings.avc,
661 global_settings.channel_config,
662 global_settings.stereo_width,
663 global_settings.mdb_strength,
664 global_settings.mdb_harmonics,
665 global_settings.mdb_center,
666 global_settings.mdb_shape,
667 global_settings.mdb_enable,
668 global_settings.superbass);
670 /* audio_init must to know the size of voice buffer so init voice first */
671 talk_init();
672 #endif /* CONFIG_CODEC != SWCODEC */
674 CHART(">audio_init");
675 audio_init();
676 CHART("<audio_init");
678 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
679 pcm_rec_init();
680 #endif
682 /* runtime database has to be initialized after audio_init() */
683 cpu_boost(false);
685 #if CONFIG_CHARGING
686 car_adapter_mode_init();
687 #endif
688 #ifdef IPOD_ACCESSORY_PROTOCOL
689 iap_setup(global_settings.serial_bitrate);
690 #endif
691 #ifdef HAVE_ACCESSORY_SUPPLY
692 accessory_supply_set(global_settings.accessory_supply);
693 #endif
694 #ifdef HAVE_LINEOUT_POWEROFF
695 lineout_set(global_settings.lineout_active);
696 #endif
697 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
698 CHART("<check_bootfile(false)");
699 check_bootfile(false); /* remember write time and filesize */
700 CHART(">check_bootfile(false)");
701 #endif
702 CHART("<settings_apply_skins");
703 settings_apply_skins();
704 CHART(">settings_apply_skins");
707 #ifdef CPU_PP
708 void __attribute__((noreturn)) cop_main(void)
710 /* This is the entry point for the coprocessor
711 Anyone not running an upgraded bootloader will never reach this point,
712 so it should not be assumed that the coprocessor be usable even on
713 platforms which support it.
715 A kernel thread is initially setup on the coprocessor and immediately
716 destroyed for purposes of continuity. The cop sits idle until at least
717 one thread exists on it. */
719 #if NUM_CORES > 1
720 system_init();
721 kernel_init();
722 /* This should never be reached */
723 #endif
724 while(1) {
725 sleep_core(COP);
728 #endif /* CPU_PP */
730 #endif /* SIMULATOR */