From ba91ff10e8c974e50e429d072641ac5e0acdd72e Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Wed, 19 Oct 2016 17:03:52 +0200 Subject: nwztools: add a new plattools directory with code to run on the device This is code is intended to development into a library of code for the NWZ that will be useful to write the "bootloader" on those device. At the same time, it comes with test programs that are easy to run in firmware upgrade mode and also provide a great test bench for the library. At the moment, two test programs are available: - test_display: simply prints two messages using /usr/bin/lcdmsg - test_keys: displays input key event Change-Id: I9d214894ffc9127b528fcdd3eb5d6b61f4e657a7 --- utils/nwztools/plattools/Makefile | 17 ++++ utils/nwztools/plattools/README | 27 ++++++ utils/nwztools/plattools/nwz_keys.h | 60 ++++++++++++ utils/nwztools/plattools/nwz_lib.c | 159 ++++++++++++++++++++++++++++++++ utils/nwztools/plattools/nwz_lib.h | 64 +++++++++++++ utils/nwztools/plattools/test_display.c | 30 ++++++ utils/nwztools/plattools/test_keys.c | 69 ++++++++++++++ 7 files changed, 426 insertions(+) create mode 100644 utils/nwztools/plattools/Makefile create mode 100644 utils/nwztools/plattools/README create mode 100644 utils/nwztools/plattools/nwz_keys.h create mode 100644 utils/nwztools/plattools/nwz_lib.c create mode 100644 utils/nwztools/plattools/nwz_lib.h create mode 100644 utils/nwztools/plattools/test_display.c create mode 100644 utils/nwztools/plattools/test_keys.c (limited to 'utils/nwztools/plattools') diff --git a/utils/nwztools/plattools/Makefile b/utils/nwztools/plattools/Makefile new file mode 100644 index 0000000000..d3efdb74a3 --- /dev/null +++ b/utils/nwztools/plattools/Makefile @@ -0,0 +1,17 @@ +PREFIX?=arm-sony-linux-gnueabi- +CC=$(PREFIX)gcc +LD=$(PREFIX)gcc +CFLAGS=-std=gnu99 -Wall -O2 +INCLUDES=-I. + +LIB_FILES=nwz_lib.c +ALL_BUT_LIB=$(patsubst %.c,%.elf,$(filter-out $(LIB_FILES),$(wildcard *.c))) + +all: $(ALL_BUT_LIB) + +%.elf: %.c $(LIB_FILES) + $(CC) $(CFLAGS) $(INCLUDES) -o $@ $^ + +clean: + rm -rf $(ALL_BUT_LIB) + diff --git a/utils/nwztools/plattools/README b/utils/nwztools/plattools/README new file mode 100644 index 0000000000..e33dfeb354 --- /dev/null +++ b/utils/nwztools/plattools/README @@ -0,0 +1,27 @@ +Platform tools +-------------- + +Those tools are designed to run on the devices. They are mostly tests that can +be run in firmware upgrade mode (using exec_file in utils/nwztools/scripts/). To +compile those, you will need the sony nwz cross compiler. The canonical way to +run them is as follows: + +1) Build the tools: + cd /path/to/utils/nwztools/plattools + make +Note that the default cross compiler prefix is arm-sony-linux-gnueabi- but it +can be changed using PREFIX: +PREFIX="sony-nwz-linux-gnueabi-" make + +2) Embed the wanted excutable in a firmware upgrade for your device. The README +in utils/nwztools/scripts contains more documentation on how to select the right +target. For example if you want to embed test_display for the NWZ-E460 series, +you should run: + cd /path/to/utils/nwztools/scripts + make exec_file UPG=test_display_nwze46x.upg NWZ_TARGET=nwz-e46x EXEC=../plattools/test_display.elf + +3) Put the upgrade file on the device and trigger a firmware upgrade. Assuming +your NWZ device is /dev/sdb1 and is mounted at /media/pamaury/WALKMAN, run: + cd /path/to/utils/nwztools/scripts + make copy_fw_upgrade UPG=test_display_nwze46x.upg NWZ_MOUNT=/media/pamaury/WALKMAN/ + sudo make do_fw_upgrade NWZ_DEV=/dev/sdb1 diff --git a/utils/nwztools/plattools/nwz_keys.h b/utils/nwztools/plattools/nwz_keys.h new file mode 100644 index 0000000000..8228e5b620 --- /dev/null +++ b/utils/nwztools/plattools/nwz_keys.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * __________ __ ___. + * 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. + */ + +/* 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/utils/nwztools/plattools/nwz_lib.c b/utils/nwztools/plattools/nwz_lib.c new file mode 100644 index 0000000000..ec862e638b --- /dev/null +++ b/utils/nwztools/plattools/nwz_lib.c @@ -0,0 +1,159 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "nwz_lib.h" + +void nwz_run(const char *file, const char *args[], bool wait) +{ + pid_t child_pid = fork(); + if(child_pid != 0) + { + if(wait) + { + int status; + waitpid(child_pid, &status, 0); + } + } + else + { + execvp(file, (char * const *)args); + _exit(1); + } +} + +void nwz_lcdmsg(bool clear, int x, int y, const char *msg) +{ + const char *path_lcdmsg = "/usr/local/bin/lcdmsg"; + const char *args[16]; + int index = 0; + char locate[32]; + args[index++] = path_lcdmsg; + if(clear) + args[index++] = "-c"; + args[index++] = "-f"; + args[index++] = "/usr/local/bin/font_08x12.bmp"; + args[index++] = "-l"; + sprintf(locate, "%d,%d", x, y); + args[index++] = locate; + args[index++] = msg; + args[index++] = NULL; + /* wait for lcdmsg to finish to avoid any race conditions in framebuffer + * accesses */ + nwz_run(path_lcdmsg, args, true); +} + +void nwz_lcdmsgf(bool clear, int x, int y, const char *format, ...) +{ + char buffer[1024]; + va_list args; + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + nwz_lcdmsg(clear, x, y, buffer); +} + +int nwz_key_open(void) +{ + return open("/dev/input/event0", O_RDONLY); +} + +void nwz_key_close(int fd) +{ + close(fd); +} + +int nwz_key_get_hold_status(int fd) +{ + unsigned long led_hold = 0; + if(ioctl(fd, EVIOCGLED(sizeof(led_hold)), &led_hold) < 0) + return -1; + return led_hold; +} + +int nwz_key_wait_event(int fd, long tmo_us) +{ + fd_set rfds; + struct timeval tv; + struct timeval *tv_ptr = NULL; + /* watch the input device */ + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + /* setup timeout */ + if(tmo_us >= 0) + { + tv.tv_sec = 0; + tv.tv_usec = tmo_us; + tv_ptr = &tv; + } + return select(fd + 1, &rfds, NULL, NULL, tv_ptr); +} + +int nwz_key_read_event(int fd, struct input_event *evt) +{ + int ret = read(fd, evt, sizeof(struct input_event)); + if(ret != sizeof(struct input_event)) + return -1; + return 1; +} + +int nwz_key_event_get_keycode(struct input_event *evt) +{ + return evt->code & NWZ_KEY_MASK; +} + +bool nwz_key_event_is_press(struct input_event *evt) +{ + return evt->value == 0; +} + +bool nwz_key_event_get_hold_status(struct input_event *evt) +{ + return !!(evt->code & NWZ_KEY_HOLD_MASK); +} + +static const char *nwz_keyname[NWZ_KEY_MASK + 1] = +{ + [0 ... NWZ_KEY_MASK] = "unknown", + [NWZ_KEY_PLAY] = "PLAY", + [NWZ_KEY_RIGHT] = "RIGHT", + [NWZ_KEY_LEFT] = "LEFT", + [NWZ_KEY_UP] = "UP", + [NWZ_KEY_DOWN] = "DOWN", + [NWZ_KEY_ZAPPIN] = "ZAPPIN", + [NWZ_KEY_AD0_6] = "AD0_6", + [NWZ_KEY_AD0_7] = "AD0_7", + [NWZ_KEY_NONE] = "NONE", + [NWZ_KEY_VOL_DOWN] = "VOL DOWN", + [NWZ_KEY_VOL_UP] = "VOL UP", + [NWZ_KEY_BACK] = "BACK", + [NWZ_KEY_OPTION] = "OPTION", + [NWZ_KEY_BT] = "BT", + [NWZ_KEY_AD1_5] = "AD1_5", + [NWZ_KEY_AD1_6] = "AD1_6", + [NWZ_KEY_AD1_7] = "AD1_7", +}; + +const char *nwz_key_get_name(int keycode) +{ + if(keycode <0 || keycode > NWZ_KEY_MASK) + return "invalid"; + else + return nwz_keyname[keycode]; +} diff --git a/utils/nwztools/plattools/nwz_lib.h b/utils/nwztools/plattools/nwz_lib.h new file mode 100644 index 0000000000..e9d885d87a --- /dev/null +++ b/utils/nwztools/plattools/nwz_lib.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _NWZLIB_H_ +#define _NWZLIB_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nwz_keys.h" + +/* run a program and exit with nonzero status in case of error + * argument list must be NULL terminated */ +void nwz_run(const char *file, const char *args[], bool wait); + +/* invoke /usr/bin/lcdmsg to display a message using the small font, optionally + * clearing the screen before */ +void nwz_lcdmsg(bool clear, int x, int y, const char *msg); +void nwz_lcdmsgf(bool clear, int x, int y, const char *format, ...); + +/* open icx_key input device and return file descriptor */ +int nwz_key_open(void); +void nwz_key_close(int fd); +/* return HOLD status: 0 or 1, or -1 on error */ +int nwz_key_get_hold_status(int fd); +/* wait for an input event (and return 1), or a timeout (return 0), or error (-1) + * set the timeout to -1 to block */ +int nwz_key_wait_event(int fd, long tmo_us); +/* read an event from the device (may block unless you waited for an event before), + * return 1 on success, <0 on error */ +int nwz_key_read_event(int fd, struct input_event *evt); +/* return keycode from event */ +int nwz_key_event_get_keycode(struct input_event *evt); +/* return press/released status from event */ +bool nwz_key_event_is_press(struct input_event *evt); +/* return HOLD status from event */ +bool nwz_key_event_get_hold_status(struct input_event *evt); +/* get keycode name */ +const char *nwz_key_get_name(int keycode); + +#endif /* _NWZLIB_H_ */ diff --git a/utils/nwztools/plattools/test_display.c b/utils/nwztools/plattools/test_display.c new file mode 100644 index 0000000000..a0dc706624 --- /dev/null +++ b/utils/nwztools/plattools/test_display.c @@ -0,0 +1,30 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "nwz_lib.h" + +int main(int argc, char **argv) +{ + /* clear screen and display welcome message */ + nwz_lcdmsg(true, 0, 0, "test_display"); + nwz_lcdmsg(false, 3, 10, "This program will stop in 5 seconds"); + sleep(5); + return 0; +} diff --git a/utils/nwztools/plattools/test_keys.c b/utils/nwztools/plattools/test_keys.c new file mode 100644 index 0000000000..3640e007fc --- /dev/null +++ b/utils/nwztools/plattools/test_keys.c @@ -0,0 +1,69 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2016 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "nwz_lib.h" + +int main(int argc, char **argv) +{ + /* clear screen and display welcome message */ + nwz_lcdmsg(true, 0, 0, "test_keys"); + nwz_lcdmsg(false, 0, 2, "hold PWR OFF for 3 seconds to quit"); + /* open input device */ + int input_fd = nwz_key_open(); + if(input_fd < 0) + { + nwz_lcdmsg(false, 3, 4, "Cannot open input device"); + sleep(2); + return 1; + } + /* display input state in a loop */ + int pwr_off_pressed = 0; /* 0 = no pressed, >0 = number of seconds pressed - 1 */ + while(1) + { + /* display HOLD status */ + nwz_lcdmsgf(false, 2, 5, "HOLD: %d", nwz_key_get_hold_status(input_fd)); + /* wait for event */ + int ret = nwz_key_wait_event(input_fd, 1000000); + if(ret != 1) + { + if(pwr_off_pressed > 0) + pwr_off_pressed++; + if(pwr_off_pressed >= 4) + break; + continue; + } + struct input_event evt; + if(nwz_key_read_event(input_fd, &evt) != 1) + continue; + nwz_lcdmsgf(false, 2, 6, "%s %s (HOLD=%d) ", + nwz_key_get_name(nwz_key_event_get_keycode(&evt)), + nwz_key_event_is_press(&evt) ? "pressed" : "released", + nwz_key_event_get_hold_status(&evt)); + if(nwz_key_event_get_keycode(&evt) == NWZ_KEY_OPTION && nwz_key_event_is_press(&evt)) + pwr_off_pressed = 1; + else + pwr_off_pressed = 0; + } + /* close input device */ + close(input_fd); + /* finish nicely */ + return 0; +} + -- cgit