A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
at master 2998 lines 95 kB view raw
1/*************************************************************************** 2 * __________ __ ___. 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 7 * \/ \/ \/ \/ \/ 8 * $Id$ 9 * 10 * Copyright (C) 2002 Heikki Hannikainen 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 <stdlib.h> 24#include <stdio.h> 25#include <stdbool.h> 26#include <string-extra.h> 27#include "lcd.h" 28#include "lang.h" 29#include "menu.h" 30#include "debug_menu.h" 31#include "kernel.h" 32#include "action.h" 33#include "debug.h" 34#include "thread.h" 35#include "powermgmt.h" 36#include "system.h" 37#include "font.h" 38#include "audio.h" 39#include "settings.h" 40#include "list.h" 41#include "dir.h" 42#include "panic.h" 43#include "screens.h" 44#include "misc.h" 45#include "splash.h" 46#include "shortcuts.h" 47#include "dircache.h" 48#include "viewport.h" 49#ifdef HAVE_TAGCACHE 50#include "tagcache.h" 51#endif 52#ifdef HAVE_REMOTE_LCD 53#include "lcd-remote.h" 54#endif 55#include "crc32.h" 56#include "logf.h" 57#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 58#include "disk.h" 59#include "adc.h" 60#include "usb.h" 61#include "rtc.h" 62#include "storage.h" 63#include "fs_defines.h" 64#include "eeprom_24cxx.h" 65#if (CONFIG_STORAGE & STORAGE_MMC) || (CONFIG_STORAGE & STORAGE_SD) 66#include "sdmmc.h" 67#endif 68#if (CONFIG_STORAGE & STORAGE_ATA) 69#include "ata.h" 70#endif 71#endif /* CONFIG_PLATFORM & PLATFORM_NATIVE */ 72#include "power.h" 73 74#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) \ 75 || defined(SONY_NWZ_LINUX)) \ 76 && CONFIG_TUNER != 0 77#include "tuner.h" 78#include "radio.h" 79#endif 80 81#include "scrollbar.h" 82#include "peakmeter.h" 83#include "skin_engine/skin_engine.h" 84#include "logfdisp.h" 85#include "core_alloc.h" 86#include "pcmbuf.h" 87#include "buffering.h" 88#include "playback.h" 89#if defined(HAVE_SPDIF_OUT) || defined(HAVE_SPDIF_IN) 90#include "spdif.h" 91#endif 92#ifdef IRIVER_H300_SERIES 93#include "pcf50606.h" /* for pcf50606_read */ 94#endif 95#ifdef IAUDIO_X5 96#include "ds2411.h" 97#endif 98#include "hwcompat.h" 99#include "button.h" 100#if CONFIG_RTC == RTC_PCF50605 101#include "pcf50605.h" 102#endif 103#include "appevents.h" 104 105#if defined(HAVE_AS3514) && CONFIG_CHARGING 106#include "ascodec.h" 107#endif 108 109#ifdef IPOD_NANO2G 110#include "pmu-target.h" 111#endif 112 113#ifdef SANSA_CONNECT 114#include "avr-sansaconnect.h" 115#endif 116 117#ifdef HAVE_USBSTACK 118#include "usb_core.h" 119#ifdef USB_ENABLE_AUDIO 120#include "../usbstack/usb_audio.h" 121#endif 122#endif 123 124#include "talk.h" 125 126#if defined(HAVE_DEVICEDATA)// && !defined(SIMULATOR) 127#include "devicedata.h" 128#endif 129 130#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) 131#include "bootdata.h" 132#include "multiboot.h" 133#include "rbpaths.h" 134#include "pathfuncs.h" 135#include "rb-loader.h" 136#endif 137 138#if defined(IPOD_6G) && !defined(SIMULATOR) 139#include "norboot-target.h" 140#endif 141 142#if defined(IPOD_ACCESSORY_PROTOCOL) 143#include "iap.h" 144#endif 145 146#define SCREEN_MAX_CHARS (LCD_WIDTH / SYSFONT_WIDTH) 147 148static const char* threads_getname(int selected_item, void *data, 149 char *buffer, size_t buffer_len) 150{ 151 int *x_offset = (int*) data; 152 153#if NUM_CORES > 1 154 if (selected_item < (int)NUM_CORES) 155 { 156 struct core_debug_info coreinfo; 157 core_get_debug_info(selected_item, &coreinfo); 158 snprintf(buffer, buffer_len, "Idle (%2d): %2d%%", selected_item, 159 coreinfo.idle_stack_usage); 160 return buffer; 161 } 162 163 selected_item -= NUM_CORES; 164#endif 165 166 const char *fmtstr = "%2d: ---"; 167 168 struct thread_debug_info threadinfo; 169 if (thread_get_debug_info(selected_item, &threadinfo) > 0) 170 { 171 fmtstr = "%2d:" IF_COP(" (%d)") " %s%n" IF_PRIO(" %2d %2d") 172 IFN_SDL(" %2d%% %2d%%") " %s"; 173 } 174 int status_len; 175 size_t len = snprintf(buffer, buffer_len, fmtstr, 176 selected_item, 177 IF_COP(threadinfo.core,) 178 threadinfo.statusstr, 179 &status_len, 180 IF_PRIO(threadinfo.base_priority, threadinfo.current_priority,) 181 IFN_SDL(threadinfo.stack_usage_cur, threadinfo.stack_usage,) 182 threadinfo.name); 183 184 int start = 0; 185#if LCD_WIDTH <= 128 186 if (len >= SCREEN_MAX_CHARS) 187 { 188 int ch_offset = (*x_offset)%(len-1); 189 int rem = SCREEN_MAX_CHARS - (len - ch_offset); 190 if (rem > 0) 191 ch_offset -= rem; 192 193 if (ch_offset > 0) 194 { 195 /* don't scroll the # and status */ 196 status_len++; 197 if ((unsigned int)ch_offset + status_len < buffer_len) 198 memmove(&buffer[ch_offset], &buffer[0], status_len); 199 start = ch_offset; 200 } 201 } 202#else 203 (void) x_offset; 204 (void) len; 205#endif 206 return &buffer[start]; 207} 208 209static int dbg_threads_action_callback(int action, struct gui_synclist *lists) 210{ 211 212 if (action == ACTION_NONE) 213 { 214 return ACTION_REDRAW; 215 } 216#if LCD_WIDTH <= 128 217 int *x_offset = ((int*) lists->data); 218 if (action == ACTION_STD_OK) 219 { 220 *x_offset += 1; 221 action = ACTION_REDRAW; 222 } 223 else if (IS_SYSEVENT(action)) 224 { 225 return ACTION_REDRAW; 226 } 227 else if (action != ACTION_UNKNOWN) 228 { 229 *x_offset = 0; 230 } 231#else 232 (void) lists; 233#endif 234 return action; 235} 236/* Test code!!! */ 237static bool dbg_os(void) 238{ 239 struct simplelist_info info; 240 int xoffset = 0; 241 242 simplelist_info_init(&info, IF_COP("Core and ") "Stack usage:", 243 MAXTHREADS IF_COP( + NUM_CORES ), &xoffset); 244 info.scroll_all = false; 245 info.action_callback = dbg_threads_action_callback; 246 info.get_name = threads_getname; 247 return simplelist_show_list(&info); 248} 249 250#ifdef __linux__ 251#include "cpuinfo-linux.h" 252 253#define MAX_STATES 16 254static struct time_state states[MAX_STATES]; 255 256static const char* get_cpuinfo(int selected_item, void *data, 257 char *buffer, size_t buffer_len) 258{ 259 (void)data;(void)buffer_len; 260 const char* text; 261 long time, diff; 262 struct cpuusage us; 263 static struct cpuusage last_us; 264 int state_count = *(int*)data; 265 266 if (cpuusage_linux(&us) != 0) 267 return NULL; 268 269 switch(selected_item) 270 { 271 case 0: 272 diff = abs(last_us.usage - us.usage); 273 sprintf(buffer, "Usage: %ld.%02ld%% (%c %ld.%02ld)", 274 us.usage/100, us.usage%100, 275 (us.usage >= last_us.usage) ? '+':'-', 276 diff/100, diff%100); 277 last_us.usage = us.usage; 278 return buffer; 279 case 1: 280 text = "User"; 281 time = us.utime; 282 diff = us.utime - last_us.utime; 283 last_us.utime = us.utime; 284 break; 285 case 2: 286 text = "Sys"; 287 time = us.stime; 288 diff = us.stime - last_us.stime; 289 last_us.stime = us.stime; 290 break; 291 case 3: 292 text = "Real"; 293 time = us.rtime; 294 diff = us.rtime - last_us.rtime; 295 last_us.rtime = us.rtime; 296 break; 297 case 4: 298 return "*** Per CPU freq stats ***"; 299 default: 300 { 301 int cpu = (selected_item - 5) / (state_count + 1); 302 int cpu_line = (selected_item - 5) % (state_count + 1); 303 304 /* scaling info */ 305 int min_freq = min_scaling_frequency(cpu); 306 int cur_freq = current_scaling_frequency(cpu); 307 /* fallback if scaling frequency is not available */ 308 if(cur_freq <= 0) 309 cur_freq = frequency_linux(cpu); 310 int max_freq = max_scaling_frequency(cpu); 311 char governor[20]; 312 bool have_governor = current_scaling_governor(cpu, governor, sizeof(governor)); 313 if(cpu_line == 0) 314 { 315 sprintf(buffer, 316 " CPU%d: %s: %d/%d/%d MHz", 317 cpu, 318 have_governor ? governor : "Min/Cur/Max freq", 319 min_freq > 0 ? min_freq/1000 : -1, 320 cur_freq > 0 ? cur_freq/1000 : -1, 321 max_freq > 0 ? max_freq/1000 : -1); 322 } 323 else 324 { 325 cpustatetimes_linux(cpu, states, ARRAYLEN(states)); 326 snprintf(buffer, buffer_len, " %ld %ld", 327 states[cpu_line-1].frequency, 328 states[cpu_line-1].time); 329 } 330 return buffer; 331 } 332 } 333 sprintf(buffer, "%s: %ld.%02lds (+ %ld.%02ld)", text, 334 time / us.hz, time % us.hz, 335 diff / us.hz, diff % us.hz); 336 return buffer; 337} 338 339static int cpuinfo_cb(int action, struct gui_synclist *lists) 340{ 341 (void)lists; 342 if (action == ACTION_NONE) 343 action = ACTION_REDRAW; 344 return action; 345} 346 347static bool dbg_cpuinfo(void) 348{ 349 struct simplelist_info info; 350 int cpu_count = MAX(cpucount_linux(), 1); 351 int state_count = cpustatetimes_linux(0, states, ARRAYLEN(states)); 352 printf("%s(): %d %d\n", __func__, cpu_count, state_count); 353 simplelist_info_init(&info, "CPU info:", 5 + cpu_count*(state_count+1), &state_count); 354 info.get_name = get_cpuinfo; 355 info.action_callback = cpuinfo_cb; 356 info.timeout = HZ; 357 info.scroll_all = true; 358 return simplelist_show_list(&info); 359} 360 361#endif 362 363static unsigned int ticks, freq_sum; 364#ifndef CPU_MULTI_FREQUENCY 365static unsigned int boost_ticks; 366#endif 367 368static void dbg_audio_task(void) 369{ 370#ifdef CPUFREQ_NORMAL 371#ifndef CPU_MULTI_FREQUENCY 372 if(FREQ > CPUFREQ_NORMAL) 373 boost_ticks++; 374#endif 375 freq_sum += FREQ/1000000; /* in MHz */ 376#endif 377 ticks++; 378} 379 380static bool dbg_buffering_thread(void) 381{ 382 int button; 383 int line; 384 bool done = false; 385 size_t bufused; 386 size_t bufsize = pcmbuf_get_bufsize(); 387 int pcmbufdescs = pcmbuf_descs(); 388 struct buffering_debug d; 389 size_t filebuflen = audio_get_filebuflen(); 390 /* This is a size_t, but call it a long so it puts a - when it's bad. */ 391#if LCD_WIDTH > 96 392 #define STR_DATAREM "data_rem" 393 const char * const fmt_used = "%s: %6ld/%ld"; 394#else /* clipzip, ?*/ 395 #define STR_DATAREM "remain" 396 const char * const fmt_used = "%s:%ld/%ld"; 397#endif 398 399#ifndef CPU_MULTI_FREQUENCY 400 boost_ticks = 0; 401#endif 402 ticks = freq_sum = 0; 403 404 tick_add_task(dbg_audio_task); 405 406 FOR_NB_SCREENS(i) 407 screens[i].setfont(FONT_SYSFIXED); 408 409 while(!done) 410 { 411 button = get_action(CONTEXT_STD,HZ/5); 412 switch(button) 413 { 414 case ACTION_STD_NEXT: 415 audio_next(); 416 break; 417 case ACTION_STD_PREV: 418 audio_prev(); 419 break; 420 case ACTION_STD_CANCEL: 421 done = true; 422 break; 423 } 424 425 buffering_get_debugdata(&d); 426 bufused = bufsize - pcmbuf_free(); 427 428 FOR_NB_SCREENS(i) 429 { 430 line = 0; 431 screens[i].clear_display(); 432 433 434 screens[i].putsf(0, line++, fmt_used, "pcm", (long) bufused, (long) bufsize); 435 436 gui_scrollbar_draw(&screens[i],0, line*SYSFONT_HEIGHT, screens[i].lcdwidth, 6, 437 bufsize, 0, bufused, HORIZONTAL); 438 line++; 439 440 screens[i].putsf(0, line++, fmt_used, "alloc", audio_filebufused(), 441 (long) filebuflen); 442 443#if LCD_HEIGHT > 80 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_HEIGHT > 80) 444 if (screens[i].lcdheight > 80) 445 { 446 gui_scrollbar_draw(&screens[i],0, line*SYSFONT_HEIGHT, screens[i].lcdwidth, 6, 447 filebuflen, 0, audio_filebufused(), HORIZONTAL); 448 line++; 449 450 screens[i].putsf(0, line++, fmt_used, "real", (long)d.buffered_data, 451 (long)filebuflen); 452 453 gui_scrollbar_draw(&screens[i],0, line*SYSFONT_HEIGHT, screens[i].lcdwidth, 6, 454 filebuflen, 0, (long)d.buffered_data, HORIZONTAL); 455 line++; 456 } 457#endif 458 459 screens[i].putsf(0, line++, fmt_used, "usefl", (long)(d.useful_data), 460 (long)filebuflen); 461 462#if LCD_HEIGHT > 80 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_HEIGHT > 80) 463 if (screens[i].lcdheight > 80) 464 { 465 gui_scrollbar_draw(&screens[i],0, line*SYSFONT_HEIGHT, screens[i].lcdwidth, 6, 466 filebuflen, 0, d.useful_data, HORIZONTAL); 467 line++; 468 } 469#endif 470 471 screens[i].putsf(0, line++, "%s: %ld", STR_DATAREM, (long)d.data_rem); 472 473 screens[i].putsf(0, line++, "track count: %2u", audio_track_count()); 474 475 screens[i].putsf(0, line++, "handle count: %d", (int)d.num_handles); 476 477#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 478 screens[i].putsf(0, line++, "cpu freq: %3dMHz", 479 (int)((FREQ + 500000) / 1000000)); 480#endif 481 482 if (ticks > 0) 483 { 484 int avgclock = freq_sum * 10 / ticks; /* in 100 kHz */ 485#ifdef CPU_MULTI_FREQUENCY 486 int boostquota = (avgclock * 100 - CPUFREQ_NORMAL/1000) / 487 ((CPUFREQ_MAX - CPUFREQ_NORMAL) / 1000000); /* in 0.1 % */ 488#else 489 int boostquota = boost_ticks * 1000 / ticks; /* in 0.1 % */ 490#endif 491 screens[i].putsf(0, line++, "boost:%3d.%d%% (%d.%dMHz)", 492 boostquota/10, boostquota%10, avgclock/10, avgclock%10); 493 } 494 495 screens[i].putsf(0, line++, "pcmbufdesc: %2d/%2d", 496 pcmbuf_used_descs(), pcmbufdescs); 497 screens[i].putsf(0, line++, "watermark: %6d", 498 (int)(d.watermark)); 499 500 screens[i].update(); 501 } 502 } 503 504 tick_remove_task(dbg_audio_task); 505 506 FOR_NB_SCREENS(i) 507 screens[i].setfont(FONT_UI); 508 509 return false; 510#undef STR_DATAREM 511} 512 513#ifdef BUFLIB_DEBUG_PRINT 514static const char* bf_getname(int selected_item, void *data, 515 char *buffer, size_t buffer_len) 516{ 517 (void)data; 518 core_print_block_at(selected_item, buffer, buffer_len); 519 return buffer; 520} 521 522static int bf_action_cb(int action, struct gui_synclist* list) 523{ 524 if (action == ACTION_STD_OK) 525 { 526 if (gui_synclist_get_sel_pos(list) == 0 && core_test_free()) 527 { 528 splash(HZ, "Freed test handle. New alloc should trigger compact"); 529 } 530 else 531 { 532 splash(HZ/1, "Attempting a 64k allocation"); 533 int handle = core_alloc(64<<10); 534 splash(HZ/2, (handle > 0) ? "Success":"Fail"); 535 /* for some reason simplelist doesn't allow adding items here if 536 * info.get_name is given, so use normal list api */ 537 gui_synclist_set_nb_items(list, core_get_num_blocks()); 538 core_free(handle); 539 } 540 action = ACTION_REDRAW; 541 } 542 return action; 543} 544 545static bool dbg_buflib_allocs(void) 546{ 547 struct simplelist_info info; 548 simplelist_info_init(&info, "mem allocs", core_get_num_blocks(), NULL); 549 info.get_name = bf_getname; 550 info.action_callback = bf_action_cb; 551 info.timeout = HZ; 552 return simplelist_show_list(&info); 553} 554#endif /* BUFLIB_DEBUG_PRINT */ 555 556#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 557static const char* dbg_partitions_getname(int selected_item, void *data, 558 char *buffer, size_t buffer_len) 559{ 560 (void)data; 561 int partition = selected_item/2; 562 563 struct partinfo p; 564 if (!disk_partinfo(partition, &p)) 565 return buffer; 566 567 // XXX fix this up to use logical sector size 568 // XXX and if mounted, show free info... 569 if (selected_item%2) 570 { 571 snprintf(buffer, buffer_len, " T:%x %lu MB", p.type, 572 (unsigned long)(p.size / ( 2048 / ( SECTOR_SIZE / 512 )))); 573 } 574 else 575 { 576 snprintf(buffer, buffer_len, "P%d: S:%llx", partition, (unsigned long long)p.start); 577 } 578 return buffer; 579} 580 581static bool dbg_partitions(void) 582{ 583 struct simplelist_info info; 584 simplelist_info_init(&info, "Partition Info", NUM_DRIVES * MAX_PARTITIONS_PER_DRIVE, NULL); 585 info.selection_size = 2; 586 info.scroll_all = true; 587 info.get_name = dbg_partitions_getname; 588 return simplelist_show_list(&info); 589} 590#endif /* PLATFORM_NATIVE */ 591 592#if defined(CPU_COLDFIRE) && defined(HAVE_SPDIF_OUT) 593static bool dbg_spdif(void) 594{ 595 int line; 596 unsigned int control; 597 int x; 598 char *s; 599 int category; 600 int generation; 601 unsigned int interruptstat; 602 bool valnogood, symbolerr, parityerr; 603 bool done = false; 604 bool spdif_src_on; 605 int spdif_source = spdif_get_output_source(&spdif_src_on); 606 spdif_set_output_source(AUDIO_SRC_SPDIF IF_SPDIF_POWER_(, true)); 607 608 lcd_clear_display(); 609 lcd_setfont(FONT_SYSFIXED); 610 611#ifdef HAVE_SPDIF_POWER 612 spdif_power_enable(true); /* We need SPDIF power for both sending & receiving */ 613#endif 614 615 while (!done) 616 { 617 line = 0; 618 619 control = EBU1RCVCCHANNEL1; 620 interruptstat = INTERRUPTSTAT; 621 INTERRUPTCLEAR = 0x03c00000; 622 623 valnogood = (interruptstat & 0x01000000)?true:false; 624 symbolerr = (interruptstat & 0x00800000)?true:false; 625 parityerr = (interruptstat & 0x00400000)?true:false; 626 627 lcd_putsf(0, line++, "Val: %s Sym: %s Par: %s", 628 valnogood?"--":"OK", 629 symbolerr?"--":"OK", 630 parityerr?"--":"OK"); 631 632 lcd_putsf(0, line++, "Status word: %08x", (int)control); 633 634 line++; 635 636 x = control >> 31; 637 lcd_putsf(0, line++, "PRO: %d (%s)", 638 x, x?"Professional":"Consumer"); 639 640 x = (control >> 30) & 1; 641 lcd_putsf(0, line++, "Audio: %d (%s)", 642 x, x?"Non-PCM":"PCM"); 643 644 x = (control >> 29) & 1; 645 lcd_putsf(0, line++, "Copy: %d (%s)", 646 x, x?"Permitted":"Inhibited"); 647 648 x = (control >> 27) & 7; 649 switch(x) 650 { 651 case 0: 652 s = "None"; 653 break; 654 case 1: 655 s = "50/15us"; 656 break; 657 default: 658 s = "Reserved"; 659 break; 660 } 661 lcd_putsf(0, line++, "Preemphasis: %d (%s)", x, s); 662 663 x = (control >> 24) & 3; 664 lcd_putsf(0, line++, "Mode: %d", x); 665 666 category = (control >> 17) & 127; 667 switch(category) 668 { 669 case 0x00: 670 s = "General"; 671 break; 672 case 0x40: 673 s = "Audio CD"; 674 break; 675 default: 676 s = "Unknown"; 677 } 678 lcd_putsf(0, line++, "Category: 0x%02x (%s)", category, s); 679 680 x = (control >> 16) & 1; 681 generation = x; 682 if(((category & 0x70) == 0x10) || 683 ((category & 0x70) == 0x40) || 684 ((category & 0x78) == 0x38)) 685 { 686 generation = !generation; 687 } 688 lcd_putsf(0, line++, "Generation: %d (%s)", 689 x, generation?"Original":"No ind."); 690 691 x = (control >> 12) & 15; 692 lcd_putsf(0, line++, "Source: %d", x); 693 694 695 x = (control >> 8) & 15; 696 switch(x) 697 { 698 case 0: 699 s = "Unspecified"; 700 break; 701 case 8: 702 s = "A (Left)"; 703 break; 704 case 4: 705 s = "B (Right)"; 706 break; 707 default: 708 s = ""; 709 break; 710 } 711 lcd_putsf(0, line++, "Channel: %d (%s)", x, s); 712 713 x = (control >> 4) & 15; 714 switch(x) 715 { 716 case 0: 717 s = "44.1kHz"; 718 break; 719 case 0x4: 720 s = "48kHz"; 721 break; 722 case 0xc: 723 s = "32kHz"; 724 break; 725 } 726 lcd_putsf(0, line++, "Frequency: %d (%s)", x, s); 727 728 x = (control >> 2) & 3; 729 lcd_putsf(0, line++, "Clock accuracy: %d", x); 730 line++; 731 732#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 733 lcd_putsf(0, line++, "Measured freq: %ldHz", 734 spdif_measure_frequency()); 735#endif 736 737 lcd_update(); 738 739 if (action_userabort(HZ/10)) 740 break; 741 } 742 743 spdif_set_output_source(spdif_source IF_SPDIF_POWER_(, spdif_src_on)); 744 745#ifdef HAVE_SPDIF_POWER 746 spdif_power_enable(global_settings.spdif_enable); 747#endif 748 749 lcd_setfont(FONT_UI); 750 return false; 751} 752#endif /* CPU_COLDFIRE */ 753 754#if (CONFIG_RTC == RTC_PCF50605) && (CONFIG_PLATFORM & PLATFORM_NATIVE) 755static bool dbg_pcf(void) 756{ 757 int line; 758 759 lcd_setfont(FONT_SYSFIXED); 760 lcd_clear_display(); 761 762 while(1) 763 { 764 line = 0; 765 766 lcd_putsf(0, line++, "DCDC1: %02x", pcf50605_read(0x1b)); 767 lcd_putsf(0, line++, "DCDC2: %02x", pcf50605_read(0x1c)); 768 lcd_putsf(0, line++, "DCDC3: %02x", pcf50605_read(0x1d)); 769 lcd_putsf(0, line++, "DCDC4: %02x", pcf50605_read(0x1e)); 770 lcd_putsf(0, line++, "DCDEC1: %02x", pcf50605_read(0x1f)); 771 lcd_putsf(0, line++, "DCDEC2: %02x", pcf50605_read(0x20)); 772 lcd_putsf(0, line++, "DCUDC1: %02x", pcf50605_read(0x21)); 773 lcd_putsf(0, line++, "DCUDC2: %02x", pcf50605_read(0x22)); 774 lcd_putsf(0, line++, "IOREGC: %02x", pcf50605_read(0x23)); 775 lcd_putsf(0, line++, "D1REGC: %02x", pcf50605_read(0x24)); 776 lcd_putsf(0, line++, "D2REGC: %02x", pcf50605_read(0x25)); 777 lcd_putsf(0, line++, "D3REGC: %02x", pcf50605_read(0x26)); 778 lcd_putsf(0, line++, "LPREG1: %02x", pcf50605_read(0x27)); 779 lcd_update(); 780 if (action_userabort(HZ/10)) 781 { 782 lcd_setfont(FONT_UI); 783 return false; 784 } 785 } 786 787 lcd_setfont(FONT_UI); 788 return false; 789} 790#endif 791 792#ifdef HAVE_ADJUSTABLE_CPU_FREQ 793static bool dbg_cpufreq(void) 794{ 795 int line; 796 int button; 797 int x = 0; 798 bool done = false; 799 800 lcd_setfont(FONT_SYSFIXED); 801 lcd_clear_display(); 802 803 while(!done) 804 { 805 line = 0; 806 807 int temp = FREQ / 1000; 808 lcd_putsf(x, line++, "Frequency: %ld.%ld MHz", temp / 1000, temp % 1000); 809 lcd_putsf(x, line++, "boost_counter: %d", get_cpu_boost_counter()); 810 811#ifdef HAVE_ADJUSTABLE_CPU_VOLTAGE 812 extern int get_cpu_voltage_setting(void); 813 temp = get_cpu_voltage_setting(); 814 lcd_putsf(x, line++, "CPU voltage: %d.%03dV", temp / 1000, temp % 1000); 815#endif 816 817 lcd_update(); 818 button = get_action(CONTEXT_STD,HZ/10); 819 820 switch(button) 821 { 822 case ACTION_STD_PREV: 823 cpu_boost(true); 824 break; 825 826 case ACTION_STD_NEXT: 827 cpu_boost(false); 828 break; 829 case ACTION_STD_MENU: 830 x--; 831 break; 832 case ACTION_STD_OK: 833 x = 0; 834 while (get_cpu_boost_counter() > 0) 835 cpu_boost(false); 836 set_cpu_frequency(CPUFREQ_DEFAULT); 837 break; 838 839 case ACTION_STD_CANCEL: 840 done = true;; 841 } 842 lcd_clear_display(); 843 } 844 lcd_setfont(FONT_UI); 845 return false; 846} 847#endif /* HAVE_ADJUSTABLE_CPU_FREQ */ 848 849#if defined(HAVE_TSC2100) && (CONFIG_PLATFORM & PLATFORM_NATIVE) 850#include "tsc2100.h" 851static const char* tsc2100_debug_getname(int selected_item, void * data, 852 char *buffer, size_t buffer_len) 853{ 854 int *page = (int*)data; 855 bool reserved = false; 856 switch (*page) 857 { 858 case 0: 859 if ((selected_item > 0x0a) || 860 (selected_item == 0x04) || 861 (selected_item == 0x08)) 862 reserved = true; 863 break; 864 case 1: 865 if ((selected_item > 0x05) || 866 (selected_item == 0x02)) 867 reserved = true; 868 break; 869 case 2: 870 if (selected_item > 0x1e) 871 reserved = true; 872 break; 873 } 874 if (reserved) 875 snprintf(buffer, buffer_len, "%02x: RSVD", selected_item); 876 else 877 snprintf(buffer, buffer_len, "%02x: %04x", selected_item, 878 tsc2100_readreg(*page, selected_item)&0xffff); 879 return buffer; 880} 881static int tsc2100debug_action_callback(int action, struct gui_synclist *lists) 882{ 883 int *page = (int*)lists->data; 884 if (action == ACTION_STD_OK) 885 { 886 *page = (*page+1)%3; 887 snprintf((char*)lists->title, 32, "tsc2100 registers - Page %d", *page); 888 return ACTION_REDRAW; 889 } 890 return action; 891} 892static bool tsc2100_debug(void) 893{ 894 int page = 0; 895 char title[32]; 896 snprintf(title, 32, "tsc2100 registers - Page %d", page); 897 struct simplelist_info info; 898 simplelist_info_init(&info, title, 32, &page); 899 info.timeout = HZ/100; 900 info.get_name = tsc2100_debug_getname; 901 info.action_callback= tsc2100debug_action_callback; 902 return simplelist_show_list(&info); 903} 904#endif 905#if (CONFIG_BATTERY_MEASURE != 0) && !defined(SIMULATOR) 906/* 907 * view_battery() shows a automatically scaled graph of the battery voltage 908 * over time. Usable for estimating battery life / charging rate. 909 * The power_history array is updated in power_thread of powermgmt.c. 910 */ 911 912#define BAT_LAST_VAL MIN(LCD_WIDTH, POWER_HISTORY_LEN) 913#define BAT_TSPACE 20 914#define BAT_YSPACE (LCD_HEIGHT - BAT_TSPACE) 915 916 917static bool view_battery(void) 918{ 919 extern struct battery_tables_t device_battery_tables; /* powermgmt.c */ 920 unsigned short *power_history = device_battery_tables.history; 921 int view = 0; 922 int i, x, y, z, y1, y2, grid, graph; 923 unsigned short maxv, minv; 924 lcd_setfont(FONT_SYSFIXED); 925 926 while(1) 927 { 928 lcd_clear_display(); 929 switch (view) { 930 case 0: /* voltage history graph */ 931 /* Find maximum and minimum voltage for scaling */ 932 minv = power_history[0]; 933 maxv = minv + 1; 934 for (i = 1; i < BAT_LAST_VAL && power_history[i]; i++) { 935 if (power_history[i] > maxv) 936 maxv = power_history[i]; 937 if (power_history[i] < minv) 938 minv = power_history[i]; 939 } 940 /* print header */ 941#if (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) 942 /* adjust grid scale */ 943 if ((maxv - minv) > 50) 944 grid = 50; 945 else 946 grid = 5; 947 948 lcd_putsf(0, 0, "%s %d.%03dV", "Battery", power_history[0] / 1000, 949 power_history[0] % 1000); 950 lcd_putsf(0, 1, "%d.%03d-%d.%03dV (%2dmV)", 951 minv / 1000, minv % 1000, maxv / 1000, maxv % 1000, 952 grid); 953#elif (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) 954 /* adjust grid scale */ 955 if ((maxv - minv) > 10) 956 grid = 10; 957 else 958 grid = 1; 959 lcd_putsf(0, 0, "%s %d%%", "Battery", power_history[0]); 960 lcd_putsf(0, 1, "%d%%-%d%% (%d %%)", minv, maxv, grid); 961#endif 962 963 i = 1; 964 while ((y = (minv - (minv % grid)+i*grid)) < maxv) 965 { 966 graph = ((y-minv)*BAT_YSPACE)/(maxv-minv); 967 graph = LCD_HEIGHT-1 - graph; 968 969 /* draw dotted horizontal grid line */ 970 for (x=0; x<LCD_WIDTH;x=x+2) 971 lcd_drawpixel(x,graph); 972 973 i++; 974 } 975 976 x = 0; 977 /* draw plot of power history 978 * skip empty entries 979 */ 980 for (i = BAT_LAST_VAL - 1; i > 0; i--) 981 { 982 if (power_history[i] && power_history[i-1]) 983 { 984 y1 = (power_history[i] - minv) * BAT_YSPACE / 985 (maxv - minv); 986 y1 = MIN(MAX(LCD_HEIGHT-1 - y1, BAT_TSPACE), 987 LCD_HEIGHT-1); 988 y2 = (power_history[i-1] - minv) * BAT_YSPACE / 989 (maxv - minv); 990 y2 = MIN(MAX(LCD_HEIGHT-1 - y2, BAT_TSPACE), 991 LCD_HEIGHT-1); 992 993 lcd_set_drawmode(DRMODE_SOLID); 994 995 /* make line thicker */ 996 lcd_drawline(((x*LCD_WIDTH)/(BAT_LAST_VAL)), 997 y1, 998 (((x+1)*LCD_WIDTH)/(BAT_LAST_VAL)), 999 y2); 1000 lcd_drawline(((x*LCD_WIDTH)/(BAT_LAST_VAL))+1, 1001 y1+1, 1002 (((x+1)*LCD_WIDTH)/(BAT_LAST_VAL))+1, 1003 y2+1); 1004 x++; 1005 } 1006 } 1007 break; 1008 1009 case 1: /* status: */ 1010#if CONFIG_CHARGING >= CHARGING_MONITOR 1011 lcd_putsf(0, 0, "Pwr status: %s", 1012 charging_state() ? "charging" : "discharging"); 1013#else 1014 lcd_putsf(0, 0, "Pwr status: %s", "unknown"); 1015#endif 1016 battery_read_info(&y, &z); 1017 if (y > 0) 1018 lcd_putsf(0, 1, "%s: %d.%03d V (%d %%)", "Battery", y / 1000, y % 1000, z); 1019 else if (z > 0) 1020 lcd_putsf(0, 1, "%s: %d %%", "Battery", z); 1021#ifdef ADC_EXT_POWER 1022 y = (adc_read(ADC_EXT_POWER) * EXT_SCALE_FACTOR) / 1000; 1023 lcd_putsf(0, 2, "%s: %d.%03d V", "External", y / 1000, y % 1000); 1024#endif 1025#if CONFIG_CHARGING 1026#if defined IPOD_NANO || defined IPOD_VIDEO 1027 int usb_pwr = (GPIOL_INPUT_VAL & 0x10)?true:false; 1028 int ext_pwr = (GPIOL_INPUT_VAL & 0x08)?false:true; 1029 int dock = (GPIOA_INPUT_VAL & 0x10)?true:false; 1030 int charging = (GPIOB_INPUT_VAL & 0x01)?false:true; 1031 int headphone= (GPIOA_INPUT_VAL & 0x80)?true:false; 1032 1033 lcd_putsf(0, 3, "USB pwr: %s", 1034 usb_pwr ? "present" : "absent"); 1035 lcd_putsf(0, 4, "EXT pwr: %s", 1036 ext_pwr ? "present" : "absent"); 1037 lcd_putsf(0, 5, "%s: %s", "Battery", 1038 charging ? "charging" : (usb_pwr||ext_pwr) ? "charged" : "discharging"); 1039 lcd_putsf(0, 6, "Dock mode: %s", 1040 dock ? "enabled" : "disabled"); 1041 lcd_putsf(0, 7, "Headphone: %s", 1042 headphone ? "connected" : "disconnected"); 1043#ifdef IPOD_VIDEO 1044 if(probed_ramsize == 64) 1045 x = (adc_read(ADC_4066_ISTAT) * 2400) / (1024 * 2); 1046 else 1047#endif 1048 x = (adc_read(ADC_4066_ISTAT) * 2400) / (1024 * 3); 1049 lcd_putsf(0, 8, "Ibat: %d mA", x); 1050 lcd_putsf(0, 9, "Vbat * Ibat: %d mW", x * y / 1000); 1051#elif defined TOSHIBA_GIGABEAT_S 1052 int line = 3; 1053 unsigned int st; 1054 1055 static const unsigned char * const chrgstate_strings[] = 1056 { 1057 "Disabled", 1058 "Error", 1059 "Discharging", 1060 "Precharge", 1061 "Constant Voltage", 1062 "Constant Current", 1063 "<unknown>", 1064 }; 1065 1066 lcd_putsf(0, line++, "Charger: %s", 1067 charger_inserted() ? "present" : "absent"); 1068 1069 st = power_input_status() & 1070 (POWER_INPUT_CHARGER | POWER_INPUT_BATTERY); 1071 1072 lcd_putsf(0, line++, "%.*s%.*s", 1073 !!(st & POWER_INPUT_MAIN_CHARGER)*5, " Main", 1074 !!(st & POWER_INPUT_USB_CHARGER)*4, " USB"); 1075 1076 y = ARRAYLEN(chrgstate_strings) - 1; 1077 1078 switch (charge_state) 1079 { 1080 case CHARGE_STATE_DISABLED: y--; 1081 case CHARGE_STATE_ERROR: y--; 1082 case DISCHARGING: y--; 1083 case TRICKLE: y--; 1084 case TOPOFF: y--; 1085 case CHARGING: y--; 1086 default:; 1087 } 1088 1089 lcd_putsf(0, line++, "State: %s", chrgstate_strings[y]); 1090 1091 lcd_putsf(0, line++, "%s Switch: %s", "Battery", 1092 (st & POWER_INPUT_BATTERY) ? "On" : "Off"); 1093 1094 y = chrgraw_adc_voltage(); 1095 lcd_putsf(0, line++, "CHRGRAW: %d.%03d V", 1096 y / 1000, y % 1000); 1097 1098 y = application_supply_adc_voltage(); 1099 lcd_putsf(0, line++, "BP : %d.%03d V", 1100 y / 1000, y % 1000); 1101 1102 y = battery_adc_charge_current(); 1103 lcd_putsf(0, line++, "CHRGISN:% d mA", y); 1104 1105 y = cccv_regulator_dissipation(); 1106 lcd_putsf(0, line++, "P CCCV : %d mW", y); 1107 1108 y = battery_charge_current(); 1109 lcd_putsf(0, line++, "I Charge:% d mA", y); 1110 1111 y = battery_adc_temp(); 1112 1113 if (y != INT_MIN) { 1114 lcd_putsf(0, line++, "T %s: %d\u00b0C (%d\u00b0F)", 1115 "Battery", y, (9*y + 160) / 5); 1116 } else { 1117 /* Conversion disabled */ 1118 lcd_putsf(0, line++, "T %s: ?", "Battery"); 1119 } 1120#elif defined(HAVE_AS3514) && CONFIG_CHARGING 1121 static const char * const chrgstate_strings[] = 1122 { 1123 [CHARGE_STATE_DISABLED - CHARGE_STATE_DISABLED]= "Disabled", 1124 [CHARGE_STATE_ERROR - CHARGE_STATE_DISABLED] = "Error", 1125 [DISCHARGING - CHARGE_STATE_DISABLED] = "Discharging", 1126 [CHARGING - CHARGE_STATE_DISABLED] = "Charging", 1127 }; 1128 const char *str = NULL; 1129 1130 lcd_putsf(0, 3, "Charger: %s", 1131 charger_inserted() ? "present" : "absent"); 1132 1133 y = charge_state - CHARGE_STATE_DISABLED; 1134 if ((unsigned)y < ARRAYLEN(chrgstate_strings)) 1135 str = chrgstate_strings[y]; 1136 1137 lcd_putsf(0, 4, "State: %s", 1138 str ? str : "<unknown>"); 1139 1140 lcd_putsf(0, 5, "CHARGER: %02X", ascodec_read_charger()); 1141#elif defined(IPOD_NANO2G) 1142 y = pmu_read_battery_voltage(); 1143 lcd_putsf(17, 1, "RAW: %d.%03d V", y / 1000, y % 1000); 1144 y = pmu_read_battery_current(); 1145 lcd_putsf(0, 2, "%s current: %d mA", "Battery", y); 1146 lcd_putsf(0, 3, "PWRCON: %08x %08x", PWRCON, PWRCONEXT); 1147 lcd_putsf(0, 4, "CLKCON: %08x %03x %03x", CLKCON, CLKCON2, CLKCON3); 1148 lcd_putsf(0, 5, "PLL: %06x %06x %06x", PLL0PMS, PLL1PMS, PLL2PMS); 1149 x = pmu_read(0x1b) & 0xf; 1150 y = pmu_read(0x1a) * 25 + 625; 1151 lcd_putsf(0, 6, "AUTO: %x / %d mV", x, y); 1152 x = pmu_read(0x1f) & 0xf; 1153 y = pmu_read(0x1e) * 25 + 625; 1154 lcd_putsf(0, 7, "DOWN1: %x / %d mV", x, y); 1155 x = pmu_read(0x23) & 0xf; 1156 y = pmu_read(0x22) * 25 + 625; 1157 lcd_putsf(0, 8, "DOWN2: %x / %d mV", x, y); 1158 x = pmu_read(0x27) & 0xf; 1159 y = pmu_read(0x26) * 100 + 900; 1160 lcd_putsf(0, 9, "MEMLDO: %x / %d mV", x, y); 1161 for (i = 0; i < 6; i++) 1162 { 1163 x = pmu_read(0x2e + (i << 1)) & 0xf; 1164 y = pmu_read(0x2d + (i << 1)) * 100 + 900; 1165 lcd_putsf(0, 10 + i, "LDO%d: %x / %d mV", i + 1, x, y); 1166 } 1167#elif defined(SANSA_CONNECT) 1168 lcd_putsf(0, 3, "Charger: %s", 1169 charger_inserted() ? "present" : "absent"); 1170 x = (avr_hid_hdq_read_short(HDQ_REG_TEMP) / 4) - 273; 1171 lcd_putsf(0, 4, "%s temperature: %d C", "Battery", x); 1172 x = (avr_hid_hdq_read_short(HDQ_REG_AI) * 357) / 200; 1173 lcd_putsf(0, 5, "%s current: %d.%01d mA", "Battery", x / 10, x % 10); 1174 x = (avr_hid_hdq_read_short(HDQ_REG_AP) * 292) / 20; 1175 lcd_putsf(0, 6, "Discharge power: %d.%01d mW", x / 10, x % 10); 1176 x = (avr_hid_hdq_read_short(HDQ_REG_SAE) * 292) / 2; 1177 lcd_putsf(0, 7, "Available energy: %d.%01d mWh", x / 10, x % 10); 1178#else 1179 lcd_putsf(0, 3, "Charger: %s", 1180 charger_inserted() ? "present" : "absent"); 1181#endif /* target type */ 1182#endif /* CONFIG_CHARGING */ 1183 break; 1184 case 2: /* voltage deltas: */ 1185#if (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) 1186 lcd_puts(0, 0, "Voltage deltas:"); 1187 for (i = 0; i < POWER_HISTORY_LEN-1; i++) { 1188 y = power_history[i] - power_history[i+1]; 1189 lcd_putsf(0, i+1, "-%d min: %c%d.%03d V", i, 1190 (y < 0) ? '-' : ' ', ((y < 0) ? y * -1 : y) / 1000, 1191 ((y < 0) ? y * -1 : y ) % 1000); 1192 } 1193#elif (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) 1194 lcd_puts(0, 0, "Percentage deltas:"); 1195 for (i = 0; i < POWER_HISTORY_LEN-1; i++) { 1196 y = power_history[i] - power_history[i+1]; 1197 lcd_putsf(0, i+1, "-%d min: %c%d%%", i, 1198 (y < 0) ? '-' : ' ', ((y < 0) ? y * -1 : y)); 1199 } 1200#endif 1201 break; 1202 1203 case 3: /* remaining time estimation: */ 1204 1205#if (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) 1206 lcd_putsf(0, 5, "Last PwrHist: %d.%03dV", 1207 power_history[0] / 1000, 1208 power_history[0] % 1000); 1209#endif 1210 1211 lcd_putsf(0, 6, "%s level: %d%%", "Battery", battery_level()); 1212 1213 int time_left = battery_time(); 1214 if (time_left >= 0) 1215 lcd_putsf(0, 7, "Est. remain: %d m", time_left); 1216 else 1217 lcd_puts(0, 7, "Estimation n/a"); 1218 1219#if (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) 1220 lcd_putsf(0, 8, "%s current: %d mA", "Battery", battery_current()); 1221#endif 1222 break; 1223 } 1224 1225 lcd_update(); 1226 1227 switch(get_action(CONTEXT_STD,HZ/2)) 1228 { 1229 case ACTION_STD_PREV: 1230 if (view) 1231 view--; 1232 break; 1233 1234 case ACTION_STD_NEXT: 1235 if (view < 3) 1236 view++; 1237 break; 1238 1239 case ACTION_STD_CANCEL: 1240 lcd_setfont(FONT_UI); 1241 return false; 1242 } 1243 } 1244 lcd_setfont(FONT_UI); 1245 return false; 1246} 1247 1248#endif /* (CONFIG_BATTERY_MEASURE != 0) */ 1249 1250#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 1251#if (CONFIG_STORAGE & STORAGE_MMC) || (CONFIG_STORAGE & STORAGE_SD) 1252 1253#if (CONFIG_STORAGE & STORAGE_MMC) 1254#define CARDTYPE "MMC" 1255#elif (CONFIG_STORAGE & STORAGE_SD) 1256#define CARDTYPE "microSD" 1257#endif 1258 1259static int disk_callback(int btn, struct gui_synclist *lists) 1260{ 1261 tCardInfo *card; 1262 int *cardnum = (int*)lists->data; 1263 unsigned char card_name[6]; 1264 unsigned char pbuf[32]; 1265 /* Casting away const is safe; the buffer is defined as non-const. */ 1266 char *title = (char *)lists->title; 1267 static const unsigned char i_vmin[] = { 0, 1, 5, 10, 25, 35, 60, 100 }; 1268 static const unsigned char i_vmax[] = { 1, 5, 10, 25, 35, 45, 80, 200 }; 1269 static const unsigned char * const kbit_units[] = { "kBit/s", "MBit/s", "GBit/s" }; 1270 static const unsigned char * const nsec_units[] = { "ns", "µs", "ms" }; 1271#if (CONFIG_STORAGE & STORAGE_MMC) 1272 static const char * const mmc_spec_vers[] = { "1.0-1.2", "1.4", "2.0-2.2", 1273 "3.1-3.31", "4.0" }; 1274#endif 1275 1276 if ((btn == ACTION_STD_OK) || (btn == SYS_FS_CHANGED) || (btn == ACTION_REDRAW)) 1277 { 1278#ifdef HAVE_HOTSWAP 1279 if (btn == ACTION_STD_OK) 1280 { 1281 *cardnum ^= 0x1; /* change cards */ 1282 } 1283#endif 1284 1285 simplelist_reset_lines(); 1286 1287 card = card_get_info(*cardnum); 1288 1289 if (card->initialized > 0) 1290 { 1291 unsigned i; 1292 for (i=0; i<sizeof(card_name); i++) 1293 { 1294 card_name[i] = card_extract_bits(card->cid, (103-8*i), 8); 1295 } 1296 strmemccpy(card_name, card_name, sizeof(card_name)); 1297 simplelist_addline( 1298 "%s Rev %d.%d", card_name, 1299 (int) card_extract_bits(card->cid, 63, 4), 1300 (int) card_extract_bits(card->cid, 59, 4)); 1301 simplelist_addline( 1302 "Prod: %d/%d", 1303#if (CONFIG_STORAGE & STORAGE_SD) 1304 (int) card_extract_bits(card->cid, 11, 4), 1305 (int) card_extract_bits(card->cid, 19, 8) + 2000 1306#elif (CONFIG_STORAGE & STORAGE_MMC) 1307 (int) card_extract_bits(card->cid, 15, 4), 1308 (int) card_extract_bits(card->cid, 11, 4) + 1997 1309#endif 1310 ); 1311 simplelist_addline( 1312#if (CONFIG_STORAGE & STORAGE_SD) 1313 "Ser#: 0x%08lx", 1314 card_extract_bits(card->cid, 55, 32) 1315#elif (CONFIG_STORAGE & STORAGE_MMC) 1316 "Ser#: 0x%04lx", 1317 card_extract_bits(card->cid, 47, 16) 1318#endif 1319 ); 1320 1321 simplelist_addline("M=%02x, " 1322#if (CONFIG_STORAGE & STORAGE_SD) 1323 "O=%c%c", 1324 (int) card_extract_bits(card->cid, 127, 8), 1325 (int) card_extract_bits(card->cid, 119, 8), 1326 (int) card_extract_bits(card->cid, 111, 8) 1327#elif (CONFIG_STORAGE & STORAGE_MMC) 1328 "O=%04x", 1329 (int) card_extract_bits(card->cid, 127, 8), 1330 (int) card_extract_bits(card->cid, 119, 16) 1331#endif 1332 ); 1333 1334#if (CONFIG_STORAGE & STORAGE_MMC) 1335 int temp = card_extract_bits(card->csd, 125, 4); 1336 simplelist_addline( 1337 "MMC v%s", temp < 5 ? 1338 mmc_spec_vers[temp] : "?.?"); 1339#endif 1340 simplelist_addline( 1341 "Blocks: 0x%08lx", card->numblocks); 1342 output_dyn_value(pbuf, sizeof pbuf, card->speed / 1000, 1343 kbit_units, 3, false); 1344 simplelist_addline( 1345 "Speed: %s", pbuf); 1346 output_dyn_value(pbuf, sizeof pbuf, card->taac, 1347 nsec_units, 3, false); 1348 simplelist_addline( 1349 "Taac: %s", pbuf); 1350 simplelist_addline( 1351 "Nsac: %d clk", card->nsac); 1352 simplelist_addline( 1353 "R2W: *%d", 1 << card->r2w_factor); 1354#if (CONFIG_STORAGE & STORAGE_SD) 1355 int csd_structure = card_extract_bits(card->csd, 127, 2); 1356 const char *ver; 1357 switch(csd_structure) { 1358 case 0: 1359 ver = "1 (SD)"; 1360 break; 1361 case 1: 1362 ver = "2 (SDHC/SDXC)"; 1363 break; 1364 case 2: 1365 ver = "3 (SDUC)"; 1366 break; 1367 default: 1368 ver = "Unknown"; 1369 break; 1370 } 1371 simplelist_addline("SDVer: %s", ver); 1372 if (csd_structure == 0) /* CSD version 1.0 */ 1373#endif 1374 { 1375 simplelist_addline( 1376 "IRmax: %d..%d mA", 1377 i_vmin[card_extract_bits(card->csd, 61, 3)], 1378 i_vmax[card_extract_bits(card->csd, 58, 3)]); 1379 simplelist_addline( 1380 "IWmax: %d..%d mA", 1381 i_vmin[card_extract_bits(card->csd, 55, 3)], 1382 i_vmax[card_extract_bits(card->csd, 52, 3)]); 1383 } 1384 } 1385 else if (card->initialized == 0) 1386 { 1387 simplelist_setline("Not Found!"); 1388 } 1389#if (CONFIG_STORAGE & STORAGE_SD) 1390 else /* card->initialized < 0 */ 1391 { 1392 simplelist_addline("Init Error! (%d)", card->initialized); 1393 } 1394#endif 1395 snprintf(title, 16, "[" CARDTYPE " %d]", *cardnum); 1396 gui_synclist_set_title(lists, title, Icon_NOICON); 1397 gui_synclist_set_nb_items(lists, simplelist_get_line_count()); 1398 gui_synclist_select_item(lists, 0); 1399 btn = ACTION_REDRAW; 1400 } 1401 return btn; 1402} 1403#elif (CONFIG_STORAGE & STORAGE_ATA) 1404static int disk_callback(int btn, struct gui_synclist *lists) 1405{ 1406 static const char atanums[] = { " 0 1 2 3 4 5 6" }; 1407 1408 (void)lists; 1409 int i; 1410 char buf[128]; 1411 unsigned short* identify_info = ata_get_identify(); 1412 bool timing_info_present = false; 1413 (void)btn; 1414 1415 simplelist_reset_lines(); 1416 1417 for (i=0; i < 20; i++) 1418 ((unsigned short*)buf)[i]=htobe16(identify_info[i+27]); 1419 buf[40]=0; 1420 /* kill trailing space */ 1421 for (i=39; i && buf[i]==' '; i--) 1422 buf[i] = 0; 1423 simplelist_addline("Model: %s", buf); 1424 for (i=0; i < 10; i++) 1425 ((unsigned short*)buf)[i]=htobe16(identify_info[i+10]); 1426 buf[20]=0; 1427 /* kill trailing space */ 1428 for (i=19; i && buf[i]==' '; i--) 1429 buf[i] = 0; 1430 simplelist_addline("Serial number: %s", buf); 1431 for (i=0; i < 4; i++) 1432 ((unsigned short*)buf)[i]=htobe16(identify_info[i+23]); 1433 buf[8]=0; 1434 simplelist_addline( 1435 "Firmware: %s", buf); 1436 1437 uint64_t total_sectors = (identify_info[61] << 16) | identify_info[60]; 1438#ifdef HAVE_LBA48 1439 if (identify_info[83] & 0x0400 && total_sectors == 0x0FFFFFFF) 1440 total_sectors = ((uint64_t)identify_info[103] << 48) | 1441 ((uint64_t)identify_info[102] << 32) | 1442 ((uint64_t)identify_info[101] << 16) | 1443 identify_info[100]; 1444#endif 1445 1446 uint32_t sector_size; 1447 1448 /* Logical sector size > 512B ? */ 1449 if ((identify_info[106] & 0xd000) == 0x5000) /* B14, B12 */ 1450 sector_size = (identify_info[117] | (identify_info[118] << 16)) * 2; 1451 else 1452 sector_size = 512; 1453 1454 total_sectors *= sector_size; /* Convert to bytes */ 1455 total_sectors /= (1024 * 1024); /* Convert to MB */ 1456 1457 simplelist_addline("Size: %lu MB", (unsigned long)total_sectors); 1458 simplelist_addline("Logical sector size: %lu B", sector_size); 1459#ifdef MAX_VIRT_SECTOR_SIZE 1460 simplelist_addline("Sector multiplier: %u", disk_get_sector_multiplier()); 1461#endif 1462 1463 if((identify_info[106] & 0xe000) == 0x6000) /* B14, B13 */ 1464 sector_size *= BIT_N(identify_info[106] & 0x000f); 1465 simplelist_addline( 1466 "Physical sector size: %lu B", sector_size); 1467 1468#ifndef HAVE_MULTIVOLUME 1469 // XXX this needs to be fixed for multi-volume setups 1470 sector_t free; 1471 volume_size( IF_MV(0,) NULL, &free ); 1472 simplelist_addline( 1473 "Free: %lu MB", (unsigned long)(free / 1024)); 1474#endif 1475 1476 simplelist_addline("SSD detected: %s", ata_disk_isssd() ? "yes" : "no"); 1477 simplelist_addline( 1478 "Spinup time: %d ms", storage_spinup_time() * (1000/HZ)); 1479 i = identify_info[82] & (1<<3); 1480 simplelist_addline( 1481 "Power mgmt: %s", i ? "enabled" : "unsupported"); 1482 i = identify_info[83] & (1<<3); 1483 simplelist_addline( 1484 "Adv Power mgmt: %s", i ? "enabled" : "unsupported"); 1485 i = identify_info[83] & (1<<9); 1486 simplelist_addline( 1487 "Noise mgmt: %s", i ? "enabled" : "unsupported"); 1488 i = identify_info[85] & (1<<0); 1489 simplelist_addline( 1490 "SMART: %s", i ? "enabled" : "unsupported"); 1491 simplelist_addline( 1492 "Flush cache: %s", identify_info[83] & (1<<13) ? "extended" : identify_info[83] & (1<<12) ? "standard" : identify_info[80] >= (1<<5) ? "ATA-5" : "unsupported"); 1493 i = identify_info[82] & (1<<6); 1494 simplelist_addline( 1495 "Read-ahead: %s", i ? "enabled" : "unsupported"); 1496 timing_info_present = identify_info[53] & (1<<1); 1497 if(timing_info_present) { 1498 simplelist_addline( 1499 "PIO modes: 0 1 2%.*s%.*s", 1500 (identify_info[64] & (1<<0)) << 1, &atanums[3*2], 1501 (identify_info[64] & (1<<1)) , &atanums[4*2]); 1502 } 1503 else { 1504 simplelist_setline( 1505 "No PIO mode info"); 1506 } 1507 timing_info_present = identify_info[53] & (1<<1); 1508 if(timing_info_present) { 1509 simplelist_addline( 1510 "Cycle times %dns/%dns", 1511 identify_info[67], 1512 identify_info[68] ); 1513 } else { 1514 simplelist_setline( 1515 "No timing info"); 1516 } 1517 1518#ifdef HAVE_ATA_DMA 1519 if (identify_info[63] & (1<<0)) { 1520 simplelist_addline( 1521 "MDMA modes:%.*s%.*s%.*s", 1522 (identify_info[63] & (1<<0)) << 1, &atanums[0*2], 1523 (identify_info[63] & (1<<1)) , &atanums[1*2], 1524 (identify_info[63] & (1<<2)) >> 1, &atanums[2*2]); 1525 simplelist_addline( 1526 "MDMA Cycle times %dns/%dns", 1527 identify_info[65], 1528 identify_info[66] ); 1529 } 1530 else { 1531 simplelist_setline( 1532 "No MDMA mode info"); 1533 } 1534 if (identify_info[53] & (1<<2)) { 1535 simplelist_addline( 1536 "UDMA modes:%.*s%.*s%.*s%.*s%.*s%.*s%.*s", 1537 (identify_info[88] & (1<<0)) << 1, &atanums[0*2], 1538 (identify_info[88] & (1<<1)) , &atanums[1*2], 1539 (identify_info[88] & (1<<2)) >> 1, &atanums[2*2], 1540 (identify_info[88] & (1<<3)) >> 2, &atanums[3*2], 1541 (identify_info[88] & (1<<4)) >> 3, &atanums[4*2], 1542 (identify_info[88] & (1<<5)) >> 4, &atanums[5*2], 1543 (identify_info[88] & (1<<6)) >> 5, &atanums[6*2]); 1544 } 1545 else { 1546 simplelist_setline("No UDMA mode info"); 1547 } 1548#endif /* HAVE_ATA_DMA */ 1549 timing_info_present = identify_info[53] & (1<<1); 1550 if(timing_info_present) { 1551 i = identify_info[49] & (1<<11); 1552 simplelist_addline( 1553 "IORDY support: %s", i ? "yes" : "no"); 1554 i = identify_info[49] & (1<<10); 1555 simplelist_addline( 1556 "IORDY disable: %s", i ? "yes" : "no"); 1557 } else { 1558 simplelist_setline("No timing info"); 1559 } 1560 simplelist_addline( 1561 "Cluster size: %d bytes", volume_get_cluster_size(IF_MV(0))); 1562#ifdef HAVE_ATA_DMA 1563 i = ata_get_dma_mode(); 1564 if (i == 0) { 1565 simplelist_setline("DMA not enabled"); 1566 } else if (i == 0xff) { 1567 simplelist_setline("CE-ATA mode"); 1568 } else { 1569 simplelist_addline( 1570 "DMA mode: %s %c", 1571 (i & 0x40) ? "UDMA" : "MDMA", 1572 '0' + (i & 7)); 1573 } 1574#endif /* HAVE_ATA_DMA */ 1575 i = identify_info[83] & (1 << 2); 1576 simplelist_addline( 1577 "CFA compatible: %s", i ? "yes" : "no"); 1578 i = identify_info[0] & (1 << 6); 1579 simplelist_addline( 1580 "Fixed device: %s", i ? "yes" : "no"); 1581 i = identify_info[0] & (1 << 7); 1582 simplelist_addline( 1583 "Removeable media: %s", i ? "yes" : "no"); 1584 1585 return btn; 1586} 1587 1588#ifdef HAVE_ATA_SMART 1589static struct ata_smart_values smart_data STORAGE_ALIGN_ATTR; 1590 1591static const char * ata_smart_get_attr_name(unsigned char id) 1592{ 1593 if (id == 1) return "Raw Read Error Rate"; 1594 if (id == 2) return "Throughput Performance"; 1595 if (id == 3) return "Spin-Up Time"; 1596 if (id == 4) return "Start/Stop Count"; 1597 if (id == 5) return "Reallocated Sector Count"; 1598 if (id == 7) return "Seek Error Rate"; 1599 if (id == 8) return "Seek Time Performance"; 1600 if (id == 9) return "Power-On Hours Count"; 1601 if (id == 10) return "Spin-Up Retry Count"; 1602 if (id == 12) return "Power Cycle Count"; 1603 if (id == 191) return "G-Sense Error Rate"; 1604 if (id == 192) return "Power-Off Retract Count"; 1605 if (id == 193) return "Load/Unload Cycle Count"; 1606 if (id == 194) return "HDA Temperature"; 1607 if (id == 195) return "Hardware ECC Recovered"; 1608 if (id == 196) return "Reallocated Event Count"; 1609 if (id == 197) return "Current Pending Sector Count"; 1610 if (id == 198) return "Uncorrectable Sector Count"; 1611 if (id == 199) return "UDMA CRC Error Count"; 1612 if (id == 200) return "Write Error Rate"; 1613 if (id == 201) return "TA Counter Detected"; 1614 if (id == 220) return "Disk Shift"; 1615 if (id == 222) return "Loaded Hours"; 1616 if (id == 223) return "Load/Unload Retry Count"; 1617 if (id == 224) return "Load Friction"; 1618 if (id == 225) return "Load Cycle Count"; 1619 if (id == 226) return "Load-In Time"; 1620 if (id == 240) return "Transfer Error Rate"; /* Fujitsu */ 1621 return "Unknown Attribute"; 1622}; 1623 1624static int ata_smart_get_attr_rawfmt(unsigned char id) 1625{ 1626 if (id == 3) /* Spin-up time */ 1627 return RAWFMT_RAW16_OPT_AVG16; 1628 1629 if (id == 5 || /* Reallocated sector count */ 1630 id == 196) /* Reallocated event count */ 1631 return RAWFMT_RAW16_OPT_RAW16; 1632 1633 if (id == 190 || /* Airflow Temperature */ 1634 id == 194) /* HDA Temperature */ 1635 return RAWFMT_TEMPMINMAX; 1636 1637 return RAWFMT_RAW48; 1638}; 1639 1640static int ata_smart_attr_to_string( 1641 struct ata_smart_attribute *attr, char *str, int size) 1642{ 1643 uint16_t w[3]; /* 3 words to store 6 bytes of raw data */ 1644 char buf[size]; /* temp string to store attribute data */ 1645 int len, slen; 1646 int id = attr->id; 1647 1648 if (id == 0) 1649 return 0; /* null attribute */ 1650 1651 /* align and convert raw data */ 1652 memcpy(w, attr->raw, 6); 1653 w[0] = letoh16(w[0]); 1654 w[1] = letoh16(w[1]); 1655 w[2] = letoh16(w[2]); 1656 1657 len = snprintf(buf, size, ": %u,%u ", attr->current, attr->worst); 1658 1659 switch (ata_smart_get_attr_rawfmt(id)) 1660 { 1661 case RAWFMT_RAW16_OPT_RAW16: 1662 len += snprintf(buf+len, size-len, "%u", w[0]); 1663 if ((w[1] || w[2]) && (len < size)) 1664 len += snprintf(buf+len, size-len, " %u %u", w[1],w[2]); 1665 break; 1666 1667 case RAWFMT_RAW16_OPT_AVG16: 1668 len += snprintf(buf+len, size-len, "%u", w[0]); 1669 if (w[1] && (len < size)) 1670 len += snprintf(buf+len, size-len, " Avg: %u", w[1]); 1671 break; 1672 1673 case RAWFMT_TEMPMINMAX: 1674 len += snprintf(buf+len, size-len, "%u -/+: %u/%u", w[0],w[1],w[2]); 1675 break; 1676 1677 case RAWFMT_RAW48: 1678 default: { 1679 uint32_t tmp; 1680 memcpy(&tmp, w, sizeof(tmp)); 1681 /* shows first 4 bytes of raw data as uint32 LE, 1682 and the ramaining 2 bytes as uint16 LE */ 1683 len += snprintf(buf+len, size-len, "%lu", letoh32(tmp)); 1684 if (w[2] && (len < size)) 1685 len += snprintf(buf+len, size-len, " %u", w[2]); 1686 break; 1687 } 1688 } 1689 /* ignore trailing \0 when truncated */ 1690 if (len >= size) len = size-1; 1691 1692 /* fill return string; when max. size is exceded: first truncate 1693 attribute name, then attribute data and finally attribute id */ 1694 slen = snprintf(str, size, "%d ", id); 1695 if (slen < size) { 1696 /* maximum space disponible for attribute name, 1697 including initial space separator */ 1698 int name_sz = size - (slen + len); 1699 if (name_sz > 1) { 1700 len = snprintf(str+slen, name_sz, " %s", 1701 ata_smart_get_attr_name(id)); 1702 if (len >= name_sz) len = name_sz-1; 1703 slen += len; 1704 } 1705 1706 strmemccpy(str+slen, buf, size-slen); 1707 } 1708 1709 return 1; /* ok */ 1710} 1711 1712static bool ata_smart_dump(void) 1713{ 1714 int fd; 1715 1716 fd = creat("/smart_data.bin", 0666); 1717 if(fd >= 0) 1718 { 1719 write(fd, &smart_data, sizeof(struct ata_smart_values)); 1720 close(fd); 1721 } 1722 1723 fd = creat("/smart_data.txt", 0666); 1724 if(fd >= 0) 1725 { 1726 int i; 1727 char buf[128]; 1728 for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) 1729 { 1730 if (ata_smart_attr_to_string( 1731 &smart_data.vendor_attributes[i], buf, sizeof(buf))) 1732 { 1733 write(fd, buf, strlen(buf)); 1734 write(fd, "\n", 1); 1735 } 1736 } 1737 close(fd); 1738 } 1739 1740 return false; 1741} 1742 1743static int ata_smart_callback(int btn, struct gui_synclist *lists) 1744{ 1745 (void)lists; 1746 static bool read_done = false; 1747 1748 if (btn == ACTION_STD_CANCEL) 1749 { 1750 read_done = false; 1751 return btn; 1752 } 1753 1754 /* read S.M.A.R.T. data only on first redraw */ 1755 if (!read_done) 1756 { 1757 int rc; 1758 memset(&smart_data, 0, sizeof(struct ata_smart_values)); 1759 rc = ata_read_smart(&smart_data, ATA_SMART_READ_DATA); 1760 simplelist_reset_lines(); 1761 if (rc == 0) 1762 { 1763 int i; 1764 char buf[SIMPLELIST_MAX_LINELENGTH]; 1765 simplelist_setline("Id Name: Current,Worst Raw"); 1766 for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++) 1767 { 1768 if (ata_smart_attr_to_string( 1769 &smart_data.vendor_attributes[i], buf, sizeof(buf))) 1770 { 1771 simplelist_addline(buf); 1772 } 1773 } 1774 } 1775 else 1776 { 1777 simplelist_addline("ATA SMART error: %#x", rc); 1778 } 1779 read_done = true; 1780 } 1781 1782 if (btn == ACTION_STD_CONTEXT) 1783 { 1784 splash(0, "Dumping data..."); 1785 ata_smart_dump(); 1786 splash(HZ, "SMART data dumped"); 1787 } 1788 1789 return btn; 1790} 1791 1792static bool dbg_ata_smart(void) 1793{ 1794 struct simplelist_info info; 1795 simplelist_info_init(&info, "S.M.A.R.T. Data [CONTEXT to dump]", 1, NULL); 1796 info.action_callback = ata_smart_callback; 1797 info.scroll_all = true; 1798 return simplelist_show_list(&info); 1799} 1800#endif /* HAVE_ATA_SMART */ 1801#else /* No SD, MMC or ATA */ 1802static int disk_callback(int btn, struct gui_synclist *lists) 1803{ 1804 (void)lists; 1805 struct storage_info info; 1806 storage_get_info(0,&info); 1807 simplelist_addline("Vendor: %s", info.vendor); 1808 simplelist_addline("Model: %s", info.product); 1809 simplelist_addline("Firmware: %s", info.revision); 1810 simplelist_addline( 1811 "Size: %lu MB", (unsigned long)(info.num_sectors*(info.sector_size/512)/2048)); 1812 sector_t free; 1813 volume_size( IF_MV(0,) NULL, &free ); 1814 simplelist_addline( 1815 "Free: %ld MB", free / 1024); 1816 simplelist_addline( 1817 "Cluster size: %d bytes", volume_get_cluster_size(IF_MV(0))); 1818 return btn; 1819} 1820#endif 1821 1822#if (CONFIG_STORAGE & STORAGE_ATA) 1823static bool dbg_identify_info(void) 1824{ 1825 int fd = creat("/identify_info.bin", 0666); 1826 if(fd >= 0) 1827 { 1828 const unsigned short *identify_info = ata_get_identify(); 1829#ifdef ROCKBOX_LITTLE_ENDIAN 1830 /* this is a pointer to a driver buffer so we can't modify it */ 1831 for (int i = 0; i < ATA_IDENTIFY_WORDS; ++i) 1832 { 1833 unsigned short word = swap16(identify_info[i]); 1834 write(fd, &word, 2); 1835 } 1836#else 1837 write(fd, identify_info, ATA_IDENTIFY_WORDS*2); 1838#endif 1839 close(fd); 1840 } 1841 return false; 1842} 1843#endif 1844 1845static bool dbg_disk_info(void) 1846{ 1847 struct simplelist_info info; 1848 simplelist_info_init(&info, "Disk Info", 1, NULL); 1849#if (CONFIG_STORAGE & STORAGE_MMC) || (CONFIG_STORAGE & STORAGE_SD) 1850 char title[16]; 1851 int card = 0; 1852 info.callback_data = (void*)&card; 1853 info.title = title; 1854#endif 1855 info.action_callback = disk_callback; 1856 info.scroll_all = true; 1857 return simplelist_show_list(&info); 1858} 1859#endif /* PLATFORM_NATIVE */ 1860 1861#ifdef HAVE_DIRCACHE 1862static int dircache_callback(int btn, struct gui_synclist *lists) 1863{ 1864 (void)lists; 1865 struct dircache_info info; 1866 dircache_get_info(&info); 1867 1868 if (global_settings.dircache) 1869 { 1870 switch (btn) 1871 { 1872 case ACTION_STD_CONTEXT: 1873 splash(HZ/2, "Rebuilding cache"); 1874 dircache_suspend(); 1875 *(int *)lists->data = dircache_resume(); 1876 /* Fallthrough */ 1877 case ACTION_UNKNOWN: 1878 btn = ACTION_NONE; 1879 break; 1880 #ifdef DIRCACHE_DUMPSTER 1881 case ACTION_STD_OK: 1882 splash(0, "Dumping cache"); 1883 dircache_dump(); 1884 btn = ACTION_NONE; 1885 break; 1886 #endif /* DIRCACHE_DUMPSTER */ 1887 case ACTION_STD_CANCEL: 1888 if (*(int *)lists->data > 0 && info.status == DIRCACHE_SCANNING) 1889 { 1890 splash(HZ, ID2P(LANG_SCANNING_DISK)); 1891 btn = ACTION_NONE; 1892 } 1893 break; 1894 } 1895 } 1896 1897 simplelist_reset_lines(); 1898 1899 simplelist_addline("Cache status: %s", info.statusdesc); 1900 simplelist_addline("Last size: %zu B", info.last_size); 1901 simplelist_addline("Size: %zu B", info.size); 1902 unsigned int utilized = info.size ? 1000ull*info.sizeused / info.size : 0; 1903 simplelist_addline("Used: %zu B (%u.%u%%)", info.sizeused, 1904 utilized / 10, utilized % 10); 1905 simplelist_addline("Limit: %zu B", info.size_limit); 1906 simplelist_addline("Reserve: %zu/%zu B", info.reserve_used, info.reserve); 1907 long ticks = ALIGN_UP(info.build_ticks, HZ / 10); 1908 simplelist_addline("Scanning took: %ld.%ld s", 1909 ticks / HZ, (ticks*10 / HZ) % 10); 1910 simplelist_addline("Entry count: %u", info.entry_count); 1911 1912 return btn; 1913} 1914 1915static bool dbg_dircache_info(void) 1916{ 1917 struct simplelist_info info; 1918 int syncbuild = 0; 1919 simplelist_info_init(&info, "Dircache Info", 0, &syncbuild); 1920 info.action_callback = dircache_callback; 1921 info.scroll_all = true; 1922 return simplelist_show_list(&info); 1923} 1924 1925#endif /* HAVE_DIRCACHE */ 1926 1927#ifdef HAVE_TAGCACHE 1928static int database_callback(int btn, struct gui_synclist *lists) 1929{ 1930 (void)lists; 1931 struct tagcache_stat *stat = tagcache_get_stat(); 1932 static bool synced = false; 1933 static int update_entries = 0; 1934 1935 simplelist_reset_lines(); 1936 1937 simplelist_addline("Initialized: %s", 1938 stat->initialized ? "Yes" : "No"); 1939 simplelist_addline("DB %s: %s", "Ready", 1940 stat->ready ? "Yes" : "No"); 1941 simplelist_addline("DB Path: %s", stat->db_path); 1942 simplelist_addline("RAM Cache: %s", 1943 stat->ramcache ? "Yes" : "No"); 1944 simplelist_addline("RAM: %d/%d B", 1945 stat->ramcache_used, stat->ramcache_allocated); 1946 simplelist_addline("Total entries: %d", 1947 stat->total_entries); 1948 simplelist_setline("Progress:"); 1949 simplelist_addline(" %d%% (%d entries)", 1950 stat->progress, stat->processed_entries); 1951 simplelist_setline("Curfile:"); 1952 simplelist_addline(" %s", stat->curentry ? stat->curentry : "---"); 1953 simplelist_addline("Commit step: %d", 1954 stat->commit_step); 1955 simplelist_addline("Commit delayed: %s", 1956 stat->commit_delayed ? "Yes" : "No"); 1957 1958 simplelist_addline("Queue length: %d", 1959 stat->queue_length); 1960 1961 if (synced) 1962 { 1963 synced = false; 1964 tagcache_screensync_event(); 1965 } 1966 1967 if (!btn && stat->curentry) 1968 { 1969 synced = true; 1970 if (update_entries <= stat->processed_entries) 1971 { 1972 update_entries = stat->processed_entries + 100; 1973 return ACTION_REDRAW; 1974 } 1975 return ACTION_NONE; 1976 } 1977 1978 if (btn == ACTION_STD_CANCEL) 1979 { 1980 update_entries = 0; 1981 tagcache_screensync_enable(false); 1982 } 1983 return btn; 1984} 1985static bool dbg_tagcache_info(void) 1986{ 1987 struct simplelist_info info; 1988 simplelist_info_init(&info, "Database Info", 0, NULL); 1989 info.action_callback = database_callback; 1990 info.scroll_all = true; 1991 1992 /* Don't do nonblock here, must give enough processing time 1993 for tagcache thread. */ 1994 /* info.timeout = TIMEOUT_NOBLOCK; */ 1995 info.timeout = 1; 1996 tagcache_screensync_enable(true); 1997 return simplelist_show_list(&info); 1998} 1999#endif 2000 2001#if defined CPU_COLDFIRE 2002static bool dbg_save_roms(void) 2003{ 2004 int fd; 2005 int oldmode = system_memory_guard(MEMGUARD_NONE); 2006 2007#if defined(IRIVER_H100_SERIES) 2008 fd = creat("/internal_rom_000000-1FFFFF.bin", 0666); 2009#elif defined(IRIVER_H300_SERIES) 2010 fd = creat("/internal_rom_000000-3FFFFF.bin", 0666); 2011#elif defined(IAUDIO_X5) || defined(IAUDIO_M5) || defined(IAUDIO_M3) 2012 fd = creat("/internal_rom_000000-3FFFFF.bin", 0666); 2013#elif defined(MPIO_HD200) || defined(MPIO_HD300) 2014 fd = creat("/internal_rom_000000-1FFFFF.bin", 0666); 2015#endif 2016 if(fd >= 0) 2017 { 2018 write(fd, (void *)0, FLASH_SIZE); 2019 close(fd); 2020 } 2021 system_memory_guard(oldmode); 2022 2023#ifdef HAVE_EEPROM 2024 fd = creat("/internal_eeprom.bin", 0666); 2025 if (fd >= 0) 2026 { 2027 int old_irq_level; 2028 char buf[EEPROM_SIZE]; 2029 int err; 2030 2031 old_irq_level = disable_irq_save(); 2032 2033 err = eeprom_24cxx_read(0, buf, sizeof buf); 2034 2035 restore_irq(old_irq_level); 2036 2037 if (err) 2038 splashf(HZ*3, "Eeprom read failure (%d)", err); 2039 else 2040 { 2041 write(fd, buf, sizeof buf); 2042 } 2043 2044 close(fd); 2045 } 2046#endif 2047 2048 return false; 2049} 2050#elif defined(CPU_PP) && !(CONFIG_STORAGE & STORAGE_SD) 2051static bool dbg_save_roms(void) 2052{ 2053 int fd = creat("/internal_rom_000000-0FFFFF.bin", 0666); 2054 if(fd >= 0) 2055 { 2056 write(fd, (void *)0x20000000, FLASH_SIZE); 2057 close(fd); 2058 } 2059 2060 return false; 2061} 2062#elif CONFIG_CPU == AS3525v2 || CONFIG_CPU == AS3525 2063static bool dbg_save_roms(void) 2064{ 2065 int fd = creat("/rom.bin", 0666); 2066 if(fd >= 0) 2067 { 2068 write(fd, (void *)0x80000000, 0x20000); 2069 close(fd); 2070 } 2071 2072 return false; 2073} 2074#elif CONFIG_CPU == IMX31L 2075bool __dbg_dvfs_dptc(void); 2076static bool dbg_save_roms(void) 2077{ 2078 int fd = creat("/flash_rom_A0000000-A01FFFFF.bin", 0666); 2079 if (fd >= 0) 2080 { 2081 write(fd, (void*)0xa0000000, FLASH_SIZE); 2082 close(fd); 2083 } 2084 2085 return false; 2086} 2087#elif defined(CPU_TCC780X) 2088static bool dbg_save_roms(void) 2089{ 2090 int fd = creat("/eeprom_E0000000-E0001FFF.bin", 0666); 2091 if (fd >= 0) 2092 { 2093 write(fd, (void*)0xe0000000, 0x2000); 2094 close(fd); 2095 } 2096 2097 return false; 2098} 2099#elif CONFIG_CPU == RK27XX 2100static bool dbg_save_roms(void) 2101{ 2102 char buf[0x200]; 2103 2104 int fd = creat("/rom.bin", 0666); 2105 if(fd < 0) 2106 return false; 2107 2108 for(int addr = 0; addr < 0x2000; addr += sizeof(buf)) 2109 { 2110 int old_irq = disable_irq_save(); 2111 2112 /* map rom at 0 */ 2113 SCU_REMAP = 0; 2114 commit_discard_idcache(); 2115 2116 /* copy rom */ 2117 memcpy((void *)buf, (void *)addr, sizeof(buf)); 2118 2119 /* map iram back at 0 */ 2120 SCU_REMAP = 0xdeadbeef; 2121 commit_discard_idcache(); 2122 2123 restore_irq(old_irq); 2124 2125 write(fd, (void *)buf, sizeof(buf)); 2126 } 2127 close(fd); 2128 2129 return false; 2130} 2131#endif /* CPU */ 2132 2133#ifndef SIMULATOR 2134#if CONFIG_TUNER 2135 2136#ifdef CONFIG_TUNER_MULTI 2137static int tuner_type = 0; 2138#define IF_TUNER_TYPE(type) if(tuner_type==type) 2139#else 2140#define IF_TUNER_TYPE(type) 2141#endif 2142 2143static int radio_callback(int btn, struct gui_synclist *lists) 2144{ 2145 (void)lists; 2146 if (btn == ACTION_STD_CANCEL) 2147 return btn; 2148 simplelist_reset_lines(); 2149 simplelist_setline("HW detected: yes"); 2150 2151#if (CONFIG_TUNER & LV24020LP) 2152 simplelist_addline( 2153 "CTRL_STAT: %02X", lv24020lp_get(LV24020LP_CTRL_STAT) ); 2154 simplelist_addline( 2155 "RADIO_STAT: %02X", lv24020lp_get(LV24020LP_REG_STAT) ); 2156 simplelist_addline( 2157 "MSS_FM: %d kHz", lv24020lp_get(LV24020LP_MSS_FM) ); 2158 simplelist_addline( 2159 "MSS_IF: %d Hz", lv24020lp_get(LV24020LP_MSS_IF) ); 2160 simplelist_addline( 2161 "MSS_SD: %d Hz", lv24020lp_get(LV24020LP_MSS_SD) ); 2162 simplelist_addline( 2163 "if_set: %d Hz", lv24020lp_get(LV24020LP_IF_SET) ); 2164 simplelist_addline( 2165 "sd_set: %d Hz", lv24020lp_get(LV24020LP_SD_SET) ); 2166#endif /* LV24020LP */ 2167#if (CONFIG_TUNER & TEA5767) 2168 struct tea5767_dbg_info nfo; 2169 tea5767_dbg_info(&nfo); 2170 simplelist_setline("Philips regs:"); 2171 simplelist_addline( 2172 " %s: %02X %02X %02X %02X %02X", "Read", 2173 (unsigned)nfo.read_regs[0], (unsigned)nfo.read_regs[1], 2174 (unsigned)nfo.read_regs[2], (unsigned)nfo.read_regs[3], 2175 (unsigned)nfo.read_regs[4]); 2176 simplelist_addline( 2177 " %s: %02X %02X %02X %02X %02X", "Write", 2178 (unsigned)nfo.write_regs[0], (unsigned)nfo.write_regs[1], 2179 (unsigned)nfo.write_regs[2], (unsigned)nfo.write_regs[3], 2180 (unsigned)nfo.write_regs[4]); 2181#endif /* TEA5767 */ 2182#if (CONFIG_TUNER & SI4700) 2183 IF_TUNER_TYPE(SI4700) 2184 { 2185 struct si4700_dbg_info nfo; 2186 si4700_dbg_info(&nfo); 2187 simplelist_setline("SI4700 regs:"); 2188 for (int i = 0; i < 16; i += 4) { 2189 simplelist_addline("%02X: %04X %04X %04X %04X", 2190 i, nfo.regs[i], nfo.regs[i+1], nfo.regs[i+2], nfo.regs[i+3]); 2191 } 2192 } 2193#endif /* SI4700 */ 2194#if (CONFIG_TUNER & RDA5802) 2195 IF_TUNER_TYPE(RDA5802) 2196 { 2197 struct rda5802_dbg_info nfo; 2198 rda5802_dbg_info(&nfo); 2199 simplelist_setline("RDA5802 regs:"); 2200 for (int i = 0; i < 16; i += 4) { 2201 simplelist_addline("%02X: %04X %04X %04X %04X", 2202 i, nfo.regs[i], nfo.regs[i+1], nfo.regs[i+2], nfo.regs[i+3]); 2203 } 2204 } 2205#endif /* RDA55802 */ 2206#if (CONFIG_TUNER & STFM1000) 2207 IF_TUNER_TYPE(STFM1000) 2208 { 2209 struct stfm1000_dbg_info nfo; 2210 stfm1000_dbg_info(&nfo); 2211 simplelist_setline("STFM1000 regs:"); 2212 simplelist_addline("chipid: 0x%lx", nfo.chipid); 2213 } 2214#endif /* STFM1000 */ 2215#if (CONFIG_TUNER & TEA5760) 2216 IF_TUNER_TYPE(TEA5760) 2217 { 2218 struct tea5760_dbg_info nfo; 2219 tea5760_dbg_info(&nfo); 2220 simplelist_setline("TEA5760 regs:"); 2221 for (int i = 0; i < 16; i += 4) { 2222 simplelist_addline("%02X: %02X %02X %02X %02X", 2223 i, nfo.read_regs[i], nfo.read_regs[i+1], nfo.read_regs[i+2], nfo.read_regs[i+3]); 2224 } 2225 } 2226#endif /* TEA5760 */ 2227 2228#ifdef HAVE_RDS_CAP 2229 { 2230 char buf[65*4]; 2231 uint16_t pi; 2232 time_t seconds; 2233 2234 tuner_get_rds_info(RADIO_RDS_NAME, buf, sizeof (buf)); 2235 tuner_get_rds_info(RADIO_RDS_PROGRAM_INFO, &pi, sizeof (pi)); 2236 simplelist_addline("PI:%04X PS:'%-8s'", pi, buf); 2237 tuner_get_rds_info(RADIO_RDS_TEXT, buf, sizeof (buf)); 2238 simplelist_addline("RT:%s", buf); 2239 tuner_get_rds_info(RADIO_RDS_CURRENT_TIME, &seconds, sizeof (seconds)); 2240 2241 struct tm* time = gmtime(&seconds); 2242 simplelist_addline( 2243 "CT:%4d-%02d-%02d %02d:%02d:%02d", 2244 time->tm_year + 1900, time->tm_mon + 1, time->tm_mday, 2245 time->tm_hour, time->tm_min, time->tm_sec); 2246 } 2247#endif /* HAVE_RDS_CAP */ 2248 return ACTION_REDRAW; 2249} 2250static bool dbg_fm_radio(void) 2251{ 2252 struct simplelist_info info; 2253#ifdef CONFIG_TUNER_MULTI 2254 tuner_type = tuner_detect_type(); 2255#endif 2256 info.scroll_all = true; 2257 simplelist_info_init(&info, "FM Radio", 0, NULL); 2258 simplelist_reset_lines(); 2259 simplelist_setline("HW detected: no"); 2260 2261 info.action_callback = radio_hardware_present()?radio_callback : NULL; 2262 return simplelist_show_list(&info); 2263} 2264#endif /* CONFIG_TUNER */ 2265#endif /* !SIMULATOR */ 2266 2267#if !defined(APPLICATION) 2268extern bool do_screendump_instead_of_usb; 2269 2270static bool dbg_screendump(void) 2271{ 2272 do_screendump_instead_of_usb = !do_screendump_instead_of_usb; 2273 splashf(HZ, "Screendump %sabled", do_screendump_instead_of_usb?"en":"dis"); 2274 return false; 2275} 2276#endif /* !APPLICATION */ 2277 2278extern bool write_metadata_log; 2279 2280static bool dbg_metadatalog(void) 2281{ 2282 write_metadata_log = !write_metadata_log; 2283 splashf(HZ, "Metadata log %sabled", write_metadata_log ? "en" : "dis"); 2284 return false; 2285} 2286 2287#if defined(CPU_COLDFIRE) 2288static bool dbg_set_memory_guard(void) 2289{ 2290 static const struct opt_items names[MAXMEMGUARD] = { 2291 { "None", -1 }, 2292 { "Flash ROM writes", -1 }, 2293 { "Zero area (all)", -1 } 2294 }; 2295 int mode = system_memory_guard(MEMGUARD_KEEP); 2296 2297 set_option( "Catch mem accesses", &mode, RB_INT, names, MAXMEMGUARD, NULL); 2298 system_memory_guard(mode); 2299 2300 return false; 2301} 2302#endif /* defined(CPU_COLDFIRE) */ 2303 2304#if defined(HAVE_EEPROM) && !defined(HAVE_EEPROM_SETTINGS) 2305static bool dbg_write_eeprom(void) 2306{ 2307 int fd = open("/internal_eeprom.bin", O_RDONLY); 2308 2309 if (fd >= 0) 2310 { 2311 char buf[EEPROM_SIZE]; 2312 int rc = read(fd, buf, EEPROM_SIZE); 2313 2314 if(rc == EEPROM_SIZE) 2315 { 2316 int old_irq_level = disable_irq_save(); 2317 2318 int err = eeprom_24cxx_write(0, buf, sizeof buf); 2319 if (err) 2320 splashf(HZ*3, "Eeprom write failure (%d)", err); 2321 else 2322 splash(HZ*3, "Eeprom written successfully"); 2323 2324 restore_irq(old_irq_level); 2325 } 2326 else 2327 { 2328 splashf(HZ*3, "File read error (%d)",rc); 2329 } 2330 close(fd); 2331 } 2332 else 2333 { 2334 splash(HZ*3, "Failed to open 'internal_eeprom.bin'"); 2335 } 2336 2337 return false; 2338} 2339#endif /* defined(HAVE_EEPROM) && !defined(HAVE_EEPROM_SETTINGS) */ 2340#ifdef CPU_BOOST_LOGGING 2341static bool cpu_boost_log(void) 2342{ 2343 int count = cpu_boost_log_getcount(); 2344 char *str = cpu_boost_log_getlog_first(); 2345 bool done; 2346 lcd_setfont(FONT_SYSFIXED); 2347 for (int i = 0; i < count ;) 2348 { 2349 lcd_clear_display(); 2350 for(int j=0; j<LCD_HEIGHT/SYSFONT_HEIGHT; j++,i++) 2351 { 2352 if (!str) 2353 str = cpu_boost_log_getlog_next(); 2354 if (str) 2355 { 2356 if(strlen(str) > LCD_WIDTH/SYSFONT_WIDTH) 2357 lcd_puts_scroll(0, j, str); 2358 else 2359 lcd_puts(0, j,str); 2360 } 2361 str = NULL; 2362 } 2363 lcd_update(); 2364 done = false; 2365 while (!done) 2366 { 2367 switch(get_action(CONTEXT_STD,TIMEOUT_BLOCK)) 2368 { 2369 case ACTION_STD_OK: 2370 case ACTION_STD_PREV: 2371 case ACTION_STD_NEXT: 2372 done = true; 2373 break; 2374 case ACTION_STD_CANCEL: 2375 i = count; 2376 done = true; 2377 break; 2378 } 2379 } 2380 } 2381 lcd_scroll_stop(); 2382 get_action(CONTEXT_STD,TIMEOUT_BLOCK); 2383 lcd_setfont(FONT_UI); 2384 return false; 2385} 2386 2387static bool cpu_boost_log_dump(void) 2388{ 2389 int fd; 2390 int count = cpu_boost_log_getcount(); 2391 char *str = cpu_boost_log_getlog_first(); 2392 2393 splashf(HZ, "Boost Log File Dumped"); 2394 2395 /* nothing to print ? */ 2396 if(count == 0) 2397 return false; 2398 2399#if CONFIG_RTC 2400 char fname[MAX_PATH]; 2401 struct tm *nowtm = get_time(); 2402 fd = open_pathfmt(fname, sizeof(fname), O_CREAT|O_WRONLY|O_TRUNC, 2403 "%s/boostlog_%04d%02d%02d%02d%02d%02d.txt", ROCKBOX_DIR, 2404 nowtm->tm_year + 1900, nowtm->tm_mon + 1, nowtm->tm_mday, 2405 nowtm->tm_hour, nowtm->tm_min, nowtm->tm_sec); 2406#else 2407 fd = open(ROCKBOX_DIR "/boostlog.txt", O_CREAT|O_WRONLY|O_TRUNC, 0666); 2408#endif 2409 if(-1 != fd) { 2410 for (int i = 0; i < count; i++) 2411 { 2412 if (!str) 2413 str = cpu_boost_log_getlog_next(); 2414 if (str) 2415 { 2416 fdprintf(fd, "%s\n", str); 2417 str = NULL; 2418 } 2419 } 2420 2421 close(fd); 2422 return true; 2423 } 2424 2425 return false; 2426} 2427#endif 2428 2429#if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) \ 2430 && !defined(IPOD_MINI) && !defined(SIMULATOR)) 2431extern bool wheel_is_touched; 2432extern int old_wheel_value; 2433extern int new_wheel_value; 2434extern int wheel_delta; 2435extern unsigned int accumulated_wheel_delta; 2436extern unsigned int wheel_velocity; 2437 2438static bool dbg_scrollwheel(void) 2439{ 2440 lcd_setfont(FONT_SYSFIXED); 2441 2442 while (1) 2443 { 2444 if (action_userabort(HZ/10)) 2445 break; 2446 2447 lcd_clear_display(); 2448 2449 /* show internal variables of scrollwheel driver */ 2450 lcd_putsf(0, 0, "wheel touched: %s", (wheel_is_touched) ? "true" : "false"); 2451 lcd_putsf(0, 1, "new position: %2d", new_wheel_value); 2452 lcd_putsf(0, 2, "old position: %2d", old_wheel_value); 2453 lcd_putsf(0, 3, "wheel delta: %2d", wheel_delta); 2454 lcd_putsf(0, 4, "accumulated delta: %2d", accumulated_wheel_delta); 2455 lcd_putsf(0, 5, "velo [deg/s]: %4d", (int)wheel_velocity); 2456 2457 /* show effective accelerated scrollspeed */ 2458 lcd_putsf(0, 6, "accel. speed: %4d", 2459 button_apply_acceleration((1<<31)|(1<<24)|wheel_velocity) ); 2460 2461 lcd_update(); 2462 } 2463 lcd_setfont(FONT_UI); 2464 return false; 2465} 2466#endif 2467 2468static bool dbg_talk(void) 2469{ 2470 struct simplelist_info list; 2471 struct talk_debug_data data; 2472 talk_get_debug_data(&data); 2473 2474 simplelist_info_init(&list, "Voice Information:", 0, NULL); 2475 2476 list.scroll_all = true; 2477 list.timeout = HZ; 2478 2479 simplelist_reset_lines(); 2480 2481 simplelist_setline("Current voice file:"); 2482 if (data.status != TALK_STATUS_ERR_NOFILE) 2483 simplelist_addline(" %s", data.voicefile); 2484 else 2485 simplelist_setline(" No voice information available"); 2486 2487 if (data.status != TALK_STATUS_OK) 2488 { 2489 simplelist_addline("Talk Status: ERR (%i)", 2490 data.status); 2491 return simplelist_show_list(&list); 2492 } 2493 else 2494 simplelist_setline("Talk Status: OK"); 2495 simplelist_setline("Number of (empty) clips in voice file:"); 2496 simplelist_addline(" (%d) %d", data.num_empty_clips, data.num_clips); 2497 simplelist_setline("Min/Avg/Max size of clips:"); 2498 simplelist_addline(" %d / %d / %d", 2499 data.min_clipsize, data.avg_clipsize, data.max_clipsize); 2500 simplelist_setline("Memory allocated:"); 2501 simplelist_addline(" %ld.%02ld KB", 2502 data.memory_allocated / 1024, data.memory_allocated % 1024); 2503 simplelist_addline("Memory used:"); 2504 simplelist_addline(" %ld.%02ld KB", 2505 data.memory_used / 1024, data.memory_used % 1024); 2506 simplelist_setline("Number of clips in cache:"); 2507 simplelist_addline(" %d", data.cached_clips); 2508 simplelist_setline("Cache hits / misses:"); 2509 simplelist_addline("%d / %d", data.cache_hits, data.cache_misses); 2510 2511 return simplelist_show_list(&list); 2512} 2513 2514#ifdef HAVE_USBSTACK 2515#if (defined(ROCKBOX_HAS_LOGF) && defined(USB_ENABLE_SERIAL)) 2516static bool toggle_usb_core_driver(int driver, char *msg) 2517{ 2518 bool enabled = !usb_core_driver_enabled(driver); 2519 2520 usb_core_enable_driver(driver,enabled); 2521 splashf(HZ, "%s %s", msg, enabled ? "enabled" : "disabled"); 2522 2523 return false; 2524} 2525 2526#ifdef USB_ENABLE_SERIAL 2527static bool toggle_usb_serial(void) 2528{ 2529 return toggle_usb_core_driver(USB_DRIVER_SERIAL, "USB Serial"); 2530} 2531#endif /* USB_ENABLE_SERIAL */ 2532#endif 2533 2534#ifdef USB_ENABLE_AUDIO 2535static int dbg_usb_audio_cb(int action, struct gui_synclist *lists) 2536{ 2537 (void)lists; 2538 simplelist_reset_lines(); 2539 simplelist_addline("%sabled", usb_core_driver_enabled(USB_DRIVER_AUDIO)?"En":"Dis"); 2540 simplelist_addline("%sPlaying", usb_audio_get_playing()?"":"Not "); 2541 simplelist_addline("iface: %d alt: %d", usb_audio_get_main_intf(), usb_audio_get_alt_intf()); 2542 simplelist_addline("out ep: 0x%X in ep: 0x%X", usb_audio_get_out_ep(), usb_audio_get_in_ep()); 2543 simplelist_addline("Volume: %d", usb_audio_get_cur_volume()); 2544 simplelist_addline("Playback Frequency: %lu", usb_audio_get_playback_sampling_frequency()); 2545 simplelist_addline("Frames dropped: %d", usb_audio_get_frames_dropped()); 2546 simplelist_addline("Buffers filled: %f", (double)usb_audio_get_prebuffering_avg()/(1<<16)); // convert from 16.16 fixed to float 2547 simplelist_addline("Min: %d / Max: %d", usb_audio_get_prebuffering_maxmin(false), usb_audio_get_prebuffering_maxmin(true)); 2548 simplelist_addline("Samples used per Frame: %f", (double)usb_audio_get_samplesperframe()/(1<<16)); // convert from 16.16 fixed to float 2549 simplelist_addline("Samples received per frame: %f", (double)usb_audio_get_samples_rx_perframe()/(1<<16)); // convert from 16.16 fixed to float 2550 simplelist_addline("Samples diff: %f", (double)(usb_audio_get_samplesperframe()-usb_audio_get_samples_rx_perframe())/(1<<16)); // convert from 16.16 fixed to float 2551 simplelist_addline("%s", usb_audio_get_underflow()?"UNDERFLOW!":" "); 2552 simplelist_addline("%s", usb_audio_get_overflow()?"OVERFLOW!":" "); 2553 simplelist_addline("%s", usb_audio_get_alloc_failed()?"ALLOC FAILED!":" "); 2554 if (action == ACTION_NONE) 2555 { 2556 action = ACTION_REDRAW; 2557 } 2558 return action; 2559} 2560static bool dbg_usb_audio(void) 2561{ 2562 struct simplelist_info info; 2563 simplelist_info_init(&info, "USB Audio", 0, NULL); 2564 info.scroll_all = true; 2565 info.action_callback = dbg_usb_audio_cb; 2566 return simplelist_show_list(&info); 2567} 2568#endif /* USB_ENABLE_AUDIO */ 2569#endif /* HAVE_USBSTACK */ 2570 2571#if CONFIG_USBOTG == USBOTG_ISP1583 2572extern int dbg_usb_num_items(void); 2573extern const char* dbg_usb_item(int selected_item, void *data, 2574 char *buffer, size_t buffer_len); 2575 2576static int isp1583_action_callback(int action, struct gui_synclist *lists) 2577{ 2578 (void)lists; 2579 if (action == ACTION_NONE) 2580 action = ACTION_REDRAW; 2581 return action; 2582} 2583 2584static bool dbg_isp1583(void) 2585{ 2586 struct simplelist_info isp1583; 2587 isp1583.scroll_all = true; 2588 simplelist_info_init(&isp1583, "ISP1583", dbg_usb_num_items(), NULL); 2589 isp1583.timeout = HZ/100; 2590 isp1583.get_name = dbg_usb_item; 2591 isp1583.action_callback = isp1583_action_callback; 2592 return simplelist_show_list(&isp1583); 2593} 2594#endif 2595 2596#if defined(CREATIVE_ZVx) && !defined(SIMULATOR) 2597extern int pic_dbg_num_items(void); 2598extern const char* pic_dbg_item(int selected_item, void *data, 2599 char *buffer, size_t buffer_len); 2600 2601static int pic_action_callback(int action, struct gui_synclist *lists) 2602{ 2603 (void)lists; 2604 if (action == ACTION_NONE) 2605 action = ACTION_REDRAW; 2606 return action; 2607} 2608 2609static bool dbg_pic(void) 2610{ 2611 struct simplelist_info pic; 2612 pic.scroll_all = true; 2613 simplelist_info_init(&pic, "PIC", pic_dbg_num_items(), NULL); 2614 pic.timeout = HZ/100; 2615 pic.get_name = pic_dbg_item; 2616 pic.action_callback = pic_action_callback; 2617 return simplelist_show_list(&pic); 2618} 2619#endif 2620 2621#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) 2622static bool dbg_boot_data(void) 2623{ 2624 struct simplelist_info info; 2625 info.scroll_all = true; 2626 simplelist_info_init(&info, "Boot data", 0, NULL); 2627 simplelist_reset_lines(); 2628 2629 if (!boot_data_valid) 2630 { 2631 simplelist_setline("Boot data invalid"); 2632 simplelist_addline("Magic[0]: %08lx", boot_data.magic[0]); 2633 simplelist_addline("Magic[1]: %08lx", boot_data.magic[1]); 2634 simplelist_addline("Length: %lu", boot_data.length); 2635 } 2636 else 2637 { 2638 simplelist_setline("Boot data valid"); 2639 simplelist_addline("Version: %d", (int)boot_data.version); 2640 2641 if (boot_data.version == 0) 2642 { 2643 simplelist_addline("Boot volume: %d", (int)boot_data._boot_volume); 2644 } 2645 else if (boot_data.version == 1) 2646 { 2647 simplelist_addline("Boot drive: %d", (int)boot_data.boot_drive); 2648 simplelist_addline("Boot partition: %d", (int)boot_data.boot_partition); 2649 } 2650 simplelist_setline("Boot path:"); 2651 simplelist_addline(" %s%s/%s", root_realpath(), BOOTDIR, BOOTFILE); 2652 } 2653 2654 simplelist_setline("Bootdata RAW:"); 2655 for (size_t i = 0; i < boot_data.length; i += 4) 2656 { 2657 simplelist_addline("%02x: %02x %02x %02x %02x", i, 2658 boot_data.payload[i + 0], boot_data.payload[i + 1], 2659 boot_data.payload[i + 2], boot_data.payload[i + 3]); 2660 } 2661 2662 return simplelist_show_list(&info); 2663} 2664#endif /* defined(HAVE_BOOTDATA) && !defined(SIMULATOR) */ 2665 2666#if defined(HAVE_DEVICEDATA)// && !defined(SIMULATOR) 2667static bool dbg_device_data(void) 2668{ 2669 struct simplelist_info info; 2670 info.scroll_all = true; 2671 simplelist_info_init(&info, "Device data", 0, NULL); 2672 simplelist_reset_lines(); 2673 2674 simplelist_setline("Device data"); 2675 2676#if defined(EROS_QN) 2677 simplelist_addline("Hardware Revision: %d", (int)device_data.hw_rev); 2678#endif 2679 simplelist_addline("Struct Ver: %d", (int)device_data.version); 2680 2681 simplelist_setline("Device data RAW:"); 2682 for (size_t i = 0; i < device_data.length; i += 4) 2683 { 2684 simplelist_addline("%02zx: %02x %02x %02x %02x", i, 2685 device_data.payload[i + 0], device_data.payload[i + 1], 2686 device_data.payload[i + 2], device_data.payload[i + 3]); 2687 } 2688 2689 return simplelist_show_list(&info); 2690} 2691#endif /* defined(HAVE_DEVICEDATA)*/ 2692 2693 2694#if defined(IPOD_6G) && !defined(SIMULATOR) 2695static bool dbg_syscfg(void) { 2696 struct simplelist_info info; 2697 struct SysCfg syscfg; 2698 2699 simplelist_info_init(&info, "SysCfg NOR contents", 0, NULL); 2700 simplelist_reset_lines(); 2701 2702 const ssize_t result = syscfg_read(&syscfg); 2703 2704 if (result == -1) { 2705 simplelist_setline("SCfg magic not found"); 2706 return simplelist_show_list(&info); 2707 } 2708 2709 simplelist_addline("Total size: %lu bytes, %lu entries", syscfg.header.size, syscfg.header.num_entries); 2710 2711 if (result > 0) { 2712 simplelist_addline("Wrong size: expected %ld, got %lu", result, syscfg.header.size); 2713 return simplelist_show_list(&info); 2714 } 2715 2716 if (syscfg.header.num_entries > SYSCFG_MAX_ENTRIES) { 2717 simplelist_addline("Too many entries, showing only first %u", SYSCFG_MAX_ENTRIES); 2718 } 2719 2720 const size_t syscfg_num_entries = MIN(syscfg.header.num_entries, SYSCFG_MAX_ENTRIES); 2721 2722 for (size_t i = 0; i < syscfg_num_entries; i++) { 2723 const struct SysCfgEntry* entry = &syscfg.entries[i]; 2724 const char* tag = (char *)&entry->tag; 2725 const uint32_t* data32 = (uint32_t *)entry->data; 2726 2727 switch (entry->tag) { 2728 case SYSCFG_TAG_SRNM: 2729 simplelist_addline("Serial number (SrNm): %s", entry->data); 2730 break; 2731 case SYSCFG_TAG_FWID: 2732 simplelist_addline("Firmware ID (FwId): %07lX", data32[1] & 0x0FFFFFFF); 2733 break; 2734 case SYSCFG_TAG_HWID: 2735 simplelist_addline("Hardware ID (HwId): %08lX", data32[0]); 2736 break; 2737 case SYSCFG_TAG_HWVR: 2738 simplelist_addline("Hardware version (HwVr): %06lX", data32[1]); 2739 break; 2740 case SYSCFG_TAG_CODC: 2741 simplelist_addline("Codec (Codc): %s", entry->data); 2742 break; 2743 case SYSCFG_TAG_SWVR: 2744 simplelist_addline("Software version (SwVr): %s", entry->data); 2745 break; 2746 case SYSCFG_TAG_MLBN: 2747 simplelist_addline("Logic board serial number (MLBN): %s", entry->data); 2748 break; 2749 case SYSCFG_TAG_MODN: 2750 simplelist_addline("Model number (Mod#): %s", entry->data); 2751 break; 2752 case SYSCFG_TAG_REGN: 2753 simplelist_addline("Sales region (Regn): %08lX %08lX", data32[0], data32[1]); 2754 break; 2755 default: 2756 simplelist_addline("%c%c%c%c: %08lX %08lX %08lX %08lX", 2757 tag[3], tag[2], tag[1], tag[0], 2758 data32[0], data32[1], data32[2], data32[3] 2759 ); 2760 break; 2761 } 2762 } 2763 2764 return simplelist_show_list(&info); 2765} 2766 2767#define FLASH_PAGES (FLASH_SIZE >> 12) 2768#define FLASH_PAGE_SIZE (FLASH_SIZE >> 8) 2769 2770static bool dbg_bootflash_dump(void) { 2771 splashf(HZ, "Please wait..."); 2772 2773 int fd; 2774 2775 fd = creat("/bootflash.bin", 0666); 2776 2777 if (fd < 0) 2778 { 2779 splashf(HZ * 3, "Error opening file"); 2780 return false; 2781 } 2782 2783 uint8_t page[FLASH_PAGE_SIZE]; 2784 bootflash_init(SPI_PORT); 2785 2786 for (int i = 0; i < FLASH_PAGES; i++) { 2787 bootflash_read(SPI_PORT, i << 12, FLASH_PAGE_SIZE, page); 2788 write(fd, page, FLASH_PAGE_SIZE); 2789 } 2790 2791 bootflash_close(SPI_PORT); 2792 close(fd); 2793 splashf(HZ * 3, "Dump saved to /bootflash.bin"); 2794 2795 return false; 2796} 2797#endif 2798 2799/****** The menu *********/ 2800static const struct { 2801 unsigned char *desc; /* string or ID */ 2802 bool (*function) (void); /* return true if USB was connected */ 2803} menuitems[] = { 2804#if defined(CPU_COLDFIRE) || \ 2805 (defined(CPU_PP) && !(CONFIG_STORAGE & STORAGE_SD)) || \ 2806 CONFIG_CPU == IMX31L || defined(CPU_TCC780X) || CONFIG_CPU == AS3525v2 || \ 2807 CONFIG_CPU == AS3525 || CONFIG_CPU == RK27XX 2808 { "Dump ROM contents", dbg_save_roms }, 2809#endif 2810#if defined(CPU_COLDFIRE) || defined(CPU_PP) \ 2811 || CONFIG_CPU == S3C2440 || CONFIG_CPU == IMX31L || CONFIG_CPU == AS3525 \ 2812 || CONFIG_CPU == DM320 || defined(CPU_S5L87XX) || CONFIG_CPU == AS3525v2 \ 2813 || CONFIG_CPU == RK27XX || CONFIG_CPU == JZ4760B 2814 { "View I/O ports", dbg_ports }, 2815#endif 2816#if (CONFIG_RTC == RTC_PCF50605) && (CONFIG_PLATFORM & PLATFORM_NATIVE) 2817 { "View PCF registers", dbg_pcf }, 2818#endif 2819#if defined(HAVE_TSC2100) && (CONFIG_PLATFORM & PLATFORM_NATIVE) 2820 { "TSC2100 debug", tsc2100_debug }, 2821#endif 2822#ifdef HAVE_ADJUSTABLE_CPU_FREQ 2823 { "CPU frequency", dbg_cpufreq }, 2824#endif 2825#if CONFIG_CPU == IMX31L 2826 { "DVFS/DPTC", __dbg_dvfs_dptc }, 2827#endif 2828#if defined(IRIVER_H100_SERIES) && !defined(SIMULATOR) 2829 { "S/PDIF analyzer", dbg_spdif }, 2830#endif 2831#if defined(CPU_COLDFIRE) 2832 { "Catch mem accesses", dbg_set_memory_guard }, 2833#endif 2834 { "View OS stacks", dbg_os }, 2835#ifdef __linux__ 2836 { "View CPU stats", dbg_cpuinfo }, 2837#endif 2838#if (CONFIG_BATTERY_MEASURE != 0) && !defined(SIMULATOR) 2839 { "View battery", view_battery }, 2840#endif 2841#ifndef APPLICATION 2842 { "Screendump", dbg_screendump }, 2843#endif 2844 { "Skin Engine RAM usage", dbg_skin_engine }, 2845#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || defined(FIIO_M3K_LINUX)) && !defined(SIMULATOR) 2846 { "View HW info", dbg_hw_info }, 2847#endif 2848#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 2849 { "View partitions", dbg_partitions }, 2850#endif 2851#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 2852 { "View disk info", dbg_disk_info }, 2853#if (CONFIG_STORAGE & STORAGE_ATA) 2854 { "Dump ATA identify info", dbg_identify_info}, 2855#ifdef HAVE_ATA_SMART 2856 { "View/Dump S.M.A.R.T. data", dbg_ata_smart}, 2857#endif 2858#endif 2859#endif 2860 { "Metadata log", dbg_metadatalog }, 2861#ifdef HAVE_DIRCACHE 2862 { "View dircache info", dbg_dircache_info }, 2863#endif 2864#ifdef HAVE_TAGCACHE 2865 { "View database info", dbg_tagcache_info }, 2866#endif 2867 { "View buffering thread", dbg_buffering_thread }, 2868#ifdef PM_DEBUG 2869 { "pm histogram", peak_meter_histogram}, 2870#endif /* PM_DEBUG */ 2871#ifdef BUFLIB_DEBUG_PRINT 2872 { "View buflib allocs", dbg_buflib_allocs }, 2873#endif 2874#ifndef SIMULATOR 2875#if CONFIG_TUNER 2876 { "FM Radio", dbg_fm_radio }, 2877#endif 2878#endif 2879#if defined(HAVE_EEPROM) && !defined(HAVE_EEPROM_SETTINGS) 2880 { "Write back EEPROM", dbg_write_eeprom }, 2881#endif 2882#if CONFIG_USBOTG == USBOTG_ISP1583 2883 { "View ISP1583 info", dbg_isp1583 }, 2884#endif 2885#if defined(CREATIVE_ZVx) && !defined(SIMULATOR) 2886 { "View PIC info", dbg_pic }, 2887#endif 2888#ifdef ROCKBOX_HAS_LOGF 2889 {"Show Log File", logfdisplay }, 2890 {"Dump Log File", logfdump }, 2891#endif 2892#if defined(HAVE_USBSTACK) 2893#if defined(ROCKBOX_HAS_LOGF) && defined(USB_ENABLE_SERIAL) 2894 {"USB Serial driver (logf)", toggle_usb_serial }, 2895#endif 2896#if defined(USB_ENABLE_AUDIO) 2897 {"USB-DAC", dbg_usb_audio}, 2898#endif 2899#endif /* HAVE_USBSTACK */ 2900#ifdef CPU_BOOST_LOGGING 2901 {"Show cpu_boost log",cpu_boost_log}, 2902 {"Dump cpu_boost log",cpu_boost_log_dump}, 2903#endif 2904#if (defined(HAVE_WHEEL_ACCELERATION) && (CONFIG_KEYPAD==IPOD_4G_PAD) \ 2905 && !defined(IPOD_MINI) && !defined(SIMULATOR)) 2906 {"Debug scrollwheel", dbg_scrollwheel }, 2907#endif 2908#if defined(IPOD_ACCESSORY_PROTOCOL) 2909 {"Debug IAP", dbg_iap }, 2910#endif 2911 {"Talk engine stats", dbg_talk }, 2912#if defined(HAVE_BOOTDATA) && !defined(SIMULATOR) 2913 {"Boot data", dbg_boot_data }, 2914#endif 2915 2916#if defined(HAVE_DEVICEDATA)// && !defined(SIMULATOR) 2917 {"Device data", dbg_device_data }, 2918#endif 2919 2920#if defined(IPOD_6G) && !defined(SIMULATOR) 2921 {"View SysCfg", dbg_syscfg }, 2922 {"Dump bootflash to file", dbg_bootflash_dump }, 2923#endif 2924}; 2925 2926static int menu_action_callback(int btn, struct gui_synclist *lists) 2927{ 2928 int selection = gui_synclist_get_sel_pos(lists); 2929 if (btn == ACTION_STD_OK) 2930 { 2931 FOR_NB_SCREENS(i) 2932 viewportmanager_theme_enable(i, false, NULL); 2933 menuitems[selection].function(); 2934 btn = ACTION_REDRAW; 2935 FOR_NB_SCREENS(i) 2936 viewportmanager_theme_undo(i, false); 2937 } 2938 else if (btn == ACTION_STD_CONTEXT) 2939 { 2940 MENUITEM_STRINGLIST(menu_items, "Debug Menu", NULL, ID2P(LANG_ADD_TO_FAVES)); 2941 if (do_menu(&menu_items, NULL, NULL, false) == 0) 2942 shortcuts_add(SHORTCUT_DEBUGITEM, menuitems[selection].desc); 2943 return ACTION_STD_CANCEL; 2944 } 2945 return btn; 2946} 2947 2948static const char* menu_get_name(int item, void * data, 2949 char *buffer, size_t buffer_len) 2950{ 2951 (void)data; (void)buffer; (void)buffer_len; 2952 return menuitems[item].desc; 2953} 2954 2955static int menu_get_talk(int item, void *data) 2956{ 2957 (void)data; 2958 if (global_settings.talk_menu && menuitems[item].desc) 2959 { 2960 talk_number(item + 1, true); 2961 talk_id(VOICE_PAUSE, true); 2962#if 0 /* no debug items currently have lang ids */ 2963 long id = P2ID((const unsigned char *)(menuitems[item].desc)); 2964 if(id>=0) 2965 talk_id(id, true); 2966 else 2967#endif 2968 talk_spell(menuitems[item].desc, true); 2969 } 2970 return 0; 2971} 2972 2973int debug_menu(void) 2974{ 2975 struct simplelist_info info; 2976 2977 simplelist_info_init(&info, "Debug Menu", ARRAYLEN(menuitems), NULL); 2978 info.action_callback = menu_action_callback; 2979 info.get_name = menu_get_name; 2980 info.get_talk = menu_get_talk; 2981 return (simplelist_show_list(&info)) ? 1 : 0; 2982} 2983 2984bool run_debug_screen(char* screen) 2985{ 2986 for (unsigned i=0; i<ARRAYLEN(menuitems); i++) 2987 if (!strcasecmp(screen, menuitems[i].desc)) 2988 { 2989 FOR_NB_SCREENS(j) 2990 viewportmanager_theme_enable(j, false, NULL); 2991 menuitems[i].function(); 2992 FOR_NB_SCREENS(j) 2993 viewportmanager_theme_undo(j, false); 2994 return true; 2995 } 2996 2997 return false; 2998}