mirror of
https://github.com/Rockbox/rockbox.git
synced 2026-01-22 01:30:35 -05:00
Purge "Menu" or "Rockbox" from plugin menu titles and match application names from manual. Exception: "Main Menu" is left unchanged as the title for the Main Menu Configuration plugin, since it appears in Rockbox's Settings menu and therefore should match the name of the setting. E.g.: "Rockbox Goban" => "Goban" "Image Viewer Menu" => "Image Viewer" "Viewer Menu" => "Text Viewer" "Menu" => "Chess Clock" "Do What?" => "Text Editor" "Mpegplayer Menu" => "MPEG Player" "Multiboot Settings" => "Multiboot" "Disktidy" => "Disk Tidy" ... Change-Id: Ie6d3be7557f31a36309489037ad8b2b27b06706e
496 lines
13 KiB
C
496 lines
13 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2007 Jens Arnold
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "plugin.h"
|
|
#include "lib/helper.h"
|
|
|
|
|
|
|
|
#define TESTBASEDIR HOME_DIR "/__TEST__"
|
|
#define TEST_FILE TESTBASEDIR "/test_disk.tmp"
|
|
#define FRND_SEED 0x78C3 /* arbirary */
|
|
|
|
#if (CONFIG_STORAGE & STORAGE_MMC)
|
|
#define TEST_SIZE (20*1024*1024)
|
|
#else
|
|
#define TEST_SIZE (300*1024*1024)
|
|
#endif
|
|
#define TEST_TIME 10 /* in seconds */
|
|
|
|
static unsigned char* audiobuf;
|
|
static size_t audiobuflen;
|
|
|
|
static unsigned short frnd_buffer;
|
|
static int line = 0;
|
|
static int max_line = 0;
|
|
static int log_fd;
|
|
static char logfilename[MAX_PATH];
|
|
static const char testbasedir[] = TESTBASEDIR;
|
|
|
|
static void mem_fill_frnd(unsigned char *addr, int len)
|
|
{
|
|
unsigned char *end = addr + len;
|
|
unsigned random = frnd_buffer;
|
|
|
|
while (addr < end)
|
|
{
|
|
random = 75 * random + 74;
|
|
*addr++ = random >> 8;
|
|
}
|
|
frnd_buffer = random;
|
|
}
|
|
|
|
static bool mem_cmp_frnd(unsigned char *addr, int len)
|
|
{
|
|
unsigned char *end = addr + len;
|
|
unsigned random = frnd_buffer;
|
|
|
|
while (addr < end)
|
|
{
|
|
random = 75 * random + 74;
|
|
if (*addr++ != ((random >> 8) & 0xff))
|
|
return false;
|
|
}
|
|
frnd_buffer = random;
|
|
return true;
|
|
}
|
|
|
|
static bool log_init(void)
|
|
{
|
|
int h;
|
|
|
|
rb->lcd_getstringsize("A", NULL, &h);
|
|
max_line = LCD_HEIGHT / h;
|
|
line = 0;
|
|
rb->lcd_clear_display();
|
|
rb->lcd_update();
|
|
|
|
rb->create_numbered_filename(logfilename, HOME_DIR, "test_disk_log_", ".txt",
|
|
2 IF_CNFN_NUM_(, NULL));
|
|
log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666);
|
|
return log_fd >= 0;
|
|
}
|
|
|
|
static void log_text(char *text, bool advance)
|
|
{
|
|
rb->lcd_puts(0, line, text);
|
|
rb->lcd_update();
|
|
if (advance)
|
|
{
|
|
if (++line >= max_line)
|
|
line = 0;
|
|
rb->fdprintf(log_fd, "%s\n", text);
|
|
}
|
|
}
|
|
|
|
static void log_close(void)
|
|
{
|
|
rb->close(log_fd);
|
|
}
|
|
|
|
static bool test_fs(void)
|
|
{
|
|
unsigned char text_buf[32];
|
|
int total, current, align;
|
|
int fd, ret;
|
|
|
|
log_init();
|
|
log_text("test_disk WRITE&VERIFY", true);
|
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
|
rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
|
|
*rb->cpu_frequency);
|
|
log_text(text_buf, true);
|
|
#endif
|
|
log_text("----------------------", true);
|
|
rb->snprintf(text_buf, sizeof text_buf, "Data size: %dKB", (TEST_SIZE>>10));
|
|
log_text(text_buf, true);
|
|
|
|
fd = rb->creat(TEST_FILE, 0666);
|
|
if (fd < 0)
|
|
{
|
|
rb->splashf(HZ, "creat() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
|
|
frnd_buffer = FRND_SEED;
|
|
total = TEST_SIZE;
|
|
while (total > 0)
|
|
{
|
|
align = rb->rand() & 0xf;
|
|
current = rb->rand() % (audiobuflen - align);
|
|
current = MIN(current, total);
|
|
rb->snprintf(text_buf, sizeof text_buf, "Wrt %dKB, %dKB left",
|
|
current >> 10, total >> 10);
|
|
log_text(text_buf, false);
|
|
|
|
mem_fill_frnd(audiobuf + align, current);
|
|
ret = rb->write(fd, audiobuf + align, current);
|
|
if (current != ret)
|
|
{
|
|
rb->splashf(0, "write() failed: %d/%d", ret, current);
|
|
rb->close(fd);
|
|
goto error;
|
|
}
|
|
total -= current;
|
|
}
|
|
rb->close(fd);
|
|
|
|
fd = rb->open(TEST_FILE, O_RDONLY);
|
|
if (fd < 0)
|
|
{
|
|
rb->splashf(0, "open() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
|
|
frnd_buffer = FRND_SEED;
|
|
total = TEST_SIZE;
|
|
while (total > 0)
|
|
{
|
|
align = rb->rand() & 0xf;
|
|
current = rb->rand() % (audiobuflen - align);
|
|
current = MIN(current, total);
|
|
rb->snprintf(text_buf, sizeof text_buf, "Cmp %dKB, %dKB left",
|
|
current >> 10, total >> 10);
|
|
log_text(text_buf, false);
|
|
|
|
ret = rb->read(fd, audiobuf + align, current);
|
|
if (current != ret)
|
|
{
|
|
rb->splashf(0, "read() failed: %d/%d", ret, current);
|
|
rb->close(fd);
|
|
goto error;
|
|
}
|
|
if (!mem_cmp_frnd(audiobuf + align, current))
|
|
{
|
|
log_text(text_buf, true);
|
|
log_text("Compare error.", true);
|
|
rb->close(fd);
|
|
goto error;
|
|
}
|
|
total -= current;
|
|
}
|
|
rb->close(fd);
|
|
log_text(text_buf, true);
|
|
log_text("Test passed.", true);
|
|
|
|
error:
|
|
log_close();
|
|
rb->remove(TEST_FILE);
|
|
rb->button_clear_queue();
|
|
rb->button_get(true);
|
|
|
|
return false;
|
|
}
|
|
|
|
static bool file_speed(int chunksize, bool align)
|
|
{
|
|
unsigned char text_buf[64];
|
|
int fd, ret;
|
|
long filesize = 0;
|
|
long size, time;
|
|
|
|
if ((unsigned)chunksize >= audiobuflen)
|
|
return false;
|
|
|
|
log_text("--------------------", true);
|
|
|
|
/* File creation write speed */
|
|
fd = rb->creat(TEST_FILE, 0666);
|
|
if (fd < 0)
|
|
{
|
|
rb->splashf(HZ, "creat() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
time = *rb->current_tick;
|
|
while (TIME_BEFORE(*rb->current_tick, time + TEST_TIME*HZ))
|
|
{
|
|
ret = rb->write(fd, audiobuf + (align ? 0 : 1), chunksize);
|
|
if (chunksize != ret)
|
|
{
|
|
rb->splashf(HZ, "write() failed: %d/%d", ret, chunksize);
|
|
rb->close(fd);
|
|
goto error;
|
|
}
|
|
filesize += chunksize;
|
|
}
|
|
time = *rb->current_tick - time;
|
|
rb->close(fd);
|
|
rb->snprintf(text_buf, sizeof text_buf, "Create (%d,%c): %ld KB/s",
|
|
chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
|
|
log_text(text_buf, true);
|
|
|
|
/* Existing file write speed */
|
|
fd = rb->open(TEST_FILE, O_WRONLY);
|
|
if (fd < 0)
|
|
{
|
|
rb->splashf(0, "open() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
time = *rb->current_tick;
|
|
for (size = filesize; size > 0; size -= chunksize)
|
|
{
|
|
ret = rb->write(fd, audiobuf + (align ? 0 : 1), chunksize);
|
|
if (chunksize != ret)
|
|
{
|
|
rb->splashf(0, "write() failed: %d/%d", ret, chunksize);
|
|
rb->close(fd);
|
|
goto error;
|
|
}
|
|
}
|
|
time = *rb->current_tick - time;
|
|
rb->close(fd);
|
|
rb->snprintf(text_buf, sizeof text_buf, "Write (%d,%c): %ld KB/s",
|
|
chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
|
|
log_text(text_buf, true);
|
|
|
|
/* File read speed */
|
|
fd = rb->open(TEST_FILE, O_RDONLY);
|
|
if (fd < 0)
|
|
{
|
|
rb->splashf(0, "open() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
time = *rb->current_tick;
|
|
for (size = filesize; size > 0; size -= chunksize)
|
|
{
|
|
ret = rb->read(fd, audiobuf + (align ? 0 : 1), chunksize);
|
|
if (chunksize != ret)
|
|
{
|
|
rb->splashf(0, "read() failed: %d/%d", ret, chunksize);
|
|
rb->close(fd);
|
|
goto error;
|
|
}
|
|
}
|
|
time = *rb->current_tick - time;
|
|
rb->close(fd);
|
|
rb->snprintf(text_buf, sizeof text_buf, "Read (%d,%c): %ld KB/s",
|
|
chunksize, align ? 'A' : 'U', (25 * (filesize>>8) / time) );
|
|
log_text(text_buf, true);
|
|
rb->remove(TEST_FILE);
|
|
return true;
|
|
|
|
error:
|
|
rb->remove(TEST_FILE);
|
|
return false;
|
|
}
|
|
|
|
static bool test_speed(void)
|
|
{
|
|
unsigned char text_buf[64];
|
|
DIR *dir = NULL;
|
|
struct dirent *entry = NULL;
|
|
int fd, last_file;
|
|
int i, n;
|
|
long time;
|
|
|
|
rb->memset(audiobuf, 'T', audiobuflen);
|
|
log_init();
|
|
log_text("test_disk SPEED TEST", true);
|
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
|
rb->snprintf(text_buf, sizeof(text_buf), "CPU clock: %ld Hz",
|
|
*rb->cpu_frequency);
|
|
log_text(text_buf, true);
|
|
#endif
|
|
log_text("--------------------", true);
|
|
|
|
/* File creation speed */
|
|
time = *rb->current_tick + TEST_TIME*HZ;
|
|
for (i = 0; TIME_BEFORE(*rb->current_tick, time); i++)
|
|
{
|
|
rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
|
|
fd = rb->creat(text_buf, 0666);
|
|
if (fd < 0)
|
|
{
|
|
last_file = i;
|
|
rb->splashf(HZ, "creat() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
rb->close(fd);
|
|
}
|
|
last_file = i;
|
|
rb->snprintf(text_buf, sizeof(text_buf), "Create: %d files/s",
|
|
last_file / TEST_TIME);
|
|
log_text(text_buf, true);
|
|
|
|
/* File open speed */
|
|
time = *rb->current_tick + TEST_TIME*HZ;
|
|
for (n = 0, i = 0; TIME_BEFORE(*rb->current_tick, time); n++, i++)
|
|
{
|
|
if (i >= last_file)
|
|
i = 0;
|
|
rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
|
|
fd = rb->open(text_buf, O_RDONLY);
|
|
if (fd < 0)
|
|
{
|
|
rb->splashf(HZ, "open() failed: %d", fd);
|
|
goto error;
|
|
}
|
|
rb->close(fd);
|
|
}
|
|
rb->snprintf(text_buf, sizeof(text_buf), "Open: %d files/s", n / TEST_TIME);
|
|
log_text(text_buf, true);
|
|
|
|
/* Directory scan speed */
|
|
time = *rb->current_tick + TEST_TIME*HZ;
|
|
for (n = 0; TIME_BEFORE(*rb->current_tick, time); n++)
|
|
{
|
|
if (entry == NULL)
|
|
{
|
|
if (dir != NULL)
|
|
rb->closedir(dir);
|
|
dir = rb->opendir(testbasedir);
|
|
if (dir == NULL)
|
|
{
|
|
rb->splash(HZ, "opendir() failed.");
|
|
goto error;
|
|
}
|
|
}
|
|
entry = rb->readdir(dir);
|
|
}
|
|
rb->closedir(dir);
|
|
rb->snprintf(text_buf, sizeof(text_buf), "Dirscan: %d files/s", n / TEST_TIME);
|
|
log_text(text_buf, true);
|
|
|
|
dir = NULL;
|
|
entry = NULL;
|
|
/* Directory scan speed 2 */
|
|
time = *rb->current_tick + TEST_TIME*HZ;
|
|
for (n = 0; TIME_BEFORE(*rb->current_tick, time); n++)
|
|
{
|
|
if (entry == NULL)
|
|
{
|
|
if (dir != NULL)
|
|
rb->closedir(dir);
|
|
dir = rb->opendir(testbasedir);
|
|
if (dir == NULL)
|
|
{
|
|
rb->splash(HZ, "opendir() failed.");
|
|
goto error;
|
|
}
|
|
}
|
|
else
|
|
(void) rb->dir_get_info(dir, entry);
|
|
entry = rb->readdir(dir);
|
|
}
|
|
rb->closedir(dir);
|
|
rb->snprintf(text_buf, sizeof(text_buf), "Dirscan w info: %d files/s", n / TEST_TIME);
|
|
log_text(text_buf, true);
|
|
|
|
/* File delete speed */
|
|
time = *rb->current_tick;
|
|
for (i = 0; i < last_file; i++)
|
|
{
|
|
rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
|
|
rb->remove(text_buf);
|
|
}
|
|
rb->snprintf(text_buf, sizeof(text_buf), "Delete: %ld files/s",
|
|
last_file * HZ / (*rb->current_tick - time));
|
|
log_text(text_buf, true);
|
|
|
|
if (file_speed(512, true)
|
|
&& file_speed(512, false)
|
|
&& file_speed(4096, true)
|
|
&& file_speed(4096, false)
|
|
&& file_speed(1048576, true))
|
|
file_speed(1048576, false);
|
|
|
|
log_text("DONE", false);
|
|
log_close();
|
|
rb->button_clear_queue();
|
|
rb->button_get(true);
|
|
return false;
|
|
|
|
error:
|
|
for (i = 0; i < last_file; i++)
|
|
{
|
|
rb->snprintf(text_buf, sizeof(text_buf), TESTBASEDIR "/%08x.tmp", i);
|
|
rb->remove(text_buf);
|
|
}
|
|
log_text("DONE", false);
|
|
log_close();
|
|
rb->button_clear_queue();
|
|
rb->button_get(true);
|
|
return false;
|
|
}
|
|
|
|
|
|
/* this is the plugin entry point */
|
|
enum plugin_status plugin_start(const void* parameter)
|
|
{
|
|
MENUITEM_STRINGLIST(menu, "Test Disk", NULL,
|
|
"Disk speed", "Write & verify");
|
|
int selected=0;
|
|
bool quit = false;
|
|
DIR *dir;
|
|
|
|
(void)parameter;
|
|
|
|
if ((dir = rb->opendir(testbasedir)) == NULL)
|
|
{
|
|
if (rb->mkdir(testbasedir) < 0)
|
|
{
|
|
rb->splash(HZ*2, "Can't create test directory.");
|
|
return PLUGIN_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rb->closedir(dir);
|
|
}
|
|
|
|
audiobuf = rb->plugin_get_audio_buffer(&audiobuflen);
|
|
#ifdef STORAGE_WANTS_ALIGN
|
|
/* align start and length for DMA */
|
|
STORAGE_ALIGN_BUFFER(audiobuf, audiobuflen);
|
|
#else
|
|
/* align start and length to 32 bit */
|
|
ALIGN_BUFFER(audiobuf, audiobuflen, 4);
|
|
#endif
|
|
|
|
rb->srand(*rb->current_tick);
|
|
|
|
/* Turn off backlight timeout */
|
|
backlight_ignore_timeout();
|
|
|
|
|
|
while(!quit)
|
|
{
|
|
switch(rb->do_menu(&menu, &selected, NULL, false))
|
|
{
|
|
case 0:
|
|
test_speed();
|
|
break;
|
|
case 1:
|
|
test_fs();
|
|
break;
|
|
default:
|
|
quit = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Turn on backlight timeout (revert to settings) */
|
|
backlight_use_settings();
|
|
|
|
rb->rmdir(testbasedir);
|
|
|
|
return PLUGIN_OK;
|
|
}
|