diff --git a/apps/SOURCES b/apps/SOURCES index 6118438b40..0965c498b6 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -100,7 +100,7 @@ gui/statusbar.c #ifdef HAVE_LCD_BITMAP gui/statusbar-skinned.c #endif -#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined (DX50) && !defined(DX90) +#if (CONFIG_PLATFORM&PLATFORM_ANDROID) hosted/android/yesno.c hosted/android/notification.c #else @@ -129,7 +129,7 @@ player/keyboard.c #ifdef HAVE_LCD_BITMAP recorder/bmp.c recorder/icons.c -#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined (DX50) && !defined(DX90) +#if (CONFIG_PLATFORM&PLATFORM_ANDROID) hosted/android/keyboard.c #else recorder/keyboard.c diff --git a/apps/action.c b/apps/action.c index 25f559f7bd..856bc0810c 100644 --- a/apps/action.c +++ b/apps/action.c @@ -77,6 +77,10 @@ static inline int do_button_check(const struct button_mapping *items, { if (items[i].button_code == button) { + /* + CAVEAT: This will allways return the action without pre_button_code if it has a + lower index in the list. + */ if ((items[i].pre_button_code == BUTTON_NONE) || (items[i].pre_button_code == last_button)) { diff --git a/apps/keymaps/keymap-dx50.c b/apps/keymaps/keymap-dx50.c index ee3b32005a..c6bb814469 100644 --- a/apps/keymaps/keymap-dx50.c +++ b/apps/keymaps/keymap-dx50.c @@ -1,13 +1,15 @@ /*************************************************************************** - * __________ __ ___. + * __________ __ ___ * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id$ * - * Copyright (C) 2010 Maurus Cuelenaere + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -19,7 +21,6 @@ * ****************************************************************************/ -/* Button Code Definitions for iBasso DX50 & DX90 */ #include #include @@ -30,190 +31,214 @@ #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 - */ + Button Code Definitions for iBasso DX50 & DX90. -static const struct button_mapping button_context_standard[] = { - { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, - { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, - { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, - { ACTION_STD_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, + 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. + CAVEAT: The action without prereq button code will allways be choosen if it has a + lower index in the list. + Insert LAST_ITEM_IN_LIST at the end of each mapping +*/ + + +static const struct button_mapping button_context_standard[] = +{ + { ACTION_STD_CONTEXT, BUTTON_PLAY | BUTTON_REPEAT, BUTTON_PLAY }, + { ACTION_STD_OK, BUTTON_PLAY | BUTTON_REL, BUTTON_PLAY }, + { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE }, + { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_STD_PREVREPEAT, BUTTON_LEFT | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE }, LAST_ITEM_IN_LIST -}; /* button_context_standard */ +}; + + +static const struct button_mapping button_context_wps[] = +{ + { ACTION_WPS_MENU, BUTTON_POWER, BUTTON_NONE }, + { ACTION_WPS_CONTEXT, BUTTON_PLAY | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_PLAY, BUTTON_PLAY | BUTTON_REL, BUTTON_NONE }, + { ACTION_WPS_SEEKBACK, BUTTON_LEFT | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_SEEKFWD, BUTTON_RIGHT | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_STOPSEEK, BUTTON_LEFT | BUTTON_REL, BUTTON_LEFT | BUTTON_REPEAT }, + { ACTION_WPS_STOPSEEK, BUTTON_RIGHT | BUTTON_REL, BUTTON_RIGHT | BUTTON_REPEAT }, + { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT | BUTTON_REL, BUTTON_NONE }, + { ACTION_WPS_SKIPPREV, BUTTON_LEFT | BUTTON_REL, BUTTON_NONE }, + { ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE }, + { ACTION_WPS_VOLUP, BUTTON_VOL_UP | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, + { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN | BUTTON_REPEAT, BUTTON_NONE }, -static const struct button_mapping button_context_wps[] = { - { ACTION_WPS_MENU, BUTTON_POWER, BUTTON_NONE }, - { ACTION_WPS_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_NONE }, - { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE }, - { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE }, - { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT }, - { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT }, - { ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE }, - { ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, - { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, LAST_ITEM_IN_LIST -}; /* button_context_wps */ +}; + + +static const struct button_mapping button_context_list[] = +{ + { ACTION_LIST_VOLUP, BUTTON_VOL_UP | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_LIST_VOLUP, BUTTON_VOL_UP, BUTTON_NONE }, + { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, + { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN | BUTTON_REPEAT, BUTTON_NONE }, -static const struct button_mapping button_context_list[] = { -#ifdef HAVE_VOLUME_IN_LIST - { ACTION_LIST_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_LIST_VOLUP, BUTTON_VOL_UP, BUTTON_NONE }, - { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, - { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, -#endif LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), -}; /* button_context_list */ +}; -static const struct button_mapping button_context_tree[] = { +static const struct button_mapping button_context_tree[] = +{ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), -}; /* button_context_tree */ - -static const struct button_mapping button_context_listtree_scroll_with_combo[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), }; -static const struct button_mapping button_context_listtree_scroll_without_combo[] = { - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), + +static const struct button_mapping button_context_listtree_scroll_with_combo[] = +{ + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM | CONTEXT_TREE), }; -static const struct button_mapping button_context_settings[] = { - { ACTION_SETTINGS_INC, BUTTON_VOL_UP|BUTTON_REL, BUTTON_NONE }, - { ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN|BUTTON_REL, BUTTON_NONE }, - { ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, - LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), -}; /* button_context_settings */ -static const struct button_mapping button_context_settings_right_is_inc[] = { +static const struct button_mapping button_context_listtree_scroll_without_combo[] = +{ + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM | CONTEXT_TREE), +}; + + +static const struct button_mapping button_context_settings[] = +{ + { ACTION_SETTINGS_INC, BUTTON_VOL_UP | BUTTON_REL, BUTTON_NONE }, + { ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN | BUTTON_REL, BUTTON_NONE }, + { ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN | BUTTON_REPEAT, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), -}; /* button_context_settingsgraphical */ +}; -static const struct button_mapping button_context_mainmenu[] = { + +static const struct button_mapping button_context_settings_right_is_inc[] = +{ + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), +}; + + +static const struct button_mapping button_context_mainmenu[] = +{ + { ACTION_TREE_WPS, BUTTON_POWER, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_TREE), -}; /* button_context_mainmenu */ +}; -static const struct button_mapping button_context_yesno[] = { - { ACTION_YESNO_ACCEPT, BUTTON_PLAY, BUTTON_NONE }, + +static const struct button_mapping button_context_yesno[] = +{ + { ACTION_YESNO_ACCEPT, BUTTON_PLAY, BUTTON_NONE }, + { ACTION_YESNO_ACCEPT, BUTTON_LEFT, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD), -}; /* button_context_settings_yesno */ +}; -static const struct button_mapping button_context_colorchooser[] = { + +static const struct button_mapping button_context_colorchooser[] = +{ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_colorchooser */ +}; -static const struct button_mapping button_context_eq[] = { + +static const struct button_mapping button_context_eq[] = +{ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_eq */ +}; -static const struct button_mapping button_context_keyboard[] = { - { 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_CURSOR_LEFT, BUTTON_PLAY|BUTTON_LEFT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_LEFT, BUTTON_PLAY|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_RIGHT, BUTTON_NONE }, - { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_SELECT, BUTTON_PLAY, BUTTON_NONE }, - - { ACTION_KBD_UP, BUTTON_VOL_UP, BUTTON_NONE }, - { ACTION_KBD_UP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, - { ACTION_KBD_DOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE }, +static const struct button_mapping button_context_keyboard[] = +{ + { 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_CURSOR_LEFT, BUTTON_PLAY | BUTTON_LEFT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_LEFT, BUTTON_PLAY | BUTTON_LEFT | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY | BUTTON_RIGHT, BUTTON_NONE }, + { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY | BUTTON_RIGHT | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_SELECT, BUTTON_PLAY, BUTTON_NONE }, + { ACTION_KBD_UP, BUTTON_VOL_UP, BUTTON_NONE }, + { ACTION_KBD_UP, BUTTON_VOL_UP | BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_KBD_DOWN, BUTTON_VOL_DOWN, BUTTON_NONE }, + { ACTION_KBD_DOWN, BUTTON_VOL_DOWN | BUTTON_REPEAT, BUTTON_NONE }, LAST_ITEM_IN_LIST -}; /* button_context_keyboard */ +}; -/** Bookmark Screen **/ -static const struct button_mapping button_context_bmark[] = { + + +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[] = { + +static const struct button_mapping button_context_time[] = +{ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS), -}; /* button_context_time */ +}; -static const struct button_mapping button_context_quickscreen[] = { + +static const struct button_mapping button_context_quickscreen[] = +{ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_quickscreen */ +}; -static const struct button_mapping button_context_pitchscreen[] = { - { ACTION_PS_INC_SMALL, BUTTON_VOL_UP|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_DEC_SMALL, BUTTON_VOL_DOWN|BUTTON_REL, BUTTON_NONE }, - { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE }, +static const struct button_mapping button_context_pitchscreen[] = +{ + { ACTION_PS_INC_SMALL, BUTTON_VOL_UP | BUTTON_REL, BUTTON_NONE }, + { ACTION_PS_DEC_SMALL, BUTTON_VOL_DOWN |BUTTON_REL, BUTTON_NONE }, + { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) -}; /* button_context_pitchcreen */ +}; -static const struct button_mapping button_context_radio[] = { +static const struct button_mapping button_context_radio[] = +{ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS) -}; /* button_context_radio */ +}; + const struct button_mapping* target_get_context_mapping(int context) { - switch (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: - return button_context_mainmenu; + case CONTEXT_STD: { return button_context_standard; } + case CONTEXT_WPS: { return button_context_wps; } + case CONTEXT_LIST: { return button_context_list; } + case CONTEXT_MAINMENU: { return button_context_mainmenu; } + case CONTEXT_CUSTOM | 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_KEYBOARD: { return button_context_keyboard; } + 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_CUSTOM | CONTEXT_SETTINGS: + case CONTEXT_SETTINGS_RECTRIGGER: { return button_context_settings_right_is_inc; } case CONTEXT_TREE: - if (global_settings.hold_lr_for_scroll_in_list) + { + if(global_settings.hold_lr_for_scroll_in_list) + { return button_context_listtree_scroll_without_combo; - else - return button_context_listtree_scroll_with_combo; - case CONTEXT_CUSTOM|CONTEXT_TREE: - return button_context_tree; - - case CONTEXT_SETTINGS: - return button_context_settings; - case CONTEXT_CUSTOM|CONTEXT_SETTINGS: - case CONTEXT_SETTINGS_RECTRIGGER: - return button_context_settings_right_is_inc; - - 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_KEYBOARD: - return button_context_keyboard; - - 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; + } + return button_context_listtree_scroll_with_combo; + } } + return button_context_standard; } diff --git a/apps/keymaps/keymap-touchscreen.c b/apps/keymaps/keymap-touchscreen.c index 9825c92e7d..6163cb054c 100644 --- a/apps/keymaps/keymap-touchscreen.c +++ b/apps/keymaps/keymap-touchscreen.c @@ -171,6 +171,13 @@ static const struct button_mapping button_context_settings_right_is_inc[] = { LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM2|CONTEXT_CUSTOM|CONTEXT_SETTINGS) }; /* button_context_settingsgraphical */ + +static const struct button_mapping button_context_mainmenu[] = +{ + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM2 | CONTEXT_MAINMENU) +}; + + static const struct button_mapping button_context_yesno[] = { { ACTION_YESNO_ACCEPT, BUTTON_TOPRIGHT, BUTTON_NONE }, { ACTION_YESNO_ACCEPT, BUTTON_BOTTOMLEFT, BUTTON_NONE }, @@ -389,7 +396,12 @@ const struct button_mapping* get_context_mapping(int context) case CONTEXT_LIST: return button_context_list; + case CONTEXT_MAINMENU: + { + return button_context_mainmenu; + } + case CONTEXT_TREE: if (global_settings.hold_lr_for_scroll_in_list) return button_context_listtree_scroll_without_combo; diff --git a/apps/main.c b/apps/main.c index 211f7f1b3c..88a6630f94 100644 --- a/apps/main.c +++ b/apps/main.c @@ -37,7 +37,9 @@ #include "menu.h" #include "usb.h" #include "powermgmt.h" +#if !defined(DX50) && !defined(DX90) #include "adc.h" +#endif #include "i2c.h" #ifndef DEBUG #include "serial.h" @@ -340,7 +342,7 @@ static void init(void) #ifdef SIMULATOR sim_tasks_init(); #endif -#if (CONFIG_PLATFORM & PLATFORM_ANDROID) && !defined(DX50) && !defined(DX90) +#if (CONFIG_PLATFORM & PLATFORM_ANDROID) notification_init(); #endif lang_init(core_language_builtin, language_strings, diff --git a/apps/playback.c b/apps/playback.c index c57855eeac..d1fe8ca0ea 100644 --- a/apps/playback.c +++ b/apps/playback.c @@ -1961,7 +1961,7 @@ static int audio_finish_load_track(struct track_info *info) resume_rewind_adjust_progress(track_id3, &elapsed, &offset); logf("%s: Set resume for %s to %lu %lX", __func__, - id3->title, elapsed, offset); + track_id3->title, elapsed, offset); enum data_type audiotype = rbcodec_format_is_atomic(track_id3->codectype) ? TYPE_ATOMIC_AUDIO : TYPE_PACKET_AUDIO; diff --git a/apps/plugins/SOURCES.app_build b/apps/plugins/SOURCES.app_build index 990a7c1c86..89a8b0ede6 100644 --- a/apps/plugins/SOURCES.app_build +++ b/apps/plugins/SOURCES.app_build @@ -1,4 +1,4 @@ -#ifndef HAVE_TOUCHSCREEN +#if !defined(HAVE_TOUCHSCREEN) || defined(DX50) || defined(DX90) /* In devices running RockBox as an application, but having a keypad */ #include "SOURCES" #else diff --git a/apps/plugins/SUBDIRS.app_build b/apps/plugins/SUBDIRS.app_build index 934474a996..954044146a 100644 --- a/apps/plugins/SUBDIRS.app_build +++ b/apps/plugins/SUBDIRS.app_build @@ -1,4 +1,4 @@ -#ifndef HAVE_TOUCHSCREEN +#if !defined(HAVE_TOUCHSCREEN) || defined(DX50) || defined(DX90) /* This is for devices having a keypad, running RockBox as an application */ #include "SUBDIRS" diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c index 289b399e27..9ffdb0798f 100644 --- a/apps/plugins/battery_bench.c +++ b/apps/plugins/battery_bench.c @@ -262,10 +262,10 @@ #define BATTERY_OFF_TXT "Power" #elif CONFIG_KEYPAD == DX50_PAD -#define BATTERY_ON BUTTON_PLAY -#define BATTERY_OFF BUTTON_POWER -#define BATTERY_OFF_TXT "POWER" -#define BATTERY_ON_TXT "PLAY - start" +#define BATTERY_ON BUTTON_PLAY +#define BATTERY_OFF BUTTON_POWER_LONG +#define BATTERY_OFF_TXT "Power Long" +#define BATTERY_ON_TXT "Play - start" #else #error No keymap defined! diff --git a/apps/plugins/plugins.make b/apps/plugins/plugins.make index 1edbd37306..be3d35717e 100644 --- a/apps/plugins/plugins.make +++ b/apps/plugins/plugins.make @@ -11,11 +11,9 @@ is_app_build = ifdef APP_TYPE ifneq ($(APP_TYPE),sdl-sim) -ifeq (,$(findstring standalone, $(APP_TYPE))) is_app_build = yes endif endif -endif ifdef is_app_build PLUGINS_SRC = $(call preprocess, $(APPSDIR)/plugins/SOURCES.app_build) diff --git a/apps/root_menu.c b/apps/root_menu.c index f1b5017751..7ec803f585 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c @@ -792,13 +792,13 @@ void root_menu(void) case GO_TO_ROOT: if (last_screen != GO_TO_ROOT) selected = get_selection(last_screen); -#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined(DX50) && !defined(DX90) +#if (CONFIG_PLATFORM&PLATFORM_ANDROID) /* When we are in the main menu we want the hardware BACK * button to be handled by Android instead of rockbox */ android_ignore_back_button(true); #endif next_screen = do_menu(&root_menu_, &selected, NULL, false); -#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined(DX50) && !defined(DX90) +#if (CONFIG_PLATFORM&PLATFORM_ANDROID) android_ignore_back_button(false); #endif if (next_screen != GO_TO_PREVIOUS) diff --git a/apps/scrobbler.c b/apps/scrobbler.c index 4f3693e716..2793e70725 100644 --- a/apps/scrobbler.c +++ b/apps/scrobbler.c @@ -78,7 +78,7 @@ static void get_scrobbler_filename(char *path, size_t size) used = snprintf(path, size, "/home/user/MyDocs/%s", BASE_FILENAME); #elif (CONFIG_PLATFORM & PLATFORM_ANDROID) used = snprintf(path, size, "/sdcard/%s", BASE_FILENAME); -#elif defined (SAMSUNG_YPR0) +#elif defined (SAMSUNG_YPR0) || defined(DX50) || defined(DX90) used = snprintf(path, size, "%s/%s", HOME_DIR, BASE_FILENAME); #else /* SDL/unknown RaaA build */ used = snprintf(path, size, "%s/%s", ROCKBOX_DIR, BASE_FILENAME); diff --git a/apps/settings.h b/apps/settings.h index 3029026ab6..4ea56d273e 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -291,7 +291,7 @@ struct user_settings /* audio settings */ int volume; /* audio output volume in decibels range depends on the dac */ - int balance; /* stereo balance: 0-100 0=left 50=bal 100=right */ + int balance; /* stereo balance: -100 - +100 -100=left 0=bal +100=right */ int bass; /* bass boost/cut in decibels */ int treble; /* treble boost/cut in decibels */ int channel_config; /* Stereo, Mono, Custom, Mono left, Mono right, Karaoke */ diff --git a/firmware/SOURCES b/firmware/SOURCES index 999d92012c..a67f866dcc 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -20,6 +20,7 @@ target/hosted/rtc.c #endif #if (CONFIG_PLATFORM & PLATFORM_ANDROID) == 0 && \ + !defined(DX50) && !defined(DX90) && \ (defined(DEBUG) || defined(SIMULATOR)) /* sim should define DEBUG instead */ target/hosted/debug-hosted.c #endif @@ -1814,31 +1815,53 @@ target/arm/rk27xx/ihifi/powermgmt-ihifi960.c target/hosted/kernel-unix.c target/hosted/filesystem-unix.c target/hosted/lc-unix.c -#if !defined(DX50) && !defined(DX90) target/hosted/android/lcd-android.c target/hosted/android/button-android.c +#ifdef DEBUG +target/hosted/android/debug-android.c +#endif target/hosted/android/pcm-android.c target/hosted/android/powermgmt-android.c +target/hosted/android/system-android.c target/hosted/android/telephony-android.c #ifdef APPLICATION target/hosted/android/app/button-application.c #endif -#else -drivers/lcd-memframe.c -target/hosted/android/dx50/pcm-dx50.c -target/hosted/android/dx50/tinyalsa/pcm.c -target/hosted/android/dx50/powermgmt-dx50.c -target/hosted/android/dx50/backlight-dx50.c -target/hosted/android/dx50/button-dx50.c -target/hosted/android/dx50/lcd-dx50.c -#endif -#ifdef DEBUG -target/hosted/android/debug-android.c -#endif -target/hosted/android/system-android.c drivers/audio/android.c #endif +#if defined(DX50) || defined(DX90) +drivers/lcd-memframe.c +target/hosted/kernel-unix.c +target/hosted/filesystem-unix.c +target/hosted/lc-unix.c +target/hosted/ibasso/audiohw-ibasso.c +target/hosted/ibasso/backlight-ibasso.c +target/hosted/ibasso/button-ibasso.c +#ifdef DEBUG +target/hosted/ibasso/debug-ibasso.c +#endif +target/hosted/ibasso/hostfs-ibasso.c +target/hosted/ibasso/lcd-ibasso.c +target/hosted/ibasso/pcm-ibasso.c +target/hosted/ibasso/power-ibasso.c +target/hosted/ibasso/powermgmt-ibasso.c +target/hosted/ibasso/sysfs-ibasso.c +target/hosted/ibasso/system-ibasso.c +target/hosted/ibasso/usb-ibasso.c +target/hosted/ibasso/vold-ibasso.c +target/hosted/ibasso/tinyalsa/mixer.c +target/hosted/ibasso/tinyalsa/pcm.c +#ifdef DX50 +target/hosted/ibasso/dx50/audiohw-dx50.c +target/hosted/ibasso/dx50/button-dx50.c +#endif +#ifdef DX90 +target/hosted/ibasso/dx90/audiohw-dx90.c +target/hosted/ibasso/dx90/button-dx90.c +#endif +#endif + #else /* defined(SIMULATOR) */ #ifdef WIN32 diff --git a/firmware/backlight.c b/firmware/backlight.c index d6dbf3eec7..19a1d21eb5 100644 --- a/firmware/backlight.c +++ b/firmware/backlight.c @@ -42,6 +42,13 @@ #endif #ifndef SIMULATOR +/* + Device specific implementation: + bool backlight_hw_init(void); + void backlight_hw_on(void); + void backlight_hw_off(void); + void backlight_hw_brightness(int brightness); +*/ #include "backlight-target.h" #else #include "backlight-sim.h" diff --git a/firmware/drivers/audio/android.c b/firmware/drivers/audio/android.c index f26087470b..7a5f34ea48 100644 --- a/firmware/drivers/audio/android.c +++ b/firmware/drivers/audio/android.c @@ -22,34 +22,12 @@ #include "config.h" #include "audiohw.h" -#if defined(DX50) || defined(DX90) -#include "system.h" -#include "pcm_sw_volume.h" -#endif -#if defined(DX50) || defined(DX90) -void audiohw_set_volume(int vol_l, int vol_r) -{ - int hw_volume; - hw_volume = MAX(vol_l, vol_r); - -#ifdef HAVE_SW_VOLUME_CONTROL - vol_l-=hw_volume; - vol_r-=hw_volume; - pcm_set_master_volume(vol_l, vol_r); -#endif - - extern void pcm_set_mixer_volume(int); - pcm_set_mixer_volume(hw_volume); - -} -#else void audiohw_set_volume(int volume) { extern void pcm_set_mixer_volume(int); pcm_set_mixer_volume(volume); } -#endif void audiohw_set_balance(int balance) { @@ -58,8 +36,6 @@ void audiohw_set_balance(int balance) void audiohw_close(void) { -#if !defined(DX50) && !defined(DX90) extern void pcm_shutdown(void); pcm_shutdown(); -#endif } diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 718fb6a6da..d47a486b43 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c @@ -215,6 +215,27 @@ static void button_tick(void) } else /* repeat? */ { + +#if defined(DX50) || defined(DX90) + /* + Power button on these devices reports two distinct key codes, which are + triggerd by a short or medium duration press. Additionlly a long duration press + will trigger a hard reset, which is hardwired. + + The time delta between medium and long duration press is not large enough to + register here as power off repeat. A hard reset is triggered before Rockbox + can power off. + + To cirumvent the hard reset, Rockbox will shutdown on the first POWEROFF_BUTTON + repeat. POWEROFF_BUTTON is associated with the a medium duration press of the + power button. + */ + if(btn & POWEROFF_BUTTON) + { + sys_poweroff(); + } +#endif + if ( repeat ) { if (!post) diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 7c5424a29d..d7bc3dd6de 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -114,6 +114,10 @@ struct sound_settings_info #elif (CONFIG_PLATFORM & (PLATFORM_ANDROID | PLATFORM_MAEMO\ | PLATFORM_PANDORA | PLATFORM_SDL)) #include "hosted_codec.h" +#elif defined(DX50) +#include "codec-dx50.h" +#elif defined(DX90) +#include "codec-dx90.h" #endif /* convert caps into defines */ diff --git a/firmware/export/config/ibassodx50.h b/firmware/export/config/ibassodx50.h index 5bbb515c1c..e26d43c4a7 100644 --- a/firmware/export/config/ibassodx50.h +++ b/firmware/export/config/ibassodx50.h @@ -1,14 +1,35 @@ -/* - * This config file is for Rockbox as an application on Android - */ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/* This config file is for Rockbox as an application on Android without JVM. */ /* We don't run on hardware directly */ -#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID) +#define CONFIG_PLATFORM PLATFORM_HOSTED /* For Rolo and boot loader */ #define MODEL_NUMBER 94 -#define MODEL_NAME "iBasso DX50" +#define MODEL_NAME "iBasso DX50" #define USB_NONE @@ -41,16 +62,15 @@ #define LCD_PIXELFORMAT RGB565 #define HAVE_LCD_ENABLE +#define HAVE_LCD_SLEEP +#define HAVE_LCD_SLEEP_SETTING +/*#define HAVE_LCD_FLIP*/ +#define HAVE_LCD_SHUTDOWN /* define this to indicate your device's keypad */ #define HAVE_TOUCHSCREEN #define HAVE_BUTTON_DATA - -/* define this if you have RTC RAM available for settings */ -//#define HAVE_RTC_RAM - -/* define this if you have a real-time clock */ -//#define CONFIG_RTC APPLICATION +#define HAS_BUTTON_HOLD /* Define this if you have a software controlled poweroff */ #define HAVE_SW_POWEROFF @@ -77,6 +97,10 @@ /* Define this if you do software codec */ #define CONFIG_CODEC SWCODEC +#define HAVE_SW_TONE_CONTROLS +#define HAVE_SW_VOLUME_CONTROL +#define HW_SAMPR_CAPS SAMPR_CAP_ALL +#define HAVE_PLAY_FREQ //#define HAVE_MULTIMEDIA_KEYS #define CONFIG_KEYPAD DX50_PAD @@ -84,39 +108,26 @@ /* define this if the target has volume keys which can be used in the lists */ #define HAVE_VOLUME_IN_LIST -/* define this if the host platform can change volume outside of rockbox */ -//#define PLATFORM_HAS_VOLUME_CHANGE - -#define HAVE_SW_TONE_CONTROLS - -#define HAVE_SW_VOLUME_CONTROL - #define BATTERY_CAPACITY_DEFAULT 2100 /* default battery capacity */ -#define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */ -#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */ -#define BATTERY_CAPACITY_INC 50 /* capacity increment */ -#define BATTERY_TYPES_COUNT 1 /* only one type */ +#define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 50 /* capacity increment */ +#define BATTERY_TYPES_COUNT 1 /* only one type */ #define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE +#define CONFIG_CHARGING CHARGING_MONITOR -#define CONFIG_CHARGING CHARGING_MONITOR - -#define NO_LOW_BATTERY_SHUTDOWN - -/* Define current usage levels. */ -#define CURRENT_NORMAL 210 /* 10 hours from a 2100 mAh battery */ -#define CURRENT_BACKLIGHT 30 /* TBD */ -#define CURRENT_RECORD 0 /* no recording */ - -/* Define this to the CPU frequency */ /* -#define CPU_FREQ 48000000 + 10 hours from a 2100 mAh battery + Based on battery bench with stock Samsung battery. */ +#define CURRENT_NORMAL 210 +#define CURRENT_BACKLIGHT 30 /* TBD */ +#define CURRENT_RECORD 0 /* no recording */ /* define this if the hardware can be powered off while charging */ #define HAVE_POWEROFF_WHILE_CHARGING - /* Offset ( in the firmware file's header ) to the file CRC */ #define FIRMWARE_OFFSET_FILE_CRC 0 @@ -128,9 +139,6 @@ /* Define this if a programmable hotkey is mapped */ #define HAVE_HOTKEY -#define BOOTDIR "/.rockbox" - /* No special storage */ #define CONFIG_STORAGE STORAGE_HOSTFS #define HAVE_STORAGE_FLUSH - diff --git a/firmware/export/config/ibassodx90.h b/firmware/export/config/ibassodx90.h index 68a728eab4..6de06d9e27 100644 --- a/firmware/export/config/ibassodx90.h +++ b/firmware/export/config/ibassodx90.h @@ -1,9 +1,30 @@ -/* - * This config file is for Rockbox as an application on Android - */ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +/* This config file is for Rockbox as an application on Android without JVM. */ /* We don't run on hardware directly */ -#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID) +#define CONFIG_PLATFORM PLATFORM_HOSTED /* For Rolo and boot loader */ #define MODEL_NUMBER 95 @@ -41,16 +62,14 @@ #define LCD_PIXELFORMAT RGB565 #define HAVE_LCD_ENABLE +#define HAVE_LCD_SHUTDOWN +#define HAVE_LCD_SLEEP +#define HAVE_LCD_SLEEP_SETTING /* define this to indicate your device's keypad */ #define HAVE_TOUCHSCREEN #define HAVE_BUTTON_DATA - -/* define this if you have RTC RAM available for settings */ -//#define HAVE_RTC_RAM - -/* define this if you have a real-time clock */ -//#define CONFIG_RTC APPLICATION +#define HAS_BUTTON_HOLD /* Define this if you have a software controlled poweroff */ #define HAVE_SW_POWEROFF @@ -77,6 +96,10 @@ /* Define this if you do software codec */ #define CONFIG_CODEC SWCODEC +#define HAVE_SW_TONE_CONTROLS +#define HAVE_SW_VOLUME_CONTROL +#define HW_SAMPR_CAPS SAMPR_CAP_ALL +#define HAVE_PLAY_FREQ //#define HAVE_MULTIMEDIA_KEYS #define CONFIG_KEYPAD DX50_PAD @@ -84,13 +107,6 @@ /* define this if the target has volume keys which can be used in the lists */ #define HAVE_VOLUME_IN_LIST -/* define this if the host platform can change volume outside of rockbox */ -//#define PLATFORM_HAS_VOLUME_CHANGE - -#define HAVE_SW_TONE_CONTROLS - -#define HAVE_SW_VOLUME_CONTROL - #define BATTERY_CAPACITY_DEFAULT 2100 /* default battery capacity */ #define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */ #define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */ @@ -101,22 +117,14 @@ #define CONFIG_CHARGING CHARGING_MONITOR -#define NO_LOW_BATTERY_SHUTDOWN - /* Define current usage levels. */ #define CURRENT_NORMAL 210 /* 10 hours from a 2100 mAh battery */ #define CURRENT_BACKLIGHT 30 /* TBD */ #define CURRENT_RECORD 0 /* no recording */ -/* Define this to the CPU frequency */ -/* -#define CPU_FREQ 48000000 -*/ - /* define this if the hardware can be powered off while charging */ #define HAVE_POWEROFF_WHILE_CHARGING - /* Offset ( in the firmware file's header ) to the file CRC */ #define FIRMWARE_OFFSET_FILE_CRC 0 @@ -128,9 +136,6 @@ /* Define this if a programmable hotkey is mapped */ #define HAVE_HOTKEY -#define BOOTDIR "/.rockbox" - /* No special storage */ #define CONFIG_STORAGE STORAGE_HOSTFS #define HAVE_STORAGE_FLUSH - diff --git a/firmware/export/hosted_codec.h b/firmware/export/hosted_codec.h index 00ab099772..5391ca8ee9 100644 --- a/firmware/export/hosted_codec.h +++ b/firmware/export/hosted_codec.h @@ -25,9 +25,7 @@ && !(CONFIG_PLATFORM & PLATFORM_MAEMO5) AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -80, 0, 0) #else -#if !defined(DX50) && !defined(DX90) #define AUDIOHW_CAPS (MONO_VOL_CAP) -#endif AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -99, 0, 0) #endif /* CONFIG_PLATFORM & PLATFORM_SDL */ diff --git a/firmware/export/pcm_mixer.h b/firmware/export/pcm_mixer.h index f7f869eaaf..b418a5d347 100644 --- a/firmware/export/pcm_mixer.h +++ b/firmware/export/pcm_mixer.h @@ -30,13 +30,15 @@ #if CONFIG_CPU == PP5002 /* There's far less time to do mixing because HW FIFOs are short */ #define MIX_FRAME_SAMPLES 64 -#elif (CONFIG_PLATFORM & PLATFORM_MAEMO5) +#elif (CONFIG_PLATFORM & PLATFORM_MAEMO5) || defined(DX50) || defined(DX90) /* Maemo 5 needs 2048 samples for decent performance. Otherwise the locking overhead inside gstreamer costs too much */ +/* iBasso Devices: Match Rockbox PCM buffer size to ALSA PCM buffer size + to minimize memory transfers. */ #define MIX_FRAME_SAMPLES 2048 +#else /* Assume HW DMA engine is available or sufficient latency exists in the PCM pathway */ -#else #define MIX_FRAME_SAMPLES 256 #endif diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index b04d669716..fdbf081329 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h @@ -40,10 +40,13 @@ #define ROCKBOX_DIR_LEN (sizeof(ROCKBOX_DIR)-1) #endif /* def __PCTOOL__ */ -#if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) +#if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) #if defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) #define HOME_DIR "/mnt/media0" +#elif defined(DX50) || defined(DX90) +/* Where to put save files like recordings, playlists, screen dumps ...*/ +#define HOME_DIR "/mnt/sdcard" #else #define HOME_DIR "/" #endif @@ -80,7 +83,7 @@ #define PLUGIN_DEMOS_DIR PLUGIN_DIR "/demos" #define VIEWERS_DIR PLUGIN_DIR "/viewers" -#if defined(APPLICATION) && !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) +#if defined(APPLICATION) && !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90)) #define PLUGIN_DATA_DIR ROCKBOX_DIR "/rocks.data" #define PLUGIN_GAMES_DATA_DIR PLUGIN_DATA_DIR #define PLUGIN_APPS_DATA_DIR PLUGIN_DATA_DIR diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 35c5c639f6..4cfcbbd56d 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -24,7 +24,9 @@ #include "kernel.h" #include "thread.h" #include "debug.h" +#if !defined(DX50) && !defined(DX90) #include "adc.h" +#endif #include "string.h" #include "storage.h" #include "power.h" diff --git a/firmware/target/hosted/android/dx50/adc-target.h b/firmware/target/hosted/android/dx50/adc-target.h deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/firmware/target/hosted/android/dx50/backlight-dx50.c b/firmware/target/hosted/android/dx50/backlight-dx50.c deleted file mode 100644 index 8eb4c58191..0000000000 --- a/firmware/target/hosted/android/dx50/backlight-dx50.c +++ /dev/null @@ -1,76 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * 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 "lcd-target.h" -#include -#include -#include "unistd.h" - -bool backlight_hw_init(void) -{ - /* We have nothing to do */ - return true; -} - -void backlight_hw_on(void) -{ - FILE *f = fopen("/sys/power/state", "w"); - fputs("on", f); - fclose(f); - lcd_enable(true); -} - -void backlight_hw_off(void) -{ - FILE * f; - - /* deny the player to sleep deep */ - f = fopen("/sys/power/wake_lock", "w"); - fputs("player", f); - fclose(f); - - /* deny the player to mute */ - f = fopen("/sys/class/codec/wm8740_mute", "w"); - fputc(0, f); - fclose(f); - - /* turn off backlight */ - f = fopen("/sys/power/state", "w"); - fputs("mem", f); - fclose(f); - -} - -void backlight_hw_brightness(int brightness) -{ - /* Just another check... */ - if (brightness > MAX_BRIGHTNESS_SETTING) - brightness = MAX_BRIGHTNESS_SETTING; - if (brightness < MIN_BRIGHTNESS_SETTING) - brightness = MIN_BRIGHTNESS_SETTING; - - FILE *f = fopen("/sys/devices/platform/rk29_backlight/backlight/rk28_bl/brightness", "w"); - fprintf(f, "%d", brightness); - fclose(f); -} diff --git a/firmware/target/hosted/android/dx50/button-dx50.c b/firmware/target/hosted/android/dx50/button-dx50.c deleted file mode 100644 index 250b448491..0000000000 --- a/firmware/target/hosted/android/dx50/button-dx50.c +++ /dev/null @@ -1,316 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 "button.h" -#include "buttonmap.h" -#include "config.h" -#include "kernel.h" -#include "system.h" -#include "touchscreen.h" -#include "powermgmt.h" -#include "backlight.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -static struct pollfd *ufds; -static char **device_names; -static int nfds; - -enum { - PRINT_DEVICE_ERRORS = 1U << 0, - PRINT_DEVICE = 1U << 1, - PRINT_DEVICE_NAME = 1U << 2, - PRINT_DEVICE_INFO = 1U << 3, - PRINT_VERSION = 1U << 4, - PRINT_POSSIBLE_EVENTS = 1U << 5, - PRINT_INPUT_PROPS = 1U << 6, - PRINT_HID_DESCRIPTOR = 1U << 7, - - PRINT_ALL_INFO = (1U << 8) - 1, - - PRINT_LABELS = 1U << 16, -}; - -static int last_y, last_x; -static int last_btns; - -static enum { - STATE_UNKNOWN, - STATE_UP, - STATE_DOWN -} last_touch_state = STATE_UNKNOWN; - - -static int open_device(const char *device, int print_flags) -{ - int fd; - struct pollfd *new_ufds; - char **new_device_names; - - fd = open(device, O_RDWR); - if(fd < 0) { - if(print_flags & PRINT_DEVICE_ERRORS) - fprintf(stderr, "could not open %s, %s\n", device, strerror(errno)); - return -1; - } - - new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1)); - if(new_ufds == NULL) { - fprintf(stderr, "out of memory\n"); - close(fd); - return -1; - } - ufds = new_ufds; - new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1)); - if(new_device_names == NULL) { - fprintf(stderr, "out of memory\n"); - close(fd); - return -1; - } - device_names = new_device_names; - - ufds[nfds].fd = fd; - ufds[nfds].events = POLLIN; - device_names[nfds] = strdup(device); - nfds++; - - return 0; -} - - - -static int scan_dir(const char *dirname, int print_flags) -{ - char devname[PATH_MAX]; - char *filename; - DIR *dir; - struct dirent *de; - dir = opendir(dirname); - if(dir == NULL) - return -1; - strcpy(devname, dirname); - filename = devname + strlen(devname); - *filename++ = '/'; - while((de = readdir(dir))) { - if(de->d_name[0] == '.' && - (de->d_name[1] == '\0' || - (de->d_name[1] == '.' && de->d_name[2] == '\0'))) - continue; - strcpy(filename, de->d_name); - open_device(devname, print_flags); - } - closedir(dir); - return 0; -} - -bool _hold; - -bool button_hold() -{ - FILE *f = fopen("/sys/class/axppower/holdkey", "r"); - char x; - fscanf(f, "%c", &x); - fclose(f); - _hold = !(x&STATE_UNLOCKED); - return _hold; -} - - -void button_init_device(void) -{ - int res; - int print_flags = 0; - const char *device = NULL; - const char *device_path = "/dev/input"; - - nfds = 1; - ufds = calloc(1, sizeof(ufds[0])); - ufds[0].fd = inotify_init(); - ufds[0].events = POLLIN; - if(device) { - res = open_device(device, print_flags); - if(res < 0) { - // return 1; - } - } else { - res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); - if(res < 0) { - fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno)); - // return 1; - } - res = scan_dir(device_path, print_flags); - if(res < 0) { - fprintf(stderr, "scan dir failed for %s\n", device_path); - // return 1; - } - } - - button_hold(); //store state - - set_rockbox_ready(); -} - -void touchscreen_enable_device(bool en) -{ - (void)en; /* FIXME: do something smart */ -} - - -int keycode_to_button(int keyboard_key) -{ - switch(keyboard_key){ - case KEYCODE_PWR: - return BUTTON_POWER; - - case KEYCODE_PWR_LONG: - return BUTTON_POWER_LONG; - - case KEYCODE_VOLPLUS: - return BUTTON_VOL_UP; - - case KEYCODE_VOLMINUS: - return BUTTON_VOL_DOWN; - - case KEYCODE_PREV: - return BUTTON_LEFT; - - case KEYCODE_NEXT: - return BUTTON_RIGHT; - - case KEYCODE_PLAY: - return BUTTON_PLAY; - - case KEYCODE_HOLD: - button_hold(); /* store state */ - backlight_hold_changed(_hold); - return BUTTON_NONE; - - default: - return BUTTON_NONE; - } -} - - -int button_read_device(int *data) -{ - int i; - int res; - struct input_event event; - int read_more; - unsigned button = 0; - - if(last_btns & BUTTON_POWER_LONG) - { - return last_btns; /* simulate repeat */ - } - - do { - read_more = 0; - poll(ufds, nfds, 10); - for(i = 1; i < nfds; i++) { - if(ufds[i].revents & POLLIN) { - res = read(ufds[i].fd, &event, sizeof(event)); - if(res < (int)sizeof(event)) { - fprintf(stderr, "could not get event\n"); - } - - switch(event.type) - { - case 1: /* HW-Button */ - button = keycode_to_button(event.code); - if (_hold) /* we have to wait for keycode_to_button() first to maybe clear hold state */ - break; - if (button == BUTTON_NONE) - { - last_btns = button; - break; - } -/* workaround for a wrong feedback, only present with DX90 */ -#if defined(DX90) - if (button == BUTTON_RIGHT && (last_btns & BUTTON_LEFT == BUTTON_LEFT) && !event.value) - { - button = BUTTON_LEFT; - } -#endif - if (event.value) - last_btns |= button; - else - last_btns &= (~button); - - break; - - case 3: /* Touchscreen */ - if(_hold) - break; - - switch(event.code) - { - case 53: /* x -> next will be y */ - last_x = event.value; - read_more = 1; - break; - case 54: /* y */ - last_y = event.value; - break; - case 57: /* press -> next will be x */ - if(event.value==1) - { - last_touch_state = STATE_DOWN; - read_more = 1; - } - else - last_touch_state = STATE_UP; - break; - } - break; - } - } - } - } while(read_more); - - - /* Get grid button/coordinates based on the current touchscreen mode - * - * Caveat: the caller seemingly depends on *data always being filled with - * the last known touchscreen position, so always call - * touchscreen_to_pixels() */ - int touch = touchscreen_to_pixels(last_x, last_y, data); - - if (last_touch_state == STATE_DOWN) - return last_btns | touch; - - return last_btns; -} - diff --git a/firmware/target/hosted/android/dx50/lcd-dx50.c b/firmware/target/hosted/android/dx50/lcd-dx50.c deleted file mode 100644 index 4d78baaf00..0000000000 --- a/firmware/target/hosted/android/dx50/lcd-dx50.c +++ /dev/null @@ -1,120 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id: lcd-bitmap.c 29248 2011-02-08 20:05:25Z thomasjfox $ - * - * Copyright (C) 2011 Lorenzo Miori, Thomas Martitz - * Copyright (C) 2013 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 -#include -#include -#include "config.h" -#include "file.h" -#include "debug.h" -#include "system.h" -#include "screendump.h" -#include "lcd.h" -#include "lcd-target.h" - -static int dev_fd = 0; -fb_data *dev_fb = 0; - -#ifdef HAVE_LCD_SHUTDOWN -void lcd_shutdown(void) -{ - printf("FB closed."); - munmap(dev_fb, FRAMEBUFFER_SIZE); - close(dev_fd); -} -#endif - -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/graphics/fb0", O_RDWR); - if (dev_fd == -1) { - perror("Error: cannot open framebuffer device"); - exit(1); - } - - /* 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); - } - /* framebuffer does not fit the screen, a bug of iBassos Firmware, not rockbox. - cannot be solved with parameters */ - vinfo.bits_per_pixel = LCD_DEPTH; - vinfo.xres = vinfo.xres_virtual = vinfo.width = LCD_WIDTH; - vinfo.yres = vinfo.yres_virtual = vinfo.height = LCD_HEIGHT; - - if (ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo)) { - perror("fbset(ioctl)"); - exit(4); - } - - /* Figure out the size of the screen in bytes */ - screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; - if (screensize != FRAMEBUFFER_SIZE) { - 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); - } - - /* Be sure to turn on display at startup */ - ioctl(dev_fd, FBIOBLANK, VESA_NO_BLANKING); -#ifdef HAVE_LCD_ENABLE - lcd_set_active(true); -#endif -} - -#ifdef HAVE_LCD_ENABLE -void lcd_enable(bool enable) - { - if (lcd_active() == enable) - return; - - lcd_set_active(enable); - - /* Turn on or off the display using Linux interface */ - ioctl(dev_fd, FBIOBLANK, enable ? VESA_NO_BLANKING : VESA_POWERDOWN); - - if (enable) - send_event(LCD_EVENT_ACTIVATION, NULL); -} -#endif diff --git a/firmware/target/hosted/android/dx50/pcm-dx50.c b/firmware/target/hosted/android/dx50/pcm-dx50.c deleted file mode 100644 index e7695873a0..0000000000 --- a/firmware/target/hosted/android/dx50/pcm-dx50.c +++ /dev/null @@ -1,364 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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. - * - * To make the async callback safer, an alternative stack is installed, since - * it's run from a signal hanlder (which otherwise uses the user stack). If - * tick tasks are run from a signal handler too, please install - * an alternative stack for it too. - * - * 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. - */ - - -#include "autoconf.h" - -#include -#include -#include -#include -#include "tinyalsa/asoundlib.h" -#include "tinyalsa/asound.h" -#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 "audiohw.h" - -#include -#include - -static const snd_pcm_format_t format = PCM_FORMAT_S16_LE; /* sample format */ -static const int channels = 2; /* count of channels */ -static unsigned int rate = 44100; /* stream rate */ - -typedef struct pcm snd_pcm_t; -static snd_pcm_t *handle; -struct pcm_config config; - -static snd_pcm_sframes_t period_size = 512; /* if set to >= 1024, all timers become even slower */ -static char *frames; - -static const void *pcm_data = 0; -static size_t pcm_size = 0; - -static int recursion; - -static int set_hwparams(snd_pcm_t *handle) -{ - int err; - if (!frames) - frames = malloc(pcm_frames_to_bytes(handle, pcm_get_buffer_size(handle))); - err = 0; /* success */ - return err; -} - - -/* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */ -static bool fill_frames(void) -{ - size_t copy_n, frames_left = period_size; - bool new_buffer = false; - - while (frames_left > 0) - { - if (!pcm_size) - { - new_buffer = true; - if (!pcm_play_dma_complete_callback(PCM_DMAST_OK, &pcm_data, - &pcm_size)) - { - return false; - } - } - copy_n = MIN((size_t)pcm_size, pcm_frames_to_bytes(handle, frames_left)); - memcpy(&frames[pcm_frames_to_bytes(handle, period_size-frames_left)], pcm_data, copy_n); - - pcm_data += copy_n; - pcm_size -= copy_n; - frames_left -= pcm_bytes_to_frames(handle, copy_n); - - if (new_buffer) - { - new_buffer = false; - pcm_play_dma_status_callback(PCM_DMAST_STARTED); - } - } - return true; -} - - -static void pcm_tick(void) -{ - if (fill_frames()) - { - if (pcm_write(handle, frames, pcm_frames_to_bytes(handle, period_size))) { - printf("Error playing sample\n"); - return;//break; - } - - } - else - { - DEBUGF("%s: No Data.\n", __func__); - return;//break; - } -} - -static int async_rw(snd_pcm_t *handle) -{ - int err; - snd_pcm_sframes_t sample_size; - char *samples; - - /* fill buffer with silence to initiate playback without noisy click */ - sample_size = pcm_frames_to_bytes(handle, pcm_get_buffer_size(handle)); - samples = malloc(sample_size); - - memset(samples, 0, sample_size); - - err = pcm_write(handle, samples, sample_size); - free(samples); - - if (err != 0) - { - DEBUGF("Initial write error: %d\n", err); - return err; - } - if (pcm_state(handle) == PCM_STATE_PREPARED) - { - err = pcm_start(handle); - if (err < 0) - { - DEBUGF("Start error: %d\n", err); - return err; - } - } - return 0; -} - -void cleanup(void) -{ - free(frames); - frames = NULL; - pcm_close(handle); -} - -void pcm_play_dma_init(void) -{ - config.channels = channels; - config.rate = rate; - config.period_size = period_size; - config.period_count = 4; - config.format = format; - config.start_threshold = 0; - config.stop_threshold = 0; - config.silence_threshold = 0; - - - handle = pcm_open(0, 0, PCM_OUT, &config); - if (!handle || !pcm_is_ready(handle)) { - printf("Unable to open PCM device: %s\n", pcm_get_error(handle)); - return; - } - - pcm_dma_apply_settings(); - - tick_add_task(pcm_tick); - - atexit(cleanup); - return; -} - - -void pcm_play_lock(void) -{ - if (recursion++ == 0) - tick_remove_task(pcm_tick); -} - -void pcm_play_unlock(void) -{ - if (--recursion == 0) - tick_add_task(pcm_tick); -} - -static void pcm_dma_apply_settings_nolock(void) -{ - set_hwparams(handle); -} - -void pcm_dma_apply_settings(void) -{ - pcm_play_lock(); - pcm_dma_apply_settings_nolock(); - pcm_play_unlock(); -} - - -void pcm_play_dma_pause(bool pause) -{ - (void)pause; -} - - -void pcm_play_dma_stop(void) -{ - pcm_stop(handle); -} - -void pcm_play_dma_start(const void *addr, size_t size) -{ -#if defined(DX50) || defined(DX90) - /* headphone output relay: if this is done at startup already, a loud click is audible on headphones. Here, some time later, - the output caps are charged a bit and the click is much softer */ - system("/system/bin/muteopen"); -#endif - pcm_dma_apply_settings_nolock(); - - pcm_data = addr; - pcm_size = size; - - while (1) - { - snd_pcm_state_t state = pcm_state(handle); - switch (state) - { - case PCM_STATE_RUNNING: - return; - case PCM_STATE_XRUN: - { - printf("No handler for STATE_XRUN!\n"); - continue; - } - case 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: %d\n", err); - return; - } - case PCM_STATE_PAUSED: - { /* paused, simply resume */ - pcm_play_dma_pause(0); - return; - } - case PCM_STATE_DRAINING: - /* run until drained */ - continue; - default: - DEBUGF("Unhandled state: %d\n", 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) -{ - return; -} - -void pcm_set_mixer_volume(int volume) -{ -#if defined(DX50) || defined(DX90) - /* -990 to 0 -> 0 to 255 */ - int val = (volume+990)*255/990; -#if defined(DX50) - FILE *f = fopen("/dev/codec_volume", "w"); -#else /* DX90 */ - FILE *f = fopen("/sys/class/codec/es9018_volume", "w"); -#endif /* DX50 */ - fprintf(f, "%d", val); - fclose(f); -#else - (void)volume; -#endif /* DX50 || DX90 */ -} - -#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/android/dx50/powermgmt-dx50.c b/firmware/target/hosted/android/dx50/powermgmt-dx50.c deleted file mode 100644 index 713e8a977e..0000000000 --- a/firmware/target/hosted/android/dx50/powermgmt-dx50.c +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * 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 -#include -#include "config.h" -#include "power.h" -#include "powermgmt.h" - - -unsigned int power_input_status(void) -{ - int val; - FILE *f = fopen("/sys/class/power_supply/ac/present", "r"); - fscanf(f, "%d", &val); - fclose(f); - return val?POWER_INPUT_MAIN_CHARGER:POWER_INPUT_NONE; -} - - -/* Returns true, if battery is charging, false else. */ -bool charging_state( void ) -{ - /* Full, Charging, Discharging */ - char state[9]; - - /* true if charging. */ - bool charging = false; - - FILE *f = fopen( "/sys/class/power_supply/battery/status", "r" ); - if( f != NULL ) - { - if( fgets( state, 9, f ) != NULL ) - { - charging = ( strcmp( state, "Charging" ) == 0 ); - } - } - fclose( f ); - - return charging; -} - - -/* Values for stock PISEN battery. TODO: Needs optimization */ -const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = -{ - 3380 -}; - -const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = -{ - 3100 -}; - -/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ -const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = -{ - { 3370, 3650, 3700, 3740, 3780, 3820, 3870, 3930, 4000, 4090, 4190 } -}; - -/* Voltages (millivolt) of 0%, 10%, ... 100% when charging is enabled. */ -const unsigned short percent_to_volt_charge[11] = -{ - 3370, 3650, 3700, 3740, 3780, 3820, 3870, 3930, 4000, 4090, 4190 -}; - - -/* Returns battery voltage from android measurement [millivolts] */ -int _battery_voltage(void) -{ - int val; - FILE *f = fopen("/sys/class/power_supply/battery/voltage_now", "r"); - fscanf(f, "%d", &val); - fclose(f); - return (val/1000); -} - - diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c index 6279504e48..d13b8d6462 100644 --- a/firmware/target/hosted/android/system-android.c +++ b/firmware/target/hosted/android/system-android.c @@ -23,12 +23,6 @@ #include #include #include -#if defined(DX50) || defined(DX90) -#include -#include -#include -#include -#endif /* DX50 || DX90 */ #include #include "config.h" #include "system.h" @@ -37,83 +31,40 @@ -#if !defined(DX50) && !defined(DX90) /* global fields for use with various JNI calls */ static JavaVM *vm_ptr; JNIEnv *env_ptr; jobject RockboxService_instance; jclass RockboxService_class; -#endif /* !DX50 && !DX90 */ uintptr_t *stackbegin; uintptr_t *stackend; extern int main(void); -#if !defined(DX50) && !defined(DX90) extern void telephony_init_device(void); -#endif + void system_exception_wait(void) { -#if defined(DX50) || defined(DX90) - while(1); -#else intptr_t dummy = 0; while(button_read_device(&dummy) != BUTTON_BACK); -#endif /* DX50 || DX90 */ } void system_reboot(void) { -#if defined(DX50) || defined(DX90) - reboot(RB_AUTOBOOT); -#else power_off(); -#endif /* DX50 || DX90 */ } -#if !defined(DX50) && !defined(DX90) /* this is used to return from the entry point of the native library. */ static jmp_buf poweroff_buf; -#endif - void power_off(void) { -#if defined(DX50) || defined(DX90) - reboot(RB_POWER_OFF); -#else longjmp(poweroff_buf, 1); -#endif /* DX50 || DX90 */ } void system_init(void) { -#if defined(DX50) || defined(DX90) - volatile uintptr_t stack = 0; - stackbegin = stackend = (uintptr_t*) &stack; - - struct stat m1, m2; - stat("/mnt/", &m1); - do - { - /* waiting for storage to get mounted */ - stat("/sdcard/", &m2); - usleep(100000); - } - while(m1.st_dev == m2.st_dev); -/* here would be the correct place for 'system("/system/bin/muteopen");' (headphone-out relay) but in pcm-dx50.c, pcm_play_dma_start() - the output capacitors are charged already a bit and the click of the headphone-connection-relay is softer */ - -#if defined(DX90) - /* DAC needs to be unmuted on DX90 */ - FILE * f = fopen("/sys/class/codec/wm8740_mute", "w"); - fputc(0, f); - fclose(f); -#endif /* DX90 */ - -#else /* no better place yet */ telephony_init_device(); -#endif /* DX50 || DX90 */ } int hostfs_init(void) @@ -128,7 +79,6 @@ int hostfs_flush(void) return 0; } -#if !defined(DX50) && !defined(DX90) JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void* reserved) { @@ -169,7 +119,7 @@ Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this) /* simply return here. this will allow the VM to clean up objects and do * garbage collection */ } -#endif /* !DX50 && !DX90 */ + /* below is the facility for external (from other java threads) to safely call * into our snative code. When extracting rockbox.zip the main function is diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c index 0c9943b635..826ab5bbb1 100644 --- a/firmware/target/hosted/filesystem-app.c +++ b/firmware/target/hosted/filesystem-app.c @@ -47,7 +47,7 @@ static const char *rbhome; static const char rbhome[] = HOME_DIR; #endif -#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)) && !defined(__PCTOOL__) +#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90)) && !defined(__PCTOOL__) /* Special dirs are user-accessible (and user-writable) dirs which take priority * over the ones where Rockbox is installed to. Classic example would be * $HOME/.config/rockbox.org vs /usr/share/rockbox */ diff --git a/firmware/target/hosted/ibasso/android_ndk.make b/firmware/target/hosted/ibasso/android_ndk.make new file mode 100644 index 0000000000..e2f5c93db8 --- /dev/null +++ b/firmware/target/hosted/ibasso/android_ndk.make @@ -0,0 +1,49 @@ +# __________ __ ___ +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# +# Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 +# Copyright (C) 2014 by Mario Basister: iBasso DX90 port +# Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features +# Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY +# KIND, either express or implied. + + +# This is a glibc compatibility hack to provide a get_nprocs() replacement. +# The NDK ships cpu-features.c which has a compatible function android_getCpuCount() +CPUFEAT = $(ANDROID_NDK_PATH)/sources/android/cpufeatures +CPUFEAT_BUILD = $(BUILDDIR)/android-ndk/sources/android/cpufeatures +INCLUDES += -I$(CPUFEAT) +OTHER_SRC += $(CPUFEAT)/cpu-features.c +CLEANOBJS += $(CPUFEAT_BUILD)/cpu-features.o +$(CPUFEAT_BUILD)/cpu-features.o: $(CPUFEAT)/cpu-features.c + $(SILENT)mkdir -p $(dir $@) + $(call PRINTS,CC $(subst $(CPUFEAT)/,,$<))$(CC) -o $@ -c $(CPUFEAT)/cpu-features.c $(GCCOPTS) -Wno-unused + +.SECONDEXPANSION: +.PHONY: clean dirs + +DIRS += $(CPUFEAT_BUILD) + +.PHONY: +$(BUILDDIR)/$(BINARY): $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) $(CPUFEAT_BUILD)/cpu-features.o + $(call PRINTS,LD $(BINARY))$(CC) -o $@ $^ $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map + $(call PRINTS,OC $(@F))$(call objcopy,$@,$@) + +$(DIRS): + $(SILENT)mkdir -p $@ + +dirs: $(DIRS) + +clean:: + $(SILENT)rm -rf $(BUILDDIR)/android-ndk diff --git a/firmware/target/hosted/ibasso/audiohw-ibasso.c b/firmware/target/hosted/ibasso/audiohw-ibasso.c new file mode 100644 index 0000000000..447e133eba --- /dev/null +++ b/firmware/target/hosted/ibasso/audiohw-ibasso.c @@ -0,0 +1,81 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "debug.h" +#include "pcm_sw_volume.h" +#include "settings.h" + +#include "debug-ibasso.h" +#include "pcm-ibasso.h" + + +void audiohw_close(void) +{ + TRACE; + + pcm_close_device(); +} + + +void set_software_volume(void) +{ + /* -73dB (?) minimum software volume in decibels. See pcm-internal.h. */ + static const int SW_VOLUME_MIN = 730; + + int sw_volume_l = 0; + int sw_volume_r = 0; + + if(global_settings.balance > 0) + { + if(global_settings.balance == 100) + { + sw_volume_l = PCM_MUTE_LEVEL; + } + else + { + sw_volume_l -= SW_VOLUME_MIN * global_settings.balance / 100; + } + } + else if(global_settings.balance < 0) + { + if(global_settings.balance == -100) + { + sw_volume_r = PCM_MUTE_LEVEL; + } + else + { + sw_volume_r = SW_VOLUME_MIN * global_settings.balance / 100; + } + } + + DEBUGF("DEBUG %s: global_settings.balance: %d, sw_volume_l: %d, sw_volume_r: %d.", + __func__, + global_settings.balance, + sw_volume_l, + sw_volume_r); + + /* Emulate balance with software volume. */ + pcm_set_master_volume(sw_volume_l, sw_volume_r); +} diff --git a/firmware/target/hosted/ibasso/backlight-ibasso.c b/firmware/target/hosted/ibasso/backlight-ibasso.c new file mode 100644 index 0000000000..907980e01a --- /dev/null +++ b/firmware/target/hosted/ibasso/backlight-ibasso.c @@ -0,0 +1,132 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" +#include "lcd.h" +#include "panic.h" + +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +/* + Prevent excessive backlight_hw_on usage. + Required for proper seeking. +*/ +static bool _backlight_enabled = false; + + +bool backlight_hw_init(void) +{ + TRACE; + + /* + /sys/devices/platform/rk29_backlight/backlight/rk28_bl/bl_power + 0: backlight on + */ + if(! sysfs_set_int(SYSFS_BACKLIGHT_POWER, 0)) + { + DEBUGF("ERROR %s: Can not enable backlight.", __func__); + panicf("ERROR %s: Can not enable backlight.", __func__); + return false; + } + + _backlight_enabled = true; + + return true; +} + + +void backlight_hw_on(void) +{ + if(! _backlight_enabled) + { + backlight_hw_init(); + lcd_enable(true); + } +} + + +void backlight_hw_off(void) +{ + TRACE; + + /* + /sys/devices/platform/rk29_backlight/backlight/rk28_bl/bl_power + 1: backlight off + */ + if(! sysfs_set_int(SYSFS_BACKLIGHT_POWER, 1)) + { + DEBUGF("ERROR %s: Can not disable backlight.", __func__); + return; + } + + lcd_enable(false); + + _backlight_enabled = false; +} + + +/* + Prevent excessive backlight_hw_brightness usage. + Required for proper seeking. +*/ +static int _current_brightness = -1; + + +void backlight_hw_brightness(int brightness) +{ + if(brightness > MAX_BRIGHTNESS_SETTING) + { + DEBUGF("DEBUG %s: Adjusting brightness from %d to MAX.", __func__, brightness); + brightness = MAX_BRIGHTNESS_SETTING; + } + if(brightness < MIN_BRIGHTNESS_SETTING) + { + DEBUGF("DEBUG %s: Adjusting brightness from %d to MIN.", __func__, brightness); + brightness = MIN_BRIGHTNESS_SETTING; + } + + if(_current_brightness == brightness) + { + return; + } + + TRACE; + + _current_brightness = brightness; + + /* + /sys/devices/platform/rk29_backlight/backlight/rk28_bl/max_brightness + 0 ... 255 + */ + if(! sysfs_set_int(SYSFS_BACKLIGHT_BRIGHTNESS, _current_brightness)) + { + DEBUGF("ERROR %s: Can not set brightness.", __func__); + return; + } +} diff --git a/firmware/target/hosted/android/dx50/backlight-target.h b/firmware/target/hosted/ibasso/backlight-target.h similarity index 69% rename from firmware/target/hosted/android/dx50/backlight-target.h rename to firmware/target/hosted/ibasso/backlight-target.h index 0dc7ce387a..aa8fafab04 100644 --- a/firmware/target/hosted/android/dx50/backlight-target.h +++ b/firmware/target/hosted/ibasso/backlight-target.h @@ -1,13 +1,15 @@ /*************************************************************************** - * __________ __ ___. + * __________ __ ___ * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id$ * - * Copyright (C) 2008 by Maurus Cuelenaere + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -18,14 +20,20 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef BACKLIGHT_TARGET_H -#define BACKLIGHT_TARGET_H + + +#ifndef _BACKLIGHT_TARGET_H_ +#define _BACKLIGHT_TARGET_H_ + #include + +/* See backlight.c */ bool backlight_hw_init(void); void backlight_hw_on(void); void backlight_hw_off(void); void backlight_hw_brightness(int brightness); -#endif /* BACKLIGHT_TARGET_H */ + +#endif diff --git a/firmware/target/hosted/ibasso/button-ibasso.c b/firmware/target/hosted/ibasso/button-ibasso.c new file mode 100644 index 0000000000..1694992ea4 --- /dev/null +++ b/firmware/target/hosted/ibasso/button-ibasso.c @@ -0,0 +1,420 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 +#include +#include +#include +#include + +#include "config.h" +#include "backlight.h" +#include "button.h" +#include "debug.h" +#include "panic.h" +#include "settings.h" +#include "touchscreen.h" + +#include "button-ibasso.h" +#include "button-target.h" +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +#define EVENT_TYPE_BUTTON 1 + +/* /dev/input/event0 */ +#define EVENT_CODE_BUTTON_LINEOUT 113 +#define EVENT_CODE_BUTTON_SPDIF 114 +#define EVENT_CODE_BUTTON_HOLD 115 + +/* /dev/input/event1 */ +#define EVENT_CODE_BUTTON_SDCARD 143 + + +#define EVENT_TYPE_TOUCHSCREEN 3 + +/* /dev/input/event2 */ +#define EVENT_CODE_TOUCHSCREEN_X 53 +#define EVENT_CODE_TOUCHSCREEN_Y 54 +#define EVENT_CODE_TOUCHSCREEN 57 + +#define EVENT_VALUE_TOUCHSCREEN_PRESS 1 +#define EVENT_VALUE_TOUCHSCREEN_RELEASE -1 + + +/* + Changing bit, when hold switch is toggled. + Bit is off when hold switch is engaged. +*/ +#define HOLD_SWITCH_BIT 16 + +/* + Changing bit, when coaxial out is plugged. + Bit is off when coaxial out is plugged in. +*/ +#define COAX_BIT 32 + +/* + Changing bit, when line out is plugged. + Bit is off when line out is plugged in. +*/ +#define SPDIF_BIT 64 + + +/* State of the hold switch; true: hold switch engaged. */ +static bool _hold = false; + + +/* See button.h. */ +bool button_hold(void) +{ + char hold_state; + if(! sysfs_get_char(SYSFS_HOLDKEY, &hold_state)) + { + DEBUGF("ERROR %s: Can not get hold switch state.", __func__); + hold_state = HOLD_SWITCH_BIT; + } + + /*DEBUGF("%s: hold_state: %d, %c.", __func__, hold_state, hold_state);*/ + + /*bool coax_connected = ! (hold_state & COAX_BIT); + bool spdif_connected = ! (hold_state & SPDIF_BIT);*/ + + _hold = ! (hold_state & HOLD_SWITCH_BIT); + + /*DEBUGF("%s: _hold: %d, coax_connected: %d, spdif_connected: %d.", __func__, _hold, coax_connected, spdif_connected);*/ + + return _hold; +} + + +/* Input devices monitored with poll API. */ +static struct pollfd* _fds = NULL; + + +/* Number of input devices monitored with poll API. */ +static nfds_t _nfds = 0; + + +/* The names of the devices in _fds. */ +static char** _device_names = NULL; + + +/* Open device device_name and add it to the list of polled devices. */ +static bool open_device(const char* device_name) +{ + int fd = open(device_name, O_RDONLY); + if(fd == -1) + { + DEBUGF("ERROR %s: open failed on %s.", __func__, device_name); + return false; + } + + struct pollfd* new_fds = realloc(_fds, sizeof(struct pollfd) * (_nfds + 1)); + if(new_fds == NULL) + { + DEBUGF("ERROR %s: realloc for _fds failed.", __func__); + panicf("ERROR %s: realloc for _fds failed.", __func__); + return false; + } + + _fds = new_fds; + _fds[_nfds].fd = fd; + _fds[_nfds].events = POLLIN; + + char** new_device_names = realloc(_device_names, sizeof(char*) * (_nfds + 1)); + if(new_device_names == NULL) + { + DEBUGF("ERROR %s: realloc for _device_names failed.", __func__); + panicf("ERROR %s: realloc for _device_names failed.", __func__); + return false; + } + + _device_names = new_device_names; + _device_names[_nfds] = strdup(device_name); + if(_device_names[_nfds] == NULL) + { + DEBUGF("ERROR %s: strdup failed.", __func__); + panicf("ERROR %s: strdup failed.", __func__); + return false; + } + + ++_nfds; + + DEBUGF("DEBUG %s: Opened device %s.", __func__, device_name); + + return true; +} + + +/* See button.h. */ +void button_init_device(void) +{ + TRACE; + + if((_fds != NULL) || (_nfds != 0) || (_device_names != NULL)) + { + DEBUGF("ERROR %s: Allready initialized.", __func__); + panicf("ERROR %s: Allready initialized.", __func__); + return; + } + + /* The input device directory. */ + static const char device_path[] = "/dev/input"; + + /* Path delimeter. */ + static const char delimeter[] = "/"; + + /* Open all devices in device_path. */ + DIR* dir = opendir(device_path); + if(dir == NULL) + { + DEBUGF("ERROR %s: opendir failed: errno: %d.", __func__, errno); + panicf("ERROR %s: opendir failed: errno: %d.", __func__, errno); + return; + } + + char device_name[PATH_MAX]; + strcpy(device_name, device_path); + strcat(device_name, delimeter); + char* device_name_idx = device_name + strlen(device_name); + + struct dirent* dir_entry; + while((dir_entry = readdir(dir))) + { + if( ((dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '\0')) + || ((dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '.') && (dir_entry->d_name[2] == '\0'))) + { + continue; + } + + strcpy(device_name_idx, dir_entry->d_name); + + /* Open and add device to _fds. */ + open_device(device_name); + } + + closedir(dir); + + /* Sanity check. */ + if(_nfds < 2) + { + DEBUGF("ERROR %s: No input devices.", __func__); + panicf("ERROR %s: No input devices.", __func__); + return; + } + + /* + Hold switch has a separate interface for its state. + Input events just report that it has been toggled, but not the state. + */ + button_hold(); +} + + +/* Last known touchscreen coordinates. */ +static int _last_x = 0; +static int _last_y = 0; + + +/* Last known touchscreen state. */ +static enum +{ + TOUCHSCREEN_STATE_UNKNOWN = 0, + TOUCHSCREEN_STATE_UP, + TOUCHSCREEN_STATE_DOWN +} _last_touch_state = TOUCHSCREEN_STATE_UNKNOWN; + + +static bool handle_touchscreen_event(__u16 code, __s32 value) +{ + bool read_more = false; + + switch(code) + { + case EVENT_CODE_TOUCHSCREEN_X: + { + _last_x = value; + + /* x -> next will be y. */ + read_more = true; + + break; + } + + case EVENT_CODE_TOUCHSCREEN_Y: + { + _last_y = value; + break; + } + + case EVENT_CODE_TOUCHSCREEN: + { + if(value == EVENT_VALUE_TOUCHSCREEN_PRESS) + { + _last_touch_state = TOUCHSCREEN_STATE_DOWN; + + /* Press -> next will be x. */ + read_more = true; + } + else + { + _last_touch_state = TOUCHSCREEN_STATE_UP; + } + break; + } + } + + return read_more; +} + + +/* Last known hardware buttons pressed. */ +static int _last_btns = BUTTON_NONE; + + +/* See button.h. */ +int button_read_device(int *data) +{ + bool read_more = true; + while(read_more) + { + read_more = false; + + /* Poll all input devices. */ + poll(_fds, _nfds, 0); + + for(nfds_t fds_idx = 0; fds_idx < _nfds; ++fds_idx) + { + if(! (_fds[fds_idx].revents & POLLIN)) + { + continue; + } + + struct input_event event; + if(read(_fds[fds_idx].fd, &event, sizeof(event)) < (int) sizeof(event)) + { + DEBUGF("ERROR %s: Read of input devices failed.", __func__); + continue; + } + + /*DEBUGF("DEBUG %s: device: %s, event.type: %d, event.code: %d, event.value: %d", __func__, _device_names[fds_idx], event.type, event.code, event.value);*/ + + switch(event.type) + { + case EVENT_TYPE_BUTTON: + { + if(event.code == EVENT_CODE_BUTTON_HOLD) + { + /* Hold switch toggled, update hold switch state. */ + button_hold(); + backlight_hold_changed(_hold); + + _last_btns = BUTTON_NONE; + break; + } + + _last_btns = handle_button_event(event.code, event.value, _last_btns); + + if(_hold) + { + /* Hold switch engaged. Ignore all button events. */ + _last_btns = BUTTON_NONE; + } + + /*DEBUGF("DEBUG %s: _last_btns: %#8.8x", __func__, _last_btns);*/ + break; + } + + case EVENT_TYPE_TOUCHSCREEN: + { + if(_hold) + { + /* Hold switch engaged, ignore all touchscreen events. */ + _last_touch_state = TOUCHSCREEN_STATE_UNKNOWN; + _last_btns = BUTTON_NONE; + } + else + { + read_more = handle_touchscreen_event(event.code, event.value); + /*DEBUGF("DEBUG %s: _last_touch_state: %d, _last_x: %d, _last_y: %d, read_more: %s", __func__, _last_touch_state, _last_x, _last_y, read_more ? "true" : "false");*/ + } + break; + } + } + } + } + + /* + Get grid button/coordinates based on the current touchscreen mode + Caveat: The caller seemingly depends on *data always being filled with + the last known touchscreen position, so always call + touchscreen_to_pixels(). + */ + int touch = touchscreen_to_pixels(_last_x, _last_y, data); + + if(_last_touch_state == TOUCHSCREEN_STATE_DOWN) + { + return _last_btns | touch; + } + + /*DEBUGF("DEBUG %s: _last_btns: %#8.8x.", __func__, _last_btns);*/ + + return _last_btns; +} + + +void button_close_device(void) +{ + TRACE; + + if(_fds) + { + for(nfds_t fds_idx = 0; fds_idx < _nfds; ++fds_idx) + { + close(_fds[fds_idx].fd); + } + free(_fds); + _fds = NULL; + } + + if(_device_names) + { + for(nfds_t fds_idx = 0; fds_idx < _nfds; ++fds_idx) + { + free(_device_names[fds_idx]); + } + free(_device_names); + _device_names = NULL; + } + + _nfds = 0; +} diff --git a/firmware/target/hosted/ibasso/button-ibasso.h b/firmware/target/hosted/ibasso/button-ibasso.h new file mode 100644 index 0000000000..09c09e7c83 --- /dev/null +++ b/firmware/target/hosted/ibasso/button-ibasso.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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_IBASSO_H_ +#define _BUTTON_IBASSO_H_ + + +#include + + +/* /dev/input/event0 */ +#define EVENT_CODE_BUTTON_PWR 116 +#define EVENT_CODE_BUTTON_PWR_LONG 117 + +/* /dev/input/event1 */ +#define EVENT_CODE_BUTTON_VOLPLUS 158 +#define EVENT_CODE_BUTTON_VOLMINUS 159 +#define EVENT_CODE_BUTTON_REV 160 +#define EVENT_CODE_BUTTON_PLAY 161 +#define EVENT_CODE_BUTTON_NEXT 162 + +#define EVENT_VALUE_BUTTON_PRESS 1 +#define EVENT_VALUE_BUTTON_RELEASE 0 + + +/* + Handle hardware button events. + code: Input event code. + value: Input event value. + last_btns: Last known pressed buttons. + Returns: Currently pressed buttons as bitmask (BUTTON_ values in button-target.h). +*/ +int handle_button_event(__u16 code, __s32 value, int last_btns); + + +/* Clean up the button device handler. */ +void button_close_device(void); + + +#endif diff --git a/firmware/target/hosted/android/dx50/button-target.h b/firmware/target/hosted/ibasso/button-target.h similarity index 63% rename from firmware/target/hosted/android/dx50/button-target.h rename to firmware/target/hosted/ibasso/button-target.h index adc9cf6bfd..d1b3c8a8de 100644 --- a/firmware/target/hosted/android/dx50/button-target.h +++ b/firmware/target/hosted/ibasso/button-target.h @@ -1,32 +1,32 @@ /*************************************************************************** - * __________ __ ___. + * __________ __ ___ * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id$ * - * Copyright (C) 2007 by Rob Purchase + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features * * 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.r + * 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 -#define HAS_BUTTON_HOLD - -/* Main unit's buttons */ +/* Hardware buttons. */ #define BUTTON_LEFT 0x00000001 #define BUTTON_RIGHT 0x00000002 #define BUTTON_PLAY 0x00000004 @@ -35,25 +35,15 @@ #define BUTTON_VOL_DOWN 0x00000020 #define BUTTON_POWER_LONG 0x00000040 -#define BUTTON_MAIN (BUTTON_LEFT|BUTTON_VOL_UP|BUTTON_VOL_DOWN\ - |BUTTON_RIGHT|BUTTON_PLAY|BUTTON_POWER|BUTTON_POWER_LONG) +#define BUTTON_MAIN ( BUTTON_LEFT | BUTTON_VOL_UP | BUTTON_VOL_DOWN | BUTTON_RIGHT \ + | BUTTON_PLAY | BUTTON_POWER | BUTTON_POWER_LONG) -#define KEYCODE_LINEOUT 113 -#define KEYCODE_SPDIF 114 -#define KEYCODE_HOLD 115 -#define KEYCODE_PWR 116 -#define KEYCODE_PWR_LONG 117 -#define KEYCODE_SD 143 -#define KEYCODE_VOLPLUS 158 -#define KEYCODE_VOLMINUS 159 -#define KEYCODE_PREV 160 -#define KEYCODE_NEXT 162 -#define KEYCODE_PLAY 161 -#define STATE_UNLOCKED 16 -#define STATE_SPDIF_UNPLUGGED 32 + +#define STATE_SPDIF_UNPLUGGED 32 #define STATE_LINEOUT_UNPLUGGED 64 -/* Touch Screen Area Buttons */ + +/* Touchscreen area buttons 3x3 grid. */ #define BUTTON_TOPLEFT 0x00001000 #define BUTTON_TOPMIDDLE 0x00002000 #define BUTTON_TOPRIGHT 0x00004000 @@ -65,8 +55,9 @@ #define BUTTON_BOTTOMRIGHT 0x00100000 -/* Software power-off */ -#define POWEROFF_BUTTON BUTTON_POWER_LONG -#define POWEROFF_COUNT 0 +/* Power-off */ +#define POWEROFF_BUTTON BUTTON_POWER_LONG +#define POWEROFF_COUNT 0 -#endif /* _BUTTON_TARGET_H_ */ + +#endif diff --git a/firmware/target/hosted/ibasso/debug-ibasso.c b/firmware/target/hosted/ibasso/debug-ibasso.c new file mode 100644 index 0000000000..6295de1f6c --- /dev/null +++ b/firmware/target/hosted/ibasso/debug-ibasso.c @@ -0,0 +1,70 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" + +#include "debug-ibasso.h" + + +static const char log_tag[] = "Rockbox"; + + +void debug_init(void) +{} + + +void debugf(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, fmt, ap); + va_end(ap); +} + + +void ldebugf(const char* file, int line, const char *fmt, ...) +{ + va_list ap; + /* 13: 5 literal chars and 8 chars for the line number. */ + char buf[strlen(file) + strlen(fmt) + 13]; + snprintf(buf, sizeof(buf), "%s (%d): %s", file, line, fmt); + va_start(ap, fmt); + __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, buf, ap); + va_end(ap); +} + + +void debug_trace(const char* function) +{ + static const char trace_tag[] = "TRACE: "; + char msg[strlen(trace_tag) + strlen(function) + 1]; + snprintf(msg, sizeof(msg), "%s%s", trace_tag, function); + __android_log_write(ANDROID_LOG_DEBUG, log_tag, msg); +} diff --git a/firmware/target/hosted/ibasso/debug-ibasso.h b/firmware/target/hosted/ibasso/debug-ibasso.h new file mode 100644 index 0000000000..456f189a5a --- /dev/null +++ b/firmware/target/hosted/ibasso/debug-ibasso.h @@ -0,0 +1,38 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 _DEBUG_IBASSO_H_ +#define _DEBUG_IBASSO_H_ + + +void debug_trace(const char* function); + + +#ifdef DEBUG +#define TRACE debug_trace(__func__) +#else +#define TRACE +#endif + +#endif \ No newline at end of file diff --git a/firmware/target/hosted/ibasso/dx50/audiohw-dx50.c b/firmware/target/hosted/ibasso/dx50/audiohw-dx50.c new file mode 100644 index 0000000000..5e61348c8d --- /dev/null +++ b/firmware/target/hosted/ibasso/dx50/audiohw-dx50.c @@ -0,0 +1,68 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "debug.h" + +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +extern void set_software_volume(void); + + +void audiohw_set_volume(int volume) +{ + set_software_volume(); + + /* + See codec-dx50.h. + -128db -> -1 (adjusted to 0, mute) + -127dB to 0dB -> 1 to 255 in steps of 2 + volume is in centibels (tenth-decibels). + */ + int volume_adjusted = (volume / 10) * 2 + 255; + + DEBUGF("DEBUG %s: volume: %d, volume_adjusted: %d.", __func__, volume, volume_adjusted); + + if(volume_adjusted > 255) + { + DEBUGF("DEBUG %s: Adjusting volume from %d to 255.", __func__, volume); + volume_adjusted = 255; + } + if(volume_adjusted < 0) + { + DEBUGF("DEBUG %s: Adjusting volume from %d to 0.", __func__, volume); + volume_adjusted = 0; + } + + /* + /dev/codec_volume + 0 ... 255 + */ + if(! sysfs_set_int(SYSFS_DX50_CODEC_VOLUME, volume_adjusted)) + { + DEBUGF("ERROR %s: Can not set volume.", __func__); + } +} diff --git a/firmware/target/hosted/ibasso/dx50/button-dx50.c b/firmware/target/hosted/ibasso/dx50/button-dx50.c new file mode 100644 index 0000000000..b4f6952d44 --- /dev/null +++ b/firmware/target/hosted/ibasso/dx50/button-dx50.c @@ -0,0 +1,96 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "button.h" + +#include "button-ibasso.h" + + +int handle_button_event(__u16 code, __s32 value, int last_btns) +{ + int button = BUTTON_NONE; + + switch(code) + { + case EVENT_CODE_BUTTON_PWR: + { + button = BUTTON_POWER; + break; + } + + case EVENT_CODE_BUTTON_PWR_LONG: + { + button = BUTTON_POWER_LONG; + break; + } + + case EVENT_CODE_BUTTON_VOLPLUS: + { + button = BUTTON_VOL_UP; + break; + } + + case EVENT_CODE_BUTTON_VOLMINUS: + { + button = BUTTON_VOL_DOWN; + break; + } + + case EVENT_CODE_BUTTON_REV: + { + button = BUTTON_LEFT; + break; + } + + case EVENT_CODE_BUTTON_PLAY: + { + button = BUTTON_PLAY; + break; + } + + case EVENT_CODE_BUTTON_NEXT: + { + button = BUTTON_RIGHT; + break; + } + + default: + { + return BUTTON_NONE; + } + } + + int buttons = last_btns; + if(value == EVENT_VALUE_BUTTON_PRESS) + { + buttons = (last_btns | button); + } + else + { + buttons = (last_btns & (~ button)); + } + + return buttons; +} diff --git a/firmware/target/hosted/ibasso/dx50/codec-dx50.h b/firmware/target/hosted/ibasso/dx50/codec-dx50.h new file mode 100644 index 0000000000..89a1a3f1c4 --- /dev/null +++ b/firmware/target/hosted/ibasso/dx50/codec-dx50.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 _CODEC_DX50_H_ +#define _CODEC_DX50_H_ + + +#define AUDIOHW_CAPS MONO_VOL_CAP + + +/* + http://www.wolfsonmicro.com/media/76425/WM8740.pdf + + 0.5 * ( x - 255 ) = ydB 1 <= x <= 255 + mute x = 0 + + x = 255 -> 0dB + . + . + . + x = 2 -> -126.5dB + x = 1 -> -127dB + x = 0 -> -128dB + + See audiohw.h, sound.c. +*/ +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -128, 0, -30) + + +#endif diff --git a/firmware/target/hosted/ibasso/dx90/audiohw-dx90.c b/firmware/target/hosted/ibasso/dx90/audiohw-dx90.c new file mode 100644 index 0000000000..ef18aae4bd --- /dev/null +++ b/firmware/target/hosted/ibasso/dx90/audiohw-dx90.c @@ -0,0 +1,63 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "debug.h" + +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +extern void set_software_volume(void); + + +void audiohw_set_volume(int volume) +{ + set_software_volume(); + + /* See codec-dx90.h. -2550 to 0 -> 0 to 255 */ + int volume_adjusted = ((volume + 2550) / 10); + + DEBUGF("DEBUG %s: volume: %d, volume_adjusted: %d.", __func__, volume, volume_adjusted); + + if(volume_adjusted > 255) + { + DEBUGF("DEBUG %s: Adjusting volume from %d to 255.", __func__, volume); + volume_adjusted = 255; + } + if(volume_adjusted < 0) + { + DEBUGF("DEBUG %s: Adjusting volume from %d to 0.", __func__, volume); + volume_adjusted = 0; + } + + /* + /sys/class/codec/es9018_volume + 0 ... 255 + */ + if(! sysfs_set_int(SYSFS_DX90_ES9018_VOLUME, volume_adjusted)) + { + DEBUGF("ERROR %s: Can not set volume.", __func__); + } +} diff --git a/firmware/target/hosted/ibasso/dx90/button-dx90.c b/firmware/target/hosted/ibasso/dx90/button-dx90.c new file mode 100644 index 0000000000..27e4be0c1e --- /dev/null +++ b/firmware/target/hosted/ibasso/dx90/button-dx90.c @@ -0,0 +1,104 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "button.h" + +#include "button-ibasso.h" + + +int handle_button_event(__u16 code, __s32 value, int last_btns) +{ + int button = BUTTON_NONE; + + switch(code) + { + case EVENT_CODE_BUTTON_PWR: + { + button = BUTTON_POWER; + break; + } + + case EVENT_CODE_BUTTON_PWR_LONG: + { + button = BUTTON_POWER_LONG; + break; + } + + case EVENT_CODE_BUTTON_VOLPLUS: + { + button = BUTTON_VOL_UP; + break; + } + + case EVENT_CODE_BUTTON_VOLMINUS: + { + button = BUTTON_VOL_DOWN; + break; + } + + case EVENT_CODE_BUTTON_REV: + { + button = BUTTON_LEFT; + break; + } + + case EVENT_CODE_BUTTON_PLAY: + { + button = BUTTON_PLAY; + break; + } + + case EVENT_CODE_BUTTON_NEXT: + { + button = BUTTON_RIGHT; + break; + } + + default: + { + return BUTTON_NONE; + } + } + + if( (button == BUTTON_RIGHT) + && ((last_btns & BUTTON_LEFT) == BUTTON_LEFT) + && (value == EVENT_VALUE_BUTTON_RELEASE)) + { + /* Workaround for a wrong feedback, only present with DX90. */ + button = BUTTON_LEFT; + } + + int buttons = last_btns; + if(value == EVENT_VALUE_BUTTON_PRESS) + { + buttons = (last_btns | button); + } + else + { + buttons = (last_btns & (~button)); + } + + return buttons; +} diff --git a/firmware/target/hosted/ibasso/dx90/codec-dx90.h b/firmware/target/hosted/ibasso/dx90/codec-dx90.h new file mode 100644 index 0000000000..b96377dfec --- /dev/null +++ b/firmware/target/hosted/ibasso/dx90/codec-dx90.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 _CODEC_DX90_H_ +#define _CODEC_DX90_H_ + + +#define AUDIOHW_CAPS MONO_VOL_CAP + + +AUDIOHW_SETTING(VOLUME, "", 0, 1, -255, 0, -128) + + +#endif diff --git a/firmware/target/hosted/ibasso/hostfs-ibasso.c b/firmware/target/hosted/ibasso/hostfs-ibasso.c new file mode 100644 index 0000000000..3970d06987 --- /dev/null +++ b/firmware/target/hosted/ibasso/hostfs-ibasso.c @@ -0,0 +1,47 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "debug-ibasso.h" + + +/* See hostfs.h. */ + + +int hostfs_init(void) +{ + TRACE; + + return 0; +} + + +int hostfs_flush(void) +{ + TRACE; + + sync(); + return 0; +} diff --git a/firmware/target/hosted/ibasso/lcd-ibasso.c b/firmware/target/hosted/ibasso/lcd-ibasso.c new file mode 100644 index 0000000000..4e03ba7e50 --- /dev/null +++ b/firmware/target/hosted/ibasso/lcd-ibasso.c @@ -0,0 +1,195 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 +#include +#include + +#include "config.h" +#include "debug.h" +#include "events.h" +#include "panic.h" + +#include "debug-ibasso.h" +#include "lcd-target.h" +#include "sysfs-ibasso.h" + + +fb_data *dev_fb = 0; + + +/* Framebuffer device handle. */ +static int dev_fd = 0; + + +void lcd_init_device(void) +{ + TRACE; + + dev_fd = open("/dev/graphics/fb0", O_RDWR); + if(dev_fd == -1) + { + DEBUGF("ERROR %s: open failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + exit(errno); + } + + /* Get the changeable information. */ + struct fb_var_screeninfo vinfo; + if(ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) + { + DEBUGF("ERROR %s: ioctl FBIOGET_VSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + exit(errno); + } + + DEBUGF("DEBUG %s: bits_per_pixel: %u, width: %u, height: %u.", __func__, vinfo.bits_per_pixel, vinfo.width, vinfo.height); + + /* + Framebuffer does not fit the screen, a bug of iBassos Firmware, not Rockbox. + Cannot be solved with parameters. + */ + /*vinfo.bits_per_pixel = LCD_DEPTH; + vinfo.xres = LCD_WIDTH; + vinfo.xres_virtual = LCD_WIDTH; + vinfo.width = LCD_WIDTH; + vinfo.yres = LCD_HEIGHT; + vinfo.yres_virtual = LCD_HEIGHT; + vinfo.height = LCD_HEIGHT; + vinfo.activate = FB_ACTIVATE_NOW; + if(ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) + { + DEBUGF("ERROR %s: ioctl FBIOPUT_VSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + exit(EXIT_FAILURE); + }*/ + + + /* Sanity check: Does framebuffer config match Rockbox config? */ + size_t screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; + if(screensize != FRAMEBUFFER_SIZE) + { + DEBUGF("ERROR %s: Screen size does not match config: %d != %d.", __func__, screensize, FRAMEBUFFER_SIZE); + exit(EXIT_FAILURE); + } + + /* Map the device to memory. */ + dev_fb = mmap(0, FRAMEBUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0); + if(dev_fb == MAP_FAILED) + { + DEBUGF("ERROR %s: mmap failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + exit(errno); + } + + /* Activate Rockbox LCD. */ + lcd_enable(true); +} + + +void lcd_shutdown(void) +{ + TRACE; + + lcd_set_active(false); + munmap(dev_fb, FRAMEBUFFER_SIZE); + close(dev_fd) ; +} + + +/* + Left as reference. Unblanking does not work as expected, will not enable LCD after a few + seconds of power down. + Instead the backlight power is toggled. +*/ +/*void lcd_power_on(void) +{ + TRACE; + + if(ioctl(dev_fd, FBIOBLANK, VESA_NO_BLANKING) == -1) + { + DEBUGF("ERROR %s: ioctl FBIOBLANK failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + panicf("ERROR %s: ioctl FBIOBLANK failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + return; + } + + lcd_set_active(true); + send_event(LCD_EVENT_ACTIVATION, NULL); +} + + +void lcd_power_off(void) +{ + TRACE; + + lcd_set_active(false); + + if(ioctl(dev_fd, FBIOBLANK, VESA_POWERDOWN) == -1) + { + DEBUGF("ERROR %s: ioctl FBIOBLANK failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + panicf("ERROR %s: ioctl FBIOBLANK failed on /dev/graphics/fb0, errno: %d.", __func__, errno); + return; + } +}*/ + + +void lcd_enable(bool on) +{ + TRACE; + + lcd_set_active(on); + + if(on) + { + /* + /sys/power/state + on: Cancel suspend. + */ + if(! sysfs_set_string(SYSFS_POWER_STATE, "on")) + { + DEBUGF("ERROR %s: Can not set power state.", __func__); + } + + send_event(LCD_EVENT_ACTIVATION, NULL); + } +} + + +void lcd_sleep(void) +{ + TRACE; + + /* + See system_init(). Without suspend blocker und mute prevention this will interrupt playback. + Essentially, we are turning off the touch screen. + /sys/power/state + mem: Suspend to RAM. + */ + if(! sysfs_set_string(SYSFS_POWER_STATE, "mem")) + { + DEBUGF("ERROR %s: Can not set power state.", __func__); + } +} diff --git a/firmware/target/hosted/ibasso/lcd-target.h b/firmware/target/hosted/ibasso/lcd-target.h new file mode 100644 index 0000000000..50cc92599d --- /dev/null +++ b/firmware/target/hosted/ibasso/lcd-target.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + + +#ifndef __LCD_TARGET_H__ +#define __LCD_TARGET_H__ + + +#include "lcd.h" + + +/* + Framebuffer device and framebuffer access. + See lcd-memframe.c +*/ +extern fb_data *dev_fb; +#define LCD_FRAMEBUF_ADDR(col, row) (dev_fb + row * LCD_WIDTH + col) + + +/* See lcd-memframe.c */ +extern void lcd_set_active(bool active); + + +#endif diff --git a/firmware/target/hosted/ibasso/pcm-ibasso.c b/firmware/target/hosted/ibasso/pcm-ibasso.c new file mode 100644 index 0000000000..14ef298af0 --- /dev/null +++ b/firmware/target/hosted/ibasso/pcm-ibasso.c @@ -0,0 +1,488 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" +#include "panic.h" +#include "pcm.h" +#include "pcm-internal.h" + +#include "sound/asound.h" +#include "tinyalsa/asoundlib.h" + +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +/* Tiny alsa handle. */ +static struct pcm* _alsa_handle = NULL; + + +/* Bytes left in the Rockbox PCM frame buffer. */ +static size_t _pcm_buffer_size = 0; + + +/* Rockbox PCM frame buffer. */ +static const void *_pcm_buffer = NULL; + + +/* + 1: PCM thread suspended. + 0: PCM thread running. + These are used by pcm_play_[lock|unlock] or pcm_play_dma_[start|stop|pause]. These need to be + separated because of nested calls for locking and stopping. +*/ +static volatile sig_atomic_t _dma_stopped = 1; +static volatile sig_atomic_t _dma_locked = 1; + + +/* Mutex for PCM thread suspend/unsuspend. */ +static pthread_mutex_t _dma_suspended_mtx = PTHREAD_MUTEX_INITIALIZER; + + +/* Signal condition for PCM thread suspend/unsuspend. */ +static pthread_cond_t _dma_suspended_cond = PTHREAD_COND_INITIALIZER; + + +static void* pcm_thread_run(void* nothing) +{ + (void) nothing; + + DEBUGF("DEBUG %s: Thread start.", __func__); + + while(true) + { + pthread_mutex_lock(&_dma_suspended_mtx); + while((_dma_stopped == 1) || (_dma_locked == 1)) + { + DEBUGF("DEBUG %s: Playback suspended.", __func__); + pthread_cond_wait(&_dma_suspended_cond, &_dma_suspended_mtx); + DEBUGF("DEBUG %s: Playback resumed.", __func__); + } + pthread_mutex_unlock(&_dma_suspended_mtx); + + if(_pcm_buffer_size == 0) + { + /* Retrive a new PCM buffer from Rockbox. */ + if(! pcm_play_dma_complete_callback(PCM_DMAST_OK, &_pcm_buffer, &_pcm_buffer_size)) + { + DEBUGF("DEBUG %s: No new buffer.", __func__); + + usleep( 10000 ); + continue; + } + } + pcm_play_dma_status_callback(PCM_DMAST_STARTED); + + /* This relies on Rockbox PCM frame buffer size == ALSA PCM frame buffer size. */ + if(pcm_write(_alsa_handle, _pcm_buffer, _pcm_buffer_size) != 0) + { + DEBUGF("ERROR %s: pcm_write failed: %s.", __func__, pcm_get_error(_alsa_handle)); + + usleep( 10000 ); + continue; + } + + _pcm_buffer_size = 0; + + /*DEBUGF("DEBUG %s: Thread running.", __func__);*/ + } + + DEBUGF("DEBUG %s: Thread end.", __func__); + + return 0; +} + + +#ifdef DEBUG + +/* https://github.com/tinyalsa/tinyalsa/blob/master/tinypcminfo.c */ + +static const char* format_lookup[] = +{ + /*[0] =*/ "S8", + "U8", + "S16_LE", + "S16_BE", + "U16_LE", + "U16_BE", + "S24_LE", + "S24_BE", + "U24_LE", + "U24_BE", + "S32_LE", + "S32_BE", + "U32_LE", + "U32_BE", + "FLOAT_LE", + "FLOAT_BE", + "FLOAT64_LE", + "FLOAT64_BE", + "IEC958_SUBFRAME_LE", + "IEC958_SUBFRAME_BE", + "MU_LAW", + "A_LAW", + "IMA_ADPCM", + "MPEG", + /*[24] =*/ "GSM", + [31] = "SPECIAL", + "S24_3LE", + "S24_3BE", + "U24_3LE", + "U24_3BE", + "S20_3LE", + "S20_3BE", + "U20_3LE", + "U20_3BE", + "S18_3LE", + "S18_3BE", + "U18_3LE", + /*[43] =*/ "U18_3BE" +}; + + +static const char* pcm_get_format_name(unsigned int bit_index) +{ + return(bit_index < 43 ? format_lookup[bit_index] : NULL); +} + +#endif + + +/* Thread that copies the Rockbox PCM buffer to ALSA. */ +static pthread_t _pcm_thread; + + +/* ALSA card and device. */ +static const unsigned int CARD = 0; +static const unsigned int DEVICE = 0; + + +/* ALSA config. */ +static struct pcm_config _config; + + +void pcm_play_dma_init(void) +{ + TRACE; + +#ifdef DEBUG + + /* + DEBUG pcm_play_dma_init: Access: 0x000009 + DEBUG pcm_play_dma_init: Format[0]: 0x000044 + DEBUG pcm_play_dma_init: Format[1]: 0x000010 + DEBUG pcm_play_dma_init: Format: S16_LE + DEBUG pcm_play_dma_init: Format: S24_LE + DEBUG pcm_play_dma_init: Format: S20_3LE + DEBUG pcm_play_dma_init: Subformat: 0x000001 + DEBUG pcm_play_dma_init: Rate: min = 8000Hz, max = 192000Hz + DEBUG pcm_play_dma_init: Channels: min = 2, max = 2 + DEBUG pcm_play_dma_init: Sample bits: min=16, max=32 + DEBUG pcm_play_dma_init: Period size: min=8, max=10922 + DEBUG pcm_play_dma_init: Period count: min=3, max=128 + DEBUG pcm_play_dma_init: 0 mixer controls. + */ + + struct pcm_params* params = pcm_params_get(CARD, DEVICE, PCM_OUT); + if(params == NULL) + { + DEBUGF("ERROR %s: Card/device does not exist.", __func__); + panicf("ERROR %s: Card/device does not exist.", __func__); + return; + } + + struct pcm_mask* m = pcm_params_get_mask(params, PCM_PARAM_ACCESS); + if(m) + { + DEBUGF("DEBUG %s: Access: %#08x", __func__, m->bits[0]); + } + + m = pcm_params_get_mask(params, PCM_PARAM_FORMAT); + if(m) + { + DEBUGF("DEBUG %s: Format[0]: %#08x", __func__, m->bits[0]); + DEBUGF("DEBUG %s: Format[1]: %#08x", __func__, m->bits[1]); + + unsigned int j; + unsigned int k; + const unsigned int bitcount = sizeof(m->bits[0]) * 8; + for(k = 0; k < 2; ++k) + { + for(j = 0; j < bitcount; ++j) + { + const char* name; + if(m->bits[k] & (1 << j)) + { + name = pcm_get_format_name(j + (k * bitcount)); + if(name) + { + DEBUGF("DEBUG %s: Format: %s", __func__, name); + } + } + } + } + } + + m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT); + if(m) + { + DEBUGF("DEBUG %s: Subformat: %#08x", __func__, m->bits[0]); + } + + unsigned int min = pcm_params_get_min(params, PCM_PARAM_RATE); + unsigned int max = pcm_params_get_max(params, PCM_PARAM_RATE) ; + DEBUGF("DEBUG %s: Rate: min = %uHz, max = %uHz", __func__, min, max); + + min = pcm_params_get_min(params, PCM_PARAM_CHANNELS); + max = pcm_params_get_max(params, PCM_PARAM_CHANNELS); + DEBUGF("DEBUG %s: Channels: min = %u, max = %u", __func__, min, max); + + min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS); + max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS); + DEBUGF("DEBUG %s: Sample bits: min=%u, max=%u", __func__, min, max); + + min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE); + max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE); + DEBUGF("DEBUG %s: Period size: min=%u, max=%u", __func__, min, max); + + min = pcm_params_get_min(params, PCM_PARAM_PERIODS); + max = pcm_params_get_max(params, PCM_PARAM_PERIODS); + DEBUGF("DEBUG %s: Period count: min=%u, max=%u", __func__, min, max); + + pcm_params_free(params); + + struct mixer* mixer = mixer_open(CARD); + if(! mixer) + { + DEBUGF("ERROR %s: Failed to open mixer.", __func__); + } + else + { + int num_ctls = mixer_get_num_ctls(mixer); + + DEBUGF("DEBUG %s: %d mixer controls.", __func__, num_ctls); + + mixer_close(mixer); + } + +#endif + + if(_alsa_handle != NULL) + { + DEBUGF("ERROR %s: Allready initialized.", __func__); + panicf("ERROR %s: Allready initialized.", __func__); + return; + } + + /* + Rockbox outputs 16 Bit/44.1kHz stereo by default. + + ALSA frame buffer size = config.period_count * config.period_size * config.channels * (16 \ 8) + = 4 * 256 * 2 * 2 + = 4096 + = Rockbox PCM buffer size + pcm_thread_run relies on this size match. See pcm_mixer.h. + */ + _config.channels = 2; + _config.rate = 44100; + _config.period_size = 256; + _config.period_count = 4; + _config.format = PCM_FORMAT_S16_LE; + _config.start_threshold = 0; + _config.stop_threshold = 0; + _config.silence_threshold = 0; + + _alsa_handle = pcm_open(CARD, DEVICE, PCM_OUT, &_config); + if(! pcm_is_ready(_alsa_handle)) + { + DEBUGF("ERROR %s: pcm_open failed: %s.", __func__, pcm_get_error(_alsa_handle)); + panicf("ERROR %s: pcm_open failed: %s.", __func__, pcm_get_error(_alsa_handle)); + return; + } + + DEBUGF("DEBUG %s: ALSA PCM frame buffer size: %d.", __func__, pcm_frames_to_bytes(_alsa_handle, pcm_get_buffer_size(_alsa_handle))); + + /* Create pcm thread in the suspended state. */ + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_stopped = 1; + _dma_locked = 1; + pthread_create(&_pcm_thread, NULL, pcm_thread_run, NULL); + pthread_mutex_unlock(&_dma_suspended_mtx); +} + + +void pcm_play_dma_start(const void *addr, size_t size) +{ + TRACE; + + /* + DX50 + /sys/class/codec/mute + Mute: echo 'A' > /sys/class/codec/mute + Unmute: echo 'B' > /sys/class/codec/mute + + DX90? + */ + if(! sysfs_set_char(SYSFS_MUTE, 'B')) + { + DEBUGF("ERROR %s: Could not unmute.", __func__); + panicf("ERROR %s: Could not unmute.", __func__); + } + + _pcm_buffer = addr; + _pcm_buffer_size = size; + + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_stopped = 0; + pthread_cond_signal(&_dma_suspended_cond); + pthread_mutex_unlock(&_dma_suspended_mtx); +} + + +/* TODO: Why is this in the API if it gets never called? */ +void pcm_play_dma_pause(bool pause) +{ + TRACE; + + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_stopped = pause ? 1 : 0; + if(_dma_stopped == 0) + { + pthread_cond_signal(&_dma_suspended_cond); + } + pthread_mutex_unlock(&_dma_suspended_mtx); +} + + +void pcm_play_dma_stop(void) +{ + TRACE; + + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_stopped = 1; + pcm_stop(_alsa_handle); + pthread_mutex_unlock(&_dma_suspended_mtx); +} + + +/* Unessecary play locks before pcm_play_dma_postinit. */ +static int _play_lock_recursion_count = -10000; + + +void pcm_play_dma_postinit(void) +{ + TRACE; + + _play_lock_recursion_count = 0; +} + + +void pcm_play_lock(void) +{ + TRACE; + + ++_play_lock_recursion_count; + + if(_play_lock_recursion_count == 1) + { + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_locked = 1; + pthread_mutex_unlock(&_dma_suspended_mtx); + } +} + + +void pcm_play_unlock(void) +{ + TRACE; + + --_play_lock_recursion_count; + + if(_play_lock_recursion_count == 0) + { + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_locked = 0; + pthread_cond_signal(&_dma_suspended_cond); + pthread_mutex_unlock(&_dma_suspended_mtx); + } +} + + +void pcm_dma_apply_settings(void) +{ + unsigned int rate = pcm_get_frequency(); + + DEBUGF("DEBUG %s: Current sample rate: %u, next sampe rate: %u.", __func__, _config.rate, rate); + + if(( _config.rate != rate) && (rate >= 8000) && (rate <= 192000)) + { + _config.rate = rate; + + pcm_close(_alsa_handle); + _alsa_handle = pcm_open(CARD, DEVICE, PCM_OUT, &_config); + + if(! pcm_is_ready(_alsa_handle)) + { + DEBUGF("ERROR %s: pcm_open failed: %s.", __func__, pcm_get_error(_alsa_handle)); + panicf("ERROR %s: pcm_open failed: %s.", __func__, pcm_get_error(_alsa_handle)); + } + } +} + + +size_t pcm_get_bytes_waiting(void) +{ + TRACE; + + return _pcm_buffer_size; +} + + +/* TODO: WTF */ +const void* pcm_play_dma_get_peak_buffer(int* count) +{ + TRACE; + + uintptr_t addr = (uintptr_t) _pcm_buffer; + *count = _pcm_buffer_size / 4; + return (void*) ((addr + 3) & ~3); +} + + +void pcm_close_device(void) +{ + TRACE; + + pthread_mutex_lock(&_dma_suspended_mtx); + _dma_stopped = 1; + pthread_mutex_unlock(&_dma_suspended_mtx); + + pcm_close(_alsa_handle); + _alsa_handle = NULL; +} diff --git a/firmware/target/hosted/ibasso/pcm-ibasso.h b/firmware/target/hosted/ibasso/pcm-ibasso.h new file mode 100644 index 0000000000..588c4dfb9b --- /dev/null +++ b/firmware/target/hosted/ibasso/pcm-ibasso.h @@ -0,0 +1,33 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + + +#ifndef __PCM_IBASSO_H__ +#define __PCM_IBASSO_H__ + + +/* Clean up the audio device handler. */ +void pcm_close_device(void); + + +#endif diff --git a/firmware/target/hosted/ibasso/power-ibasso.c b/firmware/target/hosted/ibasso/power-ibasso.c new file mode 100644 index 0000000000..8257de5f33 --- /dev/null +++ b/firmware/target/hosted/ibasso/power-ibasso.c @@ -0,0 +1,97 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" +#include "power.h" + +#include "button-ibasso.h" +#include "debug-ibasso.h" +#include "pcm-ibasso.h" +#include "sysfs-ibasso.h" +#include "vold-ibasso.h" + + +unsigned int power_input_status(void) +{ + /*TRACE;*/ + + /* + /sys/class/power_supply/usb/present + 0: No external power supply connected. + 1: External power supply connected. + */ + int val = 0; + if(! sysfs_get_int(SYSFS_USB_POWER_PRESENT, &val)) + { + DEBUGF("ERROR %s: Can not get power supply status.", __func__); + return POWER_INPUT_NONE; + } + + return val ? POWER_INPUT_USB_CHARGER : POWER_INPUT_NONE; +} + + +void power_off(void) +{ + TRACE; + + button_close_device(); + + if(vold_monitor_forced_close_imminent()) + { + /* + We are here, because Android Vold is going to kill Rockbox. Instead of powering off, + we exit into the loader. + */ + DEBUGF("DEBUG %s: Exit Rockbox.", __func__); + exit(42); + } + + reboot(RB_POWER_OFF); +} + + +/* Returns true, if battery is charging, false else. */ +bool charging_state(void) +{ + /*TRACE;*/ + + /* + /sys/class/power_supply/battery/status + "Full", "Charging", "Discharging" + */ + char state[9]; + if(! sysfs_get_string(SYSFS_BATTERY_STATUS, state, 9)) + { + DEBUGF("ERROR %s: Can not get battery charging state.", __func__); + return false; + } + + return(strcmp(state, "Charging") == 0);; +} diff --git a/firmware/target/hosted/ibasso/powermgmt-ibasso.c b/firmware/target/hosted/ibasso/powermgmt-ibasso.c new file mode 100644 index 0000000000..7df0064097 --- /dev/null +++ b/firmware/target/hosted/ibasso/powermgmt-ibasso.c @@ -0,0 +1,122 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" +#include "panic.h" + +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +/* Based on batterymonitor with PISEN and Samsung SIII battery. */ + + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3600 +}; + + +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3500 +}; + + +/* + Averages at percent of running time from five measuremnts with PISEN and Samsung SIII battery + during normal usage. + + Mongo default values (?) + < 3660 (0%), < 3730 (1% - 10%), < 3780 (11% - 20%), < 3830 (21% - 40%), < 3950 (41% - 60%), + < 4080 (61% - 80%), > 4081 (81% - 100%) +*/ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3522, 3660, 3720, 3752, 3784, 3827, 3896, 3978, 4072, 4168, 4255 } +}; + + +/* Copied from percent_to_volt_discharge. */ +const unsigned short percent_to_volt_charge[11] = +{ + 3500, 3544, 3578, 3623, 3660, 3773, 3782, 3853, 3980, 4130, 4360 +}; + + +static int _battery_present = -1; + + +int _battery_voltage(void) +{ + /*TRACE;*/ + + if( (_battery_present == -1) + && (! sysfs_get_int(SYSFS_BATTERY_PRESENT, &_battery_present))) + { + /* This check is only done once at startup. */ + + DEBUGF("ERROR %s: Can not get current battery availabilty.", __func__); + _battery_present = 1; + } + + int val; + + if(_battery_present == 1) + { + /* Battery is present. */ + + /* + /sys/class/power_supply/battery/voltage_now + Voltage in microvolt. + */ + if(! sysfs_get_int(SYSFS_BATTERY_VOLTAGE_NOW, &val)) + { + DEBUGF("ERROR %s: Can not get current battery voltage.", __func__); + return 0; + } + } + else + { + /* + No battery, so we have to be running solely from USB power. + This will prevent Rockbox from forcing shutdown due to low power. + */ + + /* + /sys/class/power_supply/usb/voltage_now + Voltage in microvolt. + */ + if(! sysfs_get_int(SYSFS_USB_POWER_VOLTAGE_NOW, &val)) + { + DEBUGF("ERROR %s: Can not get current USB voltage.", __func__); + return 0; + } + } + + return(val / 1000); +} diff --git a/firmware/target/hosted/ibasso/sysfs-ibasso.c b/firmware/target/hosted/ibasso/sysfs-ibasso.c new file mode 100644 index 0000000000..8ca3edf387 --- /dev/null +++ b/firmware/target/hosted/ibasso/sysfs-ibasso.c @@ -0,0 +1,404 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" + +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" + + +static const char* SYSFS_PATHS[] = +{ + /* SYSFS_DX50_CODEC_VOLUME */ + "/dev/codec_volume", + + /* SYSFS_HOLDKEY */ + "/sys/class/axppower/holdkey", + + /* SYSFS_DX90_ES9018_VOLUME */ + "/sys/class/codec/es9018_volume", + + /* SYSFS_MUTE */ + "/sys/class/codec/mute", + + /* SYSFS_WM8740_MUTE */ + "/sys/class/codec/wm8740_mute", + + /* SYSFS_BATTERY_CAPACITY */ + "/sys/class/power_supply/battery/capacity", + + /* SYSFS_BATTERY_CURRENT_NOW */ + "/sys/class/power_supply/battery/current_now", + + /* SYSFS_BATTERY_ENERGY_FULL_DESIGN */ + "/sys/class/power_supply/battery/energy_full_design", + + /* SYSFS_BATTERY_HEALTH */ + "/sys/class/power_supply/battery/health", + + /* SYSFS_BATTERY_MODEL_NAME */ + "/sys/class/power_supply/battery/model_name", + + /* SYSFS_BATTERY_ONLINE */ + "/sys/class/power_supply/battery/online", + + /* SYSFS_BATTERY_PRESENT */ + "/sys/class/power_supply/battery/present", + + /* SYSFS_BATTERY_STATUS */ + "/sys/class/power_supply/battery/status", + + /* SYSFS_BATTERY_TECHNOLOGY */ + "/sys/class/power_supply/battery/technology", + + /* SYSFS_BATTERY_TEMP */ + "/sys/class/power_supply/battery/temp", + + /* SYSFS_BATTERY_TYPE */ + "/sys/class/power_supply/battery/type", + + /* SYSFS_BATTERY_VOLTAGE_MAX_DESIGN */ + "/sys/class/power_supply/battery/voltage_max_design", + + /* SYSFS_BATTERY_VOLTAGE_MIN_DESIGN */ + "/sys/class/power_supply/battery/voltage_min_design", + + /* SYSFS_BATTERY_VOLTAGE_NOW */ + "/sys/class/power_supply/battery/voltage_now", + + /* SYSFS_USB_POWER_CURRENT_NOW */ + "/sys/class/power_supply/usb/current_now", + + /* SYSFS_USB_POWER_ONLINE */ + "/sys/class/power_supply/usb/online", + + /* SYSFS_USB_POWER_PRESENT */ + "/sys/class/power_supply/usb/present", + + /* SYSFS_USB_POWER_VOLTAGE_NOW */ + "/sys/class/power_supply/usb/voltage_now", + + /* SYSFS_BACKLIGHT_POWER */ + "/sys/devices/platform/rk29_backlight/backlight/rk28_bl/bl_power", + + /* SYSFS_BACKLIGHT_BRIGHTNESS */ + "/sys/devices/platform/rk29_backlight/backlight/rk28_bl/brightness", + + /* SYSFS_POWER_STATE */ + "/sys/power/state", + + /* SYSFS_POWER_WAKE_LOCK */ + "/sys/power/wake_lock" +}; + + +static FILE* open_read(const char* file_name) +{ + FILE *f = fopen(file_name, "r"); + if(f == NULL) + { + DEBUGF("ERROR %s: Can not open %s for reading.", __func__, file_name); + } + + return f; +} + + +static FILE* open_write(const char* file_name) +{ + FILE *f = fopen(file_name, "w"); + if(f == NULL) + { + DEBUGF("ERROR %s: Can not open %s for writing.", __func__, file_name); + } + + return f; +} + + +bool sysfs_get_int(enum sys_fs_interface_id id, int* value) +{ + *value = -1; + + switch(id) + { + case SYSFS_BATTERY_CAPACITY: + case SYSFS_BATTERY_CURRENT_NOW: + case SYSFS_BATTERY_ENERGY_FULL_DESIGN: + case SYSFS_BATTERY_ONLINE: + case SYSFS_BATTERY_PRESENT: + case SYSFS_BATTERY_TEMP: + case SYSFS_BATTERY_VOLTAGE_MAX_DESIGN: + case SYSFS_BATTERY_VOLTAGE_MIN_DESIGN: + case SYSFS_BATTERY_VOLTAGE_NOW: + case SYSFS_USB_POWER_CURRENT_NOW: + case SYSFS_USB_POWER_VOLTAGE_NOW: + case SYSFS_USB_POWER_ONLINE: + case SYSFS_USB_POWER_PRESENT: + { + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown interface id: %d.", __func__, id); + return false; + } + } + + const char* interface = SYSFS_PATHS[id]; + + /*DEBUGF("%s: interface: %s.", __func__, interface);*/ + + FILE *f = open_read(interface); + if(f == NULL) + { + return false; + } + + bool success = true; + if(fscanf(f, "%d", value) == EOF) + { + DEBUGF("ERROR %s: Read failed for %s.", __func__, interface); + success = false; + } + + fclose(f); + return success; +} + + +bool sysfs_set_int(enum sys_fs_interface_id id, int value) +{ + switch(id) + { + case SYSFS_BACKLIGHT_POWER: + case SYSFS_BACKLIGHT_BRIGHTNESS: + case SYSFS_DX50_CODEC_VOLUME: + case SYSFS_DX90_ES9018_VOLUME: + { + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown interface id: %d.", __func__, id); + return false; + } + } + + const char* interface = SYSFS_PATHS[id]; + + /*DEBUGF("%s: interface: %s, value: %d.", __func__, interface, value);*/ + + FILE *f = open_write(interface); + if(f == NULL) + { + return false; + } + + bool success = true; + if(fprintf(f, "%d", value) < 1) + { + DEBUGF("ERROR %s: Write failed for %s.", __func__, interface); + success = false; + } + + fclose(f); + return success; +} + + +bool sysfs_get_char(enum sys_fs_interface_id id, char* value) +{ + *value = '\0'; + + switch(id) + { + case SYSFS_HOLDKEY: + { + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown interface id: %d.", __func__, id); + return false; + } + } + + const char* interface = SYSFS_PATHS[id]; + + /*DEBUGF("%s: interface: %s.", __func__, interface);*/ + + FILE *f = open_read(interface); + if(f == NULL) + { + return false; + } + + bool success = true; + if(fscanf(f, "%c", value) == EOF) + { + DEBUGF("ERROR %s: Read failed for %s.", __func__, interface); + success = false; + } + + fclose(f); + return success; +} + + +bool sysfs_set_char(enum sys_fs_interface_id id, char value) +{ + switch(id) + { + case SYSFS_MUTE: + case SYSFS_WM8740_MUTE: + { + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown interface id: %d.", __func__, id); + return false; + } + } + + const char* interface = SYSFS_PATHS[id]; + + /*DEBUGF("%s: interface: %s, value: %c.", __func__, interface, value);*/ + + FILE *f = open_write(interface); + if(f == NULL) + { + return false; + } + + bool success = true; + if(fprintf(f, "%c", value) < 1) + { + DEBUGF("ERROR %s: Write failed for %s.", __func__, interface); + success = false; + } + + fclose(f); + return success; +} + + +bool sysfs_get_string(enum sys_fs_interface_id id, char* value, int size) +{ + value[0] = '\0'; + + switch(id) + { + case SYSFS_BATTERY_STATUS: + case SYSFS_BATTERY_HEALTH: + case SYSFS_BATTERY_MODEL_NAME: + case SYSFS_BATTERY_TECHNOLOGY: + case SYSFS_BATTERY_TYPE: + { + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown interface id: %d.", __func__, id); + return false; + } + } + + const char* interface = SYSFS_PATHS[id]; + + /*DEBUGF("%s: interface: %s, size: %d.", __func__, interface, size);*/ + + FILE *f = open_read(interface); + if(f == NULL) + { + return false; + } + + bool success = true; + if(fgets(value, size, f) == NULL) + { + DEBUGF("ERROR %s: Read failed for %s.", __func__, interface); + success = false; + } + else + { + size_t length = strlen(value); + if((length > 0) && value[length - 1] == '\n') + { + value[length - 1] = '\0'; + } + } + + fclose(f); + return success; +} + + +bool sysfs_set_string(enum sys_fs_interface_id id, char* value) +{ + switch(id) + { + case SYSFS_POWER_STATE: + case SYSFS_POWER_WAKE_LOCK: + { + break; + } + + default: + { + DEBUGF("ERROR %s: Unknown interface id: %d.", __func__, id); + return false; + } + } + + const char* interface = SYSFS_PATHS[id]; + + /*DEBUGF("%s: interface: %s, value: %s.", __func__, interface, value);*/ + + FILE *f = open_write(interface); + if(f == NULL) + { + return false; + } + + bool success = true; + if(fprintf(f, "%s", value) < 1) + { + DEBUGF("ERROR %s: Write failed for %s.", __func__, interface); + success = false; + } + + fclose(f); + return success; +} diff --git a/firmware/target/hosted/ibasso/sysfs-ibasso.h b/firmware/target/hosted/ibasso/sysfs-ibasso.h new file mode 100644 index 0000000000..fec8a082f9 --- /dev/null +++ b/firmware/target/hosted/ibasso/sysfs-ibasso.h @@ -0,0 +1,111 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 _SYSFS_IBASSO_H_ +#define _SYSFS_IBASSO_H_ + + +#include + + +/* + Sys FS path identifiers. + See SYSFS_PATHS in sysfs-ibasso.c. +*/ +enum sys_fs_interface_id +{ + SYSFS_DX50_CODEC_VOLUME = 0, + SYSFS_HOLDKEY, + SYSFS_DX90_ES9018_VOLUME, + SYSFS_MUTE, + SYSFS_WM8740_MUTE, + SYSFS_BATTERY_CAPACITY, + SYSFS_BATTERY_CURRENT_NOW, + SYSFS_BATTERY_ENERGY_FULL_DESIGN, + SYSFS_BATTERY_HEALTH, + SYSFS_BATTERY_MODEL_NAME, + SYSFS_BATTERY_ONLINE, + SYSFS_BATTERY_PRESENT, + SYSFS_BATTERY_STATUS, + SYSFS_BATTERY_TECHNOLOGY, + SYSFS_BATTERY_TEMP, + SYSFS_BATTERY_TYPE, + SYSFS_BATTERY_VOLTAGE_MAX_DESIGN, + SYSFS_BATTERY_VOLTAGE_MIN_DESIGN, + SYSFS_BATTERY_VOLTAGE_NOW, + SYSFS_USB_POWER_CURRENT_NOW, + SYSFS_USB_POWER_ONLINE, + SYSFS_USB_POWER_PRESENT, + SYSFS_USB_POWER_VOLTAGE_NOW, + SYSFS_BACKLIGHT_POWER, + SYSFS_BACKLIGHT_BRIGHTNESS, + SYSFS_POWER_STATE, + SYSFS_POWER_WAKE_LOCK +}; + + +/* + Read a integer value from the sys fs interface given by id. + Returns true on success, false else. +*/ +bool sysfs_get_int(enum sys_fs_interface_id id, int* value); + + +/* + Write a integer value to the sys fs interface given by id. + Returns true on success, false else. +*/ +bool sysfs_set_int(enum sys_fs_interface_id id, int value); + + +/* + Read a char value from the sys fs interface given by id. + Returns true on success, false else. +*/ +bool sysfs_get_char(enum sys_fs_interface_id id, char* value); + + +/* + Write a char value to the sys fs interface given by id. + Returns true on success, false else. +*/ +bool sysfs_set_char(enum sys_fs_interface_id id, char value); + +/* + Read a single line of text from the sys fs interface given by id. + A newline will be discarded. + size: The size of value. + Returns true on success, false else. +*/ +bool sysfs_get_string(enum sys_fs_interface_id id, char* value, int size); + + +/* + Write text to the sys fs interface given by id. + Returns true on success, false else. +*/ +bool sysfs_set_string(enum sys_fs_interface_id id, char* value); + + +#endif diff --git a/firmware/target/hosted/ibasso/system-ibasso.c b/firmware/target/hosted/ibasso/system-ibasso.c new file mode 100644 index 0000000000..00f8669ae0 --- /dev/null +++ b/firmware/target/hosted/ibasso/system-ibasso.c @@ -0,0 +1,101 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "cpufreq-linux.h" +#include "debug.h" + +#include "button-ibasso.h" +#include "debug-ibasso.h" +#include "sysfs-ibasso.h" +#include "usb-ibasso.h" +#include "vold-ibasso.h" + + +/* Fake stack. */ +uintptr_t* stackbegin; +uintptr_t* stackend; + + +void system_init(void) +{ + TRACE; + + /* Fake stack. */ + volatile uintptr_t stack = 0; + stackbegin = stackend = (uintptr_t*) &stack; + + cpufreq_set_governor("powersave", CPUFREQ_ALL_CPUS); + vold_monitor_start(); + ibasso_set_usb_mode(USB_MODE_MASS_STORAGE); + + /* + Prevent device from deep sleeping, which will interrupt playback. + /sys/power/wake_lock + */ + if(! sysfs_set_string(SYSFS_POWER_WAKE_LOCK, "rockbox")) + { + DEBUGF("ERROR %s: Can not set suspend blocker.", __func__); + } + + /* + Prevent device to mute, which will cause tinyalsa pcm_writes to fail. + /sys/class/codec/wm8740_mute + */ + if(! sysfs_set_char(SYSFS_WM8740_MUTE, '0')) + { + DEBUGF("ERROR %s: Can not set WM8740 lock.", __func__); + } +} + + +void system_reboot(void) +{ + TRACE; + + button_close_device(); + + if(vold_monitor_forced_close_imminent()) + { + /* + We are here, because Android Vold is going to kill Rockbox. Instead of powering off, + we exit into the loader. + */ + exit(42); + } + + reboot(RB_AUTOBOOT); +} + + +void system_exception_wait(void) +{ + TRACE; + + while(1) {}; +} diff --git a/firmware/target/hosted/android/dx50/lcd-target.h b/firmware/target/hosted/ibasso/system-target.h similarity index 64% rename from firmware/target/hosted/android/dx50/lcd-target.h rename to firmware/target/hosted/ibasso/system-target.h index 900350eca2..17b1238380 100644 --- a/firmware/target/hosted/android/dx50/lcd-target.h +++ b/firmware/target/hosted/ibasso/system-target.h @@ -1,11 +1,15 @@ /*************************************************************************** - * __________ __ ___. + * __________ __ ___ * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id$ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -17,13 +21,13 @@ * ****************************************************************************/ -#ifndef __LCD_TARGET_H__ -#define __LCD_TARGET_H__ -extern fb_data *dev_fb; -#define LCD_FRAMEBUF_ADDR(col, row) (dev_fb + row*LCD_WIDTH + col) -#ifdef HAVE_LCD_ENABLE -extern void lcd_set_active(bool active); -extern void lcd_enable(bool enable); -#endif +#ifndef __SYSTEM_TARGET_H__ +#define __SYSTEM_TARGET_H__ + + +#include "kernel-unix.h" +#include "system-hosted.h" + + #endif diff --git a/firmware/target/hosted/android/dx50/tinyalsa/asound.h b/firmware/target/hosted/ibasso/tinyalsa/include/sound/asound.h similarity index 99% rename from firmware/target/hosted/android/dx50/tinyalsa/asound.h rename to firmware/target/hosted/ibasso/tinyalsa/include/sound/asound.h index fc1e4f6d67..9dd66fe169 100644 --- a/firmware/target/hosted/android/dx50/tinyalsa/asound.h +++ b/firmware/target/hosted/ibasso/tinyalsa/include/sound/asound.h @@ -818,4 +818,3 @@ struct snd_ctl_event { #define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what #endif - diff --git a/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h b/firmware/target/hosted/ibasso/tinyalsa/include/tinyalsa/asoundlib.h similarity index 91% rename from firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h rename to firmware/target/hosted/ibasso/tinyalsa/include/tinyalsa/asoundlib.h index 6aacae46d6..ba58bdcdfc 100644 --- a/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h +++ b/firmware/target/hosted/ibasso/tinyalsa/include/tinyalsa/asoundlib.h @@ -55,17 +55,14 @@ struct pcm; * second call to pcm_write will attempt to * restart the stream. */ +#define PCM_MONOTONIC 0x00000008 /* see pcm_get_htimestamp */ /* PCM runtime states */ -#define PCM_STATE_OPEN 0 -#define PCM_STATE_SETUP 1 -#define PCM_STATE_PREPARED 2 -#define PCM_STATE_RUNNING 3 -#define PCM_STATE_XRUN 4 -#define PCM_STATE_DRAINING 5 -#define PCM_STATE_PAUSED 6 -#define PCM_STATE_SUSPENDED 7 -#define PCM_STATE_DISCONNECTED 8 +#define PCM_STATE_RUNNING 3 +#define PCM_STATE_XRUN 4 +#define PCM_STATE_DRAINING 5 +#define PCM_STATE_SUSPENDED 7 +#define PCM_STATE_DISCONNECTED 8 /* Bit formats */ enum pcm_format { @@ -77,6 +74,11 @@ enum pcm_format { PCM_FORMAT_MAX, }; +/* Bitmask has 256 bits (32 bytes) in asound.h */ +struct pcm_mask { + unsigned int bits[32 / sizeof(unsigned int)]; +}; + /* Configuration for a stream */ struct pcm_config { unsigned int channels; @@ -101,6 +103,11 @@ struct pcm_config { /* PCM parameters */ enum pcm_param { + /* mask parameters */ + PCM_PARAM_ACCESS, + PCM_PARAM_FORMAT, + PCM_PARAM_SUBFORMAT, + /* interval parameters */ PCM_PARAM_SAMPLE_BITS, PCM_PARAM_FRAME_BITS, PCM_PARAM_CHANNELS, @@ -138,15 +145,14 @@ int pcm_is_ready(struct pcm *pcm); struct pcm_params *pcm_params_get(unsigned int card, unsigned int device, unsigned int flags); void pcm_params_free(struct pcm_params *pcm_params); + +struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, + enum pcm_param param); unsigned int pcm_params_get_min(struct pcm_params *pcm_params, enum pcm_param param); unsigned int pcm_params_get_max(struct pcm_params *pcm_params, enum pcm_param param); -/* Set and get config */ -int pcm_get_config(struct pcm *pcm, struct pcm_config *config); -int pcm_set_config(struct pcm *pcm, struct pcm_config *config); - /* Returns a human readable reason for the last error */ const char *pcm_get_error(struct pcm *pcm); @@ -162,10 +168,9 @@ unsigned int pcm_get_buffer_size(struct pcm *pcm); unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames); unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes); -/* Returns the pcm latency in ms */ -unsigned int pcm_get_latency(struct pcm *pcm); - /* Returns available frames in pcm buffer and corresponding time stamp. + * The clock is CLOCK_MONOTONIC if flag PCM_MONOTONIC was specified in pcm_open, + * otherwise the clock is CLOCK_REALTIME. * For an input stream, frames available are frames ready for the * application to read. * For an output stream, frames available are the number of empty frames available @@ -185,11 +190,13 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count); * mmap() support. */ int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count); +int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count); int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, unsigned int *frames); int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames); - +/* Prepare the PCM substream to be triggerable */ +int pcm_prepare(struct pcm *pcm); /* Start and stop a PCM channel that doesn't transfer data */ int pcm_start(struct pcm *pcm); int pcm_stop(struct pcm *pcm); @@ -197,10 +204,6 @@ int pcm_stop(struct pcm *pcm); /* Interrupt driven API */ int pcm_wait(struct pcm *pcm, int timeout); -int pcm_avail_update(struct pcm *pcm); - -int pcm_state(struct pcm *pcm); - /* * MIXER API diff --git a/firmware/target/hosted/android/dx50/tinyalsa/mixer.c b/firmware/target/hosted/ibasso/tinyalsa/mixer.c similarity index 96% rename from firmware/target/hosted/android/dx50/tinyalsa/mixer.c rename to firmware/target/hosted/ibasso/tinyalsa/mixer.c index f75dec488a..24e94f4f1d 100644 --- a/firmware/target/hosted/android/dx50/tinyalsa/mixer.c +++ b/firmware/target/hosted/ibasso/tinyalsa/mixer.c @@ -40,7 +40,7 @@ #define __force #define __bitwise #define __user -#include +#include #include @@ -259,14 +259,11 @@ unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl) static int percent_to_int(struct snd_ctl_elem_info *ei, int percent) { - int range; + if ((percent > 100) || (percent < 0)) { + return -EINVAL; + } - if (percent > 100) - percent = 100; - else if (percent < 0) - percent = 0; - - range = (ei->value.integer.max - ei->value.integer.min); + int range = (ei->value.integer.max - ei->value.integer.min); return ei->value.integer.min + (range * percent) / 100; } @@ -389,6 +386,11 @@ int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value) break; case SNDRV_CTL_ELEM_TYPE_INTEGER: + if ((value < mixer_ctl_get_range_min(ctl)) || + (value > mixer_ctl_get_range_max(ctl))) { + return -EINVAL; + } + ev.value.integer.value[id] = value; break; @@ -396,6 +398,10 @@ int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value) ev.value.enumerated.item[id] = value; break; + case SNDRV_CTL_ELEM_TYPE_BYTES: + ev.value.bytes.data[id] = value; + break; + default: return -EINVAL; } @@ -494,4 +500,3 @@ int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string) return -EINVAL; } - diff --git a/firmware/target/hosted/android/dx50/tinyalsa/pcm.c b/firmware/target/hosted/ibasso/tinyalsa/pcm.c similarity index 90% rename from firmware/target/hosted/android/dx50/tinyalsa/pcm.c rename to firmware/target/hosted/ibasso/tinyalsa/pcm.c index bd44dce52f..0d2f0adf08 100644 --- a/firmware/target/hosted/android/dx50/tinyalsa/pcm.c +++ b/firmware/target/hosted/ibasso/tinyalsa/pcm.c @@ -44,7 +44,7 @@ #define __force #define __bitwise #define __user -#include +#include #include @@ -159,6 +159,7 @@ struct pcm { int fd; unsigned int flags; int running:1; + int prepared:1; int underruns; unsigned int buffer_size; unsigned int boundary; @@ -300,7 +301,7 @@ static void pcm_hw_munmap_status(struct pcm *pcm) { } static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset, - const char *src, unsigned int src_offset, + char *buf, unsigned int src_offset, unsigned int frames) { int size_bytes = pcm_frames_to_bytes(pcm, frames); @@ -308,12 +309,18 @@ static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset, int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset); /* interleaved only atm */ - memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes, - src + src_offset_bytes, size_bytes); + if (pcm->flags & PCM_IN) + memcpy(buf + src_offset_bytes, + (char*)pcm->mmap_buffer + pcm_offset_bytes, + size_bytes); + else + memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes, + buf + src_offset_bytes, + size_bytes); return 0; } -static int pcm_mmap_write_areas(struct pcm *pcm, const char *src, +static int pcm_mmap_transfer_areas(struct pcm *pcm, char *buf, unsigned int offset, unsigned int size) { void *pcm_areas; @@ -323,7 +330,7 @@ static int pcm_mmap_write_areas(struct pcm *pcm, const char *src, while (size > 0) { frames = size; pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames); - pcm_areas_copy(pcm, pcm_offset, src, offset, frames); + pcm_areas_copy(pcm, pcm_offset, buf, offset, frames); commit = pcm_mmap_commit(pcm, pcm_offset, frames); if (commit < 0) { oops(pcm, commit, "failed to commit %d frames\n", frames); @@ -386,14 +393,16 @@ int pcm_write(struct pcm *pcm, const void *data, unsigned int count) for (;;) { if (!pcm->running) { - if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE)) - return oops(pcm, errno, "cannot prepare channel"); + int prepare_error = pcm_prepare(pcm); + if (prepare_error) + return prepare_error; if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) return oops(pcm, errno, "cannot write initial data"); pcm->running = 1; return 0; } if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) { + pcm->prepared = 0; pcm->running = 0; if (errno == EPIPE) { /* we failed to make our window -- try to restart if we are @@ -429,6 +438,7 @@ int pcm_read(struct pcm *pcm, void *data, unsigned int count) } } if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) { + pcm->prepared = 0; pcm->running = 0; if (errno == EPIPE) { /* we failed to make our window -- try to restart */ @@ -494,6 +504,12 @@ void pcm_params_free(struct pcm_params *pcm_params) static int pcm_param_to_alsa(enum pcm_param param) { switch (param) { + case PCM_PARAM_ACCESS: + return SNDRV_PCM_HW_PARAM_ACCESS; + case PCM_PARAM_FORMAT: + return SNDRV_PCM_HW_PARAM_FORMAT; + case PCM_PARAM_SUBFORMAT: + return SNDRV_PCM_HW_PARAM_SUBFORMAT; case PCM_PARAM_SAMPLE_BITS: return SNDRV_PCM_HW_PARAM_SAMPLE_BITS; break; @@ -536,6 +552,23 @@ static int pcm_param_to_alsa(enum pcm_param param) } } +struct pcm_mask *pcm_params_get_mask(struct pcm_params *pcm_params, + enum pcm_param param) +{ + int p; + struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params; + if (params == NULL) { + return NULL; + } + + p = pcm_param_to_alsa(param); + if (p < 0 || !param_is_mask(p)) { + return NULL; + } + + return (struct pcm_mask *)param_to_mask(params, p); +} + unsigned int pcm_params_get_min(struct pcm_params *pcm_params, enum pcm_param param) { @@ -582,6 +615,7 @@ int pcm_close(struct pcm *pcm) if (pcm->fd >= 0) close(pcm->fd); + pcm->prepared = 0; pcm->running = 0; pcm->buffer_size = 0; pcm->fd = -1; @@ -706,7 +740,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, pcm->boundary = sparams.boundary = pcm->buffer_size; while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size) - pcm->boundary *= 2; + pcm->boundary *= 2; if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) { oops(pcm, errno, "cannot set sw params"); @@ -719,6 +753,17 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, goto fail; } +#ifdef SNDRV_PCM_IOCTL_TTSTAMP + if (pcm->flags & PCM_MONOTONIC) { + int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC; + rc = ioctl(pcm->fd, SNDRV_PCM_IOCTL_TTSTAMP, &arg); + if (rc < 0) { + oops(pcm, rc, "cannot set timestamp type"); + goto fail; + } + } +#endif + pcm->underruns = 0; return pcm; @@ -736,13 +781,26 @@ int pcm_is_ready(struct pcm *pcm) return pcm->fd >= 0; } -int pcm_start(struct pcm *pcm) +int pcm_prepare(struct pcm *pcm) { + if (pcm->prepared) + return 0; + if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0) return oops(pcm, errno, "cannot prepare channel"); + pcm->prepared = 1; + return 0; +} + +int pcm_start(struct pcm *pcm) +{ + int prepare_error = pcm_prepare(pcm); + if (prepare_error) + return prepare_error; + if (pcm->flags & PCM_MMAP) - pcm_sync_ptr(pcm, 0); + pcm_sync_ptr(pcm, 0); if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0) return oops(pcm, errno, "cannot start channel"); @@ -756,6 +814,7 @@ int pcm_stop(struct pcm *pcm) if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0) return oops(pcm, errno, "cannot stop channel"); + pcm->prepared = 0; pcm->running = 0; return 0; } @@ -831,7 +890,7 @@ int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames) { - (void)offset; + (void) offset; /* update the application pointer in userspace and kernel */ pcm_mmap_appl_forward(pcm, frames); pcm_sync_ptr(pcm, 0); @@ -895,7 +954,7 @@ int pcm_wait(struct pcm *pcm, int timeout) return 1; } -int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) +int pcm_mmap_transfer(struct pcm *pcm, const void *buffer, unsigned int bytes) { int err = 0, frames, avail; unsigned int offset = 0, count; @@ -915,7 +974,7 @@ int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) } /* start the audio if we reach the threshold */ - if (!pcm->running && + if (!pcm->running && (pcm->buffer_size - avail) >= pcm->config.start_threshold) { if (pcm_start(pcm) < 0) { fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n", @@ -937,6 +996,7 @@ int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) err = pcm_wait(pcm, time); if (err < 0) { + pcm->prepared = 0; pcm->running = 0; fprintf(stderr, "wait error: hw 0x%x app 0x%x avail 0x%x\n", (unsigned int)pcm->mmap_status->hw_ptr, @@ -956,7 +1016,7 @@ int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) break; /* copy frames from buffer */ - frames = pcm_mmap_write_areas(pcm, buffer, offset, frames); + frames = pcm_mmap_transfer_areas(pcm, (void *)buffer, offset, frames); if (frames < 0) { fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n", (unsigned int)pcm->mmap_status->hw_ptr, @@ -971,3 +1031,19 @@ int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) return 0; } + +int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count) +{ + if ((~pcm->flags) & (PCM_OUT | PCM_MMAP)) + return -ENOSYS; + + return pcm_mmap_transfer(pcm, (void *)data, count); +} + +int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count) +{ + if ((~pcm->flags) & (PCM_IN | PCM_MMAP)) + return -ENOSYS; + + return pcm_mmap_transfer(pcm, data, count); +} diff --git a/firmware/target/hosted/ibasso/usb-ibasso.c b/firmware/target/hosted/ibasso/usb-ibasso.c new file mode 100644 index 0000000000..e1b134e545 --- /dev/null +++ b/firmware/target/hosted/ibasso/usb-ibasso.c @@ -0,0 +1,92 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 "config.h" +#include "debug.h" + +#include "debug-ibasso.h" +#include "usb-ibasso.h" + + +static void usb_enable_adb(void) +{ + TRACE; + + if(system(NULL)) + { + system("setprop persist.sys.usb.config adb"); + system("setprop persist.usb.debug 1"); + return; + } + + DEBUGF("ERROR %s: No command processor available.", __func__); +} + + +static void usb_enable_mass_storage(void) +{ + TRACE; + + if(system(NULL)) + { + system("setprop persist.sys.usb.config mass_storage"); + system("setprop persist.usb.debug 0"); + return; + } + + DEBUGF("ERROR %s: No command processor available.", __func__); +} + + +/* Default at boot not known. */ +static int _last_usb_mode = -1; + + +void ibasso_set_usb_mode(int mode) +{ + DEBUGF("DEBUG %s: _last_usb_mode: %d, mode: %d.", __func__, _last_usb_mode, mode); + + if(_last_usb_mode != mode) + { + switch(mode) + { + case USB_MODE_MASS_STORAGE: + { + _last_usb_mode = mode; + usb_enable_mass_storage(); + break; + } + + case USB_MODE_CHARGE: /* Work around. */ + case USB_MODE_ADB: + { + _last_usb_mode = mode; + usb_enable_adb(); + break; + } + } + } +} diff --git a/firmware/target/hosted/ibasso/usb-ibasso.h b/firmware/target/hosted/ibasso/usb-ibasso.h new file mode 100644 index 0000000000..f509d43038 --- /dev/null +++ b/firmware/target/hosted/ibasso/usb-ibasso.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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_DX50_H_ +#define _USB_DX50_H_ + + +/* Supported usb modes. */ +enum ibasso_usb_mode +{ + /* + USB mass storage mode. On USB connection, Rockbox will terminate and the internel and + external storage gets exported to the connected client. + */ + USB_MODE_MASS_STORAGE = 0, + + /* + Actually the same, since we to not have proper USB detection. + Starts the adb server and enables adb connection over USB. Rockbox will continue to run. + */ + USB_MODE_CHARGE, + USB_MODE_ADB +}; + + +/* + Set the usb mode. + mode: ibasso_usb_mode +*/ +void ibasso_set_usb_mode(int mode); + + +#endif diff --git a/firmware/target/hosted/ibasso/vold-ibasso.c b/firmware/target/hosted/ibasso/vold-ibasso.c new file mode 100644 index 0000000000..c92b86d364 --- /dev/null +++ b/firmware/target/hosted/ibasso/vold-ibasso.c @@ -0,0 +1,203 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 +#include + +#include "config.h" +#include "debug.h" +#include "powermgmt.h" + +#include "debug-ibasso.h" + + +/* + Without this socket iBasso Vold will not start. + iBasso Vold uses this to send status messages about storage devices. +*/ +static const char VOLD_MONITOR_SOCKET_NAME[] = "UNIX_domain"; +static int _vold_monitor_socket_fd = -1; + + +static void vold_monitor_open_socket(void) +{ + TRACE; + + unlink(VOLD_MONITOR_SOCKET_NAME); + + _vold_monitor_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); + + if(_vold_monitor_socket_fd < 0) + { + _vold_monitor_socket_fd = -1; + return; + } + + struct sockaddr_un addr; + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + strncpy(addr.sun_path, VOLD_MONITOR_SOCKET_NAME, sizeof(addr.sun_path) -1); + + if(bind(_vold_monitor_socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) + { + close(_vold_monitor_socket_fd); + unlink(VOLD_MONITOR_SOCKET_NAME); + _vold_monitor_socket_fd = -1; + return; + } + + if(listen(_vold_monitor_socket_fd, 1) < 0) + { + close(_vold_monitor_socket_fd); + unlink(VOLD_MONITOR_SOCKET_NAME); + _vold_monitor_socket_fd = -1; + return; + } +} + + +/* + bionic does not have pthread_cancel. + 0: Vold monitor thread stopped/ending. + 1: Vold monitor thread started/running. +*/ +static volatile sig_atomic_t _vold_monitor_active = 0; + + +/* + 1: /mnt/sdcard is unmounting + 0: else +*/ +static volatile sig_atomic_t _vold_monitor_forced_close_imminent = 0; + + +static void* vold_monitor_run(void* nothing) +{ + _vold_monitor_active = 1; + + (void) nothing; + + DEBUGF("DEBUG %s: Thread start.", __func__); + + vold_monitor_open_socket(); + if(_vold_monitor_socket_fd < 0) + { + DEBUGF("ERROR %s: Thread end: No socket.", __func__); + + _vold_monitor_active = 0; + return 0; + } + + struct pollfd fds[1]; + fds[0].fd = _vold_monitor_socket_fd; + fds[0].events = POLLIN; + + while(_vold_monitor_active == 1) + { + poll(fds, 1, 10); + if(! (fds[0].revents & POLLIN)) + { + continue; + } + + int socket_fd = accept(_vold_monitor_socket_fd, NULL, NULL); + + if(socket_fd < 0) + { + DEBUGF("ERROR %s: accept failed.", __func__); + + continue; + } + + while(true) + { + char msg[1024]; + memset(msg, 0, sizeof(msg)); + int length = read(socket_fd, msg, sizeof(msg)); + + if(length <= 0) + { + close(socket_fd); + break; + } + + DEBUGF("%s: msg: %s", __func__, msg); + + if(strcmp(msg, "Volume flash /mnt/sdcard state changed from 4 (Mounted) to 5 (Unmounting)") == 0) + { + /* We are losing /mnt/sdcard, shutdown Rockbox before it is forced closed. */ + + _vold_monitor_forced_close_imminent = 1; + sys_poweroff(); + _vold_monitor_active = 0; + } + else if(strcmp(msg, "Volume sdcard /mnt/external_sd state changed from 4 (Mounted) to 5 (Unmounting)") == 0) + { + /* We are loosing the external sdcard, inform Rockbox. */ + } + else if(strcmp(msg, "Volume sdcard /mnt/external_sd state changed from 3 (Checking) to 4 (Mounted)") == 0) + { + /* The external sdcard is back, inform Rockbox. */ + } + } + } + + close(_vold_monitor_socket_fd); + unlink(VOLD_MONITOR_SOCKET_NAME); + _vold_monitor_socket_fd = -1; + + DEBUGF("%s: Thread end.", __func__); + + _vold_monitor_active = 0; + return 0; +} + + +/* Vold monitor thread. */ +static pthread_t _vold_monitor_thread; + + +void vold_monitor_start(void) +{ + TRACE; + + if(_vold_monitor_active == 0) + { + pthread_create(&_vold_monitor_thread, NULL, vold_monitor_run, NULL); + } +} + + +bool vold_monitor_forced_close_imminent(void) +{ + TRACE; + + return(_vold_monitor_forced_close_imminent == 1); +} diff --git a/firmware/target/hosted/ibasso/vold-ibasso.h b/firmware/target/hosted/ibasso/vold-ibasso.h new file mode 100644 index 0000000000..18012b7e16 --- /dev/null +++ b/firmware/target/hosted/ibasso/vold-ibasso.h @@ -0,0 +1,42 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 + * Copyright (C) 2014 by Mario Basister: iBasso DX90 port + * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features + * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features + * + * 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 __VOLD_IBASSO_H__ +#define __VOLD_IBASSO_H__ + + +/* Start the vold monitor thread. */ +void vold_monitor_start(void); + + +/* + Used to change Rockbox shutdown from reboot/power off to program exit. + true: vold monitor has detected, that vold is remounting /mnt/sdcard for USB mass storage + access. + false: else. +*/ +bool vold_monitor_forced_close_imminent(void); + + +#endif diff --git a/lib/rbcodec/dsp/compressor.c b/lib/rbcodec/dsp/compressor.c index 685851ec29..93281d276c 100644 --- a/lib/rbcodec/dsp/compressor.c +++ b/lib/rbcodec/dsp/compressor.c @@ -185,7 +185,7 @@ static bool compressor_update(struct dsp_config *dsp, auto_gain ? "Auto" : "Off"); } - if (settings->ratio != cur_set.ratio) + if (settings->ratio != curr_set.ratio) { if (ratio) { logf(" Compressor Ratio: %d:1", ratio); } @@ -193,16 +193,16 @@ static bool compressor_update(struct dsp_config *dsp, { logf(" Compressor Ratio: Limit"); } } - if (settings->knee != cur_set.knee) + if (settings->knee != curr_set.knee) { logf(" Compressor Knee: %s", soft_knee?"Soft":"Hard"); } - if (settings->release_time != cur_set.release_time) + if (settings->release_time != curr_set.release_time) { logf(" Compressor Release: %d", release); } - if (settings->attack_time != cur_set.attack_time) + if (settings->attack_time != curr_set.attack_time) { logf(" Compressor Attack: %d", attack); } @@ -357,7 +357,7 @@ static bool compressor_update(struct dsp_config *dsp, for (int i = 1; i <= 65; i++) { DEBUGF("%02d: %.6f ", i, (float)comp_curve[i] / UNITY); - if (i % 4 == 0) DEBUGF("\n"); + if (i % 4 == 0) { DEBUGF("\n"); } } DEBUGF("\n"); diff --git a/tools/configure b/tools/configure index 20b9095f73..2dd1bf3e12 100755 --- a/tools/configure +++ b/tools/configure @@ -726,6 +726,58 @@ androidcc () { prefixtools $gcctarget } +androidndkcc() +{ + if ! [ -d "$ANDROID_NDK_PATH" ]; then + echo "ERROR: You need the Android NDK installed (r16 or higher) and have the ANDROID_NDK_PATH" + echo "environment variable point to the root directory of the Android NDK." + exit + fi + + make_toolchain="${ANDROID_NDK_PATH}/build/tools/make-standalone-toolchain.sh" + + if ! [ -e "${make_toolchain}" ]; then + echo "ERROR: ${make_toolchain} could not be found." + exit + fi + + buildhost=$(uname -s | tr "[:upper:]" "[:lower:]") + buildhost="${buildhost}-$(uname -m)" + + GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib// -e s/-Wundef//` + LDOPTS="$LDOPTS -ldl -llog" + SHARED_LDFLAG="-shared" + SHARED_CFLAGS='' + GLOBAL_LDOPTS="-Wl,-z,defs -Wl,-z,noexecstack" + + # arch dependant stuff + case $1 in + armeabi) + endian="little" + gccchoice="4.6" + gcctarget="arm-linux-androideabi-" + echo "${make_toolchain} --system=${buildhost} --toolchain=arm-linux-androideabi-4.6 --platform=android-16 --install-dir=${pwd}/android-toolchain" + ${make_toolchain} --system=${buildhost} --toolchain=arm-linux-androideabi-4.6 --platform=android-16 --install-dir=${pwd}/android-toolchain + if [ ${?} != 0 ]; then + exit + fi + GCCOPTS="$GCCOPTS -march=armv5te -mtune=xscale -msoft-float -fomit-frame-pointer --sysroot=${pwd}/android-toolchain/sysroot" + LDOPTS="$LDOPTS --sysroot=${pwd}/android-toolchain/sysroot" + ;; + *) + echo "ERROR: androidndkcc(): Unknown target architecture" + exit + ;; + esac + + echo "Using endian ${endian}" + echo "Using gccchoice ${gccchoice}" + echo "Using gcctarget ${gcctarget}" + + PATH=$PATH:${pwd}/android-toolchain/bin + prefixtools $gcctarget +} + whichadvanced () { atype=`echo "$1" | cut -c 2-` ################################################################## @@ -3751,26 +3803,24 @@ fi target_id=94 modelname="ibassodx50" target="DX50" - app_type="android_standalone" + app_type="android_ndk" lcd_orientation="landscape" - sharedir="/system/rockbox/app_rockbox/rockbox" - bindir="/system/rockbox/lib" - libdir="/system/rockbox/app_rockbox" - memory=32 + # Actually 408260kB + memory=256 uname=`uname` - androidcc armeabi + androidndkcc armeabi tool="cp " boottool="cp " bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" bmp2rb_native="$rootdir/tools/bmp2rb -f 4" output="rockbox" bootoutput="rockbox" - appextra="recorder:gui:radio:hosted/android" + appextra="recorder:gui:hosted" plugins="yes" swcodec="yes" # architecture, manufacturer and model for the target-tree build t_cpu="hosted" - t_manufacturer="android" + t_manufacturer="ibasso" t_model="dx50" ;; @@ -3779,27 +3829,24 @@ fi target_id=95 modelname="ibassodx90" target="DX90" - app_type="android_standalone" + app_type="android_ndk" lcd_orientation="landscape" - sharedir="/system/rockbox/app_rockbox/rockbox" - bindir="/system/rockbox/lib" - libdir="/system/rockbox/app_rockbox" - memory=32 + memory=256 uname=`uname` - androidcc armeabi + androidndkcc armeabi tool="cp " boottool="cp " bmp2rb_mono="$rootdir/tools/bmp2rb -f 0" bmp2rb_native="$rootdir/tools/bmp2rb -f 4" output="rockbox" bootoutput="rockbox" - appextra="recorder:gui:radio:hosted/android" + appextra="recorder:gui:hosted" plugins="yes" swcodec="yes" # architecture, manufacturer and model for the target-tree build t_cpu="hosted" - t_manufacturer="android" - t_model="dx50" + t_manufacturer="ibasso" + t_model="dx90" ;; *) @@ -4333,6 +4380,8 @@ if test -n "$t_cpu"; then elif [ "$simulator" = "yes" ]; then # a few more includes for the sim target tree TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/sdl" TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted" + elif [ "$t_manufacturer" = "ibasso" ]; then + TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/hosted/ibasso/tinyalsa/include" fi TARGET_INC="$TARGET_INC -I\$(FIRMDIR)/target/$t_cpu/$t_manufacturer" diff --git a/tools/root.make b/tools/root.make index 4e0ca7c4f0..2deae8cc82 100644 --- a/tools/root.make +++ b/tools/root.make @@ -132,8 +132,12 @@ else # core include $(ROOTDIR)/firmware/target/hosted/samsungypr/ypr1/ypr1.make endif - ifneq (,$(findstring android, $(APP_TYPE))) - include $(ROOTDIR)/android/android.make + ifneq (,$(findstring android_ndk, $(APP_TYPE))) + include $(ROOTDIR)/firmware/target/hosted/ibasso/android_ndk.make + else + ifneq (,$(findstring android, $(APP_TYPE))) + include $(ROOTDIR)/android/android.make + endif endif ifneq (,$(findstring pandora, $(MODELNAME)))