Fix strcpy from a user-supplied string to fixed size string.
[kugel-rb.git] / apps / main.c
blob7c43c0c277a60523cf495a1939f161312052cde3
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 "version.h"
52 #include "sprintf.h"
53 #include "font.h"
54 #include "language.h"
55 #include "wps.h"
56 #include "playlist.h"
57 #include "buffer.h"
58 #include "rolo.h"
59 #include "screens.h"
60 #include "usb_screen.h"
61 #include "power.h"
62 #include "talk.h"
63 #include "plugin.h"
64 #include "misc.h"
65 #include "dircache.h"
66 #ifdef HAVE_TAGCACHE
67 #include "tagcache.h"
68 #include "tagtree.h"
69 #endif
70 #include "lang.h"
71 #include "string.h"
72 #include "splash.h"
73 #include "eeprom_settings.h"
74 #include "scrobbler.h"
75 #include "icon.h"
76 #include "viewport.h"
77 #include "statusbar-skinned.h"
79 #ifdef IPOD_ACCESSORY_PROTOCOL
80 #include "iap.h"
81 #endif
83 #if (CONFIG_CODEC == SWCODEC)
84 #include "playback.h"
85 #include "tdspeed.h"
86 #endif
87 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
88 #include "pcm_record.h"
89 #endif
91 #ifdef BUTTON_REC
92 #define SETTINGS_RESET BUTTON_REC
93 #elif (CONFIG_KEYPAD == GIGABEAT_PAD)
94 #define SETTINGS_RESET BUTTON_A
95 #endif
97 #if CONFIG_TUNER
98 #include "radio.h"
99 #endif
100 #if (CONFIG_STORAGE & STORAGE_MMC)
101 #include "ata_mmc.h"
102 #endif
104 #ifdef HAVE_REMOTE_LCD
105 #include "lcd-remote.h"
106 #endif
108 #if CONFIG_USBOTG == USBOTG_ISP1362
109 #include "isp1362.h"
110 #endif
112 #if CONFIG_USBOTG == USBOTG_M5636
113 #include "m5636.h"
114 #endif
116 #ifdef SIMULATOR
117 #include "sim_tasks.h"
118 #include "system-sdl.h"
119 #endif
121 /*#define AUTOROCK*/ /* define this to check for "autostart.rock" on boot */
123 const char appsversion[]=APPSVERSION;
125 static void init(void);
127 #ifdef SIMULATOR
128 void app_main(void)
129 #else
130 /* main(), and various functions called by main() and init() may be
131 * be INIT_ATTR. These functions must not be called after the final call
132 * to root_menu() at the end of main()
133 * see definition of INIT_ATTR in config.h */
134 int main(void) INIT_ATTR __attribute__((noreturn));
135 int main(void)
136 #endif
138 int i;
139 init();
140 FOR_NB_SCREENS(i)
142 screens[i].clear_display();
143 screens[i].update();
145 #ifdef HAVE_LCD_BITMAP
146 list_init();
147 #endif
148 tree_gui_init();
149 /* Keep the order of this 3
150 * Must be done before any code uses the multi-screen API */
151 #ifdef HAVE_USBSTACK
152 /* All threads should be created and public queues registered by now */
153 usb_start_monitoring();
154 #endif
156 #ifdef AUTOROCK
158 static const char filename[] = PLUGIN_APPS_DIR "/autostart.rock";
160 if(file_exists(filename)) /* no complaint if it doesn't exist */
162 plugin_load((char*)filename, NULL); /* start if it does */
165 #endif /* #ifdef AUTOROCK */
167 global_status.last_volume_change = 0;
168 /* no calls INIT_ATTR functions after this point anymore!
169 * see definition of INIT_ATTR in config.h */
170 root_menu();
173 static int init_dircache(bool preinit) INIT_ATTR;
174 static int init_dircache(bool preinit)
176 #ifdef HAVE_DIRCACHE
177 int result = 0;
178 bool clear = false;
180 if (preinit)
181 dircache_init();
183 if (!global_settings.dircache)
184 return 0;
186 # ifdef HAVE_EEPROM_SETTINGS
187 if (firmware_settings.initialized && firmware_settings.disk_clean
188 && preinit)
190 result = dircache_load();
192 if (result < 0)
194 firmware_settings.disk_clean = false;
195 if (global_status.dircache_size <= 0)
197 /* This will be in default language, settings are not
198 applied yet. Not really any easy way to fix that. */
199 splash(0, str(LANG_SCANNING_DISK));
200 clear = true;
203 dircache_build(global_status.dircache_size);
206 else
207 # endif
209 if (preinit)
210 return -1;
212 if (!dircache_is_enabled()
213 && !dircache_is_initializing())
215 if (global_status.dircache_size <= 0)
217 splash(0, str(LANG_SCANNING_DISK));
218 clear = true;
220 result = dircache_build(global_status.dircache_size);
223 if (result < 0)
225 /* Initialization of dircache failed. Manual action is
226 * necessary to enable dircache again.
228 splashf(0, "Dircache failed, disabled. Result: %d", result);
229 global_settings.dircache = false;
233 if (clear)
235 backlight_on();
236 show_logo();
237 global_status.dircache_size = dircache_get_cache_size();
238 status_save();
241 return result;
242 #else
243 (void)preinit;
244 return 0;
245 #endif
248 #ifdef HAVE_TAGCACHE
249 static void init_tagcache(void) INIT_ATTR;
250 static void init_tagcache(void)
252 bool clear = false;
253 #if CONFIG_CODEC == SWCODEC
254 long talked_tick = 0;
255 #endif
256 tagcache_init();
258 while (!tagcache_is_initialized())
260 int ret = tagcache_get_commit_step();
262 if (ret > 0)
264 #if CONFIG_CODEC == SWCODEC
265 /* hwcodec can't use voice here, as the database commit
266 * uses the audio buffer. */
267 if(global_settings.talk_menu
268 && (talked_tick == 0
269 || TIME_AFTER(current_tick, talked_tick+7*HZ)))
271 talked_tick = current_tick;
272 talk_id(LANG_TAGCACHE_INIT, false);
273 talk_number(ret, true);
274 talk_id(VOICE_OF, true);
275 talk_number(tagcache_get_max_commit_step(), true);
277 #endif
278 #ifdef HAVE_LCD_BITMAP
279 if (lang_is_rtl())
281 splashf(0, "[%d/%d] %s", ret, tagcache_get_max_commit_step(),
282 str(LANG_TAGCACHE_INIT));
284 else
286 splashf(0, "%s [%d/%d]", str(LANG_TAGCACHE_INIT), ret,
287 tagcache_get_max_commit_step());
289 #else
290 lcd_double_height(false);
291 lcd_putsf(0, 1, " DB [%d/%d]", ret,
292 tagcache_get_max_commit_step());
293 lcd_update();
294 #endif
295 clear = true;
297 sleep(HZ/4);
299 tagtree_init();
301 if (clear)
303 backlight_on();
304 show_logo();
307 #endif
309 #ifdef SIMULATOR
311 static void init(void)
313 kernel_init();
314 buffer_init();
315 enable_irq();
316 lcd_init();
317 #ifdef HAVE_REMOTE_LCD
318 lcd_remote_init();
319 #endif
320 font_init();
321 show_logo();
322 button_init();
323 backlight_init();
324 sim_tasks_init();
325 lang_init(core_language_builtin, language_strings,
326 LANG_LAST_INDEX_IN_ARRAY);
327 #ifdef DEBUG
328 debug_init();
329 #endif
330 /* Keep the order of this 3 (viewportmanager handles statusbars)
331 * Must be done before any code uses the multi-screen API */
332 gui_syncstatusbar_init(&statusbars);
333 gui_sync_wps_init();
334 sb_skin_init();
335 viewportmanager_init();
337 storage_init();
338 settings_reset();
339 settings_load(SETTINGS_ALL);
340 settings_apply(true);
341 init_dircache(true);
342 init_dircache(false);
343 #ifdef HAVE_TAGCACHE
344 init_tagcache();
345 #endif
346 sleep(HZ/2);
347 tree_mem_init();
348 filetype_init();
349 playlist_init();
351 #if CONFIG_CODEC != SWCODEC
352 mp3_init( global_settings.volume,
353 global_settings.bass,
354 global_settings.treble,
355 global_settings.balance,
356 global_settings.loudness,
357 global_settings.avc,
358 global_settings.channel_config,
359 global_settings.stereo_width,
360 global_settings.mdb_strength,
361 global_settings.mdb_harmonics,
362 global_settings.mdb_center,
363 global_settings.mdb_shape,
364 global_settings.mdb_enable,
365 global_settings.superbass);
367 /* audio_init must to know the size of voice buffer so init voice first */
368 talk_init();
369 #endif /* CONFIG_CODEC != SWCODEC */
371 scrobbler_init();
372 #if CONFIG_CODEC == SWCODEC
373 tdspeed_init();
374 #endif /* CONFIG_CODEC == SWCODEC */
376 audio_init();
377 button_clear_queue(); /* Empty the keyboard buffer */
379 settings_apply_skins();
382 #else
384 static void init(void) INIT_ATTR;
385 static void init(void)
387 int rc;
388 bool mounted = false;
389 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
390 /* if nobody initialized ATA before, I consider this a cold start */
391 bool coldstart = (PACR2 & 0x4000) != 0; /* starting from Flash */
392 #endif
394 system_init();
395 kernel_init();
397 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
398 set_cpu_frequency(CPUFREQ_NORMAL);
399 #ifdef CPU_COLDFIRE
400 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS);
401 #endif
402 cpu_boost(true);
403 #endif
405 buffer_init();
407 settings_reset();
409 i2c_init();
411 power_init();
413 enable_irq();
414 #ifdef CPU_ARM
415 enable_fiq();
416 #endif
417 lcd_init();
418 #ifdef HAVE_REMOTE_LCD
419 lcd_remote_init();
420 #endif
421 font_init();
423 show_logo();
424 lang_init(core_language_builtin, language_strings,
425 LANG_LAST_INDEX_IN_ARRAY);
427 #ifdef DEBUG
428 debug_init();
429 #else
430 #ifdef HAVE_SERIAL
431 serial_setup();
432 #endif
433 #endif
435 #if CONFIG_RTC
436 rtc_init();
437 #endif
438 #ifdef HAVE_RTC_RAM
439 settings_load(SETTINGS_RTC); /* early load parts of global_settings */
440 #endif
442 adc_init();
444 usb_init();
445 #if CONFIG_USBOTG == USBOTG_ISP1362
446 isp1362_init();
447 #elif CONFIG_USBOTG == USBOTG_M5636
448 m5636_init();
449 #endif
451 backlight_init();
453 button_init();
455 powermgmt_init();
457 #if CONFIG_TUNER
458 radio_init();
459 #endif
461 /* Keep the order of this 3 (viewportmanager handles statusbars)
462 * Must be done before any code uses the multi-screen API */
463 gui_syncstatusbar_init(&statusbars);
464 sb_skin_init();
465 gui_sync_wps_init();
466 viewportmanager_init();
468 #if CONFIG_CHARGING && (CONFIG_CPU == SH7034)
469 /* charger_inserted() can't be used here because power_thread()
470 hasn't checked power_input_status() yet */
471 if (coldstart && (power_input_status() & POWER_INPUT_MAIN_CHARGER)
472 && !global_settings.car_adapter_mode
473 #ifdef ATA_POWER_PLAYERSTYLE
474 && !ide_powered() /* relies on probing result from bootloader */
475 #endif
478 rc = charging_screen(); /* display a "charging" screen */
479 if (rc == 1) /* charger removed */
480 power_off();
481 /* "On" pressed or USB connected: proceed */
482 show_logo(); /* again, to provide better visual feedback */
484 #endif
486 rc = storage_init();
487 if(rc)
489 #ifdef HAVE_LCD_BITMAP
490 lcd_clear_display();
491 lcd_putsf(0, 1, "ATA error: %d", rc);
492 lcd_puts(0, 3, "Press ON to debug");
493 lcd_update();
494 while(!(button_get(true) & BUTTON_REL)); /*DO NOT CHANGE TO ACTION SYSTEM */
495 dbg_ports();
496 #endif
497 panicf("ata: %d", rc);
500 #ifdef HAVE_EEPROM_SETTINGS
501 eeprom_settings_init();
502 #endif
504 #ifndef HAVE_USBSTACK
505 usb_start_monitoring();
506 while (usb_detect() == USB_INSERTED)
508 #ifdef HAVE_EEPROM_SETTINGS
509 firmware_settings.disk_clean = false;
510 #endif
511 /* enter USB mode early, before trying to mount */
512 if (button_get_w_tmo(HZ/10) == SYS_USB_CONNECTED)
513 #if (CONFIG_STORAGE & STORAGE_MMC)
514 if (!mmc_touched() ||
515 (mmc_remove_request() == SYS_HOTSWAP_EXTRACTED))
516 #endif
518 gui_usb_screen_run();
519 mounted = true; /* mounting done @ end of USB mode */
521 #ifdef HAVE_USB_POWER
522 if (usb_powered()) /* avoid deadlock */
523 break;
524 #endif
526 #endif
528 if (!mounted)
530 rc = disk_mount_all();
531 if (rc<=0)
533 lcd_clear_display();
534 lcd_puts(0, 0, "No partition");
535 lcd_puts(0, 1, "found.");
536 #ifdef HAVE_LCD_BITMAP
537 lcd_puts(0, 2, "Insert USB cable");
538 lcd_puts(0, 3, "and fix it.");
539 #endif
540 lcd_update();
542 while(button_get(true) != SYS_USB_CONNECTED) {};
543 gui_usb_screen_run();
544 system_reboot();
548 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || \
549 (CONFIG_KEYPAD == IRIVER_H10_PAD)
550 #ifdef SETTINGS_RESET
551 /* Reset settings if holding the reset button. (Rec on Archos,
552 A on Gigabeat) */
553 if ((button_status() & SETTINGS_RESET) == SETTINGS_RESET)
554 #else
555 /* Reset settings if the hold button is turned on */
556 if (button_hold())
557 #endif
559 splash(HZ*2, str(LANG_RESET_DONE_CLEAR));
560 settings_reset();
562 else
563 #endif
564 settings_load(SETTINGS_ALL);
566 if (init_dircache(true) < 0)
568 #ifdef HAVE_TAGCACHE
569 remove(TAGCACHE_STATEFILE);
570 #endif
573 settings_apply(true);
574 init_dircache(false);
575 #ifdef HAVE_TAGCACHE
576 init_tagcache();
577 #endif
579 #ifdef HAVE_EEPROM_SETTINGS
580 if (firmware_settings.initialized)
582 /* In case we crash. */
583 firmware_settings.disk_clean = false;
584 eeprom_settings_store();
586 #endif
587 playlist_init();
588 tree_mem_init();
589 filetype_init();
590 scrobbler_init();
591 #if CONFIG_CODEC == SWCODEC
592 tdspeed_init();
593 #endif /* CONFIG_CODEC == SWCODEC */
595 #if CONFIG_CODEC != SWCODEC
596 /* No buffer allocation (see buffer.c) may take place after the call to
597 audio_init() since the mpeg thread takes the rest of the buffer space */
598 mp3_init( global_settings.volume,
599 global_settings.bass,
600 global_settings.treble,
601 global_settings.balance,
602 global_settings.loudness,
603 global_settings.avc,
604 global_settings.channel_config,
605 global_settings.stereo_width,
606 global_settings.mdb_strength,
607 global_settings.mdb_harmonics,
608 global_settings.mdb_center,
609 global_settings.mdb_shape,
610 global_settings.mdb_enable,
611 global_settings.superbass);
613 /* audio_init must to know the size of voice buffer so init voice first */
614 talk_init();
615 #endif /* CONFIG_CODEC != SWCODEC */
617 audio_init();
619 #if (CONFIG_CODEC == SWCODEC) && defined(HAVE_RECORDING) && !defined(SIMULATOR)
620 pcm_rec_init();
621 #endif
623 /* runtime database has to be initialized after audio_init() */
624 cpu_boost(false);
626 #if CONFIG_CHARGING
627 car_adapter_mode_init();
628 #endif
629 #ifdef IPOD_ACCESSORY_PROTOCOL
630 iap_setup(global_settings.serial_bitrate);
631 #endif
632 #ifdef HAVE_ACCESSORY_SUPPLY
633 accessory_supply_set(global_settings.accessory_supply);
634 #endif
635 #ifdef HAVE_LINEOUT_POWEROFF
636 lineout_set(global_settings.lineout_active);
637 #endif
638 #ifdef HAVE_HOTSWAP_STORAGE_AS_MAIN
639 check_bootfile(false); /* remember write time and filesize */
640 #endif
641 settings_apply_skins();
644 #ifdef CPU_PP
645 void cop_main(void)
647 /* This is the entry point for the coprocessor
648 Anyone not running an upgraded bootloader will never reach this point,
649 so it should not be assumed that the coprocessor be usable even on
650 platforms which support it.
652 A kernel thread is initially setup on the coprocessor and immediately
653 destroyed for purposes of continuity. The cop sits idle until at least
654 one thread exists on it. */
656 /* 3G doesn't have Rolo or dual core support yet */
657 #if NUM_CORES > 1
658 system_init();
659 kernel_init();
660 /* This should never be reached */
661 #endif
662 while(1) {
663 sleep_core(COP);
666 #endif /* CPU_PP */
668 #endif