From 249bba03f1051f4984538f66b9e7d36674c61e5c Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sat, 24 Dec 2011 11:56:46 +0000 Subject: [PATCH] Initial commit of the Samsung YP-R0 port. This port is a hybrid native/RaaA port. It runs on a embedded linux system, but is the only application. It therefore can implement lots of stuff that native targets also implement, while leveraging the underlying linux kernel. The port is quite advanced. User interface, audio playback, plugins work mostly fine. Missing is e.g. power mangement and USB (see SamsungYPR0 wiki page). Included in utils/ypr0tools are scripts and programs required to generate a patched firmware. The patched firmware has the rootfs modified to load Rockbox. It includes a early/safe USB mode. This port needs a new toolchain, one that includes glibc headers and libraries. rockboxdev.sh can generate it, but e.g. codesourcey and distro packages may also work. Most of the initial effort is done by Lorenzo Miori and others (on ABI), including reverse engineering and patching of the original firmware, initial drivers, and more. Big thanks to you. Flyspray: FS#12348 Author: Lorenzo Miori, myself Merry christmas to ypr0 owners! :) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31415 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 2 + apps/keymaps/keymap-ypr0.c | 258 +++++ apps/plugin.h | 2 + apps/plugins/SOURCES.app_build | 6 + apps/plugins/SUBDIRS | 2 +- apps/plugins/SUBDIRS.app_build | 10 +- apps/plugins/battery_bench.c | 3 +- apps/plugins/blackjack.c | 16 + apps/plugins/bounce.c | 3 +- apps/plugins/brickmania.c | 3 +- apps/plugins/calculator.c | 11 + apps/plugins/calendar.c | 10 + apps/plugins/chessbox/chessbox_pgn.h | 10 + apps/plugins/chessclock.c | 10 + apps/plugins/chip8.c | 12 + apps/plugins/chopper.c | 3 +- apps/plugins/clix.c | 3 +- apps/plugins/cube.c | 10 + apps/plugins/doom/i_video.c | 11 + apps/plugins/fft/fft.c | 9 + apps/plugins/fireworks.c | 3 +- apps/plugins/flipit.c | 12 + apps/plugins/fractals/fractal.h | 12 + apps/plugins/goban/goban.h | 10 + apps/plugins/imageviewer/imageviewer_button.h | 12 + apps/plugins/invadrox.c | 3 +- apps/plugins/jewels.c | 3 +- apps/plugins/lamp.c | 3 +- apps/plugins/lib/pluginlib_actions.c | 6 +- apps/plugins/lib/simple_viewer.c | 1 + apps/plugins/logo.c | 3 +- apps/plugins/lua/strcspn.c | 1 + apps/plugins/lua/strpbrk.c | 1 + apps/plugins/matrix.c | 3 +- apps/plugins/midi/midiplay.c | 8 + apps/plugins/minesweeper.c | 10 + apps/plugins/mosaique.c | 3 +- apps/plugins/mp3_encoder.c | 3 +- apps/plugins/mpegplayer/mpeg_settings.c | 8 + apps/plugins/mpegplayer/mpegplayer.c | 9 + apps/plugins/oscilloscope.c | 11 + apps/plugins/pacbox/pacbox.h | 11 + apps/plugins/pdbox/pdbox.h | 19 +- apps/plugins/pegbox.c | 18 + apps/plugins/pong.c | 8 + apps/plugins/reversi/reversi-gui.h | 9 + apps/plugins/rockblox.c | 12 + apps/plugins/rockblox1d.c | 3 +- apps/plugins/rockboy/rockboy.c | 12 + apps/plugins/rockboy/rockmacros.h | 2 - apps/plugins/rockpaint.c | 11 + apps/plugins/sliding_puzzle.c | 6 +- apps/plugins/snake.c | 3 +- apps/plugins/snake2.c | 3 +- apps/plugins/snow.c | 3 +- apps/plugins/sokoban.c | 15 + apps/plugins/solitaire.c | 18 + apps/plugins/spacerocks.c | 9 + apps/plugins/star.c | 17 + apps/plugins/starfield.c | 3 +- apps/plugins/stats.c | 3 +- apps/plugins/stopwatch.c | 8 + apps/plugins/sudoku/sudoku.h | 10 + apps/plugins/superdom.c | 3 +- apps/plugins/test_codec.c | 2 + apps/plugins/test_fps.c | 2 + apps/plugins/test_gfx.c | 6 +- apps/plugins/text_viewer/tv_button.h | 10 + apps/plugins/vu_meter.c | 11 + apps/plugins/wormlet.c | 3 +- apps/plugins/xobox.c | 9 + apps/plugins/zxbox/keymaps.h | 12 +- apps/plugins/zxbox/zxbox_keyb.c | 9 + docs/CREDITS | 1 + firmware/SOURCES | 29 +- firmware/common/rbpaths.c | 34 + firmware/drivers/audio/as3514.c | 40 + firmware/drivers/rtc/rtc_as3514.c | 4 +- firmware/export/as3514.h | 5 + firmware/export/ascodec.h | 4 + firmware/export/audiohw.h | 2 +- firmware/export/config.h | 16 + firmware/export/config/ypr0.h | 168 ++++ firmware/export/rbpaths.h | 5 +- firmware/include/dir_uncached.h | 2 +- firmware/pcm_mixer.c | 5 + firmware/sound.c | 5 +- firmware/system.c | 2 +- firmware/target/hosted/pcm-alsa.c | 518 ++++++++++ firmware/target/hosted/ypr0/adc-target.h | 25 + firmware/target/hosted/ypr0/ascodec-target.h | 92 ++ firmware/target/hosted/ypr0/ascodec-ypr0.c | 206 ++++ .../target/hosted/ypr0/backlight-target.h | 29 + firmware/target/hosted/ypr0/backlight-ypr0.c | 89 ++ firmware/target/hosted/ypr0/button-target.h | 53 ++ firmware/target/hosted/ypr0/button-ypr0.c | 103 ++ firmware/target/hosted/ypr0/dir-target.h | 56 ++ firmware/target/hosted/ypr0/fs-ypr0.c | 141 +++ firmware/target/hosted/ypr0/i2c-target.h | 25 + firmware/target/hosted/ypr0/kernel-ypr0.c | 163 ++++ firmware/target/hosted/ypr0/lc-ypr0.c | 40 + firmware/target/hosted/ypr0/lcd-ypr0.c | 147 +++ firmware/target/hosted/ypr0/powermgmt-ypr0.c | 133 +++ firmware/target/hosted/ypr0/system-target.h | 37 + firmware/target/hosted/ypr0/system-ypr0.c | 106 +++ firmware/target/hosted/ypr0/usb-target.h | 25 + firmware/target/hosted/ypr0/ypr0.make | 25 + tools/buildzip.pl | 7 +- tools/configure | 48 +- tools/root.make | 4 + utils/ypr0tools/Makefile | 13 + utils/ypr0tools/MuonEncrypt | Bin 0 -> 11006 bytes utils/ypr0tools/README | 12 + utils/ypr0tools/cramfs-1.1/COPYING | 340 +++++++ utils/ypr0tools/cramfs-1.1/GNUmakefile | 12 + utils/ypr0tools/cramfs-1.1/NOTES | 168 ++++ utils/ypr0tools/cramfs-1.1/README | 76 ++ utils/ypr0tools/cramfs-1.1/cramfsck.c | 716 ++++++++++++++ utils/ypr0tools/cramfs-1.1/linux/cramfs_fs.h | 98 ++ .../ypr0tools/cramfs-1.1/linux/cramfs_fs_sb.h | 15 + utils/ypr0tools/cramfs-1.1/mkcramfs.c | 889 ++++++++++++++++++ utils/ypr0tools/extract_section.c | 85 ++ utils/ypr0tools/files/.rockbox/README | 1 + utils/ypr0tools/files/Playlists/README | 1 + utils/ypr0tools/files/etc/mods/safe_mode.raw | Bin 0 -> 230400 bytes utils/ypr0tools/files/etc/mods/safe_mode.sh | 111 +++ utils/ypr0tools/files/etc/profile | 66 ++ utils/ypr0tools/pack-firmware.sh | 132 +++ utils/ypr0tools/patch-firmware.sh | 67 ++ utils/ypr0tools/rockbox.sh | 47 + utils/ypr0tools/unpack-firmware.sh | 90 ++ 131 files changed, 6074 insertions(+), 48 deletions(-) create mode 100644 apps/keymaps/keymap-ypr0.c create mode 100644 firmware/export/config/ypr0.h create mode 100644 firmware/target/hosted/pcm-alsa.c create mode 100644 firmware/target/hosted/ypr0/adc-target.h create mode 100644 firmware/target/hosted/ypr0/ascodec-target.h create mode 100644 firmware/target/hosted/ypr0/ascodec-ypr0.c create mode 100644 firmware/target/hosted/ypr0/backlight-target.h create mode 100644 firmware/target/hosted/ypr0/backlight-ypr0.c create mode 100644 firmware/target/hosted/ypr0/button-target.h create mode 100644 firmware/target/hosted/ypr0/button-ypr0.c create mode 100644 firmware/target/hosted/ypr0/dir-target.h create mode 100644 firmware/target/hosted/ypr0/fs-ypr0.c create mode 100644 firmware/target/hosted/ypr0/i2c-target.h create mode 100644 firmware/target/hosted/ypr0/kernel-ypr0.c create mode 100644 firmware/target/hosted/ypr0/lc-ypr0.c create mode 100644 firmware/target/hosted/ypr0/lcd-ypr0.c create mode 100644 firmware/target/hosted/ypr0/powermgmt-ypr0.c create mode 100644 firmware/target/hosted/ypr0/system-target.h create mode 100644 firmware/target/hosted/ypr0/system-ypr0.c create mode 100644 firmware/target/hosted/ypr0/usb-target.h create mode 100644 firmware/target/hosted/ypr0/ypr0.make create mode 100644 utils/ypr0tools/Makefile create mode 100755 utils/ypr0tools/MuonEncrypt create mode 100644 utils/ypr0tools/README create mode 100644 utils/ypr0tools/cramfs-1.1/COPYING create mode 100644 utils/ypr0tools/cramfs-1.1/GNUmakefile create mode 100644 utils/ypr0tools/cramfs-1.1/NOTES create mode 100644 utils/ypr0tools/cramfs-1.1/README create mode 100644 utils/ypr0tools/cramfs-1.1/cramfsck.c create mode 100644 utils/ypr0tools/cramfs-1.1/linux/cramfs_fs.h create mode 100644 utils/ypr0tools/cramfs-1.1/linux/cramfs_fs_sb.h create mode 100644 utils/ypr0tools/cramfs-1.1/mkcramfs.c create mode 100644 utils/ypr0tools/extract_section.c create mode 100644 utils/ypr0tools/files/.rockbox/README create mode 100644 utils/ypr0tools/files/Playlists/README create mode 100644 utils/ypr0tools/files/etc/mods/safe_mode.raw create mode 100755 utils/ypr0tools/files/etc/mods/safe_mode.sh create mode 100755 utils/ypr0tools/files/etc/profile create mode 100755 utils/ypr0tools/pack-firmware.sh create mode 100755 utils/ypr0tools/patch-firmware.sh create mode 100755 utils/ypr0tools/rockbox.sh create mode 100755 utils/ypr0tools/unpack-firmware.sh diff --git a/apps/SOURCES b/apps/SOURCES index 34dc202345..53a67fd307 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -332,5 +332,7 @@ keymaps/keymap-hm60x.c keymaps/keymap-hm801.c #elif CONFIG_KEYPAD == SANSA_CONNECT_PAD keymaps/keymap-sansa-connect.c +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +keymaps/keymap-ypr0.c #endif diff --git a/apps/keymaps/keymap-ypr0.c b/apps/keymaps/keymap-ypr0.c new file mode 100644 index 0000000000..b5706760ba --- /dev/null +++ b/apps/keymaps/keymap-ypr0.c @@ -0,0 +1,258 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: keymap-sdl.c 28704 2010-11-29 11:28:53Z teru $ + * + * Copyright (C) 2011 Lorenzo Miori + * + * 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. + * + ****************************************************************************/ + +/* Button Code Definitions for Samsung YP-R0 target */ + +#include +#include +#include + +#include "config.h" +#include "action.h" +#include "button.h" +#include "settings.h" + +/* + * The format of the list is as follows + * { Action Code, Button code, Prereq button code } + * if there's no need to check the previous button's value, use BUTTON_NONE + * Insert LAST_ITEM_IN_LIST at the end of each mapping + */ + +static const struct button_mapping button_context_standard[] = { + { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_STD_CANCEL, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, + + { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, + { ACTION_STD_OK, BUTTON_RIGHT, BUTTON_NONE }, + + { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, + { ACTION_STD_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, + + { ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_NONE }, + { ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, + + LAST_ITEM_IN_LIST +}; /* button_context_standard */ + +static const struct button_mapping button_context_wps[] = { + { ACTION_WPS_PLAY, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, + { ACTION_WPS_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_WPS_BROWSE, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, + { ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, + + /* NOTE: this is available only enabling AB-Repeat mode */ + { ACTION_WPS_HOTKEY, BUTTON_USER|BUTTON_REL, BUTTON_USER }, + { ACTION_WPSAB_SINGLE, BUTTON_USER|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER }, + { ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT }, + { ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT }, + { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, + + { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT }, + { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, + + + { ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_VOLUP, BUTTON_UP, BUTTON_NONE }, + { ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_VOLDOWN, BUTTON_DOWN, BUTTON_NONE }, + + LAST_ITEM_IN_LIST +}; /* button_context_wps */ + +static const struct button_mapping button_context_list[] = { + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_list */ + +static const struct button_mapping button_context_tree[] = { + { ACTION_TREE_WPS, BUTTON_USER|BUTTON_REPEAT, BUTTON_USER }, + { ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_TREE_HOTKEY, BUTTON_USER|BUTTON_REL, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) +}; /* button_context_tree */ + +static const struct button_mapping button_context_settings[] = { + + { ACTION_SETTINGS_INC, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_SETTINGS_INCREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_DEC, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_SETTINGS_DECREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_TREE) +}; /* button_context_settings */ + +static const struct button_mapping button_context_yesno[] = { + { ACTION_YESNO_ACCEPT, BUTTON_SELECT, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_settings_yesno */ + +static const struct button_mapping button_context_colorchooser[] = { //check + { ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT }, + { ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), +}; /* button_context_colorchooser */ + +static const struct button_mapping button_context_eq[] = { + + { ACTION_STD_CANCEL, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_SETTINGS), +}; /* button_context_eq */ + +/** Bookmark Screen **/ +static const struct button_mapping button_context_bmark[] = { + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), +}; /* button_context_bmark */ + +static const struct button_mapping button_context_time[] = { + + { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE }, + { ACTION_SETTINGS_INCREPEAT, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_SETTINGS_DECREPEAT, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), +}; /* button_context_time */ + +static const struct button_mapping button_context_quickscreen[] = { + + { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE }, + { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_quickscreen */ + +static const struct button_mapping button_context_pitchscreen[] = { + + { ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE }, + { ACTION_PS_INC_BIG, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_PS_DEC_BIG, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_PS_SLOWER, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_PS_FASTER, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_PS_NUDGE_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_PS_NUDGE_LEFTOFF, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, + { ACTION_PS_NUDGE_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, + + { ACTION_PS_RESET, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_PS_TOGGLE_MODE, BUTTON_USER, BUTTON_NONE }, + { ACTION_PS_EXIT, BUTTON_MENU|BUTTON_REL, BUTTON_NONE }, + { ACTION_PS_EXIT, BUTTON_BACK|BUTTON_REL, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_pitchcreen */ + +static const struct button_mapping button_context_keyboard[] = { + + { ACTION_KBD_UP, BUTTON_UP, BUTTON_NONE }, + { ACTION_KBD_UP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE }, + { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, + + { ACTION_KBD_SELECT, BUTTON_SELECT, BUTTON_NONE }, + { ACTION_KBD_ABORT, BUTTON_BACK|BUTTON_REL, BUTTON_BACK }, + { ACTION_KBD_DONE, BUTTON_MENU|BUTTON_REL, BUTTON_MENU }, + { ACTION_KBD_BACKSPACE, BUTTON_USER, BUTTON_NONE }, + { ACTION_KBD_PAGE_FLIP, BUTTON_POWER, BUTTON_NONE }, + + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) +}; /* button_context_keyboard */ + +static const struct button_mapping button_context_radio[] = { + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS) +}; /* button_context_radio */ + +const struct button_mapping* get_context_mapping(int context) +{ + switch (context) + { + case CONTEXT_STD: + return button_context_standard; + case CONTEXT_WPS: + return button_context_wps; + + case CONTEXT_LIST: + return button_context_list; + case CONTEXT_MAINMENU: + case CONTEXT_TREE: + return button_context_tree; + + case CONTEXT_SETTINGS: + return button_context_settings; + + case CONTEXT_SETTINGS_COLOURCHOOSER: + return button_context_colorchooser; + case CONTEXT_SETTINGS_EQ: + return button_context_eq; + + case CONTEXT_SETTINGS_TIME: + return button_context_time; + + case CONTEXT_YESNOSCREEN: + return button_context_yesno; + case CONTEXT_FM: + return button_context_radio; + case CONTEXT_BOOKMARKSCREEN: + return button_context_bmark; + case CONTEXT_QUICKSCREEN: + return button_context_quickscreen; + case CONTEXT_PITCHSCREEN: + return button_context_pitchscreen; + case CONTEXT_KEYBOARD: + return button_context_keyboard; + } + return button_context_standard; +} diff --git a/apps/plugin.h b/apps/plugin.h index 4a62697724..e778f51f62 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -121,6 +121,8 @@ void* plugin_get_buffer(size_t *buffer_size); /* on some platforms strcmp() seems to be a tricky define which * breaks if we write down strcmp's prototype */ #undef strcmp +#undef strncmp +#undef strchr #ifdef PLUGIN diff --git a/apps/plugins/SOURCES.app_build b/apps/plugins/SOURCES.app_build index ddac2b9ba8..e374062536 100644 --- a/apps/plugins/SOURCES.app_build +++ b/apps/plugins/SOURCES.app_build @@ -1,3 +1,7 @@ +#ifndef HAVE_TOUCHSCREEN +/* In devices running RockBox as an application, but having a keypad */ +#include "SOURCES" +#else /* plugins common to all models */ credits.c properties.c @@ -39,3 +43,5 @@ test_sampr.c #endif test_viewports.c #endif /* HAVE_TEST_PLUGINS */ + +#endif /* HAVE_TOUCHSCREEN */ diff --git a/apps/plugins/SUBDIRS b/apps/plugins/SUBDIRS index c497c49b14..d2feb721d4 100644 --- a/apps/plugins/SUBDIRS +++ b/apps/plugins/SUBDIRS @@ -73,7 +73,7 @@ mikmod #if defined(IRIVER_H300_SERIES) || defined(IRIVER_H100_SERIES) || \ (CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_E200_PAD) || \ (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ - (CONFIG_KEYPAD == IPOD_1G2G_PAD) + (CONFIG_KEYPAD == IPOD_1G2G_PAD || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) /* PDBox is confirmed to run on these player models. */ pdbox #endif diff --git a/apps/plugins/SUBDIRS.app_build b/apps/plugins/SUBDIRS.app_build index dbf4382b62..23b840fd87 100644 --- a/apps/plugins/SUBDIRS.app_build +++ b/apps/plugins/SUBDIRS.app_build @@ -1,4 +1,11 @@ -/* For all targets with a bitmap display */ +#ifndef HAVE_TOUCHSCREEN +/* This is for devices having a keypad, running RockBox as an application */ +#include "SUBDIRS" + +#else +/* For all targets with a bitmap display and a touchscreen + * In fact, most of the plugins aren't supposed to be used on a touch(mouse) device + */ #ifdef HAVE_LCD_BITMAP #ifdef HAVE_TAGCACHE @@ -15,3 +22,4 @@ mikmod #endif #endif /* CONFIG_CODEC == SWCODEC */ +#endif /* HAVE_TOUCHSCREEN */ \ No newline at end of file diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index a16302e8b0..be509cffcb 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -125,7 +125,8 @@ #define BATTERY_ON_TXT "SELECT - start" #define BATTERY_OFF_TXT "POWER" -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \ + || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define BATTERY_ON BUTTON_SELECT #define BATTERY_OFF BUTTON_BACK diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c index 0c35306cfc..ab4da37b0a 100644 --- a/apps/plugins/blackjack.c +++ b/apps/plugins/blackjack.c @@ -466,6 +466,22 @@ enum { #define BJACK_RIGHT BUTTON_RIGHT #define BJACK_LEFT BUTTON_LEFT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define BJACK_SELECT_NAME "SELECT" +#define BJACK_STAY_NAME "MENU" +#define BJACK_QUIT_NAME "BACK" +#define BJACK_DOUBLE_NAME "USER" +#define BJACK_SELECT BUTTON_SELECT +#define BJACK_QUIT BUTTON_BACK +#define BJACK_MAX (BUTTON_LEFT|BUTTON_UP) +#define BJACK_MIN (BUTTON_RIGHT|BUTTON_DOWN) +#define BJACK_STAY BUTTON_MENU +#define BJACK_DOUBLEDOWN BUTTON_USER +#define BJACK_UP BUTTON_UP +#define BJACK_DOWN BUTTON_DOWN +#define BJACK_RIGHT BUTTON_RIGHT +#define BJACK_LEFT BUTTON_LEFT + #else #error No keymap defined! #endif diff --git a/apps/plugins/bounce.c b/apps/plugins/bounce.c index 6880e269e2..5bd81b7fed 100644 --- a/apps/plugins/bounce.c +++ b/apps/plugins/bounce.c @@ -127,7 +127,8 @@ #define BOUNCE_QUIT BUTTON_POWER #define BOUNCE_MODE BUTTON_PLAY -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) \ + || (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define BOUNCE_LEFT BUTTON_LEFT #define BOUNCE_RIGHT BUTTON_RIGHT #define BOUNCE_UP BUTTON_UP diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c index c362ffe702..dd3903eb26 100644 --- a/apps/plugins/brickmania.c +++ b/apps/plugins/brickmania.c @@ -158,7 +158,8 @@ CONFIG_KEYPAD == SANSA_CONNECT_PAD #define UP BUTTON_SCROLL_UP #define DOWN BUTTON_SCROLL_DOWN -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \ + || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define QUIT BUTTON_BACK #define LEFT BUTTON_LEFT #define RIGHT BUTTON_RIGHT diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c index 8288f34c28..77c7a5588d 100644 --- a/apps/plugins/calculator.c +++ b/apps/plugins/calculator.c @@ -431,6 +431,17 @@ F3: equal to "=" #define CALCULATOR_CALC BUTTON_NEXT #define CALCULATOR_CLEAR BUTTON_PREV +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) + +#define CALCULATOR_LEFT BUTTON_LEFT +#define CALCULATOR_RIGHT BUTTON_RIGHT +#define CALCULATOR_UP BUTTON_UP +#define CALCULATOR_DOWN BUTTON_DOWN +#define CALCULATOR_QUIT BUTTON_BACK +#define CALCULATOR_INPUT BUTTON_SELECT +#define CALCULATOR_CALC BUTTON_MENU +#define CALCULATOR_CLEAR BUTTON_USER + #else #error No keymap defined! #endif diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c index d8d8f1ad12..d498b97ffb 100644 --- a/apps/plugins/calendar.c +++ b/apps/plugins/calendar.c @@ -308,6 +308,16 @@ #define CALENDAR_NEXT_MONTH BUTTON_NEXT #define CALENDAR_PREV_MONTH BUTTON_PREV +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define CALENDAR_QUIT BUTTON_BACK +#define CALENDAR_SELECT BUTTON_SELECT +#define CALENDAR_NEXT_WEEK BUTTON_DOWN +#define CALENDAR_PREV_WEEK BUTTON_UP +#define CALENDAR_NEXT_DAY BUTTON_RIGHT +#define CALENDAR_PREV_DAY BUTTON_LEFT +#define CALENDAR_NEXT_MONTH BUTTON_POWER +#define CALENDAR_PREV_MONTH BUTTON_USER + #else #error "No keypad setting." #endif diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h index 1627426cef..765e52ec8c 100644 --- a/apps/plugins/chessbox/chessbox_pgn.h +++ b/apps/plugins/chessbox/chessbox_pgn.h @@ -422,6 +422,16 @@ #define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT) #define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT) +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define CB_SELECT BUTTON_SELECT +#define CB_UP BUTTON_UP +#define CB_DOWN BUTTON_DOWN +#define CB_LEFT BUTTON_LEFT +#define CB_RIGHT BUTTON_RIGHT +#define CB_PLAY BUTTON_USER +#define CB_LEVEL BUTTON_BACK +#define CB_MENU BUTTON_MENU + #else #error No keymap defined! #endif diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c index dca5c4040e..94f069d0a0 100644 --- a/apps/plugins/chessclock.c +++ b/apps/plugins/chessclock.c @@ -326,6 +326,16 @@ #define CHC_SETTINGS_OK BUTTON_SELECT #define CHC_SETTINGS_CANCEL BUTTON_LEFT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define CHC_QUIT BUTTON_BACK +#define CHC_STARTSTOP BUTTON_SELECT +#define CHC_RESET BUTTON_USER +#define CHC_MENU BUTTON_MENU +#define CHC_SETTINGS_INC BUTTON_UP +#define CHC_SETTINGS_DEC BUTTON_DOWN +#define CHC_SETTINGS_OK BUTTON_SELECT +#define CHC_SETTINGS_CANCEL BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/chip8.c b/apps/plugins/chip8.c index 97d8351fe9..470a8e4c89 100644 --- a/apps/plugins/chip8.c +++ b/apps/plugins/chip8.c @@ -1193,6 +1193,18 @@ CONFIG_KEYPAD == MROBE500_PAD #define CHIP8_KEY8 BUTTON_VOL_DOWN #define CHIP8_KEY9 BUTTON_VOL_UP +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define CHIP8_OFF (BUTTON_BACK|BUTTON_REPEAT) +#define CHIP8_KEY1 BUTTON_MENU +#define CHIP8_KEY2 BUTTON_UP +#define CHIP8_KEY3 BUTTON_DOWN +#define CHIP8_KEY4 BUTTON_LEFT +#define CHIP8_KEY5 BUTTON_SELECT +#define CHIP8_KEY6 BUTTON_RIGHT +#define CHIP8_KEY7 BUTTON_BACK +#define CHIP8_KEY8 BUTTON_POWER +#define CHIP8_KEY9 BUTTON_USER + #else #error No keymap defined! #endif diff --git a/apps/plugins/chopper.c b/apps/plugins/chopper.c index 71ea8f835f..d819da421b 100644 --- a/apps/plugins/chopper.c +++ b/apps/plugins/chopper.c @@ -97,7 +97,8 @@ Still To do: #define ACTION2 BUTTON_MENU #define ACTIONTEXT "UP" -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD \ + || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define QUIT BUTTON_BACK #define ACTION BUTTON_SELECT #define ACTION2 BUTTON_MENU diff --git a/apps/plugins/clix.c b/apps/plugins/clix.c index 378e9813e6..06fe0d84e0 100644 --- a/apps/plugins/clix.c +++ b/apps/plugins/clix.c @@ -83,7 +83,8 @@ #define CLIX_BUTTON_UP BUTTON_UP #define CLIX_BUTTON_DOWN BUTTON_DOWN -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define CLIX_BUTTON_QUIT BUTTON_BACK #define CLIX_BUTTON_LEFT BUTTON_LEFT #define CLIX_BUTTON_RIGHT BUTTON_RIGHT diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c index 7e97eaf569..cecb10e1f2 100644 --- a/apps/plugins/cube.c +++ b/apps/plugins/cube.c @@ -329,6 +329,16 @@ #define CUBE_PAUSE BUTTON_DOWN #define CUBE_HIGHSPEED BUTTON_LEFT +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define CUBE_QUIT BUTTON_BACK +#define CUBE_NEXT BUTTON_RIGHT +#define CUBE_PREV BUTTON_LEFT +#define CUBE_INC BUTTON_UP +#define CUBE_DEC BUTTON_DOWN +#define CUBE_MODE BUTTON_MENU +#define CUBE_PAUSE BUTTON_USER +#define CUBE_HIGHSPEED BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c index d12799cac4..9009acc67f 100644 --- a/apps/plugins/doom/i_video.c +++ b/apps/plugins/doom/i_video.c @@ -424,6 +424,17 @@ void I_ShutdownGraphics(void) #define DOOMBUTTON_ENTER BUTTON_NEXT #define DOOMBUTTON_WEAPON BUTTON_PREV +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define DOOMBUTTON_UP BUTTON_UP +#define DOOMBUTTON_DOWN BUTTON_DOWN +#define DOOMBUTTON_LEFT BUTTON_LEFT +#define DOOMBUTTON_RIGHT BUTTON_RIGHT +#define DOOMBUTTON_SHOOT BUTTON_SELECT +#define DOOMBUTTON_OPEN BUTTON_MENU +#define DOOMBUTTON_ESC BUTTON_BACK +#define DOOMBUTTON_ENTER BUTTON_POWER +#define DOOMBUTTON_WEAPON BUTTON_USER + #else #error Keymap not defined! #endif diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c index 89205503e7..b2ef8d8e33 100644 --- a/apps/plugins/fft/fft.c +++ b/apps/plugins/fft/fft.c @@ -257,6 +257,15 @@ GREY_INFO_STRUCT # define FFT_FREQ_SCALE BUTTON_DOWN # define FFT_QUIT BUTTON_POWER +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +# define FFT_PREV_GRAPH BUTTON_LEFT +# define FFT_NEXT_GRAPH BUTTON_RIGHT +# define FFT_ORIENTATION BUTTON_USER +# define FFT_WINDOW BUTTON_MENU +# define FFT_AMP_SCALE BUTTON_SELECT +# define FFT_FREQ_SCALE BUTTON_DOWN +# define FFT_QUIT BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/fireworks.c b/apps/plugins/fireworks.c index e3a391035a..52b11b7079 100644 --- a/apps/plugins/fireworks.c +++ b/apps/plugins/fireworks.c @@ -63,7 +63,8 @@ #elif (CONFIG_KEYPAD == GIGABEAT_PAD) || \ (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ - (CONFIG_KEYPAD == MROBE100_PAD) + (CONFIG_KEYPAD == MROBE100_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define BTN_MENU BUTTON_MENU #define BTN_FIRE BUTTON_SELECT diff --git a/apps/plugins/flipit.c b/apps/plugins/flipit.c index ffc691c720..da5a9e8c6b 100644 --- a/apps/plugins/flipit.c +++ b/apps/plugins/flipit.c @@ -380,6 +380,18 @@ #define FLIPIT_STEP_BY_STEP BUTTON_NEXT #define FLIPIT_TOGGLE BUTTON_SELECT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD + +#define FLIPIT_LEFT BUTTON_LEFT +#define FLIPIT_RIGHT BUTTON_RIGHT +#define FLIPIT_UP BUTTON_UP +#define FLIPIT_DOWN BUTTON_DOWN +#define FLIPIT_QUIT BUTTON_BACK +#define FLIPIT_SHUFFLE BUTTON_MENU +#define FLIPIT_SOLVE BUTTON_USER +#define FLIPIT_STEP_BY_STEP BUTTON_POWER +#define FLIPIT_TOGGLE BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h index 76f3229399..0d1aff3078 100644 --- a/apps/plugins/fractals/fractal.h +++ b/apps/plugins/fractals/fractal.h @@ -378,6 +378,18 @@ #define FRACTAL_PRECISION_DEC BUTTON_VOL_DOWN #define FRACTAL_RESET BUTTON_PREV +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define FRACTAL_QUIT BUTTON_BACK +#define FRACTAL_UP BUTTON_UP +#define FRACTAL_DOWN BUTTON_DOWN +#define FRACTAL_LEFT BUTTON_LEFT +#define FRACTAL_RIGHT BUTTON_RIGHT +#define FRACTAL_ZOOM_IN (BUTTON_MENU|BUTTON_REL) +#define FRACTAL_ZOOM_OUT (BUTTON_USER|BUTTON_REL) +#define FRACTAL_PRECISION_INC (BUTTON_MENU|BUTTON_REPEAT) +#define FRACTAL_PRECISION_DEC (BUTTON_USER|BUTTON_REPEAT) +#define FRACTAL_RESET BUTTON_POWER + #else #error No keymap defined! #endif diff --git a/apps/plugins/goban/goban.h b/apps/plugins/goban/goban.h index d03bc82474..20940d74f0 100644 --- a/apps/plugins/goban/goban.h +++ b/apps/plugins/goban/goban.h @@ -364,6 +364,16 @@ #define GBN_BUTTON_PLAY BUTTON_SELECT #define GBN_BUTTON_MENU BUTTON_POWER +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define GBN_BUTTON_UP BUTTON_UP +#define GBN_BUTTON_DOWN BUTTON_DOWN +#define GBN_BUTTON_LEFT BUTTON_LEFT +#define GBN_BUTTON_RIGHT BUTTON_RIGHT +#define GBN_BUTTON_RETREAT BUTTON_BACK +#define GBN_BUTTON_ADVANCE BUTTON_USER +#define GBN_BUTTON_PLAY BUTTON_SELECT +#define GBN_BUTTON_MENU BUTTON_MENU + #else #error Unsupported keypad #endif diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h index 9f345d83f3..10d239922e 100644 --- a/apps/plugins/imageviewer/imageviewer_button.h +++ b/apps/plugins/imageviewer/imageviewer_button.h @@ -379,6 +379,18 @@ #define IMGVIEW_MENU BUTTON_POWER #define IMGVIEW_SLIDE_SHOW BUTTON_NEXT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define IMGVIEW_ZOOM_IN BUTTON_POWER +#define IMGVIEW_ZOOM_OUT BUTTON_USER +#define IMGVIEW_UP BUTTON_UP +#define IMGVIEW_DOWN BUTTON_DOWN +#define IMGVIEW_LEFT BUTTON_LEFT +#define IMGVIEW_RIGHT BUTTON_RIGHT +#define IMGVIEW_NEXT BUTTON_SELECT +#define IMGVIEW_PREVIOUS 0xFFFFFFA //not used +#define IMGVIEW_MENU BUTTON_MENU +#define IMGVIEW_QUIT BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c index 96e04a976f..c52208d3c6 100644 --- a/apps/plugins/invadrox.c +++ b/apps/plugins/invadrox.c @@ -122,7 +122,8 @@ #define RIGHT BUTTON_RIGHT #define FIRE BUTTON_SELECT -#elif CONFIG_KEYPAD == GIGABEAT_PAD +#elif CONFIG_KEYPAD == GIGABEAT_PAD \ + || CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define QUIT BUTTON_POWER #define LEFT BUTTON_LEFT diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c index 4d5a5b6ce9..7d80a536dd 100644 --- a/apps/plugins/jewels.c +++ b/apps/plugins/jewels.c @@ -172,7 +172,8 @@ CONFIG_KEYPAD == SANSA_M200_PAD #define HK_SELECT "PLAY" #define HK_CANCEL "POWER" -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define JEWELS_UP BUTTON_UP #define JEWELS_DOWN BUTTON_DOWN #define JEWELS_LEFT BUTTON_LEFT diff --git a/apps/plugins/lamp.c b/apps/plugins/lamp.c index d9ad70b946..583e2753fa 100644 --- a/apps/plugins/lamp.c +++ b/apps/plugins/lamp.c @@ -57,7 +57,8 @@ # define LAMP_UP BUTTON_UP # define LAMP_DOWN BUTTON_DOWN -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) # define LAMP_LEFT BUTTON_LEFT # define LAMP_RIGHT BUTTON_RIGHT # define LAMP_UP BUTTON_UP diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c index 0a2f12da50..44a2cd8c03 100644 --- a/apps/plugins/lib/pluginlib_actions.c +++ b/apps/plugins/lib/pluginlib_actions.c @@ -116,7 +116,8 @@ const struct button_mapping pla_main_ctx[] = || (CONFIG_KEYPAD == SANSA_FUZE_PAD) \ || (CONFIG_KEYPAD == SAMSUNG_YH_PAD) \ || (CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD) \ - || (CONFIG_KEYPAD == SANSA_CONNECT_PAD)) + || (CONFIG_KEYPAD == SANSA_CONNECT_PAD) \ + || (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)) { PLA_UP, BUTTON_UP, BUTTON_NONE }, { PLA_DOWN, BUTTON_DOWN, BUTTON_NONE }, { PLA_LEFT, BUTTON_LEFT, BUTTON_NONE }, @@ -278,7 +279,8 @@ const struct button_mapping pla_main_ctx[] = {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE}, {PLA_SELECT_REL, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, {PLA_SELECT_REPEAT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_NONE}, -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) \ + || (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) {PLA_CANCEL, BUTTON_BACK, BUTTON_NONE}, {PLA_EXIT, BUTTON_MENU, BUTTON_NONE}, {PLA_SELECT, BUTTON_SELECT, BUTTON_NONE}, diff --git a/apps/plugins/lib/simple_viewer.c b/apps/plugins/lib/simple_viewer.c index 16cbcb35de..06cc9c1a71 100644 --- a/apps/plugins/lib/simple_viewer.c +++ b/apps/plugins/lib/simple_viewer.c @@ -25,6 +25,7 @@ #include "simple_viewer.h" #include + struct view_info { #ifdef HAVE_LCD_BITMAP struct font* pf; diff --git a/apps/plugins/logo.c b/apps/plugins/logo.c index d651c2f634..be163f566e 100644 --- a/apps/plugins/logo.c +++ b/apps/plugins/logo.c @@ -123,7 +123,8 @@ const unsigned char rockbox16x7[] = { #elif CONFIG_KEYPAD == MROBE500_PAD #define LP_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define LP_QUIT BUTTON_BACK #define LP_DEC_X BUTTON_LEFT #define LP_INC_X BUTTON_RIGHT diff --git a/apps/plugins/lua/strcspn.c b/apps/plugins/lua/strcspn.c index 7af6f693eb..0a19eaebf2 100644 --- a/apps/plugins/lua/strcspn.c +++ b/apps/plugins/lua/strcspn.c @@ -1,5 +1,6 @@ #include "rocklibc.h" +#undef strcspn size_t strcspn(const char *s, const char *reject) { size_t l=0; diff --git a/apps/plugins/lua/strpbrk.c b/apps/plugins/lua/strpbrk.c index f416f391ae..1e0491f779 100644 --- a/apps/plugins/lua/strpbrk.c +++ b/apps/plugins/lua/strpbrk.c @@ -1,5 +1,6 @@ #include "rocklibc.h" +#undef strpbrk char *strpbrk(const char *s, const char *accept) { register int i,l=strlen(accept); for (; *s; s++) diff --git a/apps/plugins/matrix.c b/apps/plugins/matrix.c index 1a1008073c..10b8ce578d 100644 --- a/apps/plugins/matrix.c +++ b/apps/plugins/matrix.c @@ -101,7 +101,8 @@ #define MATRIX_SLEEP_LESS BUTTON_DOWN #define MATRIX_PAUSE BUTTON_SELECT -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define MATRIX_EXIT BUTTON_BACK #define MATRIX_SLEEP_MORE BUTTON_UP #define MATRIX_SLEEP_LESS BUTTON_DOWN diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index 1b5d18465b..ace7290a12 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c @@ -233,6 +233,14 @@ #define BTN_DOWN BUTTON_DOWN #define BTN_PLAY BUTTON_SELECT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define BTN_QUIT BUTTON_BACK +#define BTN_RIGHT BUTTON_RIGHT +#define BTN_LEFT BUTTON_LEFT +#define BTN_UP BUTTON_UP +#define BTN_DOWN BUTTON_DOWN +#define BTN_PLAY BUTTON_USER + #else #error No keymap defined! #endif diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c index ad67b1dd67..e0da928b02 100644 --- a/apps/plugins/minesweeper.c +++ b/apps/plugins/minesweeper.c @@ -311,6 +311,16 @@ CONFIG_KEYPAD == MROBE500_PAD # define MINESWP_DISCOVER BUTTON_SELECT # define MINESWP_INFO BUTTON_PREV +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +# define MINESWP_LEFT BUTTON_LEFT +# define MINESWP_RIGHT BUTTON_RIGHT +# define MINESWP_UP BUTTON_UP +# define MINESWP_DOWN BUTTON_DOWN +# define MINESWP_QUIT BUTTON_BACK +# define MINESWP_TOGGLE BUTTON_USER +# define MINESWP_DISCOVER BUTTON_SELECT +# define MINESWP_INFO BUTTON_MENU + #else #error No keymap defined! #endif diff --git a/apps/plugins/mosaique.c b/apps/plugins/mosaique.c index ec41c8c02b..87e664e102 100644 --- a/apps/plugins/mosaique.c +++ b/apps/plugins/mosaique.c @@ -113,7 +113,8 @@ #elif CONFIG_KEYPAD == MROBE500_PAD #define MOSAIQUE_QUIT BUTTON_POWER -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define MOSAIQUE_QUIT BUTTON_BACK #define MOSAIQUE_SPEED BUTTON_SELECT #define MOSAIQUE_RESTART BUTTON_MENU diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c index a70e316f06..567ec5dbc8 100644 --- a/apps/plugins/mp3_encoder.c +++ b/apps/plugins/mp3_encoder.c @@ -2394,7 +2394,8 @@ static void get_mp3_filename(const char *wav_name) #define MP3ENC_DONE BUTTON_POWER #define MP3ENC_SELECT BUTTON_SELECT -#elif CONFIG_KEYPAD == GIGABEAT_PAD +#elif CONFIG_KEYPAD == GIGABEAT_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define MP3ENC_PREV BUTTON_UP #define MP3ENC_NEXT BUTTON_DOWN #define MP3ENC_DONE BUTTON_POWER diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c index 90b547893e..e9b1c01680 100644 --- a/apps/plugins/mpegplayer/mpeg_settings.c +++ b/apps/plugins/mpegplayer/mpeg_settings.c @@ -248,6 +248,14 @@ struct mpeg_settings settings; #define MPEG_START_TIME_DOWN BUTTON_DOWN #define MPEG_START_TIME_EXIT BUTTON_POWER +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define MPEG_START_TIME_SELECT BUTTON_SELECT +#define MPEG_START_TIME_LEFT BUTTON_LEFT +#define MPEG_START_TIME_RIGHT BUTTON_RIGHT +#define MPEG_START_TIME_UP BUTTON_UP +#define MPEG_START_TIME_DOWN BUTTON_DOWN +#define MPEG_START_TIME_EXIT BUTTON_BACK + #else #error No keymap defined! #endif diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c index e3d9865e12..f73e5f2090 100644 --- a/apps/plugins/mpegplayer/mpegplayer.c +++ b/apps/plugins/mpegplayer/mpegplayer.c @@ -362,6 +362,15 @@ CONFIG_KEYPAD == SANSA_M200_PAD #define MPEG_RW BUTTON_LEFT #define MPEG_FF BUTTON_RIGHT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define MPEG_MENU BUTTON_MENU +#define MPEG_PAUSE BUTTON_SELECT +#define MPEG_STOP BUTTON_POWER +#define MPEG_VOLDOWN BUTTON_DOWN +#define MPEG_VOLUP BUTTON_UP +#define MPEG_RW BUTTON_LEFT +#define MPEG_FF BUTTON_RIGHT + #else #error No keymap defined! #endif diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c index 4469a92e12..0b1687da5c 100644 --- a/apps/plugins/oscilloscope.c +++ b/apps/plugins/oscilloscope.c @@ -342,6 +342,17 @@ #define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP #define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define OSCILLOSCOPE_QUIT BUTTON_BACK +#define OSCILLOSCOPE_DRAWMODE BUTTON_USER +#define OSCILLOSCOPE_ADVMODE BUTTON_MENU +#define OSCILLOSCOPE_ORIENTATION BUTTON_POWER +#define OSCILLOSCOPE_PAUSE BUTTON_SELECT +#define OSCILLOSCOPE_SPEED_UP BUTTON_RIGHT +#define OSCILLOSCOPE_SPEED_DOWN BUTTON_LEFT +#define OSCILLOSCOPE_VOL_UP BUTTON_UP +#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN + #else #error No keymap defined! #endif diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h index 3c906ac0aa..0183b0c3f6 100644 --- a/apps/plugins/pacbox/pacbox.h +++ b/apps/plugins/pacbox/pacbox.h @@ -265,6 +265,17 @@ #define PACMAN_COIN BUTTON_VOL_DOWN #define PACMAN_MENU BUTTON_POWER +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD + +#define PACMAN_UP BUTTON_UP +#define PACMAN_DOWN BUTTON_DOWN +#define PACMAN_LEFT BUTTON_LEFT +#define PACMAN_RIGHT BUTTON_RIGHT +#define PACMAN_1UP BUTTON_SELECT +#define PACMAN_2UP BUTTON_POWER +#define PACMAN_COIN BUTTON_USER +#define PACMAN_MENU BUTTON_MENU + #else #error Keymap not defined! diff --git a/apps/plugins/pdbox/pdbox.h b/apps/plugins/pdbox/pdbox.h index 56ad568a3b..b53e15f94e 100644 --- a/apps/plugins/pdbox/pdbox.h +++ b/apps/plugins/pdbox/pdbox.h @@ -89,7 +89,9 @@ float rb_atan(float); float rb_atan2(float, float); float rb_sinh(float); float rb_tan(float); -#ifndef SIMULATOR +//#ifndef SIMULATOR +/*FIXME: is it a correct replacement??? */ +#if !(CONFIG_PLATFORM & PLATFORM_HOSTED) typedef struct { int quot; @@ -163,9 +165,12 @@ void pd_init(void); #define atoi rb->atoi #define write rb->write +#undef strncat #define strncat rb_strncat -#ifndef SIMULATOR +//#ifndef SIMULATOR +/*FIXME: is it a correct replacement??? */ +#if !(CONFIG_PLATFORM & PLATFORM_HOSTED) #define floor rb_floor #define atof rb_atof #define atol rb_atol @@ -186,6 +191,7 @@ void pd_init(void); #endif #define ftoan rb_ftoan +#undef strtok_r #define strtok_r rb->strtok_r #define strstr rb->strcasestr @@ -282,6 +288,15 @@ enum pd_key_id #define PDPOD_WHEELLEFT (BUTTON_SCROLL_BACK) #define PDPOD_WHEELRIGHT (BUTTON_SCROLL_FWD) #define PDPOD_ACTION (BUTTON_SELECT) +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) + #define PDPOD_QUIT BUTTON_BACK + #define PDPOD_PLAY BUTTON_USER + #define PDPOD_PREVIOUS BUTTON_LEFT + #define PDPOD_NEXT BUTTON_RIGHT + #define PDPOD_MENU BUTTON_MENU + #define PDPOD_WHEELLEFT BUTTON_UP + #define PDPOD_WHEELRIGHT BUTTON_DOWN + #define PDPOD_ACTION BUTTON_SELECT #else #warning "No keys defined for this architecture!" #endif diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c index 3eb6008f76..479f7c5ec2 100644 --- a/apps/plugins/pegbox.c +++ b/apps/plugins/pegbox.c @@ -510,6 +510,24 @@ CONFIG_KEYPAD == MROBE500_PAD #define LVL_DOWN_TEXT "PREV" #define SELECT_TEXT "SELECT" +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define PEGBOX_SELECT BUTTON_SELECT +#define PEGBOX_QUIT BUTTON_BACK +#define PEGBOX_RESTART BUTTON_MENU +#define PEGBOX_LVL_UP BUTTON_USER +#define PEGBOX_LVL_DOWN BUTTON_POWER +#define PEGBOX_UP BUTTON_UP +#define PEGBOX_DOWN BUTTON_DOWN +#define PEGBOX_RIGHT BUTTON_RIGHT +#define PEGBOX_LEFT BUTTON_LEFT + +#define SAVE_TEXT "PLAYPAUSE" +#define QUIT_TEXT "POWER" +#define RESTART_TEXT "BACK" +#define LVL_UP_TEXT "Vol+" +#define LVL_DOWN_TEXT "Vol-" +#define SELECT_TEXT "SELECT" + #else #error Unsupported keymap! #endif diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c index d3875f39e4..430b688f1f 100644 --- a/apps/plugins/pong.c +++ b/apps/plugins/pong.c @@ -244,6 +244,14 @@ CONFIG_KEYPAD == MROBE500_PAD #define PONG_RIGHT_UP BUTTON_UP #define PONG_RIGHT_DOWN BUTTON_RIGHT +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define PONG_QUIT BUTTON_BACK +#define PONG_PAUSE BUTTON_SELECT +#define PONG_LEFT_UP BUTTON_UP +#define PONG_LEFT_DOWN BUTTON_DOWN +#define PONG_RIGHT_UP BUTTON_MENU +#define PONG_RIGHT_DOWN BUTTON_POWER + #else #error No keymap defined! #endif diff --git a/apps/plugins/reversi/reversi-gui.h b/apps/plugins/reversi/reversi-gui.h index a36efe51cb..c0d6183c2f 100644 --- a/apps/plugins/reversi/reversi-gui.h +++ b/apps/plugins/reversi/reversi-gui.h @@ -252,6 +252,15 @@ #define REVERSI_BUTTON_MAKE_MOVE BUTTON_PLAYPAUSE #define REVERSI_BUTTON_MENU BUTTON_BACK +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define REVERSI_BUTTON_QUIT BUTTON_BACK +#define REVERSI_BUTTON_UP BUTTON_UP +#define REVERSI_BUTTON_DOWN BUTTON_DOWN +#define REVERSI_BUTTON_LEFT BUTTON_LEFT +#define REVERSI_BUTTON_RIGHT BUTTON_RIGHT +#define REVERSI_BUTTON_MAKE_MOVE BUTTON_SELECT +#define REVERSI_BUTTON_MENU BUTTON_MENU + #else #error No keymap defined! #endif diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c index 674b14ed83..c23c6b11cb 100644 --- a/apps/plugins/rockblox.c +++ b/apps/plugins/rockblox.c @@ -379,6 +379,18 @@ #define ROCKBLOX_DROP BUTTON_SELECT #define ROCKBLOX_RESTART BUTTON_VOL_DOWN +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD + +#define ROCKBLOX_OFF BUTTON_BACK +#define ROCKBLOX_ROTATE_CCW BUTTON_POWER +#define ROCKBLOX_ROTATE_CW BUTTON_MENU +#define ROCKBLOX_ROTATE BUTTON_UP +#define ROCKBLOX_DOWN BUTTON_DOWN +#define ROCKBLOX_LEFT BUTTON_LEFT +#define ROCKBLOX_RIGHT BUTTON_RIGHT +#define ROCKBLOX_DROP BUTTON_SELECT +#define ROCKBLOX_RESTART BUTTON_USER + #else #error No keymap defined! #endif diff --git a/apps/plugins/rockblox1d.c b/apps/plugins/rockblox1d.c index 49219c2eba..5b6e812abf 100644 --- a/apps/plugins/rockblox1d.c +++ b/apps/plugins/rockblox1d.c @@ -69,7 +69,8 @@ #define ONEDROCKBLOX_DOWN BUTTON_PLAY #define ONEDROCKBLOX_QUIT BUTTON_POWER -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define ONEDROCKBLOX_DOWN BUTTON_SELECT #define ONEDROCKBLOX_QUIT BUTTON_BACK diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c index 37f0566b21..bc73abee92 100644 --- a/apps/plugins/rockboy/rockboy.c +++ b/apps/plugins/rockboy/rockboy.c @@ -342,6 +342,18 @@ static void setoptions (void) options.SELECT = BUTTON_NEXT; options.MENU = BUTTON_SELECT; +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD + options.UP = BUTTON_UP; + options.DOWN = BUTTON_DOWN; + options.LEFT = BUTTON_LEFT; + options.RIGHT = BUTTON_RIGHT; + + options.A = BUTTON_SELECT; + options.B = BUTTON_BACK; + options.START = BUTTON_POWER; + options.SELECT = BUTTON_USER; + options.MENU = BUTTON_MENU; + #else #error No Keymap Defined! #endif diff --git a/apps/plugins/rockboy/rockmacros.h b/apps/plugins/rockboy/rockmacros.h index 724a0fb96d..87e570b55a 100644 --- a/apps/plugins/rockboy/rockmacros.h +++ b/apps/plugins/rockboy/rockmacros.h @@ -23,8 +23,6 @@ #include "plugin.h" -#include "autoconf.h" - #define malloc(a) my_malloc(a) void *my_malloc(size_t size); diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index 7f16bf2763..eeca916d1d 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c @@ -243,6 +243,17 @@ #define ROCKPAINT_LEFT BUTTON_LEFT #define ROCKPAINT_RIGHT BUTTON_RIGHT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define ROCKPAINT_QUIT BUTTON_BACK +#define ROCKPAINT_DRAW BUTTON_SELECT +#define ROCKPAINT_MENU BUTTON_MENU +#define ROCKPAINT_TOOLBAR BUTTON_USER +#define ROCKPAINT_TOOLBAR2 ( BUTTON_USER | BUTTON_REPEAT ) +#define ROCKPAINT_UP BUTTON_UP +#define ROCKPAINT_DOWN BUTTON_DOWN +#define ROCKPAINT_LEFT BUTTON_LEFT +#define ROCKPAINT_RIGHT BUTTON_RIGHT + #else #error "Please define keys for this keypad" #endif diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c index 653099a547..a176f75c91 100644 --- a/apps/plugins/sliding_puzzle.c +++ b/apps/plugins/sliding_puzzle.c @@ -136,7 +136,8 @@ #define PUZZLE_SHUFFLE BUTTON_REW #define PUZZLE_PICTURE BUTTON_PLAY -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define PUZZLE_QUIT BUTTON_BACK #define PUZZLE_LEFT BUTTON_LEFT #define PUZZLE_RIGHT BUTTON_RIGHT @@ -784,7 +785,8 @@ enum plugin_status plugin_start( rb->lcd_putsxy(0, 18, "[OFF] to stop"); rb->lcd_putsxy(0, 28, "[REW] shuffle"); rb->lcd_putsxy(0, 38, "[PLAY] change pic"); -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD rb->lcd_putsxy(0, 18, "[BACK] to stop"); rb->lcd_putsxy(0, 28, "[SELECT] shuffle"); rb->lcd_putsxy(0, 38, "[MENU] change pic"); diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c index 09e72a5fff..a20376742f 100644 --- a/apps/plugins/snake.c +++ b/apps/plugins/snake.c @@ -130,7 +130,8 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left; #define SNAKE_DOWN BUTTON_SCROLL_DOWN #define SNAKE_PLAYPAUSE BUTTON_PLAY -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define SNAKE_QUIT BUTTON_BACK #define SNAKE_LEFT BUTTON_LEFT #define SNAKE_RIGHT BUTTON_RIGHT diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c index 0e7b499271..bd0257d2be 100644 --- a/apps/plugins/snake2.c +++ b/apps/plugins/snake2.c @@ -238,7 +238,8 @@ Head and Tail are stored #define SNAKE2_PLAYPAUSE BUTTON_FF #define SNAKE2_PLAYPAUSE_TEXT "FF" -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define SNAKE2_LEFT BUTTON_LEFT #define SNAKE2_RIGHT BUTTON_RIGHT #define SNAKE2_UP BUTTON_UP diff --git a/apps/plugins/snow.c b/apps/plugins/snow.c index 8a2de39707..6371a697da 100644 --- a/apps/plugins/snow.c +++ b/apps/plugins/snow.c @@ -67,7 +67,8 @@ #define SNOW_QUIT (BUTTON_HOME|BUTTON_REPEAT) #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ -(CONFIG_KEYPAD == CREATIVEZVM_PAD) +(CONFIG_KEYPAD == CREATIVEZVM_PAD) || \ +(CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define SNOW_QUIT BUTTON_BACK #elif (CONFIG_KEYPAD == PHILIPS_HDD1630_PAD) || \ diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c index ddc95290da..942b101d4c 100644 --- a/apps/plugins/sokoban.c +++ b/apps/plugins/sokoban.c @@ -526,6 +526,21 @@ #define BUTTON_SAVE (BUTTON_SELECT|BUTTON_REPEAT) #define BUTTON_SAVE_NAME "SELECT LONG" +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define SOKOBAN_LEFT BUTTON_LEFT +#define SOKOBAN_RIGHT BUTTON_RIGHT +#define SOKOBAN_UP BUTTON_UP +#define SOKOBAN_DOWN BUTTON_DOWN +#define SOKOBAN_MENU BUTTON_MENU +#define SOKOBAN_UNDO BUTTON_BACK +#define SOKOBAN_REDO BUTTON_USER +//#define SOKOBAN_LEVEL_DOWN (BUTTON_POWER|BUTTON_REL) +//#define SOKOBAN_LEVEL_REPEAT (BUTTON_CENTER|BUTTON_REPEAT) +//#define SOKOBAN_LEVEL_UP (BUTTON_MENU|BUTTON_REPEAT) +#define SOKOBAN_PAUSE BUTTON_SELECT +#define BUTTON_SAVE BUTTON_SELECT +#define BUTTON_SAVE_NAME "SELECT" + #else #error No keymap defined! #endif diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c index 91ef346221..a1e8b7694b 100644 --- a/apps/plugins/solitaire.c +++ b/apps/plugins/solitaire.c @@ -544,6 +544,24 @@ CONFIG_KEYPAD == MROBE500_PAD # define HK_CUR2STACK "NEXT" # define HK_REM2STACK "PREV" +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +# define SOL_QUIT BUTTON_BACK +# define SOL_UP BUTTON_UP +# define SOL_DOWN BUTTON_DOWN +# define SOL_LEFT BUTTON_LEFT +# define SOL_RIGHT BUTTON_RIGHT +# define SOL_MOVE_PRE BUTTON_SELECT +# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL) +# define SOL_DRAW BUTTON_MENU +# define SOL_REM2CUR (BUTTON_USER | BUTTON_REPEAT) +# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT) +# define SOL_REM2STACK BUTTON_POWER +# define HK_MOVE "Select" +# define HK_DRAW "Menu" +# define HK_REM2CUR "Long User" +# define HK_CUR2STACK "Long Select.." +# define HK_REM2STACK "Power" + #else #error No keymap defined! #endif diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c index 0c03a3183b..946d97d075 100644 --- a/apps/plugins/spacerocks.c +++ b/apps/plugins/spacerocks.c @@ -278,6 +278,15 @@ #define AST_RIGHT BUTTON_RIGHT #define AST_FIRE BUTTON_SELECT +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define AST_PAUSE BUTTON_MENU +#define AST_QUIT BUTTON_BACK +#define AST_THRUST BUTTON_UP +#define AST_HYPERSPACE BUTTON_DOWN +#define AST_LEFT BUTTON_LEFT +#define AST_RIGHT BUTTON_RIGHT +#define AST_FIRE BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/star.c b/apps/plugins/star.c index 620cddf77e..cf04e02edc 100644 --- a/apps/plugins/star.c +++ b/apps/plugins/star.c @@ -480,6 +480,23 @@ #define STAR_LEVEL_DOWN_NAME "Vol-" #define STAR_LEVEL_REPEAT_NAME "PREV LONG" +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) + +#define STAR_QUIT BUTTON_BACK +#define STAR_LEFT BUTTON_LEFT +#define STAR_RIGHT BUTTON_RIGHT +#define STAR_UP BUTTON_UP +#define STAR_DOWN BUTTON_DOWN +#define STAR_TOGGLE_CONTROL BUTTON_SELECT +#define STAR_LEVEL_UP BUTTON_MENU +#define STAR_LEVEL_DOWN BUTTON_POWER +#define STAR_LEVEL_REPEAT BUTTON_USER +#define STAR_TOGGLE_CONTROL_NAME "Select" +#define STAR_QUIT_NAME "Back" +#define STAR_LEVEL_UP_NAME "Menu" +#define STAR_LEVEL_DOWN_NAME "Power" +#define STAR_LEVEL_REPEAT_NAME "User" + #else #error No keymap defined! #endif diff --git a/apps/plugins/starfield.c b/apps/plugins/starfield.c index e3b5634978..c996da9234 100644 --- a/apps/plugins/starfield.c +++ b/apps/plugins/starfield.c @@ -78,7 +78,8 @@ #define STARFIELD_DECREASE_NB_STARS BUTTON_LEFT #define STARFIELD_TOGGLE_COLOR BUTTON_SELECT -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define STARFIELD_QUIT BUTTON_BACK #define STARFIELD_INCREASE_ZMOVE BUTTON_UP #define STARFIELD_DECREASE_ZMOVE BUTTON_DOWN diff --git a/apps/plugins/stats.c b/apps/plugins/stats.c index c5ff31e2bd..da231b772c 100644 --- a/apps/plugins/stats.c +++ b/apps/plugins/stats.c @@ -72,7 +72,8 @@ static bool cancel; #define STATS_STOP BUTTON_POWER #define STATS_STOP_REMOTE BUTTON_RC_DOWN -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define STATS_STOP BUTTON_BACK #elif CONFIG_KEYPAD == MROBE100_PAD diff --git a/apps/plugins/stopwatch.c b/apps/plugins/stopwatch.c index 94785dc352..fd33bb7c03 100644 --- a/apps/plugins/stopwatch.c +++ b/apps/plugins/stopwatch.c @@ -263,6 +263,14 @@ #define STOPWATCH_SCROLL_UP BUTTON_UP #define STOPWATCH_SCROLL_DOWN BUTTON_DOWN +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define STOPWATCH_QUIT BUTTON_BACK +#define STOPWATCH_START_STOP BUTTON_SELECT +#define STOPWATCH_RESET_TIMER BUTTON_MENU +#define STOPWATCH_LAP_TIMER BUTTON_USER +#define STOPWATCH_SCROLL_UP BUTTON_UP +#define STOPWATCH_SCROLL_DOWN BUTTON_DOWN + #else #error No keymap defined! #endif diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h index 456e4fd9ee..07147185ae 100644 --- a/apps/plugins/sudoku/sudoku.h +++ b/apps/plugins/sudoku/sudoku.h @@ -329,6 +329,16 @@ #define SUDOKU_BUTTON_MENU BUTTON_SELECT #define SUDOKU_BUTTON_POSSIBLE BUTTON_VOL_DOWN +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define SUDOKU_BUTTON_QUIT BUTTON_BACK +#define SUDOKU_BUTTON_UP BUTTON_UP +#define SUDOKU_BUTTON_DOWN BUTTON_DOWN +#define SUDOKU_BUTTON_LEFT BUTTON_LEFT +#define SUDOKU_BUTTON_RIGHT BUTTON_RIGHT +#define SUDOKU_BUTTON_MENU BUTTON_MENU +#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT +#define SUDOKU_BUTTON_POSSIBLE BUTTON_USER + #else #error No keymap defined! #endif diff --git a/apps/plugins/superdom.c b/apps/plugins/superdom.c index b4e25afdb1..135a6ae445 100644 --- a/apps/plugins/superdom.c +++ b/apps/plugins/superdom.c @@ -120,7 +120,8 @@ char buf[255]; #define SUPERDOM_RIGHT BUTTON_RIGHT #define SUPERDOM_CANCEL (BUTTON_HOME|BUTTON_REPEAT) -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define SUPERDOM_OK BUTTON_SELECT #define SUPERDOM_UP BUTTON_UP #define SUPERDOM_DOWN BUTTON_DOWN diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index 6e1b3b6f9e..849b40de42 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c @@ -39,6 +39,8 @@ #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_REPEAT) #elif CONFIG_KEYPAD == RK27XX_GENERIC_PAD #define TESTCODEC_EXITBUTTON (BUTTON_M | BUTTON_REPEAT) +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define TESTCODEC_EXITBUTTON BUTTON_BACK #elif defined(HAVE_TOUCHSCREEN) #define TESTCODEC_EXITBUTTON BUTTON_TOPLEFT #else diff --git a/apps/plugins/test_fps.c b/apps/plugins/test_fps.c index da4684f60a..4514aa61bb 100644 --- a/apps/plugins/test_fps.c +++ b/apps/plugins/test_fps.c @@ -37,6 +37,8 @@ #define FPS_QUIT (BUTTON_REC|BUTTON_REPEAT) #elif CONFIG_KEYPAD == RK27XX_GENERIC_PAD #define FPS_QUIT (BUTTON_M|BUTTON_REPEAT) +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define FPS_QUIT BUTTON_BACK #elif defined(BUTTON_OFF) #define FPS_QUIT BUTTON_OFF #else diff --git a/apps/plugins/test_gfx.c b/apps/plugins/test_gfx.c index cde77c55fe..4081e64d13 100644 --- a/apps/plugins/test_gfx.c +++ b/apps/plugins/test_gfx.c @@ -402,7 +402,7 @@ static void time_text(void) /* tests mono_bitmap performance */ /* plugin entry point */ enum plugin_status plugin_start(const void* parameter) { -#ifndef SIMULATOR +#ifdef HAVE_ADJUSTABLE_CPU_FREQ int cpu_freq; #endif @@ -447,7 +447,7 @@ enum plugin_status plugin_start(const void* parameter) 6*4*DURATION/HZ); init_rand_table(); -#ifndef SIMULATOR +#ifdef HAVE_ADJUSTABLE_CPU_FREQ cpu_freq = *rb->cpu_frequency; /* remember CPU frequency */ #endif @@ -458,7 +458,7 @@ enum plugin_status plugin_start(const void* parameter) time_fillrect(); time_text(); -#ifndef SIMULATOR +#ifdef HAVE_ADJUSTABLE_CPU_FREQ if (*rb->cpu_frequency != cpu_freq) rb->fdprintf(log_fd, "\nCPU: %s\n", "clock changed!"); else diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h index 697076e643..fe16b5f8ce 100644 --- a/apps/plugins/text_viewer/tv_button.h +++ b/apps/plugins/text_viewer/tv_button.h @@ -436,6 +436,16 @@ #define TV_LINE_DOWN BUTTON_SCROLL_FWD #define TV_BOOKMARK (BUTTON_DOWN|BUTTON_SELECT) +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD +#define TV_QUIT BUTTON_BACK +#define TV_SCROLL_UP BUTTON_UP +#define TV_SCROLL_DOWN BUTTON_DOWN +#define TV_SCREEN_LEFT BUTTON_LEFT +#define TV_SCREEN_RIGHT BUTTON_RIGHT +#define TV_MENU BUTTON_MENU +#define TV_AUTOSCROLL BUTTON_USER +#define TV_BOOKMARK BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c index cf66070c6b..7ca7b43726 100644 --- a/apps/plugins/vu_meter.c +++ b/apps/plugins/vu_meter.c @@ -338,6 +338,17 @@ #define LABEL_MENU "PREV" #define LABEL_VOLUME "VOL+/VOL-" +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) +#define VUMETER_QUIT BUTTON_BACK +#define VUMETER_HELP BUTTON_USER +#define VUMETER_MENU BUTTON_MENU +#define VUMETER_UP BUTTON_UP +#define VUMETER_DOWN BUTTON_DOWN +#define LABEL_HELP "User" +#define LABEL_QUIT "Back" +#define LABEL_MENU "Menu" +#define LABEL_VOLUME "Up/Down" + #else #error No keymap defined! #endif diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c index 016c4ad31b..f1834aade5 100644 --- a/apps/plugins/wormlet.c +++ b/apps/plugins/wormlet.c @@ -180,7 +180,8 @@ static long max_cycle; #define BTN_QUIT BUTTON_POWER #define BTN_STOPRESET BUTTON_REW -#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) +#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD) || \ + (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) #define BTN_DIR_UP BUTTON_UP #define BTN_DIR_DOWN BUTTON_DOWN diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c index 8de0c8fe16..30fd5fde13 100644 --- a/apps/plugins/xobox.c +++ b/apps/plugins/xobox.c @@ -277,6 +277,15 @@ CONFIG_KEYPAD == MROBE500_PAD #define DOWN BUTTON_DOWN #define PAUSE BUTTON_SELECT +#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD) + +#define QUIT BUTTON_BACK +#define LEFT BUTTON_LEFT +#define RIGHT BUTTON_RIGHT +#define UP BUTTON_UP +#define DOWN BUTTON_DOWN +#define PAUSE BUTTON_SELECT + #else #error No keymap defined! #endif diff --git a/apps/plugins/zxbox/keymaps.h b/apps/plugins/zxbox/keymaps.h index 4e5d73a343..317e67cd9f 100644 --- a/apps/plugins/zxbox/keymaps.h +++ b/apps/plugins/zxbox/keymaps.h @@ -28,7 +28,8 @@ #define ZX_SELECT BUTTON_SELECT #define ZX_MENU BUTTON_MENU -#elif CONFIG_KEYPAD == GIGABEAT_S_PAD +#elif CONFIG_KEYPAD == GIGABEAT_S_PAD || \ + CONFIG_KEYPAD == SAMSUNG_YPR0_PAD #define ZX_UP BUTTON_UP #define ZX_DOWN BUTTON_DOWN @@ -226,6 +227,15 @@ #define ZX_LEFT BUTTON_LEFT #define ZX_RIGHT BUTTON_RIGHT +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD + +#define ZX_MENU BUTTON_MENU +#define ZX_UP BUTTON_UP +#define ZX_DOWN BUTTON_DOWN +#define ZX_SELECT BUTTON_CENTER +#define ZX_LEFT BUTTON_LEFT +#define ZX_RIGHT BUTTON_RIGHT + #else #error Keymap not defined! diff --git a/apps/plugins/zxbox/zxbox_keyb.c b/apps/plugins/zxbox/zxbox_keyb.c index fc5ed41169..e8b5219de3 100644 --- a/apps/plugins/zxbox/zxbox_keyb.c +++ b/apps/plugins/zxbox/zxbox_keyb.c @@ -225,6 +225,15 @@ #elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD +#define KBD_SELECT BUTTON_CENTER +#define KBD_ABORT BUTTON_BACK +#define KBD_LEFT BUTTON_LEFT +#define KBD_RIGHT BUTTON_RIGHT +#define KBD_UP BUTTON_UP +#define KBD_DOWN BUTTON_DOWN + +#elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD + #define KBD_SELECT BUTTON_SELECT #define KBD_ABORT BUTTON_BACK #define KBD_LEFT BUTTON_LEFT diff --git a/docs/CREDITS b/docs/CREDITS index 614b165afd..477741816a 100644 --- a/docs/CREDITS +++ b/docs/CREDITS @@ -610,6 +610,7 @@ Desu Rozen Olivier Kaloudoff Kessia Pinheiro Jean-Louis Biasini +Lorenzo Miori The libmad team The wavpack team diff --git a/firmware/SOURCES b/firmware/SOURCES index 7053358bee..f59475e27a 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -14,8 +14,10 @@ target/hosted/cpuinfo-linux.c #endif target/hosted/powermgmt.c +#ifndef SAMSUNG_YPR0 /* uses as3514 rtc */ target/hosted/rtc.c #endif +#endif system.c usb.c #ifdef ROCKBOX_HAS_LOGF @@ -62,6 +64,26 @@ target/hosted/sdl/app/button-application.c #endif #endif +#ifdef SAMSUNG_YPR0 +#if (CONFIG_RTC == RTC_AS3514) +drivers/rtc/rtc_as3514.c +#else +target/hosted/rtc.c +#endif +target/hosted/ypr0/button-ypr0.c +target/hosted/ypr0/kernel-ypr0.c +target/hosted/ypr0/lcd-ypr0.c +target/hosted/ypr0/system-ypr0.c +target/hosted/ypr0/fs-ypr0.c +target/hosted/ypr0/lc-ypr0.c +thread.c +#ifdef HAVE_BACKLIGHT +target/hosted/ypr0/backlight-ypr0.c +#endif +target/hosted/ypr0/ascodec-ypr0.c +target/hosted/ypr0/powermgmt-ypr0.c +#endif + /* Maemo specific files */ #if (CONFIG_PLATFORM & PLATFORM_MAEMO) target/hosted/maemo/maemo-thread.c @@ -368,6 +390,10 @@ drivers/audio/aic3x.c #elif defined (HAVE_DUMMY_CODEC) drivers/audio/dummy_codec.c #endif /* defined(HAVE_*) */ +#else /* PLATFORM_HOSTED */ +#if defined(SAMSUNG_YPR0) && defined(HAVE_AS3514) +drivers/audio/as3514.c +target/hosted/pcm-alsa.c #elif defined(HAVE_SDL_AUDIO) drivers/audio/sdl.c #if CONFIG_CODEC == SWCODEC @@ -377,6 +403,7 @@ target/hosted/maemo/pcm-gstreamer.c target/hosted/sdl/pcm-sdl.c #endif /* (CONFIG_PLATFORM & PLATFORM_MAEMO) */ #endif /* CONFIG_CODEC == SWCODEC */ +#endif #endif /* (CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(BOOTLOADER) */ /* CPU Specific - By class then particular chip if applicable */ @@ -722,7 +749,7 @@ target/arm/ascodec-pp.c # endif # if !defined(BOOTLOADER) || defined(CPU_PP) target/arm/adc-as3514.c -# ifndef SANSA_M200V4 +# if !defined(SANSA_M200V4) && !defined(SAMSUNG_YPR0) target/arm/powermgmt-ascodec.c # endif # endif diff --git a/firmware/common/rbpaths.c b/firmware/common/rbpaths.c index ed413eb03e..95bff3341f 100644 --- a/firmware/common/rbpaths.c +++ b/firmware/common/rbpaths.c @@ -23,6 +23,7 @@ #include /* snprintf */ #include #include +#include "config.h" #include "rbpaths.h" #include "file.h" /* MAX_PATH */ #include "logf.h" @@ -38,11 +39,17 @@ #undef mkdir #undef rmdir + #if (CONFIG_PLATFORM & PLATFORM_ANDROID) #include "dir-target.h" #define opendir opendir_android #define mkdir mkdir_android #define rmdir rmdir_android +#elif defined(SAMSUNG_YPR0) +#include "dir-target.h" +#define opendir opendir_ypr0 +#define mkdir mkdir_ypr0 +#define rmdir rmdir_ypr0 #elif (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA)) #define open sim_open #define remove sim_remove @@ -59,6 +66,8 @@ extern int sim_rmdir(const char* name); const char *rbhome; #endif +#if !defined(SAMSUNG_YPR0) + /* flags for get_user_file_path() */ /* whether you need write access to that file/dir, especially true * for runtime generated files (config.cfg) */ @@ -238,3 +247,28 @@ int app_rmdir(const char* name) } return rmdir(fname); } + +#else + +int app_open(const char *name, int o, ...) +{ + if (o & O_CREAT) + { + int ret; + va_list ap; + va_start(ap, o); + ret = open(name, o, va_arg(ap, mode_t)); + va_end(ap); + return ret; + } + return open(name, o); +} + +int app_creat(const char* name, mode_t mode) { return creat(name, mode); } +int app_remove(const char *name) { return remove(name); } +int app_rename(const char *old, const char *new) { return rename(old,new); } +DIR *app_opendir(const char *name) { return opendir(name); } +int app_mkdir(const char* name) { return mkdir(name); } +int app_rmdir(const char* name) { return rmdir(name); } + +#endif diff --git a/firmware/drivers/audio/as3514.c b/firmware/drivers/audio/as3514.c index 64531cfc2b..0fe3070c19 100644 --- a/firmware/drivers/audio/as3514.c +++ b/firmware/drivers/audio/as3514.c @@ -78,6 +78,7 @@ const struct sound_settings_info audiohw_settings[] = { #endif }; +#ifndef SAMSUNG_YPR0 /* Shadow registers */ static uint8_t as3514_regs[AS3514_NUM_AUDIO_REGS]; /* 8-bit registers */ @@ -110,7 +111,29 @@ static void as3514_write_masked(unsigned int reg, unsigned int bits, { as3514_write(reg, (as3514_regs[reg] & ~mask) | (bits & mask)); } +#else +static void as3514_write(unsigned int reg, unsigned int value) +{ + ascodec_write(reg, value); +} +/* Helpers to set/clear bits */ +static void as3514_set(unsigned int reg, unsigned int bits) +{ + ascodec_write(reg, ascodec_read(reg) | bits); +} + +static void as3514_clear(unsigned int reg, unsigned int bits) +{ + ascodec_write(reg, ascodec_read(reg) & ~bits); +} + +static void as3514_write_masked(unsigned int reg, unsigned int bits, + unsigned int mask) +{ + ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask)); +} +#endif /* convert tenth of dB volume to master volume register value */ int tenthdb2master(int db) { @@ -145,8 +168,11 @@ int sound_val2phys(int setting, int value) */ void audiohw_preinit(void) { + +#ifndef SAMSUNG_YPR0 /* read all reg values */ ascodec_readbytes(0x0, AS3514_NUM_AUDIO_REGS, as3514_regs); +#endif #ifdef HAVE_AS3543 @@ -284,9 +310,14 @@ void audiohw_set_master_vol(int vol_l, int vol_r) #if CONFIG_CPU == AS3525v2 #define MIXER_MAX_VOLUME 0x1b #else /* lets leave the AS3514 alone until its better tested*/ +#ifdef SAMSUNG_YPR0 +#define MIXER_MAX_VOLUME 0x1a +#else #define MIXER_MAX_VOLUME 0x16 #endif +#endif +#ifndef SAMSUNG_YPR0 if (vol_r <= MIXER_MAX_VOLUME) { mix_r = vol_r; hph_r = 0; @@ -302,7 +333,16 @@ void audiohw_set_master_vol(int vol_l, int vol_r) mix_l = MIXER_MAX_VOLUME; hph_l = vol_l - MIXER_MAX_VOLUME; } +#else +/* Okay. This is shit coded indeed. It is just a test. + Some considerations: Samsung keeps DAC constantly to 0x1a volume. It modifies only the headphone amp volume +*/ + mix_r = 0x1a; + mix_l = 0x1a; + hph_l = vol_l; + hph_r = vol_r; +#endif as3514_write_masked(AS3514_DAC_R, mix_r, AS3514_VOL_MASK); as3514_write_masked(AS3514_DAC_L, mix_l, AS3514_VOL_MASK); diff --git a/firmware/drivers/rtc/rtc_as3514.c b/firmware/drivers/rtc/rtc_as3514.c index 44ef3cc4a1..868fa9753b 100644 --- a/firmware/drivers/rtc/rtc_as3514.c +++ b/firmware/drivers/rtc/rtc_as3514.c @@ -141,11 +141,11 @@ void rtc_alarm_poweroff(void) seconds = 24*3600; seconds -= tm.tm_sec; - +#ifndef SAMSUNG_YPR0 /* disable MCLK, it is a wakeup source and prevents proper shutdown */ CGU_AUDIO = (2 << 0) | (1 << 11); CGU_PLLBSUP = (1 << 2) | (1 << 3); - +#endif /* write wakeup register */ alarm.seconds = seconds; alarm.enabled = true; diff --git a/firmware/export/as3514.h b/firmware/export/as3514.h index acf13444fa..bcdb1a78c6 100644 --- a/firmware/export/as3514.h +++ b/firmware/export/as3514.h @@ -131,9 +131,14 @@ extern void audiohw_set_sampr_dividers(int fsel); /* Headphone volume goes from -81.0 ... +6dB */ #define VOLUME_MIN -810 #else +#ifdef SAMSUNG_YPR0 +/* Headphone volume goes from -40.5 ... +6dB */ +#define VOLUME_MIN -405 +#else /* Headphone volume goes from -73.5 ... +6dB */ #define VOLUME_MIN -735 #endif +#endif #define VOLUME_MAX 60 /*** Audio Registers ***/ diff --git a/firmware/export/ascodec.h b/firmware/export/ascodec.h index 93cd767608..658153e420 100644 --- a/firmware/export/ascodec.h +++ b/firmware/export/ascodec.h @@ -28,4 +28,8 @@ #include "ascodec-target.h" #endif +#ifdef SAMSUNG_YPR0 +#include "ascodec-target.h" +#endif + #endif diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 102d107d8a..304c5aa460 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -79,7 +79,7 @@ #elif defined(HAVE_DUMMY_CODEC) #include "dummy_codec.h" #endif -#if (CONFIG_PLATFORM & PLATFORM_HOSTED) +#if (CONFIG_PLATFORM & (PLATFORM_ANDROID|PLATFORM_MAEMO|PLATFORM_PANDORA|PLATFORM_SDL)) /* #include gives errors in other code areas, * we don't really need it here, so don't. but it should maybe be fixed */ #ifndef SIMULATOR /* simulator gets values from the target .h files */ diff --git a/firmware/export/config.h b/firmware/export/config.h index 039b48a759..542587fc9d 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -143,6 +143,7 @@ #define HM60X_PAD 50 #define HM801_PAD 51 #define SANSA_CONNECT_PAD 52 +#define SAMSUNG_YPR0_PAD 53 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -232,6 +233,7 @@ #define LCD_HX8340B 44 /* as used by the HiFiMAN HM-601/HM-602/HM-801 */ #define LCD_CONNECT 45 /* as used by the Sandisk Sansa Connect */ #define LCD_GIGABEATS 46 +#define LCD_YPR0 47 /* LCD_PIXELFORMAT */ #define HORIZONTAL_PACKING 1 @@ -483,6 +485,8 @@ Lyre prototype 1 */ #include "config/nokian900.h" #elif defined(PANDORA) #include "config/pandora.h" +#elif defined(SAMSUNG_YPR0) +#include "config/ypr0.h" #else /* no known platform */ #endif @@ -580,6 +584,10 @@ Lyre prototype 1 */ #define CONFIG_BACKLIGHT_FADING BACKLIGHT_NO_FADING #endif +#ifndef CONFIG_I2C +#define CONFIG_I2C I2C_NONE +#endif + #ifndef CONFIG_TUNER #define CONFIG_TUNER 0 #endif @@ -600,6 +608,14 @@ Lyre prototype 1 */ #define CONFIG_RTC 0 #endif +#ifndef BATTERY_TYPES_COUNT +#define BATTERY_TYPES_COUNT 0 +#endif + +#ifndef BATTERY_CAPACITY_INC +#define BATTERY_CAPACITY_INC 0 +#endif + #ifndef CONFIG_ORIENTATION #if LCD_HEIGHT > LCD_WIDTH #define CONFIG_ORIENTATION SCREEN_PORTRAIT diff --git a/firmware/export/config/ypr0.h b/firmware/export/config/ypr0.h new file mode 100644 index 0000000000..25e1906a80 --- /dev/null +++ b/firmware/export/config/ypr0.h @@ -0,0 +1,168 @@ +/* + * This config file is for the RockBox as application on the Samsung YP-R0 player. + * The target name for ifdefs is: SAMSUNG_YPR0; or CONFIG_PLATFORM & PLAFTORM_YPR0 + */ + +#define TARGET_TREE /* this target is using the target tree system */ + +/* We don't run on hardware directly */ +/* YP-R0 need it too of course */ +#define CONFIG_PLATFORM (PLATFORM_HOSTED) + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 100 + +#define MODEL_NAME "Samsung YP-R0" + +/* Indeed to check that */ +/*TODO: R0 should charge battery automatically, no software stuff to manage that. Just to know about some as3543 registers, that should be set after loading samsung's afe.ko module + */ +/*TODO: implement USB data transfer management -> see safe mode script and think a way to implemtent it in the code */ +#define USB_NONE + +/* Hardware controlled charging with monitoring */ +//#define CONFIG_CHARGING CHARGING_MONITOR + +/* There is only USB charging */ +//#define HAVE_USB_POWER + +/* define this if you have a bitmap LCD display */ +#define HAVE_LCD_BITMAP + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR + +/* define this if the LCD needs to be shutdown */ +/* TODO: Our framebuffer must be closed... */ +#define HAVE_LCD_SHUTDOWN + +/* define this if you want album art for this target */ +#define HAVE_ALBUMART + +/* define this to enable bitmap scaling */ +#define HAVE_BMP_SCALING + +/* define this to enable JPEG decoding */ +#define HAVE_JPEG + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you have access to the pitchscreen */ +#define HAVE_PITCHSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +/* LCD dimensions + * + * overriden by configure for application builds */ +#ifndef LCD_WIDTH +#define LCD_WIDTH 240 +#endif + +#ifndef LCD_HEIGHT +#define LCD_HEIGHT 320 +#endif + +#define LCD_DEPTH 16 +/* Check that but should not matter */ +#define LCD_PIXELFORMAT 565 + +/* YP-R0 has the backlight */ +#define HAVE_BACKLIGHT + +/* Define this for LCD backlight brightness available */ +#define HAVE_BACKLIGHT_BRIGHTNESS + +/* Main LCD backlight brightness range and defaults */ +/* 0 is turned off. 31 is the real maximum for the ASCODEC DCDC but samsung doesn't use any value over 15, so it safer to don't go up too much */ +#define MIN_BRIGHTNESS_SETTING 1 +#define MAX_BRIGHTNESS_SETTING 15 +#define DEFAULT_BRIGHTNESS_SETTING 4 + +/* Which backlight fading type? */ +/* TODO: ASCODEC has an auto dim feature, so disabling the supply to leds should do the trick. But for now I tested SW fading only */ +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING + +/* define this if you have RTC RAM available for settings */ +/* TODO: in theory we could use that, ascodec offers us such a ram. we have also a small device, part of the nand of 1 MB size, that Samsung uses to store region code etc and it's almost unused space */ +//#define HAVE_RTC_RAM + +/* define this if you have a real-time clock */ +//#define CONFIG_RTC APPLICATION +#define CONFIG_RTC RTC_AS3514 +#define HAVE_RTC_ALARM + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x80000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x100000 + +/* We can do AB-repeat -> we use User key, our hotkey */ +#define AB_REPEAT_ENABLE +#define ACTION_WPSAB_SINGLE ACTION_WPS_HOTKEY + +/* Define this if you do software codec */ +#define CONFIG_CODEC SWCODEC + +/* R0 KeyPad configuration for plugins */ +#define CONFIG_KEYPAD SAMSUNG_YPR0_PAD +/* It's better to close /dev/r0Btn at shutdown */ +#define BUTTON_DRIVER_CLOSE + +/* The YPR0 has a as3534 codec and we use that to control the volume */ +#define HAVE_AS3514 +#define HAVE_AS3543 + +#define HAVE_SW_TONE_CONTROLS + +/* TODO: Make use of the si4703 tuner hardware */ +/* #define CONFIG_TUNER SI4700 */ +/* #define HAVE_TUNER_PWR_CTRL*/ + +/*TODO: In R0 there is an interrupt for this (figure out ioctls)*/ +/* #define HAVE_HEADPHONE_DETECTION */ + +/* Define current usage levels. */ +/* TODO: to be filled with correct values after implementing power management */ +#define CURRENT_NORMAL 88 /* 18 hours from a 1600 mAh battery */ +#define CURRENT_BACKLIGHT 30 /* TBD */ +#define CURRENT_RECORD 0 /* no recording yet */ + +/* TODO: We need to do battery handling */ +//#define BATTERY_CAPACITY_DEFAULT 600 /* default battery capacity */ +//#define BATTERY_CAPACITY_MIN 600 /* min. capacity selectable */ +//#define BATTERY_CAPACITY_MAX 700 /* max. capacity selectable */ +//#define BATTERY_CAPACITY_INC 50 /* capacity increment */ +//#define BATTERY_TYPES_COUNT 1 /* only one type */ + +/* TODO: We possibly can only watch linux charging */ +//#define CONFIG_CHARGING CHARGING_TARGET +//#define HAVE_RESET_BATTERY_FILTER + +/* same dimensions as gigabeats */ +#define CONFIG_LCD LCD_YPR0 + +/* Define this if a programmable hotkey is mapped */ +#define HAVE_HOTKEY + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* Define this if you have adjustable CPU frequency + * NOTE: We could do that on this device, but it's probably better + * to let linux do it (we set ondemand governor before loading Rockbox) */ +/* #define HAVE_ADJUSTABLE_CPU_FREQ */ +/* Define this to the CPU frequency */ +#define CPU_FREQ 532000000 +/* 0.8Vcore using 200 MHz */ +/* #define CPUFREQ_DEFAULT 200000000 */ +/* This is 400 MHz -> not so powersaving-ful */ +/* #define CPUFREQ_NORMAL 400000000 */ +/* Max IMX37 Cpu Frequency */ +/* #define CPUFREQ_MAX CPU_FREQ */ + +/* TODO: my idea is to create a folder in the cramfs [/.rockbox], mounting it by the starter script as the current working directory, so no issues of any type keeping the rockbox folder as in all other players */ +#define BOOTDIR "/.rockbox" diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index 74d26f93d3..8f554c25f4 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h @@ -44,7 +44,7 @@ #define ROCKBOX_DIR_LEN (sizeof(ROCKBOX_DIR)-1) #endif /* def __PCTOOL__ */ -#ifndef APPLICATION +#if !defined(APPLICATION) || defined(SAMSUNG_YPR0) /* make sure both are the same for native builds */ #undef ROCKBOX_LIBRARY_PATH @@ -57,6 +57,7 @@ #define PLAYLIST_CATALOG_DEFAULT_DIR "/Playlists" #define paths_init() + #else /* application */ #define PLUGIN_DIR ROCKBOX_LIBRARY_PATH "/rockbox/rocks" @@ -80,7 +81,7 @@ extern void paths_init(void); #define PLUGIN_DEMOS_DIR PLUGIN_DIR "/demos" #define VIEWERS_DIR PLUGIN_DIR "/viewers" -#ifdef APPLICATION +#if defined(APPLICATION) && !defined(SAMSUNG_YPR0) #define PLUGIN_DATA_DIR "/.rockbox/rocks.data" #define PLUGIN_GAMES_DATA_DIR PLUGIN_DATA_DIR #define PLUGIN_APPS_DATA_DIR PLUGIN_DATA_DIR diff --git a/firmware/include/dir_uncached.h b/firmware/include/dir_uncached.h index d9a29fbada..e0fea13c14 100644 --- a/firmware/include/dir_uncached.h +++ b/firmware/include/dir_uncached.h @@ -74,7 +74,7 @@ typedef struct { #if defined(APPLICATION) -#if (CONFIG_PLATFORM & PLATFORM_ANDROID) +#if (CONFIG_PLATFORM & PLATFORM_ANDROID) || defined(SAMSUNG_YPR0) #include "dir-target.h" #endif # undef opendir_uncached diff --git a/firmware/pcm_mixer.c b/firmware/pcm_mixer.c index 25c41c2586..3194f76e04 100644 --- a/firmware/pcm_mixer.c +++ b/firmware/pcm_mixer.c @@ -70,6 +70,11 @@ static struct mixer_channel * active_channels[PCM_MIXER_NUM_CHANNELS+1] IBSS_ATT #define MAX_IDLE_FRAMES (NATIVE_FREQUENCY*3 / MIX_FRAME_SAMPLES) static unsigned int idle_counter = 0; +/* Cheapo buffer align macro to align to the 16-16 PCM size */ +#define ALIGN_CHANNEL(start, size) \ + ({ start = (void *)(((uintptr_t)start + 3) & ~3); \ + size &= ~3; }) + #if (CONFIG_PLATFORM & PLATFORM_NATIVE) /* Include any implemented CPU-optimized mixdown routines */ diff --git a/firmware/sound.c b/firmware/sound.c index c97ccc243f..99db7896ab 100644 --- a/firmware/sound.c +++ b/firmware/sound.c @@ -235,7 +235,8 @@ static void set_prescaled_volume(void) dsp_callback(DSP_CALLBACK_SET_SW_VOLUME, 0); #endif -#ifndef HAVE_SDL_AUDIO +/* ypr0 with sdl has separate volume controls */ +#if !defined(HAVE_SDL_AUDIO) || defined(SAMSUNG_YPR0) #if CONFIG_CODEC == MAS3507D dac_volume(tenthdb2reg(l), tenthdb2reg(r), false); #elif defined(HAVE_UDA1380) || defined(HAVE_WM8975) || defined(HAVE_WM8758) \ @@ -670,7 +671,7 @@ void sound_set(int setting, int value) && !defined (HAVE_WM8711) && !defined (HAVE_WM8721) \ && !defined (HAVE_WM8731) && !defined (HAVE_WM8978) \ && !defined (HAVE_WM8750) && !defined (HAVE_WM8751) \ - && !defined(HAVE_AK4537)) || (CONFIG_PLATFORM & PLATFORM_HOSTED) + && !defined(HAVE_AK4537)) || defined(SIMULATOR) int sound_val2phys(int setting, int value) { #if CONFIG_CODEC == MAS3587F diff --git a/firmware/system.c b/firmware/system.c index 7e269ee119..111a94f80e 100644 --- a/firmware/system.c +++ b/firmware/system.c @@ -26,7 +26,7 @@ #include "string.h" #include "file.h" -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) +#ifdef HAVE_ADJUSTABLE_CPU_FREQ long cpu_frequency SHAREDBSS_ATTR = CPU_FREQ; #endif diff --git a/firmware/target/hosted/pcm-alsa.c b/firmware/target/hosted/pcm-alsa.c new file mode 100644 index 0000000000..928187993e --- /dev/null +++ b/firmware/target/hosted/pcm-alsa.c @@ -0,0 +1,518 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Thomas Martitz + * + * 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. + * + ****************************************************************************/ + + +/* + * Based, but heavily modified, on the example given at + * http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html + * + * This driver uses the so-called unsafe async callback method and hardcoded device + * names. It fails when the audio device is busy by other apps. + * + * TODO: Rewrite this to do it properly with multithreading + * + * Alternatively, a version using polling in a tick task is provided. While + * supposedly safer, it appears to use more CPU (however I didn't measure it + * accurately, only looked at htop). At least, in this mode the "default" + * device works which doesnt break with other apps running. + * device works which doesnt break with other apps running. + */ + + +#include "autoconf.h" + +#include +#include +#include +#include "system.h" +#include "debug.h" +#include "kernel.h" + +#include "pcm.h" +#include "pcm-internal.h" +#include "pcm_mixer.h" +#include "pcm_sampr.h" + +#include +#include + +#define USE_ASYNC_CALLBACK +/* plughw:0,0 works with both, however "default" is recommended. + * default doesnt seem to work with async callback but doesn't break + * with multple applications running */ +static char device[] = "plughw:0,0"; /* playback device */ +static const snd_pcm_access_t access_ = SND_PCM_ACCESS_RW_INTERLEAVED; /* access mode */ +static const snd_pcm_format_t format = SND_PCM_FORMAT_S16; /* sample format */ +static const int channels = 2; /* count of channels */ +static unsigned int rate = 44100; /* stream rate */ + +static snd_pcm_t *handle; +static snd_pcm_sframes_t buffer_size = MIX_FRAME_SAMPLES * 32; /* ~16k */ +static snd_pcm_sframes_t period_size = MIX_FRAME_SAMPLES * 4; /* ~4k */ +static short *frames; + +static const char *pcm_data = 0; +static size_t pcm_size = 0; + +#ifdef USE_ASYNC_CALLBACK +static snd_async_handler_t *ahandler; +static pthread_mutex_t pcm_mtx; +#else +static int recursion; +#endif + +static int set_hwparams(snd_pcm_t *handle, unsigned sample_rate) +{ + unsigned int rrate; + int err; + snd_pcm_hw_params_t *params; + snd_pcm_hw_params_alloca(¶ms); + + + /* choose all parameters */ + err = snd_pcm_hw_params_any(handle, params); + if (err < 0) + { + printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(err)); + return err; + } + /* set the interleaved read/write format */ + err = snd_pcm_hw_params_set_access(handle, params, access_); + if (err < 0) + { + printf("Access type not available for playback: %s\n", snd_strerror(err)); + return err; + } + /* set the sample format */ + err = snd_pcm_hw_params_set_format(handle, params, format); + if (err < 0) + { + printf("Sample format not available for playback: %s\n", snd_strerror(err)); + return err; + } + /* set the count of channels */ + err = snd_pcm_hw_params_set_channels(handle, params, channels); + if (err < 0) + { + printf("Channels count (%i) not available for playbacks: %s\n", channels, snd_strerror(err)); + return err; + } + /* set the stream rate */ + rrate = sample_rate; + err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); + if (err < 0) + { + printf("Rate %iHz not available for playback: %s\n", rate, snd_strerror(err)); + return err; + } + if (rrate != sample_rate) + { + printf("Rate doesn't match (requested %iHz, get %iHz)\n", sample_rate, err); + return -EINVAL; + } + + /* set the buffer size */ + err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &buffer_size); + if (err < 0) + { + printf("Unable to set buffer size %i for playback: %s\n", buffer_size, snd_strerror(err)); + return err; + } + + /* set the period size */ + err = snd_pcm_hw_params_set_period_size_near (handle, params, &period_size, NULL); + if (err < 0) + { + printf("Unable to set period size %i for playback: %s\n", period_size, snd_strerror(err)); + return err; + } + if (!frames) + frames = malloc(period_size * channels * sizeof(short)); + + /* write the parameters to device */ + err = snd_pcm_hw_params(handle, params); + if (err < 0) + { + printf("Unable to set hw params for playback: %s\n", snd_strerror(err)); + return err; + } + return 0; +} + +/* Set sw params: playback start threshold and low buffer watermark */ +static int set_swparams(snd_pcm_t *handle) +{ + int err; + + snd_pcm_sw_params_t *swparams; + snd_pcm_sw_params_alloca(&swparams); + + /* get the current swparams */ + err = snd_pcm_sw_params_current(handle, swparams); + if (err < 0) + { + printf("Unable to determine current swparams for playback: %s\n", snd_strerror(err)); + return err; + } + /* start the transfer when the buffer is haalmost full */ + err = snd_pcm_sw_params_set_start_threshold(handle, swparams, buffer_size / 2); + if (err < 0) + { + printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(err)); + return err; + } + /* allow the transfer when at least period_size samples can be processed */ + err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_size); + if (err < 0) + { + printf("Unable to set avail min for playback: %s\n", snd_strerror(err)); + return err; + } + /* write the parameters to the playback device */ + err = snd_pcm_sw_params(handle, swparams); + if (err < 0) + { + printf("Unable to set sw params for playback: %s\n", snd_strerror(err)); + return err; + } + return 0; +} + +/* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */ +static bool fill_frames(void) +{ + ssize_t copy_n, frames_left = period_size; + bool new_buffer = false; + + while (frames_left > 0) + { + if (!pcm_size) + { + new_buffer = true; + pcm_play_get_more_callback((void **)&pcm_data, &pcm_size); + if (!pcm_size || !pcm_data) + return false; + } + copy_n = MIN((ssize_t)pcm_size, frames_left*4); + memcpy(&frames[2*(period_size-frames_left)], pcm_data, copy_n); + + pcm_data += copy_n; + pcm_size -= copy_n; + frames_left -= copy_n/4; + + if (new_buffer) + { + new_buffer = false; + pcm_play_dma_started_callback(); + } + } + return true; +} + +#ifdef USE_ASYNC_CALLBACK +static void async_callback(snd_async_handler_t *ahandler) +{ + snd_pcm_t *handle = snd_async_handler_get_pcm(ahandler); + + if (pthread_mutex_trylock(&pcm_mtx) != 0) + return; +#else +static void pcm_tick(void) +{ + if (snd_pcm_state(handle) != SND_PCM_STATE_RUNNING) + return; +#endif + + while (snd_pcm_avail_update(handle) >= period_size) + { + if (fill_frames()) + { + int err = snd_pcm_writei(handle, frames, period_size); + if (err < 0 && err != period_size && err != -EAGAIN) + { + printf("Write error: written %i expected %li\n", err, period_size); + break; + } + } + else + { + DEBUGF("%s: No Data.\n", __func__); + break; + } + } +#ifdef USE_ASYNC_CALLBACK + pthread_mutex_unlock(&pcm_mtx); +#endif +} + +static int async_rw(snd_pcm_t *handle) +{ + int err; + snd_pcm_sframes_t sample_size; + short *samples; + +#ifdef USE_ASYNC_CALLBACK + err = snd_async_add_pcm_handler(&ahandler, handle, async_callback, NULL); + if (err < 0) + { + DEBUGF("Unable to register async handler: %s\n", snd_strerror(err)); + return err; + } +#endif + + /* fill buffer with silence to initiate playback without noisy click */ + sample_size = buffer_size; + samples = malloc(sample_size * channels * sizeof(short)); + + snd_pcm_format_set_silence(format, samples, sample_size); + err = snd_pcm_writei(handle, samples, sample_size); + free(samples); + + if (err < 0) + { + DEBUGF("Initial write error: %s\n", snd_strerror(err)); + return err; + } + if (err != (ssize_t)sample_size) + { + DEBUGF("Initial write error: written %i expected %li\n", err, sample_size); + return err; + } + if (snd_pcm_state(handle) == SND_PCM_STATE_PREPARED) + { + err = snd_pcm_start(handle); + if (err < 0) + { + DEBUGF("Start error: %s\n", snd_strerror(err)); + return err; + } + } + return 0; +} + + +void cleanup(void) +{ + free(frames); + frames = NULL; + snd_pcm_close(handle); +} + + +void pcm_play_dma_init(void) +{ + int err; + + + if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) + { + printf("%s(): Cannot open device %s: %s\n", __func__, device, snd_strerror(err)); + exit(EXIT_FAILURE); + return; + } + + if ((err = snd_pcm_nonblock(handle, 1))) + printf("Could not set non-block mode: %s\n", snd_strerror(err)); + + if ((err = set_hwparams(handle, rate)) < 0) + { + printf("Setting of hwparams failed: %s\n", snd_strerror(err)); + exit(EXIT_FAILURE); + } + if ((err = set_swparams(handle)) < 0) + { + printf("Setting of swparams failed: %s\n", snd_strerror(err)); + exit(EXIT_FAILURE); + } + +#ifdef USE_ASYNC_CALLBACK + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&pcm_mtx, &attr); +#else + tick_add_task(pcm_tick); +#endif + + + atexit(cleanup); + return; +} + + +void pcm_play_lock(void) +{ +#ifdef USE_ASYNC_CALLBACK + pthread_mutex_lock(&pcm_mtx); +#else + if (recursion++ == 0) + tick_remove_task(pcm_tick); +#endif +} + +void pcm_play_unlock(void) +{ +#ifdef USE_ASYNC_CALLBACK + pthread_mutex_unlock(&pcm_mtx); +#else + if (--recursion == 0) + tick_add_task(pcm_tick); +#endif +} + +static void pcm_dma_apply_settings_nolock(void) +{ + snd_pcm_drop(handle); + set_hwparams(handle, pcm_sampr); +} + +void pcm_dma_apply_settings(void) +{ + pcm_play_lock(); + pcm_dma_apply_settings_nolock(); + pcm_play_unlock(); +} + + +void pcm_play_dma_pause(bool pause) +{ + snd_pcm_pause(handle, pause); +} + + +void pcm_play_dma_stop(void) +{ + snd_pcm_drain(handle); +} + +void pcm_play_dma_start(const void *addr, size_t size) +{ + pcm_dma_apply_settings_nolock(); + + pcm_data = addr; + pcm_size = size; + + while (1) + { + snd_pcm_state_t state = snd_pcm_state(handle); + switch (state) + { + case SND_PCM_STATE_RUNNING: + return; + case SND_PCM_STATE_XRUN: + { + DEBUGF("Trying to recover from error\n"); + int err = snd_pcm_recover(handle, -EPIPE, 0); + if (err < 0) + DEBUGF("Recovery failed: %s\n", snd_strerror(err)); + continue; + } + case SND_PCM_STATE_SETUP: + { + int err = snd_pcm_prepare(handle); + if (err < 0) + printf("Prepare error: %s\n", snd_strerror(err)); + /* fall through */ + } + case SND_PCM_STATE_PREPARED: + { /* prepared state, we need to fill the buffer with silence before + * starting */ + int err = async_rw(handle); + if (err < 0) + printf("Start error: %s\n", snd_strerror(err)); + return; + } + case SND_PCM_STATE_PAUSED: + { /* paused, simply resume */ + pcm_play_dma_pause(0); + return; + } + case SND_PCM_STATE_DRAINING: + /* run until drained */ + continue; + default: + DEBUGF("Unhandled state: %s\n", snd_pcm_state_name(state)); + return; + } + } +} + +size_t pcm_get_bytes_waiting(void) +{ + return pcm_size; +} + +const void * pcm_play_dma_get_peak_buffer(int *count) +{ + uintptr_t addr = (uintptr_t)pcm_data; + *count = pcm_size / 4; + return (void *)((addr + 3) & ~3); +} + +void pcm_play_dma_postinit(void) +{ +} + + +void pcm_set_mixer_volume(int volume) +{ + (void)volume; +} +#ifdef HAVE_RECORDING +void pcm_rec_lock(void) +{ +} + +void pcm_rec_unlock(void) +{ +} + +void pcm_rec_dma_init(void) +{ +} + +void pcm_rec_dma_close(void) +{ +} + +void pcm_rec_dma_start(void *start, size_t size) +{ + (void)start; + (void)size; +} + +void pcm_rec_dma_stop(void) +{ +} + +const void * pcm_rec_dma_get_peak_buffer(void) +{ + return NULL; +} + +void audiohw_set_recvol(int left, int right, int type) +{ + (void)left; + (void)right; + (void)type; +} + +#endif /* HAVE_RECORDING */ diff --git a/firmware/target/hosted/ypr0/adc-target.h b/firmware/target/hosted/ypr0/adc-target.h new file mode 100644 index 0000000000..bdbc4cfabd --- /dev/null +++ b/firmware/target/hosted/ypr0/adc-target.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: adc-target.h 29516 2011-03-05 15:31:52Z thomasjfox $ + * + * Copyright (C) 2011 by Lorenzo Miori + * + * 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_TARGET_H__ +#define __ADC_TARGET_H__ + +#endif /* __ADC_TARGET_H__ */ diff --git a/firmware/target/hosted/ypr0/ascodec-target.h b/firmware/target/hosted/ypr0/ascodec-target.h new file mode 100644 index 0000000000..f4ecf20a1b --- /dev/null +++ b/firmware/target/hosted/ypr0/ascodec-target.h @@ -0,0 +1,92 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: ascodec-target.h 26116 2010-05-17 20:53:25Z funman $ + * + * Module wrapper for AS3543 audio codec, using /dev/afe (afe.ko) of Samsung YP-R0 + * + * Copyright (c) 2011 Lorenzo Miori + * + * 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 _ASCODEC_TARGET_H +#define _ASCODEC_TARGET_H + +#include "as3514.h" +#include "kernel.h" +#include "adc.h" +#include "ascodec.h" + +/* ioctl parameter struct */ + +struct codec_req_struct { +/* This works for every kind of afe.ko module requests */ + unsigned char reg; /* Main register address */ + unsigned char subreg; /* Set this only if you are reading/writing a PMU register*/ + unsigned char value; /* To be read if reading a register; to be set if writing to a register */ +}; + +int ascodec_init(void); +void ascodec_close(void); +int ascodec_write(unsigned int reg, unsigned int value); +int ascodec_read(unsigned int reg); +void ascodec_write_pmu(unsigned int index, unsigned int subreg, unsigned int value); +int ascodec_read_pmu(unsigned int index, unsigned int subreg); +void ascodec_set(unsigned int reg, unsigned int bits); +void ascodec_clear(unsigned int reg, unsigned int bits); +void ascodec_write_masked(unsigned int reg, unsigned int bits, unsigned int mask); +int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data); +unsigned short adc_read(int channel); +void ascodec_lock(void); +void ascodec_unlock(void); + +static inline bool ascodec_chg_status(void) +{ + return ascodec_read(AS3514_IRQ_ENRD0) & CHG_STATUS; +} + +static inline bool ascodec_endofch(void) +{ + return ascodec_read(AS3514_IRQ_ENRD0) & CHG_ENDOFCH; +} + +static inline void ascodec_monitor_endofch(void) +{ + ascodec_write(AS3514_IRQ_ENRD0, IRQ_ENDOFCH); +} + +static inline void ascodec_wait_adc_finished(void) +{ + /* + * FIXME: not implemented + * + * If irqs are not available on the target platform, + * this should be most likely implemented by polling + * AS3514_IRQ_ENRD2 in the same way powermgmt-ascodec.c + * is polling IRQ_ENDOFCH. + */ +} + +static inline void ascodec_write_charger(int value) +{ + ascodec_write_pmu(AS3543_CHARGER, 1, value); +} + +static inline int ascodec_read_charger(void) +{ + return ascodec_read_pmu(AS3543_CHARGER, 1); +} + +#endif /* !_ASCODEC_TARGET_H */ diff --git a/firmware/target/hosted/ypr0/ascodec-ypr0.c b/firmware/target/hosted/ypr0/ascodec-ypr0.c new file mode 100644 index 0000000000..a4e92e6f6b --- /dev/null +++ b/firmware/target/hosted/ypr0/ascodec-ypr0.c @@ -0,0 +1,206 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: ascodec-target.h 26116 2010-05-17 20:53:25Z funman $ + * + * Module wrapper for AS3543 audio codec, using /dev/afe (afe.ko) of Samsung YP-R0 + * + * Copyright (c) 2011 Lorenzo Miori + * + * 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 "fcntl.h" +#include "unistd.h" +#include "stdio.h" +#include "string.h" +#include "sys/ioctl.h" +#include "stdlib.h" + +#include "ascodec-target.h" + +int afe_dev = -1; + +/* Write to a normal register */ +#define IOCTL_REG_WRITE 0x40034101 +/* Write to a PMU register */ +#define IOCTL_SUBREG_WRITE 0x40034103 +/* Read from a normal register */ +#define IOCTL_REG_READ 0x80034102 +/* Read from a PMU register */ +#define IOCTL_SUBREG_READ 0x80034103 + +static struct mutex as_mtx; + +int ascodec_init(void) { + + afe_dev = open("/dev/afe", O_RDWR); + + mutex_init(&as_mtx); + + return afe_dev; + +} + +void ascodec_close(void) { + + if (afe_dev >= 0) { + close(afe_dev); + } + +} + +/* Read functions returns -1 if fail, otherwise the register's value if success */ +/* Write functions return >= 0 if success, otherwise -1 if fail */ + +int ascodec_write(unsigned int reg, unsigned int value) +{ + struct codec_req_struct y; + struct codec_req_struct *p; + p = &y; + p->reg = reg; + p->value = value; + return ioctl(afe_dev, IOCTL_REG_WRITE, p); +} + +int ascodec_read(unsigned int reg) +{ + int retval = -1; + struct codec_req_struct y; + struct codec_req_struct *p; + p = &y; + p->reg = reg; + retval = ioctl(afe_dev, IOCTL_REG_READ, p); + if (retval >= 0) + return p->value; + else + return retval; +} + +void ascodec_write_pmu(unsigned int index, unsigned int subreg, + unsigned int value) +{ + struct codec_req_struct y; + struct codec_req_struct *p; + p = &y; + p->reg = index; + p->subreg = subreg; + p->value = value; + ioctl(afe_dev, IOCTL_SUBREG_WRITE, p); +} + +int ascodec_read_pmu(unsigned int index, unsigned int subreg) +{ + int retval = -1; + struct codec_req_struct y; + struct codec_req_struct *p; + p = &y; + p->reg = index; + p->subreg = subreg; + retval = ioctl(afe_dev, IOCTL_SUBREG_READ, p); + if (retval >= 0) + return p->value; + else + return retval; +} + +/* Helpers to set/clear bits */ +void ascodec_set(unsigned int reg, unsigned int bits) +{ + ascodec_write(reg, ascodec_read(reg) | bits); +} + +void ascodec_clear(unsigned int reg, unsigned int bits) +{ + ascodec_write(reg, ascodec_read(reg) & ~bits); +} + +void ascodec_write_masked(unsigned int reg, unsigned int bits, + unsigned int mask) +{ + ascodec_write(reg, (ascodec_read(reg) & ~mask) | (bits & mask)); +} + +/*FIXME: doesn't work */ +int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data) +{ + unsigned int i; + + for (i=index; i= NUM_ADC_CHANNELS) + return 0; + + ascodec_lock(); + + /* Select channel */ + ascodec_write(AS3514_ADC_0, (channel << 4)); + unsigned char buf[2]; + + /* + * The AS3514 ADC will trigger an interrupt when the conversion + * is finished, if the corresponding enable bit in IRQ_ENRD2 + * is set. + * Previously the code did not wait and this apparently did + * not pose any problems, but this should be more correct. + * Without the wait the data read back may be completely or + * partially (first one of the two bytes) stale. + */ + /*FIXME: not implemented*/ + ascodec_wait_adc_finished(); + + /* Read data */ + ascodec_readbytes(AS3514_ADC_0, 2, buf); + data = (((buf[0] & 0x3) << 8) | buf[1]); + + ascodec_unlock(); + return data; +} + +void adc_init(void) +{ +} diff --git a/firmware/target/hosted/ypr0/backlight-target.h b/firmware/target/hosted/ypr0/backlight-target.h new file mode 100644 index 0000000000..561e159e8c --- /dev/null +++ b/firmware/target/hosted/ypr0/backlight-target.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: backlight-target.h 19322 2008-12-04 04:16:53Z jethead71 $ + * + * Copyright (C) 2011 by Lorenzo Miori + * + * 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_init(void); +void _backlight_on(void); +void _backlight_off(void); +void _backlight_set_brightness(int brightness); + +#endif /* BACKLIGHT_TARGET_H */ diff --git a/firmware/target/hosted/ypr0/backlight-ypr0.c b/firmware/target/hosted/ypr0/backlight-ypr0.c new file mode 100644 index 0000000000..930b56be2e --- /dev/null +++ b/firmware/target/hosted/ypr0/backlight-ypr0.c @@ -0,0 +1,89 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: backlight-gigabeat-s.c 25800 2010-05-04 10:07:53Z jethead71 $ + * + * Copyright (C) 2011 by Lorenzo Miori + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "system.h" +#include "backlight.h" +#include "backlight-target.h" +#include "lcd.h" +#include "as3514.h" +#include "ascodec-target.h" +#include +#include "unistd.h" + +static bool backlight_on_status = true; /* Is on or off? */ + +/*TODO: see if LCD sleep could be implemented in a better way -> ie using a rockbox feature */ +/* Turn off LCD power supply */ +static void _backlight_lcd_sleep(void) +{ + int fp = open("/sys/class/graphics/fb0/blank", O_RDWR); + write(fp, "1", 1); + close(fp); +} +/* Turn on LCD screen */ +static void _backlight_lcd_power(void) +{ + int fp = open("/sys/class/graphics/fb0/blank", O_RDWR); + write(fp, "0", 1); + close(fp); +} + +bool _backlight_init(void) +{ + /* We have nothing to do */ + return true; +} + +void _backlight_on(void) +{ + if (!backlight_on_status) + { + /* Turn on lcd power before backlight */ + _backlight_lcd_power(); + /* Original app sets this to 0xb1 when backlight is on... */ + ascodec_write_pmu(AS3543_BACKLIGHT, 0x1, 0xb1); + } + + backlight_on_status = true; + +} + +void _backlight_off(void) +{ + if (backlight_on_status) { + /* Disabling the DCDC15 completely, keeps brightness register value */ + ascodec_write_pmu(AS3543_BACKLIGHT, 0x1, 0x00); + /* Turn off lcd power then */ + _backlight_lcd_sleep(); + } + + backlight_on_status = false; +} + +void _backlight_set_brightness(int brightness) +{ + /* Just another check... */ + if (brightness > MAX_BRIGHTNESS_SETTING) + brightness = MAX_BRIGHTNESS_SETTING; + if (brightness < MIN_BRIGHTNESS_SETTING) + brightness = MIN_BRIGHTNESS_SETTING; + ascodec_write_pmu(AS3543_BACKLIGHT, 0x3, brightness << 3 & 0xf8); +} diff --git a/firmware/target/hosted/ypr0/button-target.h b/firmware/target/hosted/ypr0/button-target.h new file mode 100644 index 0000000000..5d65d97607 --- /dev/null +++ b/firmware/target/hosted/ypr0/button-target.h @@ -0,0 +1,53 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: button-target.h 29248 2011-02-08 20:05:25Z thomasjfox $ + * + * Copyright (C) 2011 by Lorenzo Miori + * + * 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 +#include "config.h" + +void button_init_device(void); +void button_close_device(void); +int button_read_device(void); + +/* Logical buttons key codes */ +#define BUTTON_UP 0x00000001 +#define BUTTON_DOWN 0x00000002 +#define BUTTON_LEFT 0x00000004 +#define BUTTON_RIGHT 0x00000008 +#define BUTTON_USER 0x00000010 +#define BUTTON_MENU 0x00000020 +#define BUTTON_BACK 0x00000040 +#define BUTTON_POWER 0x00000080 +#define BUTTON_SELECT 0x00000100 + +#define BUTTON_MAIN 0x1FF /* all buttons */ + +/* No remote */ +#define BUTTON_REMOTE 0 + +/* Software power-off */ +#define POWEROFF_BUTTON BUTTON_POWER +/* About 3 seconds */ +#define POWEROFF_COUNT 10 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/hosted/ypr0/button-ypr0.c b/firmware/target/hosted/ypr0/button-ypr0.c new file mode 100644 index 0000000000..4298410161 --- /dev/null +++ b/firmware/target/hosted/ypr0/button-ypr0.c @@ -0,0 +1,103 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: button-sdl.c 30482 2011-09-08 14:53:28Z kugel $ + * + * Copyright (C) 2011 Lorenzo Miori + * + * 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 +#include +#include +#include /* EXIT_SUCCESS */ +#include "config.h" +#include "button.h" +#include "kernel.h" +#include "system.h" +#include "button-target.h" + +/* R0 physical key codes */ +enum ypr0_buttons { + R0BTN_NONE = BUTTON_NONE, + R0BTN_POWER = 1, + R0BTN_UP, + R0BTN_DOWN, + R0BTN_RIGHT, + R0BTN_LEFT, + R0BTN_CENTRAL, + R0BTN_MENU, + R0BTN_BACK, + R0BTN_3DOTS = 11, +}; + + +static int r0_btn_fd = 0; +/* Samsung keypad driver doesn't allow multiple key combinations :( */ +static enum ypr0_buttons r0_read_key(void) +{ + unsigned char keys; + + if (r0_btn_fd < 0) + return 0; + + if (read(r0_btn_fd, &keys, 1)) + return keys; + + return 0; +} + +/* Conversion from physical keypress code to logic key code */ +static int key_to_button(enum ypr0_buttons keyboard_button) +{ + switch (keyboard_button) + { + default: return BUTTON_NONE; + case R0BTN_POWER: return BUTTON_POWER; + case R0BTN_UP: return BUTTON_UP; + case R0BTN_DOWN: return BUTTON_DOWN; + case R0BTN_RIGHT: return BUTTON_RIGHT; + case R0BTN_LEFT: return BUTTON_LEFT; + case R0BTN_CENTRAL: return BUTTON_SELECT; + case R0BTN_MENU: return BUTTON_MENU; + case R0BTN_BACK: return BUTTON_BACK; + case R0BTN_3DOTS: return BUTTON_USER; + } +} + +int button_read_device(void) +{ + return key_to_button(r0_read_key()); +} + + +/* Open the keypad device: it is offered by r0Btn.ko module */ +void button_init_device(void) +{ + r0_btn_fd = open("/dev/r0Btn", O_RDONLY); + if (r0_btn_fd < 0) + printf("/dev/r0Btn open error!"); +} + +#ifdef BUTTON_DRIVER_CLOSE +/* I'm not sure it's called at shutdown...give a check! */ +void button_close_device(void) +{ + if (r0_btn_fd >= 0) { + close(r0_btn_fd); + printf("/dev/r0Btn closed!"); + } +} +#endif /* BUTTON_DRIVER_CLOSE */ diff --git a/firmware/target/hosted/ypr0/dir-target.h b/firmware/target/hosted/ypr0/dir-target.h new file mode 100644 index 0000000000..48859526df --- /dev/null +++ b/firmware/target/hosted/ypr0/dir-target.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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 __DIR_TARGET_H__ +#define __DIR_TARGET_H__ + +#include +/* including unistd.h is too noisy */ +extern int rmdir(const char* name); + + +#define dirent_uncached dirent +#define DIR_UNCACHED DIR +#define opendir_uncached _opendir +#define readdir_uncached _readdir +#define closedir_uncached _closedir +#define mkdir_uncached _mkdir +#define rmdir_uncached rmdir + +#define dirent_ypr0 dirent +#define DIR_ypr0 DIR +#define opendir_ypr0 _opendir +#define readdir_ypr0 _readdir +#define closedir_ypr0 _closedir +#define mkdir_ypr0 _mkdir +#define rmdir_ypr0 rmdir + +extern DIR* _opendir(const char* name); +extern int _mkdir(const char* name); +extern int _closedir(DIR* dir); +extern struct dirent *_readdir(DIR* dir); +extern void fat_size(unsigned long *size, unsigned long *free); + +#define DIRFUNCTIONS_DEFINED +#define DIRENT_DEFINED +#define DIR_DEFINED + +#endif /* __DIR_TARGET_H__ */ diff --git a/firmware/target/hosted/ypr0/fs-ypr0.c b/firmware/target/hosted/ypr0/fs-ypr0.c new file mode 100644 index 0000000000..7f49a5f91a --- /dev/null +++ b/firmware/target/hosted/ypr0/fs-ypr0.c @@ -0,0 +1,141 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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 +#include /* stat() */ +#include /* snprintf */ +#include /* size_t */ +#include +#include /* localtime() */ +#include "system-target.h" +#include "dir-target.h" +#include "file.h" +#include "dir.h" +#include "rbpaths.h" + + +long filesize(int fd) +{ + struct stat buf; + + if (!fstat(fd, &buf)) + return buf.st_size; + else + return -1; +} + +/* do we really need this in the app? */ +void fat_size(unsigned long* size, unsigned long* free) +{ + *size = *free = 0; +} + +#undef opendir +#undef closedir +#undef mkdir +#undef readdir + +/* need to wrap around DIR* because we need to save the parent's + * directory path in order to determine dirinfo */ +struct __dir { + DIR *dir; + char *path; +}; + +DIR* _opendir(const char *name) +{ + char *buf = malloc(sizeof(struct __dir) + strlen(name)+1); + if (!buf) + return NULL; + + struct __dir *this = (struct __dir*)buf; + + this->path = buf+sizeof(struct __dir); + /* definitely fits due to strlen() */ + strcpy(this->path, name); + + this->dir = opendir(name); + + if (!this->dir) + { + free(buf); + return NULL; + } + return (DIR*)this; +} + +int _mkdir(const char *name) +{ + return mkdir(name, 0777); +} + +int _closedir(DIR *dir) +{ + struct __dir *this = (struct __dir*)dir; + int ret = closedir(this->dir); + free(this); + return ret; +} + +struct dirent* _readdir(DIR* dir) +{ + struct __dir *d = (struct __dir*)dir; + return readdir(d->dir); +} + +struct dirinfo dir_get_info(DIR* _parent, struct dirent *dir) +{ + struct __dir *parent = (struct __dir*)_parent; + struct stat s; + struct tm *tm = NULL; + struct dirinfo ret; + char path[MAX_PATH]; + + snprintf(path, sizeof(path), "%s/%s", parent->path, dir->d_name); + memset(&ret, 0, sizeof(ret)); + + if (!stat(path, &s)) + { + if (S_ISDIR(s.st_mode)) + { + ret.attribute = ATTR_DIRECTORY; + } + ret.size = s.st_size; + tm = localtime(&(s.st_mtime)); + } + + if (!lstat(path, &s) && S_ISLNK(s.st_mode)) + { + ret.attribute |= ATTR_LINK; + } + + if (tm) + { + ret.wrtdate = ((tm->tm_year - 80) << 9) | + ((tm->tm_mon + 1) << 5) | + tm->tm_mday; + ret.wrttime = (tm->tm_hour << 11) | + (tm->tm_min << 5) | + (tm->tm_sec >> 1); + } + + return ret; +} diff --git a/firmware/target/hosted/ypr0/i2c-target.h b/firmware/target/hosted/ypr0/i2c-target.h new file mode 100644 index 0000000000..3b046bba96 --- /dev/null +++ b/firmware/target/hosted/ypr0/i2c-target.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: i2c-target.h 29516 2011-03-05 15:31:52Z thomasjfox $ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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 __I2C_TARGET_H__ +#define __I2C_TARGET_H__ + +#endif /* __I2C_TARGET_H__ */ diff --git a/firmware/target/hosted/ypr0/kernel-ypr0.c b/firmware/target/hosted/ypr0/kernel-ypr0.c new file mode 100644 index 0000000000..bcf2cee583 --- /dev/null +++ b/firmware/target/hosted/ypr0/kernel-ypr0.c @@ -0,0 +1,163 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (c) 2010 Thomas Martitz + * + * 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 +#include +#include +#include +#include +#include "config.h" +#include "system.h" +#include "button.h" +#include "audio.h" +#include "panic.h" +#include "timer.h" + + +static pthread_cond_t wfi_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t wfi_mtx = PTHREAD_MUTEX_INITIALIZER; +/* + * call tick tasks and wake the scheduler up */ +void timer_signal(union sigval arg) +{ + (void)arg; + call_tick_tasks(); + interrupt(); +} + +/* + * wait on the sem which the signal handler posts to save cpu time (aka sleep) + * + * other mechanisms could use them as well */ +void wait_for_interrupt(void) +{ + pthread_cond_wait(&wfi_cond, &wfi_mtx); +} + +/* + * Wakeup the kernel, if sleeping (shall not be called from a signal handler) */ +void interrupt(void) +{ + pthread_cond_signal(&wfi_cond); +} + + +/* + * setup a hrtimer to send a signal to our process every tick + */ +union sigval tick_arg = { + .sival_int = 0, +}; + +void tick_start(unsigned int interval_in_ms) +{ + int ret = 0; + timer_t timerid; + struct itimerspec ts; + sigevent_t sigev; + + /* initializing in the declaration causes some weird warnings */ + memset(&sigev, 0, sizeof(sigevent_t)); + sigev.sigev_notify = SIGEV_THREAD, + sigev.sigev_notify_function = timer_signal; + + ts.it_value.tv_sec = ts.it_interval.tv_sec = 0; + ts.it_value.tv_nsec = ts.it_interval.tv_nsec = interval_in_ms*1000*1000; + + /* add the timer */ + ret |= timer_create(CLOCK_REALTIME, &sigev, &timerid); + ret |= timer_settime(timerid, 0, &ts, NULL); + + /* Grab the mutex already now and leave it to this thread. We don't + * care about race conditions when signaling the condition (because + * they are not critical), but a mutex is necessary due to the API */ + pthread_mutex_lock(&wfi_mtx); + + if (ret != 0) + panicf("%s(): %s\n", __func__, strerror(errno)); +} + +#define cycles_to_microseconds(cycles) \ + ((int)((1000000*cycles)/TIMER_FREQ)) + + +static timer_t timer_tid; +static int timer_prio = -1; +void (*global_unreg_callback)(void); +void (*global_timer_callback)(void); + +static void timer_cb(union sigval arg) +{ + (void)arg; + if (global_timer_callback) + global_timer_callback(); +} + +bool timer_register(int reg_prio, void (*unregister_callback)(void), + long cycles, void (*timer_callback)(void)) +{ + int ret = 0; + struct itimerspec ts; + sigevent_t sigev; + long in_us = cycles_to_microseconds(cycles); + + if (reg_prio <= timer_prio || in_us <= 0) + return false; + + if (timer_prio >= 0 && global_unreg_callback) + global_unreg_callback(); + + /* initializing in the declaration causes some weird warnings */ + memset(&sigev, 0, sizeof(sigevent_t)); + sigev.sigev_notify = SIGEV_THREAD, + sigev.sigev_notify_function = timer_cb; + + ts.it_value.tv_sec = ts.it_interval.tv_sec = in_us / 1000000; + ts.it_value.tv_nsec = ts.it_interval.tv_nsec = (in_us%1000000)*1000; + + /* add the timer */ + ret |= timer_create(CLOCK_REALTIME, &sigev, &timer_tid); + ret |= timer_settime(timer_tid, 0, &ts, NULL); + + global_timer_callback = timer_callback; + global_unreg_callback = unregister_callback; + timer_prio = reg_prio; + + return ret == 0; +} + +bool timer_set_period(long cycles) +{ + struct itimerspec ts; + long in_us = cycles_to_microseconds(cycles); + ts.it_value.tv_sec = ts.it_interval.tv_sec = in_us / 1000000; + ts.it_value.tv_nsec = ts.it_interval.tv_nsec = (in_us%1000000)*1000; + + return timer_settime(timer_tid, 0, &ts, NULL) == 0; +} + +void timer_unregister(void) +{ + timer_delete(timer_tid); + timer_prio = -1; +} + diff --git a/firmware/target/hosted/ypr0/lc-ypr0.c b/firmware/target/hosted/ypr0/lc-ypr0.c new file mode 100644 index 0000000000..434e901a56 --- /dev/null +++ b/firmware/target/hosted/ypr0/lc-ypr0.c @@ -0,0 +1,40 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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 /* size_t */ +#include "load_code.h" + +/* the load_code wrappers simply wrap, nothing to do */ +void *lc_open(const char *filename, unsigned char *buf, size_t buf_size) +{ + return _lc_open(filename, buf, buf_size); +} + +void *lc_get_header(void *handle) +{ + return _lc_get_header(handle); +} + +void lc_close(void *handle) +{ + _lc_close(handle); +} + diff --git a/firmware/target/hosted/ypr0/lcd-ypr0.c b/firmware/target/hosted/ypr0/lcd-ypr0.c new file mode 100644 index 0000000000..f0565ae2d4 --- /dev/null +++ b/firmware/target/hosted/ypr0/lcd-ypr0.c @@ -0,0 +1,147 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: lcd-bitmap.c 29248 2011-02-08 20:05:25Z thomasjfox $ + * + * Copyright (C) 2011 Lorenzo Miori, Thomas Martitz + * + * 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 +#include +#include +#include "string.h" +#include +#include +#include + +#include "file.h" +#include "debug.h" +#include "system.h" +#include "screendump.h" +#include "lcd.h" + +/* eqivalent to fb + y*width + x */ +#define LCDADDR(x, y) (&lcd_framebuffer[(y)][(x)]) + +static int dev_fd = 0; +static fb_data *dev_fb = 0; + +void lcd_update(void) +{ + /* update the entire display */ + memcpy(dev_fb, lcd_framebuffer, sizeof(lcd_framebuffer)); +} + +/* Copy Rockbox frame buffer to the mmapped lcd device */ +void lcd_update_rect(int x, int y, int width, int height) +{ + /* nothing to draw? */ + if ((width <= 0) || (height <= 0) || (x >= LCD_WIDTH) || + (y >= LCD_HEIGHT) || (x + width <= 0) || (y + height <= 0)) + return; + + /* do the necessary clipping */ + if (x < 0) + { /* clip left */ + width += x; + x = 0; + } + if (y < 0) + { /* clip top */ + height += y; + y = 0; + } + if (x + width > LCD_WIDTH) + width = LCD_WIDTH - x; /* clip right */ + if (y + height > LCD_HEIGHT) + height = LCD_HEIGHT - y; /* clip bottom */ + + fb_data* src = LCDADDR(x, y); + fb_data* dst = dev_fb + y*LCD_WIDTH + x; + + if (LCD_WIDTH == width) + { /* optimized full-width update */ + memcpy(dst, src, width * height * sizeof(fb_data)); + } + else + { /* row by row */ + do + { + memcpy(dst, src, width * sizeof(fb_data)); + src += LCD_WIDTH; + dst += LCD_WIDTH; + } while(--height > 0); + } +} + +void lcd_shutdown(void) +{ + printf("FB closed."); + munmap(dev_fb, sizeof(lcd_framebuffer)); + close(dev_fd); +} + +void lcd_init_device(void) +{ + size_t screensize; + struct fb_var_screeninfo vinfo; + struct fb_fix_screeninfo finfo; + + /* Open the framebuffer device */ + dev_fd = open("/dev/fb0", O_RDWR); + if (dev_fd == -1) { + perror("Error: cannot open framebuffer device"); + exit(1); + } + printf("The framebuffer device was opened successfully.\n"); + + /* Get the fixed properties */ + if (ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo) == -1) { + perror("Error reading fixed information"); + exit(2); + } + + /* Now we get the settable settings, and we set 16 bit bpp */ + if (ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) { + perror("Error reading variable information"); + exit(3); + } + + vinfo.bits_per_pixel = 16; + + if (ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo)) { + perror("fbset(ioctl)"); + exit(4); + } + + printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel); + + /* Figure out the size of the screen in bytes */ + screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; + if (screensize != sizeof(lcd_framebuffer)) + { + exit(4); + perror("Display and framebuffer mismatch!\n"); + } + + /* Map the device to memory */ + dev_fb = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0); + if ((int)dev_fb == -1) { + perror("Error: failed to map framebuffer device to memory"); + exit(4); + } + printf("The framebuffer device was mapped to memory successfully.\n"); +} diff --git a/firmware/target/hosted/ypr0/powermgmt-ypr0.c b/firmware/target/hosted/ypr0/powermgmt-ypr0.c new file mode 100644 index 0000000000..5701e9f02f --- /dev/null +++ b/firmware/target/hosted/ypr0/powermgmt-ypr0.c @@ -0,0 +1,133 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: powermgmt-sim.c 29543 2011-03-08 19:33:30Z thomasjfox $ + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "config.h" +#include "system.h" +#include +#include "kernel.h" +#include "powermgmt.h" +#include "ascodec-target.h" +#include "stdio.h" + +#if 0 /*still unused*/ +/* The battery manufacturer's website shows discharge curves down to 3.0V, + so 'dangerous' and 'shutoff' levels of 3.4V and 3.3V should be safe. + */ +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3550 +}; + +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] = +{ + { 3300, 3692, 3740, 3772, 3798, 3828, 3876, 3943, 4013, 4094, 4194 } +}; + +#if CONFIG_CHARGING +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short percent_to_volt_charge[11] = +{ + 3417, 3802, 3856, 3888, 3905, 3931, 3973, 4025, 4084, 4161, 4219 +}; +#endif /* CONFIG_CHARGING */ +#endif + +#define BATT_MINMVOLT 3450 /* minimum millivolts of battery */ +#define BATT_MAXMVOLT 4150 /* maximum millivolts of battery */ +#define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in + minutes */ + +extern void send_battery_level_event(void); +extern int last_sent_battery_level; +extern int battery_percent; + +static unsigned int battery_millivolts = BATT_MAXMVOLT; +/* estimated remaining time in minutes */ +static int powermgmt_est_runningtime_min = BATT_MAXRUNTIME; + +static void battery_status_update(void) +{ + static time_t last_change = 0; + time_t now; + + time(&now); + + if (last_change < now) { + last_change = now; + + battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) / + (BATT_MAXMVOLT - BATT_MINMVOLT); + + powermgmt_est_runningtime_min = + battery_percent * BATT_MAXRUNTIME / 100; + } + + send_battery_level_event(); +} + +void battery_read_info(int *voltage, int *level) +{ + battery_status_update(); + + if (voltage) + *voltage = battery_millivolts; + + if (level) + *level = battery_percent; +} + +unsigned int battery_voltage(void) +{ + battery_status_update(); + return battery_millivolts; +} + +int battery_level(void) +{ + battery_status_update(); + return battery_percent; +} + +int battery_time(void) +{ + battery_status_update(); + return powermgmt_est_runningtime_min; +} + +bool battery_level_safe(void) +{ + return battery_level() >= 10; +} + +void set_battery_capacity(int capacity) +{ + (void)capacity; +} + +#if BATTERY_TYPES_COUNT > 1 +void set_battery_type(int type) +{ + (void)type; +} +#endif diff --git a/firmware/target/hosted/ypr0/system-target.h b/firmware/target/hosted/ypr0/system-target.h new file mode 100644 index 0000000000..07a3163ea9 --- /dev/null +++ b/firmware/target/hosted/ypr0/system-target.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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__ + +#define disable_irq() +#define enable_irq() +#define disable_irq_save() 0 +#define restore_irq(level) (void)level + +void wait_for_interrupt(void); +void interrupt(void); + +static inline void commit_dcache(void) {} +static inline void commit_discard_dcache(void) {} +static inline void commit_discard_idcache(void) {} + +#define NEED_GENERIC_BYTESWAPS +#endif /* __SYSTEM_TARGET_H__ */ diff --git a/firmware/target/hosted/ypr0/system-ypr0.c b/firmware/target/hosted/ypr0/system-ypr0.c new file mode 100644 index 0000000000..3a2b30339f --- /dev/null +++ b/firmware/target/hosted/ypr0/system-ypr0.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: system-sdl.c 29925 2011-05-25 20:11:03Z thomasjfox $ + * + * Copyright (C) 2006 by Daniel Everton + * + * 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 +#include +#include +#include "system.h" +#include "panic.h" +#include "debug.h" + +#if defined(HAVE_SDL_AUDIO) || defined(HAVE_SDL_THREADS) || defined(HAVE_SDL) +#include +#endif + +#include "ascodec-target.h" + +void sim_do_exit(void) +{ + exit(EXIT_SUCCESS); +} + +void shutdown_hw(void) +{ + /* Something that we need to do before exit on our platform YPR0 */ + ascodec_close(); + sim_do_exit(); +} + +uintptr_t *stackbegin; +uintptr_t *stackend; +void system_init(void) +{ + int *s; + /* fake stack, OS manages size (and growth) */ + stackbegin = stackend = (uintptr_t*)&s; + +#if defined(HAVE_SDL_AUDIO) || defined(HAVE_SDL_THREADS) || defined(HAVE_SDL) + SDL_Init(0); /* need this if using any SDL subsystem */ +#endif + /* Here begins our platform specific initilization for various things */ + ascodec_init(); +} + + +void system_reboot(void) +{ + sim_do_exit(); +} + +void system_exception_wait(void) +{ + system_reboot(); +} + +#ifdef HAVE_ADJUSTABLE_CPU_FREQ +#include +#include "file.h" +/* This is the Linux Kernel CPU governor... */ +static void set_cpu_freq(int speed) +{ + char temp[10]; + int cpu_dev; + cpu_dev = open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed", O_WRONLY); + if (cpu_dev < 0) + return; + write(cpu_dev, temp, sprintf(temp, "%d", speed) + 1); + close(cpu_dev); +} + +void set_cpu_frequency(long frequency) +{ + switch (frequency) + { + case CPUFREQ_MAX: + set_cpu_freq(532000); + cpu_frequency = CPUFREQ_MAX; + break; + case CPUFREQ_NORMAL: + set_cpu_freq(400000); + cpu_frequency = CPUFREQ_NORMAL; + break; + default: + set_cpu_freq(200000); + cpu_frequency = CPUFREQ_DEFAULT; + break; + } +} +#endif diff --git a/firmware/target/hosted/ypr0/usb-target.h b/firmware/target/hosted/ypr0/usb-target.h new file mode 100644 index 0000000000..237d179775 --- /dev/null +++ b/firmware/target/hosted/ypr0/usb-target.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: usb-target.h 29516 2011-03-05 15:31:52Z thomasjfox $ + * + * Copyright (C) 2010 by Thomas Martitz + * + * 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 __USB_TARGET_H__ +#define __USB_TARGET_H__ + +#endif /* __USB_TARGET_H__ */ diff --git a/firmware/target/hosted/ypr0/ypr0.make b/firmware/target/hosted/ypr0/ypr0.make new file mode 100644 index 0000000000..c2114878db --- /dev/null +++ b/firmware/target/hosted/ypr0/ypr0.make @@ -0,0 +1,25 @@ +# __________ __ ___. +# 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) + +.SECONDEXPANSION: # $$(OBJ) is not populated until after this + + +$(BUILDDIR)/rockbox.elf : $$(OBJ) $$(FIRMLIB) $$(VOICESPEEXLIB) $$(SKINLIB) + $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ + -L$(BUILDDIR)/firmware -lfirmware \ + -L$(BUILDDIR)/apps/codecs $(VOICESPEEXLIB:lib%.a=-l%) \ + -L$(BUILDDIR)/lib -lskin_parser \ + $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map + +$(BUILDDIR)/rockbox : $(BUILDDIR)/rockbox.elf + $(call PRINTS,OC $(@F))$(OC) -S -x $< $@ diff --git a/tools/buildzip.pl b/tools/buildzip.pl index ed937d42e4..e17c2f0712 100755 --- a/tools/buildzip.pl +++ b/tools/buildzip.pl @@ -201,7 +201,7 @@ sub make_install { @files = readdir(DIR); closedir(DIR); - foreach my $file (grep (/[a-zA-Z]+\.(txt|config|ignnore)/,@files)) { + foreach my $file (grep (/[a-zA-Z]+\.(txt|config|ignore|sh)/,@files)) { glob_install("$src/$file", "$userdir/"); } return 1; @@ -423,6 +423,11 @@ sub buildzip { # create the file so the database does not try indexing a folder open(IGNORE, ">$temp_dir/database.ignore") || die "can't open database.ignore"; close(IGNORE); + + # the samsung ypr0 has a loader script that's needed in the zip + if ($modelname =~ /samsungypr0/) { + glob_copy("$ROOT/utils/ypr0tools/rockbox.sh", "$temp_dir/"); + } glob_mkdir("$temp_dir/langs"); glob_mkdir("$temp_dir/rocks"); diff --git a/tools/configure b/tools/configure index 895aca8025..1cb4c5b240 100755 --- a/tools/configure +++ b/tools/configure @@ -647,6 +647,26 @@ pandoracc () { GCCOPTS="$GCCOPTS -ffast-math -fsingle-precision-constant" } +ypr0cc () { + + GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib//` + GCCOPTIMIZE='' + LDOPTS="-lasound -lpthread -lm -ldl -lrt $LDOPTS" + GLOBAL_LDOPTS="$GLOBAL_LDOPTS -Wl,-z,defs" + SHARED_LDFLAG="-shared" + SHARED_CFLAGS='' + endian="little" + thread_support="HAVE_SIGALTSTACK_THREADS" + app_type="ypr0" + + # Include path + GCCOPTS="$GCCOPTS -D_GNU_SOURCE=1 -U_FORTIFY_SOURCE -D_REENTRANT" + + # Set up compiler + gccchoice="4.4.6" + prefixtools "arm-ypr0-linux-gnueabi-" +} + androidcc () { if [ -z "$ANDROID_SDK_PATH" ]; then echo "ERROR: You need the Android SDK installed and have the ANDROID_SDK_PATH" @@ -1290,7 +1310,7 @@ cat <&1 | sed -e 's/[^0-9.-]//g'` else - ldver=`$LD --version | head -n 1 | sed -e 's/[^0-9.]//g'` + ldver=`$LD --version | head -n 1 | sed -e 's/\ /\n/g' | tail -n 1` fi if [ -z "$gccver" ]; then diff --git a/tools/root.make b/tools/root.make index f97588f158..dd827d6d3f 100644 --- a/tools/root.make +++ b/tools/root.make @@ -102,6 +102,10 @@ else include $(ROOTDIR)/uisimulator/uisimulator.make endif + ifneq (,$(findstring ypr0,$(APP_TYPE))) + include $(ROOTDIR)/firmware/target/hosted/ypr0/ypr0.make + endif + ifneq (,$(findstring android, $(APP_TYPE))) include $(ROOTDIR)/android/android.make endif diff --git a/utils/ypr0tools/Makefile b/utils/ypr0tools/Makefile new file mode 100644 index 0000000000..efc1de63f2 --- /dev/null +++ b/utils/ypr0tools/Makefile @@ -0,0 +1,13 @@ + +.PHONY: all clean +PROGS = extract_section +CC = gcc +CFLAGS = -O1 -g -W -Wall + + +all: $(PROGS) + $(MAKE) -C cramfs-1.1 + +clean: + $(MAKE) -C cramfs-1.1 clean + rm -f extract_section diff --git a/utils/ypr0tools/MuonEncrypt b/utils/ypr0tools/MuonEncrypt new file mode 100755 index 0000000000000000000000000000000000000000..b1bc12452386c60cfdd1bd59d37339c1c62ca75a GIT binary patch literal 11006 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 + Copyright (C) + + 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 program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/utils/ypr0tools/cramfs-1.1/GNUmakefile b/utils/ypr0tools/cramfs-1.1/GNUmakefile new file mode 100644 index 0000000000..e15fb22f01 --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/GNUmakefile @@ -0,0 +1,12 @@ +CC = gcc +CFLAGS = -W -Wall -O2 -g -Wno-pointer-sign +CPPFLAGS = -I. +LDLIBS = -lz +PROGS = mkcramfs cramfsck + +all: $(PROGS) + +distclean clean: + rm -f $(PROGS) + +.PHONY: all clean diff --git a/utils/ypr0tools/cramfs-1.1/NOTES b/utils/ypr0tools/cramfs-1.1/NOTES new file mode 100644 index 0000000000..445d1c2d76 --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/NOTES @@ -0,0 +1,168 @@ +Notes on Filesystem Layout +-------------------------- + +These notes describe what mkcramfs generates. Kernel requirements are +a bit looser, e.g. it doesn't care if the items are +swapped around (though it does care that directory entries (inodes) in +a given directory are contiguous, as this is used by readdir). + +All data is currently in host-endian format; neither mkcramfs nor the +kernel ever do swabbing. (See section `Block Size' below.) + +: + + + + +: struct cramfs_super (see cramfs_fs.h). + +: + For each file: + struct cramfs_inode (see cramfs_fs.h). + Filename. Not generally null-terminated, but it is + null-padded to a multiple of 4 bytes. + +The order of inode traversal is described as "width-first" (not to be +confused with breadth-first); i.e. like depth-first but listing all of +a directory's entries before recursing down its subdirectories: the +same order as `ls -AUR' (but without the /^\..*:$/ directory header +lines); put another way, the same order as `find -type d -exec +ls -AU1 {} \;'. + +Beginning in 2.4.7, directory entries are sorted. This optimization +allows cramfs_lookup to return more quickly when a filename does not +exist, speeds up user-space directory sorts, etc. + +: + One for each file that's either a symlink or a + regular file of non-zero st_size. + +: + nblocks * + (where nblocks = (st_size - 1) / blksize + 1) + nblocks * + padding to multiple of 4 bytes + +The i'th for a file stores the byte offset of the +*end* of the i'th (i.e. one past the last byte, which is the +same as the start of the (i+1)'th if there is one). The first + immediately follows the last for the file. +s are each 32 bits long. + +The order of 's is a depth-first descent of the directory +tree, i.e. the same order as `find -size +0 \( -type f -o -type l \) +-print'. + + +: The i'th is the output of zlib's compress function +applied to the i'th blksize-sized chunk of the input data. +(For the last of the file, the input may of course be smaller.) +Each may be a different size. (See above.) +s are merely byte-aligned, not generally u32-aligned. + + +Holes +----- + +This kernel supports cramfs holes (i.e. [efficient representation of] +blocks in uncompressed data consisting entirely of NUL bytes), but by +default mkcramfs doesn't test for & create holes, since cramfs in +kernels up to at least 2.3.39 didn't support holes. Run mkcramfs +with -z if you want it to create files that can have holes in them. + + +Tools +----- + +The cramfs user-space tools, including mkcramfs and cramfsck, are +located at . + + +Future Development +================== + +Block Size +---------- + +(Block size in cramfs refers to the size of input data that is +compressed at a time. It's intended to be somewhere around +PAGE_CACHE_SIZE for cramfs_readpage's convenience.) + +The superblock ought to indicate the block size that the fs was +written for, since comments in indicate that +PAGE_CACHE_SIZE may grow in future (if I interpret the comment +correctly). + +Currently, mkcramfs #define's PAGE_CACHE_SIZE as 4096 and uses that +for blksize, whereas Linux-2.3.39 uses its PAGE_CACHE_SIZE, which in +turn is defined as PAGE_SIZE (which can be as large as 32KB on arm). +This discrepancy is a bug, though it's not clear which should be +changed. + +One option is to change mkcramfs to take its PAGE_CACHE_SIZE from +. Personally I don't like this option, but it does +require the least amount of change: just change `#define +PAGE_CACHE_SIZE (4096)' to `#include '. The disadvantage +is that the generated cramfs cannot always be shared between different +kernels, not even necessarily kernels of the same architecture if +PAGE_CACHE_SIZE is subject to change between kernel versions +(currently possible with arm and ia64). + +The remaining options try to make cramfs more sharable. + +One part of that is addressing endianness. The two options here are +`always use little-endian' (like ext2fs) or `writer chooses +endianness; kernel adapts at runtime'. Little-endian wins because of +code simplicity and little CPU overhead even on big-endian machines. + +The cost of swabbing is changing the code to use the le32_to_cpu +etc. macros as used by ext2fs. We don't need to swab the compressed +data, only the superblock, inodes and block pointers. + + +The other part of making cramfs more sharable is choosing a block +size. The options are: + + 1. Always 4096 bytes. + + 2. Writer chooses blocksize; kernel adapts but rejects blocksize > + PAGE_CACHE_SIZE. + + 3. Writer chooses blocksize; kernel adapts even to blocksize > + PAGE_CACHE_SIZE. + +It's easy enough to change the kernel to use a smaller value than +PAGE_CACHE_SIZE: just make cramfs_readpage read multiple blocks. + +The cost of option 1 is that kernels with a larger PAGE_CACHE_SIZE +value don't get as good compression as they can. + +The cost of option 2 relative to option 1 is that the code uses +variables instead of #define'd constants. The gain is that people +with kernels having larger PAGE_CACHE_SIZE can make use of that if +they don't mind their cramfs being inaccessible to kernels with +smaller PAGE_CACHE_SIZE values. + +Option 3 is easy to implement if we don't mind being CPU-inefficient: +e.g. get readpage to decompress to a buffer of size MAX_BLKSIZE (which +must be no larger than 32KB) and discard what it doesn't need. +Getting readpage to read into all the covered pages is harder. + +The main advantage of option 3 over 1, 2, is better compression. The +cost is greater complexity. Probably not worth it, but I hope someone +will disagree. (If it is implemented, then I'll re-use that code in +e2compr.) + + +Another cost of 2 and 3 over 1 is making mkcramfs use a different +block size, but that just means adding and parsing a -b option. + + +Inode Size +---------- + +Given that cramfs will probably be used for CDs etc. as well as just +silicon ROMs, it might make sense to expand the inode a little from +its current 12 bytes. Inodes other than the root inode are followed +by filename, so the expansion doesn't even have to be a multiple of 4 +bytes. diff --git a/utils/ypr0tools/cramfs-1.1/README b/utils/ypr0tools/cramfs-1.1/README new file mode 100644 index 0000000000..31f53f0ab9 --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/README @@ -0,0 +1,76 @@ + + Cramfs - cram a filesystem onto a small ROM + +cramfs is designed to be simple and small, and to compress things well. + +It uses the zlib routines to compress a file one page at a time, and +allows random page access. The meta-data is not compressed, but is +expressed in a very terse representation to make it use much less +diskspace than traditional filesystems. + +You can't write to a cramfs filesystem (making it compressible and +compact also makes it _very_ hard to update on-the-fly), so you have to +create the disk image with the "mkcramfs" utility. + + +Usage Notes +----------- + +File sizes are limited to less than 16MB. + +Maximum filesystem size is a little over 256MB. (The last file on the +filesystem is allowed to extend past 256MB.) + +Only the low 8 bits of gid are stored. The current version of +mkcramfs simply truncates to 8 bits, which is a potential security +issue. + +Hard links are supported, but hard linked files +will still have a link count of 1 in the cramfs image. + +Cramfs directories have no `.' or `..' entries. Directories (like +every other file on cramfs) always have a link count of 1. (There's +no need to use -noleaf in `find', btw.) + +No timestamps are stored in a cramfs, so these default to the epoch +(1970 GMT). Recently-accessed files may have updated timestamps, but +the update lasts only as long as the inode is cached in memory, after +which the timestamp reverts to 1970, i.e. moves backwards in time. + +Currently, cramfs must be written and read with architectures of the +same endianness, and can be read only by kernels with PAGE_CACHE_SIZE +== 4096. At least the latter of these is a bug, but it hasn't been +decided what the best fix is. For the moment if you have larger pages +you can just change the #define in mkcramfs.c, so long as you don't +mind the filesystem becoming unreadable to future kernels. + + +For /usr/share/magic +-------------------- + +0 ulelong 0x28cd3d45 Linux cramfs offset 0 +>4 ulelong x size %d +>8 ulelong x flags 0x%x +>12 ulelong x future 0x%x +>16 string >\0 signature "%.16s" +>32 ulelong x fsid.crc 0x%x +>36 ulelong x fsid.edition %d +>40 ulelong x fsid.blocks %d +>44 ulelong x fsid.files %d +>48 string >\0 name "%.16s" +512 ulelong 0x28cd3d45 Linux cramfs offset 512 +>516 ulelong x size %d +>520 ulelong x flags 0x%x +>524 ulelong x future 0x%x +>528 string >\0 signature "%.16s" +>544 ulelong x fsid.crc 0x%x +>548 ulelong x fsid.edition %d +>552 ulelong x fsid.blocks %d +>556 ulelong x fsid.files %d +>560 string >\0 name "%.16s" + + +Hacker Notes +------------ + +See fs/cramfs/README for filesystem layout and implementation notes. diff --git a/utils/ypr0tools/cramfs-1.1/cramfsck.c b/utils/ypr0tools/cramfs-1.1/cramfsck.c new file mode 100644 index 0000000000..aef017a4b4 --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/cramfsck.c @@ -0,0 +1,716 @@ +/* + * cramfsck - check a cramfs file system + * + * Copyright (C) 2000-2002 Transmeta Corporation + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * 1999/12/03: Linus Torvalds (cramfs tester and unarchive program) + * 2000/06/03: Daniel Quinlan (CRC and length checking program) + * 2000/06/04: Daniel Quinlan (merged programs, added options, support + * for special files, preserve permissions and + * ownership, cramfs superblock v2, bogus mode + * test, pathname length test, etc.) + * 2000/06/06: Daniel Quinlan (support for holes, pretty-printing, + * symlink size test) + * 2000/07/11: Daniel Quinlan (file length tests, start at offset 0 or 512, + * fsck-compatible exit codes) + * 2000/07/15: Daniel Quinlan (initial support for block devices) + * 2002/01/10: Daniel Quinlan (additional checks, test more return codes, + * use read if mmap fails, standardize messages) + */ + +/* compile-time options */ +#define INCLUDE_FS_TESTS /* include cramfs checking and extraction */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#define _LINUX_STRING_H_ +#include +#include +#include + +/* Exit codes used by fsck-type programs */ +#define FSCK_OK 0 /* No errors */ +#define FSCK_NONDESTRUCT 1 /* File system errors corrected */ +#define FSCK_REBOOT 2 /* System should be rebooted */ +#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */ +#define FSCK_ERROR 8 /* Operational error */ +#define FSCK_USAGE 16 /* Usage or syntax error */ +#define FSCK_LIBRARY 128 /* Shared library error */ + +#define PAD_SIZE 512 + +#define PAGE_CACHE_SIZE page_size + +static const char *progname = "cramfsck"; + +static int fd; /* ROM image file descriptor */ +static char *filename; /* ROM image filename */ +struct cramfs_super super; /* just find the cramfs superblock once */ +static int opt_verbose = 0; /* 1 = verbose (-v), 2+ = very verbose (-vv) */ +#ifdef INCLUDE_FS_TESTS +static int opt_extract = 0; /* extract cramfs (-x) */ +static char *extract_dir = "root"; /* extraction directory (-x) */ +static uid_t euid; /* effective UID */ + +/* (cramfs_super + start) <= start_dir < end_dir <= start_data <= end_data */ +static unsigned long start_dir = ~0UL; /* start of first non-root inode */ +static unsigned long end_dir = 0; /* end of the directory structure */ +static unsigned long start_data = ~0UL; /* start of the data (256 MB = max) */ +static unsigned long end_data = 0; /* end of the data */ + +/* Guarantee access to at least 8kB at a time */ +#define ROMBUFFER_BITS 13 +#define ROMBUFFERSIZE (1 << ROMBUFFER_BITS) +#define ROMBUFFERMASK (ROMBUFFERSIZE-1) +static char read_buffer[ROMBUFFERSIZE * 2]; +static unsigned long read_buffer_block = ~0UL; + +/* Uncompressing data structures... */ +static char *outbuffer; +static z_stream stream; + +static size_t page_size; + +/* Prototypes */ +static void expand_fs(char *, struct cramfs_inode *); +#endif /* INCLUDE_FS_TESTS */ + +/* Input status of 0 to print help and exit without an error. */ +static void usage(int status) +{ + FILE *stream = status ? stderr : stdout; + + fprintf(stream, "usage: %s [-hv] [-x dir] file\n" + " -h print this help\n" + " -x dir extract into dir\n" + " -v be more verbose\n" + " file file to test\n", progname); + + exit(status); +} + +static void die(int status, int syserr, const char *fmt, ...) +{ + va_list arg_ptr; + int save = errno; + + fflush(0); + va_start(arg_ptr, fmt); + fprintf(stderr, "%s: ", progname); + vfprintf(stderr, fmt, arg_ptr); + if (syserr) { + fprintf(stderr, ": %s", strerror(save)); + } + fprintf(stderr, "\n"); + va_end(arg_ptr); + exit(status); +} + +static void test_super(int *start, size_t *length) { + struct stat st; + + /* find the physical size of the file or block device */ + if (stat(filename, &st) < 0) { + die(FSCK_ERROR, 1, "stat failed: %s", filename); + } + fd = open(filename, O_RDONLY); + if (fd < 0) { + die(FSCK_ERROR, 1, "open failed: %s", filename); + } + if (S_ISBLK(st.st_mode)) { + if (ioctl(fd, BLKGETSIZE, length) < 0) { + die(FSCK_ERROR, 1, "ioctl failed: unable to determine device size: %s", filename); + } + *length = *length * 512; + } + else if (S_ISREG(st.st_mode)) { + *length = st.st_size; + } + else { + die(FSCK_ERROR, 0, "not a block device or file: %s", filename); + } + + if (*length < sizeof(struct cramfs_super)) { + die(FSCK_UNCORRECTED, 0, "file length too short"); + } + + /* find superblock */ + if (read(fd, &super, sizeof(super)) != sizeof(super)) { + die(FSCK_ERROR, 1, "read failed: %s", filename); + } + if (super.magic == CRAMFS_MAGIC) { + *start = 0; + } + else if (*length >= (PAD_SIZE + sizeof(super))) { + lseek(fd, PAD_SIZE, SEEK_SET); + if (read(fd, &super, sizeof(super)) != sizeof(super)) { + die(FSCK_ERROR, 1, "read failed: %s", filename); + } + if (super.magic == CRAMFS_MAGIC) { + *start = PAD_SIZE; + } + } + + /* superblock tests */ + if (super.magic != CRAMFS_MAGIC) { + die(FSCK_UNCORRECTED, 0, "superblock magic not found"); + } + if (super.flags & ~CRAMFS_SUPPORTED_FLAGS) { + die(FSCK_ERROR, 0, "unsupported filesystem features"); + } + if (super.size < PAGE_CACHE_SIZE) { + die(FSCK_UNCORRECTED, 0, "superblock size (%d) too small", super.size); + } + if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { + if (super.fsid.files == 0) { + die(FSCK_UNCORRECTED, 0, "zero file count"); + } + if (*length < super.size) { + die(FSCK_UNCORRECTED, 0, "file length too short"); + } + else if (*length > super.size) { + fprintf(stderr, "warning: file extends past end of filesystem\n"); + } + } + else { + fprintf(stderr, "warning: old cramfs format\n"); + } +} + +static void test_crc(int start) +{ + void *buf; + u32 crc; + + if (!(super.flags & CRAMFS_FLAG_FSID_VERSION_2)) { +#ifdef INCLUDE_FS_TESTS + return; +#else /* not INCLUDE_FS_TESTS */ + die(FSCK_USAGE, 0, "unable to test CRC: old cramfs format"); +#endif /* not INCLUDE_FS_TESTS */ + } + + crc = crc32(0L, Z_NULL, 0); + + buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); + if (buf == MAP_FAILED) { + buf = mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (buf != MAP_FAILED) { + lseek(fd, 0, SEEK_SET); + read(fd, buf, super.size); + } + } + if (buf != MAP_FAILED) { + ((struct cramfs_super *) (buf+start))->fsid.crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, buf+start, super.size-start); + munmap(buf, super.size); + } + else { + int retval; + size_t length = 0; + + buf = malloc(4096); + if (!buf) { + die(FSCK_ERROR, 1, "malloc failed"); + } + lseek(fd, start, SEEK_SET); + for (;;) { + retval = read(fd, buf, 4096); + if (retval < 0) { + die(FSCK_ERROR, 1, "read failed: %s", filename); + } + else if (retval == 0) { + break; + } + if (length == 0) { + ((struct cramfs_super *) buf)->fsid.crc = crc32(0L, Z_NULL, 0); + } + length += retval; + if (length > (super.size-start)) { + crc = crc32(crc, buf, retval - (length - (super.size-start))); + break; + } + crc = crc32(crc, buf, retval); + } + free(buf); + } + + if (crc != super.fsid.crc) { + die(FSCK_UNCORRECTED, 0, "crc error"); + } +} + +#ifdef INCLUDE_FS_TESTS +static void print_node(char type, struct cramfs_inode *i, char *name) +{ + char info[10]; + + if (S_ISCHR(i->mode) || (S_ISBLK(i->mode))) { + /* major/minor numbers can be as high as 2^12 or 4096 */ + snprintf(info, 10, "%4d,%4d", major(i->size), minor(i->size)); + } + else { + /* size be as high as 2^24 or 16777216 */ + snprintf(info, 10, "%9d", i->size); + } + + printf("%c %04o %s %5d:%-3d %s\n", + type, i->mode & ~S_IFMT, info, i->uid, i->gid, name); +} + +/* + * Create a fake "blocked" access + */ +static void *romfs_read(unsigned long offset) +{ + unsigned int block = offset >> ROMBUFFER_BITS; + if (block != read_buffer_block) { + read_buffer_block = block; + lseek(fd, block << ROMBUFFER_BITS, SEEK_SET); + read(fd, read_buffer, ROMBUFFERSIZE * 2); + } + return read_buffer + (offset & ROMBUFFERMASK); +} + +static struct cramfs_inode *cramfs_iget(struct cramfs_inode * i) +{ + struct cramfs_inode *inode = malloc(sizeof(struct cramfs_inode)); + + if (!inode) { + die(FSCK_ERROR, 1, "malloc failed"); + } + *inode = *i; + return inode; +} + +static struct cramfs_inode *iget(unsigned int ino) +{ + return cramfs_iget(romfs_read(ino)); +} + +static void iput(struct cramfs_inode *inode) +{ + free(inode); +} + +/* + * Return the offset of the root directory + */ +static struct cramfs_inode *read_super(void) +{ + unsigned long offset = super.root.offset << 2; + + if (!S_ISDIR(super.root.mode)) + die(FSCK_UNCORRECTED, 0, "root inode is not directory"); + if (!(super.flags & CRAMFS_FLAG_SHIFTED_ROOT_OFFSET) && + ((offset != sizeof(struct cramfs_super)) && + (offset != PAD_SIZE + sizeof(struct cramfs_super)))) + { + die(FSCK_UNCORRECTED, 0, "bad root offset (%lu)", offset); + } + return cramfs_iget(&super.root); +} + +static int uncompress_block(void *src, int len) +{ + int err; + + stream.next_in = src; + stream.avail_in = len; + + stream.next_out = (unsigned char *) outbuffer; + stream.avail_out = PAGE_CACHE_SIZE*2; + + inflateReset(&stream); + + if (len > PAGE_CACHE_SIZE*2) { + die(FSCK_UNCORRECTED, 0, "data block too large"); + } + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + die(FSCK_UNCORRECTED, 0, "decompression error %p(%d): %s", + zError(err), src, len); + } + return stream.total_out; +} + +static void do_uncompress(char *path, int fd, unsigned long offset, unsigned long size) +{ + unsigned long curr = offset + 4 * ((size + PAGE_CACHE_SIZE - 1) / PAGE_CACHE_SIZE); + + do { + unsigned long out = PAGE_CACHE_SIZE; + unsigned long next = *(u32 *) romfs_read(offset); + + if (next > end_data) { + end_data = next; + } + + offset += 4; + if (curr == next) { + if (opt_verbose > 1) { + printf(" hole at %ld (%d)\n", curr, PAGE_CACHE_SIZE); + } + if (size < PAGE_CACHE_SIZE) + out = size; + memset(outbuffer, 0x00, out); + } + else { + if (opt_verbose > 1) { + printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); + } + out = uncompress_block(romfs_read(curr), next - curr); + } + if (size >= PAGE_CACHE_SIZE) { + if (out != PAGE_CACHE_SIZE) { + die(FSCK_UNCORRECTED, 0, "non-block (%ld) bytes", out); + } + } else { + if (out != size) { + die(FSCK_UNCORRECTED, 0, "non-size (%ld vs %ld) bytes", out, size); + } + } + size -= out; + if (opt_extract) { + if (write(fd, outbuffer, out) < 0) { + die(FSCK_ERROR, 1, "write failed: %s", path); + } + } + curr = next; + } while (size); +} + +static void change_file_status(char *path, struct cramfs_inode *i) +{ + struct utimbuf epoch = { 0, 0 }; + + if (euid == 0) { + if (lchown(path, i->uid, i->gid) < 0) { + die(FSCK_ERROR, 1, "lchown failed: %s", path); + } + if (S_ISLNK(i->mode)) + return; + if ((S_ISUID | S_ISGID) & i->mode) { + if (chmod(path, i->mode) < 0) { + die(FSCK_ERROR, 1, "chown failed: %s", path); + } + } + } + if (S_ISLNK(i->mode)) + return; + if (utime(path, &epoch) < 0) { + die(FSCK_ERROR, 1, "utime failed: %s", path); + } +} + +static void do_directory(char *path, struct cramfs_inode *i) +{ + int pathlen = strlen(path); + int count = i->size; + unsigned long offset = i->offset << 2; + char *newpath = malloc(pathlen + 256); + + if (!newpath) { + die(FSCK_ERROR, 1, "malloc failed"); + } + if (offset == 0 && count != 0) { + die(FSCK_UNCORRECTED, 0, "directory inode has zero offset and non-zero size: %s", path); + } + if (offset != 0 && offset < start_dir) { + start_dir = offset; + } + /* TODO: Do we need to check end_dir for empty case? */ + memcpy(newpath, path, pathlen); + newpath[pathlen] = '/'; + pathlen++; + if (opt_verbose) { + print_node('d', i, path); + } + if (opt_extract) { + if (mkdir(path, i->mode) < 0) { + die(FSCK_ERROR, 1, "mkdir failed: %s", path); + } + change_file_status(path, i); + } + while (count > 0) { + struct cramfs_inode *child = iget(offset); + int size; + int newlen = child->namelen << 2; + + size = sizeof(struct cramfs_inode) + newlen; + count -= size; + + offset += sizeof(struct cramfs_inode); + + memcpy(newpath + pathlen, romfs_read(offset), newlen); + newpath[pathlen + newlen] = 0; + if (newlen == 0) { + die(FSCK_UNCORRECTED, 0, "filename length is zero"); + } + if ((pathlen + newlen) - strlen(newpath) > 3) { + die(FSCK_UNCORRECTED, 0, "bad filename length"); + } + expand_fs(newpath, child); + + offset += newlen; + + if (offset <= start_dir) { + die(FSCK_UNCORRECTED, 0, "bad inode offset"); + } + if (offset > end_dir) { + end_dir = offset; + } + iput(child); /* free(child) */ + } + free(newpath); +} + +static void do_file(char *path, struct cramfs_inode *i) +{ + unsigned long offset = i->offset << 2; + int fd = 0; + + if (offset == 0 && i->size != 0) { + die(FSCK_UNCORRECTED, 0, "file inode has zero offset and non-zero size"); + } + if (i->size == 0 && offset != 0) { + die(FSCK_UNCORRECTED, 0, "file inode has zero size and non-zero offset"); + } + if (offset != 0 && offset < start_data) { + start_data = offset; + } + if (opt_verbose) { + print_node('f', i, path); + } + if (opt_extract) { + fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, i->mode); + if (fd < 0) { + die(FSCK_ERROR, 1, "open failed: %s", path); + } + } + if (i->size) { + do_uncompress(path, fd, offset, i->size); + } + if (opt_extract) { + close(fd); + change_file_status(path, i); + } +} + +static void do_symlink(char *path, struct cramfs_inode *i) +{ + unsigned long offset = i->offset << 2; + unsigned long curr = offset + 4; + unsigned long next = *(u32 *) romfs_read(offset); + unsigned long size; + + if (offset == 0) { + die(FSCK_UNCORRECTED, 0, "symbolic link has zero offset"); + } + if (i->size == 0) { + die(FSCK_UNCORRECTED, 0, "symbolic link has zero size"); + } + + if (offset < start_data) { + start_data = offset; + } + if (next > end_data) { + end_data = next; + } + + size = uncompress_block(romfs_read(curr), next - curr); + if (size != i->size) { + die(FSCK_UNCORRECTED, 0, "size error in symlink: %s", path); + } + outbuffer[size] = 0; + if (opt_verbose) { + char *str; + + asprintf(&str, "%s -> %s", path, outbuffer); + print_node('l', i, str); + if (opt_verbose > 1) { + printf(" uncompressing block at %ld to %ld (%ld)\n", curr, next, next - curr); + } + free(str); + } + if (opt_extract) { + if (symlink(outbuffer, path) < 0) { + die(FSCK_ERROR, 1, "symlink failed: %s", path); + } + change_file_status(path, i); + } +} + +static void do_special_inode(char *path, struct cramfs_inode *i) +{ + dev_t devtype = 0; + char type; + + if (i->offset) { /* no need to shift offset */ + die(FSCK_UNCORRECTED, 0, "special file has non-zero offset: %s", path); + } + if (S_ISCHR(i->mode)) { + devtype = i->size; + type = 'c'; + } + else if (S_ISBLK(i->mode)) { + devtype = i->size; + type = 'b'; + } + else if (S_ISFIFO(i->mode)) { + if (i->size != 0) { + die(FSCK_UNCORRECTED, 0, "fifo has non-zero size: %s", path); + } + type = 'p'; + } + else if (S_ISSOCK(i->mode)) { + if (i->size != 0) { + die(FSCK_UNCORRECTED, 0, "socket has non-zero size: %s", path); + } + type = 's'; + } + else { + die(FSCK_UNCORRECTED, 0, "bogus mode: %s (%o)", path, i->mode); + return; /* not reached */ + } + + if (opt_verbose) { + print_node(type, i, path); + } + + if (opt_extract) { + if (mknod(path, i->mode, devtype) < 0) { + die(FSCK_ERROR, 1, "mknod failed: %s", path); + } + change_file_status(path, i); + } +} + +static void expand_fs(char *path, struct cramfs_inode *inode) +{ + if (S_ISDIR(inode->mode)) { + do_directory(path, inode); + } + else if (S_ISREG(inode->mode)) { + do_file(path, inode); + } + else if (S_ISLNK(inode->mode)) { + do_symlink(path, inode); + } + else { + do_special_inode(path, inode); + } +} + +static void test_fs(int start) +{ + struct cramfs_inode *root; + + root = read_super(); + umask(0); + euid = geteuid(); + stream.next_in = NULL; + stream.avail_in = 0; + inflateInit(&stream); + expand_fs(extract_dir, root); + inflateEnd(&stream); + if (start_data != ~0UL) { + if (start_data < (sizeof(struct cramfs_super) + start)) { + die(FSCK_UNCORRECTED, 0, "directory data start (%ld) < sizeof(struct cramfs_super) + start (%ld)", start_data, sizeof(struct cramfs_super) + start); + } + if (end_dir != start_data) { + die(FSCK_UNCORRECTED, 0, "directory data end (%ld) != file data start (%ld)", end_dir, start_data); + } + } + if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) { + if (end_data > super.size) { + die(FSCK_UNCORRECTED, 0, "invalid file data offset"); + } + } + iput(root); /* free(root) */ +} +#endif /* INCLUDE_FS_TESTS */ + +int main(int argc, char **argv) +{ + int c; /* for getopt */ + int start = 0; + size_t length; + + page_size = sysconf(_SC_PAGESIZE); + + if (argc) + progname = argv[0]; + + outbuffer = malloc(page_size * 2); + if (!outbuffer) + die(FSCK_ERROR, 1, "failed to allocate outbuffer"); + + /* command line options */ + while ((c = getopt(argc, argv, "hx:v")) != EOF) { + switch (c) { + case 'h': + usage(FSCK_OK); + case 'x': +#ifdef INCLUDE_FS_TESTS + opt_extract = 1; + extract_dir = optarg; + break; +#else /* not INCLUDE_FS_TESTS */ + die(FSCK_USAGE, 0, "compiled without -x support"); +#endif /* not INCLUDE_FS_TESTS */ + case 'v': + opt_verbose++; + break; + } + } + + if ((argc - optind) != 1) + usage(FSCK_USAGE); + filename = argv[optind]; + + test_super(&start, &length); + test_crc(start); +#ifdef INCLUDE_FS_TESTS + test_fs(start); +#endif /* INCLUDE_FS_TESTS */ + + if (opt_verbose) { + printf("%s: OK\n", filename); + } + + exit(FSCK_OK); +} + +/* + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/utils/ypr0tools/cramfs-1.1/linux/cramfs_fs.h b/utils/ypr0tools/cramfs-1.1/linux/cramfs_fs.h new file mode 100644 index 0000000000..a8948f34b7 --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/linux/cramfs_fs.h @@ -0,0 +1,98 @@ +#ifndef __CRAMFS_H +#define __CRAMFS_H + +#ifndef __KERNEL__ + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; + +#endif + +#define CRAMFS_MAGIC 0x28cd3d45 /* some random number */ +#define CRAMFS_SIGNATURE "Compressed ROMFS" + +/* + * Width of various bitfields in struct cramfs_inode. + * Primarily used to generate warnings in mkcramfs. + */ +#define CRAMFS_MODE_WIDTH 16 +#define CRAMFS_UID_WIDTH 16 +#define CRAMFS_SIZE_WIDTH 24 +#define CRAMFS_GID_WIDTH 8 +#define CRAMFS_NAMELEN_WIDTH 6 +#define CRAMFS_OFFSET_WIDTH 26 + +/* + * Since inode.namelen is a unsigned 6-bit number, the maximum cramfs + * path length is 63 << 2 = 252. + */ +#define CRAMFS_MAXPATHLEN (((1 << CRAMFS_NAMELEN_WIDTH) - 1) << 2) + +/* + * Reasonably terse representation of the inode data. + */ +struct cramfs_inode { + u32 mode:CRAMFS_MODE_WIDTH, uid:CRAMFS_UID_WIDTH; + /* SIZE for device files is i_rdev */ + u32 size:CRAMFS_SIZE_WIDTH, gid:CRAMFS_GID_WIDTH; + /* NAMELEN is the length of the file name, divided by 4 and + rounded up. (cramfs doesn't support hard links.) */ + /* OFFSET: For symlinks and non-empty regular files, this + contains the offset (divided by 4) of the file data in + compressed form (starting with an array of block pointers; + see README). For non-empty directories it is the offset + (divided by 4) of the inode of the first file in that + directory. For anything else, offset is zero. */ + u32 namelen:CRAMFS_NAMELEN_WIDTH, offset:CRAMFS_OFFSET_WIDTH; +}; + +struct cramfs_info { + u32 crc; + u32 edition; + u32 blocks; + u32 files; +}; + +/* + * Superblock information at the beginning of the FS. + */ +struct cramfs_super { + u32 magic; /* 0x28cd3d45 - random number */ + u32 size; /* length in bytes */ + u32 flags; /* feature flags */ + u32 future; /* reserved for future use */ + u8 signature[16]; /* "Compressed ROMFS" */ + struct cramfs_info fsid; /* unique filesystem info */ + u8 name[16]; /* user-defined name */ + struct cramfs_inode root; /* root inode data */ +}; + +/* + * Feature flags + * + * 0x00000000 - 0x000000ff: features that work for all past kernels + * 0x00000100 - 0xffffffff: features that don't work for past kernels + */ +#define CRAMFS_FLAG_FSID_VERSION_2 0x00000001 /* fsid version #2 */ +#define CRAMFS_FLAG_SORTED_DIRS 0x00000002 /* sorted dirs */ +#define CRAMFS_FLAG_HOLES 0x00000100 /* support for holes */ +#define CRAMFS_FLAG_WRONG_SIGNATURE 0x00000200 /* reserved */ +#define CRAMFS_FLAG_SHIFTED_ROOT_OFFSET 0x00000400 /* shifted root fs */ + +/* + * Valid values in super.flags. Currently we refuse to mount + * if (flags & ~CRAMFS_SUPPORTED_FLAGS). Maybe that should be + * changed to test super.future instead. + */ +#define CRAMFS_SUPPORTED_FLAGS ( 0x000000ff \ + | CRAMFS_FLAG_HOLES \ + | CRAMFS_FLAG_WRONG_SIGNATURE \ + | CRAMFS_FLAG_SHIFTED_ROOT_OFFSET ) + +/* Uncompression interfaces to the underlying zlib */ +int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen); +int cramfs_uncompress_init(void); +int cramfs_uncompress_exit(void); + +#endif diff --git a/utils/ypr0tools/cramfs-1.1/linux/cramfs_fs_sb.h b/utils/ypr0tools/cramfs-1.1/linux/cramfs_fs_sb.h new file mode 100644 index 0000000000..afea368796 --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/linux/cramfs_fs_sb.h @@ -0,0 +1,15 @@ +#ifndef _CRAMFS_FS_SB +#define _CRAMFS_FS_SB + +/* + * cramfs super-block data in memory + */ +struct cramfs_sb_info { + unsigned long magic; + unsigned long size; + unsigned long blocks; + unsigned long files; + unsigned long flags; +}; + +#endif diff --git a/utils/ypr0tools/cramfs-1.1/mkcramfs.c b/utils/ypr0tools/cramfs-1.1/mkcramfs.c new file mode 100644 index 0000000000..2eccb733be --- /dev/null +++ b/utils/ypr0tools/cramfs-1.1/mkcramfs.c @@ -0,0 +1,889 @@ +/* + * mkcramfs - make a cramfs file system + * + * Copyright (C) 1999-2002 Transmeta Corporation + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * If you change the disk format of cramfs, please update fs/cramfs/README. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Exit codes used by mkfs-type programs */ +#define MKFS_OK 0 /* No errors */ +#define MKFS_ERROR 8 /* Operational error */ +#define MKFS_USAGE 16 /* Usage or syntax error */ + +/* The kernel only supports PAD_SIZE of 0 and 512. */ +#define PAD_SIZE 512 + +/* + * The longest filename component to allow for in the input directory tree. + * ext2fs (and many others) allow up to 255 bytes. A couple of filesystems + * allow longer (e.g. smbfs 1024), but there isn't much use in supporting + * >255-byte names in the input directory tree given that such names get + * truncated to CRAMFS_MAXPATHLEN (252 bytes) when written to cramfs. + * + * Old versions of mkcramfs generated corrupted filesystems if any input + * filenames exceeded CRAMFS_MAXPATHLEN (252 bytes), however old + * versions of cramfsck seem to have been able to detect the corruption. + */ +#define MAX_INPUT_NAMELEN 255 + +/* + * Maximum size fs you can create is roughly 256MB. (The last file's + * data must begin within 256MB boundary but can extend beyond that.) + * + * Note that if you want it to fit in a ROM then you're limited to what the + * hardware and kernel can support. + */ +#define MAXFSLEN ((((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */ \ + + (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */ \ + + (1 << CRAMFS_SIZE_WIDTH) * 4 / blksize /* block pointers */ ) + +static const char *progname = "mkcramfs"; +static unsigned int blksize; +static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */ +static int image_length = 0; + +/* + * If opt_holes is set, then mkcramfs can create explicit holes in the + * data, which saves 26 bytes per hole (which is a lot smaller a + * saving than most most filesystems). + * + * Note that kernels up to at least 2.3.39 don't support cramfs holes, + * which is why this is turned off by default. + * + * If opt_verbose is 1, be verbose. If it is higher, be even more verbose. + */ +static u32 opt_edition = 0; +static int opt_errors = 0; +static int opt_holes = 0; +static int opt_pad = 0; +static int opt_verbose = 0; +static char *opt_image = NULL; +static char *opt_name = NULL; + +static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid; + +/* In-core version of inode / directory entry. */ +struct entry { + /* stats */ + unsigned char *name; + unsigned int mode, size, uid, gid; + + /* these are only used for non-empty files */ + char *path; /* always null except non-empty files */ + int fd; /* temporarily open files while mmapped */ + + /* FS data */ + void *uncompressed; + /* points to other identical file */ + struct entry *same; + unsigned int offset; /* pointer to compressed data in archive */ + unsigned int dir_offset; /* Where in the archive is the directory entry? */ + + /* organization */ + struct entry *child; /* null for non-directories and empty directories */ + struct entry *next; +}; + +/* Input status of 0 to print help and exit without an error. */ +static void usage(int status) +{ + FILE *stream = status ? stderr : stdout; + + fprintf(stream, "usage: %s [-h] [-b blksize] [-e edition] [-i file] [-n name] dirname outfile\n" + " -h print this help\n" + " -E make all warnings errors (non-zero exit status)\n" + " -b blksize blocksize to use\n" + " -e edition set edition number (part of fsid)\n" + " -i file insert a file image into the filesystem (requires >= 2.4.0)\n" + " -n name set name of cramfs filesystem\n" + " -p pad by %d bytes for boot code\n" + " -s sort directory entries (old option, ignored)\n" + " -v be more verbose\n" + " -z make explicit holes (requires >= 2.3.39)\n" + " dirname root of the directory tree to be compressed\n" + " outfile output file\n", progname, PAD_SIZE); + + exit(status); +} + +static void die(int status, int syserr, const char *fmt, ...) +{ + va_list arg_ptr; + int save = errno; + + fflush(0); + va_start(arg_ptr, fmt); + fprintf(stderr, "%s: ", progname); + vfprintf(stderr, fmt, arg_ptr); + if (syserr) { + fprintf(stderr, ": %s", strerror(save)); + } + fprintf(stderr, "\n"); + va_end(arg_ptr); + exit(status); +} + +static void map_entry(struct entry *entry) +{ + if (entry->path) { + entry->fd = open(entry->path, O_RDONLY); + if (entry->fd < 0) { + die(MKFS_ERROR, 1, "open failed: %s", entry->path); + } + entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, entry->fd, 0); + if (entry->uncompressed == MAP_FAILED) { + die(MKFS_ERROR, 1, "mmap failed: %s", entry->path); + } + } +} + +static void unmap_entry(struct entry *entry) +{ + if (entry->path) { + if (munmap(entry->uncompressed, entry->size) < 0) { + die(MKFS_ERROR, 1, "munmap failed: %s", entry->path); + } + close(entry->fd); + } +} + +static int find_identical_file(struct entry *orig, struct entry *newfile) +{ + if (orig == newfile) + return 1; + if (!orig) + return 0; + if (orig->size == newfile->size && (orig->path || orig->uncompressed)) + { + map_entry(orig); + map_entry(newfile); + if (!memcmp(orig->uncompressed, newfile->uncompressed, orig->size)) + { + newfile->same = orig; + unmap_entry(newfile); + unmap_entry(orig); + return 1; + } + unmap_entry(newfile); + unmap_entry(orig); + } + return (find_identical_file(orig->child, newfile) || + find_identical_file(orig->next, newfile)); +} + +static void eliminate_doubles(struct entry *root, struct entry *orig) { + if (orig) { + if (orig->size && (orig->path || orig->uncompressed)) + find_identical_file(root, orig); + eliminate_doubles(root, orig->child); + eliminate_doubles(root, orig->next); + } +} + +/* + * We define our own sorting function instead of using alphasort which + * uses strcoll and changes ordering based on locale information. + */ +static int cramsort (const void *a, const void *b) +{ + return strcmp ((*(const struct dirent **) a)->d_name, + (*(const struct dirent **) b)->d_name); +} + +static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub) +{ + struct dirent **dirlist; + int totalsize = 0, dircount, dirindex; + char *path, *endpath; + size_t len = strlen(name); + + /* Set up the path. */ + /* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */ + path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1); + if (!path) { + die(MKFS_ERROR, 1, "malloc failed"); + } + memcpy(path, name, len); + endpath = path + len; + *endpath = '/'; + endpath++; + + /* read in the directory and sort */ + dircount = scandir(name, &dirlist, 0, cramsort); + + if (dircount < 0) { + die(MKFS_ERROR, 1, "scandir failed: %s", name); + } + + /* process directory */ + for (dirindex = 0; dirindex < dircount; dirindex++) { + struct dirent *dirent; + struct entry *entry; + struct stat st; + int size; + size_t namelen; + + dirent = dirlist[dirindex]; + + /* Ignore "." and ".." - we won't be adding them to the archive */ + if (dirent->d_name[0] == '.') { + if (dirent->d_name[1] == '\0') + continue; + if (dirent->d_name[1] == '.') { + if (dirent->d_name[2] == '\0') + continue; + } + } + namelen = strlen(dirent->d_name); + if (namelen > MAX_INPUT_NAMELEN) { + die(MKFS_ERROR, 0, + "very long (%u bytes) filename found: %s\n" + "please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile", + namelen, dirent->d_name); + } + memcpy(endpath, dirent->d_name, namelen + 1); + + if (lstat(path, &st) < 0) { + warn_skip = 1; + continue; + } + entry = calloc(1, sizeof(struct entry)); + if (!entry) { + die(MKFS_ERROR, 1, "calloc failed"); + } + entry->name = strdup(dirent->d_name); + if (!entry->name) { + die(MKFS_ERROR, 1, "strdup failed"); + } + /* truncate multi-byte UTF-8 filenames on character boundary */ + if (namelen > CRAMFS_MAXPATHLEN) { + namelen = CRAMFS_MAXPATHLEN; + warn_namelen = 1; + /* the first lost byte must not be a trail byte */ + while ((entry->name[namelen] & 0xc0) == 0x80) { + namelen--; + /* are we reasonably certain it was UTF-8 ? */ + if (entry->name[namelen] < 0x80 || !namelen) { + die(MKFS_ERROR, 0, "cannot truncate filenames not encoded in UTF-8"); + } + } + entry->name[namelen] = '\0'; + } + entry->mode = st.st_mode; + entry->size = st.st_size; + entry->uid = st.st_uid; + if (entry->uid >= 1 << CRAMFS_UID_WIDTH) + warn_uid = 1; + entry->gid = st.st_gid; + if (entry->gid >= 1 << CRAMFS_GID_WIDTH) + /* TODO: We ought to replace with a default + gid instead of truncating; otherwise there + are security problems. Maybe mode should + be &= ~070. Same goes for uid once Linux + supports >16-bit uids. */ + warn_gid = 1; + size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3); + *fslen_ub += size; + if (S_ISDIR(st.st_mode)) { + entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub); + } else if (S_ISREG(st.st_mode)) { + if (entry->size) { + if (access(path, R_OK) < 0) { + warn_skip = 1; + continue; + } + entry->path = strdup(path); + if (!entry->path) { + die(MKFS_ERROR, 1, "strdup failed"); + } + if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) { + warn_size = 1; + entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1; + } + } + } else if (S_ISLNK(st.st_mode)) { + int len; + entry->uncompressed = malloc(entry->size); + if (!entry->uncompressed) { + die(MKFS_ERROR, 1, "malloc failed"); + } + len = readlink(path, entry->uncompressed, entry->size); + if (len < 0) { + warn_skip = 1; + continue; + } + entry->size = len; + } else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) { + /* maybe we should skip sockets */ + entry->size = 0; + } else if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) { + entry->size = st.st_rdev; + if (entry->size & -(1<name); + } + + if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { + int blocks = ((entry->size - 1) / blksize + 1); + + /* block pointers & data expansion allowance + data */ + if (entry->size) + *fslen_ub += (4+26)*blocks + entry->size + 3; + } + + /* Link it into the list */ + *prev = entry; + prev = &entry->next; + totalsize += size; + } + free(path); + free(dirlist); /* allocated by scandir() with malloc() */ + return totalsize; +} + +/* Returns sizeof(struct cramfs_super), which includes the root inode. */ +static unsigned int write_superblock(struct entry *root, char *base, int size) +{ + struct cramfs_super *super = (struct cramfs_super *) base; + unsigned int offset = sizeof(struct cramfs_super) + image_length; + + offset += opt_pad; /* 0 if no padding */ + + super->magic = CRAMFS_MAGIC; + super->flags = CRAMFS_FLAG_FSID_VERSION_2 | CRAMFS_FLAG_SORTED_DIRS; + if (opt_holes) + super->flags |= CRAMFS_FLAG_HOLES; + if (image_length > 0) + super->flags |= CRAMFS_FLAG_SHIFTED_ROOT_OFFSET; + super->size = size; + memcpy(super->signature, CRAMFS_SIGNATURE, sizeof(super->signature)); + + super->fsid.crc = crc32(0L, Z_NULL, 0); + super->fsid.edition = opt_edition; + super->fsid.blocks = total_blocks; + super->fsid.files = total_nodes; + + memset(super->name, 0x00, sizeof(super->name)); + if (opt_name) + strncpy(super->name, opt_name, sizeof(super->name)); + else + strncpy(super->name, "Compressed", sizeof(super->name)); + + super->root.mode = root->mode; + super->root.uid = root->uid; + super->root.gid = root->gid; + super->root.size = root->size; + super->root.offset = offset >> 2; + + return offset; +} + +static void set_data_offset(struct entry *entry, char *base, unsigned long offset) +{ + struct cramfs_inode *inode = (struct cramfs_inode *) (base + entry->dir_offset); + + if ((offset & 3) != 0) { + die(MKFS_ERROR, 0, "illegal offset of %lu bytes", offset); + } + if (offset >= (1 << (2 + CRAMFS_OFFSET_WIDTH))) { + die(MKFS_ERROR, 0, "filesystem too big"); + } + inode->offset = (offset >> 2); +} + +/* + * TODO: Does this work for chars >= 0x80? Most filesystems use UTF-8 + * encoding for filenames, whereas the console is a single-byte + * character set like iso-latin-1. + */ +static void print_node(struct entry *e) +{ + char info[10]; + char type = '?'; + + if (S_ISREG(e->mode)) type = 'f'; + else if (S_ISDIR(e->mode)) type = 'd'; + else if (S_ISLNK(e->mode)) type = 'l'; + else if (S_ISCHR(e->mode)) type = 'c'; + else if (S_ISBLK(e->mode)) type = 'b'; + else if (S_ISFIFO(e->mode)) type = 'p'; + else if (S_ISSOCK(e->mode)) type = 's'; + + if (S_ISCHR(e->mode) || (S_ISBLK(e->mode))) { + /* major/minor numbers can be as high as 2^12 or 4096 */ + snprintf(info, 10, "%4d,%4d", major(e->size), minor(e->size)); + } + else { + /* size be as high as 2^24 or 16777216 */ + snprintf(info, 10, "%9d", e->size); + } + + printf("%c %04o %s %5d:%-3d %s\n", + type, e->mode & ~S_IFMT, info, e->uid, e->gid, e->name); +} + +/* + * We do a width-first printout of the directory + * entries, using a stack to remember the directories + * we've seen. + */ +static unsigned int write_directory_structure(struct entry *entry, char *base, unsigned int offset) +{ + int stack_entries = 0; + int stack_size = 64; + struct entry **entry_stack; + + entry_stack = malloc(stack_size * sizeof(struct entry *)); + if (!entry_stack) { + die(MKFS_ERROR, 1, "malloc failed"); + } + + if (opt_verbose) { + printf("root:\n"); + } + + for (;;) { + int dir_start = stack_entries; + while (entry) { + struct cramfs_inode *inode = (struct cramfs_inode *) (base + offset); + size_t len = strlen(entry->name); + + entry->dir_offset = offset; + + inode->mode = entry->mode; + inode->uid = entry->uid; + inode->gid = entry->gid; + inode->size = entry->size; + inode->offset = 0; + /* Non-empty directories, regfiles and symlinks will + write over inode->offset later. */ + + offset += sizeof(struct cramfs_inode); + total_nodes++; /* another node */ + memcpy(base + offset, entry->name, len); + /* Pad up the name to a 4-byte boundary */ + while (len & 3) { + *(base + offset + len) = '\0'; + len++; + } + inode->namelen = len >> 2; + offset += len; + + if (opt_verbose) + print_node(entry); + + if (entry->child) { + if (stack_entries >= stack_size) { + stack_size *= 2; + entry_stack = realloc(entry_stack, stack_size * sizeof(struct entry *)); + if (!entry_stack) { + die(MKFS_ERROR, 1, "realloc failed"); + } + } + entry_stack[stack_entries] = entry; + stack_entries++; + } + entry = entry->next; + } + + /* + * Reverse the order the stack entries pushed during + * this directory, for a small optimization of disk + * access in the created fs. This change makes things + * `ls -UR' order. + */ + { + struct entry **lo = entry_stack + dir_start; + struct entry **hi = entry_stack + stack_entries; + struct entry *tmp; + + while (lo < --hi) { + tmp = *lo; + *lo++ = *hi; + *hi = tmp; + } + } + + /* Pop a subdirectory entry from the stack, and recurse. */ + if (!stack_entries) + break; + stack_entries--; + entry = entry_stack[stack_entries]; + + set_data_offset(entry, base, offset); + if (opt_verbose) { + printf("%s:\n", entry->name); + } + entry = entry->child; + } + free(entry_stack); + return offset; +} + +static int is_zero(char const *begin, unsigned len) +{ + /* Returns non-zero iff the first LEN bytes from BEGIN are all NULs. */ + return (len-- == 0 || + (begin[0] == '\0' && + (len-- == 0 || + (begin[1] == '\0' && + (len-- == 0 || + (begin[2] == '\0' && + (len-- == 0 || + (begin[3] == '\0' && + memcmp(begin, begin + 4, len) == 0)))))))); +} + +/* + * One 4-byte pointer per block and then the actual blocked + * output. The first block does not need an offset pointer, + * as it will start immediately after the pointer block; + * so the i'th pointer points to the end of the i'th block + * (i.e. the start of the (i+1)'th block or past EOF). + * + * Note that size > 0, as a zero-sized file wouldn't ever + * have gotten here in the first place. + */ +static unsigned int do_compress(char *base, unsigned int offset, char const *name, char *uncompressed, unsigned int size) +{ + unsigned long original_size = size; + unsigned long original_offset = offset; + unsigned long new_size; + unsigned long blocks = (size - 1) / blksize + 1; + unsigned long curr = offset + 4 * blocks; + int change; + + total_blocks += blocks; + + do { + unsigned long len = 2 * blksize; + unsigned int input = size; + int err; + + if (input > blksize) + input = blksize; + size -= input; + if (!(opt_holes && is_zero (uncompressed, input))) { + err = compress2(base + curr, &len, uncompressed, input, Z_BEST_COMPRESSION); + if (err != Z_OK) { + die(MKFS_ERROR, 0, "compression error: %s", zError(err)); + } + curr += len; + } + uncompressed += input; + + if (len > blksize*2) { + /* (I don't think this can happen with zlib.) */ + die(MKFS_ERROR, 0, "AIEEE: block \"compressed\" to > 2*blocklength (%ld)", len); + } + + *(u32 *) (base + offset) = curr; + offset += 4; + } while (size); + + curr = (curr + 3) & ~3; + new_size = curr - original_offset; + /* TODO: Arguably, original_size in these 2 lines should be + st_blocks * 512. But if you say that then perhaps + administrative data should also be included in both. */ + change = new_size - original_size; + if (opt_verbose > 1) { + printf("%6.2f%% (%+d bytes)\t%s\n", + (change * 100) / (double) original_size, change, name); + } + + return curr; +} + + +/* + * Traverse the entry tree, writing data for every item that has + * non-null entry->path (i.e. every non-empty regfile) and non-null + * entry->uncompressed (i.e. every symlink). + */ +static unsigned int write_data(struct entry *entry, char *base, unsigned int offset) +{ + do { + if (entry->path || entry->uncompressed) { + if (entry->same) { + set_data_offset(entry, base, entry->same->offset); + entry->offset = entry->same->offset; + } + else { + set_data_offset(entry, base, offset); + entry->offset = offset; + map_entry(entry); + offset = do_compress(base, offset, entry->name, entry->uncompressed, entry->size); + unmap_entry(entry); + } + } + else if (entry->child) + offset = write_data(entry->child, base, offset); + entry=entry->next; + } while (entry); + return offset; +} + +static unsigned int write_file(char *file, char *base, unsigned int offset) +{ + int fd; + char *buf; + + fd = open(file, O_RDONLY); + if (fd < 0) { + die(MKFS_ERROR, 1, "open failed: %s", file); + } + buf = mmap(NULL, image_length, PROT_READ, MAP_PRIVATE, fd, 0); + if (buf == MAP_FAILED) { + die(MKFS_ERROR, 1, "mmap failed"); + } + memcpy(base + offset, buf, image_length); + munmap(buf, image_length); + close (fd); + /* Pad up the image_length to a 4-byte boundary */ + while (image_length & 3) { + *(base + offset + image_length) = '\0'; + image_length++; + } + return (offset + image_length); +} + +int main(int argc, char **argv) +{ + struct stat st; /* used twice... */ + struct entry *root_entry; + char *rom_image; + ssize_t offset, written; + int fd; + /* initial guess (upper-bound) of required filesystem size */ + loff_t fslen_ub = sizeof(struct cramfs_super); + char const *dirname, *outfile; + u32 crc; + int c; /* for getopt */ + char *ep; /* for strtoul */ + + blksize = sysconf(_SC_PAGESIZE); + total_blocks = 0; + + if (argc) + progname = argv[0]; + + /* command line options */ + while ((c = getopt(argc, argv, "hEb:e:i:n:psvz")) != EOF) { + switch (c) { + case 'h': + usage(MKFS_OK); + case 'E': + opt_errors = 1; + break; + case 'b': + errno = 0; + blksize = strtoul(optarg, &ep, 10); + if (errno || optarg[0] == '\0' || *ep != '\0') + usage(MKFS_USAGE); + if (blksize < 512 || (blksize & (blksize - 1))) + die(MKFS_ERROR, 0, "invalid blocksize: %u", blksize); + break; + case 'e': + errno = 0; + opt_edition = strtoul(optarg, &ep, 10); + if (errno || optarg[0] == '\0' || *ep != '\0') + usage(MKFS_USAGE); + break; + case 'i': + opt_image = optarg; + if (lstat(opt_image, &st) < 0) { + die(MKFS_ERROR, 1, "lstat failed: %s", opt_image); + } + image_length = st.st_size; /* may be padded later */ + fslen_ub += (image_length + 3); /* 3 is for padding */ + break; + case 'n': + opt_name = optarg; + break; + case 'p': + opt_pad = PAD_SIZE; + fslen_ub += PAD_SIZE; + break; + case 's': + /* old option, ignored */ + break; + case 'v': + opt_verbose++; + break; + case 'z': + opt_holes = 1; + break; + } + } + + if ((argc - optind) != 2) + usage(MKFS_USAGE); + dirname = argv[optind]; + outfile = argv[optind + 1]; + + if (stat(dirname, &st) < 0) { + die(MKFS_USAGE, 1, "stat failed: %s", dirname); + } + fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0666); + if (fd < 0) { + die(MKFS_USAGE, 1, "open failed: %s", outfile); + } + + root_entry = calloc(1, sizeof(struct entry)); + if (!root_entry) { + die(MKFS_ERROR, 1, "calloc failed"); + } + root_entry->mode = st.st_mode; + root_entry->uid = st.st_uid; + root_entry->gid = st.st_gid; + + root_entry->size = parse_directory(root_entry, dirname, &root_entry->child, &fslen_ub); + + /* always allocate a multiple of blksize bytes because that's + what we're going to write later on */ + fslen_ub = ((fslen_ub - 1) | (blksize - 1)) + 1; + + if (fslen_ub > MAXFSLEN) { + fprintf(stderr, + "warning: estimate of required size (upper bound) is %jdMB, but maximum image size is %uMB, we might die prematurely\n", + (intmax_t) (fslen_ub >> 20), + MAXFSLEN >> 20); + fslen_ub = MAXFSLEN; + } + + /* find duplicate files. TODO: uses the most inefficient algorithm + possible. */ + eliminate_doubles(root_entry, root_entry); + + /* TODO: Why do we use a private/anonymous mapping here + followed by a write below, instead of just a shared mapping + and a couple of ftruncate calls? Is it just to save us + having to deal with removing the file afterwards? If we + really need this huge anonymous mapping, we ought to mmap + in smaller chunks, so that the user doesn't need nn MB of + RAM free. If the reason is to be able to write to + un-mmappable block devices, then we could try shared mmap + and revert to anonymous mmap if the shared mmap fails. */ + rom_image = mmap(NULL, fslen_ub?fslen_ub:1, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + + if (rom_image == MAP_FAILED) { + die(MKFS_ERROR, 1, "mmap failed"); + } + + /* Skip the first opt_pad bytes for boot loader code */ + offset = opt_pad; + memset(rom_image, 0x00, opt_pad); + + /* Skip the superblock and come back to write it later. */ + offset += sizeof(struct cramfs_super); + + /* Insert a file image. */ + if (opt_image) { + printf("Including: %s\n", opt_image); + offset = write_file(opt_image, rom_image, offset); + } + + offset = write_directory_structure(root_entry->child, rom_image, offset); + printf("Directory data: %zd bytes\n", offset); + + offset = write_data(root_entry, rom_image, offset); + + /* We always write a multiple of blksize bytes, so that + losetup works. */ + offset = ((offset - 1) | (blksize - 1)) + 1; + printf("Everything: %zd kilobytes\n", offset >> 10); + + /* Write the superblock now that we can fill in all of the fields. */ + write_superblock(root_entry, rom_image+opt_pad, offset); + printf("Super block: %zd bytes\n", sizeof(struct cramfs_super)); + + /* Put the checksum in. */ + crc = crc32(0L, Z_NULL, 0); + crc = crc32(crc, (rom_image+opt_pad), (offset-opt_pad)); + ((struct cramfs_super *) (rom_image+opt_pad))->fsid.crc = crc; + printf("CRC: %x\n", crc); + + /* Check to make sure we allocated enough space. */ + if (fslen_ub < offset) { + die(MKFS_ERROR, 0, "not enough space allocated for ROM image (%Ld allocated, %d used)", fslen_ub, offset); + } + + written = write(fd, rom_image, offset); + if (written < 0) { + die(MKFS_ERROR, 1, "write failed"); + } + if (offset != written) { + die(MKFS_ERROR, 0, "ROM image write failed (wrote %d of %d bytes): No space left on device?", written, offset); + } + + /* (These warnings used to come at the start, but they scroll off the + screen too quickly.) */ + if (warn_namelen) + fprintf(stderr, /* bytes, not chars: think UTF-8. */ + "warning: filenames truncated to %d bytes (possibly less if multi-byte UTF-8)\n", + CRAMFS_MAXPATHLEN); + if (warn_skip) + fprintf(stderr, "warning: files were skipped due to errors\n"); + if (warn_size) + fprintf(stderr, + "warning: file sizes truncated to %luMB (minus 1 byte)\n", + 1L << (CRAMFS_SIZE_WIDTH - 20)); + if (warn_uid) /* (not possible with current Linux versions) */ + fprintf(stderr, + "warning: uids truncated to %u bits (this may be a security concern)\n", + CRAMFS_UID_WIDTH); + if (warn_gid) + fprintf(stderr, + "warning: gids truncated to %u bits (this may be a security concern)\n", + CRAMFS_GID_WIDTH); + if (warn_dev) + fprintf(stderr, + "WARNING: device numbers truncated to %u bits (this almost certainly means\n" + "that some device files will be wrong)\n", + CRAMFS_OFFSET_WIDTH); + if (opt_errors && + (warn_namelen||warn_skip||warn_size||warn_uid||warn_gid||warn_dev)) + exit(MKFS_ERROR); + + exit(MKFS_OK); +} + +/* + * Local variables: + * c-file-style: "linux" + * End: + */ diff --git a/utils/ypr0tools/extract_section.c b/utils/ypr0tools/extract_section.c new file mode 100644 index 0000000000..8ad12bc7df --- /dev/null +++ b/utils/ypr0tools/extract_section.c @@ -0,0 +1,85 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2011 Thomas Martitz + * + * 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 +#include +#include +#include +#include +#include +#include + +/* A simple replacement program for ( + * dd if=$file1 of=$file2 bs=1 skip=$offset count=$size + * + * Written because byte-size operations with dd are unbearably slow. + */ + +void usage(void) +{ + fprintf(stderr, "Usage: extract_section \n"); + exit(1); +} + +void die(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + exit(1); +} + +int main(int argc, const char* argv[]) +{ + if (argc != 5) + usage(); + + int ifd, ofd; + ssize_t size = atol(argv[4]); + long skip = atol(argv[3]); + + if (!size) + die("invalid byte count\n"); + + ifd = open(argv[1], O_RDONLY); + if (ifd < 0) + die("Could not open %s for reading!\n", argv[1]); + + ofd = open(argv[2], O_WRONLY|O_CREAT|O_TRUNC, 0666); + if (ofd < 0) + die("Could not create %s\n", argv[2]); + + void *buf = malloc(size); + if (!buf) die("OOM\n"); + + lseek(ifd, skip, SEEK_SET); + lseek(ofd, 0, SEEK_SET); + if (read(ifd, buf, size) != size) + die("Read failed\n"); + if (write(ofd, buf, size) != size) + die("write failed\n"); + + close(ifd); + close(ofd); + + exit(EXIT_SUCCESS); +} diff --git a/utils/ypr0tools/files/.rockbox/README b/utils/ypr0tools/files/.rockbox/README new file mode 100644 index 0000000000..f0e306e196 --- /dev/null +++ b/utils/ypr0tools/files/.rockbox/README @@ -0,0 +1 @@ +This directory is empty and acts as mount point. diff --git a/utils/ypr0tools/files/Playlists/README b/utils/ypr0tools/files/Playlists/README new file mode 100644 index 0000000000..f0e306e196 --- /dev/null +++ b/utils/ypr0tools/files/Playlists/README @@ -0,0 +1 @@ +This directory is empty and acts as mount point. diff --git a/utils/ypr0tools/files/etc/mods/safe_mode.raw b/utils/ypr0tools/files/etc/mods/safe_mode.raw new file mode 100644 index 0000000000000000000000000000000000000000..1c1aa61dd1b509bc7b599b01d9ee414621513b89 GIT binary patch literal 230400 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 /sys/class/graphics/fb0/blank + echo -n "0" >> /sys/class/graphics/fb0/blank +# echo -n "1" > /sys/class/graphics/fb2/blank +# echo -n "0" >> /sys/class/graphics/fb2/blank + if [ -e $CustomIMG ] + then + cat $CustomIMG > "/dev/fb0" + else + cat $DefIMG > "/dev/fb0" + fi + + # Here the real USB connection stuff + # This is slightly modified by me; it was contained in the cramfs shipped with + # YP-R0 opensource package... + + lsmod | grep g_file_storage + if [ $? == 0 ] + then + umount /mnt/media1/dev/gadget + fi + #if [ -d /mnt/media0 ] + #then + umount /mnt/media1 + umount /mnt/media0 + #umount /mnt/mmc + #fi + lsmod | grep rfs + if [ $? == 0 ] + then + rmmod rfs + fi + lsmod | grep g_file_storage + if [ $? == 0 ] + then + rmmod gadgetfs + rmmod g_file_storage + rmmod arcotg_udc + fi + lsmod | grep g_file_storage + if [ $? != 0 ] + then + modprobe g-file-storage file=/dev/stl3,/dev/stl2,/dev/mmcblk0 removable=1 + fi + + # Let's implement the check if usb cable is still inserted or not... + cableDaemon + + return 1 +else + return 0 +fi diff --git a/utils/ypr0tools/files/etc/profile b/utils/ypr0tools/files/etc/profile new file mode 100755 index 0000000000..4ba61d7535 --- /dev/null +++ b/utils/ypr0tools/files/etc/profile @@ -0,0 +1,66 @@ +export PS1='\u@\h \w$ ' +export PS2='> ' +export PS3='? ' +export PS4='[$LINENO]+' + +export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin +export LD_LIBRARY_PATH=/mnt/media1/Lib:/mnt/media1/Lib/ExtraLib:/usr/lib +export FSL_OMX_COMPONENT_REGISTRY="/Sysdata/OpenMaxIL/ComponentRegistry.txt" +export FSL_OMX_MAX_INDEX_SIZE=1048576 +export MALLOC_CHECK_=0 + +ulimit -s unlimited +hwclock -s + +alias ls='ls --color=auto' +alias ll='ls -l --color=auto' + +# Start with lorenzo92's safe mode +SCRIPT="/etc/mods/safe_mode.sh" +if [ -f $SCRIPT ] +then + /bin/sh $SCRIPT + # it returns 1 if usb was connected + if [ "$?" = "1" ] + then + sync + sleep 1 + reboot + fi +fi + +if [ -e "/mnt/media1/r0" ] +then + MAINFILE="/mnt/media1/r0" +elif [ -f "/mnt/media0/r0" ] +then + # copy to media1 since USB wouldn't work + cp /mnt/media0/r0 /mnt/media1/r0_media0 + if [ "$?" = "0" ] + then # perhaps cp failed due to insufficient storage or so + MAINFILE="/mnt/media1/r0_media0" + else + MAINFILE="/usr/local/bin/r0" + fi +else + MAINFILE="/usr/local/bin/r0" +fi + +# source the rockbox loader script +SOURCE="/mnt/media0/.rockbox/rockbox.sh" +[ -f $SOURCE ] && . $SOURCE + +# source user script if available +SOURCE="/mnt/media0/rc.user" +[ -f $SOURCE ] && . $SOURCE + +# finally call the entry point +if [ -e $MAINFILE ] +then + chmod 777 $MAINFILE + $MAINFILE Application AppMain + rm -f /mnt/media1/r0_media0 + sync +# sleep 5 + reboot +fi diff --git a/utils/ypr0tools/pack-firmware.sh b/utils/ypr0tools/pack-firmware.sh new file mode 100755 index 0000000000..f3b55548d9 --- /dev/null +++ b/utils/ypr0tools/pack-firmware.sh @@ -0,0 +1,132 @@ +#!/bin/bash + +###################################################################### +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# +# * Script to generate a Samsung YP-R0 firmware file (R0.ROM) */ +###################################################################### +# +# This file was oringally called NewPack.sh, its origin is the R0 open source +# package from Samsung. +# +# Muon Platform +# Copyright (c) 2004-2009 Samsung Electronics, Inc. +# All rights reserved. +# +# Rom Packaging Script +# It needs sudoer privilege of rm, mkdir, cp, mkcramfs. +# You can configure it in the /etc/sudoer file. +# This script is very dangerous. Be careful to use. +# +# SangMan Sim + +# bail out early +set -e + +DIR=${2:-"."} +DIR=${DIR%/} +REVISION="$DIR/RevisionInfo.txt" +CRAMFS="$DIR/cramfs-fsl.rom" +SYSDATA="$DIR/SYSDATA.bin" +MBOOT="$DIR/MBoot.bin" +MBOOT_TMP="${TMP_DIR:-$DIR}/MBoot.tmp" +LINUX="$DIR/zImage" +R0ROM=$1 + +# some sanity checks +if [ $# -lt 1 ] || [ $# -gt 2 ]; then + echo "Usage $0 [path to image files]" + exit 1 +fi + +if [ ! -f ./MuonEncrypt ]; then + echo "Couldn't find MuonEncrypt binary (try 'make')" + exit 1 +fi + +if [ ! -e $REVISION ]; then + cat >$REVISION <> $R0ROM + #cat $MBOOT >> $R0ROM +} + +function Pack4Byte { + FILE_SIZE=`stat -c%s $R0ROM` + PACK_SIZE=`expr 4 - $FILE_SIZE % 4` + + if [ $PACK_SIZE != 4 ] + then + while [ $PACK_SIZE -gt 0 ] + do + PACK_SIZE=`expr $PACK_SIZE - 1` || true + echo -en $1 >> $R0ROM + done + fi + +} + +echo Make $R0ROM + +cat $REVISION > $R0ROM +echo User : $USER >> $R0ROM +echo Dir : $PWD >> $R0ROM +echo BuildTime : `date "+%y/%m/%d %H:%M:%S"` >> $R0ROM +echo MBoot : size\(`stat -c%s $MBOOT`\),checksum\(`md5sum $MBOOT | cut -d " " -f 1`\) >> $R0ROM +echo Linux : size\(`stat -c%s $LINUX`\),checksum\(`md5sum $LINUX | cut -d " " -f 1`\) >> $R0ROM +echo RootFS : size\(`stat -c%s $CRAMFS`\),checksum\(`md5sum $CRAMFS | cut -d " " -f 1`\) >> $R0ROM +echo Sysdata : size\(`stat -c%s $SYSDATA`\),checksum\(`md5sum $SYSDATA | cut -d " " -f 1`\) >> $R0ROM + +Pack4Byte "\\n" + + +dd if=$MBOOT of=$MBOOT_TMP bs=96 count=1 2> /dev/null + +echo `stat -c%s $MBOOT`:`md5sum $MBOOT | cut -d " " -f 1` >> $MBOOT_TMP +echo `stat -c%s $LINUX`:`md5sum $LINUX | cut -d " " -f 1` >> $MBOOT_TMP +echo `stat -c%s $CRAMFS`:`md5sum $CRAMFS | cut -d " " -f 1` >> $MBOOT_TMP +echo `stat -c%s $SYSDATA`:`md5sum $SYSDATA | cut -d " " -f 1` >> $MBOOT_TMP + +dd if=$MBOOT of=$MBOOT_TMP bs=1088 skip=1 seek=1 2> /dev/null +WriteImage $MBOOT_TMP + +#rm $MBOOT_TMP + +Pack4Byte "0" + +WriteImage $LINUX + +Pack4Byte "0" + +WriteImage $CRAMFS + +Pack4Byte "0" + +WriteImage $SYSDATA + +echo $R0ROM : `stat -c%s $R0ROM`, `md5sum $R0ROM | cut -d " " -f 1` +#head -9 $R0ROM + +echo "Done" diff --git a/utils/ypr0tools/patch-firmware.sh b/utils/ypr0tools/patch-firmware.sh new file mode 100755 index 0000000000..879b3f879d --- /dev/null +++ b/utils/ypr0tools/patch-firmware.sh @@ -0,0 +1,67 @@ +#!/bin/sh + + +###################################################################### +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# +# * Script to patch an unpacked Samsung YP-R0 firmware file */ +# Copyright (C) 2011 Thomas Martitz +###################################################################### +# bail out early +set -e + +if [ $# -lt 1 ] || [ $# -gt 2 ]; then + echo "Usage: $0 [path to unpacked rom]" + echo "\t is expected to have a rootfs layout and to contain" + echo "\tonly the files to overwrite (plain cp -r is used)" + exit 1 +fi + +FILES=${1%/} +FILES=${FILES:-"/"} +DIR=${2:-"."} +DIR=${DIR%/} +ROOTFS=$DIR/rootfs +CRAMFS=$DIR/cramfs-fsl.rom + +# sanity checks + +# this needs to be run as root! +if [ $(whoami) != "root" ] +then + echo "This needs to be run as root" + exit 1 +fi + +if [ ! -e $1 ] || [ ! -e $2 ]; then + echo "$1 or $2 does not exist" + exit 1 +fi + +if [ -z $ROOTFS ] || [ -z $FILES ]; then + echo "Invalid input directories" + exit 1 +fi + +if [ ! -e $CRAMFS ]; then + echo "Cramfs image not found (did you extract the firmware?)" + exit 1 +fi + +echo "Extracting cramfs image" + +[ ! -e $ROOTFS ] || rmdir -p $ROOTFS +cramfs-1.1/cramfsck -x $ROOTFS $CRAMFS + +echo "Patching rootfs" +echo "cp -r $FILES/* $ROOTFS/" +cp -r $FILES/.rockbox $ROOTFS/ +cp -r $FILES/* $ROOTFS/ + +echo "Packing new cramfs image" +cramfs-1.1/mkcramfs $ROOTFS $CRAMFS diff --git a/utils/ypr0tools/rockbox.sh b/utils/ypr0tools/rockbox.sh new file mode 100755 index 0000000000..cbe54fd223 --- /dev/null +++ b/utils/ypr0tools/rockbox.sh @@ -0,0 +1,47 @@ +#!/bin/sh +###################################################################### +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# +# * Samsung YP-R0 Rockbox as an application loader * +# Lorenzo Miori (C) 2011 +###################################################################### + +# This is expected to be sourced by the shell, which is then +# expected to run $MAINFILE + +# Check for menu button being pressed. Return immediately to launch the OF +var=$(dd if=/dev/r0Btn bs=4 count=1) +# Here a workaround to detect the byte +var2=$(echo -e -n "\x07") + +if [[ "$var" = "$var2" ]] +then + return +fi + + +# Blank-Unblank video to get rid of Samsung BootLogo, but turn off backlight before to hide these things :) +echo -n "0" > /sys/devices/platform/afe.0/bli +echo -n "1" > /sys/class/graphics/fb0/blank +echo -n "0" >> /sys/class/graphics/fb0/blank + +amixer sset 'Soft Mute' 0 +amixer sset 'Master' 85% + +# We set-up various settings for the cpu governor: default are +# Every 1,5 s the kernel evaluates if it's the case to down/up clocking the cpu +echo "ondemand" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor +echo "1" > /sys/devices/system/cpu/cpu0/cpufreq/ondemand/ignore_nice_load +echo "150000" > /sys/devices/system/cpu/cpu0/cpufreq/ondemand/sampling_rate +echo "95" > /sys/devices/system/cpu/cpu0/cpufreq/ondemand/up_threshold + +# bind these two to the root so that they're writable +mount --bind /mnt/media0/.rockbox /.rockbox +mount --bind /mnt/media0/Playlists /Playlists + +MAINFILE="/mnt/media0/.rockbox/rockbox" diff --git a/utils/ypr0tools/unpack-firmware.sh b/utils/ypr0tools/unpack-firmware.sh new file mode 100755 index 0000000000..ab80670c79 --- /dev/null +++ b/utils/ypr0tools/unpack-firmware.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +###################################################################### +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# +# * Script to unpack a Samsung YP-R0 firmware file (R0.ROM) */ +###################################################################### + +# The file was originally called MuonDecrypt.sh +# +# I'm not sure about the original author of this file, as it wasn't included in Samsung package. +# But I guess it was done by JeanLouis, an Italian user of the Hardware Upgrade Forum. If needed, we should search throug old posts for that... +# + + +# bail out early +set -e + +# some sanity checks +if [ $# -lt 1 ] || [ $# -gt 2 ]; then + echo "Usage $0 [out dir]" + exit 1 +fi + + +ROM=$1 +DIR=${2:-"."} +DIR=${DIR%/} +MBOOT="$DIR/MBoot.bin" +MBOOT_TMP="${TMP_DIR:-$DIR}/MBoot.tmp" +LINUX="$DIR/zImage" +CRAMFS="$DIR/cramfs-fsl.rom" +SYSDATA="$DIR/SYSDATA.bin" +MD5SUMS="$DIR/MD5SUMS" +TMP="${TMP_DIR:-$DIR}/_$$.tmp" + + +if [ ! -f ./extract_section ]; then + echo "Couldn't find extract_section binary (try 'make')" + exit 1 +fi + +if [ ! -f ./MuonEncrypt ]; then + echo "Couldn't find MuonEncrypt binary (try 'make')" + exit 1 +fi + +mkdir -p $DIR + +if [ ! -w $DIR ]; then + echo "Target dir not writable" + exit 1 +fi + +ExtractAndDecrypt() { + START=$(expr $START - $2) + echo "Extracting $1..." + ./extract_section $ROM $TMP $START $2 + echo "Decrypt $1..." + ./MuonEncrypt $TMP > $1 +} + +size=( `head -n 9 $ROM | tail -n 4 | while read LINE; do echo $LINE | cut -d\( -f 2 | cut -d\) -f 1; done`) +checksum=( `head -n 9 $ROM | tail -n 4 | while read LINE; do echo $LINE | cut -d\( -f 3 | cut -d\) -f 1; done`) + +echo "${checksum[0]} $MBOOT" > $MD5SUMS +echo "${checksum[1]} $LINUX" >> $MD5SUMS +echo "${checksum[2]} $CRAMFS" >> $MD5SUMS +echo "${checksum[3]} $SYSDATA" >> $MD5SUMS + +START=`stat -c%s $ROM` + +ExtractAndDecrypt $SYSDATA ${size[3]} +ExtractAndDecrypt $CRAMFS ${size[2]} +ExtractAndDecrypt $LINUX ${size[1]} +ExtractAndDecrypt $MBOOT_TMP ${size[0]} + +rm $TMP +echo "Create $MBOOT..." +dd if=$MBOOT_TMP of=$MBOOT bs=96 count=1 2>/dev/null +dd if=$MBOOT_TMP of=$MBOOT bs=1088 skip=1 seek=1 2>/dev/null +rm $MBOOT_TMP + +echo "Check integrity:" +md5sum -c $MD5SUMS