1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 Jens Arnold
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
23 #include "oldmenuapi.h"
28 #define TESTBASEDIR "/__TEST__"
29 #define TEST_FILE TESTBASEDIR "/test_disk.tmp"
30 #define FRND_SEED 0x78C3 /* arbirary */
33 #define TEST_SIZE (20*1024*1024)
35 #define TEST_SIZE (300*1024*1024)
37 #define TEST_TIME 10 /* in seconds */
39 static const struct plugin_api
* rb
;
40 static unsigned char* audiobuf
;
41 static ssize_t audiobuflen
;
43 static unsigned short frnd_buffer
;
45 static int max_line
= 0;
47 static char logfilename
[MAX_PATH
];
48 static const char testbasedir
[] = TESTBASEDIR
;
50 static void mem_fill_frnd(unsigned char *addr
, int len
)
52 unsigned char *end
= addr
+ len
;
53 unsigned random
= frnd_buffer
;
57 random
= 75 * random
+ 74;
58 *addr
++ = random
>> 8;
63 static bool mem_cmp_frnd(unsigned char *addr
, int len
)
65 unsigned char *end
= addr
+ len
;
66 unsigned random
= frnd_buffer
;
70 random
= 75 * random
+ 74;
71 if (*addr
++ != ((random
>> 8) & 0xff))
78 static bool log_init(void)
82 rb
->lcd_getstringsize("A", NULL
, &h
);
83 max_line
= LCD_HEIGHT
/ h
;
85 rb
->lcd_clear_display();
88 rb
->create_numbered_filename(logfilename
, "/", "test_disk_log_", ".txt",
89 2 IF_CNFN_NUM_(, NULL
));
90 log_fd
= rb
->open(logfilename
, O_RDWR
|O_CREAT
|O_TRUNC
);
94 static void log_text(char *text
, bool advance
)
96 rb
->lcd_puts(0, line
, text
);
100 if (++line
>= max_line
)
102 rb
->fdprintf(log_fd
, "%s\n", text
);
106 static void log_close(void)
111 static bool test_fs(void)
113 unsigned char text_buf
[32];
114 int total
, current
, align
;
118 log_text("test_disk WRITE&VERIFY", true);
120 rb
->snprintf(text_buf
, sizeof(text_buf
), "CPU clock: %ld Hz",
122 log_text(text_buf
, true);
124 log_text("----------------------", true);
125 rb
->snprintf(text_buf
, sizeof text_buf
, "Data size: %dKB", (TEST_SIZE
>>10));
126 log_text(text_buf
, true);
128 fd
= rb
->creat(TEST_FILE
);
131 rb
->splash(HZ
, "creat() failed.");
135 frnd_buffer
= FRND_SEED
;
139 current
= rb
->rand() % (audiobuflen
- 4);
140 current
= MIN(current
, total
);
141 align
= rb
->rand() & 3;
142 rb
->snprintf(text_buf
, sizeof text_buf
, "Wrt %dKB, %dKB left",
143 current
>> 10, total
>> 10);
144 log_text(text_buf
, false);
146 mem_fill_frnd(audiobuf
+ align
, current
);
147 if (current
!= rb
->write(fd
, audiobuf
+ align
, current
))
149 rb
->splash(0, "write() failed.");
157 fd
= rb
->open(TEST_FILE
, O_RDONLY
);
160 rb
->splash(0, "open() failed.");
164 frnd_buffer
= FRND_SEED
;
168 current
= rb
->rand() % (audiobuflen
- 4);
169 current
= MIN(current
, total
);
170 align
= rb
->rand() & 3;
171 rb
->snprintf(text_buf
, sizeof text_buf
, "Cmp %dKB, %dKB left",
172 current
>> 10, total
>> 10);
173 log_text(text_buf
, false);
175 if (current
!= rb
->read(fd
, audiobuf
+ align
, current
))
177 rb
->splash(0, "read() failed.");
181 if (!mem_cmp_frnd(audiobuf
+ align
, current
))
183 log_text(text_buf
, true);
184 log_text("Compare error.", true);
191 log_text(text_buf
, true);
192 log_text("Test passed.", true);
196 rb
->remove(TEST_FILE
);
197 rb
->button_clear_queue();
198 rb
->button_get(true);
203 static bool file_speed(int chunksize
, bool align
)
205 unsigned char text_buf
[64];
210 if (chunksize
>= audiobuflen
)
213 log_text("--------------------", true);
215 /* File creation write speed */
216 fd
= rb
->creat(TEST_FILE
);
219 rb
->splash(HZ
, "creat() failed.");
222 time
= *rb
->current_tick
;
223 while (TIME_BEFORE(*rb
->current_tick
, time
+ TEST_TIME
*HZ
))
225 if (chunksize
!= rb
->write(fd
, audiobuf
+ (align
? 0 : 1), chunksize
))
227 rb
->splash(HZ
, "write() failed.");
231 filesize
+= chunksize
;
233 time
= *rb
->current_tick
- time
;
235 rb
->snprintf(text_buf
, sizeof text_buf
, "Create (%d,%c): %ld KB/s",
236 chunksize
, align
? 'A' : 'U', (25 * (filesize
>>8) / time
) );
237 log_text(text_buf
, true);
239 /* Existing file write speed */
240 fd
= rb
->open(TEST_FILE
, O_WRONLY
);
243 rb
->splash(0, "open() failed.");
246 time
= *rb
->current_tick
;
247 for (size
= filesize
; size
> 0; size
-= chunksize
)
249 if (chunksize
!= rb
->write(fd
, audiobuf
+ (align
? 0 : 1), chunksize
))
251 rb
->splash(0, "write() failed.");
256 time
= *rb
->current_tick
- time
;
258 rb
->snprintf(text_buf
, sizeof text_buf
, "Write (%d,%c): %ld KB/s",
259 chunksize
, align
? 'A' : 'U', (25 * (filesize
>>8) / time
) );
260 log_text(text_buf
, true);
262 /* File read speed */
263 fd
= rb
->open(TEST_FILE
, O_RDONLY
);
266 rb
->splash(0, "open() failed.");
269 time
= *rb
->current_tick
;
270 for (size
= filesize
; size
> 0; size
-= chunksize
)
272 if (chunksize
!= rb
->read(fd
, audiobuf
+ (align
? 0 : 1), chunksize
))
274 rb
->splash(0, "read() failed.");
279 time
= *rb
->current_tick
- time
;
281 rb
->snprintf(text_buf
, sizeof text_buf
, "Read (%d,%c): %ld KB/s",
282 chunksize
, align
? 'A' : 'U', (25 * (filesize
>>8) / time
) );
283 log_text(text_buf
, true);
284 rb
->remove(TEST_FILE
);
288 rb
->remove(TEST_FILE
);
292 static bool test_speed(void)
294 unsigned char text_buf
[64];
296 struct dirent
*entry
= NULL
;
301 rb
->memset(audiobuf
, 'T', audiobuflen
);
303 log_text("test_disk SPEED TEST", true);
305 rb
->snprintf(text_buf
, sizeof(text_buf
), "CPU clock: %ld Hz",
307 log_text(text_buf
, true);
309 log_text("--------------------", true);
311 /* File creation speed */
312 time
= *rb
->current_tick
+ TEST_TIME
*HZ
;
313 for (i
= 0; TIME_BEFORE(*rb
->current_tick
, time
); i
++)
315 rb
->snprintf(text_buf
, sizeof(text_buf
), TESTBASEDIR
"/%08x.tmp", i
);
316 fd
= rb
->creat(text_buf
);
320 rb
->splash(HZ
, "creat() failed.");
326 rb
->snprintf(text_buf
, sizeof(text_buf
), "Create: %d files/s",
327 last_file
/ TEST_TIME
);
328 log_text(text_buf
, true);
330 /* File open speed */
331 time
= *rb
->current_tick
+ TEST_TIME
*HZ
;
332 for (n
= 0, i
= 0; TIME_BEFORE(*rb
->current_tick
, time
); n
++, i
++)
336 rb
->snprintf(text_buf
, sizeof(text_buf
), TESTBASEDIR
"/%08x.tmp", i
);
337 fd
= rb
->open(text_buf
, O_RDONLY
);
340 rb
->splash(HZ
, "open() failed.");
345 rb
->snprintf(text_buf
, sizeof(text_buf
), "Open: %d files/s", n
/ TEST_TIME
);
346 log_text(text_buf
, true);
348 /* Directory scan speed */
349 time
= *rb
->current_tick
+ TEST_TIME
*HZ
;
350 for (n
= 0; TIME_BEFORE(*rb
->current_tick
, time
); n
++)
356 dir
= rb
->opendir(testbasedir
);
359 rb
->splash(HZ
, "opendir() failed.");
363 entry
= rb
->readdir(dir
);
366 rb
->snprintf(text_buf
, sizeof(text_buf
), "Dirscan: %d files/s", n
/ TEST_TIME
);
367 log_text(text_buf
, true);
369 /* File delete speed */
370 time
= *rb
->current_tick
;
371 for (i
= 0; i
< last_file
; i
++)
373 rb
->snprintf(text_buf
, sizeof(text_buf
), TESTBASEDIR
"/%08x.tmp", i
);
374 rb
->remove(text_buf
);
376 rb
->snprintf(text_buf
, sizeof(text_buf
), "Delete: %ld files/s",
377 last_file
* HZ
/ (*rb
->current_tick
- time
));
378 log_text(text_buf
, true);
380 if (file_speed(512, true)
381 && file_speed(512, false)
382 && file_speed(4096, true)
383 && file_speed(4096, false)
384 && file_speed(1048576, true))
385 file_speed(1048576, false);
387 log_text("DONE", false);
389 rb
->button_clear_queue();
390 rb
->button_get(true);
394 for (i
= 0; i
< last_file
; i
++)
396 rb
->snprintf(text_buf
, sizeof(text_buf
), TESTBASEDIR
"/%08x.tmp", i
);
397 rb
->remove(text_buf
);
399 log_text("DONE", false);
401 rb
->button_clear_queue();
402 rb
->button_get(true);
407 /* this is the plugin entry point */
408 enum plugin_status
plugin_start(const struct plugin_api
* api
, const void* parameter
)
410 static const struct menu_item items
[] = {
411 { "Disk speed", test_speed
},
412 { "Write & verify", test_fs
},
421 if ((dir
= rb
->opendir(testbasedir
)) == NULL
)
423 if (rb
->mkdir(testbasedir
) < 0)
425 rb
->splash(HZ
*2, "Can't create test directory.");
434 audiobuf
= rb
->plugin_get_audio_buffer((size_t *)&audiobuflen
);
435 /* align start and length to 32 bit */
436 align
= (-(int)audiobuf
) & 3;
438 audiobuflen
= (audiobuflen
- align
) & ~3;
440 rb
->srand(*rb
->current_tick
);
442 /* Turn off backlight timeout */
443 backlight_force_on(rb
); /* backlight control in lib/helper.c */
445 m
= menu_init(rb
, items
, sizeof(items
) / sizeof(*items
), NULL
,
450 /* Turn on backlight timeout (revert to settings) */
451 backlight_use_settings(rb
); /* backlight control in lib/helper.c */
453 rb
->rmdir(testbasedir
);