Initial commit for the Sony NWZ linux port

SUPPORTED SERIES:
- NWZ-E450
- NWZ-E460
- NWZ-E470
- NWZ-E580
- NWZ-A10

NOTES:
- bootloader makefile convert an extra font to be installed alongside the bootloader
  since sysfont is way too small
- the toolsicon bitmap comes from the Oxygen iconset
- touchscreen driver is untested

TODO:
- implement audio routing driver (pcm is handled by pcm-alsa)
- fix playback: it crashes on illegal instruction in DEBUG builds
- find out why the browser starts at / instead of /contents
- implement radio support
- implement return to OF for usb handling
- calibrate battery curve (NB: of can report a battery level on a 0-5 scale but
  probabl don't want to use that ?)
- implement simulator build (we need a nice image of the player)
- figure out if we can detect jack removal

POTENTIAL TODOS:
- try to build a usb serial gadget and gdbserver

Change-Id: Ic77d71e0651355d47cc4e423a40fb64a60c69a80
This commit is contained in:
Amaury Pouly 2017-02-23 11:33:19 +01:00
parent 142f80f07d
commit 1d121e8c08
89 changed files with 4439 additions and 2913 deletions

View file

@ -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];
}

View file

@ -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

View file

@ -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 */

View file

@ -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);
}

View file

@ -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_ */

View file

@ -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;
}

View file

@ -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();
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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__ */

File diff suppressed because it is too large Load diff

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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);
}

View file

@ -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__ */

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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__ */