A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 320 lines 7.7 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2008 by Maurus Cuelenaere 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 22#include "config.h" 23#include "jz4740.h" 24#include "../kernel-internal.h" 25#include "backlight.h" 26#include "font.h" 27#include "lcd.h" 28#include "file.h" 29#include "usb.h" 30#include "system.h" 31#include "button.h" 32#include "common.h" 33#include "rb-loader.h" 34#include "loader_strerror.h" 35#include "storage.h" 36#include "file_internal.h" 37#include "disk.h" 38#include "string.h" 39#include "adc.h" 40#include "version.h" 41 42extern void show_logo(void); 43extern void power_off(void); 44 45static void show_splash(int timeout, const char *msg) 46{ 47 reset_screen(); 48 lcd_putsxy( (LCD_WIDTH - (SYSFONT_WIDTH * strlen(msg))) / 2, 49 (LCD_HEIGHT - SYSFONT_HEIGHT) / 2, msg); 50 lcd_update(); 51 52 sleep(timeout); 53} 54 55static void usb_mode(void) 56{ 57 int button; 58 59 /* Init USB */ 60 usb_init(); 61 usb_start_monitoring(); 62 63 /* Wait for threads to connect */ 64 show_splash(HZ/2, "Waiting for USB"); 65 66 while (1) 67 { 68 button = button_get_w_tmo(HZ/2); 69 70 if (button == SYS_USB_CONNECTED) 71 break; /* Hit */ 72 } 73 74 if (button == SYS_USB_CONNECTED) 75 { 76 /* Got the message - wait for disconnect */ 77 show_splash(0, "Bootloader USB mode"); 78 79 usb_acknowledge(SYS_USB_CONNECTED_ACK); 80 81 while (1) 82 { 83 button = button_get(true); 84 if (button == SYS_USB_DISCONNECTED) 85 break; 86 } 87 } 88} 89 90static int boot_of(void) 91{ 92 int fd, rc, len, i, checksum = 0; 93 void (*kernel_entry)(int, void*, void*); 94 95 printf("Mounting disk..."); 96 rc = disk_mount_all(); 97 if (rc <= 0) 98 error(EDISK, rc, true); 99 100 /* TODO: get this from the NAND flash instead of SD */ 101 fd = open("/ccpmp.bin", O_RDONLY); 102 if(fd < 0) 103 return EFILE_NOT_FOUND; 104 105 lseek(fd, 4, SEEK_SET); 106 rc = read(fd, (char*)&len, 4); /* CPU is LE */ 107 if(rc < 4) 108 return EREAD_IMAGE_FAILED; 109 110 len += 8; 111 printf("Reading %d bytes...", len); 112 113 lseek(fd, 0, SEEK_SET); 114 rc = read(fd, (void*)0x80004000, len); 115 if(rc < len) 116 return EREAD_IMAGE_FAILED; 117 118 close(fd); 119 120 for(i=0; i<len; i++) 121 checksum += ((unsigned char*)0x80004000)[i]; 122 123 *((unsigned int*)0x80004000) = checksum; 124 125 printf("Starting the OF..."); 126 127 /* OF requires all clocks on */ 128 __cpm_start_all(); 129 130 disable_interrupt(); 131 commit_discard_idcache(); 132 133 for(i=8000; i>0; i--) 134 asm volatile("nop\n"); 135 136 kernel_entry = (void*) 0x80004008; 137 kernel_entry(0, "Jan 10 2008", "15:34:42"); /* Reversed from the SPL */ 138 139 return 0; /* Shouldn't happen */ 140} 141 142static int boot_rockbox(void) 143{ 144 int rc; 145 void (*kernel_entry)(void); 146 147 printf("Mounting disk..."); 148 rc = disk_mount_all(); 149 if (rc <= 0) 150 error(EDISK,rc, true); 151 152 printf("Loading firmware..."); 153 rc = load_firmware((unsigned char *)CONFIG_SDRAM_START, BOOTFILE, 0x400000); 154 if(rc <= EFILE_EMPTY) 155 return rc; 156 else 157 { 158 printf("Starting Rockbox..."); 159 adc_close(); /* Disable SADC, seems to fix the re-init Rockbox does */ 160 161 disable_interrupt(); 162 kernel_entry = (void*) CONFIG_SDRAM_START; 163 kernel_entry(); 164 165 return 0; /* Shouldn't happen */ 166 } 167} 168 169static void reset_configuration(void) 170{ 171 int rc; 172 173 rc = disk_mount_all(); 174 if (rc <= 0) 175 error(EDISK,rc, true); 176 177 if(rename(ROCKBOX_DIR "/config.cfg", ROCKBOX_DIR "/config.old") == 0) 178 show_splash(HZ/2, "Configuration reset successfully!"); 179 else 180 show_splash(HZ/2, "Couldn't reset configuration!"); 181} 182 183#define RECT_X (LCD_WIDTH/8) 184#define RECT_Y(i) (LCD_HEIGHT/20 + LCD_HEIGHT/10*i + RECT_HEIGHT*i) 185#define RECT_WIDTH (LCD_WIDTH*3/4) 186#define RECT_HEIGHT (LCD_HEIGHT/ARRAYLEN(strings) - LCD_HEIGHT/10) 187#define TEXT_X(i) (RECT_X + RECT_WIDTH/2 - strlen(strings[i])*SYSFONT_WIDTH/2) 188#define TEXT_Y(i) (RECT_Y(i) + RECT_HEIGHT/2 - SYSFONT_HEIGHT/2) 189static int boot_menu(void) 190{ 191 const char* strings[] = {"Boot Rockbox", "Boot OF", "USB mode", "Reset Rockbox configuration"}; 192 int button, touch, poweroff_repeat = 0; 193 unsigned int i; 194 195 verbose = true; 196 adc_init(); 197 198redraw: 199 lcd_clear_display(); 200 for(i=0; i<ARRAYLEN(strings); i++) 201 { 202 lcd_drawrect(RECT_X, RECT_Y(i), RECT_WIDTH, RECT_HEIGHT); 203 lcd_putsxy(TEXT_X(i), TEXT_Y(i), strings[i]); 204 } 205 lcd_update(); 206 207 while(1) 208 { 209 button = button_get_w_tmo(HZ/4); 210 if(button & BUTTON_TOUCHSCREEN) 211 { 212 touch = button_get_data(); 213 unsigned int x = touch & 0xFFFF, y = touch >> 16; 214 int found = -1; 215 for(i=0; i<ARRAYLEN(strings); i++) 216 { 217 if(x > RECT_X && x < RECT_X+RECT_WIDTH && 218 y > RECT_Y(i) && y < RECT_Y(i)+RECT_HEIGHT) 219 { 220 found = i; 221 break; 222 } 223 } 224 225 switch(found) 226 { 227 case 0: 228 reset_screen(); 229 boot_rockbox(); 230 break; 231 case 1: 232 reset_screen(); 233 boot_of(); 234 break; 235 case 2: 236 usb_mode(); 237 break; 238 case 3: 239 reset_configuration(); 240 break; 241 } 242 243 if(found != -1) 244 goto redraw; 245 } 246 else if(button & BUTTON_POWER) 247 { 248 if(poweroff_repeat++ > 8) 249 power_off(); 250 } 251 else 252 poweroff_repeat = 0; 253 } 254 return 0; 255} 256 257int main(void) 258{ 259 int rc; 260#ifdef HAVE_TOUCHSCREEN 261 int dummy; 262#endif 263 264 kernel_init(); 265 lcd_init(); 266 font_init(); 267 lcd_setfont(FONT_SYSFIXED); 268 button_init(); 269 backlight_init(); 270 271 show_logo(); 272 273 filesystem_init(); 274 275 rc = storage_init(); 276 if(rc) 277 error(EATA, rc, true); 278 279 /* Don't mount the disks yet, there could be file system/partition errors 280 which are fixable in USB mode */ 281 282#ifdef HAVE_TOUCHSCREEN 283 rc = button_read_device(&dummy); 284#else 285 rc = button_read_device(); 286#endif 287 288 if(rc) 289 verbose = true; 290 291#ifdef BUTTON_VOL_UP 292 if(rc & BUTTON_VOL_UP || 293#endif 294#ifdef BUTTON_POWER 295 rc & BUTTON_POWER || 296#endif 297 0) 298 rc = boot_menu(); 299 300 if(verbose) 301 reset_screen(); 302 printf(MODEL_NAME" Rockbox Bootloader"); 303 printf("Version %s", rbversion); 304 305#ifdef HAS_BUTTON_HOLD 306 if(button_hold()) 307 rc = boot_of(); 308 else 309#endif 310 rc = boot_rockbox(); 311 312 if(rc <= EFILE_EMPTY) 313 printf("Error: %s", loader_strerror(rc)); 314 315 /* Halt */ 316 while (1) 317 core_idle(); 318 319 return 0; 320}