diff options
89 files changed, 4439 insertions, 2913 deletions
diff --git a/apps/bitmaps/bitmaps.make b/apps/bitmaps/bitmaps.make index a8165b9409..d39531a8b8 100644 --- a/apps/bitmaps/bitmaps.make +++ b/apps/bitmaps/bitmaps.make @@ -29,7 +29,8 @@ BMPOBJ = $(call full_path_subst,$(ROOTDIR)/%.bmp,$(BUILDDIR)/%.o,$(BMP)) BMPHFILES = $(BMPINCDIR)/usblogo.h $(BMPINCDIR)/remote_usblogo.h \ $(BMPINCDIR)/default_icons.h $(BMPINCDIR)/remote_default_icons.h \ - $(BMPINCDIR)/rockboxlogo.h $(BMPINCDIR)/remote_rockboxlogo.h + $(BMPINCDIR)/rockboxlogo.h $(BMPINCDIR)/remote_rockboxlogo.h \ + $(BMPINCDIR)/rockboxicon.h $(BMPINCDIR)/toolsicon.h $(BMPHFILES): $(BMPOBJ) diff --git a/apps/bitmaps/native/SOURCES b/apps/bitmaps/native/SOURCES index 88a571bdbd..dbd0f577ed 100644 --- a/apps/bitmaps/native/SOURCES +++ b/apps/bitmaps/native/SOURCES @@ -39,6 +39,12 @@ rockboxlogo.480x149x16.bmp rockboxlogo.640x198x16.bmp #endif +/* The Sony NWZ linux bootloader needs icons to display a menu */ +#if defined(BOOTLOADER) && defined(SONY_NWZ_LINUX) +rockboxicon.130x130x16.bmp +toolsicon.130x130x16.bmp +#endif + #ifndef BOOTLOADER /* We don't need these for the bootloader */ /* USB logo */ diff --git a/utils/nwztools/plattools/data/rockbox_icon.bmp b/apps/bitmaps/native/rockboxicon.130x130x16.bmp Binary files differindex 69e6792e7b..69e6792e7b 100644 --- a/utils/nwztools/plattools/data/rockbox_icon.bmp +++ b/apps/bitmaps/native/rockboxicon.130x130x16.bmp diff --git a/utils/nwztools/plattools/data/tools_icon.bmp b/apps/bitmaps/native/toolsicon.130x130x16.bmp Binary files differindex f9fccf0306..f9fccf0306 100644 --- a/utils/nwztools/plattools/data/tools_icon.bmp +++ b/apps/bitmaps/native/toolsicon.130x130x16.bmp diff --git a/apps/debug_menu.c b/apps/debug_menu.c index 08fc6e0da4..55454e0b94 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -2594,7 +2594,7 @@ static const struct { #endif { "Skin Engine RAM usage", dbg_skin_engine }, #endif -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SONY_NWZ_LINUX) { "View HW info", dbg_hw_info }, #endif #if (CONFIG_PLATFORM & PLATFORM_NATIVE) diff --git a/apps/keymaps/keymap-nwz.c b/apps/keymaps/keymap-nwz.c index 210841ba44..90a26e54f8 100644 --- a/apps/keymaps/keymap-nwz.c +++ b/apps/keymaps/keymap-nwz.c @@ -210,6 +210,7 @@ static const struct button_mapping button_context_colorchooser[] = { }; /* button_context_colorchooser */ static const struct button_mapping button_context_eq[] = { + { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), diff --git a/bootloader/SOURCES b/bootloader/SOURCES index a9c6aebd37..88b8aa03d2 100644 --- a/bootloader/SOURCES +++ b/bootloader/SOURCES @@ -71,6 +71,8 @@ main-pp.c show_logo.c #elif defined(MPIO_HD200) || defined(MPIO_HD300) mpio_hd200_hd300.c +#elif defined(SONY_NWZ_LINUX) +nwz_linux.c #elif defined(RK27_GENERIC) || defined(HM60X) || defined(HM801) \ || defined(MA9) || defined(MA9C) || defined(MA8) || defined(MA8C) \ || defined(IHIFI760) || defined(IHIFI960) diff --git a/bootloader/common.c b/bootloader/common.c index 46c0e3441f..4969d92b40 100644 --- a/bootloader/common.c +++ b/bootloader/common.c @@ -60,6 +60,7 @@ bool verbose = false; bool verbose = true; #endif +#if !(CONFIG_PLATFORM & PLATFORM_HOSTED) int line = 0; #ifdef HAVE_REMOTE_LCD int remote_line = 0; @@ -101,6 +102,7 @@ int printf(const char *format, ...) #endif return len; } +#endif void error(int errortype, int error, bool shutdown) { diff --git a/bootloader/common.h b/bootloader/common.h index d09ff1a5ab..56cbbb335a 100644 --- a/bootloader/common.h +++ b/bootloader/common.h @@ -30,8 +30,10 @@ extern bool verbose; #define EBOOTFILE -3 /* Functions common to all bootloaders */ +#if !(CONFIG_PLATFORM & PLATFORM_HOSTED) void reset_screen(void); int printf(const char *format, ...); +#endif void error(int errortype, int error, bool shutdown); int load_raw_firmware(unsigned char* buf, char* firmware, int buffer_size); #ifdef ROCKBOX_HAS_LOGF diff --git a/bootloader/nwz_linux.c b/bootloader/nwz_linux.c new file mode 100644 index 0000000000..7fe635bf76 --- /dev/null +++ b/bootloader/nwz_linux.c @@ -0,0 +1,524 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Amaury Pouly + * + * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing + * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach + * + * 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 "system.h" +#include "lcd.h" +#include "backlight.h" +#include "button-target.h" +#include "button.h" +#include "../kernel/kernel-internal.h" +#include "core_alloc.h" +#include "filesystem-app.h" +#include "nvp-nwz.h" +#include "power-nwz.h" +#include "lcd.h" +#include "font.h" +#include "power.h" +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/wait.h> +#include <stdarg.h> + +/* all images must have the following size */ +#define ICON_WIDTH 130 +#define ICON_HEIGHT 130 + +/* images */ +#include "bitmaps/rockboxicon.h" +#include "bitmaps/toolsicon.h" + +/* don't issue an error when parsing the file for dependencies */ +#if defined(BMPWIDTH_rockboxicon) && (BMPWIDTH_rockboxicon != ICON_WIDTH || \ + BMPHEIGHT_rockboxicon != ICON_HEIGHT) +#error rockboxicon has the wrong resolution +#endif +#if defined(BMPWIDTH_toolsicon) && (BMPWIDTH_toolsicon != ICON_WIDTH || \ + BMPHEIGHT_toolsicon != ICON_HEIGHT) +#error toolsicon has the wrong resolution +#endif + +/* buffer for Sony image, filled from NVP */ +unsigned short sonyicon[ICON_WIDTH * ICON_HEIGHT]; +const struct bitmap bm_sonyicon = +{ + .width = ICON_WIDTH, + .height = ICON_HEIGHT, + .format = FORMAT_NATIVE, + .data = (unsigned char*)sonyicon +}; + +/* return icon y position (x is always centered) */ +int get_icon_y(void) +{ + /* adjust so that this contains the Sony logo and produces a nice logo + * when used with rockbox */ + if(LCD_HEIGHT == 320) + return 70; + else if(LCD_HEIGHT == 400) + return 100; + else + return LCD_HEIGHT / 2 - ICON_HEIGHT + 30; /* guess, probably won't work */ +} + +/* Sony logo extraction */ +bool extract_sony_logo(void) +{ + /* load the entire image from the nvp */ + int bti_size = nwz_nvp_read(NWZ_NVP_BTI, NULL); + if(bti_size < 0) + return false; + unsigned short *bti = malloc(bti_size); + if(nwz_nvp_read(NWZ_NVP_BTI, bti) != bti_size) + return false; + /* compute the offset in the image of the logo itself */ + int x_off = (LCD_WIDTH - ICON_WIDTH) / 2; /* logo is centered horizontally */ + int y_off = get_icon_y(); + /* extract part of the image */ + for(int y = 0; y < ICON_HEIGHT; y++) + { + memcpy(sonyicon + ICON_WIDTH * y, + bti + LCD_WIDTH * (y + y_off) + x_off, ICON_WIDTH * sizeof(unsigned short)); + } + free(bti); + return true; +} + +/* Important Note: this bootloader is carefully written so that in case of + * error, the OF is run. This seems like the safest option since the OF is + * always there and might do magic things. */ + +enum boot_mode +{ + BOOT_ROCKBOX, + BOOT_TOOLS, + BOOT_OF, + BOOT_COUNT, + BOOT_USB, /* special */ + BOOT_STOP, /* power down/suspend */ +}; + +static void display_text_center(int y, const char *text) +{ + int width; + lcd_getstringsize(text, &width, NULL); + lcd_putsxy(LCD_WIDTH / 2 - width / 2, y, text); +} + +static void display_text_centerf(int y, const char *format, ...) +{ + char buf[1024]; + va_list ap; + va_start(ap, format); + + vsnprintf(buf, sizeof(buf), format, ap); + display_text_center(y, buf); +} + +/* get timeout before taking action if the user doesn't touch the device */ +int get_inactivity_tmo(void) +{ + if(button_hold()) + return 5 * HZ; /* Inactivity timeout when on hold */ + else + return 10 * HZ; /* Inactivity timeout when not on hold */ +} + +/* return action on idle timeout */ +enum boot_mode inactivity_action(enum boot_mode cur_selection) +{ + if(button_hold()) + return BOOT_STOP; /* power down/suspend */ + else + return cur_selection; /* return last choice */ +} + +/* we store the boot mode in a file in /tmp so we can reload it between 'boots' + * (since the mostly suspends instead of powering down) */ +enum boot_mode load_boot_mode(enum boot_mode mode) +{ + int fd = open("/tmp/rb_bl_mode.txt", O_RDONLY); + if(fd >= 0) + { + read(fd, &mode, sizeof(mode)); + close(fd); + } + return mode; +} + +void save_boot_mode(enum boot_mode mode) +{ + int fd = open("/tmp/rb_bl_mode.txt", O_RDWR | O_CREAT | O_TRUNC); + if(fd >= 0) + { + write(fd, &mode, sizeof(mode)); + close(fd); + } +} + +enum boot_mode get_boot_mode(void) +{ + /* load previous mode, or start with rockbox if none */ + enum boot_mode init_mode = load_boot_mode(BOOT_ROCKBOX); + /* wait for user action */ + enum boot_mode mode = init_mode; + int last_activity = current_tick; + bool hold_status = button_hold(); + while(true) + { + /* on usb detect, return to usb + * FIXME this is a hack, we need proper usb detection */ + if(power_input_status() & POWER_INPUT_USB_CHARGER) + { + /* save last choice */ + save_boot_mode(mode); + return BOOT_USB; + } + /* inactivity detection */ + int timeout = last_activity + get_inactivity_tmo(); + if(TIME_AFTER(current_tick, timeout)) + { + /* save last choice */ + save_boot_mode(mode); + return inactivity_action(mode); + } + /* redraw */ + lcd_clear_display(); + /* display top text */ + if(button_hold()) + { + lcd_set_foreground(LCD_RGBPACK(255, 0, 0)); + display_text_center(0, "ON HOLD!"); + } + else + { + lcd_set_foreground(LCD_RGBPACK(255, 201, 0)); + display_text_center(0, "SELECT PLAYER"); + } + lcd_set_foreground(LCD_RGBPACK(255, 201, 0)); + /* display icon */ + const struct bitmap *icon = (mode == BOOT_OF) ? &bm_sonyicon : + (mode == BOOT_ROCKBOX) ? &bm_rockboxicon : &bm_toolsicon; + lcd_bmp(icon, (LCD_WIDTH - ICON_WIDTH) / 2, get_icon_y()); + /* display bottom description */ + const char *desc = (mode == BOOT_OF) ? "SONY" : + (mode == BOOT_ROCKBOX) ? "ROCKBOX" : "TOOLS"; + display_text_center(get_icon_y() + ICON_HEIGHT + 30, desc); + /* display arrows */ + int arrow_width, arrow_height; + lcd_getstringsize("<", &arrow_width, &arrow_height); + int arrow_y = get_icon_y() + ICON_HEIGHT / 2 - arrow_height / 2; + lcd_putsxy(arrow_width / 2, arrow_y, "<"); + lcd_putsxy(LCD_WIDTH - 3 * arrow_width / 2, arrow_y, ">"); + + lcd_set_foreground(LCD_RGBPACK(0, 255, 0)); + display_text_centerf(LCD_HEIGHT - arrow_height * 3 / 2, "timeout in %d sec", + (timeout - current_tick + HZ - 1) / HZ); + + lcd_update(); + + /* wait for a key */ + int btn = button_get_w_tmo(HZ / 10); + /* record action, changing HOLD counts as action */ + if(btn & BUTTON_MAIN || hold_status != button_hold()) + last_activity = current_tick; + hold_status = button_hold(); + /* ignore release, allow repeat */ + if(btn & BUTTON_REL) + continue; + if(btn & BUTTON_REPEAT) + btn &= ~BUTTON_REPEAT; + /* play -> stop loop and return mode */ + if(btn == BUTTON_PLAY) + break; + /* left/right/up/down: change mode */ + if(btn == BUTTON_LEFT || btn == BUTTON_DOWN) + mode = (mode + BOOT_COUNT - 1) % BOOT_COUNT; + if(btn == BUTTON_RIGHT || btn == BUTTON_UP) + mode = (mode + 1) % BOOT_COUNT; + } + + /* save mode */ + save_boot_mode(mode); + return mode; +} + +void error_screen(const char *msg) +{ + lcd_clear_display(); + lcd_putsf(0, 0, msg); + lcd_update(); +} + +void create_sony_logo(void) +{ + for(int y = 0; y < ICON_HEIGHT; y++) + for(int x = 0; x < ICON_WIDTH; x++) + sonyicon[y * ICON_WIDTH + x] = 0xf81f; +} + +int choice_screen(const char *title, bool center, int nr_choices, const char *choices[]) +{ + int choice = 0; + int max_len = 0; + int h; + lcd_getstringsize("x", NULL, &h); + for(int i = 0; i < nr_choices; i++) + { + int len = strlen(choices[i]); + if(len > max_len) + max_len = len; + } + char *buf = malloc(max_len + 10); + int top_y = 2 * h; + int nr_lines = (LCD_HEIGHT - top_y) / h; + while(true) + { + /* make sure choice is visible */ + int offset = choice - nr_lines / 2; + if(offset < 0) + offset = 0; + lcd_clear_display(); + /* display top text */ + lcd_set_foreground(LCD_RGBPACK(255, 201, 0)); + display_text_center(0, title); + int line = 0; + for(int i = 0; i < nr_choices && line < nr_lines; i++) + { + if(i < offset) + continue; + if(i == choice) + lcd_set_foreground(LCD_RGBPACK(255, 0, 0)); + else + lcd_set_foreground(LCD_RGBPACK(255, 201, 0)); + sprintf(buf, "%s", choices[i]); + if(center) + display_text_center(top_y + h * line, buf); + else + lcd_putsxy(0, top_y + h * line, buf); + line++; + } + + lcd_update(); + + /* wait for a key */ + int btn = button_get_w_tmo(HZ / 10); + /* ignore release, allow repeat */ + if(btn & BUTTON_REL) + continue; + if(btn & BUTTON_REPEAT) + btn &= ~BUTTON_REPEAT; + /* play -> stop loop and return mode */ + if(btn == BUTTON_PLAY || btn == BUTTON_BACK) + { + free(buf); + return btn == BUTTON_PLAY ? choice : -1; + } + /* left/right/up/down: change mode */ + if(btn == BUTTON_LEFT || btn == BUTTON_UP) + choice = (choice + nr_choices - 1) % nr_choices; + if(btn == BUTTON_RIGHT || btn == BUTTON_DOWN) + choice = (choice + 1) % nr_choices; + } +} + +void run_file(const char *name) +{ + char *dirname = "/contents/"; + char *buf = malloc(strlen(dirname) + strlen(name) + 1); + sprintf(buf, "%s%s", dirname, name); + + lcd_clear_display(); + lcd_set_foreground(LCD_RGBPACK(255, 201, 0)); + lcd_putsf(0, 0, "Running %s", name); + lcd_update(); + + pid_t pid = fork(); + if(pid == 0) + { + execlp("sh", "sh", buf, NULL); + _exit(42); + } + int status; + waitpid(pid, &status, 0); + if(WIFEXITED(status)) + { + lcd_set_foreground(LCD_RGBPACK(255, 201, 0)); + lcd_putsf(0, 1, "program returned %d", WEXITSTATUS(status)); + } + else + { + lcd_set_foreground(LCD_RGBPACK(255, 0, 0)); + lcd_putsf(0, 1, "an error occured: %x", status); + } + lcd_set_foreground(LCD_RGBPACK(255, 0, 0)); + lcd_putsf(0, 3, "Press any key or wait"); + lcd_update(); + /* wait a small time */ + sleep(HZ); + /* ignore event */ + while(button_get(false) != 0) {} + /* wait for any key or timeout */ + button_get_w_tmo(4 * HZ); +} + +void run_script_menu(void) +{ + const char **entries = NULL; + int nr_entries = 0; + DIR *dir = opendir("/contents/"); + struct dirent *ent; + while((ent = readdir(dir))) + { + if(ent->d_type != DT_REG) + continue; + entries = realloc(entries, (nr_entries + 1) * sizeof(const char *)); + entries[nr_entries++] = strdup(ent->d_name); + } + closedir(dir); + int idx = choice_screen("RUN SCRIPT", false, nr_entries, entries); + if(idx >= 0) + run_file(entries[idx]); + for(int i = 0; i < nr_entries; i++) + free((char *)entries[i]); + free(entries); +} + +void tools_screen(void) +{ + const char *choices[] = {"Service menu", "Run script", "Restart", "Shutdown"}; + int choice = choice_screen("TOOLS MENU", true, 4, choices); + if(choice == 0) + { + /* run service menu */ + fflush(stdout); + execl("/usr/local/bin/mptapp", "mptapp", NULL); + error_screen("Cannot boot service menu"); + sleep(5 * HZ); + } + else if(choice == 1) + run_script_menu(); + else if(choice == 2) + nwz_power_restart(); + else if(choice == 3) + nwz_power_shutdown(); +} + +/* open log file */ +int open_log(void) +{ + /* open regular log file */ + int fd = open("/contents/rockbox.log", O_RDWR | O_CREAT | O_APPEND); + /* get its size */ + struct stat stat; + if(fstat(fd, &stat) != 0) + return fd; /* on error, don't do anything */ + /* if file is too large, rename it and start a new log file */ + if(stat.st_size < 1000000) + return fd; + close(fd); + /* move file */ + rename("/contents/rockbox.log", "/contents/rockbox.log.1"); + /* re-open the file, truncate in case the move was unsuccessful */ + return open("/contents/rockbox.log", O_RDWR | O_CREAT | O_APPEND | O_TRUNC); +} + +int main(int argc, char **argv) +{ + (void) argc; + (void) argv; + /* redirect stdout and stderr to have error messages logged somewhere on the + * user partition */ + int fd = open_log(); + if(fd >= 0) + { + dup2(fd, fileno(stdout)); + dup2(fd, fileno(stderr)); + close(fd); + } + system_init(); + core_allocator_init(); + kernel_init(); + paths_init(); + lcd_init(); + font_init(); + button_init(); + backlight_init(); + backlight_set_brightness(DEFAULT_BRIGHTNESS_SETTING); + /* try to load the extra font we install on the device */ + int font_id = font_load("/usr/local/share/rockbox/bootloader.fnt"); + if(font_id >= 0) + lcd_setfont(font_id); + /* extract logo */ + if(!extract_sony_logo()) + create_sony_logo(); + /* run all tools menu */ + while(true) + { + enum boot_mode mode = get_boot_mode(); + if(mode == BOOT_USB || mode == BOOT_OF) + { + fflush(stdout); + fflush(stderr); + close(fileno(stdout)); + close(fileno(stderr)); + /* for now the only way we have to trigger USB mode it to run the OF */ + /* boot OF */ + execvp("/usr/local/bin/SpiderApp.of", argv); + error_screen("Cannot boot OF"); + sleep(5 * HZ); + } + else if(mode == BOOT_TOOLS) + { + tools_screen(); + } + else if(mode == BOOT_ROCKBOX) + { + /* Rockbox expects /.rockbox to contain themes, rocks, etc, but we + * cannot easily create this symlink because the root filesystem is + * mounted read-only. Although we could remount it read-write temporarily, + * this is neededlessly complicated and we defer this job to the dualboot + * install script */ + fflush(stdout); + execl("/contents/.rockbox/rockbox.sony", "rockbox.sony", NULL); + printf("execvp failed: %s\n", strerror(errno)); + /* fallback to OF in case of failure */ + error_screen("Cannot boot Rockbox"); + sleep(5 * HZ); + } + else + { + /* FIXME doesn't seem to work */ + printf("suspend\n"); + nwz_power_suspend(); + } + } + /* if we reach this point, everything failed, so return an error so that + * sysmgrd knows something is wrong */ + return 1; +} diff --git a/firmware/SOURCES b/firmware/SOURCES index e31bc2a651..8ec17f7ec6 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -95,6 +95,23 @@ target/hosted/samsungypr/radio-ypr.c #endif #endif +#ifdef SONY_NWZ_LINUX +target/hosted/backtrace-glibc.c +target/hosted/kernel-unix.c +target/hosted/filesystem-unix.c +target/hosted/lc-unix.c +target/hosted/pcm-alsa.c +target/hosted/sonynwz/lcd-nwz.c +target/hosted/sonynwz/button-nwz.c +target/hosted/sonynwz/system-nwz.c +target/hosted/sonynwz/powermgmt-nwz.c +target/hosted/sonynwz/power-nwz.c +target/hosted/sonynwz/adc-nwz.c +target/hosted/sonynwz/debug-nwz.c +target/hosted/sonynwz/nvp-nwz.c +target/hosted/sonynwz/nwz-db.c +#endif + #if defined(SAMSUNG_YPR0) && !defined(SIMULATOR) drivers/adc-as3514.c #if (CONFIG_RTC == RTC_AS3514) @@ -447,6 +464,9 @@ target/hosted/pcm-alsa.c #elif defined(SAMSUNG_YPR1) && defined(HAVE_WM8978) drivers/audio/wm8978.c target/hosted/pcm-alsa.c +#elif defined(HAVE_NWZ_LINUX_CODEC) +drivers/audio/nwzlinux-codec.c +target/hosted/alsa-controls.c #elif defined(HAVE_SDL_AUDIO) drivers/audio/sdl.c #if CONFIG_CODEC == SWCODEC diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES index f16285e623..5a1310ed65 100644 --- a/firmware/asm/SOURCES +++ b/firmware/asm/SOURCES @@ -15,7 +15,7 @@ mempcpy.c defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \ defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \ defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \ - defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI)) && \ + defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX)) && \ !defined(SIMULATOR) #if LCD_DEPTH == 24 lcd-as-memframe-24bit.c diff --git a/firmware/drivers/audio/nwzlinux-codec.c b/firmware/drivers/audio/nwzlinux-codec.c new file mode 100644 index 0000000000..aa0c7efcf8 --- /dev/null +++ b/firmware/drivers/audio/nwzlinux-codec.c @@ -0,0 +1,385 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (c) 2016 Amaury Pouly + * + * 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 "logf.h" +#include "system.h" +#include "kernel.h" +#include "string.h" +#include "stdio.h" +#include "audio.h" +#include "sound.h" +#include "audiohw.h" +#include "cscodec.h" +#include "nwzlinux_codec.h" +#include "stdlib.h" +#include "panic.h" +#include <sys/ioctl.h> +#include "nwz_audio.h" +#include "pcm-alsa.h" +#include "alsa-controls.h" + +/* This driver handle the Sony linux audio drivers: despite using many differents + * codecs, it appears that they all share a common interface and common controls. */ + +/* This is the alsa mixer interface exposed by Sony: +numid=3,iface=MIXER,name='Capture Src Switch' + ; type=ENUMERATED,access=rw------,values=1,items=4 + ; Item #0 'None' + ; Item #1 'Line' + ; Item #2 'Fm' + ; Item #3 'Mic' + : values=0 +numid=2,iface=MIXER,name='Playback Src Switch' + ; type=ENUMERATED,access=rw------,values=1,items=7 + ; Item #0 'None' + ; Item #1 'Music' + ; Item #2 'Video' + ; Item #3 'Tv' + ; Item #4 'Fm' + ; Item #5 'Line' + ; Item #6 'Mic' + : values=1 +numid=1,iface=MIXER,name='Playback Volume' + ; type=INTEGER,access=rw------,values=2,min=0,max=100,step=1 + : values=5,5 +numid=7,iface=MIXER,name='CODEC Acoustic Switch' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=8,iface=MIXER,name='CODEC Cue/Rev Switch' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=9,iface=MIXER,name='CODEC Fade In Switch' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=6,iface=MIXER,name='CODEC Mute Switch' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=5,iface=MIXER,name='CODEC Power Switch' + ; type=BOOLEAN,access=rw------,values=1 + : values=on +numid=10,iface=MIXER,name='CODEC Stanby Switch' + ; type=BOOLEAN,access=rw------,values=1 + : values=off +numid=4,iface=MIXER,name='Output Switch' + ; type=ENUMERATED,access=rw------,values=1,items=4 + ; Item #0 'Headphone' + ; Item #1 'LineVariable' + ; Item #2 'LineFixed' + ; Item #3 'Speaker' + : values=0 +*/ + +/* List of various codecs used by Sony */ +enum nwz_codec_t +{ + NWZ_CS42L56, + NWZ_R2A15602LG_D, + NWZ_CS47L01_A, + NWZ_CS47L01_D, + NWZ_CXD3774GF_D, + NWZ_UNK_CODEC, +}; + +#define NWZ_LEVEL_MUTE -1000 +/* Description of the volume curve implemented by the kernel driver */ +struct nwz_vol_curve_t +{ + int count; /* number of levels */ + int level[]; /* levels in tenth-dB, level[0] is always mute */ +}; + +/* file descriptor of the icx_noican device */ +static int fd_noican; +/* file descriptor of the hardware sound device */ +static int fd_hw; +/* Codec */ +static enum nwz_codec_t nwz_codec; + +static enum nwz_codec_t find_codec(void) +{ + if(nwz_is_kernel_module_loaded("cs42L56_d")) + return NWZ_CS42L56; + if(nwz_is_kernel_module_loaded("r2A15602LG_d")) + return NWZ_R2A15602LG_D; + if(nwz_is_kernel_module_loaded("cs47L01_d")) + return NWZ_CS47L01_D; + if(nwz_is_kernel_module_loaded("cs47L01_a")) + return NWZ_CS47L01_A; + if(nwz_is_kernel_module_loaded("cxd3774gf_d")) + return NWZ_CXD3774GF_D; + return NWZ_UNK_CODEC; +} + +const char *nwz_get_codec_name(void) +{ + switch(nwz_codec) + { + case NWZ_CS42L56: return "cs42L56_d"; + case NWZ_R2A15602LG_D: return "r2A15602LG_d"; + case NWZ_CS47L01_D: return "cs47L01_d"; + case NWZ_CS47L01_A: return "cs47L01_a"; + case NWZ_CXD3774GF_D: return "cxd3774gf_d"; + default: return "Unknown"; + } +} + +static struct nwz_vol_curve_t cxd3774gf_vol_curve = +{ + .count = 31, + /* Most Sonys seem to follow the convention of 3dB/step then 2dB/step then 1dB/step */ + .level = {NWZ_LEVEL_MUTE, + -550, -520, -490, -460, -430, -400, -370, -340, -310, -280, -250, /* 3dB/step */ + -230, -210, -190, -170, -150, -130, -110, -90, /* 2dB/step */ + -80, -70, -60, -50, -40, -30, -20, -10, 0, /* 1dB/step */ + 15, 35, /* 1.5dB then 2dB */ + } +}; + +struct nwz_vol_curve_t *nwz_get_codec_vol_curve(void) +{ + switch(nwz_codec) + { + case NWZ_CS47L01_A: + case NWZ_CS47L01_D: + /* there are 32 levels but the last two are the same so in fact it + * is the same curve as the cxd3774gf_d */ + case NWZ_CXD3774GF_D: + return &cxd3774gf_vol_curve; + default: + /* return the safest curve (only 31 levels) */ + return &cxd3774gf_vol_curve; + } +} + +static void noican_init(void) +{ + fd_noican = open(NWZ_NC_DEV, O_RDWR); + /* some targets don't have noise cancelling so silently fail */ +} + +static void noican_close(void) +{ + if(fd_noican >= 0) + close(fd_noican); +} + +/* Set NC switch */ +static void noican_set_switch(int sw) +{ + if(ioctl(fd_noican, NWZ_NC_SET_SWITCH, &sw) < 0) + panicf("ioctl(NWZ_NC_SET_SWITCH) failed"); +} + +/* Get NC switch */ +static int noican_get_switch(void) +{ + int val; + if(ioctl(fd_noican, NWZ_NC_GET_SWITCH, &val) < 0) + panicf("ioctl(NWZ_NC_GET_SWITCH) failed"); + return val; +} + +/* Get HP status */ +static int noican_get_hp_status(void) +{ + int val; + if(ioctl(fd_noican, NWZ_NC_GET_HP_STATUS, &val) < 0) + panicf("ioctl(NWZ_NC_GET_HP_STATUS) failed"); + return val; +} + +/* Set HP type */ +static void noican_set_hp_type(int type) +{ + if(ioctl(fd_noican, NWZ_NC_SET_HP_TYPE, &type) < 0) + panicf("ioctl(NWZ_NC_SET_HP_TYPE) failed"); +} + +/* Get HP type */ +static int noican_get_hp_type(void) +{ + int val; + if(ioctl(fd_noican, NWZ_NC_GET_HP_TYPE, &val) < 0) + panicf("ioctl(NWZ_NC_GET_HP_TYPE) failed"); + return val; +} + + +/* Set gain */ +static void noican_set_gain(int gain) +{ + if(ioctl(fd_noican, NWZ_NC_SET_GAIN, &gain) < 0) + panicf("ioctl(NWZ_NC_SET_GAIN) failed"); +} + +/* Get gain */ +static int noican_get_gain(void) +{ + int val; + if(ioctl(fd_noican, NWZ_NC_GET_GAIN, &val) < 0) + panicf("ioctl(NWZ_NC_GET_GAIN) failed"); + return val; +} + +/* Set filter */ +static void noican_set_filter(int filter) +{ + if(ioctl(fd_noican, NWZ_NC_SET_FILTER, &filter) < 0) + panicf("ioctl(NWZ_NC_SET_FILTER) failed"); +} + +/* Get filter */ +static int noican_get_filter(void) +{ + int val; + if(ioctl(fd_noican, NWZ_NC_GET_FILTER, &val) < 0) + panicf("ioctl(NWZ_NC_GET_FILTER) failed"); + return val; +} + +static void hw_open(void) +{ + fd_hw = open("/dev/snd/hwC0D0", O_RDWR); + if(fd_hw < 0) + panicf("Cannot open '/dev/snd/hwC0D0'"); +} + +static void hw_close(void) +{ + close(fd_hw); +} + +void audiohw_preinit(void) +{ + alsa_controls_init(); + /* turn on codec */ + alsa_controls_set_bool("CODEC Power Switch", true); + /* mute */ + alsa_controls_set_bool("CODEC Mute Switch", true); + /* Acoustic and Cue/Rev control how the volume curve, but it is not clear + * what the intention of these modes are and the OF does not seem to use + * them by default */ + alsa_controls_set_bool("CODEC Acoustic Switch", false); + alsa_controls_set_bool("CODEC Cue/Rev Switch", false); + /* not sure exactly what it means */ + alsa_controls_set_enum("Playback Src Switch", "Music"); + /* use headphone output */ + alsa_controls_set_enum("Output Switch", "Headphone"); + /* unmute */ + alsa_controls_set_bool("CODEC Mute Switch", false); + + /* init noican */ + noican_init(); + if(fd_noican >= 0) + { + /* dump configuration, for debug purposes */ + printf("nc hp status: %d\n", noican_get_hp_status()); + printf("nc type: %d\n", noican_get_hp_type()); + printf("nc switch: %d\n", noican_get_switch()); + printf("nc gain: %d\n", noican_get_gain()); + printf("nc filter: %d\n", noican_get_filter()); + /* make sure we start in a clean state */ + noican_set_switch(NWZ_NC_SWITCH_OFF); + noican_set_hp_type(NC_HP_TYPE_DEFAULT); + noican_set_filter(NWZ_NC_FILTER_INDEX_0); + noican_set_gain(NWZ_NC_GAIN_CENTER); + } + + /* init hw */ + hw_open(); + nwz_codec = find_codec(); + printf("Codec: %s\n", nwz_get_codec_name()); +} + +void audiohw_postinit(void) +{ +} + +/* volume must be driver unit */ +static void nwz_set_driver_vol(int vol) +{ + long vols[2]; + /* the driver expects percent, convert from centibel in range 0...x */ + vols[0] = vols[1] = vol; + /* on some recent players like A10, Sony decided to merge left/right volume + * into one, thus we need to make sure we write the correct number of values */ + int vol_cnt; + alsa_controls_get_info("Playback Volume", &vol_cnt); + alsa_controls_set_ints("Playback Volume", vol_cnt, vols); +} + +/* volume is in tenth-dB */ +void audiohw_set_volume(int vol_l, int vol_r) +{ + /* FIXME at the moment we don't support balance and just average left and right. + * But this could be implemented using pcm alsa digital volume */ + + /* the Sony drivers expect vol_l = vol_r */ + int vol = (vol_l + vol_r) / 2; + printf("request volume %d dB\n", vol / 10); + struct nwz_vol_curve_t *curve = nwz_get_codec_vol_curve(); + /* min/max for pcm volume */ + int min_pcm = -430; + int max_pcm = 0; + /* On some codecs (like cs47L01), Sony clear overdrives the DAC which produces + * massive clipping at any level (since they fix the DAC volume at around +6dB + * and then adjust HP volume in negative at the top of range !!). The only + * solution around this problem is to use the digital volume first so that + * very quickly the digital volume compensate for the DAC overdrive and we + * avoid clipping. */ + int sony_clip_level = -80; /* any volume above this will cause massive clipping the DAC */ + + /* to avoid the clipping problem, virtually decrease requested volume by the + * clipping threshold, so that we will compensate in digital later by + * at least this amount if possibly */ + vol -= sony_clip_level; + + int drv_vol = curve->count - 1; + /* pick driver level just above request volume */ + while(drv_vol > 0 && curve->level[drv_vol - 1] >= vol) + drv_vol--; + /* now remove the artifical volume change */ + vol += sony_clip_level; + /* now adjust digital volume */ + vol -= curve->level[drv_vol]; + if(vol < min_pcm) + { + vol = min_pcm; /* digital cannot do <43dB */ + drv_vol = 0; /* mute */ + } + else if(vol > max_pcm) + vol = max_pcm; /* digital cannot do >0dB */ + printf(" set driver volume %d (%d dB)\n", drv_vol, curve->level[drv_vol] / 10); + nwz_set_driver_vol(drv_vol); + printf(" set digital volume %d dB\n", vol / 10); + pcm_alsa_set_digital_volume(vol / 10); +} + +void audiohw_close(void) +{ + hw_close(); + alsa_controls_close(); + noican_close(); +} + +void audiohw_set_frequency(int fsel) +{ + (void) fsel; +} diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index e6bb8dc3fc..6026a3b4bd 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -207,6 +207,8 @@ struct sound_settings_info #include "df1704.h" #elif defined(HAVE_PCM1792_CODEC) #include "pcm1792.h" +#elif defined(HAVE_NWZ_LINUX_CODEC) +#include "nwzlinux_codec.h" #elif (CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO\ | PLATFORM_PANDORA | PLATFORM_SDL)) #include "hosted_codec.h" diff --git a/firmware/export/backtrace.h b/firmware/export/backtrace.h new file mode 100644 index 0000000000..283e293b2a --- /dev/null +++ b/firmware/export/backtrace.h @@ -0,0 +1,36 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2017 by Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __ROCKBOX_BACKTRACE_H__ +#define __ROCKBOX_BACKTRACE_H__ + +#include "config.h" +#ifdef BACKTRACE_UNWARMINDER +#include "backtrace-unwarminder.h" +#endif + +/* Print a backtrace using lcd_* functions, starting at the given line and updating + * the line number. On targets that support it (typically native targets), the + * backtrace will start at the given value of PC and using the stack frame given + * by PC. On hosted targets, it will typically ignore those values and backtrace + * from the caller */ +void rb_backtrace(int pcAddr, int spAddr, unsigned *line); + +#endif /* __ROCKBOX_BACKTRACE_H__ */ diff --git a/firmware/export/config.h b/firmware/export/config.h index 4209955c2d..aa11766e63 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -277,6 +277,7 @@ #define LCD_IHIFI 60 /* as used by IHIFI 760/960 */ #define LCD_CREATIVEZENXFISTYLE 61 /* as used by Creative Zen X-Fi Style */ #define LCD_SAMSUNGYPR1 62 /* as used by Samsung YP-R1 */ +#define LCD_NWZ_LINUX 63 /* as used in the Linux-based NWZ series */ /* LCD_PIXELFORMAT */ #define HORIZONTAL_PACKING 1 @@ -581,6 +582,16 @@ Lyre prototype 1 */ #include "config/ibassodx50.h" #elif defined(DX90) #include "config/ibassodx90.h" +#elif defined(SONY_NWZE460) +#include "config/sonynwze460.h" +#elif defined(SONY_NWZE450) +#include "config/sonynwze450.h" +#elif defined(SONY_NWZE580) +#include "config/sonynwze580.h" +#elif defined(SONY_NWZA10) +#include "config/sonynwza10.h" +#elif defined(SONY_NWZE470) +#include "config/sonynwze470.h" #else /* no known platform */ #endif diff --git a/firmware/export/config/sonynwza10.h b/firmware/export/config/sonynwza10.h new file mode 100644 index 0000000000..a0650cf22d --- /dev/null +++ b/firmware/export/config/sonynwza10.h @@ -0,0 +1,16 @@ +/* + * This config file is for the Sony NW-A10 series + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 104 + +#define MODEL_NAME "Sony NWZ-A10 Series" + +/* LCD dimensions */ +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +/* sqrt(240^2 + 320^2) / 2 = 200 */ +#define LCD_DPI 200 + +#include "sonynwzlinux.h" diff --git a/firmware/export/config/sonynwze450.h b/firmware/export/config/sonynwze450.h new file mode 100644 index 0000000000..6b9955072d --- /dev/null +++ b/firmware/export/config/sonynwze450.h @@ -0,0 +1,16 @@ +/* + * This config file is for the Sony NWZ-E450 series + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 100 + +#define MODEL_NAME "Sony NWZ-E450 Series" + +/* LCD dimensions */ +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +/* sqrt(240^2 + 320^2) / 2 = 200 */ +#define LCD_DPI 200 + +#include "sonynwzlinux.h" diff --git a/firmware/export/config/sonynwze460.h b/firmware/export/config/sonynwze460.h new file mode 100644 index 0000000000..4f2bc8c698 --- /dev/null +++ b/firmware/export/config/sonynwze460.h @@ -0,0 +1,16 @@ +/* + * This config file is for the Sony NWZ-E460 series + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 101 + +#define MODEL_NAME "Sony NWZ-E460 Series" + +/* LCD dimensions */ +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +/* sqrt(240^2 + 320^2) / 2 = 200 */ +#define LCD_DPI 200 + +#include "sonynwzlinux.h" diff --git a/firmware/export/config/sonynwze470.h b/firmware/export/config/sonynwze470.h new file mode 100644 index 0000000000..23fe74a016 --- /dev/null +++ b/firmware/export/config/sonynwze470.h @@ -0,0 +1,16 @@ +/* + * This config file is for the Sony NWZ-E470 series + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 103 + +#define MODEL_NAME "Sony NWZ-E470 Series" + +/* LCD dimensions */ +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +/* sqrt(240^2 + 320^2) / 2 = 200 */ +#define LCD_DPI 200 + +#include "sonynwzlinux.h" diff --git a/firmware/export/config/sonynwze580.h b/firmware/export/config/sonynwze580.h new file mode 100644 index 0000000000..f692e6a22e --- /dev/null +++ b/firmware/export/config/sonynwze580.h @@ -0,0 +1,16 @@ +/* + * This config file is for the Sony NWZ-E580 series + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 102 + +#define MODEL_NAME "Sony NWZ-E580 Series" + +/* LCD dimensions */ +#define LCD_WIDTH 240 +#define LCD_HEIGHT 320 +/* sqrt(240^2 + 320^2) / 2 = 200 */ +#define LCD_DPI 200 + +#include "sonynwzlinux.h" diff --git a/firmware/export/config/sonynwzlinux.h b/firmware/export/config/sonynwzlinux.h new file mode 100644 index 0000000000..4c66651e6b --- /dev/null +++ b/firmware/export/config/sonynwzlinux.h @@ -0,0 +1,105 @@ +/* + * This config file is for the Sony NWZ Linux based targets + */ + +#define CONFIG_PLATFORM (PLATFORM_HOSTED) + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR + +/* Define this if the LCD can shut down */ +#define HAVE_LCD_SHUTDOWN + +/* define this if you want album art for this target */ +#define HAVE_ALBUMART + +/* define this to enable bitmap scaling */ +#define HAVE_BMP_SCALING + +/* define this to enable JPEG decoding */ +#define HAVE_JPEG + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +#define LCD_DEPTH 16 +/* Check that but should not matter */ +#define LCD_PIXELFORMAT RGB565 + +#define HAVE_BACKLIGHT +#define HAVE_BACKLIGHT_BRIGHTNESS + +/* Main LCD backlight brightness range and defaults: the backlight driver only + * has levels from 0 to 5. But 0 is off so start at 1. The driver has configurable + * periods for fade in/out but we can't easily export that to Rockbox */ +#define MIN_BRIGHTNESS_SETTING 1 +#define MAX_BRIGHTNESS_SETTING 5 +#define DEFAULT_BRIGHTNESS_SETTING 4 + +/* Which backlight fading type? */ +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING + +/* define this if you have a real-time clock */ +#define CONFIG_RTC 0 + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x80000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x100000 + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* KeyPad configuration for plugins */ +#define CONFIG_KEYPAD SONY_NWZ_PAD +#define HAS_BUTTON_HOLD + +/* We have usb power and can detect usb but it is handled by Linux */ +#define HAVE_USB_POWER +#define USB_NONE + +#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE + +/* Linux controlls charging, we can monitor */ +#define CONFIG_CHARGING CHARGING_MONITOR + +/* define this if the hardware can be powered off while charging */ +#define HAVE_POWEROFF_WHILE_CHARGING + +/* same dimensions as gigabeats */ +#define CONFIG_LCD LCD_NWZ_LINUX + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* Define this to the CPU frequency */ +#define CPU_FREQ 532000000 + +/* No special storage */ +#define CONFIG_STORAGE STORAGE_HOSTFS +#define HAVE_STORAGE_FLUSH + +/* Battery */ +#define BATTERY_TYPES_COUNT 1 + +/* Audio codec */ +#define HAVE_NWZ_LINUX_CODEC + +/* special define to be use in various places */ +#define SONY_NWZ_LINUX + +/* Battery */ +#define BATTERY_CAPACITY_DEFAULT 600 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 600 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 600 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 0 /* capacity increment */ diff --git a/firmware/export/nwzlinux_codec.h b/firmware/export/nwzlinux_codec.h new file mode 100644 index 0000000000..fbd424a22e --- /dev/null +++ b/firmware/export/nwzlinux_codec.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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. + * + ****************************************************************************/ + +#ifndef __NWZLINUX_CODEC_H__ +#define __NWZLINUX_CODEC_H__ + +#define AUDIOHW_CAPS 0 + +/* Ranges from -100dB to 4dB */ +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -100, 4, -10) + +#endif /* __NWZLINUX_CODEC_H__ */ diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index fdbf081329..8dc9b3a7f9 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h @@ -40,10 +40,13 @@ #define ROCKBOX_DIR_LEN (sizeof(ROCKBOX_DIR)-1) #endif /* def __PCTOOL__ */ -#if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) +#if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \ + defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) #if defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) #define HOME_DIR "/mnt/media0" +#elif defined(SONY_NWZ_LINUX) +#define HOME_DIR "/contents" #elif defined(DX50) || defined(DX90) /* Where to put save files like recordings, playlists, screen dumps ...*/ #define HOME_DIR "/mnt/sdcard" @@ -83,7 +86,8 @@ #define PLUGIN_DEMOS_DIR PLUGIN_DIR "/demos" #define VIEWERS_DIR PLUGIN_DIR "/viewers" -#if defined(APPLICATION) && !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90)) +#if defined(APPLICATION) && !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \ + defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX)) #define PLUGIN_DATA_DIR ROCKBOX_DIR "/rocks.data" #define PLUGIN_GAMES_DATA_DIR PLUGIN_DATA_DIR #define PLUGIN_APPS_DATA_DIR PLUGIN_DATA_DIR diff --git a/firmware/export/system.h b/firmware/export/system.h index 62da252e80..911c9edf4b 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -336,7 +336,7 @@ static inline void cpu_boost_unlock(void) #ifndef SIMULATOR bool dbg_ports(void); #endif -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SONY_NWZ_LINUX) bool dbg_hw_info(void); #endif diff --git a/firmware/font.c b/firmware/font.c index 617a8a33e3..3208125a6a 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -85,7 +85,7 @@ /* compiled-in font */ extern struct font sysfont; -#ifndef BOOTLOADER +#if !defined(BOOTLOADER) || defined(SONY_NWZ_LINUX) struct buflib_alloc_data { struct font font; /* must be the first member! */ diff --git a/firmware/panic.c b/firmware/panic.c index a35291636d..7e7e43d609 100644 --- a/firmware/panic.c +++ b/firmware/panic.c @@ -115,7 +115,7 @@ void panicf( const char *fmt, ...) } #if defined(CPU_ARM) - backtrace(pc, sp, &y); + rb_backtrace(pc, sp, &y); #endif #ifdef ROCKBOX_HAS_LOGF logf_panic_dump(&y); diff --git a/firmware/target/arm/system-arm.c b/firmware/target/arm/system-arm.c index e687e1d82b..74df5ed277 100644 --- a/firmware/target/arm/system-arm.c +++ b/firmware/target/arm/system-arm.c @@ -148,7 +148,7 @@ void NORETURN_ATTR UIE(unsigned int pc, unsigned int num) if (!triggered) { triggered = true; - backtrace(pc, __get_sp(), &line); + rb_backtrace(pc, __get_sp(), &line); } lcd_update(); diff --git a/firmware/target/hosted/alsa-controls.c b/firmware/target/hosted/alsa-controls.c new file mode 100644 index 0000000000..9747fbefa9 --- /dev/null +++ b/firmware/target/hosted/alsa-controls.c @@ -0,0 +1,181 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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 "alsa-controls.h" +#include "panic.h" +#include <stdlib.h> + +/* alsa control handle, we keep it open at all times */ +static snd_ctl_t *alsa_ctl; +/* list of all controls, we allocate and fill it once, so we can easily lookup */ +static snd_ctl_elem_list_t *alsa_ctl_list; + +void alsa_controls_init(void) +{ + snd_ctl_elem_info_t *info; + /* allocate list on heap because it is used it is used in other functions */ + snd_ctl_elem_list_malloc(&alsa_ctl_list); + /* allocate info on stack so there is no need to free them */ + snd_ctl_elem_info_alloca(&info); + /* there is only one card and "default" always works */ + if(snd_ctl_open(&alsa_ctl, "default", 0) < 0) + panicf("Cannot open ctl\n"); + /* ALSA is braindead: first "get" the list -> only retrieve count */ + if(snd_ctl_elem_list(alsa_ctl, alsa_ctl_list) < 0) + panicf("Cannot get element list\n"); + /* now we can allocate the list since the know the size */ + int count = snd_ctl_elem_list_get_count(alsa_ctl_list); + if(snd_ctl_elem_list_alloc_space(alsa_ctl_list, count) < 0) + panicf("Cannot allocate space for element list\n"); + /* ... and get the list again! */ + if(snd_ctl_elem_list(alsa_ctl, alsa_ctl_list) < 0) + panicf("Cannot get element list\n"); +} + +void alsa_controls_close(void) +{ + snd_ctl_close(alsa_ctl); +} + +/* find a control element ID by name, return false of not found, the id needs + * to be allocated */ +bool alsa_controls_find(snd_ctl_elem_id_t *id, const char *name) +{ + /* ALSA identifies controls by "id"s, it almost makes sense, except ids + * are a horrible opaque structure */ + int count = snd_ctl_elem_list_get_count(alsa_ctl_list); + /* enumerate controls */ + for(int i = 0; i < count; i++) + { + snd_ctl_elem_list_get_id(alsa_ctl_list, i, id); + + if(strcmp(snd_ctl_elem_id_get_name(id), name) == 0) + return true; + } + /* not found */ + return false; +} + +/* find a control element enum index by name, return -1 if not found */ +int alsa_controls_find_enum(const char *name, const char *enum_name) +{ + snd_ctl_elem_id_t *id; + snd_ctl_elem_info_t *info; + /* allocate things on stack to speedup */ + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_info_alloca(&info); + /* find control */ + if(!alsa_controls_find(id, name)) + panicf("Cannot find control '%s'", name); + snd_ctl_elem_info_set_id(info, id); + if(snd_ctl_elem_info(alsa_ctl, info) < 0) + panicf("Cannot get control '%s' info", name); + /* list items */ + unsigned count = snd_ctl_elem_info_get_items(info); + for(unsigned i = 0; i < count; i++) + { + snd_ctl_elem_info_set_item(info, i); + if(snd_ctl_elem_info(alsa_ctl, info) < 0) + panicf("Cannot get control '%s' info for item %u", name, i); + if(strcmp(snd_ctl_elem_info_get_item_name(info), enum_name) == 0) + return i; + } + return -1; +} + +/* set a control, potentially supports several values */ +void alsa_controls_set(const char *name, snd_ctl_elem_type_t type, + unsigned nr_values, long *val) +{ + snd_ctl_elem_id_t *id; + snd_ctl_elem_info_t *info; + snd_ctl_elem_value_t *value; + /* allocate things on stack to speedup */ + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_info_alloca(&info); + snd_ctl_elem_value_alloca(&value); + /* find control */ + if(!alsa_controls_find(id, name)) + panicf("Cannot find control '%s'", name); + /* check the type of the control */ + snd_ctl_elem_info_set_id(info, id); + if(snd_ctl_elem_info(alsa_ctl, info) < 0) + panicf("Cannot get control '%s' info", name); + if(snd_ctl_elem_info_get_type(info) != type) + panicf("Control '%s' has wrong type (got %d, expected %d", name, + snd_ctl_elem_info_get_type(info), type); + if(snd_ctl_elem_info_get_count(info) != nr_values) + panicf("Control '%s' has wrong count (got %u, expected %u)", + name, snd_ctl_elem_info_get_count(info), nr_values); + /* set value */ + snd_ctl_elem_value_set_id(value, id); + for(unsigned i = 0; i < nr_values; i++) + { + /* ALSA is braindead: there are "typed" setters but they all take long anyway */ + if(type == SND_CTL_ELEM_TYPE_BOOLEAN) + snd_ctl_elem_value_set_boolean(value, i, val[i]); + else if(type == SND_CTL_ELEM_TYPE_INTEGER) + snd_ctl_elem_value_set_integer(value, i, val[i]); + else if(type == SND_CTL_ELEM_TYPE_ENUMERATED) + snd_ctl_elem_value_set_enumerated(value, i, val[i]); + } + /* write value */ + if(snd_ctl_elem_write(alsa_ctl, value) < 0) + panicf("Cannot write control '%s'", name); +} + +/* get control information */ +void alsa_controls_get_info(const char *name, int *out_count) +{ + snd_ctl_elem_id_t *id; + snd_ctl_elem_info_t *info; + /* allocate things on stack to speedup */ + snd_ctl_elem_id_alloca(&id); + snd_ctl_elem_info_alloca(&info); + /* find control */ + if(!alsa_controls_find(id, name)) + panicf("Cannot find control '%s'", name); + /* get info */ + snd_ctl_elem_info_set_id(info, id); + if(snd_ctl_elem_info(alsa_ctl, info) < 0) + panicf("Cannot get control '%s' info", name); + *out_count = snd_ctl_elem_info_get_count(info); +} + +/* helper function: set a control with a single boolean value */ +void alsa_controls_set_bool(const char *name, bool val) +{ + long lval = val; + alsa_controls_set(name, SND_CTL_ELEM_TYPE_BOOLEAN, 1, &lval); +} + +/* helper function: set a control with a single enum value */ +void alsa_controls_set_enum(const char *name, const char *enum_name) +{ + long idx = alsa_controls_find_enum(name, enum_name); + if(idx < 0) + panicf("Cannot find enum '%s' for control '%s'", enum_name, name); + alsa_controls_set(name, SND_CTL_ELEM_TYPE_ENUMERATED, 1, &idx); +} + +/* helper function: set a control with one or more integers */ +void alsa_controls_set_ints(const char *name, int count, long *val) +{ + return alsa_controls_set(name, SND_CTL_ELEM_TYPE_INTEGER, count, val); +} diff --git a/firmware/target/hosted/alsa-controls.h b/firmware/target/hosted/alsa-controls.h new file mode 100644 index 0000000000..ea2475a98e --- /dev/null +++ b/firmware/target/hosted/alsa-controls.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __ALSA_CONTROLS_RB_H__ +#define __ALSA_CONTROLS_RB_H__ + +#include <config.h> +#include <stddef.h> +#include <stdbool.h> +#include <alsa/asoundlib.h> +#include <alloca.h> + +/* open alsa control interface and list all controls, keep control open */ +void alsa_controls_init(void); +/* close alsa controls */ +void alsa_controls_close(void); + +/* find a control element ID by name, return false of not found, the id needs + * to be allocated */ +bool alsa_controls_find(snd_ctl_elem_id_t *id, const char *name); +/* find a control element enum index by name, return -1 if not found */ +int alsa_controls_find_enum(const char *name, const char *enum_name); +/* set a control, potentially supports several values */ +void alsa_controls_set(const char *name, snd_ctl_elem_type_t type, + unsigned nr_values, long *val); +/* get control information: number of values */ +void alsa_controls_get_info(const char *name, int *out_count); +/* helper function: set a control with a single boolean value */ +void alsa_controls_set_bool(const char *name, bool val); +/* helper function: set a control with a single enum value */ +void alsa_controls_set_enum(const char *name, const char *enum_name); +/* helper function: set a control with one or more integers */ +void alsa_controls_set_ints(const char *name, int count, long *val); + +#endif /* __ALSA_CONTROLS_RB_H__ */ diff --git a/firmware/target/hosted/backtrace-glibc.c b/firmware/target/hosted/backtrace-glibc.c new file mode 100644 index 0000000000..19becda38b --- /dev/null +++ b/firmware/target/hosted/backtrace-glibc.c @@ -0,0 +1,60 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (c) 2017 Amaury Pouly + * + * 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 "config.h" +#include "system.h" +#include "lcd.h" +#include <execinfo.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +/* backtrace from the call-site of this function */ +void rb_backtrace(int pc, int sp, unsigned *line) +{ + /* ignore SP and PC */ + (void) pc; + (void) sp; + + /* backtrace */ + #define BT_BUF_SIZE 100 + void *buffer[BT_BUF_SIZE]; + int count = backtrace(buffer, BT_BUF_SIZE); + /* print symbols to stdout for debug */ + fprintf(stdout, "backtrace:\n"); + fflush(stdout); + backtrace_symbols_fd(buffer, count, STDOUT_FILENO); + /* print on screen */ + char **strings; + strings = backtrace_symbols(buffer, count); + if(strings == NULL) + { + perror("backtrace_symbols"); + return; + } + + for(int i = 0; i < count; i++) + { + lcd_putsf(0, (*line)++, " %s", buffer[i], strings[i]); + lcd_update(); + } + + free(strings); +} diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c index 826ab5bbb1..64ce9f41bc 100644 --- a/firmware/target/hosted/filesystem-app.c +++ b/firmware/target/hosted/filesystem-app.c @@ -43,11 +43,12 @@ static const char rbhome[] = "/sdcard"; && !defined(__PCTOOL__) static const char *rbhome; #else -/* YPR0, YPR1 */ +/* YPR0, YPR1, NWZ */ static const char rbhome[] = HOME_DIR; #endif -#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90)) && !defined(__PCTOOL__) +#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || \ + defined(SONY_NWZ_LINUX) || defined(DX90)) && !defined(__PCTOOL__) /* Special dirs are user-accessible (and user-writable) dirs which take priority * over the ones where Rockbox is installed to. Classic example would be * $HOME/.config/rockbox.org vs /usr/share/rockbox */ diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c index 715af58fd9..d55eebccc1 100644 --- a/firmware/target/hosted/pcm-alsa.c +++ b/firmware/target/hosted/pcm-alsa.c @@ -50,12 +50,14 @@ #include "system.h" #include "debug.h" #include "kernel.h" +#include "panic.h" #include "pcm.h" #include "pcm-internal.h" #include "pcm_mixer.h" #include "pcm_sampr.h" #include "audiohw.h" +#include "pcm-alsa.h" #include <pthread.h> #include <signal.h> @@ -66,14 +68,21 @@ * with multple applications running */ static char device[] = "plughw:0,0"; /* playback device */ static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ +#ifdef SONY_NWZ_LINUX +/* Sony NWZ must use 32-bit per sample */ +static const snd_pcm_format_t format = SND_PCM_FORMAT_S32_LE; /* sample format */ +typedef long sample_t; +#else static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */ +typedef short sample_t; +#endif static const int channels = 2; /* count of channels */ static unsigned int rate = 44100; /* stream rate */ static snd_pcm_t *handle; static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */ static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */ -static short *frames; +static sample_t *frames; static const void *pcm_data = 0; static size_t pcm_size = 0; @@ -153,7 +162,7 @@ static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) goto error; } if (!frames) - frames = malloc(period_size * channels * sizeof(short)); + frames = malloc(period_size * channels * sizeof(sample_t)); /* write the parameters to device */ err = snd_pcm_hw_params(handle, params); @@ -212,6 +221,40 @@ error: return err; } +#ifdef SONY_NWZ_LINUX +/* Digital volume explanation: + * with very good approximation (<0.1dB) the convertion from dB to multiplicative + * factor, for dB>=0, is 2^(dB/3). We can then notice that if we write dB=3*k+r + * then this is 2^k*2^(r/3) so we only need to look at r=0,1,2. For r=0 this is + * 1, for r=1 we have 2^(1/3)~=1.25 so we approximate by 1+1/4, and 2^(2/3)~=1.5 + * so we approximate by 1+1/2. To go from negative to nonnegative we notice that + * 48 dB => 63095 factor ~= 2^16 so we virtually pre-multiply everything by 2^(-16) + * and add 48dB to the input volume. We cannot go lower -43dB because several + * values between -48dB and -43dB would require a fractional multiplier, which is + * stupid to implement for such very low volume. */ +static int dig_vol_mult = 2 ^ 16; /* multiplicative factor to apply to each sample */ + +void pcm_alsa_set_digital_volume(int vol_db) +{ + if(vol_db > 0 || vol_db < -43) + panicf("invalid pcm alsa volume"); + if(format != SND_PCM_FORMAT_S32_LE) + panicf("this function assumes 32-bit sample size"); + vol_db += 48; /* -42dB .. 0dB => 5dB .. 48dB */ + /* NOTE if vol_dB = 5 then vol_shift = 1 but r = 1 so we do vol_shift - 1 >= 0 + * otherwise vol_dB >= 0 implies vol_shift >= 2 so vol_shift - 2 >= 0 */ + int vol_shift = vol_db / 3; + int r = vol_db % 3; + if(r == 0) + dig_vol_mult = 1 << vol_shift; + else if(r == 1) + dig_vol_mult = 1 << vol_shift | 1 << (vol_shift - 2); + else + dig_vol_mult = 1 << vol_shift | 1 << (vol_shift - 1); + printf("%d dB -> factor = %d\n", vol_db - 48, dig_vol_mult); +} +#endif + /* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */ static bool fill_frames(void) { @@ -229,12 +272,28 @@ static bool fill_frames(void) return false; } } - copy_n = MIN((ssize_t)pcm_size, frames_left*4); - memcpy(&frames[2*(period_size-frames_left)], pcm_data, copy_n); - pcm_data += copy_n; - pcm_size -= copy_n; - frames_left -= copy_n/4; + if (pcm_size % 4) + panicf("Wrong pcm_size"); + /* the compiler will optimize this test away */ + copy_n = MIN((ssize_t)pcm_size/4, frames_left); + if (format == SND_PCM_FORMAT_S32_LE) + { + /* We have to convert 16-bit to 32-bit, the need to multiply the + * sample by some value so the sound is not too low */ + const short *pcm_ptr = pcm_data; + sample_t *sample_ptr = &frames[2*(period_size-frames_left)]; + for (int i = 0; i < copy_n*2; i++) + *sample_ptr++ = *pcm_ptr++ * dig_vol_mult; + } + else + { + /* Rockbox and PCM have same format: memcopy */ + memcpy(&frames[2*(period_size-frames_left)], pcm_data, copy_n); + } + pcm_data += copy_n*4; + pcm_size -= copy_n*4; + frames_left -= copy_n; if (new_buffer) { @@ -285,7 +344,7 @@ static int async_rw(snd_pcm_t *handle) { int err; snd_pcm_sframes_t sample_size; - short *samples; + sample_t *samples; #ifdef USE_ASYNC_CALLBACK /* assign alternative stack for the signal handlers */ @@ -323,7 +382,7 @@ static int async_rw(snd_pcm_t *handle) /* fill buffer with silence to initiate playback without noisy click */ sample_size = buffer_size; - samples = malloc(sample_size * channels * sizeof(short)); + samples = malloc(sample_size * channels * sizeof(sample_t)); snd_pcm_format_set_silence(format, samples, sample_size); err = snd_pcm_writei(handle, samples, sample_size); @@ -367,23 +426,19 @@ void pcm_play_dma_init(void) if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { - printf("%s(): Cannot open device %s: %s\n", __func__, device, snd_strerror(err)); - exit(EXIT_FAILURE); - return; + panicf("%s(): Cannot open device %s: %s\n", __func__, device, snd_strerror(err)); } if ((err = snd_pcm_nonblock(handle, 1))) - printf("Could not set non-block mode: %s\n", snd_strerror(err)); + panicf("Could not set non-block mode: %s\n", snd_strerror(err)); if ((err = set_hwparams(handle, rate)) < 0) { - printf("Setting of hwparams failed: %s\n", snd_strerror(err)); - exit(EXIT_FAILURE); + panicf("Setting of hwparams failed: %s\n", snd_strerror(err)); } if ((err = set_swparams(handle)) < 0) { - printf("Setting of swparams failed: %s\n", snd_strerror(err)); - exit(EXIT_FAILURE); + panicf("Setting of swparams failed: %s\n", snd_strerror(err)); } pcm_dma_apply_settings(); diff --git a/firmware/target/hosted/pcm-alsa.h b/firmware/target/hosted/pcm-alsa.h new file mode 100644 index 0000000000..a2514494de --- /dev/null +++ b/firmware/target/hosted/pcm-alsa.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __PCM_ALSA_RB_H__ +#define __PCM_ALSA_RB_H__ + +#include <config.h> + +#ifdef SONY_NWZ_LINUX +/* Set the PCM volume in dB: each sample with have this volume applied digitally + * before being sent to ALSA. Volume must satisfy -43 <= dB <= 0 */ +void pcm_alsa_set_digital_volume(int vol_db); +#endif + +#endif /* __PCM_ALSA_RB_H__ */ diff --git a/firmware/target/hosted/sonynwz/adc-nwz.c b/firmware/target/hosted/sonynwz/adc-nwz.c new file mode 100644 index 0000000000..d981ead9eb --- /dev/null +++ b/firmware/target/hosted/sonynwz/adc-nwz.c @@ -0,0 +1,63 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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 "adc.h" +#include "adc-target.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +static int adc_fd = -1; /* file descriptor */ + +static const char *nwz_adc_channel_name[NWZ_ADC_MAX_CHAN + 1] = +{ + [NWZ_ADC_VCCBAT] = "VCCBAT", + [NWZ_ADC_VCCVBUS] = "VCCBUS", + [NWZ_ADC_ADIN3] = "ADIN3", + [NWZ_ADC_ADIN4] = "ADIN4", + [NWZ_ADC_ADIN5] = "ADIN5", + [NWZ_ADC_ADIN6] = "ADIN6", + [NWZ_ADC_ADIN7] = "ADIN7", + [NWZ_ADC_ADIN8] = "ADIN8" +}; + +void adc_init(void) +{ + adc_fd = open(NWZ_ADC_DEV, O_RDONLY); +} + +unsigned short adc_read(int channel) +{ + unsigned char val; + if(ioctl(adc_fd, NWZ_ADC_GET_VAL(channel), &val) < 0) + return 0; + else + return val; +} + +const char *adc_name(int channel) +{ + if(channel < NWZ_ADC_MIN_CHAN || channel > NWZ_ADC_MAX_CHAN) + return ""; + return nwz_adc_channel_name[channel]; +} + diff --git a/utils/nwztools/plattools/nwz_adc.h b/firmware/target/hosted/sonynwz/adc-target.h index 86b2dc7595..bee028a8ac 100644 --- a/utils/nwztools/plattools/nwz_adc.h +++ b/firmware/target/hosted/sonynwz/adc-target.h @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2016 Amaury Pouly + * Copyright (C) 2016 by Amaury Pouly * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,8 +18,10 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef __NWZ_ADC_H__ -#define __NWZ_ADC_H__ +#ifndef _ADC_NWZ_H_ +#define _ADC_NWZ_H_ + +#include "adc.h" #define NWZ_ADC_DEV "/dev/icx_adc" @@ -39,4 +41,7 @@ #define NWZ_ADC_GET_VAL(chan) _IOR(NWZ_ADC_TYPE, chan, unsigned char) -#endif /* __NWZ_ADC_H__ */ +/* Return channel name */ +const char *adc_name(int channel); + +#endif diff --git a/firmware/target/hosted/sonynwz/backlight-target.h b/firmware/target/hosted/sonynwz/backlight-target.h new file mode 100644 index 0000000000..b5a200d07a --- /dev/null +++ b/firmware/target/hosted/sonynwz/backlight-target.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef BACKLIGHT_TARGET_H +#define BACKLIGHT_TARGET_H + +bool backlight_hw_init(void); +void backlight_hw_on(void); +void backlight_hw_off(void); +void backlight_hw_brightness(int brightness); + +#endif /* BACKLIGHT_TARGET_H */ diff --git a/firmware/target/hosted/sonynwz/button-nwz.c b/firmware/target/hosted/sonynwz/button-nwz.c new file mode 100644 index 0000000000..0cbb3c5869 --- /dev/null +++ b/firmware/target/hosted/sonynwz/button-nwz.c @@ -0,0 +1,323 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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 "button.h" +#define LOGF_ENABLE +#include "logf.h" +#include "panic.h" +#include "backlight.h" + +#include "nwz_keys.h" +#include "nwz_ts.h" + +#include <poll.h> +#include <dir.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <linux/input.h> +#include <fcntl.h> +#include <string.h> +#include <stdlib.h> + +/* device types */ +#define DEV_KEY 0 /* icx_keys driver */ +#define DEV_TOUCH 1 /* icx_touch_screen driver */ + +/* HOLD status */ +static bool hold_status; +/* button bitmap */ +static int button_bitmap; +/* poll() descriptors (up to 2 for now: keys and touchscreen) */ +#define NR_POLL_DESC 2 +static struct pollfd poll_fds[NR_POLL_DESC]; +static nfds_t poll_nfds; +int dev_type[NR_POLL_DESC]; /* DEV_* */ + +#ifdef HAVE_TOUCHSCREEN +/* structure to track touch state */ +static struct +{ + int x, y; /* current position (valid is touch is true) */ + int max_x, max_y; /* maximum possible values */ + int pressure, tool_width; /* current pressure and tool width */ + int max_pressure, max_tool_width; /* maximum possible values */ + bool touch; /* is the user touching the screen? */ + /* the hardware supports "flick" gesture */ + bool flick; /* was the action a flick? */ + int flick_x, flick_y; /* if so, this is the flick direction */ +}ts_state; +/* rockbox state, updated from ts state on SYN event */ +static int touch_x, touch_y; +static bool touch_detect; + +/* get touchscreen information and init state */ +int ts_init_state(int fd) +{ + memset(state, 0, sizeof(struct nwz_ts_state_t)); + struct input_absinfo info; + if(ioctl(fd, EVIOCGABS(ABS_X), &info) < 0) + return -1; + state->max_x = info.maximum; + if(ioctl(fd, EVIOCGABS(ABS_Y), &info) < 0) + return -1; + state->max_y = info.maximum; + if(ioctl(fd, EVIOCGABS(ABS_PRESSURE), &info) < 0) + return -1; + state->max_pressure = info.maximum; + if(ioctl(fd, EVIOCGABS(ABS_TOOL_WIDTH), &info) < 0) + return -1; + state->max_tool_width = info.maximum; + touch_detect = false; + return 0; +} + +void handle_touch(struct input_event *evt) +{ + switch(evt->type) + { + case EV_SYN: + /* on SYN, we copy the state to the rockbox state */ + touch_x = ts_state->x; + touch_y = ts_state->y; + /* map coordinate to screen */ + x = x * LCD_WIDTH / ts_state->max_x; + y = y * LCD_HEIGHT / ts_state->max_y; + /* don't trust driver reported ranges */ + x = MAX(0, MIN(x, LCD_WIDTH - 1)); + y = MAX(0, MIN(y, LCD_HEIGHT - 1)); + touch_detect = ts_state->touch; + /* reset flick */ + state->flick = false; + break; + case EV_REL: + if(evt->code == REL_RX) + state->flick_x = evt->value; + else if(evt->code == REL_RY) + state->flick_y = evt->value; + else + break; + state->flick = true; + break; + case EV_ABS: + if(evt->code == ABS_X) + state->x = evt->value; + else if(evt->code == ABS_Y) + state->y = evt->value; + else if(evt->code == ABS_PRESSURE) + state->pressure = evt->value; + else if(evt->code == ABS_TOOL_WIDTH) + state->tool_width = evt->value; + break; + case EV_KEY: + if(evt->code == BTN_TOUCH) + state->touch = evt->value; + break; + default: + break; + } +} +#endif + +static void load_hold_status(int fd) +{ + /* HOLD is reported as the first LED */ + unsigned long led_hold = 0; + if(ioctl(fd, EVIOCGLED(sizeof(led_hold)), &led_hold) < 0) + logf("cannot read HOLD status: %s", strerror(errno)); + hold_status = !!led_hold; +} + +static void key_init_state(int fd) +{ + /* the driver knows the HOLD statu at all times */ + load_hold_status(fd); + /* the driver can be queried for button status but the output is garbage + * so just assume no keys are pressed */ + button_bitmap = 0; +} + +static void open_input_device(const char *path) +{ + int fd = open(path, O_RDWR); + if(fd < 0) + return; + /* query name */ + char name[256]; + if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) + { + close(fd); + return; + } + + if(strcmp(name, NWZ_KEY_NAME) == 0) + dev_type[poll_nfds] = DEV_KEY; + else if(strcmp(name, NWZ_TS_NAME) == 0) + dev_type[poll_nfds] = DEV_TOUCH; + else + { + /* only keep devices we know about */ + close(fd); + return; + } + /* if we found a key driver, we can read the hold status from it (and keep + * it updated with events) */ + if(dev_type[poll_nfds] == DEV_KEY) + key_init_state(fd); +#ifdef HAVE_TOUCHSCREEN + else if(dev_type[poll_nfds] == DEV_TOUCH) + ts_init_state(fd); +#endif + /* fill poll descriptor */ + poll_fds[poll_nfds].fd = fd; + poll_fds[poll_nfds].events = POLLIN; + poll_fds[poll_nfds].revents = 0; + poll_nfds++; +} + +/* keycode -> rockbox button mapping */ +static int button_map[NWZ_KEY_MASK + 1] = +{ + [0 ... NWZ_KEY_MASK] = 0, + [NWZ_KEY_PLAY] = BUTTON_PLAY, + [NWZ_KEY_RIGHT] = BUTTON_RIGHT, + [NWZ_KEY_LEFT] = BUTTON_LEFT, + [NWZ_KEY_UP] = BUTTON_UP, + [NWZ_KEY_DOWN] = BUTTON_DOWN, + [NWZ_KEY_ZAPPIN] = 0, + [NWZ_KEY_AD0_6] = 0, + [NWZ_KEY_AD0_7] = 0, + [NWZ_KEY_NONE] = 0, + [NWZ_KEY_VOL_DOWN] = BUTTON_VOL_DOWN, + [NWZ_KEY_VOL_UP] = BUTTON_VOL_UP, + [NWZ_KEY_BACK] = BUTTON_BACK, + [NWZ_KEY_OPTION] = BUTTON_POWER, + [NWZ_KEY_BT] = 0, + [NWZ_KEY_AD1_5] = 0, + [NWZ_KEY_AD1_6] = 0, + [NWZ_KEY_AD1_7] = 0, +}; + +static void handle_key(struct input_event evt) +{ + /* See headers/nwz_keys.h for explanation of Sony's nonstandard interface */ + int keycode = evt.code & NWZ_KEY_MASK; + bool press = (evt.value == 0); + if(press) + button_bitmap |= button_map[keycode]; + else + button_bitmap &= ~button_map[keycode]; + bool new_hold_status = !!(evt.code & NWZ_KEY_HOLD_MASK); + if(new_hold_status != hold_status) + { + hold_status = new_hold_status; +#ifndef BOOTLOADER + backlight_hold_changed(hold_status); +#endif + } +} + +bool button_hold(void) +{ + return hold_status; +} + +void button_init_device(void) +{ + const char *input_path = "/dev/input"; + char device_name[PATH_MAX]; + /* find what input devices are available */ + DIR* input_dir = opendir(input_path); + if(input_dir == NULL) + panicf("Cannot read /dev/input directory: %s", strerror(errno)); + strcpy(device_name, input_path); + strcat(device_name, "/"); + char *device_name_p = device_name + strlen(device_name); + struct dirent *dir_entry; + while((dir_entry = readdir(input_dir))) + { + /* skip '.' and '..' entries */ + if(strcmp(dir_entry->d_name, ".") == 0 || strcmp(dir_entry->d_name, "..") == 0) + continue; + /* create device full path and open it */ + strcpy(device_name_p, dir_entry->d_name); + open_input_device(device_name); + } + closedir(input_dir); + /* check if we have at least one device */ + if(poll_nfds == 0) + panicf("No input device found"); +} + +int button_read_device( +#ifdef HAVE_BUTTON_DATA + int *data +#else + void +#endif + ) +{ + struct input_event event; + /* check if there are any events pending and process them */ + while(true) + { + /* stop when there are no more events */ + if(poll(poll_fds, poll_nfds, 0) == 0) + break; + for(unsigned int i = 0; i < poll_nfds; i++) + { + /* only read if we won't block */ + if(!(poll_fds[i].revents & POLLIN)) + continue; + if(read(poll_fds[i].fd, &event, sizeof(event)) != (int)sizeof(event)) + continue; + if(dev_type[i] == DEV_KEY) + handle_key(event); +#ifdef HAVE_TOUCHSCREEN + else if(dev_type[i] == DEV_TOUCH) + handle_touch(event); +#endif + } + } +#ifdef HAVE_TOUCHSCREEN + button_bitmap |= touchscreen_to_pixels(touch_x, touch_y, data); +#endif + return hold_status ? 0 : button_bitmap; +} + +void nwz_button_reload_after_suspend(void) +{ + /* reinit everything, particularly important for keys and HOLD */ + for(unsigned int i = 0; i < poll_nfds; i++) + { + if(dev_type[i] == DEV_KEY) + key_init_state(poll_fds[i].fd); +#ifdef HAVE_TOUCHSCREEN + else if(dev_type[i] == DEV_TOUCH) + ts_init_state(poll_fds[i].fd); +#endif + } +} + +void button_close_device(void) +{ + /* close descriptors */ + for(unsigned int i = 0; i < poll_nfds; i++) + close(poll_fds[i].fd); +} diff --git a/firmware/target/hosted/sonynwz/button-target.h b/firmware/target/hosted/sonynwz/button-target.h new file mode 100644 index 0000000000..6cf915b4ad --- /dev/null +++ b/firmware/target/hosted/sonynwz/button-target.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef _BUTTON_TARGET_H_ +#define _BUTTON_TARGET_H_ + +#include <stdbool.h> +#include "config.h" + +/* Main unit's buttons */ +#define BUTTON_POWER 0x00000001 +#define BUTTON_BACK 0x00000002 +#define BUTTON_PLAY 0x00000004 +#define BUTTON_LEFT 0x00000008 +#define BUTTON_UP 0x00000010 +#define BUTTON_DOWN 0x00000020 +#define BUTTON_RIGHT 0x00000040 +#define BUTTON_VOL_DOWN 0x00000080 +#define BUTTON_VOL_UP 0x00000100 + +#define BUTTON_MAIN 0x000001ff + +/* Software power-off */ +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 10 + +/* force driver to reload button state (useful after suspend) */ +void nwz_button_reload_after_suspend(void); + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/hosted/sonynwz/debug-nwz.c b/firmware/target/hosted/sonynwz/debug-nwz.c new file mode 100644 index 0000000000..c55029524c --- /dev/null +++ b/firmware/target/hosted/sonynwz/debug-nwz.c @@ -0,0 +1,439 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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 "cpu.h" +#include "system.h" +#include "kernel.h" +#include "lcd.h" +#include "font.h" +#include "adc.h" +#include "adc-target.h" +#include "button.h" +#include "button-target.h" +#include "powermgmt.h" +#include "power-nwz.h" +#include "nvp-nwz.h" +#include "nwz_sysinfo.h" +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +/* NOTE: some targets with touchscreen don't have the usual keypad, on those + * we use a mixture of rewind/forward/volume+/- to emulate it */ +#define ACT_NONE 0 +#define ACT_CANCEL 1 +#define ACT_OK 2 +#define ACT_PREV 3 +#define ACT_NEXT 4 +#define ACT_REPEAT 0x1000 + +int xlate_button(int btn) +{ + switch(btn) + { +#ifdef BUTTON_POWER + case BUTTON_POWER: +#endif + case BUTTON_BACK: + return ACT_CANCEL; + case BUTTON_PLAY: + return ACT_OK; + case BUTTON_UP: + case BUTTON_LEFT: + case BUTTON_VOL_UP: + return ACT_PREV; + case BUTTON_DOWN: + case BUTTON_RIGHT: + case BUTTON_VOL_DOWN: + return ACT_NEXT; + default: + return ACT_NONE; + } +} + +int my_get_status(void) +{ + return xlate_button(button_status()); +} + +int my_get_action(int tmo) +{ + int btn = button_get_w_tmo(tmo); + while(btn & BUTTON_REL) + btn = button_get_w_tmo(tmo); + bool repeat = btn & BUTTON_REPEAT; + int act = xlate_button(btn & ~BUTTON_REPEAT); + if(repeat) + act |= ACT_REPEAT; + return act; +} + +bool dbg_hw_info_adc(void) +{ + lcd_setfont(FONT_SYSFIXED); + + while(1) + { + int button = my_get_action(HZ / 25); + switch(button) + { + case ACT_NEXT: + case ACT_PREV: + case ACT_OK: + lcd_setfont(FONT_UI); + return true; + case ACT_CANCEL: + lcd_setfont(FONT_UI); + return false; + } + + lcd_clear_display(); + + /* add battery readout in mV, this it is not the direct output of a channel */ + lcd_putsf(0, 0, "Battery(mV) %d", _battery_voltage()); + for(unsigned i = NWZ_ADC_MIN_CHAN; i <= NWZ_ADC_MAX_CHAN; i++) + lcd_putsf(0, i + 1, "%7s %3d", adc_name(i), adc_read(i)); + + lcd_update(); + yield(); + } +} + +static const char *charge_status_name(int chgstat) +{ + switch(chgstat) + { + case NWZ_POWER_STATUS_CHARGE_STATUS_CHARGING: return "charging"; + case NWZ_POWER_STATUS_CHARGE_STATUS_SUSPEND: return "suspend"; + case NWZ_POWER_STATUS_CHARGE_STATUS_TIMEOUT: return "timeout"; + case NWZ_POWER_STATUS_CHARGE_STATUS_NORMAL: return "normal"; + default: return "unknown"; + } +} + +static const char *get_batt_gauge_name(int gauge) +{ + switch(gauge) + { + case NWZ_POWER_BAT_NOBAT: return "no batt"; + case NWZ_POWER_BAT_VERYLOW: return "very low"; + case NWZ_POWER_BAT_LOW: return "low"; + case NWZ_POWER_BAT_GAUGE0: return "____"; + case NWZ_POWER_BAT_GAUGE1: return "O___"; + case NWZ_POWER_BAT_GAUGE2: return "OO__"; + case NWZ_POWER_BAT_GAUGE3: return "OOO_"; + case NWZ_POWER_BAT_GAUGE4: return "OOOO"; + default: return "unknown"; + } +} + +static const char *acc_charge_mode_name(int mode) +{ + switch(mode) + { + case NWZ_POWER_ACC_CHARGE_NONE: return "none"; + case NWZ_POWER_ACC_CHARGE_VBAT: return "vbat"; + case NWZ_POWER_ACC_CHARGE_VSYS: return "vsys"; + default: return "unknown"; + } +} + +bool dbg_hw_info_power(void) +{ + lcd_setfont(FONT_SYSFIXED); + + while(1) + { + int button = my_get_action(HZ / 25); + switch(button) + { + case ACT_NEXT: + case ACT_PREV: + case ACT_OK: + lcd_setfont(FONT_UI); + return true; + case ACT_CANCEL: + lcd_setfont(FONT_UI); + return false; + } + + lcd_clear_display(); + + int line = 0; + int status = nwz_power_get_status(); + int chgstat = status & NWZ_POWER_STATUS_CHARGE_STATUS; + int acc_chg_mode = nwz_power_get_acc_charge_mode(); + lcd_putsf(0, line++, "ac detected: %s", + (status & NWZ_POWER_STATUS_AC_DET) ? "yes" : "no"); + lcd_putsf(0, line++, "vbus detected: %s ", + (status & NWZ_POWER_STATUS_VBUS_DET) ? "yes" : "no"); + lcd_putsf(0, line++, "vbus voltage: %d mV (AD=%d)", + nwz_power_get_vbus_voltage(), nwz_power_get_vbus_adval()); + lcd_putsf(0, line++, "vbus limit: %d mA ", + nwz_power_get_vbus_limit()); + lcd_putsf(0, line++, "vsys voltage: %d mV (AD=%d)", + nwz_power_get_vsys_voltage(), nwz_power_get_vsys_adval()); + lcd_putsf(0, line++, "charge switch: %s ", + nwz_power_get_charge_switch() ? "on" : "off"); + lcd_putsf(0, line++, "full voltage: %s V ", + (status & NWZ_POWER_STATUS_CHARGE_LOW) ? "4.1" : "4.2"); + lcd_putsf(0, line++, "current limit: %d mA", + nwz_power_get_charge_current()); + lcd_putsf(0, line++, "charge status: %s (%x)", + charge_status_name(chgstat), chgstat); + lcd_putsf(0, line++, "battery full: %s ", + nwz_power_is_fully_charged() ? "yes" : "no"); + lcd_putsf(0, line++, "bat gauge: %s (%d)", + get_batt_gauge_name(nwz_power_get_battery_gauge()), + nwz_power_get_battery_gauge()); + lcd_putsf(0, line++, "avg voltage: %d mV (AD=%d)", + nwz_power_get_battery_voltage(), nwz_power_get_battery_adval()); + lcd_putsf(0, line++, "sample count: %d ", + nwz_power_get_sample_count()); + lcd_putsf(0, line++, "raw voltage: %d mV (AD=%d)", + nwz_power_get_vbat_voltage(), nwz_power_get_vbat_adval()); + lcd_putsf(0, line++, "acc charge mode: %s (%d)", + acc_charge_mode_name(acc_chg_mode), acc_chg_mode); + + lcd_update(); + yield(); + } +} + +bool dbg_hw_info_button(void) +{ + lcd_setfont(FONT_SYSFIXED); + + while(1) + { + int btn = my_get_action(0); + switch(btn) + { + case ACT_OK: + lcd_setfont(FONT_UI); + return true; + case ACT_CANCEL: + lcd_setfont(FONT_UI); + return false; + } + + lcd_clear_display(); + int line = 0; + +#ifdef HAVE_BUTTON_DATA + int data; + btn = button_read_device(&data); +#else + btn = button_read_device(); +#endif + lcd_putsf(0, line++, "raw buttons: %x", btn); +#ifdef HAS_BUTTON_HOLD + lcd_putsf(0, line++, "hold: %d", button_hold()); +#endif +#ifdef HAVE_HEADPHONE_DETECTION + lcd_putsf(0, line++, "headphones: %d", headphones_inserted()); +#endif +#ifdef HAVE_BUTTON_DATA +#ifdef HAVE_TOUCHSCREEN + lcd_putsf(0, line++, "touch: x=%d y=%d", data >> 16, data & 0xffff); +#else + lcd_putsf(0, line++, "data: %d", data); +#endif +#endif + + lcd_update(); + yield(); + } +} + +int read_sysinfo(int ioctl_nr, unsigned int *val) +{ + int fd = open(NWZ_SYSINFO_DEV, O_RDONLY); + if(fd < 0) + return -1; + int ret = ioctl(fd, ioctl_nr, val); + close(fd); + return ret; +} + +bool dbg_hw_info_sysinfo(void) +{ + lcd_setfont(FONT_SYSFIXED); + + while(1) + { + int btn = my_get_action(0); + switch(btn) + { + case ACT_OK: + lcd_setfont(FONT_UI); + return true; + case ACT_CANCEL: + lcd_setfont(FONT_UI); + return false; + } + + lcd_clear_display(); + int line = 0; + unsigned int val; + + lcd_putsf(0, line++, "mid: %x (%s)", nwz_get_model_id(), nwz_get_model_name()); +#define print_info(def, name) \ + if(read_sysinfo(NWZ_SYSINFO_GET_##def##_TYPE, &val) < 0) \ + lcd_putsf(0, line++, "%s: -", name); \ + else \ + lcd_putsf(0, line++, "%s: %d", name, val); + + /* WARNING the interpretation of values is difficult because it changes + * very often */ + /* DAC type: ... */ + print_info(DAC, "dac") + /* Noise cancelling: 0=no, 1=yes */ + print_info(NCR, "nc") + /* Speaker: 0=no, 1=yes */ + print_info(SPK, "spk") + /* Microphone: 0=no, 1=yes */ + print_info(MIC, "mic") + /* Video encoder: 0=no, ... */ + print_info(NPE, "videoenc") + /* FM receiver: 0=no, 1=si470x */ + print_info(FMT, "fm") + /* Touch screen: 0=none, ... */ + print_info(TSP, "touch") + /* Bluetooth: 0=no, 1=yes */ + print_info(WAB, "bt") + /* SD card: 0=no, ... */ + print_info(SDC, "sd") + + lcd_update(); + yield(); + } +} + +#include "pcm-alsa.h" + +bool dbg_hw_info_audio(void) +{ + lcd_setfont(FONT_SYSFIXED); + int vol = 0; + + while(1) + { + int btn = my_get_action(0); + switch(btn) + { + case ACT_PREV: + vol--; + pcm_alsa_set_digital_volume(vol); + break; + case ACT_NEXT: + vol++; + pcm_alsa_set_digital_volume(vol); + break; + case ACT_OK: + lcd_setfont(FONT_UI); + return true; + case ACT_CANCEL: + lcd_setfont(FONT_UI); + return false; + } + + lcd_clear_display(); + int line = 0; + unsigned int val; + + lcd_putsf(0, line++, "vol: %d dB", vol); + + lcd_update(); + yield(); + } +} + +static struct +{ + const char *name; + bool (*fn)(void); +} debug_screens[] = +{ + {"sysinfo", dbg_hw_info_sysinfo}, + {"adc", dbg_hw_info_adc}, + {"power", dbg_hw_info_power}, + {"button", dbg_hw_info_button}, + {"audio", dbg_hw_info_audio}, +}; + +bool dbg_hw_info(void) +{ + int nr_lines = lcd_getheight() / font_get(lcd_getfont())->height; + int len = ARRAYLEN(debug_screens); + int top_visible = 0; + int highlight = 0; + while(1) + { + int button = my_get_action(HZ / 10); + switch(button) + { + case ACT_NEXT: + highlight = (highlight + 1) % len; + break; + case ACT_PREV: + highlight = (highlight + len - 1) % len; + break; + case ACT_OK: + // if the screen returns true, advance to next screen + while(debug_screens[highlight].fn()) + highlight = (highlight + 1) % len; + lcd_setfont(FONT_UI); + break; + case ACT_CANCEL: + return false; + } + // adjust top visible if needed + if(highlight < top_visible) + top_visible = highlight; + else if(highlight >= top_visible + nr_lines) + top_visible = highlight - nr_lines + 1; + + lcd_clear_display(); + + for(int i = top_visible; i < len && i < top_visible + nr_lines; i++) + { + if(i == highlight) + { + lcd_set_foreground(LCD_BLACK); + lcd_set_background(LCD_RGBPACK(255, 255, 0)); + } + else + { + lcd_set_foreground(LCD_WHITE); + lcd_set_background(LCD_BLACK); + } + lcd_putsf(0, i - top_visible, "%s", debug_screens[i].name); + } + lcd_set_foreground(LCD_WHITE); + lcd_set_background(LCD_BLACK); + + lcd_update(); + yield(); + } + return false; +} diff --git a/firmware/target/hosted/sonynwz/lcd-nwz.c b/firmware/target/hosted/sonynwz/lcd-nwz.c new file mode 100644 index 0000000000..bfcde3a76a --- /dev/null +++ b/firmware/target/hosted/sonynwz/lcd-nwz.c @@ -0,0 +1,200 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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 <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <linux/fb.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include "lcd.h" +#include "lcd-target.h" +#include "backlight-target.h" + +static int fb_fd = 0; +fb_data *nwz_framebuffer = 0; /* global variable, see lcd-target.h */ +enum +{ + FB_MP200, /* MP200 fb driver */ + FB_EMXX, /* EMXX fb driver */ + FB_OTHER, /* unknown */ +}nwz_fb_type; + +void identify_fb(const char *id) +{ + if(strcmp(id, "MP200 FB") == 0) + nwz_fb_type = FB_MP200; + else if(strcmp(id, "EMXX FB") == 0) + nwz_fb_type = FB_EMXX; + else + nwz_fb_type = FB_OTHER; + printf("lcd: fb id = '%s -> type = %d\n", id, nwz_fb_type); +} + +/* select which page (0 or 1) to display, disable DSP, transparency and rotation */ +static int nwz_fb_set_page(int page) +{ + /* set page 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 = page; + mode_info.update = NWZ_FB_ONLY_2D_MODE; + if(ioctl(fb_fd, NWZ_FB_UPDATE, &mode_info) < 0) + return -1; + return 0; +} + +/* make sure framebuffer is in standard state so rendering works */ +static int nwz_fb_set_standard_mode(void) +{ + /* 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; + /* we don't check the result of the next ioctl() because it will fail in + * newer version of the driver, where the timer disapperared. */ + ioctl(fb_fd, NWZ_FB_UPDATE_TIMER, &update_timer); + return nwz_fb_set_page(0); +} + +void backlight_hw_brightness(int brightness) +{ + struct nwz_fb_brightness bl; + bl.level = brightness; /* brightness level: 0-5 */ + bl.step = 25; /* number of hardware steps to do when changing: 1-100 (smooth transition) */ + bl.period = NWZ_FB_BL_MIN_PERIOD; /* period in ms between steps when changing: >=10 */ + + ioctl(fb_fd, nwz_fb_type == FB_MP200 ? NWZ_FB_SET_BRIGHTNESS_MP200 : NWZ_FB_SET_BRIGHTNESS_EMXX, &bl); +} + +bool backlight_hw_init(void) +{ + backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING); + return true; +} + +void backlight_hw_on(void) +{ +#ifdef HAVE_LCD_ENABLE + lcd_enable(true); /* power on lcd + visible display */ +#endif + /* don't do anything special, the core will set the brightness */ +} + +void backlight_hw_off(void) +{ + /* there is no real on/off but we can set to 0 brightness */ + backlight_hw_brightness(0); +#ifdef HAVE_LCD_ENABLE + lcd_enable(false); /* power off visible display */ +#endif +} + +void lcd_shutdown(void) +{ + munmap(nwz_framebuffer, FRAMEBUFFER_SIZE); + close(fb_fd); +} + +void lcd_init_device(void) +{ + fb_fd = open("/dev/fb/0", O_RDWR); + if(fb_fd < 0) + { + perror("Cannot open framebuffer"); + exit(0); + } + + /* get fixed and variable information */ + struct fb_fix_screeninfo finfo; + if(ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) + { + perror("Cannot read framebuffer fixed information"); + exit(0); + } + identify_fb(finfo.id); + struct fb_var_screeninfo vinfo; + if(ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) + { + perror("Cannot read framebuffer variable information"); + exit(0); + } + /* check resolution and framebuffer size */ + if(vinfo.xres != LCD_WIDTH || vinfo.yres != LCD_HEIGHT || vinfo.bits_per_pixel != LCD_DEPTH) + { + printf("Unexpected framebuffer resolution: %dx%dx%d\n", vinfo.xres, + vinfo.yres, vinfo.bits_per_pixel); + exit(0); + } + /* Note: we use a framebuffer size of width*height*bbp. We cannot trust the + * values returned by the driver for line_length */ + + /* map framebuffer */ + nwz_framebuffer = mmap(0, FRAMEBUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0); + if((void *)nwz_framebuffer == (void *)-1) + { + perror("Cannot map framebuffer"); + fflush(stdout); + execlp("/usr/local/bin/SpiderApp.of", "SpiderApp", NULL); + exit(0); + } + /* make sure rendering state is correct */ + nwz_fb_set_standard_mode(); +} + +static void redraw(void) +{ + nwz_fb_set_page(0); +} + +extern void lcd_copy_buffer_rect(fb_data *dst, const fb_data *src, + int width, int height); + +void lcd_update(void) +{ + /* Copy the Rockbox framebuffer to the second framebuffer */ + lcd_copy_buffer_rect(LCD_FRAMEBUF_ADDR(0, 0), FBADDR(0,0), + LCD_WIDTH*LCD_HEIGHT, 1); + redraw(); +} + +void lcd_update_rect(int x, int y, int width, int height) +{ + fb_data *dst = LCD_FRAMEBUF_ADDR(x, y); + fb_data * src = FBADDR(x,y); + + /* Copy part of the Rockbox framebuffer to the second framebuffer */ + if (width < LCD_WIDTH) + { + /* Not full width - do line-by-line */ + lcd_copy_buffer_rect(dst, src, width, height); + } + else + { + /* Full width - copy as one line */ + lcd_copy_buffer_rect(dst, src, LCD_WIDTH*height, 1); + } + redraw(); +} diff --git a/utils/nwztools/plattools/nwz_fb.h b/firmware/target/hosted/sonynwz/lcd-target.h index 9334b625c9..dcc4a61c69 100644 --- a/utils/nwztools/plattools/nwz_fb.h +++ b/firmware/target/hosted/sonynwz/lcd-target.h @@ -5,7 +5,6 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id$ * * Copyright (C) 2016 Amaury Pouly * @@ -18,8 +17,12 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef __NWZ_FB_H__ -#define __NWZ_FB_H__ + +#ifndef __LCD_TARGET_H__ +#define __LCD_TARGET_H__ + +extern fb_data *nwz_framebuffer; /* see lcd-nwz.c */ +#define LCD_FRAMEBUF_ADDR(col, row) (nwz_framebuffer + (row)*LCD_WIDTH + (col)) #define NWZ_FB_LCD_DEV "/dev/fb/0" #define NWZ_FB_TV_DEV "/dev/fb/1" @@ -62,6 +65,7 @@ struct nwz_fb_brightness * * 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? + * Also it only exists on early version (up to generation x60 roughly) * * On a side note, this information only applies to a subset of LCD types (the * LCD type can be gathered from icx_sysinfo): @@ -126,14 +130,17 @@ struct nwz_fb_update_timer /* 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_WAIT_REFRESH _IOR(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) +/* the timer only exits on MP200, it disappeared in EMXX and the ioctl fails */ #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) +/* unfortnately, Sony change the ioctl numbers of those between MP200 and EMXX */ +#define NWZ_FB_SET_BRIGHTNESS_MP200 _IOW(NWZ_FB_TYPE, 0x07, struct nwz_fb_brightness) +#define NWZ_FB_GET_BRIGHTNESS_MP200 _IOR(NWZ_FB_TYPE, 0x08, struct nwz_fb_brightness) +#define NWZ_FB_SET_BRIGHTNESS_EMXX _IOW(NWZ_FB_TYPE, 0x10, struct nwz_fb_brightness) +#define NWZ_FB_GET_BRIGHTNESS_EMXX _IOR(NWZ_FB_TYPE, 0x11, struct nwz_fb_brightness) +#endif /* __LCD_TARGET_H__ */ -#endif /* __NWZ_FB_H__ */ diff --git a/firmware/target/hosted/sonynwz/nvp-nwz.c b/firmware/target/hosted/sonynwz/nvp-nwz.c new file mode 100644 index 0000000000..f7511d6118 --- /dev/null +++ b/firmware/target/hosted/sonynwz/nvp-nwz.c @@ -0,0 +1,119 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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 "nvp-nwz.h" +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdio.h> + +static unsigned long find_model_id(void) +{ + /* try with the environment variable */ + const char *mid = getenv("ICX_MODEL_ID"); + if(mid == NULL) + return 0; + char *end; + unsigned long v = strtoul(mid, &end, 0); + if(*end) + return 0; + else + return v; +} + +unsigned long nwz_get_model_id(void) +{ + static unsigned long model_id = 0xffffffff; + if(model_id == 0xffffffff) + model_id = find_model_id(); + return model_id; +} + +const char *nwz_get_model_name(void) +{ + for(int i = 0; i < NWZ_MODEL_COUNT; i++) + if(nwz_model[i].mid == nwz_get_model_id()) + return nwz_model[i].name; + return NULL; +} + +static int find_series(void) +{ + for(int i = 0; i < NWZ_SERIES_COUNT; i++) + for(int j = 0; j < nwz_series[i].mid_count; j++) + if(nwz_series[i].mid[j] == nwz_get_model_id()) + return i; + return -1; +} + +int nwz_get_series(void) +{ + static int series = -2; + if(series == -2) + series = find_series(); + return series; +} + +static nwz_nvp_index_t *get_nvp_index(void) +{ + static nwz_nvp_index_t *index = 0; + if(index == 0) + { + int series = nwz_get_series(); + index = series < 0 ? 0 : nwz_series[series].nvp_index; + } + return index; +} + +int nwz_nvp_read(enum nwz_nvp_node_t node, void *data) +{ + int size = nwz_nvp[node].size; + if(data == 0) + return size; + nwz_nvp_index_t *index = get_nvp_index(); + if(index == 0 || (*index)[node] == NWZ_NVP_INVALID) + return -1; + char nvp_path[32]; + snprintf(nvp_path, sizeof(nvp_path), "/dev/icx_nvp/%03d", (*index)[node]); + int fd = open(nvp_path, O_RDONLY); + if(fd < 0) + return -1; + int cnt = read(fd, data, size); + close(fd); + return cnt == size ? size : -1; +} + +int nwz_nvp_write(enum nwz_nvp_node_t node, void *data) +{ + int size = nwz_nvp[node].size; + nwz_nvp_index_t *index = get_nvp_index(); + if(index == 0 || (*index)[node] == NWZ_NVP_INVALID) + return -1; + char nvp_path[32]; + snprintf(nvp_path, sizeof(nvp_path), "/dev/icx_nvp/%03d", (*index)[node]); + int fd = open(nvp_path, O_WRONLY); + if(fd < 0) + return -1; + int cnt = write(fd, data, size); + close(fd); + return cnt == size ? 0 : -1; +} diff --git a/firmware/target/hosted/sonynwz/nvp-nwz.h b/firmware/target/hosted/sonynwz/nvp-nwz.h new file mode 100644 index 0000000000..648e8b5ca4 --- /dev/null +++ b/firmware/target/hosted/sonynwz/nvp-nwz.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __NVP_NWZ_H__ +#define __NVP_NWZ_H__ + +#include "system.h" +#include "nwz-db.h" + +/* get model ID */ +unsigned long nwz_get_model_id(void); +/* get model NAME (ie NWZ-E463) */ +const char *nwz_get_model_name(void); +/* return series (index into nwz_db) */ +int nwz_get_series(void); + +/* read a nvp node and return its size, if the data pointer is null, then simply + * return the size, return -1 on error */ +int nwz_nvp_read(enum nwz_nvp_node_t node, void *data); +/* write a nvp node, return 0 on success and -1 on error, the size of the buffer + * must be the one returned by nwz_nvp_read */ +int nwz_nvp_write(enum nwz_nvp_node_t node, void *data); + +#endif /* __NVP_NWZ_H__ */ diff --git a/utils/nwztools/database/nwz_db.c b/firmware/target/hosted/sonynwz/nwz-db.c index b65b49d191..2aef1e3a49 100644 --- a/utils/nwztools/database/nwz_db.c +++ b/firmware/target/hosted/sonynwz/nwz-db.c @@ -20,7 +20,7 @@ /** /!\ This file was automatically generated, DO NOT MODIFY IT DIRECTLY /!\ */ -#include "nwz_db.h" +#include "nwz-db.h" struct nwz_model_info_t nwz_model[NWZ_MODEL_COUNT] = { diff --git a/utils/nwztools/database/nwz_db.h b/firmware/target/hosted/sonynwz/nwz-db.h index cb130f96a2..cb130f96a2 100644 --- a/utils/nwztools/database/nwz_db.h +++ b/firmware/target/hosted/sonynwz/nwz-db.h diff --git a/firmware/target/hosted/sonynwz/nwz_audio.h b/firmware/target/hosted/sonynwz/nwz_audio.h new file mode 100644 index 0000000000..f18674345d --- /dev/null +++ b/firmware/target/hosted/sonynwz/nwz_audio.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __NWZ_AUDIO_H__ +#define __NWZ_AUDIO_H__ + +/* The Sony audio driver is a beast that involves several modules but eventually + * all boils down to the codec driver that handles everything, including ALSA + * controls. The volume, power up and other controls are doing through the ALSA + * interface. The driver also accepts private IOCTL on the hardware device + * (/dev/snd/hwC0D0). Finally some noice cancelling (NC) ioctl must be sent to + * the noican driver (/dev/icx_noican). + */ + +/** + * Sound driver + */ + +#define NWZ_AUDIO_TYPE 'a' + +#define NWZ_AUDIO_GET_CLRSTRO_VAL _IOR(NWZ_AUDIO_TYPE, 0x04, struct nwz_cst_param_t) +struct nwz_cst_param_t +{ + int no_ext_cbl; + int with_ext_cbl; +}; + +#define NEW_AUDIO_ALC_DATA_NUM 32 + +enum nwz_audio_alc_types +{ + NWZ_ALC_TYPE_NONE = 0, /* invalid */ + NWZ_ALC_TYPE_HP_DSP, /* HP / DSP ALC */ + NWZ_ALC_TYPE_HP_ARM, /* HP / ARM ALC */ + NWZ_ALC_TYPE_LINE_DSP, /* LINE / DSP ALC */ + NWZ_ALC_TYPE_LINE_ARM, /* LINE / ARM ALC */ + NWZ_ALC_TYPE_BT_DSP, /* BT / DSP ALC */ + NWZ_ALC_TYPE_BT_ARM /* BT / ARM ALC */ +}; + +struct nwz_audio_alc_data_ex_t +{ + enum nwz_audio_alc_types type; + unsigned short table[NEW_AUDIO_ALC_DATA_NUM]; +}; + +#define NWZ_AUDIO_GET_ALC_DATA_EX _IOWR(NWZ_AUDIO_TYPE, 0x0f, struct nwz_audio_alc_data_ex_t) + +/** + * Noise cancelling driver + */ + +#define NWZ_NC_DEV "/dev/icx_noican" + +#define NWZ_NC_TYPE 'c' + +/* Enable/Disable NC switch */ +#define NWZ_NC_SET_SWITCH _IOW(NWZ_NC_TYPE, 0x01, int) +#define NWZ_NC_GET_SWITCH _IOR(NWZ_NC_TYPE, 0x02, int) +#define NWZ_NC_SWITCH_OFF 0 +#define NWZ_NC_SWITCH_ON 1 + +/* Get NC HP status (whether it is NC capable or not) */ +#define NWZ_NC_GET_HP_STATUS _IOR(NWZ_NC_TYPE, 0x09, int) +#define NWZ_NC_HP_NMLHP (0x1 << 0) +#define NWZ_NC_HP_NCHP (0x1 << 1) + +/* NC amp gain */ +#define NWZ_NC_SET_GAIN _IOW(NWZ_NC_TYPE, 0x03, int) +#define NWZ_NC_GET_GAIN _IOR(NWZ_NC_TYPE, 0x04, int) +#define NWZ_NC_GAIN_MIN 0 +#define NWZ_NC_GAIN_CENTER 15 +#define NWZ_NC_GAIN_MAX 30 + +/* NC amp gain by value */ +#define NWZ_NC_SET_GAIN_VALUE _IOW(NWZ_NC_TYPE, 0x05, int) +#define NWZ_NC_GET_GAIN_VALUE _IOR(NWZ_NC_TYPE, 0x06, int) +#define NWZ_NC_MAKE_GAIN(l, r) (((r) << 8) | (l)) +#define NWZ_NC_GET_L_GAIN(vol) ((vol) & 0xff) +#define NWZ_NC_GET_R_GAIN(vol) (((vol) >> 8) & 0xff) + +/* Set/Get NC filter */ +#define NWZ_NC_SET_FILTER _IOWR(NWZ_NC_TYPE, 0x07, int) +#define NWZ_NC_GET_FILTER _IOWR(NWZ_NC_TYPE, 0x08, int) +#define NWZ_NC_FILTER_INDEX_0 0 +#define NWZ_NC_FILTER_INDEX_1 1 +#define NWZ_NC_FILTER_INDEX_2 2 + +/* Get/Set HP type */ +#define NWZ_NC_SET_HP_TYPE _IOWR(NWZ_NC_TYPE, 0x09, int) +#define NWZ_NC_GET_HP_TYPE _IOWR(NWZ_NC_TYPE, 0x0a, int) +#define NC_HP_TYPE_DEFAULT 0 +#define NC_HP_TYPE_NWNC200 1 + +#endif /* __NWZ_AUDIO_H__ */ diff --git a/utils/nwztools/plattools/nwz_keys.h b/firmware/target/hosted/sonynwz/nwz_keys.h index 9fc5b4c9fd..d2314d4a12 100644 --- a/utils/nwztools/plattools/nwz_keys.h +++ b/firmware/target/hosted/sonynwz/nwz_keys.h @@ -21,8 +21,6 @@ #ifndef __NWZ_KEYS_H__ #define __NWZ_KEYS_H__ -#define NWZ_KEY_NAME "icx_key" - /* The Sony icx_key driver reports keys via the /dev/input/event0 device and * abuses the standard struct input_event. The input_event.code is split into * two parts: @@ -32,6 +30,9 @@ * the first LED. */ +/* device name */ +#define NWZ_KEY_NAME "icx_key" + /* key code and mask */ #define NWZ_KEY_MASK 0x1f #define NWZ_KEY_PLAY 0 diff --git a/firmware/target/hosted/sonynwz/nwz_sysinfo.h b/firmware/target/hosted/sonynwz/nwz_sysinfo.h new file mode 100644 index 0000000000..ef63c9ad51 --- /dev/null +++ b/firmware/target/hosted/sonynwz/nwz_sysinfo.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2017 Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __NWZ_SYSINFO_H__ +#define __NWZ_SYSINFO_H__ + +#define NWZ_SYSINFO_DEV "/dev/icx_sysinfo" +#define NWZ_SYSINFO_TYPE 's' + +#define NWZ_SYSINFO_GET_SYS_INFO _IOR(NWZ_SYSINFO_TYPE, 0, unsigned int *) +#define NWZ_SYSINFO_PUT_SYS_INFO _IOW(NWZ_SYSINFO_TYPE, 1, unsigned int *) +#define NWZ_SYSINFO_GET_BRD_REVS _IOR(NWZ_SYSINFO_TYPE, 2, unsigned int *) +#define NWZ_SYSINFO_PUT_BRD_REVS _IOW(NWZ_SYSINFO_TYPE, 3, unsigned int *) +#define NWZ_SYSINFO_GET_MEM_SIZE _IOR(NWZ_SYSINFO_TYPE, 4, unsigned int *) +#define NWZ_SYSINFO_PUT_MEM_SIZE _IOW(NWZ_SYSINFO_TYPE, 5, unsigned int *) +#define NWZ_SYSINFO_GET_BTT_TYPE _IOR(NWZ_SYSINFO_TYPE, 6, unsigned int *) +#define NWZ_SYSINFO_PUT_BTT_TYPE _IOW(NWZ_SYSINFO_TYPE, 7, unsigned int *) +#define NWZ_SYSINFO_GET_LCD_TYPE _IOR(NWZ_SYSINFO_TYPE, 8, unsigned int *) +#define NWZ_SYSINFO_PUT_LCD_TYPE _IOW(NWZ_SYSINFO_TYPE, 9, unsigned int *) +#define NWZ_SYSINFO_GET_NPE_TYPE _IOR(NWZ_SYSINFO_TYPE, 10, unsigned int *) +#define NWZ_SYSINFO_PUT_NPE_TYPE _IOW(NWZ_SYSINFO_TYPE, 11, unsigned int *) +#define NWZ_SYSINFO_GET_DAC_TYPE _IOR(NWZ_SYSINFO_TYPE, 12, unsigned int *) +#define NWZ_SYSINFO_PUT_DAC_TYPE _IOW(NWZ_SYSINFO_TYPE, 13, unsigned int *) +#define NWZ_SYSINFO_GET_NCR_TYPE _IOR(NWZ_SYSINFO_TYPE, 14, unsigned int *) +#define NWZ_SYSINFO_PUT_NCR_TYPE _IOW(NWZ_SYSINFO_TYPE, 15, unsigned int *) +#define NWZ_SYSINFO_GET_SPK_TYPE _IOR(NWZ_SYSINFO_TYPE, 16, unsigned int *) +#define NWZ_SYSINFO_PUT_SPK_TYPE _IOW(NWZ_SYSINFO_TYPE, 17, unsigned int *) +#define NWZ_SYSINFO_GET_FMT_TYPE _IOR(NWZ_SYSINFO_TYPE, 18, unsigned int *) +#define NWZ_SYSINFO_PUT_FMT_TYPE _IOW(NWZ_SYSINFO_TYPE, 19, unsigned int *) +#define NWZ_SYSINFO_GET_OSG_TYPE _IOR(NWZ_SYSINFO_TYPE, 20, unsigned int *) +#define NWZ_SYSINFO_PUT_OSG_TYPE _IOW(NWZ_SYSINFO_TYPE, 21, unsigned int *) +#define NWZ_SYSINFO_GET_WAB_TYPE _IOR(NWZ_SYSINFO_TYPE, 22, unsigned int *) +#define NWZ_SYSINFO_PUT_WAB_TYPE _IOW(NWZ_SYSINFO_TYPE, 23, unsigned int *) +#define NWZ_SYSINFO_GET_TSP_TYPE _IOR(NWZ_SYSINFO_TYPE, 24, unsigned int *) +#define NWZ_SYSINFO_PUT_TSP_TYPE _IOW(NWZ_SYSINFO_TYPE, 25, unsigned int *) +#define NWZ_SYSINFO_GET_GSR_TYPE _IOR(NWZ_SYSINFO_TYPE, 26, unsigned int *) +#define NWZ_SYSINFO_PUT_GSR_TYPE _IOW(NWZ_SYSINFO_TYPE, 27, unsigned int *) +#define NWZ_SYSINFO_GET_MIC_TYPE _IOR(NWZ_SYSINFO_TYPE, 28, unsigned int *) +#define NWZ_SYSINFO_PUT_MIC_TYPE _IOW(NWZ_SYSINFO_TYPE, 29, unsigned int *) +#define NWZ_SYSINFO_GET_WMP_TYPE _IOR(NWZ_SYSINFO_TYPE, 30, unsigned int *) +#define NWZ_SYSINFO_PUT_WMP_TYPE _IOW(NWZ_SYSINFO_TYPE, 31, unsigned int *) +#define NWZ_SYSINFO_GET_SMS_TYPE _IOR(NWZ_SYSINFO_TYPE, 32, unsigned int *) +#define NWZ_SYSINFO_PUT_SMS_TYPE _IOW(NWZ_SYSINFO_TYPE, 33, unsigned int *) +#define NWZ_SYSINFO_GET_HCG_TYPE _IOR(NWZ_SYSINFO_TYPE, 34, unsigned int *) +#define NWZ_SYSINFO_PUT_HCG_TYPE _IOW(NWZ_SYSINFO_TYPE, 35, unsigned int *) +#define NWZ_SYSINFO_GET_RTC_TYPE _IOR(NWZ_SYSINFO_TYPE, 36, unsigned int *) +#define NWZ_SYSINFO_PUT_RTC_TYPE _IOW(NWZ_SYSINFO_TYPE, 37, unsigned int *) +#define NWZ_SYSINFO_GET_SDC_TYPE _IOR(NWZ_SYSINFO_TYPE, 38, unsigned int *) +#define NWZ_SYSINFO_PUT_SDC_TYPE _IOW(NWZ_SYSINFO_TYPE, 39, unsigned int *) +#define NWZ_SYSINFO_GET_SCG_TYPE _IOR(NWZ_SYSINFO_TYPE, 40, unsigned int *) +#define NWZ_SYSINFO_PUT_SCG_TYPE _IOW(NWZ_SYSINFO_TYPE, 41, unsigned int *) +#define NWZ_SYSINFO_GET_NFC_TYPE _IOR(NWZ_SYSINFO_TYPE, 42, unsigned int *) +#define NWZ_SYSINFO_PUT_NFC_TYPE _IOW(NWZ_SYSINFO_TYPE, 43, unsigned int *) + +#endif /* __NWZ_SYSINFO_H__ */ diff --git a/utils/nwztools/plattools/nwz_ts.h b/firmware/target/hosted/sonynwz/nwz_ts.h index 4528609ddc..4528609ddc 100644 --- a/utils/nwztools/plattools/nwz_ts.h +++ b/firmware/target/hosted/sonynwz/nwz_ts.h diff --git a/firmware/target/hosted/sonynwz/power-nwz.c b/firmware/target/hosted/sonynwz/power-nwz.c new file mode 100644 index 0000000000..a5b19d6ead --- /dev/null +++ b/firmware/target/hosted/sonynwz/power-nwz.c @@ -0,0 +1,208 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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 "system.h" +#include "power-nwz.h" +#include "button-target.h" +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <string.h> +#include <sys/reboot.h> + +static int power_fd = -1; /* file descriptor */ + +void power_init(void) +{ + power_fd = open(NWZ_POWER_DEV, O_RDWR); +} + +void power_close(void) +{ + close(power_fd); +} + +int nwz_power_get_status(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_STATUS, &status) < 0) + return -1; + return status; +} + +static int nwz_power_adval_to_mv(int adval, int ad_base) +{ + if(adval == -1) + return -1; + /* the AD base corresponds to the millivolt value if adval was 255 */ + return (adval * ad_base) / 255; +} + +int nwz_power_get_vbus_adval(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_VBUS_ADVAL, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_vbus_voltage(void) +{ + return nwz_power_adval_to_mv(nwz_power_get_vbus_adval(), NWZ_POWER_AD_BASE_VBUS); +} + +int nwz_power_get_vbus_limit(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_VBUS_LIMIT, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_charge_switch(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_CHARGE_SWITCH, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_charge_current(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_CHARGE_CURRENT, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_battery_gauge(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_BAT_GAUGE, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_battery_adval(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_BAT_ADVAL, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_battery_voltage(void) +{ + return nwz_power_adval_to_mv(nwz_power_get_battery_adval(), NWZ_POWER_AD_BASE_VBAT); +} + +int nwz_power_get_vbat_adval(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_VBAT_ADVAL, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_vbat_voltage(void) +{ + return nwz_power_adval_to_mv(nwz_power_get_vbat_adval(), NWZ_POWER_AD_BASE_VBAT); +} + +int nwz_power_get_sample_count(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_SAMPLE_COUNT, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_vsys_adval(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_VSYS_ADVAL, &status) < 0) + return -1; + return status; +} + +int nwz_power_get_vsys_voltage(void) +{ + return nwz_power_adval_to_mv(nwz_power_get_vsys_adval(), NWZ_POWER_AD_BASE_VSYS); +} + +int nwz_power_get_acc_charge_mode(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_GET_ACCESSARY_CHARGE_MODE, &status) < 0) + return -1; + return status; +} + +int nwz_power_is_fully_charged(void) +{ + int status; + if(ioctl(power_fd, NWZ_POWER_IS_FULLY_CHARGED, &status) < 0) + return -1; + return status; +} + +static int write_string_to_file(const char *file, const char *msg) +{ + int fd = open(file, O_WRONLY); + if(fd < 0) + return -1; + const int len = strlen(msg); + int res = write(fd, msg, len); + close(fd); + return res == len ? 0 : -1; +} + +int do_nwz_power_suspend(void) +{ + /* older devices use /proc/pm, while the new one use the standard sys file */ + if(write_string_to_file("/proc/pm", "S3") == 0) + return 0; + return write_string_to_file("/sys/power/state", "mem"); +} + +int nwz_power_suspend(void) +{ + int ret = do_nwz_power_suspend(); + /* the button driver tracks button status using events, but the kernel does + * not generate an event if a key is changed during suspend, so make sure we + * reload as much information as possible */ + nwz_button_reload_after_suspend(); + return ret; +} + +int nwz_power_shutdown(void) +{ + sync(); /* man page advises to sync to avoid data loss */ + return reboot(RB_POWER_OFF); +} + +int nwz_power_restart(void) +{ + sync(); /* man page advises to sync to avoid data loss */ + return reboot(RB_AUTOBOOT); +} diff --git a/utils/nwztools/plattools/nwz_power.h b/firmware/target/hosted/sonynwz/power-nwz.h index 7b325ce047..965013a35a 100644 --- a/utils/nwztools/plattools/nwz_power.h +++ b/firmware/target/hosted/sonynwz/power-nwz.h @@ -18,8 +18,10 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef __NWZ_POWER_H__ -#define __NWZ_POWER_H__ +#ifndef __POWER_NWZ_H__ +#define __POWER_NWZ_H__ + +#include "power.h" /** power */ @@ -112,4 +114,42 @@ #define ICX_PMINFO_FACTOR_KEY_PAD 0x00001000 /* keypad */ #define ICX_PMINFO_FACTOR_KEY_CODE 0x00000FFF /* keycode */ -#endif /* __NWZ_POWER_H__ */ +void power_init(void); +/* get power status (return -1 on error, bitmap on success) */ +int nwz_power_get_status(void); +/* get vbus adval (or -1 on error) */ +int nwz_power_get_vbus_adval(void); +/* get vbus voltage in mV (or -1 on error) */ +int nwz_power_get_vbus_voltage(void); +/* get vbus current limit (or -1 on error) */ +int nwz_power_get_vbus_limit(void); +/* get charge switch (or -1 on error) */ +int nwz_power_get_charge_switch(void); +/* get charge current (or -1 on error) */ +int nwz_power_get_charge_current(void); +/* get battery gauge (or -1 on error) */ +int nwz_power_get_battery_gauge(void); +/* get battery adval (or -1 on error) */ +int nwz_power_get_battery_adval(void); +/* get battery voltage in mV (or -1 on error) */ +int nwz_power_get_battery_voltage(void); +/* get vbat adval (or -1 on error) */ +int nwz_power_get_vbat_adval(void); +/* get vbat voltage (or -1 on error) */ +int nwz_power_get_vbat_voltage(void); +/* get sample count (or -1 on error) */ +int nwz_power_get_sample_count(void); +/* get vsys adval (or -1 on error) */ +int nwz_power_get_vsys_adval(void); +/* get vsys voltage in mV (or -1 on error) */ +int nwz_power_get_vsys_voltage(void); +/* get accessory charge mode */ +int nwz_power_get_acc_charge_mode(void); +/* is battery fully charged? (or -1 on error) */ +int nwz_power_is_fully_charged(void); +/* change power state (-1 on error, 0 otherwise)*/ +int nwz_power_suspend(void); +int nwz_power_shutdown(void); +int nwz_power_restart(void); + +#endif /* __POWER_NWZ_H__ */ diff --git a/firmware/target/hosted/sonynwz/powermgmt-nwz.c b/firmware/target/hosted/sonynwz/powermgmt-nwz.c new file mode 100644 index 0000000000..ce5f251570 --- /dev/null +++ b/firmware/target/hosted/sonynwz/powermgmt-nwz.c @@ -0,0 +1,69 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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 "powermgmt.h" +#include "power.h" +#include "power-nwz.h" + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3470 +}; + +/* the OF shuts down at this voltage */ +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3450 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3450, 3502, 3550, 3587, 3623, 3669, 3742, 3836, 3926, 4026, 4200 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short const percent_to_volt_charge[11] = +{ + 3450, 3670, 3721, 3751, 3782, 3821, 3876, 3941, 4034, 4125, 4200 +}; + +unsigned int power_input_status(void) +{ + unsigned pwr = 0; + int sts = nwz_power_get_status(); + if(sts & NWZ_POWER_STATUS_VBUS_DET) + pwr |= POWER_INPUT_USB_CHARGER; + if(sts & NWZ_POWER_STATUS_AC_DET) + pwr |= POWER_INPUT_MAIN_CHARGER; + return pwr; +} + +int _battery_voltage(void) +{ + /* the raw voltage is unstable on some devices, so use the average provided + * by the driver */ + return nwz_power_get_battery_voltage(); +} + +bool charging_state(void) +{ + return (nwz_power_get_status() & NWZ_POWER_STATUS_CHARGE_STATUS) == + NWZ_POWER_STATUS_CHARGE_STATUS_CHARGING; +} diff --git a/firmware/target/hosted/sonynwz/sonynwz.make b/firmware/target/hosted/sonynwz/sonynwz.make new file mode 100644 index 0000000000..6c58e1a709 --- /dev/null +++ b/firmware/target/hosted/sonynwz/sonynwz.make @@ -0,0 +1,82 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +INCLUDES += -I$(FIRMDIR)/include -I$(FIRMDIR)/export $(TARGET_INC) -I$(BUILDDIR) -I$(APPSDIR) + +SIMFLAGS += $(INCLUDES) $(DEFINES) -DHAVE_CONFIG_H $(GCCOPTS) + +# bootloader build is sligtly different +ifneq (,$(findstring bootloader,$(APPSDIR))) + +SRC += $(call preprocess, $(APPSDIR)/SOURCES) +CLEANOBJS += $(BUILDDIR)/bootloader.* + +endif #bootloader + +.SECONDEXPANSION: # $$(OBJ) is not populated until after this + +# bootloader build is sligtly different +ifneq (,$(findstring bootloader,$(APPSDIR))) + +# We install a second font along the bootloader because sysfont is too small +# for our purpose +BL_FONT = $(ROOTDIR)/fonts/27-Adobe-Helvetica.bdf + +# Limits for the bootloader sysfont: ASCII +BL_MAXCHAR = 127 + +# Function that adds a single file to a tar and explicitely set the name +# in the archive (which can be completely different from the original filename) +# their devices +# arguments: +# $(1) = tar file +# $(2) = archive file name +# $(3) = file to add +tar_add_file = \ + tar -Prf $(1) --transform="s|.*|$(strip $(2))|" $(3) + +$(BUILDDIR)/bootloader.fnt: $(BL_FONT) $(TOOLS) + $(call PRINTS,CONVBDF $(subst $(ROOTDIR)/,,$<))$(TOOLSDIR)/convbdf -l $(MAXCHAR) -f -o $@ $< + +$(BUILDDIR)/bootloader.elf : $$(OBJ) $(FIRMLIB) $(CORE_LIBS) + $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ + -L$(BUILDDIR)/firmware -lfirmware \ + -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \ + $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,--gc-sections -Wl,-Map,$(BUILDDIR)/bootloader.map + +$(BUILDDIR)/$(BINARY): $(BUILDDIR)/bootloader.elf $(BUILDDIR)/bootloader.fnt +# NOTE: the install script will call a command like +# tar -C $(ROOTFS_MOUNT_POINT) -f bootloader.tar +# thus the names in the archive must be of the form ./absolute/path +# +# NOTE 2: Sony uses unusual user IDs (500 on somes devices, 1002 on others) +# so make sure the files are readable/executable by anyone + $(SILENT)rm -rf $(BUILDDIR)/bootloader.tar + $(SILENT)$(call tar_add_file, $(BUILDDIR)/bootloader.tar,\ + ./usr/local/bin/SpiderApp, \ + $(BUILDDIR)/bootloader.elf) + $(SILENT)$(call tar_add_file, $(BUILDDIR)/bootloader.tar, \ + ./usr/local/share/rockbox/bootloader.fnt, \ + $(BUILDDIR)/bootloader.fnt) + $(call PRINTS,SCRAMBLE $(notdir $@))$(MKFIRMWARE) $(BUILDDIR)/bootloader.tar $@; + +else # bootloader + +$(BUILDDIR)/rockbox.elf : $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) + $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ + -L$(BUILDDIR)/firmware -lfirmware \ + -L$(RBCODEC_BLD)/codecs $(call a2lnk, $(VOICESPEEXLIB)) \ + -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \ + $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map + +$(BUILDDIR)/rockbox.sony : $(BUILDDIR)/rockbox.elf + $(call PRINTS,OC $(@F))$(call objcopy,$^,$@) + +endif # bootloader + diff --git a/firmware/target/hosted/sonynwz/system-nwz.c b/firmware/target/hosted/sonynwz/system-nwz.c new file mode 100644 index 0000000000..c804c5ab66 --- /dev/null +++ b/firmware/target/hosted/sonynwz/system-nwz.c @@ -0,0 +1,204 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * 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 <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <ucontext.h> +#include <string.h> +#include "system.h" +#include "lcd.h" +#include "font.h" +#include "logf.h" +#include "system.h" +#include "backlight-target.h" +#include "button.h" +#include "adc.h" +#include "power.h" +#include "power-nwz.h" +#include <backtrace.h> +#include <stdio.h> + +static const char **kern_mod_list; + +void power_off(void) +{ + exit(0); +} + +static void compute_kern_mod_list(void) +{ + /* create empty list */ + kern_mod_list = malloc(sizeof(const char **)); + kern_mod_list[0] = NULL; + /* read from proc file system */ + FILE *f = fopen("/proc/modules", "r"); + if(f == NULL) + { + printf("Cannot open /proc/modules"); + return; + } + for(int i = 0;; i++) + { + /* the last entry of the list points to NULL so getline() will allocate + * some memory */ + size_t n; + if(getline((char **)&kern_mod_list[i], &n, f) < 0) + { + /* make sure last entry is NULL and stop */ + kern_mod_list[i] = NULL; + break; + } + /* grow array */ + kern_mod_list = realloc(kern_mod_list, (i + 2) * sizeof(const char **)); + /* and fill last entry with NULL */ + kern_mod_list[i + 1] = NULL; + /* parse line to only keep module name */ + char *p = strchr(kern_mod_list[i], ' '); + if(p != NULL) + *p = 0; /* stop at first blank */ + } + fclose(f); +} + +static void print_kern_mod_list(void) +{ + printf("Kernel modules:\n"); + const char **p = kern_mod_list; + while(*p) + printf(" %s\n", *p++); +} + +/* to make thread-internal.h happy */ +uintptr_t *stackbegin; +uintptr_t *stackend; + +static void nwz_sig_handler(int sig, siginfo_t *siginfo, void *context) +{ + /* safe guard variable - we call backtrace() only on first + * UIE call. This prevent endless loop if backtrace() touches + * memory regions which cause abort + */ + static bool triggered = false; + + lcd_set_backdrop(NULL); + lcd_set_drawmode(DRMODE_SOLID); + lcd_set_foreground(LCD_BLACK); + lcd_set_background(LCD_WHITE); + unsigned line = 0; + + lcd_setfont(FONT_SYSFIXED); + lcd_set_viewport(NULL); + lcd_clear_display(); + + /* get context info */ + ucontext_t *uc = (ucontext_t *)context; + unsigned long pc = uc->uc_mcontext.arm_pc; + unsigned long sp = uc->uc_mcontext.arm_sp; + + lcd_putsf(0, line++, "%s at %08x", strsignal(sig), pc); + + if(sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS || sig == SIGTRAP) + lcd_putsf(0, line++, "address 0x%08x", siginfo->si_addr); + + if(!triggered) + { + triggered = true; + rb_backtrace(pc, sp, &line); + } + +#ifdef ROCKBOX_HAS_LOGF + lcd_putsf(0, line++, "logf:"); + logf_panic_dump(&line); +#endif + + lcd_update(); + + system_exception_wait(); /* If this returns, try to reboot */ + system_reboot(); + while (1); /* halt */ +} + +void system_init(void) +{ + int *s; + /* fake stack, to make thread-internal.h happy */ + stackbegin = stackend = (uintptr_t*)&s; + /* catch some signals for easier debugging */ + struct sigaction sa; + sigfillset(&sa.sa_mask); + sa.sa_flags = SA_SIGINFO; + sa.sa_sigaction = &nwz_sig_handler; + sigaction(SIGILL, &sa, NULL); + sigaction(SIGABRT, &sa, NULL); + sigaction(SIGFPE, &sa, NULL); + sigaction(SIGSEGV, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGBUS, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + compute_kern_mod_list(); + print_kern_mod_list(); + /* some init not done on hosted targets */ + adc_init(); + power_init(); +} + + +void system_reboot(void) +{ + power_off(); +} + +void system_exception_wait(void) +{ + backlight_hw_on(); + backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING); + /* wait until button press and release */ + while(button_read_device() != 0) {} + while(button_read_device() == 0) {} + while(button_read_device() != 0) {} + while(button_read_device() == 0) {} +} + +int hostfs_init(void) +{ + return 0; +} + +int hostfs_flush(void) +{ + sync(); + return 0; +} + +const char **nwz_get_kernel_module_list(void) +{ + return kern_mod_list; +} + +bool nwz_is_kernel_module_loaded(const char *name) +{ + const char **p = kern_mod_list; + while(*p) + if(strcmp(*p++, name) == 0) + return true; + return false; +} diff --git a/firmware/target/hosted/sonynwz/system-target.h b/firmware/target/hosted/sonynwz/system-target.h new file mode 100644 index 0000000000..0e3ed5f5ce --- /dev/null +++ b/firmware/target/hosted/sonynwz/system-target.h @@ -0,0 +1,34 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 by Amaury Pouly + * + * 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. + * + ****************************************************************************/ +#ifndef __SYSTEM_TARGET_H__ +#define __SYSTEM_TARGET_H__ + +#include "kernel-unix.h" +#include "system-hosted.h" + +#define NEED_GENERIC_BYTESWAPS + +/* get list of loaded kernel modules (computed once at init time), list is NULL + * terminated */ +const char **nwz_get_kernel_module_list(void); +bool nwz_is_kernel_module_loaded(const char *name); + +#endif /* __SYSTEM_TARGET_H__ */ diff --git a/lib/unwarminder/SOURCES b/lib/unwarminder/SOURCES index b2e5e3e4b9..87c7d69010 100644 --- a/lib/unwarminder/SOURCES +++ b/lib/unwarminder/SOURCES @@ -1,4 +1,4 @@ -backtrace.c +backtrace-unwarminder.c get_sp.S unwarm_arm.c unwarm.c diff --git a/lib/unwarminder/backtrace.c b/lib/unwarminder/backtrace-unwarminder.c index 683d2fdcc1..7808a1f2d7 100644 --- a/lib/unwarminder/backtrace.c +++ b/lib/unwarminder/backtrace-unwarminder.c @@ -106,7 +106,7 @@ Boolean CliInvalidateW(const Int32 a) return TRUE; } -void backtrace(int pcAddr, int spAddr, unsigned *line) +void rb_backtrace(int pcAddr, int spAddr, unsigned *line) { lcd_putsf(0, (*line)++, "pc:%08x sp:%08x", pcAddr, spAddr); lcd_update(); diff --git a/lib/unwarminder/backtrace.h b/lib/unwarminder/backtrace-unwarminder.h index 3bf3eb5aac..e08f725aaf 100644 --- a/lib/unwarminder/backtrace.h +++ b/lib/unwarminder/backtrace-unwarminder.h @@ -49,7 +49,7 @@ CliStack; extern const UnwindCallbacks cliCallbacks; -void backtrace(int pcAddr, int spAddr, unsigned *line); +void rb_backtrace(int pcAddr, int spAddr, unsigned *line); #endif diff --git a/lib/unwarminder/unwarminder.make b/lib/unwarminder/unwarminder.make index 5093156f54..563c5cadab 100644 --- a/lib/unwarminder/unwarminder.make +++ b/lib/unwarminder/unwarminder.make @@ -16,6 +16,7 @@ UNWARMLIB = $(BUILDDIR)/lib/libunwarminder.a CORE_LIBS += $(UNWARMLIB) INCLUDES += -I$(UNWARMLIB_DIR) +DEFINES += -DBACKTRACE_UNWARMINDER $(UNWARMLIB): $(UNWARMLIB_OBJ) $(SILENT)$(shell rm -f $@) diff --git a/rbutil/mknwzboot/Makefile b/rbutil/mknwzboot/Makefile new file mode 100644 index 0000000000..9530ac369e --- /dev/null +++ b/rbutil/mknwzboot/Makefile @@ -0,0 +1,35 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ + +# We use the SB code available in the Rockbox utils/sbtools directory +UPGTOOLS_DIR=../../utils/nwztools/upgtools/ +CFLAGS += -I$(UPGTOOLS_DIR) -Wall +# std=gnu99 is required by MinGW on Windows (c99 is sufficient for Linux / MXE) +CFLAGS += -std=gnu99 -g -O3 +# dependencies +# FIXME make it work for windows and maybe embed crypto++ +LDOPTS += `pkg-config --libs libcrypto++` + +OUTPUT = mknwzboot + +# inputs for lib +UPGTOOLS_SOURCES = misc.c upg.c fwp.c mg.cpp md5.cpp +LIBSOURCES := mknwzboot.c install_script.c \ + $(addprefix $(UPGTOOLS_DIR),$(UPGTOOLS_SOURCES)) +# inputs for binary only +SOURCES := $(LIBSOURCES) main.c +# dependencies for binary +EXTRADEPS := + +include ../libtools.make + +install_script.c install_script.h: install_script.sh $(BIN2C) + $(BIN2C) install_script.sh install_script + +# explicit dependencies on install_script.{c,h} and mknwzboot.h +$(OBJDIR)mknwzboot.o: install_script.h install_script.c mknwzboot.h +$(OBJDIR)main.o: install_script.h install_script.c main.c mknwzboot.h diff --git a/rbutil/mknwzboot/install_script.sh b/rbutil/mknwzboot/install_script.sh new file mode 100644 index 0000000000..18296d257e --- /dev/null +++ b/rbutil/mknwzboot/install_script.sh @@ -0,0 +1,142 @@ +#!/bin/sh + +# The updater script on the NWZ has a major bug/feature: +# it does NOT clear the update flag if the update scrit fails +# thus causing a update/reboot loop and a bricked device +# always clear to make sure we don't end up being screwed +nvpflag fup 0xFFFFFFFF + +# go to /tmp +cd /tmp + +# get content partition path +CONTENTS="/contents" +CONTENTS_PART=`mount | grep contents | awk '{ print $1 }'` + +lcdmsg -c -f /usr/local/bin/font_08x12.bmp -l 0,3 "Contents partition:\n$CONTENTS_PART" + +# We need to remount the contents partition in read-write mode be able to +# write something on it +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,6 "Remount $CONTENTS rw" +mount -o remount,rw $CONTENTS_PART $CONTENTS +if [ "$?" != 0 ]; then + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: remount failed" + sleep 3 + exit 0 +fi + +# redirect all output to a log file +exec > "$CONTENTS/install_dualboot_log.txt" 2>&1 + +# import constants +. /install_script/constant.txt +_UPDATE_FN_=`nvpstr ufn` +ROOTFS_TMP_DIR=/tmp/rootfs +SPIDERAPP_PATH=$ROOTFS_TMP_DIR/usr/local/bin/SpiderApp + +# mount root partition +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,7 "Mount root filesystem" +mkdir $ROOTFS_TMP_DIR +if [ "$?" != 0 ]; then + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: mkdir failed" + sleep 3 + exit 0 +fi + +# If there is an ext4 mounter, try it. Otherwise or on failure, try ext3 and +# then ext2. +# NOTE some platforms probably use an mtd and this might need some fixing +if [ -e /usr/local/bin/icx_mount.ext4 ]; then + /usr/local/bin/icx_mount.ext4 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR +else + false +fi +if [ "$?" != 0 ]; then + mount -t ext3 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR +fi +if [ "$?" != 0 ]; then + mount -t ext2 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR +fi +if [ "$?" != 0 ]; then + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: mount failed" + sleep 3 + exit 0 +fi + +# rename the previous main application unless there is already a copy +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,8 "Backup OF" +if [ ! -e $SPIDERAPP_PATH.of ]; then + mv $SPIDERAPP_PATH $SPIDERAPP_PATH.of +fi + +# extract our payload: the second file in the upgrade is a tar file +# the files in the archive have paths of the form ./absolute/path and we extract +# it at the rootfs mount it, so it can create/overwrite any file +# +# we need a small trick here: we want to pipe directly the output of the decryption +# tool to tar, to avoid using space in /tmp/ or on the user partition +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,9 "Install rockbox" +FIFO_FILE=/tmp/rb.fifo +mkfifo $FIFO_FILE +if [ "$?" != 0 ]; then + umount "$ROOTFS_TMP_DIR" + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot create fifo" + sleep 3 + exit 0 +fi +fwpchk -f /contents/$_UPDATE_FN_.UPG -c -1 $FIFO_FILE & +#tar -tvf $FIFO_FILE +tar -C $ROOTFS_TMP_DIR -xvf $FIFO_FILE +if [ "$?" != 0 ]; then + umount "$ROOTFS_TMP_DIR" + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: extraction failed" + sleep 3 + exit 0 +fi +# wait for fwpchk +wait +if [ "$?" != 0 ]; then + umount "$ROOTFS_TMP_DIR" + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: no file to extract" + sleep 3 + exit 0 +fi + +# create a symlink from /.rockbox to /contents/.rockbox (see dualboot code +# for why) +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,10 "Create rockbox symlink" +rm -f "$ROOTFS_TMP_DIR/.rockbox" +ln -s "$CONTENTS/.rockbox" "$ROOTFS_TMP_DIR/.rockbox" +if [ "$?" != 0 ]; then + umount "$ROOTFS_TMP_DIR" + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: cannot create rockbox symlink" + sleep 3 + exit 0 +fi + +# unmount root partition +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,11 "Unmount root filesystem" +sync +if [ "$?" != 0 ]; then + umount "$ROOTFS_TMP_DIR" + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: sync failed" + sleep 3 + exit 0 +fi + +umount $ROOTFS_TMP_DIR +if [ "$?" != 0 ]; then + lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: umount failed" + sleep 3 + exit 0 +fi + +# Success screen +lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "Rebooting in 3 seconds." +sleep 3 +sync + +echo "Installation successful" +# finish +exit 0 + diff --git a/rbutil/mknwzboot/main.c b/rbutil/mknwzboot/main.c new file mode 100644 index 0000000000..a36c24eaf5 --- /dev/null +++ b/rbutil/mknwzboot/main.c @@ -0,0 +1,105 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * 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 <getopt.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "mknwzboot.h" + +static void usage(void) +{ + printf("Usage: mknwzboot [options | file]...\n"); + printf("Options:\n"); + printf(" -h/--help Display this message\n"); + printf(" -o <file> Set output file\n"); + printf(" -b <file> Set boot file\n"); + printf(" -d/--debug Enable debug output\n"); + printf(" -x Dump device informations\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + char *outfile = NULL; + char *bootfile = NULL; + bool debug = false; + + if(argc == 1) + usage(); + + while(1) + { + static struct option long_options[] = + { + {"help", no_argument, 0, 'h'}, + {"out-file", required_argument, 0, 'o'}, + {"boot-file", required_argument, 0, 'b'}, + {"debug", no_argument, 0, 'd'}, + {"dev-info", no_argument, 0, 'x'}, + {0, 0, 0, 0} + }; + + int c = getopt_long(argc, argv, "ho:b:dx", long_options, NULL); + if(c == -1) + break; + switch(c) + { + case 'd': + debug = true; + break; + case 'h': + usage(); + break; + case 'o': + outfile = optarg; + break; + case 'b': + bootfile = optarg; + break; + case 'x': + dump_nwz_dev_info(""); + break; + default: + abort(); + } + } + + if(!outfile) + { + printf("You must specify an output file\n"); + return 1; + } + if(!bootfile) + { + printf("You must specify a boot file\n"); + return 1; + } + if(optind != argc) + { + printf("Extra arguments on command line\n"); + return 1; + } + + int err = mknwzboot(bootfile, outfile, debug); + printf("Result: %d\n", err); + return err; +} diff --git a/rbutil/mknwzboot/mknwzboot.c b/rbutil/mknwzboot/mknwzboot.c new file mode 100644 index 0000000000..1fc105ae48 --- /dev/null +++ b/rbutil/mknwzboot/mknwzboot.c @@ -0,0 +1,230 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 by Amaury Pouly + * + * 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 <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <ctype.h> +#include "mknwzboot.h" +#include "upg.h" + +#include "install_script.h" + +struct nwz_model_desc_t +{ + /* Descriptive name of this model */ + const char *model_name; + /* Model name used in the Rockbox header in ".sansa" files - these match the + -add parameter to the "scramble" tool */ + const char *rb_model_name; + /* Model number used to initialise the checksum in the Rockbox header in + ".sansa" files - these are the same as MODEL_NUMBER in config-target.h */ + const int rb_model_num; + /* Codename used in upgtool */ + const char *codename; +}; + +static const struct nwz_model_desc_t nwz_models[] = +{ + { "Sony NWZ-E450 Series", "e450", 100, "nwz-e450" }, + { "Sony NWZ-E460 Series", "e460", 101, "nwz-e460" }, + { "Sony NWZ-E470 Series", "e470", 103, "nwz-e470" }, + { "Sony NWZ-E580 Series", "e580", 102, "nwz-e580" }, + { "Sony NWZ-A10 Series", "a10", 104, "nwz-a10" }, +}; + +#define NR_NWZ_MODELS (sizeof(nwz_models) / sizeof(nwz_models[0])) + +void dump_nwz_dev_info(const char *prefix) +{ + printf("%smknwzboot models:\n", prefix); + for(int i = 0; i < NR_NWZ_MODELS; i++) + { + printf("%s %s: rb_model=%s rb_num=%d codename=%s\n", prefix, + nwz_models[i].model_name, nwz_models[i].rb_model_name, + nwz_models[i].rb_model_num, nwz_models[i].codename); + } +} + +/* read a file to a buffer */ +static void *read_file(const char *file, size_t *size) +{ + FILE *f = fopen(file, "rb"); + if(f == NULL) + { + printf("[ERR] Cannot open file '%s' for reading: %m\n", file); + return NULL; + } + fseek(f, 0, SEEK_END); + *size = ftell(f); + fseek(f, 0, SEEK_SET); + void *buffer = malloc(*size); + if(fread(buffer, *size, 1, f) != 1) + { + free(buffer); + fclose(f); + printf("[ERR] Cannot read file '%s': %m\n", file); + return NULL; + } + fclose(f); + return buffer; +} + +/* write a file from a buffer */ +static bool write_file(const char *file, void *buffer, size_t size) +{ + FILE *f = fopen(file, "wb"); + if(f == NULL) + { + printf("[ERR] Cannot open file '%s' for writing: %m\n", file); + return false; + } + if(fwrite(buffer, size, 1, f) != 1) + { + fclose(f); + printf("[ERR] Cannot write file '%s': %m\n", file); + return false; + } + fclose(f); + return true; +} + +static unsigned int be2int(unsigned char* buf) +{ + return ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); +} + +static int find_model(uint8_t *boot, size_t boot_size) +{ + if(boot_size < 8) + { + printf("[ERR] Boot file is too small to be valid\n"); + return -1; + } + /* find model by comparing magic scramble value */ + int model = 0; + for(; model < NR_NWZ_MODELS; model++) + if(memcmp(boot + 4, nwz_models[model].rb_model_name, 4) == 0) + break; + if(model == NR_NWZ_MODELS) + { + printf("[ERR] This player is not supported: %.4s\n", boot + 4); + return -1; + } + printf("[INFO] Bootloader file for %s\n", nwz_models[model].model_name); + /* verify checksum */ + uint32_t sum = nwz_models[model].rb_model_num; + for(int i = 8; i < boot_size; i++) + sum += boot[i]; + if(sum != be2int(boot)) + { + printf("[ERR] Checksum mismatch\n"); + return -1; + } + return model; +} + +static bool get_model_keysig(int model, char key[NWZ_KEY_SIZE], char sig[NWZ_SIG_SIZE]) +{ + const char *codename = nwz_models[model].codename; + for(int i = 0; g_model_list[i].model; i++) + if(strcmp(g_model_list[i].model, codename) == 0) + { + if(decrypt_keysig(g_model_list[i].kas, key, sig) == 0) + return true; + printf("[ERR] Cannot decrypt kas '%s'\n", g_model_list[i].kas); + return false; + } + printf("[ERR] Codename '%s' matches to entry in upg database\n", codename); + return false; +} + +void nwz_printf(void *u, bool err, color_t c, const char *f, ...) +{ + (void)err; + (void)c; + bool *debug = u; + va_list args; + va_start(args, f); + if(err || *debug) + vprintf(f, args); + va_end(args); +} + +static void *memdup(void *data, size_t size) +{ + void *buf = malloc(size); + memcpy(buf, data, size); + return buf; +} + +int mknwzboot(const char *bootfile, const char *outfile, bool debug) +{ + size_t boot_size; + uint8_t *boot = read_file(bootfile, &boot_size); + if(boot == NULL) + { + printf("[ERR] Cannot open boot file\n"); + return 1; + } + /* check that it is a valid scrambled file */ + int model = find_model(boot, boot_size); + if(model < 0) + { + free(boot); + printf("[ERR] Invalid boot file\n"); + return 2; + } + /* find keys */ + char key[NWZ_KEY_SIZE]; + char sig[NWZ_SIG_SIZE]; + if(!get_model_keysig(model, key, sig)) + { + printf("[ERR][INTERNAL] Cannot get keys for model\n"); + return 3; + } + /* create the upg file */ + struct upg_file_t *upg = upg_new(); + /* first file is the install script: we have to copy data because upg_free() + * will free it */ + upg_append(upg, memdup(install_script, LEN_install_script), LEN_install_script); + /* second file is the bootloader content (expected to be a tar file): we have + * to copy data because upg_free() will free it */ + upg_append(upg, memdup(boot + 8, boot_size - 8), boot_size - 8); + free(boot); + /* write file to buffer */ + size_t upg_size; + void *upg_buf = upg_write_memory(upg, key, sig, &upg_size, &debug, nwz_printf); + upg_free(upg); + if(upg_buf == NULL) + { + printf("[ERR] Cannot create UPG file\n"); + return 4; + } + if(!write_file(outfile, upg_buf, upg_size)) + { + free(upg_buf); + printf("[ERR] Cannpt write UPG file\n"); + return 5; + } + free(upg_buf); + return 0; +} diff --git a/utils/nwztools/plattools/nwz_plattools.h b/rbutil/mknwzboot/mknwzboot.h index 56d584ce30..f46dd75d5c 100644 --- a/utils/nwztools/plattools/nwz_plattools.h +++ b/rbutil/mknwzboot/mknwzboot.h @@ -9,9 +9,6 @@ * * Copyright (C) 2011 by Amaury Pouly * - * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing - * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach - * * 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 @@ -21,17 +18,24 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef __NWZ_PLATTOOLS_H__ -#define __NWZ_PLATTOOLS_H__ -/** Platform tools can be either built individually, or be included in a - * single build (or even dualboot code) for easy testing. Thus, each tool must - * use the following macros to support all scenarios. */ +#ifndef MKIMXBOOT_H +#define MKIMXBOOT_H -#ifdef NWZ_EMBED_TOOLS -#define NWZ_TOOL_MAIN(tool) tool##_main -#else -#define NWZ_TOOL_MAIN(tool) main +#include <stdbool.h> +#include <stdint.h> +#include <sys/types.h> + +#ifdef __cplusplus +extern "C" { +#endif + +void dump_nwz_dev_info(const char *prefix); +/* return 0 on success */ +int mknwzboot(const char *bootfile, const char *outfile, bool debug); + +#ifdef __cplusplus +} +#endif #endif -#endif /* __NWZ_PLATTOOLS_H__ */ diff --git a/tools/configure b/tools/configure index fd86d8a76d..3b481e9fa8 100755 --- a/tools/configure +++ b/tools/configure @@ -706,12 +706,15 @@ pandoracc () { GCCOPTS="$GCCOPTS -ffast-math -fsingle-precision-constant" } -ypr0cc () { - +arm1176jzlinuxcc () { GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib//` + # Although the ARM1176JZ-S supports unaligned accesses, those seems to disabled + # by the kernel. Since GCC emits unaligned accesses by default on ARMv6, we + # need to disable that + GCCOPTS="$GCCOPTS -mcpu=arm1176jz-s -mno-unaligned-access -mfloat-abi=softfp" GCCOPTIMIZE='' LDOPTS="-lasound -lpthread -lm -ldl -lrt $LDOPTS" - GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs" + GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs" # warn about undefined symbols in shared libraries SHARED_LDFLAG="-shared" SHARED_CFLAGS='' endian="little" @@ -721,8 +724,18 @@ ypr0cc () { GCCOPTS="$GCCOPTS -D_GNU_SOURCE=1 -U_FORTIFY_SOURCE -D_REENTRANT" # Set up compiler - gccchoice="4.4.6" - prefixtools "arm-ypr0-linux-gnueabi-" + gccchoice="4.9.4" + prefixtools "arm-rockbox-linux-gnueabi-" +} + +ypr0cc () { + arm1176jzlinuxcc + app_type="ypr0" +} + +sonynwzcc () { + arm1176jzlinuxcc + app_type="sonynwz" } androidcc () { @@ -1493,11 +1506,14 @@ cat <<EOF 202) Nokia N8xx 211) MA9C ==Sony== 203) Nokia N900 212) MA8 220) NWZ-E370/E380 series 204) Pandora 213) MA8C 221) NWZ-E360 series - 205) Samsung YP-R0 - 206) Android MIPS ==IHIFI== ==iBasso== - 207) Android x86 230) 760 232) DX50 - 208) Samsung YP-R1 231) 960 233) DX90 - + 205) Samsung YP-R0 222) NWZ-E450 series + 206) Android MIPS ==IHIFI== 223) NWZ-E460 series + 207) Android x86 230) 760 224) NWZ-E470 series + 208) Samsung YP-R1 231) 960 225) NWZ-E580 series + 226) NWZ-A10 series + ==iBasso== + 232) DX50 + 233) DX90 EOF @@ -3853,6 +3869,121 @@ fi arm926ejscc ;; + 222|sonynwze450) + application="yes" + target_id=96 + modelname="sonynwze450" + target="SONY_NWZE450" + memory=16 + bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" + bmp2rb_native="$rootdir/tools/bmp2rb -f 4" + tool="cp" + output="rockbox.sony" + boottool="$rootdir/tools/scramble -add=e450" + bootoutput="bootloader-nwze450.sony" + appextra="gui:recorder" + plugins="" + swcodec="yes" + toolset=$genericbitmaptools + t_cpu="hosted" + t_manufacturer="sonynwz" + t_model="nwze450" + uname=`uname` + sonynwzcc + ;; + + 223|sonynwze460) + application="yes" + target_id=97 + modelname="sonynwze460" + target="SONY_NWZE460" + memory=16 + bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" + bmp2rb_native="$rootdir/tools/bmp2rb -f 4" + tool="cp" + output="rockbox.sony" + boottool="$rootdir/tools/scramble -add=e460" + bootoutput="bootloader-nwze460.sony" + appextra="gui:recorder" + plugins="yes" + swcodec="yes" + toolset=$genericbitmaptools + t_cpu="hosted" + t_manufacturer="sonynwz" + t_model="nwze460" + uname=`uname` + sonynwzcc + ;; + + 224|sonynwze470) + application="yes" + target_id=100 + modelname="sonynwze470" + target="SONY_NWZE470" + memory=16 + bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" + bmp2rb_native="$rootdir/tools/bmp2rb -f 4" + tool="cp" + output="rockbox.sony" + boottool="$rootdir/tools/scramble -add=e470" + bootoutput="bootloader-nwze470.sony" + appextra="gui:recorder" + plugins="" + swcodec="yes" + toolset=$genericbitmaptools + t_cpu="hosted" + t_manufacturer="sonynwz" + t_model="nwze470" + uname=`uname` + sonynwzcc + ;; + + 225|sonynwze580) + application="yes" + target_id=98 + modelname="sonynwze580" + target="SONY_NWZE580" + memory=16 + bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" + bmp2rb_native="$rootdir/tools/bmp2rb -f 4" + tool="cp" + output="rockbox.sony" + boottool="$rootdir/tools/scramble -add=e580" + bootoutput="bootloader-nwze580.sony" + appextra="gui:recorder" + plugins="" + swcodec="yes" + toolset=$genericbitmaptools + t_cpu="hosted" + t_manufacturer="sonynwz" + t_model="nwze580" + uname=`uname` + sonynwzcc + ;; + + 226|sonynwza10) + application="yes" + target_id=101 + modelname="sonynwza10" + target="SONY_NWZA10" + memory=16 + bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" + bmp2rb_native="$rootdir/tools/bmp2rb -f 4" + tool="cp" + output="rockbox.sony" + boottool="$rootdir/tools/scramble -add=a10" + bootoutput="bootloader-nwza10.sony" + appextra="gui:recorder" + plugins="" + swcodec="yes" + toolset=$genericbitmaptools + t_cpu="hosted" + t_manufacturer="sonynwz" + t_model="nwza10" + uname=`uname` + sonynwzcc + ;; + 230|ihifi760) target_id=92 modelname="ihifi760" diff --git a/tools/root.make b/tools/root.make index c9f4a2eb65..b5bd0e8096 100644 --- a/tools/root.make +++ b/tools/root.make @@ -73,7 +73,10 @@ ifeq (,$(findstring checkwps,$(APP_TYPE))) include $(FIRMDIR)/firmware.make include $(ROOTDIR)/apps/bitmaps/bitmaps.make ifeq (arch_arm,$(ARCH)) - include $(ROOTDIR)/lib/unwarminder/unwarminder.make + # some targets don't use the unwarminder because they have the glibc backtrace + ifeq (,$(filter sonynwz,$(APP_TYPE))) + include $(ROOTDIR)/lib/unwarminder/unwarminder.make + endif endif ifeq (,$(findstring bootloader,$(APPSDIR))) include $(ROOTDIR)/lib/skin_parser/skin_parser.make @@ -98,7 +101,11 @@ ifeq (,$(findstring bootloader,$(APPSDIR))) endif ifneq (,$(findstring bootloader,$(APPSDIR))) - include $(APPSDIR)/bootloader.make + ifneq (,$(findstring sonynwz,$(APP_TYPE))) + include $(ROOTDIR)/firmware/target/hosted/sonynwz/sonynwz.make + else + include $(APPSDIR)/bootloader.make + endif else ifneq (,$(findstring bootbox,$(APPSDIR))) include $(APPSDIR)/bootbox.make else ifneq (,$(findstring checkwps,$(APP_TYPE))) @@ -132,6 +139,10 @@ else # core include $(ROOTDIR)/firmware/target/hosted/samsungypr/ypr1/ypr1.make endif + ifneq (,$(findstring sonynwz,$(APP_TYPE))) + include $(ROOTDIR)/firmware/target/hosted/sonynwz/sonynwz.make + endif + ifneq (,$(findstring android_ndk, $(APP_TYPE))) include $(ROOTDIR)/firmware/target/hosted/ibasso/android_ndk.make else diff --git a/tools/scramble.c b/tools/scramble.c index 5378be2853..8c5230cc3e 100644 --- a/tools/scramble.c +++ b/tools/scramble.c @@ -129,7 +129,8 @@ void usage(void) "\t m2v4, fuze, c2v2, clv2, y820, y920, y925, x747,\n" "\t 747p, x777, nn2g, m244, cli+, fuz2, hd20, hd30,\n" "\t ip6g, rk27, clzp, zxf2, zxf3, fuz+, e370, e360,\n" - "\t zxfi, zmoz, zen, zenv, ypz5, zxfs)\n"); + "\t zxfi, zmoz, zen, zenv, ypz5, zxfs, e450, e460,\n" + "\t e470,e580,a10)\n"); printf("\nNo option results in Archos standard player/recorder format.\n"); exit(1); @@ -382,6 +383,16 @@ int main (int argc, char** argv) modelnum = 90; else if (!strcmp(&argv[1][5], "zxfs")) /* Creative ZEN X-Fi Style */ modelnum = 94; + else if (!strcmp(&argv[1][5], "e450")) /* Sony NWZ-E450 series */ + modelnum = 100; + else if (!strcmp(&argv[1][5], "e460")) /* Sony NWZ-E460 series */ + modelnum = 101; + else if (!strcmp(&argv[1][5], "e580")) /* Sony NWZ-E580 series */ + modelnum = 102; + else if (!strcmp(&argv[1][5], "e470")) /* Sony NWZ-E470 series */ + modelnum = 103; + else if (!strcmp(&argv[1][5], "a10")) /* Sony NW-A10 series */ + modelnum = 104; else { fprintf(stderr, "unsupported model: %s\n", &argv[1][5]); return 2; diff --git a/utils/nwztools/database/gen_db.py b/utils/nwztools/database/gen_db.py index de78d05cab..be4cc34db0 100755 --- a/utils/nwztools/database/gen_db.py +++ b/utils/nwztools/database/gen_db.py @@ -200,7 +200,7 @@ extern struct nwz_series_info_t nwz_series[NWZ_SERIES_COUNT]; #endif /* __NWZ_DB_H__ */ """ -with open("nwz_db.h", "w") as fp: +with open("nwz-db.h", "w") as fp: fp.write(header_begin) # generate list of all nvp nodes for name in sorted(g_nvp_names): @@ -241,7 +241,7 @@ impl_begin = \ /** /!\ This file was automatically generated, DO NOT MODIFY IT DIRECTLY /!\ */ -#include "nwz_db.h" +#include "nwz-db.h" struct nwz_model_info_t nwz_model[NWZ_MODEL_COUNT] = { @@ -256,7 +256,7 @@ def by_name(nvp_entry): def codename_to_c(codename): return re.sub('[^a-zA-Z0-9]', '_', codename, 0) -with open("nwz_db.c", "w") as fp: +with open("nwz-db.c", "w") as fp: fp.write(impl_begin) # generate model list (sort by mid) for model in sorted(g_models, key = by_mid): diff --git a/utils/nwztools/plattools/Makefile b/utils/nwztools/plattools/Makefile deleted file mode 100644 index 71188ba11a..0000000000 --- a/utils/nwztools/plattools/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -PREFIX?=arm-sony-linux-gnueabi- -CC=$(PREFIX)gcc -LD=$(PREFIX)gcc -CFLAGS=-std=gnu99 -Wall -O2 -NWZ_DB_DIR=../database -INCLUDES=-I. -I$(NWZ_DB_DIR) - -LIB_FILES=nwz_lib.c $(NWZ_DB_DIR)/nwz_db.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_fb.c -ALL_ELF=$(patsubst %.c,%.elf,$(TOOL_FILES)) all_tools.elf dualboot.elf - -all: $(ALL_ELF) - -# image dependency -data/rockbox_icon.h data/tools_icon.h: - make -C data - -dualboot.elf: data/rockbox_icon.h data/tools_icon.h - -%.elf: %.c $(LIB_FILES) - $(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ - -all_tools.elf: all_tools.c $(TOOL_FILES) $(LIB_FILES) - $(CC) $(CFLAGS) -DNWZ_EMBED_TOOLS $(INCLUDES) -o $@ $^ - -dualboot.elf: dualboot.c all_tools.c $(TOOL_FILES) $(LIB_FILES) - $(CC) $(CFLAGS) -DNWZ_DUALBOOT -DNWZ_EMBED_TOOLS $(INCLUDES) -o $@ $^ - -clean: - rm -rf $(ALL_ELF) diff --git a/utils/nwztools/plattools/README b/utils/nwztools/plattools/README deleted file mode 100644 index e33dfeb354..0000000000 --- a/utils/nwztools/plattools/README +++ /dev/null @@ -1,27 +0,0 @@ -Platform tools --------------- - -Those tools are designed to run on the devices. They are mostly tests that can -be run in firmware upgrade mode (using exec_file in utils/nwztools/scripts/). To -compile those, you will need the sony nwz cross compiler. The canonical way to -run them is as follows: - -1) Build the tools: - cd /path/to/utils/nwztools/plattools - make -Note that the default cross compiler prefix is arm-sony-linux-gnueabi- but it -can be changed using PREFIX: -PREFIX="sony-nwz-linux-gnueabi-" make - -2) Embed the wanted excutable in a firmware upgrade for your device. The README -in utils/nwztools/scripts contains more documentation on how to select the right -target. For example if you want to embed test_display for the NWZ-E460 series, -you should run: - cd /path/to/utils/nwztools/scripts - make exec_file UPG=test_display_nwze46x.upg NWZ_TARGET=nwz-e46x EXEC=../plattools/test_display.elf - -3) Put the upgrade file on the device and trigger a firmware upgrade. Assuming -your NWZ device is /dev/sdb1 and is mounted at /media/pamaury/WALKMAN, run: - cd /path/to/utils/nwztools/scripts - make copy_fw_upgrade UPG=test_display_nwze46x.upg NWZ_MOUNT=/media/pamaury/WALKMAN/ - sudo make do_fw_upgrade NWZ_DEV=/dev/sdb1 diff --git a/utils/nwztools/plattools/all_tools.c b/utils/nwztools/plattools/all_tools.c deleted file mode 100644 index c93e26b36e..0000000000 --- a/utils/nwztools/plattools/all_tools.c +++ /dev/null @@ -1,133 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2011 by Amaury Pouly - * - * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing - * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -#define TOOL_LIST \ - TOOL(dest_tool) \ - TOOL(test_adc) \ - TOOL(test_bl) \ - TOOL(test_display) \ - TOOL(test_keys) \ - TOOL(test_power) \ - TOOL(test_ts) \ - TOOL(test_fb) \ - -typedef int (*nwz_tool_main_t)(int argc, char **argv); - -struct nwz_tool_t -{ - const char *name; - nwz_tool_main_t main; -}; - -/* create list of extern definition */ -#define TOOL(name) extern int NWZ_TOOL_MAIN(name)(int argc, char **argv); -TOOL_LIST -#undef TOOL - -/* create actual list */ -#define TOOL(name) { #name, NWZ_TOOL_MAIN(name) }, -static struct nwz_tool_t g_tools[] = -{ - TOOL_LIST -}; -#undef TOOL - -#define NR_TOOLS (sizeof(g_tools) / sizeof(g_tools[0])) - -static void hello(void) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "all_tools"); - nwz_lcdmsg(false, 0, 1, "BACK: quit"); - nwz_lcdmsg(false, 0, 2, "LEFT/RIGHT: change tool"); - nwz_lcdmsg(false, 0, 3, "PLAY: run tool"); -} - -/* this tool itself can be embedded in the dualboot */ -#ifdef NWZ_DUALBOOT -int NWZ_TOOL_MAIN(all_tools)(int argc, char **argv) -#else -int main(int argc, char **argv) -#endif -{ - hello(); - /* open input device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_lcdmsg(false, 3, 5, "Cannot open input device"); - sleep(2); - return 1; - } - /* main loop */ - int cur_tool = 0; - while(true) - { - /* print tools */ - int line = 5; - for(size_t i = 0; i < NR_TOOLS; i++) - { - nwz_lcdmsgf(false, 0, line++, "%c %s", (i == cur_tool) ? '>' : ' ', - g_tools[i].name); - } - /* wait for event (1000ms) */ - 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; - /* only act on key release */ - if(nwz_key_event_is_press(&evt)) - continue; - int keycode = nwz_key_event_get_keycode(&evt); - if(keycode == NWZ_KEY_LEFT) - { - cur_tool--; - if(cur_tool == -1) - cur_tool += NR_TOOLS; - } - else if(keycode == NWZ_KEY_RIGHT) - { - cur_tool++; - if(cur_tool == NR_TOOLS) - cur_tool = 0; - } - else if(keycode == NWZ_KEY_PLAY) - { - /* close input */ - nwz_key_close(input_fd); - g_tools[cur_tool].main(argc, argv); - /* reopen input and clear the screen */ - input_fd = nwz_key_open(); - hello(); - } - else if(keycode == NWZ_KEY_BACK) - break; - } - nwz_key_close(input_fd); - return 0; -} diff --git a/utils/nwztools/plattools/data/Makefile b/utils/nwztools/plattools/data/Makefile deleted file mode 100644 index 86f3bb339c..0000000000 --- a/utils/nwztools/plattools/data/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -TOOLS_DIR=../../../../tools/ -all: rockbox_icon.h tools_icon.h - -%.h: %.bmp - $(TOOLS_DIR)/bmp2rb -f 4 $^ > $@ - -clean: - rm -rf *.h diff --git a/utils/nwztools/plattools/data/Oxygen480-categories-preferences-system.svg b/utils/nwztools/plattools/data/Oxygen480-categories-preferences-system.svg deleted file mode 100644 index 0835251992..0000000000 --- a/utils/nwztools/plattools/data/Oxygen480-categories-preferences-system.svg +++ /dev/null @@ -1,334 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://web.resource.org/cc/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" width="128" height="128" id="svg5676" sodipodi:version="0.32" inkscape:version="0.45+devel" sodipodi:docname="settings-wip.svgz" inkscape:output_extension="org.inkscape.output.svgz.inkscape" version="1.0"> - <defs id="defs5678"> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4322" id="linearGradient4338" gradientUnits="userSpaceOnUse" gradientTransform="translate(-2.6296821,21.172877)" x1="5.1934605" y1="88.98745" x2="5.1934605" y2="145.64882"/> - <linearGradient y2="0" x2="28" y1="57.5" x1="28" gradientUnits="userSpaceOnUse" id="linearGradient8081"> - <stop id="stop8083" style="stop-color:#ffd700;stop-opacity:1;" offset="0"/> - <stop offset="0.25242719" style="stop-color:#ffea00;stop-opacity:1;" id="stop8087"/> - <stop id="stop8085" style="stop-color:#b06d00;stop-opacity:1;" offset="1"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient8081" id="linearGradient7698" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0872079,0,0,1.0872079,-59.143229,30.210796)" x1="58.557281" y1="107.76735" x2="63.943447" y2="107.76735"/> - <linearGradient id="linearGradient6924"> - <stop style="stop-color:#ffffff;stop-opacity:0.73885351;" offset="0" id="stop6926"/> - <stop id="stop10395" offset="0.24999999" style="stop-color:#ffffff;stop-opacity:0;"/> - <stop id="stop10393" offset="0.5" style="stop-color:#cccccc;stop-opacity:0;"/> - <stop style="stop-color:#9a9a9a;stop-opacity:1;" offset="1" id="stop6928"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient6924" id="linearGradient6930" x1="8.3827581" y1="8.3199806" x2="15.021504" y2="14.958727" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.2050468,0,0,1.2050468,-2.1016162,-2.0259658)"/> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4529" id="linearGradient4640" gradientUnits="userSpaceOnUse" x1="9.3031492" y1="133.25163" x2="-5.8540711" y2="130.59308"/> - <filter inkscape:collect="always" x="-0.10337079" width="1.2067416" y="-0.10337079" height="1.2067416" id="filter4626"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.42488862" id="feGaussianBlur4628"/> - </filter> - <clipPath clipPathUnits="userSpaceOnUse" id="clipPath4632"> - <rect style="opacity:0.83895126;fill:url(#linearGradient4636);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1;filter:url(#filter4626)" id="rect4634" width="13.334369" height="3.7415669" x="-2.9263651" y="130.97287" rx="0" ry="0" inkscape:transform-center-x="-16.434708" inkscape:transform-center-y="-5.5242717"/> - </clipPath> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4529" id="linearGradient4604" gradientUnits="userSpaceOnUse" x1="9.3031492" y1="133.25163" x2="-5.8540711" y2="130.59308"/> - <radialGradient inkscape:collect="always" xlink:href="#linearGradient4434" id="radialGradient4602" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1,0,0,0.3939752,0.4817163,48.449986)" cx="4.7494926" cy="132.25244" fx="4.7494926" fy="132.25244" r="5.3222656"/> - <filter inkscape:collect="always" id="filter4584"> - <feGaussianBlur inkscape:collect="always" stdDeviation="1.0829419" id="feGaussianBlur4586"/> - </filter> - <clipPath clipPathUnits="userSpaceOnUse" id="clipPath4588"> - <path sodipodi:nodetypes="ccsccccsccc" id="path4590" d="M 13.037731,82.09273 L 18.342123,87.397123 C 21.331352,87.817882 24.407038,89.18508 26.895219,91.673261 C 29.411177,94.189215 30.893289,97.328601 31.294715,100.34972 L 56.289372,125.34436 C 62.090282,131.14528 77.301422,116.01036 71.462392,110.17133 L 46.467742,85.176682 C 43.446635,84.775254 40.307258,83.29314 37.791293,80.777186 C 35.303111,78.289007 33.935917,75.213314 33.515156,72.22409 L 28.210762,66.919697 L 13.037731,82.09273 z" style="opacity:1;fill:url(#linearGradient4592);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - </clipPath> - <filter inkscape:collect="always" id="filter4551"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.15501048" id="feGaussianBlur4553"/> - </filter> - <linearGradient inkscape:collect="always" id="linearGradient4529"> - <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop4531"/> - <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop4533"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4529" id="linearGradient4537" x1="9.3031492" y1="133.25163" x2="-5.8540711" y2="130.59308" gradientUnits="userSpaceOnUse"/> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient2575" id="linearGradient4525" x1="58.557281" y1="107.76735" x2="63.943447" y2="107.76735" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.0872079,0,0,1.0872079,-71.164046,29.503688)"/> - <linearGradient inkscape:collect="always" id="linearGradient4509"> - <stop style="stop-color:#ffe900;stop-opacity:1;" offset="0" id="stop4511"/> - <stop style="stop-color:#ffe900;stop-opacity:0;" offset="1" id="stop4513"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4509" id="linearGradient4515" x1="75.585938" y1="85.083641" x2="89.453125" y2="79.224266" gradientUnits="userSpaceOnUse"/> - <filter inkscape:collect="always" id="filter4501"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.48665741" id="feGaussianBlur4503"/> - </filter> - <linearGradient inkscape:collect="always" id="linearGradient4465"> - <stop style="stop-color:#ffa300;stop-opacity:1;" offset="0" id="stop4467"/> - <stop style="stop-color:#ffa300;stop-opacity:0;" offset="1" id="stop4469"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4465" id="linearGradient4471" x1="83.886719" y1="77.661766" x2="86.300743" y2="86.671021" gradientUnits="userSpaceOnUse" gradientTransform="translate(-4,-4)"/> - <linearGradient inkscape:collect="always" id="linearGradient4434"> - <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop4436"/> - <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop4438"/> - </linearGradient> - <radialGradient inkscape:collect="always" xlink:href="#linearGradient4434" id="radialGradient4440" cx="4.7494926" cy="132.25244" fx="4.7494926" fy="132.25244" r="5.3222656" gradientTransform="matrix(1,0,0,0.3939752,-7.0710881e-2,74.137847)" gradientUnits="userSpaceOnUse"/> - <filter inkscape:collect="always" id="filter4404"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.15249406" id="feGaussianBlur4406"/> - </filter> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4322" id="linearGradient4342" gradientUnits="userSpaceOnUse" gradientTransform="translate(1.6836694,24.213436)" x1="3.5450988" y1="107.64014" x2="3.190912" y2="104.64899"/> - <linearGradient inkscape:collect="always" id="linearGradient4322"> - <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop4324"/> - <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop4326"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4322" id="linearGradient4346" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-2.6879854,-4.0690534)" x1="5.1934605" y1="103.9544" x2="5.1348171" y2="115.65614"/> - <filter inkscape:collect="always" x="-0.074906364" width="1.1498127" y="-0.11235955" height="1.224719" id="filter4238"> - <feGaussianBlur inkscape:collect="always" stdDeviation="1.1235955" id="feGaussianBlur4240"/> - </filter> - <clipPath clipPathUnits="userSpaceOnUse" id="clipPath4242"> - <path sodipodi:nodetypes="ccsccccsccc" id="path4244" d="M -4,77.788157 L -4,83.381653 C -2.645772,85.179573 -1.744968,87.522089 -1.744968,90.145881 C -1.744968,92.798965 -2.618764,95.23565 -4,97.040192 L -4,123.39712 C -4,129.51419 12,129.55437 12,123.39712 L 12,97.040192 C 10.618764,95.23565 9.744972,92.798965 9.744968,90.145881 C 9.744968,87.522089 10.645776,85.179573 12,83.381653 L 12,77.788157 L -4,77.788157 z" style="opacity:1;fill:url(#linearGradient4247);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - </clipPath> - <linearGradient id="linearGradient2575" gradientUnits="userSpaceOnUse" x1="28" y1="57.5" x2="28" y2="0"> - <stop offset="0" style="stop-color:#FFEA00" id="stop2577"/> - <stop offset="1" style="stop-color:#cd8000;stop-opacity:1;" id="stop2579"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient2575" id="linearGradient4190" x1="36" y1="100" x2="28" y2="100" gradientUnits="userSpaceOnUse" spreadMethod="reflect" gradientTransform="matrix(0.9483145,-0.9483145,0.9483145,0.9483145,-36.790528,30.877897)"/> - <linearGradient id="linearGradient6511"> - <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop6513"/> - <stop style="stop-color:#393939;stop-opacity:1;" offset="1" id="stop6515"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient6511" id="linearGradient6517" x1="38.074299" y1="4.2695875" x2="38.074299" y2="-10.42289" gradientUnits="userSpaceOnUse"/> - <linearGradient id="linearGradient3916"> - <stop style="stop-color:#d3d6d6;stop-opacity:1;" offset="0" id="stop3918"/> - <stop style="stop-color:#f7f7f7;stop-opacity:1;" offset="1" id="stop3921"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient3916" id="linearGradient3943" gradientUnits="userSpaceOnUse" x1="34.165016" y1="4.863008" x2="34.165016" y2="-14.006344"/> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient3904" id="linearGradient6112" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.1550511,0,0,1.1550511,-41.26484,21.101778)" x1="38.827515" y1="104.49192" x2="36.460194" y2="17.509802"/> - <filter inkscape:collect="always" x="-0.26177245" width="1.5235449" y="-0.075698018" height="1.151396" id="filter3838"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.41890191" id="feGaussianBlur3840"/> - </filter> - <filter inkscape:collect="always" x="-0.26177242" width="1.5235448" y="-0.075698018" height="1.151396" id="filter3834"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.41890191" id="feGaussianBlur3836"/> - </filter> - <clipPath clipPathUnits="userSpaceOnUse" id="clipPath3850"> - <path id="path3852" d="M 5.6835937,-4 C 6.7672977,-0.13901249 7.6835937,4 7.6835937,8 C 7.6835937,25.92781 15.683594,26.507796 15.683594,8 C 15.683594,4 16.274299,-0.44557713 17.683594,-4 C 16.034701,-11.286281 10.22872,-24.562662 5.6835937,-4 z" style="opacity:1;fill:#b4b4b4;fill-opacity:1;stroke:none;stroke-width:0.47008219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" sodipodi:nodetypes="ccccc"/> - </clipPath> - <linearGradient id="linearGradient3904"> - <stop style="stop-color:#141515;stop-opacity:1;" offset="0" id="stop3906"/> - <stop style="stop-color:#535557;stop-opacity:0;" offset="1" id="stop3908"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient3904" id="linearGradient6119" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.1550511,0,0,1.1550511,-40.633471,-152.2263)" x1="36.460194" y1="108.28275" x2="39.503891" y2="69.41713"/> - <linearGradient inkscape:collect="always" id="linearGradient3220"> - <stop style="stop-color:#ffffff;stop-opacity:1;" offset="0" id="stop3222"/> - <stop style="stop-color:#ffffff;stop-opacity:0;" offset="1" id="stop3224"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient3220" id="linearGradient6122" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.6737798,0,0,1.4175761,-25.92314,-147.94457)" x1="36.460194" y1="89.611626" x2="36.460194" y2="17.509802"/> - <radialGradient gradientUnits="userSpaceOnUse" r="139.55859" cy="112.3047" cx="102" id="radialGradient9613"> - <stop id="stop9615" style="stop-color:#535557" offset="0"/> - <stop id="stop9617" style="stop-color:#898A8C" offset="0.13804179"/> - <stop id="stop9619" style="stop-color:#ECECEC" offset="0.20296688"/> - <stop id="stop9621" style="stop-color:#FAFAFA" offset="0.33539036"/> - <stop id="stop9623" style="stop-color:#FFFFFF" offset="0.39464113"/> - <stop id="stop9625" style="stop-color:#FAFAFA" offset="0.5313"/> - <stop id="stop9627" style="stop-color:#EBECEC" offset="0.8449"/> - <stop id="stop9629" style="stop-color:#E1E2E3" offset="1"/> - </radialGradient> - <linearGradient inkscape:collect="always" xlink:href="#radialGradient9613" id="linearGradient6125" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.8398488,-0.8398488,0.8167445,0.8167445,-15.712841,44.354581)" spreadMethod="reflect" x1="32.228344" y1="47.999996" x2="35.935673" y2="47.999996"/> - <filter inkscape:collect="always" id="filter4503"> - <feGaussianBlur inkscape:collect="always" stdDeviation="0.43775175" id="feGaussianBlur4505"/> - </filter> - <clipPath clipPathUnits="userSpaceOnUse" id="clipPath4092"> - <path style="fill:#9c0f56" d="M 59.849,42.398 C 57.593,46.987 10.717,106.259 8.774,111.066 C 4.67,121.218 16.431,133.433 25.989,124.269 C 32.291,118.227 66.959,56.111 72.129,51.415 C 75.623,48.241 95.004,41.083 95.004,41.083 L 80.924,18.23 C 80.924,18.23 62.724,36.552 59.849,42.398 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="csssscc" id="path4094"/> - </clipPath> - <linearGradient id="XMLID_3_" gradientUnits="userSpaceOnUse" x1="11.9185" y1="119.0576" x2="98.418404" y2="44.057598"> - <stop offset="0" style="stop-color:#C9C9C9" id="stop49"/> - <stop offset="0.0229" style="stop-color:#B2B2B2" id="stop51"/> - <stop offset="0.05" style="stop-color:#9F9F9F" id="stop53"/> - <stop offset="0.0819" style="stop-color:#929292" id="stop55"/> - <stop offset="0.1225" style="stop-color:#8A8A8A" id="stop57"/> - <stop offset="0.2012" style="stop-color:#888888" id="stop59"/> - <stop offset="1" style="stop-color:#686868;stop-opacity:1;" id="stop63"/> - </linearGradient> - <linearGradient id="XMLID_11_" gradientUnits="userSpaceOnUse" x1="31.4995" y1="80.0439" x2="32.347698" y2="80.671898" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#000000" id="stop183"/> - <stop offset="1" style="stop-color:#000000;stop-opacity:0;" id="stop185"/> - </linearGradient> - <linearGradient id="XMLID_10_" gradientUnits="userSpaceOnUse" x1="23.9844" y1="120.7646" x2="12.7283" y2="109.8655" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#EEEEEE" id="stop176"/> - <stop offset="1" style="stop-color:#535353;stop-opacity:1;" id="stop178"/> - </linearGradient> - <linearGradient id="XMLID_9_" gradientUnits="userSpaceOnUse" x1="18.776899" y1="129.5986" x2="18.776899" y2="114.6055" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#000000" id="stop169"/> - <stop offset="1" style="stop-color:#000000;stop-opacity:0;" id="stop171"/> - </linearGradient> - <radialGradient id="XMLID_8_" cx="64.988297" cy="15.9429" r="19.6182" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#FFFFFF" id="stop162"/> - <stop offset="1" style="stop-color:#888A85" id="stop164"/> - </radialGradient> - <linearGradient id="XMLID_7_" gradientUnits="userSpaceOnUse" x1="40.711899" y1="75.171898" x2="48.5495" y2="80.899803" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0.213" style="stop-color:#555753" id="stop155"/> - <stop offset="1" style="stop-color:#000000" id="stop157"/> - </linearGradient> - <linearGradient id="path30758_1_" gradientUnits="userSpaceOnUse" x1="16.7803" y1="80.697304" x2="67.723602" y2="80.697304" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#888888" id="stop149"/> - <stop offset="0.8935" style="stop-color:#DDDDDD" id="stop151"/> - </linearGradient> - <linearGradient id="path34280_1_" gradientUnits="userSpaceOnUse" x1="93.023399" y1="39.3867" x2="93.023399" y2="25.928699" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#555555" id="stop141"/> - <stop offset="0.3965" style="stop-color:#888888" id="stop143"/> - <stop offset="1" style="stop-color:#555555" id="stop145"/> - </linearGradient> - <linearGradient id="rect22846_1_" gradientUnits="userSpaceOnUse" x1="247.60249" y1="-288.60791" x2="261.97269" y2="-288.60791" gradientTransform="matrix(0.9428,-0.2511,-0.2421,-0.9089,6.0921912,215.38258)"> - <stop offset="0" style="stop-color:#888888" id="stop135"/> - <stop offset="1" style="stop-color:#555555" id="stop137"/> - </linearGradient> - <radialGradient id="rect14944_1_" cx="274.56641" cy="36.065399" r="6.8733001" gradientTransform="matrix(0.523,-0.2146,-2.627,-7.0521,27.4228,356.0237)" gradientUnits="userSpaceOnUse"> - <stop offset="0" style="stop-color:#888A85" id="stop127"/> - <stop offset="0.6213" style="stop-color:#FFFFFF" id="stop129"/> - <stop offset="1" style="stop-color:#555753" id="stop131"/> - </radialGradient> - <radialGradient id="rect14938_1_" cx="290.8428" cy="36.069801" r="6.8736" gradientTransform="matrix(0.4892,-0.2059,-2.5913,-7.0931,29.692,361.6149)" gradientUnits="userSpaceOnUse"> - <stop offset="0" style="stop-color:#888A85" id="stop119"/> - <stop offset="0.6213" style="stop-color:#FFFFFF" id="stop121"/> - <stop offset="1" style="stop-color:#555753" id="stop123"/> - </radialGradient> - <radialGradient id="rect10553_1_" cx="292.49219" cy="43.388699" r="6.8727999" gradientTransform="matrix(0.498,-0.2212,-2.9368,-8.3284,56.2613,466.2682)" gradientUnits="userSpaceOnUse"> - <stop offset="0" style="stop-color:#888A85" id="stop111"/> - <stop offset="0.6213" style="stop-color:#FFFFFF" id="stop113"/> - <stop offset="1" style="stop-color:#555753" id="stop115"/> - </radialGradient> - <radialGradient id="rect14950_1_" cx="92.734398" cy="20.4307" r="4.1451998" gradientTransform="matrix(0.6131,-0.2916,-5.2659,-7.9645,125.0096,227.992)" gradientUnits="userSpaceOnUse"> - <stop offset="0" style="stop-color:#FFFFFF" id="stop103"/> - <stop offset="0.5266" style="stop-color:#BABDB6" id="stop105"/> - <stop offset="1" style="stop-color:#888A85" id="stop107"/> - </radialGradient> - <radialGradient id="rect10551_3_" cx="78.776398" cy="44.608398" r="14.3205" gradientUnits="userSpaceOnUse"> - <stop offset="0" style="stop-color:#2E3436" id="stop95"/> - <stop offset="0.72189999" style="stop-color:#000000;stop-opacity:1;" id="stop97"/> - <stop offset="1" style="stop-color:#2E3436" id="stop99"/> - </radialGradient> - <linearGradient id="rect10551_1_" gradientUnits="userSpaceOnUse" x1="77.216797" y1="44.765598" x2="73.449203" y2="30.555201"> - <stop offset="0.7219" style="stop-color:#DDDDDD" id="stop89"/> - <stop offset="1" style="stop-color:#EEEEEC" id="stop91"/> - </linearGradient> - <radialGradient id="XMLID_6_" cx="77.004028" cy="13.140214" r="64.405701" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" fx="77.004028" fy="13.140214"> - <stop offset="0" style="stop-color:#FFFFFF" id="stop82"/> - <stop id="stop13256" style="stop-color:#c3c4c2;stop-opacity:1;" offset="0.5"/> - <stop offset="1" style="stop-color:#000000;stop-opacity:1;" id="stop84"/> - </radialGradient> - <linearGradient id="XMLID_5_" gradientUnits="userSpaceOnUse" x1="15.7207" y1="125.7861" x2="24.9356" y2="108.3428" gradientTransform="translate(-80,0)"> - <stop offset="0" style="stop-color:#000000" id="stop75"/> - <stop offset="0.8935" style="stop-color:#FFFFFF" id="stop77"/> - </linearGradient> - <linearGradient id="XMLID_4_" gradientUnits="userSpaceOnUse" x1="40.527802" y1="55.75" x2="52.981899" y2="64.646004" gradientTransform="translate(-80,0)"> - <stop offset="0" style="stop-color:#ffffff;stop-opacity:0;" id="stop68"/> - <stop offset="0.8935" style="stop-color:#FFFFFF" id="stop70"/> - </linearGradient> - <linearGradient id="path2388_1_" gradientUnits="userSpaceOnUse" x1="14.9214" y1="124.6768" x2="107.7549" y2="-17.989599" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#DDDDDD" id="stop32"/> - <stop offset="0.6864" style="stop-color:#888888" id="stop34"/> - <stop offset="0.8935" style="stop-color:#DDDDDD" id="stop36"/> - </linearGradient> - <radialGradient id="path5936_1_" cx="172.123" cy="4.7476001" r="4.6967001" gradientTransform="matrix(6.7917,-1.4855,-1.2014,-5.506,-845.12621,725.19548)" gradientUnits="userSpaceOnUse"> - <stop offset="0" style="stop-color:#FFFFFF" id="stop26"/> - <stop offset="1" style="stop-color:#3E3E3E" id="stop28"/> - </radialGradient> - <linearGradient id="XMLID_1_" gradientUnits="userSpaceOnUse" x1="92.627899" y1="26.589399" x2="104.5325" y2="31.2349" gradientTransform="translate(229.83849,405.96228)"> - <stop offset="0" style="stop-color:#FFFFFF" id="stop19"/> - <stop offset="0.6391" style="stop-color:#888888" id="stop21"/> - </linearGradient> - <linearGradient id="rect25493_1_" gradientUnits="userSpaceOnUse" x1="258.88379" y1="-326.0903" x2="286.16019" y2="-287.6532" gradientTransform="matrix(0.9065,-0.2414,-0.2421,-0.9089,10.723991,214.40698)"> - <stop offset="0" style="stop-color:#555555" id="stop5"/> - <stop offset="0.6864" style="stop-color:#888888" id="stop7"/> - </linearGradient> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_5_" id="linearGradient10549" gradientUnits="userSpaceOnUse" gradientTransform="translate(-80,0)" x1="15.7207" y1="125.7861" x2="24.9356" y2="108.3428"/> - <mask maskUnits="userSpaceOnUse" id="mask10545"> - <path style="fill:url(#linearGradient10549)" id="path10547" d="M -0.051,18.554 L -0.847,9.66 C -0.847,9.66 8.141,4.482 10.38,3.193 C 3.985,-0.79 -3.654,1.07 -3.741,1.093 C -10.903,2.996 -15.908,8.865 -15.908,15.222 C -15.908,15.461 -15.901,15.701 -15.887,15.94 C -15.887,15.941 -15.887,15.941 -15.887,15.942 C -15.887,16.299 -16.25,36.73 -19.253,42.838 C -20.334,45.036 -30.401,58.18 -42.058,73.4 C -54.195,89.247 -69.3,108.968 -70.298,111.44 C -70.839,112.778 -71.079,114.126 -71.079,115.435 C -71.079,119.221 -69.06,122.663 -66.483,124.621 C -66.083,123.92 -65.655,123.178 -65.197,122.392 C -67.02,121.101 -68.463,119.074 -68.895,116.783 C -69.291,114.687 -68.831,112.48 -67.631,110.726 C -66.46,109.013 -64.659,107.855 -62.561,107.463 C -60.935,107.16 -59.182,107.593 -57.621,108.682 C -57.428,108.817 -57.245,108.966 -57.063,109.118 C -46.315,92.233 -27.938,65.35 3.195,23.824 C 1.323,20.784 -0.051,18.554 -0.051,18.554 z"/> - </mask> - <linearGradient inkscape:collect="always" xlink:href="#rect25493_1_" id="linearGradient11382" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.9065,-0.2414,-0.2421,-0.9089,10.723991,214.40698)" x1="258.88379" y1="-326.0903" x2="286.16019" y2="-287.6532"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_1_" id="linearGradient11384" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="92.627899" y1="26.589399" x2="104.5325" y2="31.2349"/> - <radialGradient inkscape:collect="always" xlink:href="#path5936_1_" id="radialGradient11386" gradientUnits="userSpaceOnUse" gradientTransform="matrix(6.7917,-1.4855,-1.2014,-5.506,-845.12621,725.19548)" cx="172.123" cy="4.7476001" r="4.6967001"/> - <linearGradient inkscape:collect="always" xlink:href="#path2388_1_" id="linearGradient11388" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="14.9214" y1="124.6768" x2="107.7549" y2="-17.989599"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_4_" id="linearGradient11390" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="77.040016" y1="14.124305" x2="92.612343" y2="4.8821697"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_4_" id="linearGradient11392" gradientUnits="userSpaceOnUse" gradientTransform="translate(-80,0)" x1="40.527802" y1="55.75" x2="52.981899" y2="64.646004"/> - <radialGradient inkscape:collect="always" xlink:href="#XMLID_6_" id="radialGradient11394" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.4337031,0.4442839,-0.7150071,0.6987259,282.84098,375.70944)" cx="77.004028" cy="13.140214" fx="77.004028" fy="13.140214" r="64.405701"/> - <linearGradient inkscape:collect="always" xlink:href="#rect10551_1_" id="linearGradient11396" gradientUnits="userSpaceOnUse" x1="77.216797" y1="44.765598" x2="73.449203" y2="30.555201"/> - <radialGradient inkscape:collect="always" xlink:href="#rect10551_3_" id="radialGradient11398" gradientUnits="userSpaceOnUse" cx="78.776398" cy="44.608398" r="14.3205"/> - <radialGradient inkscape:collect="always" xlink:href="#rect14950_1_" id="radialGradient11400" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.6131,-0.2916,-5.2659,-7.9645,125.0096,227.992)" cx="92.734398" cy="20.4307" r="4.1451998"/> - <radialGradient inkscape:collect="always" xlink:href="#rect10553_1_" id="radialGradient11402" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.498,-0.2212,-2.9368,-8.3284,56.2613,466.2682)" cx="292.49219" cy="43.388699" r="6.8727999"/> - <radialGradient inkscape:collect="always" xlink:href="#rect14938_1_" id="radialGradient11404" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.4892,-0.2059,-2.5913,-7.0931,29.692,361.6149)" cx="290.8428" cy="36.069801" r="6.8736"/> - <radialGradient inkscape:collect="always" xlink:href="#rect14944_1_" id="radialGradient11406" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.523,-0.2146,-2.627,-7.0521,27.4228,356.0237)" cx="274.56641" cy="36.065399" r="6.8733001"/> - <linearGradient inkscape:collect="always" xlink:href="#rect22846_1_" id="linearGradient11408" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.9428,-0.2511,-0.2421,-0.9089,6.0921912,215.38258)" x1="247.60249" y1="-288.60791" x2="261.97269" y2="-288.60791"/> - <linearGradient inkscape:collect="always" xlink:href="#path34280_1_" id="linearGradient11410" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="93.023399" y1="39.3867" x2="93.023399" y2="25.928699"/> - <linearGradient inkscape:collect="always" xlink:href="#path30758_1_" id="linearGradient11412" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="16.7803" y1="80.697304" x2="67.723602" y2="80.697304"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_7_" id="linearGradient11414" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="40.711899" y1="75.171898" x2="48.5495" y2="80.899803"/> - <radialGradient inkscape:collect="always" xlink:href="#XMLID_8_" id="radialGradient11416" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" cx="64.988297" cy="15.9429" r="19.6182"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_9_" id="linearGradient11418" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="18.776899" y1="129.5986" x2="18.776899" y2="114.6055"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_10_" id="linearGradient11420" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="17.509325" y1="123.23078" x2="18.875885" y2="107.20945"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_11_" id="linearGradient11422" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="31.4995" y1="80.0439" x2="32.347698" y2="80.671898"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_3_" id="linearGradient11424" gradientUnits="userSpaceOnUse" x1="11.9185" y1="119.0576" x2="98.418404" y2="44.057598"/> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4529" id="linearGradient11510" gradientUnits="userSpaceOnUse" x1="9.3031492" y1="133.25163" x2="-5.8540711" y2="130.59308"/> - <linearGradient inkscape:collect="always" xlink:href="#linearGradient4529" id="linearGradient11512" gradientUnits="userSpaceOnUse" x1="9.3031492" y1="133.25163" x2="-5.8540711" y2="130.59308"/> - <filter inkscape:collect="always" id="filter11957"> - <feGaussianBlur inkscape:collect="always" stdDeviation="2.339831" id="feGaussianBlur11959"/> - </filter> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_4_" id="linearGradient12019" gradientUnits="userSpaceOnUse" gradientTransform="translate(-80,0)" x1="40.527802" y1="55.75" x2="52.981899" y2="64.646004"/> - <linearGradient inkscape:collect="always" xlink:href="#path34280_1_" id="linearGradient12037" gradientUnits="userSpaceOnUse" gradientTransform="translate(229.83849,405.96228)" x1="93.023399" y1="39.3867" x2="93.023399" y2="25.928699"/> - <linearGradient inkscape:collect="always" xlink:href="#XMLID_3_" id="linearGradient12051" gradientUnits="userSpaceOnUse" x1="11.9185" y1="119.0576" x2="98.418404" y2="44.057598"/> - <filter inkscape:collect="always" id="filter12490"> - <feGaussianBlur inkscape:collect="always" stdDeviation="2.3509538" id="feGaussianBlur12492"/> - </filter> - </defs> - <sodipodi:namedview id="base" pagecolor="#ffffff" bordercolor="#666666" borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="1" inkscape:cx="13" inkscape:cy="18.5" inkscape:document-units="px" inkscape:current-layer="g11357" inkscape:window-width="1024" inkscape:window-height="697" inkscape:window-x="0" inkscape:window-y="0" height="128px" width="128px"/> - <metadata id="metadata5681"> - <rdf:RDF> - <cc:Work rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/> - </cc:Work> - </rdf:RDF> - </metadata> - <g inkscape:label="Livello 1" inkscape:groupmode="layer" id="layer1"> - <path style="fill:#000000;fill-opacity:1;filter:url(#filter12490);opacity:0.8" d="M 97.46875,6 C 97.18152,6.0094408 97.00831,6.0304757 97,6.03125 C 88.50154,6.7547259 81.81102,12.649899 80.96875,19.9375 C 80.96299,19.970198 76.86754,40.857308 72.875,46.3125 C 69.74177,50.594872 11.13376,102.7197 8.28125,107.28125 C 6.43475,110.23375 6.09196,113.64754 6.8125,116.75 C 6.81481,116.75995 6.81016,116.77131 6.8125,116.78125 C 7.27817,118.76618 8.16525,120.60725 9.40625,122.125 C 9.47154,122.20534 9.55786,122.26531 9.625,122.34375 C 9.73846,122.47566 9.85017,122.62373 9.96875,122.75 C 10.13123,122.9234 10.29696,123.08786 10.46875,123.25 C 10.78531,123.54834 11.12253,123.83716 11.46875,124.09375 C 11.51009,124.12442 11.55201,124.15746 11.59375,124.1875 C 11.75577,124.30387 11.92581,124.39345 12.09375,124.5 C 12.34901,124.66192 12.60676,124.83089 12.875,124.96875 C 12.90463,124.98396 12.93897,124.98509 12.96875,125 C 13.16389,125.09785 13.36099,125.19684 13.5625,125.28125 C 13.66656,125.32459 13.76932,125.36661 13.875,125.40625 C 13.96058,125.43847 14.03838,125.47026 14.125,125.5 C 14.26755,125.5489 14.41722,125.58297 14.5625,125.625 C 15.11282,125.78408 15.69527,125.91534 16.28125,125.96875 C 16.62585,125.99943 16.98844,126.00883 17.34375,126 C 17.49276,125.99631 17.6305,125.97967 17.78125,125.96875 C 18.30718,125.93117 18.83023,125.84877 19.375,125.71875 C 19.49773,125.68971 19.62642,125.65895 19.75,125.625 C 19.94658,125.5707 20.14518,125.50448 20.34375,125.4375 C 20.68974,125.32116 21.02361,125.18743 21.375,125.03125 C 21.51637,124.96837 21.67036,124.91327 21.8125,124.84375 C 22.01661,124.74364 22.23195,124.64533 22.4375,124.53125 C 22.50876,124.4917 22.58484,124.44751 22.65625,124.40625 C 22.93651,124.24411 23.21755,124.06393 23.5,123.875 C 23.72992,123.72139 24.01123,123.49888 24.3125,123.25 C 24.51715,123.08053 24.76474,122.86659 25,122.65625 C 25.31217,122.37641 25.73134,121.97195 26.09375,121.625 C 26.40496,121.32709 26.7476,121.00087 27.09375,120.65625 C 27.10095,120.64393 27.11785,120.63734 27.125,120.625 C 40.39609,107.39872 78.3196,61.213642 83.8125,57.75 C 87.95646,55.136652 109.0625,51.3125 109.0625,51.3125 C 113.21925,49.41573 118.90506,43.445638 121.3125,34.4375 C 121.72869,32.077134 121.4811,29.596922 121.375,30.03125 L 108.59375,35.78125 L 100.21875,29.0625 L 98.78125,25.40625 L 99.28125,19.21875 L 113.34375,13.96875 L 113.125,12.15625 C 107.67312,6.0868239 99.47934,5.9339145 97.46875,6 z M 17.8125,106.1875 C 21.2472,106.15572 24.40096,109.89596 24.375,114.15625 C 24.3535,117.67982 20.93573,121.18715 17.5,121.21875 C 14.06408,121.25138 10.73518,117.39784 10.6875,113.53125 C 10.68465,113.29896 10.66822,113.04283 10.6875,112.8125 C 10.70682,112.58223 10.74047,112.35167 10.78125,112.125 C 10.90349,111.44483 11.13404,110.80542 11.4375,110.1875 C 11.53867,109.98155 11.63003,109.78948 11.75,109.59375 C 12.94961,107.63625 15.09816,106.21329 17.8125,106.1875 z" id="path11963"/> - <g id="g11357" transform="matrix(1.0223499,0.1802679,-0.1801715,1.0218034,-142.50883,-466.04399)"> - <path style="fill:url(#linearGradient11382)" d="M 322.52649,444.25728 C 326.15949,443.01428 332.35849,434.45128 332.98149,424.78428 C 333.00949,424.35428 333.65649,426.67828 333.65649,428.98828 C 332.87949,437.94128 328.47049,444.55028 324.84449,447.04628 L 322.52649,444.25728 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="csssc" id="rect25493"/> - <path style="fill:#888a85" d="M 332.98149,424.78428 L 321.82849,432.38828 L 312.74849,427.41628 C 312.08149,428.88428 315.95449,447.98028 320.22749,446.96228 C 328.04849,445.09828 332.16349,435.78528 332.98149,424.78428 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="cccsc" id="path3285"/> - <path style="fill:url(#linearGradient11384)" id="path23" d="M 322.07549,432.68428 L 323.06949,441.37828 L 324.97749,444.59028 C 326.91449,443.03428 328.49449,440.87628 329.72849,438.28428 C 331.33649,434.63428 332.30349,430.21428 332.65649,425.47228 L 322.07549,432.68428 z" enable-background="new "/> - <path style="opacity:0.51380005;fill:url(#radialGradient11386)" d="M 313.59749,428.19228 C 313.59449,428.19728 313.57749,428.21928 313.57649,428.22628 C 313.57149,428.23928 313.56449,428.27228 313.56049,428.28828 C 313.04649,430.36728 316.00549,448.15728 320.19449,447.15928 C 321.12049,446.93828 322.00949,446.60928 322.83249,446.18928 L 320.58049,431.94628 L 313.59749,428.19228 z" enable-background="new " inkscape:r_cy="true" inkscape:r_cx="true" id="path5936"/> - <path style="fill:url(#linearGradient11388)" d="M 305.84149,406.08928 C 297.90049,408.19828 292.53349,414.90528 292.95349,421.96328 C 292.95349,421.99528 292.56249,442.51428 289.68749,448.36028 C 287.43149,452.94928 240.55549,512.22128 238.61249,517.02828 C 234.50849,527.18028 246.26949,539.39528 255.82749,530.23128 C 262.12949,524.18928 296.79749,462.07328 301.96749,457.37728 C 305.46149,454.20328 324.84249,447.04528 324.84249,447.04528 L 310.76249,424.19228 L 310.04449,416.17028 L 322.15949,409.19128 C 315.08849,403.65028 305.90349,406.07228 305.84149,406.08928 z M 247.46049,514.40928 C 250.71349,513.80428 254.33749,516.82428 255.02549,520.87228 C 255.59449,524.22028 252.93349,528.13028 249.67949,528.73528 C 246.42549,529.34128 242.61749,526.22128 241.92549,522.55928 C 241.26149,519.04028 243.34849,515.17628 247.46049,514.40928 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="cccssssccccssssccssss" id="path2388"/> - <path transform="translate(309.83849,405.96228)" mask="url(#mask10545)" style="fill:url(#linearGradient11392)" id="path72" d="M -0.051,18.554 L -0.847,9.66 C -0.847,9.66 8.141,4.482 10.38,3.193 C 3.985,-0.79 -3.654,1.07 -3.741,1.093 C -10.903,2.996 -15.908,8.865 -15.908,15.222 C -15.908,15.461 -15.901,15.701 -15.887,15.94 C -15.887,15.941 -15.887,15.941 -15.887,15.942 C -15.887,16.299 -16.25,36.73 -19.253,42.838 C -20.334,45.036 -30.401,58.18 -42.058,73.4 C -54.195,89.247 -69.3,108.968 -70.298,111.44 C -70.839,112.778 -71.079,114.126 -71.079,115.435 C -71.079,119.221 -69.06,122.663 -66.483,124.621 C -66.083,123.92 -65.655,123.178 -65.197,122.392 C -67.02,121.101 -68.463,119.074 -68.895,116.783 C -69.291,114.687 -68.831,112.48 -67.631,110.726 C -66.46,109.013 -64.659,107.855 -62.561,107.463 C -60.935,107.16 -59.182,107.593 -57.621,108.682 C -57.428,108.817 -57.245,108.966 -57.063,109.118 C -46.315,92.233 -27.938,65.35 3.195,23.824 C 1.323,20.784 -0.051,18.554 -0.051,18.554 z"/> - <path style="fill:url(#radialGradient11394)" id="path86" d="M 310.76249,424.19228 L 310.04449,416.17028 L 322.15949,409.19128 C 320.21949,407.64028 317.84449,406.51628 315.23549,405.92928 C 312.04649,405.90828 308.79349,406.38428 306.47749,407.16528 C 298.74149,409.77428 294.69849,415.49528 294.85149,422.31128 L 303.63249,437.15128 L 306.31749,435.47228 L 312.56749,446.29728 L 310.37649,447.80128 L 313.73849,451.42828 L 324.84249,447.04628 L 310.76249,424.19228 z"/> - <polygon transform="translate(229.83849,405.96228)" style="fill:url(#linearGradient11396)" points="65.82,36.446 76.487,27.791 85.179,40.128 72.511,46.783 65.82,36.446 " inkscape:r_cy="true" inkscape:r_cx="true" id="rect10551_2_"/> - <polygon transform="translate(229.83849,405.96228)" style="fill:url(#radialGradient11398)" points="65.82,36.446 76.487,29.791 83.179,40.128 72.511,46.783 65.82,36.446 " inkscape:r_cy="true" inkscape:r_cx="true" id="rect10551"/> - <polygon transform="translate(229.83849,405.96228)" style="fill:url(#radialGradient11400)" points="68.311,35.653 74.616,32.078 80.237,40.809 73.932,44.384 68.311,35.653 " inkscape:r_cy="true" inkscape:r_cx="true" id="rect14950"/> - <polygon transform="translate(229.83849,405.96228)" style="fill:url(#radialGradient11402)" points="67.891,36.615 77.497,32.233 77.891,33.323 68.284,37.705 67.891,36.615 " inkscape:r_cy="true" inkscape:r_cx="true" id="rect10553"/> - <polygon transform="translate(229.83849,405.96228)" style="fill:url(#radialGradient11404)" points="72.212,42.972 81.653,38.899 82.001,39.827 72.56,43.9 72.212,42.972 " inkscape:r_cy="true" inkscape:r_cx="true" id="rect14938"/> - <polygon transform="translate(229.83849,405.96228)" style="fill:url(#radialGradient11406)" points="69.661,39.991 79.757,35.751 80.11,36.673 70.015,40.914 69.661,39.991 " inkscape:r_cy="true" inkscape:r_cx="true" id="rect14944"/> - <path style="fill:url(#linearGradient11410)" d="M 320.80249,431.89128 C 320.76149,432.16128 322.10049,439.91928 322.18149,440.18928 C 322.85449,444.45728 323.83149,444.59528 324.03549,445.34928 C 324.76349,444.93528 324.29249,445.39528 324.92349,444.84628 C 324.80849,444.48028 323.48549,441.99528 322.95849,441.11128 C 322.71249,438.97728 321.93149,433.00328 321.86449,432.43528 C 321.45549,432.21328 321.29849,432.12528 320.80249,431.89128 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="ccccccc" id="path34280"/> - <path style="fill:url(#linearGradient11412)" d="M 246.62049,511.92528 C 251.42949,510.02428 257.88249,515.30428 257.53849,521.11028 C 260.82449,517.31028 296.88449,460.33528 297.44649,457.74428 C 298.30649,453.77728 294.17949,450.82228 290.89849,452.88728 C 288.60949,454.32628 246.30749,512.04828 246.62049,511.92528 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="ccsss" id="path30758"/> - <path style="fill:url(#linearGradient11414);stroke:#000000" id="path159" d="M 292.02849,454.56028 C 289.53249,456.91828 266.85449,487.60628 250.66249,509.77928 C 252.02149,510.08228 253.37949,510.67028 254.63749,511.58128 C 256.37949,512.84228 257.66849,514.51428 258.50849,516.33428 C 267.27449,503.42428 294.06749,460.80328 295.50149,457.24628 C 295.53749,457.05828 295.56249,456.87128 295.56249,456.69028 C 295.56249,455.85828 295.18949,455.11828 294.50449,454.63828 C 293.74349,454.10528 292.82549,454.08928 292.02849,454.56028 z"/> - <path style="fill:url(#radialGradient11416)" id="path166" d="M 294.94349,422.46628 C 294.86849,425.66728 294.31649,443.48028 291.48249,449.24328 C 291.40649,449.39728 291.28449,449.60828 291.13649,449.84928 C 291.56049,449.26728 291.86549,448.81828 292.01449,448.54228 C 294.75749,443.48028 297.55549,430.48328 297.76449,427.23428 L 294.94349,422.46628 z"/> - <path style="opacity:0.5;fill:url(#linearGradient11418)" id="path173" d="M 258.69149,526.59428 C 259.24949,525.08628 259.45349,523.49328 259.17549,521.97428 C 258.59949,518.81928 256.61749,515.87328 253.87449,514.09028 C 251.69549,512.67428 249.24349,512.11128 246.97049,512.50528 C 244.03849,513.01528 241.52249,514.52228 239.88549,516.74928 C 238.45149,518.70028 237.78049,521.08528 237.96049,523.44028 C 239.33149,531.34628 248.26549,537.48228 255.82849,530.23128 C 256.49049,529.59728 257.46949,528.33628 258.69149,526.59428 z M 249.67949,528.73528 C 246.42549,529.34128 242.61749,526.22128 241.92549,522.55928 C 241.26049,519.03928 243.34749,515.17528 247.46049,514.40928 C 250.71349,513.80428 254.33749,516.82428 255.02549,520.87228 C 255.59449,524.22028 252.93349,528.13028 249.67949,528.73528 z"/> - <path style="fill:url(#linearGradient11420)" id="path180" d="M 256.01149,520.70428 C 255.59949,518.27928 254.18149,516.01528 252.21849,514.64428 C 250.65849,513.55528 248.90449,513.12328 247.27849,513.42528 C 245.18049,513.81728 243.38049,514.97528 242.20849,516.68828 C 241.00949,518.44128 240.54849,520.64928 240.94449,522.74528 C 241.75449,527.03328 246.08849,530.42228 249.86349,529.71928 C 253.62049,529.02028 256.66649,524.55528 256.01149,520.70428 z M 249.67949,528.73528 C 246.42549,529.34128 242.61749,526.22128 241.92549,522.55928 C 241.26049,519.03928 243.34749,515.17528 247.46049,514.40928 C 250.71349,513.80428 254.33749,516.82428 255.02549,520.87228 C 255.59449,524.22028 252.93349,528.13028 249.67949,528.73528 z"/> - <path style="opacity:0.4;fill:url(#linearGradient11422)" id="path187" d="M 285.39049,455.48028 C 285.64549,454.95828 285.88049,454.31028 286.09549,453.56728 C 274.64749,469.16528 240.27149,512.92628 238.61349,517.02828 C 238.29049,517.82728 238.07649,518.63728 237.94149,519.45128 C 242.96749,511.10428 283.36449,459.62828 285.39049,455.48028 z"/> - <path transform="translate(229.83849,405.96228)" clip-path="url(#clipPath4092)" style="fill:url(#linearGradient11424);filter:url(#filter4503)" id="path65" d="M 72.13,49.416 C 66.96,54.112 32.292,116.228 25.99,122.27 C 18.09,129.844 8.695,122.813 7.986,114.414 C 7.207,123.618 17.468,132.44 25.99,124.27 C 32.292,118.228 66.96,56.112 72.13,51.416 C 75.624,48.242 95.005,41.084 95.005,41.084 L 94.004,39.459 C 90.005,40.965 75.147,46.674 72.13,49.416 z"/> - <path style="fill:url(#linearGradient11408)" d="M 310.04449,416.17028 L 322.15949,409.19128 L 322.67749,410.88528 L 310.13349,418.26728 L 310.04449,416.17028 z" inkscape:r_cy="true" inkscape:r_cx="true" sodipodi:nodetypes="ccccc" id="rect22846"/> - <path style="fill:url(#linearGradient11390);fill-opacity:1" id="path46" d="M 310.21449,416.07228 L 322.15949,409.19128 C 321.63949,408.78428 321.10749,408.43228 320.56949,408.10728 L 310.04449,414.17028 L 310.21449,416.07228 z"/> - </g> - <path style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.47008219000000001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998000000000;stroke-opacity:1;filter:url(#filter11957);opacity:0.80000000000000004" d="M 10.375,9 L 4.21875,15.46875 L 9.125,23.1875 C 13.08003,25.264868 17.14186,27.693549 20.375,30.75 L 69.625,77.3125 L 65.5625,81.5625 L 70.8125,86.53125 C 73.7103,86.859904 76.69384,88.078409 79.15625,90.40625 C 81.64614,92.760071 83.16605,95.732279 83.625,98.625 L 108.34375,122.03125 C 114.08456,127.45836 128.43479,112.52526 122.65625,107.0625 L 97.90625,83.6875 C 94.97813,83.378226 91.9274,82.010074 89.4375,79.65625 C 86.9751,77.328414 85.57063,74.424084 85.09375,71.5625 L 79.84375,66.59375 L 75.78125,70.84375 L 26.53125,24.28125 C 23.29811,21.224799 20.16307,17.382339 18.375,13.53125 L 10.375,9 z" id="path11428"/> - <g id="g10397" transform="matrix(0.9660937,-2.5302336e-2,2.3546854e-2,0.9608617,2.3338765,6.1294086)"> - <path id="rect3006" d="M 1.750754,7.673054 L 6.651221,15.840499 C 10.689771,18.10883 14.818666,20.740966 18.085644,24.007944 L 103.30145,109.22375 L 109.83541,102.68979 L 24.6196,17.473988 C 21.352622,14.20701 18.204176,10.093654 16.452155,6.039565 L 8.28471,1.139098 L 1.750754,7.673054 z" style="fill:url(#linearGradient6125);fill-opacity:1;stroke:none;stroke-width:0.47008219;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" sodipodi:nodetypes="ccccccccc"/> - <rect transform="matrix(0.7071068,-0.7071068,-0.7071068,-0.7071068,0,0)" style="fill:url(#linearGradient6122);fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" id="rect3912" width="1.1166428" height="98.671562" x="-1.357038" y="-123.11634"/> - <rect style="opacity:0.3857678;fill:url(#linearGradient6119);fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" id="rect4944" width="1.6020314" height="63.508739" x="0.89394951" y="-85.707031" transform="matrix(-0.7071068,0.7071068,-0.7071068,-0.7071068,0,0)"/> - <g transform="matrix(0.8167445,-0.8167445,0.8167445,0.8167445,5.2761549,23.749521)" clip-path="url(#clipPath3850)" id="g3842"> - <path style="fill:#535557;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3834)" d="M 4.296875,-4.12891 L 5.6640625,-4.12891 C 8.3203089,-0.31380448 8.5987355,3.8409896 7.6171875,8.17578 L 4.9804688,9.1523436 L 4.296875,-4.12891 z" id="path3726" sodipodi:nodetypes="ccccc"/> - <path sodipodi:nodetypes="ccccc" id="path3728" d="M 18.977324,-4.12891 L 17.610137,-4.12891 C 14.95389,-0.31380448 14.675464,3.8409896 15.657012,8.17578 L 18.293731,9.1523436 L 18.977324,-4.12891 z" style="fill:#535557;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3838)"/> - <path style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter3838)" d="M 18.977324,-4.12891 L 18.231618,-4.0598566 C 16.117808,-1.3279433 15.743286,-1.0597872 15.864172,4.9302704 L 18.293731,9.1523436 L 18.977324,-4.12891 z" id="path3969" sodipodi:nodetypes="ccccc"/> - </g> - <rect transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)" y="41.331993" x="0.84851468" height="109.04897" width="1.9142449" id="rect3886" style="fill:url(#linearGradient6112);fill-opacity:1;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - <path transform="matrix(0.8167445,-0.8167445,0.8167445,0.8167445,-14.584136,43.609812)" id="path3925" d="M 32,-12 L 30,-4 C 34.143852,8.2009511 38.115959,5.0342786 42,-4 L 40,-12 L 32,-12 z" style="fill:url(#linearGradient3943);fill-opacity:1;stroke:url(#linearGradient6517);stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" sodipodi:nodetypes="ccccc"/> - <path sodipodi:nodetypes="ccsccccsccc" id="rect3956" d="M 63.529919,78.09273 L 68.834311,83.397123 C 71.82354,83.817882 74.899226,85.18508 77.387407,87.673261 C 79.903365,90.189215 81.385477,93.328601 81.786903,96.34972 L 106.78156,121.34436 C 112.58247,127.14528 127.79361,112.01036 121.95458,106.17133 L 96.95993,81.176682 C 93.938823,80.775254 90.799446,79.29314 88.283481,76.777186 C 85.795299,74.289007 84.428105,71.213314 84.007344,68.22409 L 78.70295,62.919697 L 63.529919,78.09273 z" style="opacity:1;fill:url(#linearGradient4190);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - <path transform="matrix(0.9483145,-0.9483145,0.9483145,0.9483145,-6.4444639,0.531831)" clip-path="url(#clipPath4242)" sodipodi:nodetypes="cccccc" id="path4196" d="M -8,120 C 1.7462188,130.07566 10.00314,126.89342 16,120 L 12,136 L -16,128 L -20,112 L -8,120 z" style="fill:#ffa700;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4238)"/> - <rect transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)" y="100.16766" x="-10.297462" height="1.1132338" width="21.457907" id="rect4249" style="opacity:0.48689138;fill:#ffa500;fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - <path sodipodi:nodetypes="ccccccc" id="rect4320" d="M 72.972033,68.720893 L 75.892922,65.800004 L 81.066844,70.973925 C 80.921148,71.564914 80.822369,72.165286 81.579665,72.936868 L 79.073097,75.857759 C 78.372014,75.392484 77.997186,74.796708 78.21501,73.963871 L 72.972033,68.720893 z" style="opacity:0.83895126;fill:url(#linearGradient4346);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - <path sodipodi:nodetypes="ccccc" id="rect4340" d="M 4.6713727,129.88196 L 7.2816355,129.49996 C 7.2464436,130.37087 7.2584731,130.8014 7.8438776,132.01123 L 5.1273299,132.01123 C 4.7973883,130.83537 4.6035939,130.49599 4.6713727,129.88196 z" style="opacity:0.74531836;fill:url(#linearGradient4342);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:1.08779998;stroke-opacity:1;filter:url(#filter4404)" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-4,-4)"/> - <rect transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)" y="126.0467" x="-0.6434837" height="0.390625" width="10.644531" id="rect4432" style="opacity:1;fill:url(#radialGradient4440);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - <path sodipodi:nodetypes="ccc" id="path4454" d="M 83.597656,68.53125 L 68.753906,82.984375 C 84.820174,88.576948 78.33289,74.329762 83.597656,68.53125 z" style="fill:url(#linearGradient4471);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4501)"/> - <path transform="matrix(-1,0,0,-1,169.63281,168.51104)" style="fill:url(#linearGradient4515);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter4501)" d="M 87.597656,72.53125 L 72.753906,86.984375 C 88.820174,92.576948 82.33289,78.329762 87.597656,72.53125 z" id="path4505" sodipodi:nodetypes="ccc"/> - <rect transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)" ry="2.9279406" rx="2.9279406" y="132.02951" x="-7.5001087" height="29.279404" width="5.8558812" id="rect4517" style="opacity:0.83895126;fill:url(#linearGradient4525);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1"/> - <rect inkscape:transform-center-y="-5.5242717" inkscape:transform-center-x="-16.434708" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-4,-4)" ry="0.5577029" rx="2.9279406" y="130.97287" x="-1.1929667" height="1.1048541" width="11.60097" id="rect4527" style="opacity:0.83895126;fill:url(#linearGradient4537);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1;filter:url(#filter4551)"/> - <path transform="translate(50.492188,-4.0046875)" clip-path="url(#clipPath4588)" id="path4559" d="M 13.83125,81.09375 L 12.33125,82.59375 L 17.64375,87.90625 C 20.632979,88.327007 23.718069,89.699319 26.20625,92.1875 C 28.722207,94.703451 30.179824,97.822631 30.58125,100.84375 L 55.58125,125.84375 C 59.791769,130.05428 68.947177,123.22603 71.425,116.9375 C 68.058606,122.54366 60.345306,127.60781 56.58125,123.84375 L 31.58125,98.84375 C 31.179824,95.822631 29.722207,92.703451 27.20625,90.1875 C 24.718069,87.699319 21.632979,86.327007 18.64375,85.90625 L 13.83125,81.09375 z" style="opacity:1;fill:#996100;fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1;filter:url(#filter4584)"/> - <rect style="opacity:0.576779;fill:url(#radialGradient4602);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" id="rect4596" width="10.644531" height="0.390625" x="-0.091056541" y="100.35886" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)"/> - <rect clip-path="url(#clipPath4632)" style="opacity:0.576779;fill:url(#linearGradient4604);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1;filter:url(#filter4626)" id="rect4598" width="12.602244" height="4.0530515" x="-1.1929667" y="129.5918" rx="0" ry="0" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-21.221011,-22.313001)" inkscape:transform-center-x="-16.434708" inkscape:transform-center-y="-5.5242717"/> - <rect inkscape:transform-center-y="-5.5242717" inkscape:transform-center-x="-16.434708" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,-21.321011,-22.413001)" ry="0" rx="0" y="130.07516" x="3.1573973" height="1.7051741" width="7.9066095" id="rect4638" style="opacity:0.576779;fill:url(#linearGradient4640);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1;filter:url(#filter4626)" clip-path="url(#clipPath4632)"/> - <path sodipodi:nodetypes="ccccc" style="fill:url(#linearGradient6930);fill-opacity:1;stroke:none;stroke-width:0.30655462;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" d="M 2.9032773,7.9724105 L 7.1391831,15.032254 C 18.678358,20.720438 19.246981,15.680572 15.610994,6.5604419 L 8.5511516,2.3245361 L 2.9032773,7.9724105 z" id="path6537"/> - <rect style="opacity:0.83895126;fill:url(#linearGradient7698);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" id="rect7696" width="5.8558812" height="29.279404" x="4.5207062" y="132.73663" rx="2.9279406" ry="2.9279406" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)"/> - <rect style="opacity:0.95131088;fill:url(#linearGradient4338);fill-opacity:1;stroke:none;stroke-width:0.37;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:1.08779998;stroke-opacity:1" id="rect4336" width="2.5833137" height="38.179485" x="0.94721299" y="126.14276" transform="matrix(0.7071068,-0.7071068,0.7071068,0.7071068,0,0)"/> - </g> - </g> -</svg>
\ No newline at end of file diff --git a/utils/nwztools/plattools/data/make_images.sh b/utils/nwztools/plattools/data/make_images.sh deleted file mode 100755 index 7ac21dc17a..0000000000 --- a/utils/nwztools/plattools/data/make_images.sh +++ /dev/null @@ -1,53 +0,0 @@ -#!/bin/bash -# -# This script contains the code used to produce all the images. -# Because of the variety of tools needed to achieve that, the result is also -# included in the repository but this makes it easier to modify the data -# to add more content -# - -# path to root of repository -ROOT_DIR=../../../../ - -# final resolution -NWZ_WIDTH=130 -NWZ_HEIGHT=130 - -# path to rockbox icon -RB_ICON_PATH=$ROOT_DIR/docs/logo/rockbox-icon.svg -# path to tools icon (currently stolen from KDE Oxygen icon set) -TOOL_ICON_PATH=Oxygen480-categories-preferences-system.svg - -# convert_svg width height input output -function convert_svg -{ - local width="$1" - local height="$2" - local input="$3" - local output="$4" - TMP=tmp.png - # convert from SVG to PNG - inkscape -z -e $TMP -w $width -h $height $input - if [ "$?" != 0 ]; then - echo "SVG -> PNG conversion failed" - exit 1 - fi - # convert from PNG to BMP, force using "version 3" because the OF don't like - # "recent" BMP - convert -channel RGB $TMP -define bmp:format=bmp3 ${output}_icon.bmp - if [ "$?" != 0 ]; then - rm -f $TMP - echo "PNG -> BMP conversion failed" - exit 1 - fi - # remove temporary - rm -f $TMP -} - -# start by creating the bitmap files from rockbox-icon.svg for all resolutions -# we make a detour by svg because inkscape can only export to SVG -# NOTE: we use image magick to convert to bmp but the OF tools don't like BMPv5 -# and contrary to what the documentation says, image magick tends to produce -# those by default unless asked otherwise -convert_svg $NWZ_WIDTH $NWZ_HEIGHT $RB_ICON_PATH rockbox -convert_svg $NWZ_WIDTH $NWZ_HEIGHT $TOOL_ICON_PATH tools diff --git a/utils/nwztools/plattools/dest_tool.c b/utils/nwztools/plattools/dest_tool.c deleted file mode 100644 index 9fb075e9b3..0000000000 --- a/utils/nwztools/plattools/dest_tool.c +++ /dev/null @@ -1,192 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include <string.h> -#include <stdlib.h> -#include "nwz_plattools.h" - -static unsigned long read32(unsigned char *buf) -{ - return buf[0] | buf[1] << 8 | buf[2] << 16 | buf[3] << 24; -} - -static void write32(unsigned char *buf, unsigned long value) -{ - buf[0] = value & 0xff; - buf[1] = (value >> 8) & 0xff; - buf[2] = (value >> 16) & 0xff; - buf[3] = (value >> 24) & 0xff; -} - -static struct -{ - unsigned long dest; - const char *name; -} g_dest_list[] = -{ - { 0, "J" }, - { 1, "U" }, - { 0x101, "U2" }, - { 0x201, "U3" }, - { 0x301, "CA" }, - { 2, "CEV" }, - { 0x102, "CE7" }, - { 3, "CEW" }, - { 0x103, "CEW2" }, - { 4, "CN" }, - { 5, "KR" }, - { 6, "E" }, - { 0x106, "MX" }, - { 0x206, "E2" }, - { 0x306, "MX3" }, - { 7, "TW" }, -}; - -#define NR_DEST (sizeof(g_dest_list) / sizeof(g_dest_list[0])) - -static int get_dest_index(unsigned long dest) -{ - for(size_t i = 0; i < NR_DEST; i++) - if(g_dest_list[i].dest == dest) - return i; - return -1; -} - -static const char *get_dest_name(unsigned long dest) -{ - int index = get_dest_index(dest); - return index < 0 ? "NG" : g_dest_list[index].name; -} - -int NWZ_TOOL_MAIN(dest_tool)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "dest_tool"); - /* open input device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_lcdmsg(false, 3, 4, "Cannot open input device"); - sleep(2); - return 1; - } - unsigned long model_id = nwz_get_model_id(); - if(model_id == 0) - { - nwz_key_close(input_fd); - nwz_lcdmsg(false, 3, 4, "Cannot get model ID"); - sleep(2); - return 1; - } - const char *model_name = nwz_get_model_name(); - if(model_name == NULL) - model_name = "Unknown"; - const char *series_name = "Unknown"; - bool ok_model = false; - if(nwz_get_series() != -1) - { - series_name = nwz_series[nwz_get_series()].name; - ok_model = true; - } - nwz_lcdmsgf(false, 0, 2, "Model ID: %#x", model_id); - nwz_lcdmsgf(false, 0, 3, "Model: %s", model_name); - nwz_lcdmsgf(false, 0, 4, "Series: %s", series_name); - nwz_lcdmsg(false, 0, 5, "BACK: quit"); - nwz_lcdmsg(false, 0, 6, "LEFT/RIGHT: change dest"); - nwz_lcdmsg(false, 0, 7, "PLAY/PAUSE: change sps"); - /* display input state in a loop */ - while(1) - { - unsigned char nvp_buf[32]; - bool ok_nvp = false; - if(ok_model) - { - /* make sure node has the right size... */ - if(nwz_nvp_read(NWZ_NVP_SHP, NULL) == sizeof(nvp_buf)) - { - if(nwz_nvp_read(NWZ_NVP_SHP, nvp_buf) == sizeof(nvp_buf)) - ok_nvp = true; - else - nwz_lcdmsg(false, 1, 9, "Cannot read NVP.\n"); - } - else - nwz_lcdmsg(false, 1, 9, "NVP node has the wrong size.\n"); - } - else - { - nwz_lcdmsg(false, 1, 9, "Your model is not supported.\n"); - nwz_lcdmsg(false, 1, 10, "Please contact a developer.\n"); - } - /* display information */ - if(ok_nvp) - { - unsigned long dest = read32(nvp_buf); - unsigned long sps = read32(nvp_buf + 4); - const char *dest_name = get_dest_name(dest); - const char *sps_name = sps ? "ON" : "OFF"; - nwz_lcdmsgf(false, 1, 9, "DEST: %s (%#x) ", dest_name, dest); - nwz_lcdmsgf(false, 1, 10, "SPS: %s (%d) ", sps_name, sps); - } - /* wait for event */ - int ret = nwz_key_wait_event(input_fd, -1); - if(ret != 1) - continue; - struct input_event evt; - if(nwz_key_read_event(input_fd, &evt) != 1) - continue; - /* only act on release */ - if(nwz_key_event_is_press(&evt)) - continue; - int keycode = nwz_key_event_get_keycode(&evt); - if(keycode == NWZ_KEY_BACK) - break; - bool write_nvp = false; - if(keycode == NWZ_KEY_LEFT || keycode == NWZ_KEY_RIGHT) - { - int dest_idx = get_dest_index(read32(nvp_buf)); - /* if destination is unknown, replace by the first one */ - if(dest_idx == -1) - dest_idx = 0; - if(keycode == NWZ_KEY_LEFT) - dest_idx--; - else - dest_idx++; - dest_idx = (dest_idx + NR_DEST) % NR_DEST; - write32(nvp_buf, g_dest_list[dest_idx].dest); - write_nvp = true; - } - else if(keycode == NWZ_KEY_PLAY) - { - /* change 0 to 1 and anything nonzero to 0 */ - write32(nvp_buf + 4, read32(nvp_buf + 4) == 0 ? 1 : 0); - write_nvp = true; - } - /* write nvp */ - if(ok_nvp && write_nvp) - { - if(nwz_nvp_write(NWZ_NVP_SHP, nvp_buf) != 0) - nwz_lcdmsg(false, 1, 12, "Cannot write NVP.\n"); - } - } - /* finish nicely */ - nwz_key_close(input_fd); - return 0; -} diff --git a/utils/nwztools/plattools/dualboot.c b/utils/nwztools/plattools/dualboot.c deleted file mode 100644 index c6d07c7508..0000000000 --- a/utils/nwztools/plattools/dualboot.c +++ /dev/null @@ -1,302 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2011 by Amaury Pouly - * - * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing - * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" -#include <time.h> -#include <errno.h> - -/* all images must have the following size */ -#define ICON_WIDTH 130 -#define ICON_HEIGHT 130 - -/* images */ -#include "data/rockbox_icon.h" -#if BMPWIDTH_rockbox_icon != ICON_WIDTH || BMPHEIGHT_rockbox_icon != ICON_HEIGHT -#error rockbox_icon has the wrong resolution -#endif -#include "data/tools_icon.h" -#if BMPWIDTH_tools_icon != ICON_WIDTH || BMPHEIGHT_tools_icon != ICON_HEIGHT -#error tools_icon has the wrong resolution -#endif -/* buffer for Sony image, filled from NVP */ -unsigned short sony_icon[ICON_WIDTH * ICON_HEIGHT]; -/* resolution */ -static int width, height, bpp; - -/* return icon y position (x is always centered) */ -int get_icon_y(void) -{ - /* adjust so that this contains the Sony logo and produces a nice logo - * when used with rockbox */ - if(height == 320) - return 70; - else if(height == 320) - return 100; - else - return height / 2 - ICON_HEIGHT + 30; /* guess, probably won't work */ -} - -/* Sony logo extraction */ -bool extract_sony_logo(void) -{ - /* only support bpp of 16 */ - if(bpp != 16) - return false; - /* load the entire image from the nvp */ - int bti_size = nwz_nvp_read(NWZ_NVP_BTI, NULL); - if(bti_size < 0) - return false; - unsigned short *bti = malloc(bti_size); - if(nwz_nvp_read(NWZ_NVP_BTI, bti) != bti_size) - return false; - /* compute the offset in the image of the logo itself */ - int x_off = (width - ICON_WIDTH) / 2; /* logo is centered horizontally */ - int y_off = get_icon_y(); - /* extract part of the image */ - for(int y = 0; y < ICON_HEIGHT; y++) - { - memcpy(sony_icon + ICON_WIDTH * y, - bti + width * (y + y_off) + x_off, ICON_WIDTH * sizeof(unsigned short)); - } - free(bti); - return true; -} - -/* Important Note: this bootloader is carefully written so that in case of - * error, the OF is run. This seems like the safest option since the OF is - * always there and might do magic things. */ - -enum boot_mode -{ - BOOT_ROCKBOX, - BOOT_TOOLS, - BOOT_OF -}; - -void draw_icon(int left, int top, const unsigned short *icon, unsigned short *fb_mmap) -{ - for(int y = 0; y < ICON_HEIGHT; y++) - { - memcpy(fb_mmap + width * (y + top) + left, icon + ICON_WIDTH * y, - ICON_WIDTH * sizeof(unsigned short)); - } -} - -enum boot_mode get_boot_mode(void) -{ - if(bpp != 16) - { - nwz_lcdmsg(true, 0, 2, "Unsupported bpp"); - sleep(2); - return BOOT_OF; - } - /* open framebuffer */ - int fb_fd = nwz_fb_open(true); - if(fb_fd < 0) - { - nwz_lcdmsg(true, 0, 2, "Cannot open input device"); - sleep(2); - return BOOT_OF; - } - /* open input device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_fb_close(fb_fd); - nwz_lcdmsg(true, 0, 2, "Cannot open input device"); - sleep(2); - return BOOT_OF; - } - int fb_size = width * height * bpp / 2; - void *fb_mmap = nwz_fb_mmap(fb_fd, 0, fb_size); - void *fb_mmap_p1 = nwz_fb_mmap(fb_fd, NWZ_FB_LCD_PAGE_OFFSET, fb_size); - if(fb_mmap == NULL || fb_mmap_p1 == NULL) - { - nwz_fb_close(fb_fd); - nwz_key_close(input_fd); - nwz_lcdmsg(true, 0, 2, "Cannot map framebuffer"); - sleep(2); - return BOOT_OF; - } - /* wait for user action */ - enum boot_mode mode = BOOT_OF; - /* NOTE on drawing: since screen is redrawn automatically, and we invoke - * external programs to draw, we can't hope to fit it in the frame time - * and it will flicker. To avoid this, we use the fact that all programs - * only write to page 0. So we setup the lcd to update from page 1. When - * we need to update the screen, we ask it to draw from page 0, then copy - * page 0 to page 1 and then switch back to page 1 */ - memset(fb_mmap_p1, 0xff, fb_size); /* clear page 1 */ - nwz_fb_set_page(fb_fd, 1); - bool redraw = true; - while(true) - { - if(redraw) - { - /* redraw screen on page 0: clear screen */ - memset(fb_mmap, 0, fb_size); - /* display top text */ - nwz_display_text_center(width, 0, true, NWZ_COLOR(255, 201, 0), - NWZ_COLOR(0, 0, 0), 0, "SELECT PLAYER"); - /* display icon */ - const unsigned short *icon = (mode == BOOT_OF) ? sony_icon : - (mode == BOOT_ROCKBOX) ? rockbox_icon : tools_icon; - draw_icon((width - ICON_WIDTH) / 2, get_icon_y(), icon, fb_mmap); - /* display bottom description */ - const char *desc = (mode == BOOT_OF) ? "SONY" : - (mode == BOOT_ROCKBOX) ? "ROCKBOX" : "DEBUG TOOLS"; - nwz_display_text_center(width, get_icon_y() + ICON_HEIGHT + 30, true, - NWZ_COLOR(255, 201, 0), NWZ_COLOR(0, 0, 0), 0, desc); - /* display arrows */ - int arrow_y = get_icon_y() + ICON_HEIGHT / 2 - NWZ_FONT_H(true) / 2; - nwz_display_text(NWZ_FONT_W(true) / 2, arrow_y, true, - NWZ_COLOR(255, 201, 0), NWZ_COLOR(0, 0, 0), 0, "<"); - nwz_display_text(width - 3 * NWZ_FONT_W(true) / 2, arrow_y, true, - NWZ_COLOR(255, 201, 0), NWZ_COLOR(0, 0, 0), 0, ">"); - /* switch to page 1 */ - nwz_fb_set_page(fb_fd, 0); - /* copy page 0 to page 1 */ - memcpy(fb_mmap_p1, fb_mmap, fb_size); - /* switch back to page 1 */ - nwz_fb_set_page(fb_fd, 1); - - redraw = false; - } - - /* wait for a key */ - int ret = nwz_key_wait_event(input_fd, -1); - if(ret != 1) - continue; - struct input_event evt; - if(nwz_key_read_event(input_fd, &evt) != 1) - continue; - /* only act on release */ - if(nwz_key_event_is_press(&evt)) - continue; - int key_code = nwz_key_event_get_keycode(&evt); - /* play -> stop loop and return mode */ - if(key_code == NWZ_KEY_PLAY) - break; - /* left/right/up/down: change mode */ - if(key_code == NWZ_KEY_LEFT || key_code == NWZ_KEY_DOWN) - { - if(mode == BOOT_ROCKBOX) - mode = BOOT_OF; - else if(mode == BOOT_OF) - mode = BOOT_TOOLS; - else - mode = BOOT_ROCKBOX; - redraw = true; - } - if(key_code == NWZ_KEY_RIGHT || key_code == NWZ_KEY_UP) - { - if(mode == BOOT_ROCKBOX) - mode = BOOT_TOOLS; - else if(mode == BOOT_OF) - mode = BOOT_ROCKBOX; - else - mode = BOOT_OF; - redraw = true; - } - } - /* switch back to page 0 */ - nwz_fb_set_page(fb_fd, 0); - nwz_key_close(input_fd); - nwz_fb_close(fb_fd); - return mode; -} - -static char *boot_rb_argv[] = -{ - "rockbox.sony", - NULL -}; - -int NWZ_TOOL_MAIN(all_tools)(int argc, char **argv); - -void error_screen(const char *msg) -{ - nwz_lcdmsg(true, 0, 0, msg); - sleep(3); -} - -void create_sony_logo(void) -{ - for(int y = 0; y < ICON_HEIGHT; y++) - for(int x = 0; x < ICON_WIDTH; x++) - sony_icon[y * ICON_WIDTH + x] = 0xf81f; -} - -int main(int argc, char **argv) -{ - /* 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); - /* get resolution */ - /* we also need to get the native resolution */ - if(nwz_fb_get_resolution(fb_fd, &width, &height, &bpp) != 0) - { - /* safe one */ - width = 240; - height = 320; - bpp = 16; - } - nwz_fb_close(fb_fd); - } - /* extract logo */ - if(!extract_sony_logo()) - create_sony_logo(); - /* 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) - { - /* Rockbox expects /.rockbox to contain themes, rocks, etc, but we - * cannot easily create this symlink because the root filesystem is - * mounted read-only. Although we could remount it read-write temporarily, - * this is neededlessly complicated and we defer this job to the dualboot - * install script */ - execvp("/contents/.rockbox/rockbox.sony", boot_rb_argv); - /* fallback to OF in case of failure */ - error_screen("Cannot boot Rockbox"); - sleep(5); - } - /* boot OF */ - execvp("/usr/local/bin/SpiderApp.of", argv); - error_screen("Cannot boot OF"); - sleep(5); - /* if we reach this point, everything failed, so return an error so that - * sysmgrd knows something is wrong */ - return 1; -} diff --git a/utils/nwztools/plattools/nwz_lib.c b/utils/nwztools/plattools/nwz_lib.c deleted file mode 100644 index a81d352ff0..0000000000 --- a/utils/nwztools/plattools/nwz_lib.c +++ /dev/null @@ -1,777 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_db.h" - -int nwz_run(const char *file, const char *args[], bool wait) -{ - pid_t child_pid = fork(); - if(child_pid != 0) - { - if(wait) - { - int status; - waitpid(child_pid, &status, 0); - return status; - } - else - return 0; - } - else - { - execvp(file, (char * const *)args); - _exit(1); - } -} - -char *nwz_run_pipe(const char *file, const char *args[], int *status) -{ - int pipe_fds[2]; - pipe(pipe_fds); - pid_t child_pid = fork(); - if(child_pid == 0) - { - dup2(pipe_fds[1], 1); /* redirect stdout */ - dup2(pipe_fds[1], 2); /* redirect stderr */ - close(pipe_fds[0]); /* close reading */ - close(pipe_fds[1]); /* close writing */ - execvp(file, (char * const *)args); - _exit(1); - } - else - { - close(pipe_fds[1]); /* close writing */ - char buffer[1024]; - char *output = malloc(1); - ssize_t count; - size_t size = 0; - while((count = read(pipe_fds[0], buffer, sizeof(buffer))) > 0) - { - output = realloc(output, size + count + 1); - memcpy(output + size, buffer, count); - size += count; - } - close(pipe_fds[0]); - output[size] = 0; - waitpid(child_pid, status, 0); - return output; - } -} - -void nwz_lcdmsg(bool clear, int x, int y, const char *msg) -{ - const char *path_lcdmsg = "/usr/local/bin/lcdmsg"; - const char *args[16]; - int index = 0; - char locate[32]; - args[index++] = "lcdmsg"; - if(clear) - args[index++] = "-c"; - args[index++] = "-f"; - args[index++] = "/usr/local/bin/font_08x12.bmp"; - args[index++] = "-l"; - sprintf(locate, "%d,%d", x, y); - args[index++] = locate; - args[index++] = msg; - args[index++] = NULL; - /* wait for lcdmsg to finish to avoid any race conditions in framebuffer - * accesses */ - nwz_run(path_lcdmsg, args, true); -} - -void nwz_lcdmsgf(bool clear, int x, int y, const char *format, ...) -{ - char buffer[1024]; - va_list args; - va_start(args, format); - vsprintf(buffer, format, args); - va_end(args); - nwz_lcdmsg(clear, x, y, buffer); -} - -#define NWZ_COLOR_RGB(col) \ - NWZ_COLOR_RED(col), NWZ_COLOR_GREEN(col), NWZ_COLOR_BLUE(col) - -void nwz_display_clear(nwz_color_t color) -{ - const char *path_display = "/usr/local/bin/display"; - const char *args[16]; - int index = 0; - char col[32]; - args[index++] = "display"; - args[index++] = "lcd"; - args[index++] = "clear"; - sprintf(col, "%d,%d,%d", NWZ_COLOR_RGB(color)); - args[index++] = col; - args[index++] = NULL; - /* wait for lcdmsg to finish to avoid any race conditions in framebuffer - * accesses */ - nwz_run(path_display, args, true); -} - -void nwz_display_text(int x, int y, bool big_font, nwz_color_t foreground_col, - nwz_color_t background_col, int alpha, const char *text) -{ - const char *path_display = "/usr/local/bin/display"; - const char *args[16]; - int index = 0; - char fg[32],bg[32], pos[32], transp[16]; - args[index++] = "display"; - args[index++] = "lcd"; - args[index++] = "text"; - sprintf(pos, "%d,%d", x, y); - args[index++] = pos; - if(big_font) - args[index++] = "/usr/local/bin/font_14x24.bmp"; - else - args[index++] = "/usr/local/bin/font_08x12.bmp"; - sprintf(fg, "%d,%d,%d", NWZ_COLOR_RGB(foreground_col)); - args[index++] = fg; - sprintf(bg, "%d,%d,%d", NWZ_COLOR_RGB(background_col)); - args[index++] = bg; - sprintf(transp, "%d", alpha); - args[index++] = transp; - args[index++] = text; - args[index++] = NULL; - /* wait for lcdmsg to finish to avoid any race conditions in framebuffer - * accesses */ - nwz_run(path_display, args, true); -} - -void nwz_display_text_center(int width, int y, bool big_font, nwz_color_t fg, - nwz_color_t bg, int alpha, const char *text) -{ - int txt_w = NWZ_FONT_W(big_font) * strlen(text); - nwz_display_text((width - txt_w) / 2, y, big_font, fg, bg, alpha, text); -} - -void nwz_display_textf(int x, int y, bool big_font, nwz_color_t foreground_col, - nwz_color_t background_col, int alpha, const char *fmt, ...) -{ - char buffer[1024]; - va_list args; - va_start(args, fmt); - vsprintf(buffer, fmt, args); - va_end(args); - nwz_display_text(x, y, big_font, foreground_col, background_col, alpha, buffer); -} - -void nwz_display_textf_center(int width, int y, bool big_font, nwz_color_t fg, - nwz_color_t bg, int alpha, const char *fmt, ...) -{ - char buffer[1024]; - va_list args; - va_start(args, fmt); - vsprintf(buffer, fmt, args); - va_end(args); - nwz_display_text_center(width, y, big_font, fg, bg, alpha, buffer); -} - -void nwz_display_bitmap(int x, int y, const char *file, int left, int top, - int width, int height, nwz_color_t key_col, int bmp_alpha) -{ - const char *path_display = "/usr/local/bin/display"; - const char *args[16]; - int index = 0; - char pos[32], topleft[32], dim[32], key[32], transp[16]; - args[index++] = "display"; - args[index++] = "lcd"; - args[index++] = "bitmap"; - sprintf(pos, "%d,%d", x, y); - args[index++] = pos; - args[index++] = file; - sprintf(topleft, "%d,%d", left, top); - args[index++] = topleft; - sprintf(dim, "%d,%d", width, height); - args[index++] = dim; - if(key_col == NWZ_COLOR_NO_KEY) - sprintf(key, "no"); - else - sprintf(key, "%d,%d,%d", NWZ_COLOR_RGB(key_col)); - args[index++] = key; - sprintf(transp, "%d", bmp_alpha); - args[index++] = transp; - args[index++] = NULL; - /* wait for lcdmsg to finish to avoid any race conditions in framebuffer - * accesses */ - nwz_run(path_display, args, true); -} - -int nwz_input_open(const char *requested_name) -{ - /* try all /dev/input/eventX, there can't a lot of them */ - for(int index = 0; index < 8; index++) - { - char buffer[32]; - sprintf(buffer, "/dev/input/event%d", index); - int fd = open(buffer, O_RDWR); - if(fd < 0) - continue; /* try next one */ - /* query name */ - char name[256]; - if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) >= 0 && - strcmp(name, requested_name) == 0) - return fd; - close(fd); - } - return -1; -} - -int nwz_key_open(void) -{ - return nwz_input_open(NWZ_KEY_NAME); -} - -void nwz_key_close(int fd) -{ - close(fd); -} - -int nwz_key_get_hold_status(int fd) -{ - unsigned long led_hold = 0; - if(ioctl(fd, EVIOCGLED(sizeof(led_hold)), &led_hold) < 0) - return -1; - return led_hold; -} - -int nwz_key_wait_event(int fd, long tmo_us) -{ - return nwz_wait_fds(&fd, 1, tmo_us); -} - -int nwz_key_read_event(int fd, struct input_event *evt) -{ - int ret = read(fd, evt, sizeof(struct input_event)); - if(ret != sizeof(struct input_event)) - return -1; - return 1; -} - -int nwz_key_event_get_keycode(struct input_event *evt) -{ - return evt->code & NWZ_KEY_MASK; -} - -bool nwz_key_event_is_press(struct input_event *evt) -{ - return evt->value == 0; -} - -bool nwz_key_event_get_hold_status(struct input_event *evt) -{ - return !!(evt->code & NWZ_KEY_HOLD_MASK); -} - -static const char *nwz_keyname[NWZ_KEY_MASK + 1] = -{ - [0 ... NWZ_KEY_MASK] = "unknown", - [NWZ_KEY_PLAY] = "PLAY", - [NWZ_KEY_RIGHT] = "RIGHT", - [NWZ_KEY_LEFT] = "LEFT", - [NWZ_KEY_UP] = "UP", - [NWZ_KEY_DOWN] = "DOWN", - [NWZ_KEY_ZAPPIN] = "ZAPPIN", - [NWZ_KEY_AD0_6] = "AD0_6", - [NWZ_KEY_AD0_7] = "AD0_7", - [NWZ_KEY_NONE] = "NONE", - [NWZ_KEY_VOL_DOWN] = "VOL DOWN", - [NWZ_KEY_VOL_UP] = "VOL UP", - [NWZ_KEY_BACK] = "BACK", - [NWZ_KEY_OPTION] = "OPTION", - [NWZ_KEY_BT] = "BT", - [NWZ_KEY_AD1_5] = "AD1_5", - [NWZ_KEY_AD1_6] = "AD1_6", - [NWZ_KEY_AD1_7] = "AD1_7", -}; - -const char *nwz_key_get_name(int keycode) -{ - if(keycode <0 || keycode > NWZ_KEY_MASK) - return "invalid"; - else - return nwz_keyname[keycode]; -} - -int nwz_fb_open(bool lcd) -{ - return open(lcd ? NWZ_FB_LCD_DEV : NWZ_FB_TV_DEV, O_RDWR); -} - -void nwz_fb_close(int fd) -{ - close(fd); -} - -int nwz_fb_get_brightness(int fd, struct nwz_fb_brightness *bl) -{ - if(ioctl(fd, NWZ_FB_GET_BRIGHTNESS, bl) < 0) - return -1; - else - return 1; -} - -int nwz_fb_set_brightness(int fd, struct nwz_fb_brightness *bl) -{ - if(ioctl(fd, NWZ_FB_SET_BRIGHTNESS, bl) < 0) - return -1; - else - return 1; -} - -int nwz_fb_set_page(int fd, int page) -{ - /* set page 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 = page; - mode_info.update = NWZ_FB_ONLY_2D_MODE; - if(ioctl(fd, NWZ_FB_UPDATE, &mode_info) < 0) - return -2; - return 0; -} - -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; - return nwz_fb_set_page(fd, 0); -} - -int nwz_fb_get_resolution(int fd, int *x, int *y, int *bpp) -{ - struct fb_var_screeninfo vinfo; - if(ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) - return -1; - if(x) - *x = vinfo.xres; - if(y) - *y = vinfo.yres; - if(bpp) - *bpp = vinfo.bits_per_pixel; - return 0; -} - -void *nwz_fb_mmap(int fd, int offset, int size) -{ - return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)offset); -} - -int nwz_adc_open(void) -{ - return open(NWZ_ADC_DEV, O_RDONLY); -} - -void nwz_adc_close(int fd) -{ - close(fd); -} - -static const char *nwz_adc_name[] = -{ - [NWZ_ADC_VCCBAT] = "VCCBAT", - [NWZ_ADC_VCCVBUS] = "VCCVBUS", - [NWZ_ADC_ADIN3] = "ADIN3", - [NWZ_ADC_ADIN4] = "ADIN4", - [NWZ_ADC_ADIN5] = "ADIN5", - [NWZ_ADC_ADIN6] = "ADIN6", - [NWZ_ADC_ADIN7] = "ADIN7", - [NWZ_ADC_ADIN8] = "ADIN8", -}; - -const char *nwz_adc_get_name(int ch) -{ - return nwz_adc_name[ch]; -} - -int nwz_adc_get_val(int fd, int ch) -{ - unsigned char val; - if(ioctl(fd, NWZ_ADC_GET_VAL(ch), &val) < 0) - return -1; - else - return val; -} - -int nwz_ts_open(void) -{ - return nwz_input_open(NWZ_TS_NAME); -} - -void nwz_ts_close(int fd) -{ - close(fd); -} - -int nwz_ts_state_init(int fd, struct nwz_ts_state_t *state) -{ - memset(state, 0, sizeof(struct nwz_ts_state_t)); - struct input_absinfo info; - if(ioctl(fd, EVIOCGABS(ABS_X), &info) < 0) - return -1; - state->max_x = info.maximum; - if(ioctl(fd, EVIOCGABS(ABS_Y), &info) < 0) - return -1; - state->max_y = info.maximum; - if(ioctl(fd, EVIOCGABS(ABS_PRESSURE), &info) < 0) - return -1; - state->max_pressure = info.maximum; - if(ioctl(fd, EVIOCGABS(ABS_TOOL_WIDTH), &info) < 0) - return -1; - state->max_tool_width = info.maximum; - return 1; -} - -int nwz_ts_state_update(struct nwz_ts_state_t *state, struct input_event *evt) -{ - switch(evt->type) - { - case EV_SYN: - return 1; - case EV_REL: - if(evt->code == REL_RX) - state->flick_x = evt->value; - else if(evt->code == REL_RY) - state->flick_y = evt->value; - else - return -1; - state->flick = true; - break; - case EV_ABS: - if(evt->code == ABS_X) - state->x = evt->value; - else if(evt->code == ABS_Y) - state->y = evt->value; - else if(evt->code == ABS_PRESSURE) - state->pressure = evt->value; - else if(evt->code == ABS_TOOL_WIDTH) - state->tool_width = evt->value; - else - return -1; - break; - case EV_KEY: - if(evt->code == BTN_TOUCH) - state->touch = evt->value; - else - return -1; - break; - default: - return -1; - } - return 0; -} - -int nwz_ts_state_post_syn(struct nwz_ts_state_t *state) -{ - state->flick = false; - return 1; -} - -int nwz_ts_read_events(int fd, struct input_event *evts, int nr_evts) -{ - int ret = read(fd, evts, nr_evts * sizeof(struct input_event)); - if(ret < 0) - return -1; - return ret / sizeof(struct input_event); -} - -long nwz_wait_fds(int *fds, int nr_fds, long tmo_us) -{ - fd_set rfds; - struct timeval tv; - struct timeval *tv_ptr = NULL; - /* watch the input device */ - FD_ZERO(&rfds); - int max_fd = 0; - for(int i = 0; i < nr_fds; i++) - { - FD_SET(fds[i], &rfds); - if(fds[i] > max_fd) - max_fd = fds[i]; - } - /* setup timeout */ - if(tmo_us >= 0) - { - tv.tv_sec = 0; - tv.tv_usec = tmo_us; - tv_ptr = &tv; - } - int ret = select(max_fd + 1, &rfds, NULL, NULL, tv_ptr); - if(ret <= 0) - return ret; - long bitmap = 0; - for(int i = 0; i < nr_fds; i++) - if(FD_ISSET(fds[i], &rfds)) - bitmap |= 1 << i; - return bitmap; -} - -int nwz_power_open(void) -{ - return open(NWZ_POWER_DEV, O_RDWR); -} - -void nwz_power_close(int fd) -{ - close(fd); -} - -int nwz_power_get_status(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_STATUS, &status) < 0) - return -1; - return status; -} - -static int nwz_power_adval_to_mv(int adval, int ad_base) -{ - if(adval == -1) - return -1; - /* the AD base corresponds to the millivolt value if adval was 255 */ - return (adval * ad_base) / 255; -} - -int nwz_power_get_vbus_adval(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_VBUS_ADVAL, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_vbus_voltage(int fd) -{ - return nwz_power_adval_to_mv(nwz_power_get_vbus_adval(fd), NWZ_POWER_AD_BASE_VBUS); -} - -int nwz_power_get_vbus_limit(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_VBUS_LIMIT, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_charge_switch(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_CHARGE_SWITCH, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_charge_current(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_CHARGE_CURRENT, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_battery_gauge(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_BAT_GAUGE, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_battery_adval(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_BAT_ADVAL, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_battery_voltage(int fd) -{ - return nwz_power_adval_to_mv(nwz_power_get_battery_adval(fd), NWZ_POWER_AD_BASE_VBAT); -} - -int nwz_power_get_vbat_adval(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_VBAT_ADVAL, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_vbat_voltage(int fd) -{ - return nwz_power_adval_to_mv(nwz_power_get_vbat_adval(fd), NWZ_POWER_AD_BASE_VBAT); -} - -int nwz_power_get_sample_count(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_SAMPLE_COUNT, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_vsys_adval(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_VSYS_ADVAL, &status) < 0) - return -1; - return status; -} - -int nwz_power_get_vsys_voltage(int fd) -{ - return nwz_power_adval_to_mv(nwz_power_get_vsys_adval(fd), NWZ_POWER_AD_BASE_VSYS); -} - -int nwz_power_get_acc_charge_mode(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_GET_ACCESSARY_CHARGE_MODE, &status) < 0) - return -1; - return status; -} - -int nwz_power_is_fully_charged(int fd) -{ - int status; - if(ioctl(fd, NWZ_POWER_IS_FULLY_CHARGED, &status) < 0) - return -1; - return status; -} - -int nwz_pminfo_open(void) -{ - return open(NWZ_PMINFO_DEV, O_RDONLY); -} - -void nwz_pminfo_close(int fd) -{ - close(fd); -} - -unsigned int nwz_pminfo_get_factor(int fd) -{ - unsigned int val; - if(ioctl(fd, NWZ_PMINFO_GET_FACTOR, &val) < 0) - return 0; - else - return val; -} - -static unsigned long find_model_id(void) -{ - /* try with the environment variable */ - const char *mid = getenv("ICX_MODEL_ID"); - if(mid == NULL) - return 0; - char *end; - unsigned long v = strtoul(mid, &end, 0); - if(*end) - return 0; - else - return v; -} - -unsigned long nwz_get_model_id(void) -{ - static unsigned long model_id = 0xffffffff; - if(model_id == 0xffffffff) - model_id = find_model_id(); - return model_id; -} - -const char *nwz_get_model_name() -{ - for(int i = 0; i < NWZ_MODEL_COUNT; i++) - if(nwz_model[i].mid == nwz_get_model_id()) - return nwz_model[i].name; - return NULL; -} - -static int find_series(void) -{ - for(int i = 0; i < NWZ_SERIES_COUNT; i++) - for(int j = 0; j < nwz_series[i].mid_count; j++) - if(nwz_series[i].mid[j] == nwz_get_model_id()) - return i; - return -1; -} - -int nwz_get_series(void) -{ - static int series = -2; - if(series == -2) - series = find_series(); - return series; -} - -static nwz_nvp_index_t *get_nvp_index(void) -{ - static nwz_nvp_index_t *index = 0; - if(index == 0) - { - int series = nwz_get_series(); - index = series < 0 ? 0 : nwz_series[series].nvp_index; - } - return index; -} - -int nwz_nvp_read(enum nwz_nvp_node_t node, void *data) -{ - int size = nwz_nvp[node].size; - if(data == 0) - return size; - nwz_nvp_index_t *index = get_nvp_index(); - if(index == 0 || (*index)[node] == NWZ_NVP_INVALID) - return -1; - char nvp_path[32]; - snprintf(nvp_path, sizeof(nvp_path), "/dev/icx_nvp/%03d", (*index)[node]); - int fd = open(nvp_path, O_RDONLY); - if(fd < 0) - return -1; - int cnt = read(fd, data, size); - close(fd); - return cnt == size ? size : -1; -} - -int nwz_nvp_write(enum nwz_nvp_node_t node, void *data) -{ - int size = nwz_nvp[node].size; - nwz_nvp_index_t *index = get_nvp_index(); - if(index == 0 || (*index)[node] == NWZ_NVP_INVALID) - return -1; - char nvp_path[32]; - snprintf(nvp_path, sizeof(nvp_path), "/dev/icx_nvp/%03d", (*index)[node]); - int fd = open(nvp_path, O_WRONLY); - if(fd < 0) - return -1; - int cnt = write(fd, data, size); - close(fd); - return cnt == size ? 0 : -1; -} diff --git a/utils/nwztools/plattools/nwz_lib.h b/utils/nwztools/plattools/nwz_lib.h deleted file mode 100644 index 23bb80986d..0000000000 --- a/utils/nwztools/plattools/nwz_lib.h +++ /dev/null @@ -1,220 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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. - * - ****************************************************************************/ -#ifndef _NWZLIB_H_ -#define _NWZLIB_H_ - -#include <stdio.h> -#include <stdbool.h> -#include <stdarg.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <linux/input.h> -#include <linux/fb.h> -#include <fcntl.h> -#include <string.h> -#include <stdlib.h> -#include <sys/mman.h> - -#include "nwz_keys.h" -#include "nwz_fb.h" -#include "nwz_adc.h" -#include "nwz_ts.h" -#include "nwz_power.h" -#include "nwz_db.h" - -/* get model ID, either from ICX_MODEL_ID env var or using nvpflag, return 0 - * in case of error; note that the result is cached so this function is only - * expensive the first time it is called */ -unsigned long nwz_get_model_id(void); -/* get series (index into nwz_series, or -1 on error) */ -int nwz_get_series(void); -/* get model name, or null on error */ -const char *nwz_get_model_name(void); - -/* run a program and exit with nonzero status in case of error - * argument list must be NULL terminated */ -int nwz_run(const char *file, const char *args[], bool wait); -/* run a program and return program output */ -char *nwz_run_pipe(const char *file, const char *args[], int *status); - -/* invoke /usr/local/bin/lcdmsg to display a message using the small font, optionally - * clearing the screen before */ -void nwz_lcdmsg(bool clear, int x, int y, const char *msg); -void nwz_lcdmsgf(bool clear, int x, int y, const char *format, ...); -/* invoke /usr/local/bin/display to do various things: - * - clear screen - * - display text - * - display bitmap - * Currently all operations are performed on the LCD only. - * The small text font is 8x12 and the big one is 14x24 */ -typedef int nwz_color_t; -#define NWZ_COLOR(r, g, b) /* each component between 0 and 255 */ \ - ((r) << 16 | (g) << 8 | (b)) -#define NWZ_COLOR_RED(col) ((col) >> 16) -#define NWZ_COLOR_GREEN(col) (((col) >> 8) & 0xff) -#define NWZ_COLOR_BLUE(col) ((col) & 0xff) -#define NWZ_COLOR_NO_KEY (1 << 24) - -#define NWZ_FONT_W(big_font) ((big_font) ? 14 : 8) -#define NWZ_FONT_H(big_font) ((big_font) ? 24 : 14) - -void nwz_display_clear(nwz_color_t color); -void nwz_display_text(int x, int y, bool big_font, nwz_color_t foreground_col, - nwz_color_t background_col, int background_alpha, const char *text); -void nwz_display_text_center(int width, int y, bool big_font, nwz_color_t foreground_col, - nwz_color_t background_col, int background_alpha, const char *text); -void nwz_display_textf(int x, int y, bool big_font, nwz_color_t foreground_col, - nwz_color_t background_col, int background_alpha, const char *fmt, ...); -void nwz_display_textf_center(int width, int y, bool big_font, nwz_color_t foreground_col, - nwz_color_t background_col, int background_alpha, const char *fmt, ...); -void nwz_display_bitmap(int x, int y, const char *file, int left, int top, - int width, int height, nwz_color_t key, int bmp_alpha); - -/* open icx_key input device and return file descriptor */ -int nwz_key_open(void); -void nwz_key_close(int fd); -/* return HOLD status: 0 or 1, or -1 on error */ -int nwz_key_get_hold_status(int fd); -/* wait for an input event (and return 1), or a timeout (return 0), or error (-1) - * set the timeout to -1 to block */ -int nwz_key_wait_event(int fd, long tmo_us); -/* read an event from the device (may block unless you waited for an event before), - * return 1 on success, <0 on error */ -int nwz_key_read_event(int fd, struct input_event *evt); -/* return keycode from event */ -int nwz_key_event_get_keycode(struct input_event *evt); -/* return press/released status from event */ -bool nwz_key_event_is_press(struct input_event *evt); -/* return HOLD status from event */ -bool nwz_key_event_get_hold_status(struct input_event *evt); -/* get keycode name */ -const char *nwz_key_get_name(int keycode); - -/* open framebuffer device */ -int nwz_fb_open(bool lcd); -/* close framebuffer device */ -void nwz_fb_close(int fb); -/* get screen resolution, parameters are allowed to be NULL */ -int nwz_fb_get_resolution(int fd, int *x, int *y, int *bpp); -/* get backlight brightness (return -1 on error, 1 on success) */ -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); -/* change framebuffer page and update screen */ -int nwz_fb_set_page(int fd, int page); -/* map framebuffer */ -void *nwz_fb_mmap(int fd, int offset, int size); - -/* open adc device */ -int nwz_adc_open(void); -/* close adc device */ -void nwz_adc_close(int fd); -/* get channel name */ -const char *nwz_adc_get_name(int ch); -/* read channel value, return -1 on error */ -int nwz_adc_get_val(int fd, int ch); - -/* open touchscreen device */ -int nwz_ts_open(void); -/* close touchscreen device */ -void nwz_ts_close(int fd); -/* structure to track touch state */ -struct nwz_ts_state_t -{ - int x, y; /* current position (valid is touch is true) */ - int max_x, max_y; /* maximum possible values */ - int pressure, tool_width; /* current pressure and tool width */ - int max_pressure, max_tool_width; /* maximum possible values */ - bool touch; /* is the user touching the screen? */ - bool flick; /* was the action a flick? */ - int flick_x, flick_y; /* if so, this is the flick direction */ -}; -/* get touchscreen information and init state, return -1 on error, 1 on success */ -int nwz_ts_state_init(int fd, struct nwz_ts_state_t *state); -/* update state with an event, return -1 on unhandled event, >=0 on handled: - * 1 if sync event, 0 otherwise */ -int nwz_ts_state_update(struct nwz_ts_state_t *state, struct input_event *evt); -/* update state after a sync event to prepare for next round of events */ -int nwz_ts_state_post_syn(struct nwz_ts_state_t *state); -/* read at most N events from touch screen, and return the number of events */ -int nwz_ts_read_events(int fd, struct input_event *evts, int nr_evts); - -/* wait for events on several file descriptors, return a bitmap of active ones - * or 0 on timeout, the timeout can be -1 to block */ -long nwz_wait_fds(int *fds, int nr_fds, long timeout_us); - -/* open power device */ -int nwz_power_open(void); -/* close power device */ -void nwz_power_close(int fd); -/* get power status (return -1 on error, bitmap on success) */ -int nwz_power_get_status(int fd); -/* get vbus adval (or -1 on error) */ -int nwz_power_get_vbus_adval(int fd); -/* get vbus voltage in mV (or -1 on error) */ -int nwz_power_get_vbus_voltage(int fd); -/* get vbus current limit (or -1 on error) */ -int nwz_power_get_vbus_limit(int fd); -/* get charge switch (or -1 on error) */ -int nwz_power_get_charge_switch(int fd); -/* get charge current (or -1 on error) */ -int nwz_power_get_charge_current(int fd); -/* get battery gauge (or -1 on error) */ -int nwz_power_get_battery_gauge(int fd); -/* get battery adval (or -1 on error) */ -int nwz_power_get_battery_adval(int fd); -/* get battery voltage in mV (or -1 on error) */ -int nwz_power_get_battery_voltage(int fd); -/* get vbat adval (or -1 on error) */ -int nwz_power_get_vbat_adval(int fd); -/* get vbat voltage (or -1 on error) */ -int nwz_power_get_vbat_voltage(int fd); -/* get sample count (or -1 on error) */ -int nwz_power_get_sample_count(int fd); -/* get vsys adval (or -1 on error) */ -int nwz_power_get_vsys_adval(int fd); -/* get vsys voltage in mV (or -1 on error) */ -int nwz_power_get_vsys_voltage(int fd); -/* get accessory charge mode */ -int nwz_power_get_acc_charge_mode(int fd); -/* is battery fully charged? (or -1 on error) */ -int nwz_power_is_fully_charged(int fd); - -/* open pminfo device */ -int nwz_pminfo_open(void); -/* close pminfo device */ -void nwz_pminfo_close(int fd); -/* get pminfo factor (or 0 on error) */ -unsigned int nwz_pminfo_get_factor(int fd); - -/* read a nvp node and return its size, if the data pointer is null, then simply - * return the size, return -1 on error */ -int nwz_nvp_read(enum nwz_nvp_node_t node, void *data); -/* write a nvp node, return 0 on success and -1 on error, the size of the buffer - * must be the one returned by nwz_nvp_read */ -int nwz_nvp_write(enum nwz_nvp_node_t node, void *data); - - -#endif /* _NWZLIB_H_ */ diff --git a/utils/nwztools/plattools/test_adc.c b/utils/nwztools/plattools/test_adc.c deleted file mode 100644 index 31b685c43e..0000000000 --- a/utils/nwztools/plattools/test_adc.c +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -int NWZ_TOOL_MAIN(test_adc)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "test_adc"); - nwz_lcdmsg(false, 0, 2, "BACK: quit"); - /* open input device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_lcdmsg(false, 3, 4, "Cannot open input device"); - sleep(2); - return 1; - } - /* open adc device */ - int adc_fd = nwz_adc_open(); - if(adc_fd < 0) - { - nwz_key_close(input_fd); - nwz_lcdmsg(false, 3, 4, "Cannot open adc device"); - sleep(2); - return 1; - } - /* display input state in a loop */ - while(1) - { - /* print channels */ - for(int i = NWZ_ADC_MIN_CHAN; i <= NWZ_ADC_MAX_CHAN; i++) - nwz_lcdmsgf(false, 1, 4 + i, "%s: %d ", nwz_adc_get_name(i), - nwz_adc_get_val(adc_fd, i)); - /* 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); - nwz_adc_close(adc_fd); - return 0; -} diff --git a/utils/nwztools/plattools/test_bl.c b/utils/nwztools/plattools/test_bl.c deleted file mode 100644 index 594cbbd377..0000000000 --- a/utils/nwztools/plattools/test_bl.c +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -int NWZ_TOOL_MAIN(test_bl)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "test_bl"); - nwz_lcdmsg(false, 0, 2, "LEFT/RIGHT: level"); - nwz_lcdmsg(false, 0, 3, "UP/DOWN: step"); - nwz_lcdmsg(false, 0, 4, "VOL UP/DOWN: period"); - nwz_lcdmsg(false, 0, 5, "BACK: quit"); - /* open input and framebuffer device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_lcdmsg(false, 3, 7, "Cannot open input device"); - sleep(2); - return 1; - } - int fb_fd = nwz_fb_open(true); - if(fb_fd < 0) - { - nwz_key_close(input_fd); - nwz_lcdmsg(false, 3, 7, "Cannot open framebuffer device"); - sleep(2); - return 1; - } - /* display input state in a loop */ - while(1) - { - struct nwz_fb_brightness bl; - if(nwz_fb_get_brightness(fb_fd, &bl) == 1) - { - nwz_lcdmsgf(false, 1, 7, "level: %d ", bl.level); - nwz_lcdmsgf(false, 1, 8, "step: %d ", bl.step); - nwz_lcdmsgf(false, 1, 9, "period: %d ", bl.period); - } - /* wait for event */ - int ret = nwz_key_wait_event(input_fd, -1); - if(ret != 1) - continue; - struct input_event evt; - if(nwz_key_read_event(input_fd, &evt) != 1) - continue; - int code = nwz_key_event_get_keycode(&evt); - bool press = nwz_key_event_is_press(&evt); - /* only act on release */ - if(press) - continue; - if(code == NWZ_KEY_BACK) - break; /* quit */ - bool change_bl = false; - if(code == NWZ_KEY_RIGHT && bl.level < NWZ_FB_BL_MAX_LEVEL) - { - change_bl = true; - bl.level++; - } - else if(code == NWZ_KEY_LEFT && bl.level > NWZ_FB_BL_MIN_LEVEL) - { - change_bl = true; - bl.level--; - } - else if(code == NWZ_KEY_UP && bl.step < NWZ_FB_BL_MAX_STEP) - { - change_bl = true; - bl.step++; - } - else if(code == NWZ_KEY_DOWN && bl.step > NWZ_FB_BL_MIN_STEP) - { - change_bl = true; - bl.step--; - } - else if(code == NWZ_KEY_VOL_UP && bl.period < 100) /* artificial bound on period */ - { - change_bl = true; - bl.period++; - } - else if(code == NWZ_KEY_VOL_DOWN && bl.period > NWZ_FB_BL_MIN_PERIOD) - { - change_bl = true; - bl.period--; - } - /* change bl */ - if(change_bl) - nwz_fb_set_brightness(fb_fd, &bl); - } - /* close input device */ - nwz_key_close(input_fd); - nwz_fb_close(fb_fd); - /* finish nicely */ - return 0; -} diff --git a/utils/nwztools/plattools/test_display.c b/utils/nwztools/plattools/test_display.c deleted file mode 100644 index b05b246b6f..0000000000 --- a/utils/nwztools/plattools/test_display.c +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -int NWZ_TOOL_MAIN(test_display)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_display_clear(NWZ_COLOR(128, 128, 0)); - nwz_display_text(0, 0, true, NWZ_COLOR(255, 0, 0), NWZ_COLOR(0, 0, 255), 0, - "Hello"); - nwz_display_text(0, 30, false, NWZ_COLOR(255, 0, 0), NWZ_COLOR(0, 0, 255), 128, - "BACK: quit"); - nwz_display_text(0, 50, false, NWZ_COLOR(255, 0, 0), NWZ_COLOR(0, 0, 255), 255, - "BACK: quit"); - /* display /contents/display.bmp if any */ - const char *bmp_fname = "/contents/display.bmp"; - if(access(bmp_fname, R_OK) != -1) - { - nwz_display_bitmap(10, 70, bmp_fname, 0, 0, 200, 200, NWZ_COLOR_NO_KEY, 255); - } - else - { - nwz_display_text(0, 70, false, NWZ_COLOR(255, 0, 0), NWZ_COLOR(0, 0, 0), 0, - "Cannot find display.bmp"); - } - /* 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; -} diff --git a/utils/nwztools/plattools/test_fb.c b/utils/nwztools/plattools/test_fb.c deleted file mode 100644 index 77e8d4e497..0000000000 --- a/utils/nwztools/plattools/test_fb.c +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2011 by Amaury Pouly - * - * Based on Rockbox iriver bootloader by Linus Nielsen Feltzing - * and the ipodlinux bootloader by Daniel Palffy and Bernard Leach - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" -#include <linux/fb.h> -#include <stdint.h> -#include <sys/mman.h> - -static struct fb_fix_screeninfo finfo; -static struct fb_var_screeninfo vinfo; -static uint8_t *framebuffer; - -static inline uint32_t read32(uint8_t *p) -{ - return *p | *(p + 1) << 8 | *(p + 2) << 16 | *(p + 3) << 24; -} - -static inline void write32(uint8_t *p, uint32_t val) -{ - *p++ = val & 0xff; val >>= 8; - *p++ = val & 0xff; val >>= 8; - *p++ = val & 0xff; val >>= 8; - *p++ = val; -} - -/* assume lsb and little-endian */ -static inline void put_pix_mask(uint8_t *location, int offset, int len, uint8_t pix) -{ - /* adjust pixel */ - pix >>= 8 - len; - uint32_t mask = ((1 << len) - 1) << offset; - uint32_t val = read32(location); - val = ((val) & ~mask) | pix << offset; - write32(location, val); -} - -static inline void put_pix(int x, int y, uint8_t r, uint8_t g, uint8_t b) -{ - x += vinfo.xoffset; - y += vinfo.yoffset; - uint8_t *location = framebuffer + x * (vinfo.bits_per_pixel / 8) + y * finfo.line_length; - put_pix_mask(location, vinfo.red.offset, vinfo.red.length, r); - put_pix_mask(location, vinfo.green.offset, vinfo.green.length, g); - put_pix_mask(location, vinfo.blue.offset, vinfo.blue.length, b); -} - -static void dump_fb(FILE *out, const char *path) -{ - fprintf(out, "%s:\n", path); - int fd = open(path, O_RDWR); - if(fd < 0) - { - fprintf(out, " cannot open"); - return; - } - /* get fixed info */ - if(ioctl(fd, FBIOGET_FSCREENINFO, &finfo) < 0) - { - fprintf(out, " ioctl failed (fix info)"); - close(fd); - return; - } - fprintf(out, " identification: %s\n", finfo.id); - fprintf(out, " type: %d\n", finfo.type); - fprintf(out, " visual: %d\n", finfo.visual); - fprintf(out, " accel: %d\n", finfo.accel); - fprintf(out, " line length: %d\n", finfo.line_length); - fprintf(out, " mem length: %d\n", finfo.smem_len); - /* get variable info */ - if(ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) < 0) - { - close(fd); - fprintf(out, " ioctl failed (var info)"); - return; - } - fprintf(out, " xres: %d\n", vinfo.xres); - fprintf(out, " yres: %d\n", vinfo.yres); - fprintf(out, " xoff: %d\n", vinfo.xoffset); - fprintf(out, " yoff: %d\n", vinfo.yoffset); - fprintf(out, " bbp: %d\n", vinfo.bits_per_pixel); - fprintf(out, " red: %d-%d\n", vinfo.red.offset + vinfo.red.length - 1, vinfo.red.offset); - fprintf(out, " green: %d-%d\n", vinfo.green.offset + vinfo.green.length - 1, vinfo.green.offset); - fprintf(out, " blue: %d-%d\n", vinfo.blue.offset + vinfo.blue.length - 1, vinfo.blue.offset); - /* get mode info */ - struct nwz_fb_image_info mode_info; - nwz_fb_set_standard_mode(fd); - if(ioctl(fd, NWZ_FB_GET_MODE, &mode_info) < 0) - { - close(fd); - fprintf(out, " ioctl failed (get mode)\n"); - return; - } - fprintf(out, " tc_enable: %d\n", mode_info.tc_enable); - fprintf(out, " t_color: %d\n", mode_info.t_color); - fprintf(out, " alpha: %d\n", mode_info.alpha); - fprintf(out, " rot: %d\n", mode_info.rot); - fprintf(out, " page: %d\n", mode_info.page); - fprintf(out, " update: %d\n", mode_info.update); - /* mmap device (but avoid TV) */ - if(vinfo.xres != 720) - { - long screensize = vinfo.yres_virtual * finfo.line_length; - framebuffer = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, (off_t)0); - if(framebuffer == 0) - { - close(fd); - fprintf(out, " mmap failed"); - return; - } - for(int y = 0; y < 10; y++) - for(int x = 0; x < 10; x++) - { - put_pix(x, y, 0xff, 0, 0); - put_pix(x + 10, y, 0, 0xff, 0); - put_pix(x + 20, y, 0, 0, 0xff); - } - } - sleep(3); - close(fd); -} - -int NWZ_TOOL_MAIN(test_fb)(int argc, char **argv) -{ - FILE *f = fopen("/contents/fb.txt", "w"); - if(!f) - f = stdout; - dump_fb(f, "/dev/fb/0"); - if(f) - fclose(f); - return 0; -} diff --git a/utils/nwztools/plattools/test_keys.c b/utils/nwztools/plattools/test_keys.c deleted file mode 100644 index 353864d96f..0000000000 --- a/utils/nwztools/plattools/test_keys.c +++ /dev/null @@ -1,105 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -int NWZ_TOOL_MAIN(test_keys)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "test_keys"); - nwz_lcdmsg(false, 0, 2, "BACK: hold 3 seconds to quit"); - /* open input device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_lcdmsg(false, 3, 4, "Cannot open input device"); - sleep(2); - return 1; - } - /* display input state in a loop */ - int back_pressed = 0; /* 0 = no pressed, >0 = number of seconds pressed - 1 */ -#define FIRST_LINE 7 -#define LAST_LINE 17 - int event_line = FIRST_LINE; - int prev_evt_line = -1; - while(1) - { - /* display HOLD status */ - nwz_lcdmsgf(false, 2, 5, "HOLD: %d", nwz_key_get_hold_status(input_fd)); - /* wait for event */ - int ret = nwz_key_wait_event(input_fd, 1000000); - if(ret != 1) - { - if(back_pressed > 0) - back_pressed++; - if(back_pressed >= 4) - break; - continue; - } - struct input_event evt; - if(nwz_key_read_event(input_fd, &evt) != 1) - continue; - /* erase last '>' indicator */ - if(prev_evt_line != -1) - nwz_lcdmsg(false, 0, prev_evt_line, " "); - prev_evt_line = event_line; - char buffer[32]; - int len = sprintf(buffer, "> %s %s (HOLD=%d)", - nwz_key_get_name(nwz_key_event_get_keycode(&evt)), - nwz_key_event_is_press(&evt) ? "pressed" : "released", - nwz_key_event_get_hold_status(&evt)); - /* pad with spaces to erase old stuff */ - while(len + 1 < sizeof(buffer)) - buffer[len++] = ' '; - buffer[len] = 0; - /* print line */ - nwz_lcdmsg(false, 0, event_line, buffer); - /* compute next line */ - event_line++; - if(event_line == LAST_LINE) - event_line = FIRST_LINE; - /* handle quit */ - if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && nwz_key_event_is_press(&evt)) - back_pressed = 1; - else - back_pressed = 0; - } - /* wait until back is released, to avoid messing with all_tools (if embedded) */ - nwz_lcdmsg(true, 0, 0, "test_keys"); - nwz_lcdmsg(false, 0, 2, "BACK: release to quit"); - 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; - } - /* close input device */ - nwz_key_close(input_fd); - /* finish nicely */ - return 0; -} diff --git a/utils/nwztools/plattools/test_power.c b/utils/nwztools/plattools/test_power.c deleted file mode 100644 index f0d374bf7b..0000000000 --- a/utils/nwztools/plattools/test_power.c +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -static const char *charge_status_name(int chgstat) -{ - switch(chgstat) - { - case NWZ_POWER_STATUS_CHARGE_STATUS_CHARGING: return "charging"; - case NWZ_POWER_STATUS_CHARGE_STATUS_SUSPEND: return "suspend"; - case NWZ_POWER_STATUS_CHARGE_STATUS_TIMEOUT: return "timeout"; - case NWZ_POWER_STATUS_CHARGE_STATUS_NORMAL: return "normal"; - default: return "unknown"; - } -} - -static const char *get_batt_gauge_name(int gauge) -{ - switch(gauge) - { - case NWZ_POWER_BAT_NOBAT: return "no batt"; - case NWZ_POWER_BAT_VERYLOW: return "very low"; - case NWZ_POWER_BAT_LOW: return "low"; - case NWZ_POWER_BAT_GAUGE0: return "____"; - case NWZ_POWER_BAT_GAUGE1: return "O___"; - case NWZ_POWER_BAT_GAUGE2: return "OO__"; - case NWZ_POWER_BAT_GAUGE3: return "OOO_"; - case NWZ_POWER_BAT_GAUGE4: return "OOOO"; - default: return "unknown"; - } -} - -static const char *acc_charge_mode_name(int mode) -{ - switch(mode) - { - case NWZ_POWER_ACC_CHARGE_NONE: return "none"; - case NWZ_POWER_ACC_CHARGE_VBAT: return "vbat"; - case NWZ_POWER_ACC_CHARGE_VSYS: return "vsys"; - default: return "unknown"; - } -} - -int NWZ_TOOL_MAIN(test_power)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "test_power"); - nwz_lcdmsg(false, 0, 2, "BACK: quit"); - /* open input device */ - int input_fd = nwz_key_open(); - if(input_fd < 0) - { - nwz_lcdmsg(false, 3, 4, "Cannot open input device"); - sleep(2); - return 1; - } - /* open adc device */ - int power_fd = nwz_power_open(); - if(power_fd < 0) - { - nwz_key_close(input_fd); - nwz_lcdmsg(false, 3, 4, "Cannot open power device"); - sleep(2); - return 1; - } - /* open pminfo device */ - int pminfo_fd = nwz_pminfo_open(); - if(pminfo_fd < 0) - { - nwz_key_close(power_fd); - nwz_key_close(input_fd); - nwz_lcdmsg(false, 3, 4, "Cannot open pminfo device"); - sleep(2); - return 1; - } - /* display input state in a loop */ - while(1) - { - /* print status */ - int line = 4; - int status = nwz_power_get_status(power_fd); - int chgstat = status & NWZ_POWER_STATUS_CHARGE_STATUS; - int acc_chg_mode = nwz_power_get_acc_charge_mode(power_fd); - nwz_lcdmsgf(false, 0, line++, "ac detected: %s ", - (status & NWZ_POWER_STATUS_AC_DET) ? "yes" : "no"); - nwz_lcdmsgf(false, 0, line++, "vbus detected: %s ", - (status & NWZ_POWER_STATUS_VBUS_DET) ? "yes" : "no"); - nwz_lcdmsgf(false, 0, line++, "vbus voltage: %d mV (AD=%d) ", - nwz_power_get_vbus_voltage(power_fd), nwz_power_get_vbus_adval(power_fd)); - nwz_lcdmsgf(false, 0, line++, "vbus limit: %d mA ", - nwz_power_get_vbus_limit(power_fd)); - nwz_lcdmsgf(false, 0, line++, "vsys voltage: %d mV (AD=%d) ", - nwz_power_get_vsys_voltage(power_fd), nwz_power_get_vsys_adval(power_fd)); - nwz_lcdmsgf(false, 0, line++, "charge switch: %s ", - nwz_power_get_charge_switch(power_fd) ? "on" : "off"); - nwz_lcdmsgf(false, 0, line++, "full voltage: %s V ", - (status & NWZ_POWER_STATUS_CHARGE_LOW) ? "4.1" : "4.2"); - nwz_lcdmsgf(false, 0, line++, "current limit: %d mA ", - nwz_power_get_charge_current(power_fd)); - nwz_lcdmsgf(false, 0, line++, "charge status: %s (%x) ", - charge_status_name(chgstat), chgstat); - nwz_lcdmsgf(false, 0, line++, "battery full: %s ", - nwz_power_is_fully_charged(power_fd) ? "yes" : "no"); - nwz_lcdmsgf(false, 0, line++, "bat gauge: %s (%d) ", - get_batt_gauge_name(nwz_power_get_battery_gauge(power_fd)), - nwz_power_get_battery_gauge(power_fd)); - nwz_lcdmsgf(false, 0, line++, "avg voltage: %d mV (AD=%d) ", - nwz_power_get_battery_voltage(power_fd), nwz_power_get_battery_adval(power_fd)); - nwz_lcdmsgf(false, 0, line++, "sample count: %d ", - nwz_power_get_sample_count(power_fd)); - nwz_lcdmsgf(false, 0, line++, "raw voltage: %d mV (AD=%d) ", - nwz_power_get_vbat_voltage(power_fd), nwz_power_get_vbat_adval(power_fd)); - nwz_lcdmsgf(false, 0, line++, "acc charge mode: %s (%d) ", - acc_charge_mode_name(acc_chg_mode), acc_chg_mode); - /* pminfo */ - line++; - nwz_lcdmsgf(false, 0, line++, "pminfo: %#x ", nwz_pminfo_get_factor(pminfo_fd)); - /* wait for event (1s) */ - 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; - if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && !nwz_key_event_is_press(&evt)) - break; - } - /* finish nicely */ - nwz_key_close(power_fd); - nwz_key_close(input_fd); - nwz_pminfo_close(pminfo_fd); - return 0; -} diff --git a/utils/nwztools/plattools/test_ts.c b/utils/nwztools/plattools/test_ts.c deleted file mode 100644 index b42d93bd09..0000000000 --- a/utils/nwztools/plattools/test_ts.c +++ /dev/null @@ -1,98 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2016 Amaury Pouly - * - * 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 "nwz_lib.h" -#include "nwz_plattools.h" - -int NWZ_TOOL_MAIN(test_ts)(int argc, char **argv) -{ - /* clear screen and display welcome message */ - nwz_lcdmsg(true, 0, 0, "test_ts"); - nwz_lcdmsg(false, 0, 2, "BACK: quit"); - /* open input device */ - int key_fd = nwz_key_open(); - if(key_fd < 0) - { - nwz_lcdmsg(false, 3, 4, "Cannot open key device"); - sleep(2); - return 1; - } - int ts_fd = nwz_ts_open(); - if(ts_fd < 0) - { - nwz_key_close(key_fd); - nwz_lcdmsg(false, 3, 4, "Cannot open touch screen device"); - sleep(2); - return 1; - } - /* init state and print maximum information */ - struct nwz_ts_state_t ts_state; - if(nwz_ts_state_init(ts_fd, &ts_state) < 0) - { - nwz_key_close(key_fd); - nwz_ts_close(ts_fd); - nwz_lcdmsg(false, 3, 4, "Cannot init touch screen device"); - sleep(2); - return 1; - } - /* display static information */ - nwz_lcdmsgf(false, 1, 6, "size: %d, %d ", ts_state.max_x, ts_state.max_y); - /* display input state in a loop */ - while(1) - { - /* wait for event */ - int fds[2] = {key_fd, ts_fd}; - int ret = nwz_wait_fds(fds, 2, -1); - if(ret & 1) /* key_fd */ - { - struct input_event evt; - if(nwz_key_read_event(key_fd, &evt) == 1) - { - if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_BACK && - nwz_key_event_is_press(&evt)) - break; /* quit */ - } - } - if(ret & 2) /* ts_fd */ - { -#define NR_TS_EVTS 16 - struct input_event evts[NR_TS_EVTS]; - int nr = nwz_ts_read_events(ts_fd, evts, NR_TS_EVTS); - for(int i = 0; i < nr; i++) - if(nwz_ts_state_update(&ts_state, &evts[i]) == 1) - { - nwz_lcdmsgf(false, 1, 7, "touch: %s ", ts_state.touch ? "yes" : "no"); - nwz_lcdmsgf(false, 1, 8, "pos: %d, %d ", ts_state.x, ts_state.y); - nwz_lcdmsgf(false, 1, 9, "pressure: %d ", ts_state.pressure); - nwz_lcdmsgf(false, 1, 10, "width: %d ", ts_state.tool_width); - nwz_lcdmsgf(false, 1, 11, "flick: %s ", ts_state.flick ? "yes" : "no"); - nwz_lcdmsgf(false, 1, 12, "flick vec: %d, %d ", ts_state.flick_x, ts_state.flick_y); - /* process touch */ - nwz_ts_state_post_syn(&ts_state); - } -#undef NR_TS_EVTS - } - } - /* close input device */ - nwz_key_close(key_fd); - nwz_ts_close(ts_fd); - /* finish nicely */ - return 0; -} diff --git a/utils/nwztools/scripts/install_dualboot.sh b/utils/nwztools/scripts/install_dualboot.sh index c134929312..2e2bd050cc 100644 --- a/utils/nwztools/scripts/install_dualboot.sh +++ b/utils/nwztools/scripts/install_dualboot.sh @@ -36,8 +36,6 @@ exec > "$CONTENTS/install_dualboot_log.txt" 2>&1 . /install_script/constant.txt _UPDATE_FN_=`nvpstr ufn` ROOTFS_TMP_DIR=/tmp/rootfs -ROCKBOX_NAME=Rockbox -ROCKBOX_PATH=$ROOTFS_TMP_DIR/usr/local/bin/$ROCKBOX_NAME SPIDERAPP_PATH=$ROOTFS_TMP_DIR/usr/local/bin/SpiderApp # mount root partition @@ -51,8 +49,12 @@ fi # NOTE some platforms use ext4 with a custom mount program # (/usr/local/bin/icx_mount.ext4), some probably use an mtd too +# try ext3 and if it fails, try ext2 mount -t ext3 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR if [ "$?" != 0 ]; then + mount -t ext2 $COMMON_ROOTFS_PARTITION $ROOTFS_TMP_DIR +fi +if [ "$?" != 0 ]; then lcdmsg -f /usr/local/bin/font_08x12.bmp -l 0,15 "ERROR: mount failed" sleep 3 exit 0 diff --git a/utils/nwztools/scsitools/Makefile b/utils/nwztools/scsitools/Makefile index 6b2d7a86a4..53b901427f 100644 --- a/utils/nwztools/scsitools/Makefile +++ b/utils/nwztools/scsitools/Makefile @@ -3,7 +3,7 @@ DEFINES= PREFIX?= CC=$(PREFIX)gcc LD=$(PREFIX)gcc -NWZ_DB_DIR=../database +NWZ_DB_DIR=../../../firmware/target/hosted/sonynwz INCLUDES=-I$(NWZ_DB_DIR) -I$(SCSI_DIR) CFLAGS=-std=c99 -Wall $(DEFINES) $(INCLUDES) LDFLAGS=-L$(SCSI_DIR) -lrbscsi @@ -11,7 +11,7 @@ BINS=scsitool all: $(BINS) -scsitool: scsitool.c misc.c para_noise.c $(NWZ_DB_DIR)/nwz_db.c +scsitool: scsitool.c misc.c para_noise.c $(NWZ_DB_DIR)/nwz-db.c $(MAKE) -C $(SCSI_DIR) $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) diff --git a/utils/nwztools/scsitools/scsitool.c b/utils/nwztools/scsitools/scsitool.c index 7b8ffd5f17..63a23c416d 100644 --- a/utils/nwztools/scsitools/scsitool.c +++ b/utils/nwztools/scsitools/scsitool.c @@ -34,7 +34,7 @@ #include "rbscsi.h" #include "misc.h" #include "para_noise.h" -#include "nwz_db.h" +#include "nwz-db.h" bool g_debug = false; const char *g_force_series = NULL; |