diff --git a/utils/nwztools/plattools/Makefile b/utils/nwztools/plattools/Makefile index f4e88cd778..067b4a7033 100644 --- a/utils/nwztools/plattools/Makefile +++ b/utils/nwztools/plattools/Makefile @@ -6,7 +6,7 @@ INCLUDES=-I. LIB_FILES=nwz_lib.c nwz_lib_devlist.c TOOL_FILES=dest_tool.c test_adc.c test_adc.c test_bl.c test_display.c \ - test_keys.c test_power.c test_ts.c + test_keys.c test_power.c test_ts.c test_fb.c ALL_ELF=$(patsubst %.c,%.elf,$(TOOL_FILES)) all_tools.elf dualboot.elf all: $(ALL_ELF) diff --git a/utils/nwztools/plattools/all_tools.c b/utils/nwztools/plattools/all_tools.c index f3ecb51c05..c93e26b36e 100644 --- a/utils/nwztools/plattools/all_tools.c +++ b/utils/nwztools/plattools/all_tools.c @@ -31,7 +31,8 @@ TOOL(test_display) \ TOOL(test_keys) \ TOOL(test_power) \ - TOOL(test_ts) + TOOL(test_ts) \ + TOOL(test_fb) \ typedef int (*nwz_tool_main_t)(int argc, char **argv); @@ -60,7 +61,7 @@ static void hello(void) { /* clear screen and display welcome message */ nwz_lcdmsg(true, 0, 0, "all_tools"); - nwz_lcdmsg(false, 0, 2, "BACK: quit"); + nwz_lcdmsg(false, 0, 1, "BACK: quit"); nwz_lcdmsg(false, 0, 2, "LEFT/RIGHT: change tool"); nwz_lcdmsg(false, 0, 3, "PLAY: run tool"); } diff --git a/utils/nwztools/plattools/dualboot.c b/utils/nwztools/plattools/dualboot.c index 965fabed72..a5d04fa4ed 100644 --- a/utils/nwztools/plattools/dualboot.c +++ b/utils/nwztools/plattools/dualboot.c @@ -29,7 +29,14 @@ * error, the OF is run. This seems like the safest option since the OF is * always there and might do magic things. */ -bool boot_rockbox(void) +enum boot_mode +{ + BOOT_ROCKBOX, + BOOT_TOOLS, + BOOT_OF +}; + +enum boot_mode get_boot_mode(void) { /* get time */ struct timeval deadline; @@ -37,7 +44,7 @@ bool boot_rockbox(void) { nwz_lcdmsg(false, 0, 2, "Cannot get time"); sleep(2); - return false; + return BOOT_OF; } /* open input device */ int input_fd = nwz_key_open(); @@ -45,11 +52,11 @@ bool boot_rockbox(void) { nwz_lcdmsg(false, 0, 2, "Cannot open input device"); sleep(2); - return false; + return BOOT_OF; } deadline.tv_sec += 5; /* wait for user action */ - bool boot_rb = false; + enum boot_mode mode = BOOT_OF; while(true) { /* get time */ @@ -69,7 +76,8 @@ bool boot_rockbox(void) int sec_left = deadline.tv_sec - cur_time.tv_sec; sec_left += (deadline.tv_usec - cur_time.tv_usec + 999999) / 1000000; /* round up */ nwz_lcdmsgf(false, 0, 2, "Booting OF in %d seconds ", sec_left); - nwz_lcdmsg(false, 0, 3, "Press BACK to boot RB"); + nwz_lcdmsg(false, 0, 3, "Press BACK to run tools"); + nwz_lcdmsg(false, 0, 3, "Press PLAY to boot RB"); /* wait for a key (1s) */ int ret = nwz_key_wait_event(input_fd, 1000000); if(ret != 1) @@ -77,14 +85,21 @@ bool boot_rockbox(void) struct input_event evt; if(nwz_key_read_event(input_fd, &evt) != 1) continue; - if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && !nwz_key_event_is_press(&evt)) + if(nwz_key_event_is_press(&evt)) + continue; + if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_PLAY) { - boot_rb = true; + mode = BOOT_ROCKBOX; + break; + } + else if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK) + { + mode = BOOT_TOOLS; break; } } nwz_key_close(input_fd); - return boot_rb; + return mode; } static char *boot_rb_argv[] = @@ -97,41 +112,40 @@ static char *boot_rb_argv[] = NULL }; -static void wait_key(void) -{ - int input_fd = nwz_key_open(); - /* display input state in a loop */ - while(1) - { - /* wait for event (10ms) */ - int ret = nwz_key_wait_event(input_fd, 10000); - if(ret != 1) - continue; - struct input_event evt; - if(nwz_key_read_event(input_fd, &evt) != 1) - continue; - if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && !nwz_key_event_is_press(&evt)) - break; - } - /* finish nicely */ - nwz_key_close(input_fd); -} - int NWZ_TOOL_MAIN(all_tools)(int argc, char **argv); int main(int argc, char **argv) { -#if 0 + /* make sure backlight is on and we are running the standard lcd mode */ + int fb_fd = nwz_fb_open(true); + if(fb_fd >= 0) + { + struct nwz_fb_brightness bl; + nwz_fb_get_brightness(fb_fd, &bl); + bl.level = NWZ_FB_BL_MAX_LEVEL; + nwz_fb_set_brightness(fb_fd, &bl); + nwz_fb_set_standard_mode(fb_fd); + nwz_fb_close(fb_fd); + } nwz_lcdmsg(true, 0, 0, "dualboot"); - if(boot_rockbox()) + /* run all tools menu */ + enum boot_mode mode = get_boot_mode(); + if(mode == BOOT_TOOLS) + { + /* run tools and then run OF */ + NWZ_TOOL_MAIN(all_tools)(argc, argv); + } + else if(mode == BOOT_ROCKBOX) { /* boot rockox */ nwz_lcdmsg(true, 0, 3, "Booting rockbox..."); + /* in the future, we will run rockbox here, for now we just print a + * message */ execvp("/usr/local/bin/lcdmsg", boot_rb_argv); + /* fallback to OF in case of failure */ nwz_lcdmsg(false, 0, 4, "failed."); sleep(5); } - /* if for some reason, running rockbox failed, then try to run the OF */ /* boot OF */ nwz_lcdmsg(true, 0, 3, "Booting OF..."); execvp("/usr/local/bin/SpiderApp.of", argv); @@ -140,42 +154,4 @@ int main(int argc, char **argv) /* if we reach this point, everything failed, so return an error so that * sysmgrd knows something is wrong */ return 1; -#elif 0 - const char *args_mount[] = {"mount", NULL}; - int status; - char *output = nwz_run_pipe("mount", args_mount, &status); - nwz_lcdmsgf(true, 0, 0, "%d\n%s", status, output); - free(output); - wait_key(); - const char *args_ls[] = {"ls", "/var", NULL}; - output = nwz_run_pipe("ls", args_ls, &status); - nwz_lcdmsgf(true, 0, 0, "%d\n%s", status, output); - free(output); - wait_key(); - const char *args_glogctl[] = {"glogctl", "flush", NULL}; - output = nwz_run_pipe("/usr/local/bin/glogctl", args_glogctl, &status); - nwz_lcdmsgf(true, 0, 0, "%d\n%s", status, output); - free(output); - wait_key(); - system("cp /var/GEMINILOG* /contents/"); - sync(); - execvp("/usr/local/bin/SpiderApp.of", argv); - return 0; -#else - /* make sure backlight is on */ - int fb_fd = nwz_fb_open(true); - if(fb_fd >= 0) - { - struct nwz_fb_brightness bl; - nwz_fb_get_brightness(fb_fd, &bl); - bl.level = NWZ_FB_BL_MAX_LEVEL; - nwz_fb_set_brightness(fb_fd, &bl); - nwz_fb_close(fb_fd); - } - /* run all tools menu */ - NWZ_TOOL_MAIN(all_tools)(argc, argv); - /* run OF */ - execvp("/usr/local/bin/SpiderApp.of", argv); - return 0; -#endif } diff --git a/utils/nwztools/plattools/nwz_fb.h b/utils/nwztools/plattools/nwz_fb.h index c857c5eb8a..9334b625c9 100644 --- a/utils/nwztools/plattools/nwz_fb.h +++ b/utils/nwztools/plattools/nwz_fb.h @@ -50,7 +50,90 @@ struct nwz_fb_brightness int period; /* period in ms between steps when changing: >=10 */ }; -#define NWZ_FB_SET_BRIGHTNESS _IOW(NWZ_FB_TYPE, 0x07, struct nwz_fb_brightness) -#define NWZ_FB_GET_BRIGHTNESS _IOR(NWZ_FB_TYPE, 0x08, struct nwz_fb_brightness) +/* FB extensions: + * + * Sony added relatively complicated extensions to the framebuffer. They allow + * better control of framebuffer refresh, double-buffering and mixing with DSP + * (v4l2). Each outout (LCD and TV) has two buffers, called page 0 and 1 (or A + * and B). Each page has its own attributes (image info) that control + * transparency, rotation and updates. At any point in time, the LCD is drawing + * a page and one can select the next page to draw. Unless an UPDATE ioctl() + * is made to change it, the next page will be the same as the one being drawn. + * + * FIXME I don't know what the timer is, it seems irrelevant for the LCD but + * the OF uses it for TV, maybe this controls the refresh rate of the TV output? + * + * On a side note, this information only applies to a subset of LCD types (the + * LCD type can be gathered from icx_sysinfo): + * - BB(0): AQUILA BB LCD + * - SW(1): SWAN or FIJI LCD + * - FC(2): FALCON OLED + * - GM(3): GUAM and ROTA LCD + * - FR(5): FURANO LCD ---> /!\ DOES NOT APPLY /!\ + * - SD(6): SPICA_D LCD + * - AQ(7): AQUILA LCD + */ + +/* Image infomation: + * SET_MODE will change the attributes of the requested page (ie .page) + * GET_MODE will return the attributes of the currently being displayed page + * UPDATE will do the same thing as SET_MODE but immediately refreshes the screen */ +struct nwz_fb_image_info +{ + int tc_enable; /* enable(1)/disable(0) transparent color */ + int t_color; /* transparent color (16bpp RGB565) */ + int alpha; /* alpha ratio (0 - 255) */ + int page; /* 2D framebuffer page(0/1) */ + int rot; /* LCD image rotation(0/1=180deg.) */ + int update; /* only use with NWZ_FB_UPDATE, ignored for others */ +}; + +/* update type */ +#define NWZ_FB_ONLY_2D_MODE 0 +#define NWZ_FB_DSP_AND_2D_MODE 1 + +/* frame buffer page infomation: when NWZ_FB_WAIT_REFREHS is called, the driver + * will wait until the next refresh or the timeout, whichever comes first. It + * will then fill this structure with the page status. */ +struct nwz_fb_status +{ + int timeout; /* waiting time for any frame ready (in units of 10 ms) */ + int page0; /* page 0 is out of display or waiting to be displayed */ + int page1; /* page 0 is out of display or waiting to be displayed */ +}; + +/* frame buffer page status */ +#define NWZ_FB_OUT_OF_DISPLAY 0 +#define NWZ_FB_WAITING_FOR_ON_DISPLAY 1 + +/* frame buffer update timer infomation (use I/F fb <-> 2D API) */ +struct nwz_fb_update_timer +{ + int timerflag; /* auto update off(0) / auto update on(1) */ + int timeout; /* timeout timer value (ms) */ +}; + +/* timer flags */ +#define NWZ_FB_TIMER_ON 1 +#define NWZ_FB_TIMER_OFF 0 + +/* default and minimum timeout value */ +#define NWZ_FB_DEFAULT_TIMEOUT 60 +#define NWZ_FB_MIN_TIMEOUT 33 + +/* mmap offsets for page 1 (page 0 is always at address 0) */ +#define NWZ_FB_LCD_PAGE_OFFSET 0x2f000 + +/* NOTE: I renamed those from Sony's header, because their original names were + * pure crap */ +/* FIXME: Sony uses _IOR for NWZ_FB_WAIT_REFRESH but it should be _IORW */ +#define NWZ_FB_WAIT_REFRESH _IORW(NWZ_FB_TYPE, 0x00, struct nwz_fb_status) +#define NWZ_FB_UPDATE _IOW(NWZ_FB_TYPE, 0x01, struct nwz_fb_image_info) +#define NWZ_FB_SET_MODE _IOW(NWZ_FB_TYPE, 0x02, struct nwz_fb_image_info) +#define NWZ_FB_GET_MODE _IOR(NWZ_FB_TYPE, 0x03, struct nwz_fb_image_info) +#define NWZ_FB_UPDATE_TIMER _IOR(NWZ_FB_TYPE, 0x04, struct nwz_fb_update_timer) +#define NWZ_FB_SET_BRIGHTNESS _IOW(NWZ_FB_TYPE, 0x07, struct nwz_fb_brightness) +#define NWZ_FB_GET_BRIGHTNESS _IOR(NWZ_FB_TYPE, 0x08, struct nwz_fb_brightness) + #endif /* __NWZ_FB_H__ */ diff --git a/utils/nwztools/plattools/nwz_lib.c b/utils/nwztools/plattools/nwz_lib.c index 087db8834a..43dc977d42 100644 --- a/utils/nwztools/plattools/nwz_lib.c +++ b/utils/nwztools/plattools/nwz_lib.c @@ -238,6 +238,27 @@ int nwz_fb_set_brightness(int fd, struct nwz_fb_brightness *bl) return 1; } +int nwz_fb_set_standard_mode(int fd) +{ + /* disable timer (apparently useless with LCD) */ + struct nwz_fb_update_timer update_timer; + update_timer.timerflag = NWZ_FB_TIMER_OFF; + update_timer.timeout = NWZ_FB_DEFAULT_TIMEOUT; + if(ioctl(fd, NWZ_FB_UPDATE_TIMER, &update_timer) < 0) + return -1; + /* set page 0 mode to no transparency and no rotation */ + struct nwz_fb_image_info mode_info; + mode_info.tc_enable = 0; + mode_info.t_color = 0; + mode_info.alpha = 0; + mode_info.rot = 0; + mode_info.page = 0; + mode_info.update = NWZ_FB_ONLY_2D_MODE; + if(ioctl(fd, NWZ_FB_UPDATE, &mode_info) < 0) + return -2; + return 0; +} + int nwz_adc_open(void) { return open(NWZ_ADC_DEV, O_RDONLY); diff --git a/utils/nwztools/plattools/nwz_lib.h b/utils/nwztools/plattools/nwz_lib.h index df0105a13d..9e7b8f16c2 100644 --- a/utils/nwztools/plattools/nwz_lib.h +++ b/utils/nwztools/plattools/nwz_lib.h @@ -85,6 +85,9 @@ void nwz_fb_close(int fb); int nwz_fb_get_brightness(int fd, struct nwz_fb_brightness *bl); /* set backlight brightness (return -1 on error, 1 on success) */ int nwz_fb_set_brightness(int fd, struct nwz_fb_brightness *bl); +/* setup framebuffer to its standard mode: LCD output, page 0, no transparency + * and no rotation, 2D only updates */ +int nwz_fb_set_standard_mode(int fd); /* open adc device */ int nwz_adc_open(void); diff --git a/utils/nwztools/plattools/test_display.c b/utils/nwztools/plattools/test_display.c index 1ebf40e813..0a8089eca9 100644 --- a/utils/nwztools/plattools/test_display.c +++ b/utils/nwztools/plattools/test_display.c @@ -25,7 +25,27 @@ int NWZ_TOOL_MAIN(test_display)(int argc, char **argv) { /* clear screen and display welcome message */ nwz_lcdmsg(true, 0, 0, "test_display"); - nwz_lcdmsg(false, 3, 10, "This program will stop in 5 seconds"); - sleep(5); + nwz_lcdmsg(false, 0, 1, "BACK: quit"); + /* wait for key */ + int input_fd = nwz_key_open(); + if(input_fd < 0) + { + sleep(2); + return 1; + } + while(1) + { + /* wait for event */ + int ret = nwz_key_wait_event(input_fd, 1000000); + if(ret != 1) + continue; + struct input_event evt; + if(nwz_key_read_event(input_fd, &evt) != 1) + continue; + /* handle quit */ + if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && !nwz_key_event_is_press(&evt)) + break; + } + nwz_key_close(input_fd); return 0; }