A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 675 lines 16 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2007 by Linus Nielsen Feltzing 11 * 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. 16 * 17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 18 * KIND, either express or implied. 19 * 20 ****************************************************************************/ 21#include "config.h" 22 23#include <stdlib.h> 24#include <stdio.h> 25#include "inttypes.h" 26#include "string.h" 27#include "cpu.h" 28#include "system.h" 29#include "lcd.h" 30#include "lcd-remote.h" 31#include "scroll_engine.h" 32#include "../kernel-internal.h" 33#include "storage.h" 34#include "file_internal.h" 35#include "usb.h" 36#include "disk.h" 37#include "font.h" 38#include "adc.h" 39#include "backlight.h" 40#include "backlight-target.h" 41#include "button.h" 42#include "panic.h" 43#include "power.h" 44#include "powermgmt.h" 45#include "file.h" 46#include "eeprom_settings.h" 47#include "rbunicode.h" 48#include "pcf50606.h" 49#include "common.h" 50#include "rb-loader.h" 51#include "loader_strerror.h" 52#include "isp1362.h" 53#include "version.h" 54 55#include <stdarg.h> 56 57/* Maximum allowed firmware image size. 10MB is more than enough */ 58#define MAX_LOADSIZE (10*1024*1024) 59 60#define DRAM_START 0x31000000 61 62/* From common.c */ 63extern int line; 64extern int remote_line; 65 66static bool recovery_mode = false; 67 68/* Reset the cookie for the crt0 crash check */ 69static inline void __reset_cookie(void) 70{ 71 asm(" move.l #0,%d0"); 72 asm(" move.l %d0,0x10017ffc"); 73} 74 75void start_iriver_fw(void) 76{ 77 asm(" move.w #0x2700,%sr"); 78 __reset_cookie(); 79 asm(" movec.l %d0,%vbr"); 80 asm(" move.l 0,%sp"); 81 asm(" lea.l 8,%a0"); 82 asm(" jmp (%a0)"); 83} 84 85void start_firmware(void) 86{ 87 asm(" move.w #0x2700,%sr"); 88 __reset_cookie(); 89 asm(" move.l %0,%%d0" :: "i"(DRAM_START)); 90 asm(" movec.l %d0,%vbr"); 91 asm(" move.l %0,%%sp" :: "m"(*(int *)DRAM_START)); 92 asm(" move.l %0,%%a0" :: "m"(*(int *)(DRAM_START+4))); 93 asm(" jmp (%a0)"); 94} 95 96void start_flashed_romimage(void) 97{ 98 uint8_t *src = (uint8_t *)FLASH_ROMIMAGE_ENTRY; 99 uint32_t *reset_vector; 100 101 if (!detect_flashed_romimage()) 102 return ; 103 104 reset_vector = (uint32_t *)(&src[sizeof(struct flash_header)+sizeof(uint32_t)]); 105 106 asm(" move.w #0x2700,%sr"); 107 __reset_cookie(); 108 109 asm(" move.l %0,%%d0" :: "i"(DRAM_START)); 110 asm(" movec.l %d0,%vbr"); 111 asm(" move.l %0,%%sp" :: "m"(reset_vector[0])); 112 asm(" move.l %0,%%a0" :: "m"(reset_vector[1])); 113 asm(" jmp (%a0)"); 114 115 /* Failure */ 116 power_off(); 117} 118 119void start_flashed_ramimage(void) 120{ 121 struct flash_header hdr; 122 uint8_t *buf = (uint8_t *)DRAM_START; 123 uint8_t *src = (uint8_t *)FLASH_RAMIMAGE_ENTRY; 124 125 if (!detect_flashed_ramimage()) 126 return; 127 128 /* Load firmware from flash */ 129 cpu_boost(true); 130 memcpy(&hdr, src, sizeof(struct flash_header)); 131 src += sizeof(struct flash_header); 132 memcpy(buf, src, hdr.length); 133 cpu_boost(false); 134 135 start_firmware(); 136 137 /* Failure */ 138 power_off(); 139} 140 141void shutdown(void) 142{ 143 printf("Shutting down..."); 144 /* Reset the rockbox crash check. */ 145 firmware_settings.bl_version = 0; 146 eeprom_settings_store(); 147 148 /* We need to gracefully spin down the disk to prevent clicks. */ 149 if (ide_powered()) 150 { 151 /* Make sure ATA has been initialized. */ 152 storage_init(); 153 154 /* And put the disk into sleep immediately. */ 155 storage_sleepnow(); 156 } 157 158 sleep(HZ*2); 159 160 /* Backlight OFF */ 161 backlight_hw_off(); 162 remote_backlight_hw_off(); 163 164 __reset_cookie(); 165 power_off(); 166} 167 168/* Print the battery voltage (and a warning message). */ 169void check_battery(void) 170{ 171 int battery_voltage, batt_int, batt_frac; 172 173 battery_voltage = _battery_voltage(); 174 batt_int = battery_voltage / 1000; 175 batt_frac = (battery_voltage % 1000) / 10; 176 177 printf("Batt: %d.%02dV", batt_int, batt_frac); 178 179 if (battery_voltage <= 310) 180 { 181 printf("WARNING! BATTERY LOW!!"); 182 sleep(HZ*2); 183 } 184} 185 186void initialize_eeprom(void) 187{ 188 if (detect_original_firmware()) 189 return ; 190 191 if (!eeprom_settings_init()) 192 { 193 recovery_mode = true; 194 return ; 195 } 196 197 /* If bootloader version has not been reset, disk might 198 * not be intact. */ 199 if (firmware_settings.bl_version || !firmware_settings.disk_clean) 200 { 201 firmware_settings.disk_clean = false; 202 recovery_mode = true; 203 } 204 205 firmware_settings.bl_version = EEPROM_SETTINGS_BL_MINVER; 206 eeprom_settings_store(); 207} 208 209void try_flashboot(void) 210{ 211 if (!firmware_settings.initialized) 212 return ; 213 214 switch (firmware_settings.bootmethod) 215 { 216 case BOOT_DISK: 217 return; 218 219 case BOOT_ROM: 220 start_flashed_romimage(); 221 break; 222 223 case BOOT_RAM: 224 start_flashed_ramimage(); 225 break; 226 227 case BOOT_RECOVERY: 228 break; 229 } 230 231 recovery_mode = true; 232} 233 234void failsafe_menu(void) 235{ 236 static const char *options[] = 237 { 238 "Boot from disk", 239 "Boot RAM image", 240 "Boot ROM image", 241 "Shutdown" 242 }; 243 const int FAILSAFE_OPTIONS = sizeof(options) / sizeof(*options); 244 const long TIMEOUT = 15 * HZ; 245 long start_tick = current_tick; 246 int option = 3; 247 int button; 248 int defopt = -1; 249 char buf[32]; 250 int i; 251 252 reset_screen(); 253 printf("Bootloader %s", rbversion); 254 check_battery(); 255 printf("========================="); 256 line += FAILSAFE_OPTIONS; 257 printf(""); 258 printf(" [NAVI] to confirm."); 259 printf(" [REC] to set as default."); 260 printf(""); 261 262 if (firmware_settings.initialized) 263 { 264 defopt = firmware_settings.bootmethod; 265 if (defopt < 0 || defopt >= FAILSAFE_OPTIONS) 266 defopt = option; 267 } 268 269 while (current_tick - start_tick < TIMEOUT) 270 { 271 /* Draw the menu. */ 272 line = 3; 273 for (i = 0; i < FAILSAFE_OPTIONS; i++) 274 { 275 char *def = "[DEF]"; 276 char *arrow = "->"; 277 278 if (i != defopt) 279 def = ""; 280 if (i != option) 281 arrow = " "; 282 283 printf("%s %s %s", arrow, options[i], def); 284 } 285 286 snprintf(buf, sizeof(buf), "Time left: %lds", 287 (TIMEOUT - (current_tick - start_tick)) / HZ); 288 lcd_puts(0, 10, buf); 289 lcd_update(); 290 button = button_get_w_tmo(HZ); 291 292 if (button == BUTTON_NONE || button & SYS_EVENT) 293 continue ; 294 295 start_tick = current_tick; 296 297 /* Ignore the ON/PLAY -button because it can cause trouble 298 with the RTC alarm mod. */ 299 switch (button & ~(BUTTON_ON)) 300 { 301 case BUTTON_UP: 302 case BUTTON_RC_REW: 303 if (option > 0) 304 option--; 305 break ; 306 307 case BUTTON_DOWN: 308 case BUTTON_RC_FF: 309 if (option < FAILSAFE_OPTIONS-1) 310 option++; 311 break ; 312 313 case BUTTON_SELECT: 314 case BUTTON_RC_ON: 315 goto execute; 316 317 case BUTTON_REC: 318 case BUTTON_RC_REC: 319 if (firmware_settings.initialized) 320 { 321 firmware_settings.bootmethod = option; 322 eeprom_settings_store(); 323 defopt = option; 324 } 325 break ; 326 } 327 } 328 329 execute: 330 331 lcd_puts(0, 10, "Executing command..."); 332 lcd_update(); 333 sleep(HZ); 334 reset_screen(); 335 336 switch (option) 337 { 338 case BOOT_DISK: 339 return ; 340 341 case BOOT_RAM: 342 start_flashed_ramimage(); 343 printf("Image not found"); 344 break; 345 346 case BOOT_ROM: 347 start_flashed_romimage(); 348 printf("Image not found"); 349 break; 350 } 351 352 shutdown(); 353} 354 355/* From the pcf50606 driver */ 356extern unsigned char pcf50606_intregs[3]; 357 358void main(void) 359{ 360 int i; 361 int rc; 362 bool rc_on_button = false; 363 bool on_button = false; 364 bool rec_button = false; 365 bool hold_status = false; 366 int data; 367 bool rtc_alarm; 368 int mask; 369 bool usb_charge = false; 370 371 /* We want to read the buttons as early as possible, before the user 372 releases the ON button */ 373 374 /* Set GPIO33, GPIO37, GPIO38 and GPIO52 as general purpose inputs 375 (The ON and Hold buttons on the main unit and the remote) */ 376 or_l(0x00100062, &GPIO1_FUNCTION); 377 and_l(~0x00100062, &GPIO1_ENABLE); 378 379 data = GPIO1_READ; 380 if ((data & 0x20) == 0) 381 on_button = true; 382 383 if ((data & 0x40) == 0) 384 rc_on_button = true; 385 386 /* Set the default state of the hard drive power to OFF */ 387 ide_power_enable(false); 388 389 power_init(); 390 391 /* Check the interrupt registers if it was an RTC alarm */ 392 rtc_alarm = (pcf50606_intregs[0] & 0x80)?true:false; 393 394 /* Turn off if we believe the start was accidental */ 395 if(!(rtc_alarm || on_button || rc_on_button || 396 (usb_detect() == USB_INSERTED) || charger_inserted())) { 397 __reset_cookie(); 398 power_off(); 399 } 400 401 /* get rid of a nasty humming sound during boot */ 402 mask = disable_irq_save(); 403 pcf50606_write(0x3b, 0x00); /* GPOOD2 high Z */ 404 pcf50606_write(0x3b, 0x07); /* GPOOD2 low */ 405 restore_irq(mask); 406 407 /* Start with the main backlight OFF. */ 408 backlight_hw_init(); 409 backlight_hw_off(); 410 411 /* Remote backlight ON */ 412 remote_backlight_hw_on(); 413 414 system_init(); 415 kernel_init(); 416 417 /* Set up waitstates for the peripherals */ 418 set_cpu_frequency(0); /* PLL off */ 419 coldfire_set_pllcr_audio_bits(DEFAULT_PLLCR_AUDIO_BITS); 420 enable_irq(); 421 422 initialize_eeprom(); 423 424 isp1362_init(); 425 426 adc_init(); 427 button_init(); 428 sleep(HZ/50); /* Allow the button driver to check the buttons */ 429 430 /* Only check remote hold status if remote power button was actually used. */ 431 if (rc_on_button) 432 { 433 lcd_remote_init(); 434 435 if (remote_button_hold()) 436 hold_status = true; 437 } 438 439 /* Check main hold switch status too. */ 440 if (on_button && button_hold()) 441 { 442 hold_status = true; 443 } 444 445 /* Power on the hard drive early, to speed up the loading. */ 446 if (!hold_status && !recovery_mode) 447 { 448 ide_power_enable(true); 449 450 if (usb_detect() != USB_INSERTED) 451 try_flashboot(); 452 } 453 454 lcd_init(); 455 456 if (!rc_on_button) 457 lcd_remote_init(); 458 459 font_init(); 460 461 lcd_setfont(FONT_SYSFIXED); 462 463 backlight_init(); /* BUGFIX backlight_init MUST BE AFTER lcd_init */ 464 465 printf("Rockbox boot loader"); 466 printf("Version %s", rbversion); 467 468 rec_button = ((button_status() & BUTTON_REC) == BUTTON_REC) 469 || ((button_status() & BUTTON_RC_REC) == BUTTON_RC_REC); 470 471 check_battery(); 472 473 if(rtc_alarm) 474 printf("RTC alarm detected"); 475 476 /* Holding REC while starting runs the original firmware */ 477 if (detect_original_firmware() && rec_button) 478 { 479 printf("Starting original firmware..."); 480 start_iriver_fw(); 481 } 482 483 /* enable usb charging for charge mode and disk mode */ 484 if (usb_detect() == USB_INSERTED) 485 { 486 usb_charging_enable(USB_CHARGING_ENABLE); 487 usb_charge = true; 488 } 489 490 if(charger_inserted()) 491 { 492 const char charging_msg[] = "Charging..."; 493 const char complete_msg[] = "Charging complete"; 494 const char *msg; 495 int w, h; 496 bool blink_toggle = false; 497 bool request_start = false; 498 499 cpu_idle_mode(true); 500 501 while(charger_inserted() && !request_start) 502 { 503 long button = button_get_w_tmo(HZ); 504 505 switch(button) 506 { 507 case BUTTON_ON: 508 request_start = true; 509 break; 510 511 case BUTTON_NONE: /* Timeout */ 512 513 if(charging_state()) 514 { 515 /* To be replaced with a nice animation */ 516 blink_toggle = !blink_toggle; 517 msg = charging_msg; 518 } 519 else 520 { 521 blink_toggle = true; 522 msg = complete_msg; 523 } 524 525 font_getstringsize(msg, &w, &h, FONT_SYSFIXED); 526 reset_screen(); 527 if(blink_toggle) 528 lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, msg); 529 530 check_battery(); 531 break; 532 } 533 } 534 if(!request_start) 535 { 536 __reset_cookie(); 537 power_off(); 538 } 539 540 cpu_idle_mode(false); 541 } 542 543 usb_init(); 544 545 /* A hack to enter USB mode without using the USB thread */ 546 if(usb_detect() == USB_INSERTED) 547 { 548 const char msg[] = "Bootloader USB mode"; 549 int w, h; 550 font_getstringsize(msg, &w, &h, FONT_SYSFIXED); 551 reset_screen(); 552 lcd_putsxy((LCD_WIDTH-w)/2, (LCD_HEIGHT-h)/2, msg); 553 lcd_update(); 554 555 lcd_remote_puts(0, 3, msg); 556 lcd_remote_update(); 557 558 if (firmware_settings.initialized) 559 { 560 firmware_settings.disk_clean = false; 561 eeprom_settings_store(); 562 } 563 564 ide_power_enable(true); 565 storage_enable(false); 566 sleep(HZ/20); 567 usb_enable(true); 568 cpu_idle_mode(true); 569 while (usb_detect() == USB_INSERTED) 570 { 571 /* Print the battery status. */ 572 line = 0; 573 remote_line = 0; 574 check_battery(); 575 576 storage_spin(); /* Prevent the drive from spinning down */ 577 sleep(HZ); 578 } 579 580 cpu_idle_mode(false); 581 usb_enable(false); 582 583 reset_screen(); 584 lcd_update(); 585 } 586 587 /* disable usb charging if we enabled it earlier */ 588 if (usb_charge) 589 { 590 usb_charging_enable(USB_CHARGING_DISABLE); 591 usb_charge = false; 592 } 593 594 /* recheck the hold switch status as it may have changed */ 595 hold_status = (button_hold() || remote_button_hold()); 596 597 /* hold switch shutdown or failsafe recovery mode */ 598 if (hold_status || recovery_mode) 599 { 600 if (detect_original_firmware()) 601 { 602 printf("Hold switch on"); 603 shutdown(); 604 } 605 606 failsafe_menu(); 607 } 608 609 rc = storage_init(); 610 if(rc) 611 { 612 reset_screen(); 613 printf("ATA error: %d", rc); 614 printf("Insert USB cable and press"); 615 printf("a button"); 616 while(!(button_get(true) & BUTTON_REL)); 617 } 618 619 filesystem_init(); 620 621 rc = disk_mount_all(); 622 if (rc<=0) 623 { 624 struct partinfo pinfo; 625 reset_screen(); 626 printf("No partition found"); 627 for (int i = 0 ; i < NUM_VOLUMES ; i++) { 628 disk_partinfo(i, &pinfo); 629 if (pinfo.type) 630 printf("P%d T%02x S%llx", 631 i, pinfo.type, (unsigned long long)pinfo.size); 632 } 633 while(button_get(true) != SYS_USB_CONNECTED) {}; 634 } 635 636 printf("Loading firmware"); 637 i = load_firmware((unsigned char *)DRAM_START, BOOTFILE, MAX_LOADSIZE); 638 if(i <= EFILE_EMPTY) 639 printf("Error: %s", loader_strerror(i)); 640 641 if (i > 0) 642 start_firmware(); 643 644 if (!detect_original_firmware()) 645 { 646 printf("No firmware found on disk"); 647 sleep(HZ*2); 648 shutdown(); 649 } 650 else { 651 sleep(HZ*2); 652 start_iriver_fw(); 653 } 654} 655 656/* These functions are present in the firmware library, but we reimplement 657 them here because the originals do a lot more than we want */ 658int usb_screen(void) 659{ 660 return 0; 661} 662 663ucschar_t *bidi_l2v(const unsigned char *str, int orientation) 664{ 665 static ucschar_t utf_buf[SCROLL_LINE_SIZE]; 666 ucschar_t *target; 667 (void)orientation; 668 669 target = utf_buf; 670 671 while (*str) 672 str = utf8decode(str, target++); 673 *target = 0; 674 return utf_buf; 675}