summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES20
-rw-r--r--firmware/asm/SOURCES2
-rw-r--r--firmware/drivers/audio/nwzlinux-codec.c385
-rw-r--r--firmware/export/audiohw.h2
-rw-r--r--firmware/export/backtrace.h36
-rw-r--r--firmware/export/config.h11
-rw-r--r--firmware/export/config/sonynwza10.h16
-rw-r--r--firmware/export/config/sonynwze450.h16
-rw-r--r--firmware/export/config/sonynwze460.h16
-rw-r--r--firmware/export/config/sonynwze470.h16
-rw-r--r--firmware/export/config/sonynwze580.h16
-rw-r--r--firmware/export/config/sonynwzlinux.h105
-rw-r--r--firmware/export/nwzlinux_codec.h29
-rw-r--r--firmware/export/rbpaths.h8
-rw-r--r--firmware/export/system.h2
-rw-r--r--firmware/font.c2
-rw-r--r--firmware/panic.c2
-rw-r--r--firmware/target/arm/system-arm.c2
-rw-r--r--firmware/target/hosted/alsa-controls.c181
-rw-r--r--firmware/target/hosted/alsa-controls.h51
-rw-r--r--firmware/target/hosted/backtrace-glibc.c60
-rw-r--r--firmware/target/hosted/filesystem-app.c5
-rw-r--r--firmware/target/hosted/pcm-alsa.c89
-rw-r--r--firmware/target/hosted/pcm-alsa.h31
-rw-r--r--firmware/target/hosted/sonynwz/adc-nwz.c63
-rw-r--r--firmware/target/hosted/sonynwz/adc-target.h47
-rw-r--r--firmware/target/hosted/sonynwz/backlight-target.h29
-rw-r--r--firmware/target/hosted/sonynwz/button-nwz.c323
-rw-r--r--firmware/target/hosted/sonynwz/button-target.h47
-rw-r--r--firmware/target/hosted/sonynwz/debug-nwz.c439
-rw-r--r--firmware/target/hosted/sonynwz/lcd-nwz.c200
-rw-r--r--firmware/target/hosted/sonynwz/lcd-target.h146
-rw-r--r--firmware/target/hosted/sonynwz/nvp-nwz.c119
-rw-r--r--firmware/target/hosted/sonynwz/nvp-nwz.h41
-rw-r--r--firmware/target/hosted/sonynwz/nwz-db.c1337
-rw-r--r--firmware/target/hosted/sonynwz/nwz-db.h193
-rw-r--r--firmware/target/hosted/sonynwz/nwz_audio.h112
-rw-r--r--firmware/target/hosted/sonynwz/nwz_keys.h63
-rw-r--r--firmware/target/hosted/sonynwz/nwz_sysinfo.h72
-rw-r--r--firmware/target/hosted/sonynwz/nwz_ts.h35
-rw-r--r--firmware/target/hosted/sonynwz/power-nwz.c208
-rw-r--r--firmware/target/hosted/sonynwz/power-nwz.h155
-rw-r--r--firmware/target/hosted/sonynwz/powermgmt-nwz.c69
-rw-r--r--firmware/target/hosted/sonynwz/sonynwz.make82
-rw-r--r--firmware/target/hosted/sonynwz/system-nwz.c204
-rw-r--r--firmware/target/hosted/sonynwz/system-target.h34
46 files changed, 5095 insertions, 26 deletions
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/firmware/target/hosted/sonynwz/adc-target.h b/firmware/target/hosted/sonynwz/adc-target.h
new file mode 100644
index 0000000000..bee028a8ac
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/adc-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 _ADC_NWZ_H_
+#define _ADC_NWZ_H_
+
+#include "adc.h"
+
+#define NWZ_ADC_DEV "/dev/icx_adc"
+
+#define NWZ_ADC_TYPE 'm'
+
+#define NWZ_ADC_MIN_CHAN 0
+#define NWZ_ADC_MAX_CHAN 7
+
+#define NWZ_ADC_VCCBAT 0
+#define NWZ_ADC_VCCVBUS 1
+#define NWZ_ADC_ADIN3 2
+#define NWZ_ADC_ADIN4 3
+#define NWZ_ADC_ADIN5 4
+#define NWZ_ADC_ADIN6 5
+#define NWZ_ADC_ADIN7 6
+#define NWZ_ADC_ADIN8 7
+
+#define NWZ_ADC_GET_VAL(chan) _IOR(NWZ_ADC_TYPE, chan, unsigned char)
+
+/* 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/firmware/target/hosted/sonynwz/lcd-target.h b/firmware/target/hosted/sonynwz/lcd-target.h
new file mode 100644
index 0000000000..dcc4a61c69
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/lcd-target.h
@@ -0,0 +1,146 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 __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"
+
+#define NWZ_FB_TYPE 'N'
+
+/* How backlight works:
+ *
+ * The brightness interface is a bit strange. There 6 levels: 0 throught 5.
+ * Level 0 means backlight off. When changing brightness, one sets level to the
+ * target brightness. The driver is gradually change the brightness to reach the
+ * target level. The step parameters control how many hardware steps will be done.
+ * For example, setting step to 1 will brutally change the level in one step.
+ * Setting step to 2 will change brightness in two steps: one intermediate and
+ * finally the target one. The more steps, the more gradual the transition. The
+ * period parameters controls the speed to changes between steps. Using this
+ * interface, one can achieve fade in/out at various speeds. */
+#define NWZ_FB_BL_MIN_LEVEL 0
+#define NWZ_FB_BL_MAX_LEVEL 5
+#define NWZ_FB_BL_MIN_STEP 1
+#define NWZ_FB_BL_MAX_STEP 100
+#define NWZ_FB_BL_MIN_PERIOD 10
+
+struct nwz_fb_brightness
+{
+ int level; /* brightness level: 0-5 */
+ int step; /* number of hardware steps to do when changing: 1-100 */
+ int period; /* period in ms between steps when changing: >=10 */
+};
+
+/* FB extensions:
+ *
+ * Sony added relatively complicated extensions to the framebuffer. They allow
+ * better control of framebuffer refresh, double-buffering and mixing with DSP
+ * (v4l2). Each outout (LCD and TV) has two buffers, called page 0 and 1 (or A
+ * and B). Each page has its own attributes (image info) that control
+ * transparency, rotation and updates. At any point in time, the LCD is drawing
+ * a page and one can select the next page to draw. Unless an UPDATE ioctl()
+ * is made to change it, the next page will be the same as the one being drawn.
+ *
+ * FIXME I don't know what the timer is, it seems irrelevant for the LCD but
+ * the OF uses it for TV, maybe this controls the refresh rate of the TV output?
+ * 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):
+ * - BB(0): AQUILA BB LCD
+ * - SW(1): SWAN or FIJI LCD
+ * - FC(2): FALCON OLED
+ * - GM(3): GUAM and ROTA LCD
+ * - FR(5): FURANO LCD ---> /!\ DOES NOT APPLY /!\
+ * - SD(6): SPICA_D LCD
+ * - AQ(7): AQUILA LCD
+ */
+
+/* Image infomation:
+ * SET_MODE will change the attributes of the requested page (ie .page)
+ * GET_MODE will return the attributes of the currently being displayed page
+ * UPDATE will do the same thing as SET_MODE but immediately refreshes the screen */
+struct nwz_fb_image_info
+{
+ int tc_enable; /* enable(1)/disable(0) transparent color */
+ int t_color; /* transparent color (16bpp RGB565) */
+ int alpha; /* alpha ratio (0 - 255) */
+ int page; /* 2D framebuffer page(0/1) */
+ int rot; /* LCD image rotation(0/1=180deg.) */
+ int update; /* only use with NWZ_FB_UPDATE, ignored for others */
+};
+
+/* update type */
+#define NWZ_FB_ONLY_2D_MODE 0
+#define NWZ_FB_DSP_AND_2D_MODE 1
+
+/* frame buffer page infomation: when NWZ_FB_WAIT_REFREHS is called, the driver
+ * will wait until the next refresh or the timeout, whichever comes first. It
+ * will then fill this structure with the page status. */
+struct nwz_fb_status
+{
+ int timeout; /* waiting time for any frame ready (in units of 10 ms) */
+ int page0; /* page 0 is out of display or waiting to be displayed */
+ int page1; /* page 0 is out of display or waiting to be displayed */
+};
+
+/* frame buffer page status */
+#define NWZ_FB_OUT_OF_DISPLAY 0
+#define NWZ_FB_WAITING_FOR_ON_DISPLAY 1
+
+/* frame buffer update timer infomation (use I/F fb <-> 2D API) */
+struct nwz_fb_update_timer
+{
+ int timerflag; /* auto update off(0) / auto update on(1) */
+ int timeout; /* timeout timer value (ms) */
+};
+
+/* timer flags */
+#define NWZ_FB_TIMER_ON 1
+#define NWZ_FB_TIMER_OFF 0
+
+/* default and minimum timeout value */
+#define NWZ_FB_DEFAULT_TIMEOUT 60
+#define NWZ_FB_MIN_TIMEOUT 33
+
+/* mmap offsets for page 1 (page 0 is always at address 0) */
+#define NWZ_FB_LCD_PAGE_OFFSET 0x2f000
+
+/* NOTE: I renamed those from Sony's header, because their original names were
+ * pure crap */
+#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)
+/* 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__ */
+
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/firmware/target/hosted/sonynwz/nwz-db.c b/firmware/target/hosted/sonynwz/nwz-db.c
new file mode 100644
index 0000000000..2aef1e3a49
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/nwz-db.c
@@ -0,0 +1,1337 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+/** /!\ This file was automatically generated, DO NOT MODIFY IT DIRECTLY /!\ */
+
+#include "nwz-db.h"
+
+struct nwz_model_info_t nwz_model[NWZ_MODEL_COUNT] =
+{
+ { 0x10000, "NWZ-A815" },
+ { 0x10001, "NWZ-A816" },
+ { 0x10002, "NWZ-A818" },
+ { 0x1000000, "NW-S615F" },
+ { 0x1000001, "NW-S616F" },
+ { 0x1010000, "NW-S715F" },
+ { 0x1010001, "NW-S716F" },
+ { 0x1010002, "NW-S718F" },
+ { 0x1020000, "NWZ-S615F" },
+ { 0x1020001, "NWZ-S616F" },
+ { 0x1020002, "NWZ-S618F" },
+ { 0x1030000, "NWZ-S515" },
+ { 0x1030001, "NWZ-S516" },
+ { 0x1040000, "NWZ-S715F" },
+ { 0x1040001, "NWZ-S716F" },
+ { 0x1040002, "NWZ-S718F" },
+ { 0x2000001, "NW-A916" },
+ { 0x2000002, "NW-A918" },
+ { 0x2000004, "NW-A919" },
+ { 0x3000001, "NWZ-A826" },
+ { 0x3000002, "NWZ-A828" },
+ { 0x3000004, "NWZ-A829" },
+ { 0x3010001, "NW-A826" },
+ { 0x3010002, "NW-A828" },
+ { 0x3010004, "NW-A829" },
+ { 0x3020001, "NWZ-A726B" },
+ { 0x3020002, "NWZ-A728B" },
+ { 0x3020004, "NWZ-A729B" },
+ { 0x3030001, "NWZ-A726" },
+ { 0x3030002, "NWZ-A728" },
+ { 0x3030004, "NWZ-A729" },
+ { 0x4000001, "NW-S636F" },
+ { 0x4000002, "NW-S638F" },
+ { 0x4000004, "NW-S639F" },
+ { 0x4010001, "NW-S736F" },
+ { 0x4010002, "NW-S738F" },
+ { 0x4010004, "NW-S739F" },
+ { 0x4020001, "NWZ-S636F" },
+ { 0x4020002, "NWZ-S638F" },
+ { 0x4020004, "NWZ-S639F" },
+ { 0x4030001, "NWZ-S736F" },
+ { 0x4030002, "NWZ-S738F" },
+ { 0x4030004, "NWZ-S739F" },
+ { 0x5000002, "NW-X1040" },
+ { 0x5000004, "NW-X1050" },
+ { 0x5000005, "NW-X1060" },
+ { 0x5010002, "NWZ-NONAME" },
+ { 0x5010004, "NWZ-NONAME" },
+ { 0x5010005, "NWZ-NONAME" },
+ { 0x5020002, "NWZ-X1040" },
+ { 0x5020004, "NWZ-X1050" },
+ { 0x5020005, "NWZ-X1060" },
+ { 0x5040002, "NWZ-X1041" },
+ { 0x5040004, "NWZ-X1051" },
+ { 0x5040005, "NWZ-X1061" },
+ { 0x6010002, "NW-S644" },
+ { 0x6010004, "NW-S645" },
+ { 0x6010005, "NW-S646" },
+ { 0x6020002, "NWZ-S744" },
+ { 0x6020004, "NWZ-S745" },
+ { 0x6020005, "NWZ-S746" },
+ { 0x6030002, "NW-S744" },
+ { 0x6030004, "NW-S745" },
+ { 0x6030005, "NW-S746" },
+ { 0x7000004, "NWZ-A845" },
+ { 0x7000005, "NWZ-A846" },
+ { 0x7000006, "NWZ-A847" },
+ { 0x7010004, "NW-A845" },
+ { 0x7010005, "NW-A846" },
+ { 0x7010006, "NW-A847" },
+ { 0x8000000, "NW-E052" },
+ { 0x8000001, "NW-E053" },
+ { 0x8000002, "NW-E054" },
+ { 0x9000002, "NW-S754" },
+ { 0x9000004, "NW-S755" },
+ { 0x9000005, "NW-S756" },
+ { 0xb000001, "NWZ-E453" },
+ { 0xb000002, "NWZ-E454" },
+ { 0xb000004, "NWZ-E455" },
+ { 0xc000001, "NWZ-E353" },
+ { 0xc000002, "NWZ-E354" },
+ { 0xc000004, "NWZ-E355" },
+ { 0xd000001, "NWZ-E553" },
+ { 0xd000002, "NWZ-E554" },
+ { 0xd000004, "NWZ-E555" },
+ { 0xd000005, "NWZ-E556" },
+ { 0xe000004, "NWZ-A855" },
+ { 0xe000005, "NWZ-A856" },
+ { 0xe000006, "NWZ-A857" },
+ { 0xf000002, "NWZ-S754" },
+ { 0xf000004, "NWZ-S755" },
+ { 0x10000000, "NWZ-E052" },
+ { 0x10000001, "NWZ-E053" },
+ { 0x11000001, "NW-A863" },
+ { 0x11000002, "NW-A864" },
+ { 0x11000004, "NW-A865" },
+ { 0x11000005, "NW-A866" },
+ { 0x11000006, "NW-A867" },
+ { 0x11010001, "NWZ-A863" },
+ { 0x11010002, "NWZ-A864" },
+ { 0x11010004, "NWZ-A865" },
+ { 0x11010005, "NWZ-A866" },
+ { 0x11010006, "NWZ-A867" },
+ { 0x11020001, "NWZ-A863" },
+ { 0x11020002, "NWZ-A864" },
+ { 0x11020004, "NWZ-A865" },
+ { 0x11020005, "NWZ-A866" },
+ { 0x11020006, "NWZ-A867" },
+ { 0x12000001, "NW-S763" },
+ { 0x12000002, "NW-S764" },
+ { 0x12000004, "NW-S765" },
+ { 0x12000005, "NW-S766" },
+ { 0x12000006, "NW-S767" },
+ { 0x12010001, "NWZ-S763" },
+ { 0x12010002, "NWZ-S764" },
+ { 0x12010004, "NWZ-S765" },
+ { 0x12010005, "NWZ-S766" },
+ { 0x12010006, "NWZ-S767" },
+ { 0x13000001, "NWZ-E463" },
+ { 0x13000002, "NWZ-E464" },
+ { 0x13000004, "NWZ-E465" },
+ { 0x14000000, "NW-E062" },
+ { 0x14000001, "NW-E063" },
+ { 0x14000002, "NW-E064" },
+ { 0x14000004, "NW-E065" },
+ { 0x14000005, "NW-E066" },
+ { 0x15000001, "NWZ-E473" },
+ { 0x15000002, "NWZ-E474" },
+ { 0x15000004, "NWZ-E475" },
+ { 0x15000005, "NWZ-E476" },
+ { 0x15010001, "NWZ-E573" },
+ { 0x15010002, "NWZ-E574" },
+ { 0x15010004, "NWZ-E575" },
+ { 0x15010005, "NWZ-E576" },
+ { 0x16000001, "NW-S773" },
+ { 0x16000002, "NW-S774" },
+ { 0x16000004, "NW-S775" },
+ { 0x16000005, "NW-S776" },
+ { 0x16010001, "NWZ-S773" },
+ { 0x16010002, "NWZ-S774" },
+ { 0x16010004, "NWZ-S775" },
+ { 0x16010005, "NWZ-S776" },
+ { 0x19000001, "NW-S783" },
+ { 0x19000002, "NW-S784" },
+ { 0x19000004, "NW-S785" },
+ { 0x19000005, "NW-S786" },
+ { 0x19010001, "NW-E083" },
+ { 0x19010002, "NW-E084" },
+ { 0x19010004, "NW-E085" },
+ { 0x19010005, "NW-E086" },
+ { 0x19020001, "NWZ-E583" },
+ { 0x19020002, "NWZ-E584" },
+ { 0x19020004, "NWZ-E585" },
+ { 0x19020005, "NWZ-E586" },
+ { 0x1a000001, "NW-A13" },
+ { 0x1a000002, "NW-A14" },
+ { 0x1a000004, "NW-A15" },
+ { 0x1a000005, "NW-A16" },
+ { 0x1a000006, "NW-A17" },
+ { 0x1a010001, "NWZ-A13" },
+ { 0x1a010002, "NWZ-A14" },
+ { 0x1a010004, "NWZ-A15" },
+ { 0x1a010005, "NWZ-A16" },
+ { 0x1a010006, "NWZ-A17" },
+ { 0x1b000001, "NW-S13" },
+ { 0x1b000002, "NW-S14" },
+ { 0x1b000004, "NW-S15" },
+ { 0x1b000005, "NW-S16" },
+ { 0x1b000006, "NW-S17" },
+ { 0x1c000001, "NW-ZX103" },
+ { 0x1c000002, "NW-ZX104" },
+ { 0x1c000004, "NW-ZX105" },
+ { 0x1c000005, "NW-ZX106" },
+ { 0x1c000006, "NW-ZX107" },
+ { 0x1c000007, "NW-ZX100" },
+ { 0x1d000001, "NW-A23" },
+ { 0x1d000002, "NW-A24" },
+ { 0x1d000004, "NW-A25" },
+ { 0x1d000005, "NW-A26" },
+ { 0x1d000006, "NW-A27" },
+ { 0x1d000007, "NW-A28" },
+ { 0x20000007, "NW-WM1A" },
+ { 0x21000008, "NW-WM1Z" },
+ { 0x22000004, "NW-A35" },
+ { 0x22000005, "NW-A36" },
+ { 0x22000006, "NW-A37" },
+};
+
+static int nvp_index_0ac81d[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = 5,
+ [NWZ_NVP_BFD] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BFP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BOK] = 10,
+ [NWZ_NVP_BPR] = 35,
+ [NWZ_NVP_BTC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BTI] = 1,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 3,
+ [NWZ_NVP_CTR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBA] = 12,
+ [NWZ_NVP_DBG] = 0,
+ [NWZ_NVP_DBI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBV] = 13,
+ [NWZ_NVP_DCC] = 7,
+ [NWZ_NVP_DG0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DOR] = 21,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 22,
+ [NWZ_NVP_EP0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP2] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP3] = NWZ_NVP_INVALID,
+ [NWZ_NVP_ERI] = 6,
+ [NWZ_NVP_EXM] = 25,
+ [NWZ_NVP_FMP] = 82,
+ [NWZ_NVP_FNI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FPI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FUI] = 19,
+ [NWZ_NVP_FUP] = 9,
+ [NWZ_NVP_FUR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FVI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_GTY] = 18,
+ [NWZ_NVP_HDI] = 2,
+ [NWZ_NVP_HLD] = 80,
+ [NWZ_NVP_INS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_IPT] = 70,
+ [NWZ_NVP_KAS] = 32,
+ [NWZ_NVP_LBI] = 20,
+ [NWZ_NVP_LYR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MAC] = 77,
+ [NWZ_NVP_MCR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDL] = 8,
+ [NWZ_NVP_MID] = 16,
+ [NWZ_NVP_MLK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSC] = 84,
+ [NWZ_NVP_MSO] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MTM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MUK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_NCP] = 31,
+ [NWZ_NVP_NVR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PCD] = 26,
+ [NWZ_NVP_PCI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PNC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PRK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PSK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PTS] = 75,
+ [NWZ_NVP_RBT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RND] = 28,
+ [NWZ_NVP_RTC] = 34,
+ [NWZ_NVP_SDC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SDP] = 30,
+ [NWZ_NVP_SER] = 4,
+ [NWZ_NVP_SFI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHE] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHP] = 11,
+ [NWZ_NVP_SID] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SKD] = 81,
+ [NWZ_NVP_SKT] = 76,
+ [NWZ_NVP_SKU] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SLP] = 69,
+ [NWZ_NVP_SPS] = 83,
+ [NWZ_NVP_SYI] = 24,
+ [NWZ_NVP_TR0] = 14,
+ [NWZ_NVP_TR1] = 15,
+ [NWZ_NVP_TST] = 17,
+ [NWZ_NVP_UBP] = 23,
+ [NWZ_NVP_UFN] = 29,
+ [NWZ_NVP_UMS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_UPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VAR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VRT] = NWZ_NVP_INVALID,
+};
+
+static int nvp_index_28dc2c[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BFD] = 21,
+ [NWZ_NVP_BFP] = 20,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = 22,
+ [NWZ_NVP_BOK] = 4,
+ [NWZ_NVP_BPR] = 19,
+ [NWZ_NVP_BTC] = 85,
+ [NWZ_NVP_BTI] = 72,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 23,
+ [NWZ_NVP_CTR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBA] = 24,
+ [NWZ_NVP_DBG] = 0,
+ [NWZ_NVP_DBI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBV] = 25,
+ [NWZ_NVP_DCC] = 31,
+ [NWZ_NVP_DG0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DOR] = 26,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 71,
+ [NWZ_NVP_EP0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP2] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP3] = NWZ_NVP_INVALID,
+ [NWZ_NVP_ERI] = 76,
+ [NWZ_NVP_EXM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FMP] = 15,
+ [NWZ_NVP_FNI] = 82,
+ [NWZ_NVP_FPI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FUI] = 75,
+ [NWZ_NVP_FUP] = 3,
+ [NWZ_NVP_FUR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FVI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_GTY] = 14,
+ [NWZ_NVP_HDI] = 73,
+ [NWZ_NVP_HLD] = 5,
+ [NWZ_NVP_INS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_IPT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_KAS] = 11,
+ [NWZ_NVP_LBI] = 74,
+ [NWZ_NVP_LYR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MAC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MCR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDK] = 30,
+ [NWZ_NVP_MDL] = 70,
+ [NWZ_NVP_MID] = 7,
+ [NWZ_NVP_MLK] = 84,
+ [NWZ_NVP_MSC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSO] = 86,
+ [NWZ_NVP_MTM] = 33,
+ [NWZ_NVP_MUK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_NCP] = 17,
+ [NWZ_NVP_NVR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PCD] = 8,
+ [NWZ_NVP_PCI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PNC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PRK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PSK] = 18,
+ [NWZ_NVP_PTS] = 77,
+ [NWZ_NVP_RBT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RND] = 27,
+ [NWZ_NVP_RTC] = 6,
+ [NWZ_NVP_SDC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SDP] = 16,
+ [NWZ_NVP_SER] = 9,
+ [NWZ_NVP_SFI] = 29,
+ [NWZ_NVP_SHE] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHP] = 12,
+ [NWZ_NVP_SID] = 83,
+ [NWZ_NVP_SKD] = 28,
+ [NWZ_NVP_SKT] = 32,
+ [NWZ_NVP_SKU] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SLP] = 80,
+ [NWZ_NVP_SPS] = 69,
+ [NWZ_NVP_SYI] = 1,
+ [NWZ_NVP_TR0] = 34,
+ [NWZ_NVP_TR1] = 35,
+ [NWZ_NVP_TST] = 13,
+ [NWZ_NVP_UBP] = 2,
+ [NWZ_NVP_UFN] = 10,
+ [NWZ_NVP_UMS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_UPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VAR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VRT] = 81,
+};
+
+static int nvp_index_398250[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BFD] = 21,
+ [NWZ_NVP_BFP] = 20,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = 22,
+ [NWZ_NVP_BOK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BPR] = 19,
+ [NWZ_NVP_BTC] = 85,
+ [NWZ_NVP_BTI] = 72,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 23,
+ [NWZ_NVP_CTR] = 90,
+ [NWZ_NVP_DBA] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBG] = 0,
+ [NWZ_NVP_DBI] = 88,
+ [NWZ_NVP_DBS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBV] = 25,
+ [NWZ_NVP_DCC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DOR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 71,
+ [NWZ_NVP_EP0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP2] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP3] = NWZ_NVP_INVALID,
+ [NWZ_NVP_ERI] = 76,
+ [NWZ_NVP_EXM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FMP] = 15,
+ [NWZ_NVP_FNI] = 82,
+ [NWZ_NVP_FPI] = 33,
+ [NWZ_NVP_FUI] = 75,
+ [NWZ_NVP_FUP] = 3,
+ [NWZ_NVP_FUR] = 26,
+ [NWZ_NVP_FVI] = 31,
+ [NWZ_NVP_GTY] = 14,
+ [NWZ_NVP_HDI] = 73,
+ [NWZ_NVP_HLD] = 5,
+ [NWZ_NVP_INS] = 89,
+ [NWZ_NVP_IPT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_KAS] = 11,
+ [NWZ_NVP_LBI] = 74,
+ [NWZ_NVP_LYR] = 24,
+ [NWZ_NVP_MAC] = 32,
+ [NWZ_NVP_MCR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDK] = 30,
+ [NWZ_NVP_MDL] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MID] = 7,
+ [NWZ_NVP_MLK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSO] = 86,
+ [NWZ_NVP_MTM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MUK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_NCP] = 17,
+ [NWZ_NVP_NVR] = 77,
+ [NWZ_NVP_PCD] = 8,
+ [NWZ_NVP_PCI] = 87,
+ [NWZ_NVP_PNC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PRK] = 4,
+ [NWZ_NVP_PSK] = 18,
+ [NWZ_NVP_PTS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RBT] = 70,
+ [NWZ_NVP_RND] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RTC] = 6,
+ [NWZ_NVP_SDC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SDP] = 16,
+ [NWZ_NVP_SER] = 9,
+ [NWZ_NVP_SFI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHE] = 84,
+ [NWZ_NVP_SHP] = 12,
+ [NWZ_NVP_SID] = 83,
+ [NWZ_NVP_SKD] = 28,
+ [NWZ_NVP_SKT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SKU] = 91,
+ [NWZ_NVP_SLP] = 80,
+ [NWZ_NVP_SPS] = 69,
+ [NWZ_NVP_SYI] = 1,
+ [NWZ_NVP_TR0] = 34,
+ [NWZ_NVP_TR1] = 35,
+ [NWZ_NVP_TST] = 13,
+ [NWZ_NVP_UBP] = 2,
+ [NWZ_NVP_UFN] = 10,
+ [NWZ_NVP_UMS] = 27,
+ [NWZ_NVP_UPS] = 29,
+ [NWZ_NVP_VAR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VRT] = 81,
+};
+
+static int nvp_index_4edba7[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = 0,
+ [NWZ_NVP_BFD] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BFP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BOK] = 10,
+ [NWZ_NVP_BPR] = 35,
+ [NWZ_NVP_BTC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BTI] = 1,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 3,
+ [NWZ_NVP_CTR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBA] = 12,
+ [NWZ_NVP_DBG] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBS] = 27,
+ [NWZ_NVP_DBV] = 13,
+ [NWZ_NVP_DCC] = 7,
+ [NWZ_NVP_DG0] = 5,
+ [NWZ_NVP_DG1] = 6,
+ [NWZ_NVP_DOR] = 21,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 22,
+ [NWZ_NVP_EP0] = 71,
+ [NWZ_NVP_EP1] = 72,
+ [NWZ_NVP_EP2] = 73,
+ [NWZ_NVP_EP3] = 74,
+ [NWZ_NVP_ERI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EXM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FMP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FNI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FPI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FUI] = 19,
+ [NWZ_NVP_FUP] = 9,
+ [NWZ_NVP_FUR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FVI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_GTY] = 18,
+ [NWZ_NVP_HDI] = 2,
+ [NWZ_NVP_HLD] = 80,
+ [NWZ_NVP_INS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_IPT] = 70,
+ [NWZ_NVP_KAS] = 32,
+ [NWZ_NVP_LBI] = 20,
+ [NWZ_NVP_LYR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MAC] = 77,
+ [NWZ_NVP_MCR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDL] = 8,
+ [NWZ_NVP_MID] = 16,
+ [NWZ_NVP_MLK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSO] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MTM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MUK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_NCP] = 31,
+ [NWZ_NVP_NVR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PCD] = 26,
+ [NWZ_NVP_PCI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PNC] = 33,
+ [NWZ_NVP_PRK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PSK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PTS] = 75,
+ [NWZ_NVP_RBT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RND] = 28,
+ [NWZ_NVP_RTC] = 34,
+ [NWZ_NVP_SDC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SDP] = 30,
+ [NWZ_NVP_SER] = 4,
+ [NWZ_NVP_SFI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHE] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHP] = 11,
+ [NWZ_NVP_SID] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SKD] = 81,
+ [NWZ_NVP_SKT] = 76,
+ [NWZ_NVP_SKU] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SLP] = 69,
+ [NWZ_NVP_SPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SYI] = 24,
+ [NWZ_NVP_TR0] = 14,
+ [NWZ_NVP_TR1] = 15,
+ [NWZ_NVP_TST] = 17,
+ [NWZ_NVP_UBP] = 23,
+ [NWZ_NVP_UFN] = 29,
+ [NWZ_NVP_UMS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_UPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VAR] = 25,
+ [NWZ_NVP_VRT] = NWZ_NVP_INVALID,
+};
+
+static int nvp_index_6485c8[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BFD] = 21,
+ [NWZ_NVP_BFP] = 20,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = 22,
+ [NWZ_NVP_BOK] = 4,
+ [NWZ_NVP_BPR] = 19,
+ [NWZ_NVP_BTC] = 85,
+ [NWZ_NVP_BTI] = 72,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 23,
+ [NWZ_NVP_CTR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBA] = 24,
+ [NWZ_NVP_DBG] = 0,
+ [NWZ_NVP_DBI] = 88,
+ [NWZ_NVP_DBS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBV] = 25,
+ [NWZ_NVP_DCC] = 31,
+ [NWZ_NVP_DG0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DOR] = 26,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 71,
+ [NWZ_NVP_EP0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP2] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP3] = NWZ_NVP_INVALID,
+ [NWZ_NVP_ERI] = 76,
+ [NWZ_NVP_EXM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FMP] = 15,
+ [NWZ_NVP_FNI] = 82,
+ [NWZ_NVP_FPI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FUI] = 75,
+ [NWZ_NVP_FUP] = 3,
+ [NWZ_NVP_FUR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FVI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_GTY] = 14,
+ [NWZ_NVP_HDI] = 73,
+ [NWZ_NVP_HLD] = 5,
+ [NWZ_NVP_INS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_IPT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_KAS] = 11,
+ [NWZ_NVP_LBI] = 74,
+ [NWZ_NVP_LYR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MAC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MCR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDK] = 30,
+ [NWZ_NVP_MDL] = 70,
+ [NWZ_NVP_MID] = 7,
+ [NWZ_NVP_MLK] = 84,
+ [NWZ_NVP_MSC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSO] = 86,
+ [NWZ_NVP_MTM] = 33,
+ [NWZ_NVP_MUK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_NCP] = 17,
+ [NWZ_NVP_NVR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PCD] = 8,
+ [NWZ_NVP_PCI] = 87,
+ [NWZ_NVP_PNC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PRK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PSK] = 18,
+ [NWZ_NVP_PTS] = 77,
+ [NWZ_NVP_RBT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RND] = 27,
+ [NWZ_NVP_RTC] = 6,
+ [NWZ_NVP_SDC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SDP] = 16,
+ [NWZ_NVP_SER] = 9,
+ [NWZ_NVP_SFI] = 29,
+ [NWZ_NVP_SHE] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHP] = 12,
+ [NWZ_NVP_SID] = 83,
+ [NWZ_NVP_SKD] = 28,
+ [NWZ_NVP_SKT] = 32,
+ [NWZ_NVP_SKU] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SLP] = 80,
+ [NWZ_NVP_SPS] = 69,
+ [NWZ_NVP_SYI] = 1,
+ [NWZ_NVP_TR0] = 34,
+ [NWZ_NVP_TR1] = 35,
+ [NWZ_NVP_TST] = 13,
+ [NWZ_NVP_UBP] = 2,
+ [NWZ_NVP_UFN] = 10,
+ [NWZ_NVP_UMS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_UPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VAR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VRT] = 81,
+};
+
+static int nvp_index_92faee[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = NWZ_NVP_INVALID,
+ [NWZ_NVP_BFD] = 21,
+ [NWZ_NVP_BFP] = 20,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = 22,
+ [NWZ_NVP_BOK] = 4,
+ [NWZ_NVP_BPR] = 19,
+ [NWZ_NVP_BTC] = 85,
+ [NWZ_NVP_BTI] = 72,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 23,
+ [NWZ_NVP_CTR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBA] = 24,
+ [NWZ_NVP_DBG] = 0,
+ [NWZ_NVP_DBI] = 88,
+ [NWZ_NVP_DBS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBV] = 25,
+ [NWZ_NVP_DCC] = 31,
+ [NWZ_NVP_DG0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DOR] = 26,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 71,
+ [NWZ_NVP_EP0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP2] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP3] = NWZ_NVP_INVALID,
+ [NWZ_NVP_ERI] = 76,
+ [NWZ_NVP_EXM] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FMP] = 15,
+ [NWZ_NVP_FNI] = 82,
+ [NWZ_NVP_FPI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FUI] = 75,
+ [NWZ_NVP_FUP] = 3,
+ [NWZ_NVP_FUR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FVI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_GTY] = 14,
+ [NWZ_NVP_HDI] = 73,
+ [NWZ_NVP_HLD] = 5,
+ [NWZ_NVP_INS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_IPT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_KAS] = 11,
+ [NWZ_NVP_LBI] = 74,
+ [NWZ_NVP_LYR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MAC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MCR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MDK] = 30,
+ [NWZ_NVP_MDL] = 70,
+ [NWZ_NVP_MID] = 7,
+ [NWZ_NVP_MLK] = 84,
+ [NWZ_NVP_MSC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSO] = 86,
+ [NWZ_NVP_MTM] = 33,
+ [NWZ_NVP_MUK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_NCP] = 17,
+ [NWZ_NVP_NVR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PCD] = 8,
+ [NWZ_NVP_PCI] = 87,
+ [NWZ_NVP_PNC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PRK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PSK] = 18,
+ [NWZ_NVP_PTS] = 77,
+ [NWZ_NVP_RBT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RND] = 27,
+ [NWZ_NVP_RTC] = 6,
+ [NWZ_NVP_SDC] = 89,
+ [NWZ_NVP_SDP] = 16,
+ [NWZ_NVP_SER] = 9,
+ [NWZ_NVP_SFI] = 29,
+ [NWZ_NVP_SHE] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHP] = 12,
+ [NWZ_NVP_SID] = 83,
+ [NWZ_NVP_SKD] = 28,
+ [NWZ_NVP_SKT] = 32,
+ [NWZ_NVP_SKU] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SLP] = 80,
+ [NWZ_NVP_SPS] = 69,
+ [NWZ_NVP_SYI] = 1,
+ [NWZ_NVP_TR0] = 34,
+ [NWZ_NVP_TR1] = 35,
+ [NWZ_NVP_TST] = 13,
+ [NWZ_NVP_UBP] = 2,
+ [NWZ_NVP_UFN] = 10,
+ [NWZ_NVP_UMS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_UPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VAR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VRT] = 81,
+};
+
+static int nvp_index_f505c8[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = 78,
+ [NWZ_NVP_APP] = 5,
+ [NWZ_NVP_BFD] = 88,
+ [NWZ_NVP_BFP] = 89,
+ [NWZ_NVP_BLF] = 79,
+ [NWZ_NVP_BML] = 87,
+ [NWZ_NVP_BOK] = 10,
+ [NWZ_NVP_BPR] = 35,
+ [NWZ_NVP_BTC] = 27,
+ [NWZ_NVP_BTI] = 1,
+ [NWZ_NVP_CLV] = 68,
+ [NWZ_NVP_CNG] = 3,
+ [NWZ_NVP_CTR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBA] = 12,
+ [NWZ_NVP_DBG] = 0,
+ [NWZ_NVP_DBI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DBV] = 13,
+ [NWZ_NVP_DCC] = 7,
+ [NWZ_NVP_DG0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DG1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_DOR] = 21,
+ [NWZ_NVP_E00] = 36,
+ [NWZ_NVP_E01] = 37,
+ [NWZ_NVP_E02] = 38,
+ [NWZ_NVP_E03] = 39,
+ [NWZ_NVP_E04] = 40,
+ [NWZ_NVP_E05] = 41,
+ [NWZ_NVP_E06] = 42,
+ [NWZ_NVP_E07] = 43,
+ [NWZ_NVP_E08] = 44,
+ [NWZ_NVP_E09] = 45,
+ [NWZ_NVP_E10] = 46,
+ [NWZ_NVP_E11] = 47,
+ [NWZ_NVP_E12] = 48,
+ [NWZ_NVP_E13] = 49,
+ [NWZ_NVP_E14] = 50,
+ [NWZ_NVP_E15] = 51,
+ [NWZ_NVP_E16] = 52,
+ [NWZ_NVP_E17] = 53,
+ [NWZ_NVP_E18] = 54,
+ [NWZ_NVP_E19] = 55,
+ [NWZ_NVP_E20] = 56,
+ [NWZ_NVP_E21] = 57,
+ [NWZ_NVP_E22] = 58,
+ [NWZ_NVP_E23] = 59,
+ [NWZ_NVP_E24] = 60,
+ [NWZ_NVP_E25] = 61,
+ [NWZ_NVP_E26] = 62,
+ [NWZ_NVP_E27] = 63,
+ [NWZ_NVP_E28] = 64,
+ [NWZ_NVP_E29] = 65,
+ [NWZ_NVP_E30] = 66,
+ [NWZ_NVP_E31] = 67,
+ [NWZ_NVP_EDW] = 22,
+ [NWZ_NVP_EP0] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP1] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP2] = NWZ_NVP_INVALID,
+ [NWZ_NVP_EP3] = NWZ_NVP_INVALID,
+ [NWZ_NVP_ERI] = 6,
+ [NWZ_NVP_EXM] = 25,
+ [NWZ_NVP_FMP] = 82,
+ [NWZ_NVP_FNI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FPI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FUI] = 19,
+ [NWZ_NVP_FUP] = 9,
+ [NWZ_NVP_FUR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_FVI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_GTY] = 18,
+ [NWZ_NVP_HDI] = 2,
+ [NWZ_NVP_HLD] = 80,
+ [NWZ_NVP_INS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_IPT] = 70,
+ [NWZ_NVP_KAS] = 32,
+ [NWZ_NVP_LBI] = 20,
+ [NWZ_NVP_LYR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MAC] = 77,
+ [NWZ_NVP_MCR] = 72,
+ [NWZ_NVP_MDK] = 73,
+ [NWZ_NVP_MDL] = 8,
+ [NWZ_NVP_MID] = 16,
+ [NWZ_NVP_MLK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MSC] = 84,
+ [NWZ_NVP_MSO] = NWZ_NVP_INVALID,
+ [NWZ_NVP_MTM] = 71,
+ [NWZ_NVP_MUK] = 74,
+ [NWZ_NVP_NCP] = 31,
+ [NWZ_NVP_NVR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PCD] = 26,
+ [NWZ_NVP_PCI] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PNC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PRK] = NWZ_NVP_INVALID,
+ [NWZ_NVP_PSK] = 86,
+ [NWZ_NVP_PTS] = 75,
+ [NWZ_NVP_RBT] = NWZ_NVP_INVALID,
+ [NWZ_NVP_RND] = 28,
+ [NWZ_NVP_RTC] = 34,
+ [NWZ_NVP_SDC] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SDP] = 30,
+ [NWZ_NVP_SER] = 4,
+ [NWZ_NVP_SFI] = 33,
+ [NWZ_NVP_SHE] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SHP] = 11,
+ [NWZ_NVP_SID] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SKD] = 81,
+ [NWZ_NVP_SKT] = 76,
+ [NWZ_NVP_SKU] = NWZ_NVP_INVALID,
+ [NWZ_NVP_SLP] = 69,
+ [NWZ_NVP_SPS] = 83,
+ [NWZ_NVP_SYI] = 24,
+ [NWZ_NVP_TR0] = 14,
+ [NWZ_NVP_TR1] = 15,
+ [NWZ_NVP_TST] = 17,
+ [NWZ_NVP_UBP] = 23,
+ [NWZ_NVP_UFN] = 29,
+ [NWZ_NVP_UMS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_UPS] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VAR] = NWZ_NVP_INVALID,
+ [NWZ_NVP_VRT] = 85,
+};
+
+struct nwz_nvp_info_t nwz_nvp[NWZ_NVP_COUNT] =
+{
+ [NWZ_NVP_APD] = { "apd", 4, "application debug mode flag" },
+ [NWZ_NVP_APP] = { "app", 4096, "application parameter" },
+ [NWZ_NVP_BFD] = { "bfd", 512, "btmw factory scdb" },
+ [NWZ_NVP_BFP] = { "bfp", 512, "btmw factory pair info" },
+ [NWZ_NVP_BLF] = { "blf", 4, "browser log mode flag" },
+ [NWZ_NVP_BML] = { "bml", 4, "btmw log mode flag" },
+ [NWZ_NVP_BOK] = { "bok", 4, "beep ok flag" },
+ [NWZ_NVP_BPR] = { "bpr", 2048, "bluetooth address | bluetooth parameter" },
+ [NWZ_NVP_BTC] = { "btc", 4, "battery calibration" },
+ [NWZ_NVP_BTI] = { "bti", 262144, "boot image" },
+ [NWZ_NVP_CLV] = { "clv", 4, "color variation" },
+ [NWZ_NVP_CNG] = { "cng", 704, "aad key | aad/empr key" },
+ [NWZ_NVP_CTR] = { "ctr", 0, "" },
+ [NWZ_NVP_DBA] = { "dba", 160, "aad icv" },
+ [NWZ_NVP_DBG] = { "dbg", 0, "" },
+ [NWZ_NVP_DBI] = { "dbi", 262144, "dead battery image" },
+ [NWZ_NVP_DBS] = { "dbs", 0, "" },
+ [NWZ_NVP_DBV] = { "dbv", 520, "empr icv | empr key" },
+ [NWZ_NVP_DCC] = { "dcc", 20, "secure clock" },
+ [NWZ_NVP_DG0] = { "dg0", 0, "" },
+ [NWZ_NVP_DG1] = { "dg1", 0, "" },
+ [NWZ_NVP_DOR] = { "dor", 4, "key mode (debug/release)" },
+ [NWZ_NVP_E00] = { "e00", 1024, "EMPR 0" },
+ [NWZ_NVP_E01] = { "e01", 1024, "EMPR 1" },
+ [NWZ_NVP_E02] = { "e02", 1024, "EMPR 2" },
+ [NWZ_NVP_E03] = { "e03", 1024, "EMPR 3" },
+ [NWZ_NVP_E04] = { "e04", 1024, "EMPR 4" },
+ [NWZ_NVP_E05] = { "e05", 1024, "EMPR 5" },
+ [NWZ_NVP_E06] = { "e06", 1024, "EMPR 6" },
+ [NWZ_NVP_E07] = { "e07", 1024, "EMPR 7" },
+ [NWZ_NVP_E08] = { "e08", 1024, "EMPR 8" },
+ [NWZ_NVP_E09] = { "e09", 1024, "EMPR 9" },
+ [NWZ_NVP_E10] = { "e10", 1024, "EMPR 10" },
+ [NWZ_NVP_E11] = { "e11", 1024, "EMPR 11" },
+ [NWZ_NVP_E12] = { "e12", 1024, "EMPR 12" },
+ [NWZ_NVP_E13] = { "e13", 1024, "EMPR 13" },
+ [NWZ_NVP_E14] = { "e14", 1024, "EMPR 14" },
+ [NWZ_NVP_E15] = { "e15", 1024, "EMPR 15" },
+ [NWZ_NVP_E16] = { "e16", 1024, "EMPR 16" },
+ [NWZ_NVP_E17] = { "e17", 1024, "EMPR 17" },
+ [NWZ_NVP_E18] = { "e18", 1024, "EMPR 18" },
+ [NWZ_NVP_E19] = { "e19", 1024, "EMPR 19" },
+ [NWZ_NVP_E20] = { "e20", 1024, "EMPR 20" },
+ [NWZ_NVP_E21] = { "e21", 1024, "EMPR 21" },
+ [NWZ_NVP_E22] = { "e22", 1024, "EMPR 22" },
+ [NWZ_NVP_E23] = { "e23", 1024, "EMPR 23" },
+ [NWZ_NVP_E24] = { "e24", 1024, "EMPR 24" },
+ [NWZ_NVP_E25] = { "e25", 1024, "EMPR 25" },
+ [NWZ_NVP_E26] = { "e26", 1024, "EMPR 26" },
+ [NWZ_NVP_E27] = { "e27", 1024, "EMPR 27" },
+ [NWZ_NVP_E28] = { "e28", 1024, "EMPR 28" },
+ [NWZ_NVP_E29] = { "e29", 1024, "EMPR 29" },
+ [NWZ_NVP_E30] = { "e30", 1024, "EMPR 30" },
+ [NWZ_NVP_E31] = { "e31", 1024, "EMPR 31" },
+ [NWZ_NVP_EDW] = { "edw", 4, "quick shutdown flag" },
+ [NWZ_NVP_EP0] = { "ep0", 0, "" },
+ [NWZ_NVP_EP1] = { "ep1", 0, "" },
+ [NWZ_NVP_EP2] = { "ep2", 0, "" },
+ [NWZ_NVP_EP3] = { "ep3", 0, "" },
+ [NWZ_NVP_ERI] = { "eri", 262144, "update error image" },
+ [NWZ_NVP_EXM] = { "exm", 4, "exception monitor mode" },
+ [NWZ_NVP_FMP] = { "fmp", 16, "fm parameter" },
+ [NWZ_NVP_FNI] = { "fni", 4, "function information" },
+ [NWZ_NVP_FPI] = { "fpi", 0, "" },
+ [NWZ_NVP_FUI] = { "fui", 262144, "update image" },
+ [NWZ_NVP_FUP] = { "fup", 4, "firmware update flag" },
+ [NWZ_NVP_FUR] = { "fur", 0, "" },
+ [NWZ_NVP_FVI] = { "fvi", 0, "" },
+ [NWZ_NVP_GTY] = { "gty", 4, "getty mode flag" },
+ [NWZ_NVP_HDI] = { "hdi", 262144, "hold image" },
+ [NWZ_NVP_HLD] = { "hld", 4, "hold mode" },
+ [NWZ_NVP_INS] = { "ins", 0, "" },
+ [NWZ_NVP_IPT] = { "ipt", 4, "disable iptable flag" },
+ [NWZ_NVP_KAS] = { "kas", 64, "key and signature" },
+ [NWZ_NVP_LBI] = { "lbi", 262144, "low battery image" },
+ [NWZ_NVP_LYR] = { "lyr", 0, "" },
+ [NWZ_NVP_MAC] = { "mac", 6, "wifi mac address" },
+ [NWZ_NVP_MCR] = { "mcr", 16384, "marlin crl" },
+ [NWZ_NVP_MDK] = { "mdk", 33024, "marlin device key" },
+ [NWZ_NVP_MDL] = { "mdl", 8, "middleware parameter" },
+ [NWZ_NVP_MID] = { "mid", 64, "model id" },
+ [NWZ_NVP_MLK] = { "mlk", 4, "marlin key" },
+ [NWZ_NVP_MSC] = { "msc", 4, "mass storage class mode" },
+ [NWZ_NVP_MSO] = { "mso", 4, "MSC only mode flag" },
+ [NWZ_NVP_MTM] = { "mtm", 64, "marlin time" },
+ [NWZ_NVP_MUK] = { "muk", 24576, "marlin user key" },
+ [NWZ_NVP_NCP] = { "ncp", 64, "noise cancel driver parameter" },
+ [NWZ_NVP_NVR] = { "nvr", 0, "" },
+ [NWZ_NVP_PCD] = { "pcd", 5, "product code" },
+ [NWZ_NVP_PCI] = { "pci", 262144, "precharge image" },
+ [NWZ_NVP_PNC] = { "pnc", 0, "" },
+ [NWZ_NVP_PRK] = { "prk", 0, "" },
+ [NWZ_NVP_PSK] = { "psk", 512, "bluetooth pskey" },
+ [NWZ_NVP_PTS] = { "pts", 4, "wifi protected setup" },
+ [NWZ_NVP_RBT] = { "rbt", 0, "" },
+ [NWZ_NVP_RND] = { "rnd", 64, "random data | wmt key" },
+ [NWZ_NVP_RTC] = { "rtc", 16, "rtc alarm" },
+ [NWZ_NVP_SDC] = { "sdc", 4, "SD Card export flag" },
+ [NWZ_NVP_SDP] = { "sdp", 64, "sound driver parameter" },
+ [NWZ_NVP_SER] = { "ser", 16, "serial number" },
+ [NWZ_NVP_SFI] = { "sfi", 64, "starfish id" },
+ [NWZ_NVP_SHE] = { "she", 0, "" },
+ [NWZ_NVP_SHP] = { "shp", 32, "ship information" },
+ [NWZ_NVP_SID] = { "sid", 4, "service id" },
+ [NWZ_NVP_SKD] = { "skd", 8224, "slacker id file" },
+ [NWZ_NVP_SKT] = { "skt", 16, "slacker time" },
+ [NWZ_NVP_SKU] = { "sku", 0, "" },
+ [NWZ_NVP_SLP] = { "slp", 4, "time out to sleep" },
+ [NWZ_NVP_SPS] = { "sps", 4, "speaker ship info" },
+ [NWZ_NVP_SYI] = { "syi", 4, "system information" },
+ [NWZ_NVP_TR0] = { "tr0", 16384, "EKB 0" },
+ [NWZ_NVP_TR1] = { "tr1", 16384, "EKB 1" },
+ [NWZ_NVP_TST] = { "tst", 4, "test mode flag" },
+ [NWZ_NVP_UBP] = { "ubp", 32, "u-boot password" },
+ [NWZ_NVP_UFN] = { "ufn", 8, "update file name" },
+ [NWZ_NVP_UMS] = { "ums", 0, "" },
+ [NWZ_NVP_UPS] = { "ups", 0, "" },
+ [NWZ_NVP_VAR] = { "var", 0, "" },
+ [NWZ_NVP_VRT] = { "vrt", 4, "europe vol regulation flag" },
+};
+
+static unsigned long models_nwz_a10[] = { 0x1a000001, 0x1a000002, 0x1a000004,
+ 0x1a000005, 0x1a000006, 0x1a010001, 0x1a010002, 0x1a010004, 0x1a010005,
+ 0x1a010006 };
+
+static unsigned long models_nw_a20[] = { 0x1d000001, 0x1d000002, 0x1d000004,
+ 0x1d000005, 0x1d000006, 0x1d000007 };
+
+static unsigned long models_nw_a30[] = { 0x22000004, 0x22000005, 0x22000006 };
+
+static unsigned long models_nwz_a720[] = { 0x3030001, 0x3030002, 0x3030004,
+ 0x3020001, 0x3020002, 0x3020004 };
+
+static unsigned long models_nwz_a810[] = { 0x10000, 0x10001, 0x10002 };
+
+static unsigned long models_nwz_a820[] = { 0x3010001, 0x3010002, 0x3010004,
+ 0x3000001, 0x3000002, 0x3000004 };
+
+static unsigned long models_nwz_a840[] = { 0x7010004, 0x7010005, 0x7010006,
+ 0x7000004, 0x7000005, 0x7000006 };
+
+static unsigned long models_nwz_a850[] = { 0xe000004, 0xe000005, 0xe000006 };
+
+static unsigned long models_nwz_a860[] = { 0x11000001, 0x11000002, 0x11000004,
+ 0x11000005, 0x11000006, 0x11010001, 0x11010002, 0x11010004, 0x11010005,
+ 0x11010006, 0x11020001, 0x11020002, 0x11020004, 0x11020005, 0x11020006 };
+
+static unsigned long models_nw_a910[] = { 0x2000001, 0x2000002, 0x2000004 };
+
+static unsigned long models_nwz_e050[] = { 0x8000000, 0x8000001, 0x8000002,
+ 0x10000000, 0x10000001 };
+
+static unsigned long models_nw_e060[] = { 0x14000000, 0x14000001, 0x14000002,
+ 0x14000004, 0x14000005 };
+
+static unsigned long models_nw_e080[] = { 0x19010001, 0x19010002, 0x19010004,
+ 0x19010005 };
+
+static unsigned long models_nwz_e350[] = { 0xc000001, 0xc000002, 0xc000004 };
+
+static unsigned long models_nwz_e450[] = { 0xb000001, 0xb000002, 0xb000004 };
+
+static unsigned long models_nwz_e460[] = { 0x13000001, 0x13000002, 0x13000004 };
+
+static unsigned long models_nwz_e470[] = { 0x15000001, 0x15000002, 0x15000004,
+ 0x15000005 };
+
+static unsigned long models_nwz_e550[] = { 0xd000001, 0xd000002, 0xd000004,
+ 0xd000005 };
+
+static unsigned long models_nwz_e570[] = { 0x15010001, 0x15010002, 0x15010004,
+ 0x15010005 };
+
+static unsigned long models_nwz_e580[] = { 0x19020001, 0x19020002, 0x19020004,
+ 0x19020005 };
+
+static unsigned long models_nw_s10[] = { 0x1b000001, 0x1b000002, 0x1b000004,
+ 0x1b000005, 0x1b000006 };
+
+static unsigned long models_nwz_s510[] = { 0x1030000, 0x1030001 };
+
+static unsigned long models_nwz_s610[] = { 0x1000000, 0x1000001, 0x1020000,
+ 0x1020001, 0x1020002 };
+
+static unsigned long models_nwz_s630[] = { 0x4000001, 0x4000002, 0x4000004,
+ 0x4020001, 0x4020002, 0x4020004 };
+
+static unsigned long models_nw_s640[] = { 0x6010002, 0x6010004, 0x6010005 };
+
+static unsigned long models_nwz_s710[] = { 0x1010000, 0x1010001, 0x1010002,
+ 0x1040000, 0x1040001, 0x1040002 };
+
+static unsigned long models_nwz_s730[] = { 0x4010001, 0x4010002, 0x4010004,
+ 0x4030001, 0x4030002, 0x4030004 };
+
+static unsigned long models_nwz_s740[] = { 0x6030002, 0x6030004, 0x6030005,
+ 0x6020002, 0x6020004, 0x6020005 };
+
+static unsigned long models_nwz_s750[] = { 0x9000002, 0x9000004, 0x9000005,
+ 0xf000002, 0xf000004 };
+
+static unsigned long models_nwz_s760[] = { 0x12000001, 0x12000002, 0x12000004,
+ 0x12000005, 0x12000006, 0x12010001, 0x12010002, 0x12010004, 0x12010005,
+ 0x12010006 };
+
+static unsigned long models_nwz_s770[] = { 0x16000001, 0x16000002, 0x16000004,
+ 0x16000005, 0x16010001, 0x16010002, 0x16010004, 0x16010005 };
+
+static unsigned long models_nw_s780[] = { 0x19000001, 0x19000002, 0x19000004,
+ 0x19000005 };
+
+static unsigned long models_nw_wm1[] = { 0x20000007, 0x21000008 };
+
+static unsigned long models_nwz_x1000[] = { 0x5000002, 0x5000004, 0x5000005,
+ 0x5020002, 0x5040002, 0x5020004, 0x5040004, 0x5020005, 0x5040005 };
+
+static unsigned long models_nw_zx100[] = { 0x1c000007, 0x1c000001, 0x1c000002,
+ 0x1c000004, 0x1c000005, 0x1c000006 };
+
+static unsigned long models_nwz_noname[] = { 0x5010002, 0x5010004, 0x5010005 };
+
+struct nwz_series_info_t nwz_series[NWZ_SERIES_COUNT] =
+{
+ { "nwz-a10", "NWZ-A10 Series", 10, models_nwz_a10, &nvp_index_92faee },
+ { "nw-a20", "NW-A20 Series", 6, models_nw_a20, &nvp_index_92faee },
+ { "nw-a30", "NW-A30 Series", 3, models_nw_a30, &nvp_index_398250 },
+ { "nwz-a720", "NWZ-A720 Series", 6, models_nwz_a720, 0 },
+ { "nwz-a810", "NWZ-A810 Series", 3, models_nwz_a810, 0 },
+ { "nwz-a820", "NWZ-A820 Series", 6, models_nwz_a820, 0 },
+ { "nwz-a840", "NWZ-A840 Series", 6, models_nwz_a840, &nvp_index_0ac81d },
+ { "nwz-a850", "NWZ-A850 Series", 3, models_nwz_a850, &nvp_index_0ac81d },
+ { "nwz-a860", "NWZ-A860 Series", 15, models_nwz_a860, &nvp_index_f505c8 },
+ { "nw-a910", "NW-A910 Series", 3, models_nw_a910, 0 },
+ { "nwz-e050", "NWZ-E050 Series", 5, models_nwz_e050, &nvp_index_0ac81d },
+ { "nw-e060", "NW-E060 Series", 5, models_nw_e060, &nvp_index_f505c8 },
+ { "nw-e080", "NW-E080 Series", 4, models_nw_e080, &nvp_index_6485c8 },
+ { "nwz-e350", "NWZ-E350 Series", 3, models_nwz_e350, &nvp_index_0ac81d },
+ { "nwz-e450", "NWZ-E450 Series", 3, models_nwz_e450, &nvp_index_0ac81d },
+ { "nwz-e460", "NWZ-E460 Series", 3, models_nwz_e460, &nvp_index_f505c8 },
+ { "nwz-e470", "NWZ-E470 Series", 4, models_nwz_e470, &nvp_index_28dc2c },
+ { "nwz-e550", "NWZ-E550 Series", 4, models_nwz_e550, 0 },
+ { "nwz-e570", "NWZ-E570 Series", 4, models_nwz_e570, 0 },
+ { "nwz-e580", "NWZ-E580 Series", 4, models_nwz_e580, &nvp_index_6485c8 },
+ { "nw-s10", "NW-S10 Series", 5, models_nw_s10, &nvp_index_6485c8 },
+ { "nwz-s510", "NWZ-S510 Series", 2, models_nwz_s510, 0 },
+ { "nwz-s610", "NWZ-S610 Series", 5, models_nwz_s610, 0 },
+ { "nwz-s630", "NWZ-S630 Series", 6, models_nwz_s630, 0 },
+ { "nw-s640", "NW-S640 Series", 3, models_nw_s640, &nvp_index_0ac81d },
+ { "nwz-s710", "NWZ-S710 Series", 6, models_nwz_s710, 0 },
+ { "nwz-s730", "NWZ-S730 Series", 6, models_nwz_s730, 0 },
+ { "nwz-s740", "NWZ-S740 Series", 6, models_nwz_s740, &nvp_index_0ac81d },
+ { "nwz-s750", "NWZ-S750 Series", 5, models_nwz_s750, &nvp_index_0ac81d },
+ { "nwz-s760", "NWZ-S760 Series", 10, models_nwz_s760, &nvp_index_f505c8 },
+ { "nwz-s770", "NWZ-S770 Series", 8, models_nwz_s770, 0 },
+ { "nw-s780", "NW-S780 Series", 4, models_nw_s780, &nvp_index_6485c8 },
+ { "nw-wm1", "NW-WM1 Series", 2, models_nw_wm1, &nvp_index_398250 },
+ { "nwz-x1000", "NWZ-X1000 Series", 9, models_nwz_x1000, &nvp_index_4edba7 },
+ { "nw-zx100", "NW-ZX100 Series", 6, models_nw_zx100, &nvp_index_92faee },
+ { "nwz-noname", "NONAME", 3, models_nwz_noname, 0 },
+};
diff --git a/firmware/target/hosted/sonynwz/nwz-db.h b/firmware/target/hosted/sonynwz/nwz-db.h
new file mode 100644
index 0000000000..cb130f96a2
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/nwz-db.h
@@ -0,0 +1,193 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 __NWZ_DB_H__
+#define __NWZ_DB_H__
+
+/** /!\ This file was automatically generated, DO NOT MODIFY IT DIRECTLY /!\ */
+
+/* List of all known NVP nodes */
+enum nwz_nvp_node_t
+{
+ NWZ_NVP_APD, /* application debug mode flag */
+ NWZ_NVP_APP, /* application parameter */
+ NWZ_NVP_BFD, /* btmw factory scdb */
+ NWZ_NVP_BFP, /* btmw factory pair info */
+ NWZ_NVP_BLF, /* browser log mode flag */
+ NWZ_NVP_BML, /* btmw log mode flag */
+ NWZ_NVP_BOK, /* beep ok flag */
+ NWZ_NVP_BPR, /* bluetooth address | bluetooth parameter */
+ NWZ_NVP_BTC, /* battery calibration */
+ NWZ_NVP_BTI, /* boot image */
+ NWZ_NVP_CLV, /* color variation */
+ NWZ_NVP_CNG, /* aad key | aad/empr key */
+ NWZ_NVP_CTR, /* */
+ NWZ_NVP_DBA, /* aad icv */
+ NWZ_NVP_DBG, /* */
+ NWZ_NVP_DBI, /* dead battery image */
+ NWZ_NVP_DBS, /* */
+ NWZ_NVP_DBV, /* empr icv | empr key */
+ NWZ_NVP_DCC, /* secure clock */
+ NWZ_NVP_DG0, /* */
+ NWZ_NVP_DG1, /* */
+ NWZ_NVP_DOR, /* key mode (debug/release) */
+ NWZ_NVP_E00, /* EMPR 0 */
+ NWZ_NVP_E01, /* EMPR 1 */
+ NWZ_NVP_E02, /* EMPR 2 */
+ NWZ_NVP_E03, /* EMPR 3 */
+ NWZ_NVP_E04, /* EMPR 4 */
+ NWZ_NVP_E05, /* EMPR 5 */
+ NWZ_NVP_E06, /* EMPR 6 */
+ NWZ_NVP_E07, /* EMPR 7 */
+ NWZ_NVP_E08, /* EMPR 8 */
+ NWZ_NVP_E09, /* EMPR 9 */
+ NWZ_NVP_E10, /* EMPR 10 */
+ NWZ_NVP_E11, /* EMPR 11 */
+ NWZ_NVP_E12, /* EMPR 12 */
+ NWZ_NVP_E13, /* EMPR 13 */
+ NWZ_NVP_E14, /* EMPR 14 */
+ NWZ_NVP_E15, /* EMPR 15 */
+ NWZ_NVP_E16, /* EMPR 16 */
+ NWZ_NVP_E17, /* EMPR 17 */
+ NWZ_NVP_E18, /* EMPR 18 */
+ NWZ_NVP_E19, /* EMPR 19 */
+ NWZ_NVP_E20, /* EMPR 20 */
+ NWZ_NVP_E21, /* EMPR 21 */
+ NWZ_NVP_E22, /* EMPR 22 */
+ NWZ_NVP_E23, /* EMPR 23 */
+ NWZ_NVP_E24, /* EMPR 24 */
+ NWZ_NVP_E25, /* EMPR 25 */
+ NWZ_NVP_E26, /* EMPR 26 */
+ NWZ_NVP_E27, /* EMPR 27 */
+ NWZ_NVP_E28, /* EMPR 28 */
+ NWZ_NVP_E29, /* EMPR 29 */
+ NWZ_NVP_E30, /* EMPR 30 */
+ NWZ_NVP_E31, /* EMPR 31 */
+ NWZ_NVP_EDW, /* quick shutdown flag */
+ NWZ_NVP_EP0, /* */
+ NWZ_NVP_EP1, /* */
+ NWZ_NVP_EP2, /* */
+ NWZ_NVP_EP3, /* */
+ NWZ_NVP_ERI, /* update error image */
+ NWZ_NVP_EXM, /* exception monitor mode */
+ NWZ_NVP_FMP, /* fm parameter */
+ NWZ_NVP_FNI, /* function information */
+ NWZ_NVP_FPI, /* */
+ NWZ_NVP_FUI, /* update image */
+ NWZ_NVP_FUP, /* firmware update flag */
+ NWZ_NVP_FUR, /* */
+ NWZ_NVP_FVI, /* */
+ NWZ_NVP_GTY, /* getty mode flag */
+ NWZ_NVP_HDI, /* hold image */
+ NWZ_NVP_HLD, /* hold mode */
+ NWZ_NVP_INS, /* */
+ NWZ_NVP_IPT, /* disable iptable flag */
+ NWZ_NVP_KAS, /* key and signature */
+ NWZ_NVP_LBI, /* low battery image */
+ NWZ_NVP_LYR, /* */
+ NWZ_NVP_MAC, /* wifi mac address */
+ NWZ_NVP_MCR, /* marlin crl */
+ NWZ_NVP_MDK, /* marlin device key */
+ NWZ_NVP_MDL, /* middleware parameter */
+ NWZ_NVP_MID, /* model id */
+ NWZ_NVP_MLK, /* marlin key */
+ NWZ_NVP_MSC, /* mass storage class mode */
+ NWZ_NVP_MSO, /* MSC only mode flag */
+ NWZ_NVP_MTM, /* marlin time */
+ NWZ_NVP_MUK, /* marlin user key */
+ NWZ_NVP_NCP, /* noise cancel driver parameter */
+ NWZ_NVP_NVR, /* */
+ NWZ_NVP_PCD, /* product code */
+ NWZ_NVP_PCI, /* precharge image */
+ NWZ_NVP_PNC, /* */
+ NWZ_NVP_PRK, /* */
+ NWZ_NVP_PSK, /* bluetooth pskey */
+ NWZ_NVP_PTS, /* wifi protected setup */
+ NWZ_NVP_RBT, /* */
+ NWZ_NVP_RND, /* random data | wmt key */
+ NWZ_NVP_RTC, /* rtc alarm */
+ NWZ_NVP_SDC, /* SD Card export flag */
+ NWZ_NVP_SDP, /* sound driver parameter */
+ NWZ_NVP_SER, /* serial number */
+ NWZ_NVP_SFI, /* starfish id */
+ NWZ_NVP_SHE, /* */
+ NWZ_NVP_SHP, /* ship information */
+ NWZ_NVP_SID, /* service id */
+ NWZ_NVP_SKD, /* slacker id file */
+ NWZ_NVP_SKT, /* slacker time */
+ NWZ_NVP_SKU, /* */
+ NWZ_NVP_SLP, /* time out to sleep */
+ NWZ_NVP_SPS, /* speaker ship info */
+ NWZ_NVP_SYI, /* system information */
+ NWZ_NVP_TR0, /* EKB 0 */
+ NWZ_NVP_TR1, /* EKB 1 */
+ NWZ_NVP_TST, /* test mode flag */
+ NWZ_NVP_UBP, /* u-boot password */
+ NWZ_NVP_UFN, /* update file name */
+ NWZ_NVP_UMS, /* */
+ NWZ_NVP_UPS, /* */
+ NWZ_NVP_VAR, /* */
+ NWZ_NVP_VRT, /* europe vol regulation flag */
+ NWZ_NVP_COUNT /* Number of nvp nodes */
+};
+
+/* Invalid NVP index */
+#define NWZ_NVP_INVALID -1 /* Non-existent entry */
+/* Number of models */
+#define NWZ_MODEL_COUNT 186
+/* Number of series */
+#define NWZ_SERIES_COUNT 36
+
+/* NVP node info */
+struct nwz_nvp_info_t
+{
+ const char *name; /* Sony's name: "bti" */
+ unsigned long size; /* Size in bytes */
+ const char *desc; /* Description: "bootloader image" */
+};
+
+/* NVP index map (nwz_nvp_node_t -> index) */
+typedef int nwz_nvp_index_t[NWZ_NVP_COUNT];
+
+/* Model info */
+struct nwz_model_info_t
+{
+ unsigned long mid; /* Model ID: first 4 bytes of the NVP mid entry */
+ const char *name; /* Human name: "NWZ-E463" */
+};
+
+/* Series info */
+struct nwz_series_info_t
+{
+ const char *codename; /* Rockbox codename: nwz-e460 */
+ const char *name; /* Human name: "NWZ-E460 Series" */
+ int mid_count; /* number of entries in mid_list */
+ unsigned long *mid; /* List of model IDs */
+ /* Pointer to a name -> index map, nonexistent entries map to NWZ_NVP_INVALID */
+ nwz_nvp_index_t *nvp_index;
+};
+
+/* List of all NVP entries, indexed by nwz_nvp_node_t */
+extern struct nwz_nvp_info_t nwz_nvp[NWZ_NVP_COUNT];
+/* List of all models, sorted by increasing values of model ID */
+extern struct nwz_model_info_t nwz_model[NWZ_MODEL_COUNT];
+/* List of all series */
+extern struct nwz_series_info_t nwz_series[NWZ_SERIES_COUNT];
+
+#endif /* __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/firmware/target/hosted/sonynwz/nwz_keys.h b/firmware/target/hosted/sonynwz/nwz_keys.h
new file mode 100644
index 0000000000..d2314d4a12
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/nwz_keys.h
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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_KEYS_H__
+#define __NWZ_KEYS_H__
+
+/* 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:
+ * - one part giving the code of the key just pressed/released
+ * - one part is a bitmap of various keys (such as HOLD)
+ * The status of the HOLD can be queried at any time by reading the state of
+ * 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
+#define NWZ_KEY_RIGHT 1
+#define NWZ_KEY_LEFT 2
+#define NWZ_KEY_UP 3
+#define NWZ_KEY_DOWN 4
+#define NWZ_KEY_ZAPPIN 5
+#define NWZ_KEY_AD0_6 6
+#define NWZ_KEY_AD0_7 7
+/* special "key" when event is for bitmap key, like HOLD */
+#define NWZ_KEY_NONE 15
+#define NWZ_KEY_VOL_DOWN 16
+#define NWZ_KEY_VOL_UP 17
+#define NWZ_KEY_BACK 18
+#define NWZ_KEY_OPTION 19
+#define NWZ_KEY_BT 20
+#define NWZ_KEY_AD1_5 21
+#define NWZ_KEY_AD1_6 22
+#define NWZ_KEY_AD1_7 23
+
+/* bitmap of other things */
+#define NWZ_KEY_NMLHP_MASK 0x20
+#define NWZ_KEY_NCHP_MASK 0x40
+#define NWZ_KEY_HOLD_MASK 0x80
+#define NWZ_KEY_NC_MASK 0x100
+
+#endif /* __NWZ_KEYS_H__ */
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/firmware/target/hosted/sonynwz/nwz_ts.h b/firmware/target/hosted/sonynwz/nwz_ts.h
new file mode 100644
index 0000000000..4528609ddc
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/nwz_ts.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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_TS_H__
+#define __NWZ_TS_H__
+
+#define NWZ_TS_NAME "icx_touch_screen"
+
+/* How touchscreen works:
+ *
+ * The touchscreen uses mostly the standard linux protocol, reporting ABS_X,
+ * ABS_Y, ABS_PRESSURE, TOOL_WIDTH and BTN_TOUCH with SYN to synchronize. The
+ * only nonstandard part is the use of REL_RX and REL_RY to report "flick"
+ * detection by the hardware. */
+
+#endif /* __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/firmware/target/hosted/sonynwz/power-nwz.h b/firmware/target/hosted/sonynwz/power-nwz.h
new file mode 100644
index 0000000000..965013a35a
--- /dev/null
+++ b/firmware/target/hosted/sonynwz/power-nwz.h
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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 __POWER_NWZ_H__
+#define __POWER_NWZ_H__
+
+#include "power.h"
+
+/** power */
+
+#define NWZ_POWER_DEV "/dev/icx_power"
+
+#define NWZ_POWER_TYPE 'P'
+
+/* ioctl request */
+#define NWZ_POWER_GET_STATUS _IOR(NWZ_POWER_TYPE, 0, int *)
+#define NWZ_POWER_SET_VBUS_LIMIT _IOW(NWZ_POWER_TYPE, 1, int *)
+#define NWZ_POWER_GET_BAT_ADVAL _IOR(NWZ_POWER_TYPE, 2, int *)
+#define NWZ_POWER_GET_BAT_GAUGE _IOR(NWZ_POWER_TYPE, 3, int *)
+#define NWZ_POWER_ENABLE_CHARGER _IOW(NWZ_POWER_TYPE, 4, int *)
+#define NWZ_POWER_ENABLE_DEBUG_PORT _IO (NWZ_POWER_TYPE, 5)
+#define NWZ_POWER_IS_FULLY_CHARGED _IOR(NWZ_POWER_TYPE, 6, int *)
+#define NWZ_POWER_AVG_VALUE _IO (NWZ_POWER_TYPE, 7)
+#define NWZ_POWER_CONSIDERATION_CHARGE _IOW(NWZ_POWER_TYPE, 8, int)
+#define NWZ_POWER_GET_VBUS_LIMIT _IOR(NWZ_POWER_TYPE, 9, int *)
+#define NWZ_POWER_GET_CHARGE_SWITCH _IOR(NWZ_POWER_TYPE,10, int *)
+#define NWZ_POWER_GET_SAMPLE_COUNT _IOR(NWZ_POWER_TYPE,11, int *)
+#define NWZ_POWER_SET_CHARGE_CURRENT _IOW(NWZ_POWER_TYPE,12, int *)
+#define NWZ_POWER_GET_CHARGE_CURRENT _IOR(NWZ_POWER_TYPE,13, int *)
+#define NWZ_POWER_GET_VBUS_ADVAL _IOR(NWZ_POWER_TYPE,14, int *)
+#define NWZ_POWER_GET_VSYS_ADVAL _IOR(NWZ_POWER_TYPE,15, int *)
+#define NWZ_POWER_GET_VBAT_ADVAL _IOR(NWZ_POWER_TYPE,16, int *)
+#define NWZ_POWER_CHG_VBUS_LIMIT _IOW(NWZ_POWER_TYPE,17, int *)
+#define NWZ_POWER_SET_ACCESSARY_CHARGE_MODE _IOW(NWZ_POWER_TYPE,18, int *)
+#define NWZ_POWER_GET_ACCESSARY_CHARGE_MODE _IOR(NWZ_POWER_TYPE,19, int *)
+
+/* NWZ_POWER_GET_STATUS bitmap */
+#define NWZ_POWER_STATUS_CHARGE_INIT 0x100 /* initializing charging */
+#define NWZ_POWER_STATUS_CHARGE_STATUS 0x0c0 /* charging status mask */
+#define NWZ_POWER_STATUS_VBUS_DET 0x020 /* vbus detected */
+#define NWZ_POWER_STATUS_AC_DET 0x010 /* ac adapter detected */
+#define NWZ_POWER_STATUS_CHARGE_LOW 0x001 /* full voltage of 4.1 instead of 4.2 */
+/* NWZ_POWER_STATUS_CHARGING_MASK value */
+#define NWZ_POWER_STATUS_CHARGE_STATUS_CHARGING 0xc0
+#define NWZ_POWER_STATUS_CHARGE_STATUS_SUSPEND 0x80
+#define NWZ_POWER_STATUS_CHARGE_STATUS_TIMEOUT 0x40
+#define NWZ_POWER_STATUS_CHARGE_STATUS_NORMAL 0x00
+
+/* base values to convert from adval to mV (represents mV for adval of 255) */
+#define NWZ_POWER_AD_BASE_VBAT 4664
+#define NWZ_POWER_AD_BASE_VBUS 7254
+#define NWZ_POWER_AD_BASE_VSYS 5700
+
+/* battery gauge */
+#define NWZ_POWER_BAT_NOBAT -100 /* no battery */
+#define NWZ_POWER_BAT_VERYLOW -99 /* very low */
+#define NWZ_POWER_BAT_LOW 0 /* low */
+#define NWZ_POWER_BAT_GAUGE0 1 /* ____ */
+#define NWZ_POWER_BAT_GAUGE1 2 /* O___ */
+#define NWZ_POWER_BAT_GAUGE2 3 /* OO__ */
+#define NWZ_POWER_BAT_GAUGE3 4 /* OOO_ */
+#define NWZ_POWER_BAT_GAUGE4 5 /* OOOO */
+
+/* NWZ_POWER_GET_ACCESSARY_CHARGE_MODE */
+#define NWZ_POWER_ACC_CHARGE_NONE 0
+#define NWZ_POWER_ACC_CHARGE_VBAT 1
+#define NWZ_POWER_ACC_CHARGE_VSYS 2
+
+/** pminfo
+ *
+ * This driver seems to collect the state of the device on boot. Thus one
+ * can know if a key was pressed when booting for example.
+ */
+
+#define NWZ_PMINFO_DEV "/dev/icx_pminfo"
+
+#define NWZ_PMINFO_TYPE 'b'
+
+/* ioctl request */
+
+#define NWZ_PMINFO_GET_FACTOR _IOR(NWZ_PMINFO_TYPE, 0, unsigned int *)
+#define NWZ_PMINFO_CLR_DETRSTFLG _IO(NWZ_PMINFO_TYPE, 1)
+
+/* NWZ_PMINFO_GET_FACTOR bitmap
+ * WARNING this information may not apply to all players and some bits do not
+ * exists on some players */
+#define ICX_PMINFO_FACTOR_RTC_WAL 0x20000000 /* RTC Weekly Alarm */
+#define ICX_PMINFO_FACTOR_RTC_DAL 0x10000000 /* RTC Daily Alarm */
+#define ICX_PMINFO_FACTOR_VBUS 0x08000000 /* VBUS in/out */
+#define ICX_PMINFO_FACTOR_DC_POWER 0x04000000 /* AC Adaptor in/out */
+#define ICX_PMINFO_FACTOR_USB_WAKE 0x01000000 /* USB Wake */
+#define ICX_PMINFO_FACTOR_CHARGE 0x00400000 /* Charge */
+#define ICX_PMINFO_FACTOR_CRADLE 0x00080000 /* Cradle in/out */
+#define ICX_PMINFO_FACTOR_AB_EV 0x00008000 /* ab event */
+#define ICX_PMINFO_FACTOR_NC_SW 0x00004000 /* nc switch */
+#define ICX_PMINFO_FACTOR_HOLD_SW 0x00002000 /* hold switch */
+#define ICX_PMINFO_FACTOR_KEY_PAD 0x00001000 /* keypad */
+#define ICX_PMINFO_FACTOR_KEY_CODE 0x00000FFF /* keycode */
+
+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__ */