summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES4
-rw-r--r--apps/action.c4
-rw-r--r--apps/keymaps/keymap-dx50.c301
-rw-r--r--apps/keymaps/keymap-touchscreen.c12
-rw-r--r--apps/main.c4
-rw-r--r--apps/playback.c2
-rw-r--r--apps/plugins/SOURCES.app_build2
-rw-r--r--apps/plugins/SUBDIRS.app_build2
-rw-r--r--apps/plugins/battery_bench.c8
-rw-r--r--apps/plugins/plugins.make2
-rw-r--r--apps/root_menu.c4
-rw-r--r--apps/scrobbler.c2
-rw-r--r--apps/settings.h2
-rw-r--r--firmware/SOURCES47
-rw-r--r--firmware/backlight.c7
-rw-r--r--firmware/drivers/audio/android.c24
-rw-r--r--firmware/drivers/button.c21
-rw-r--r--firmware/export/audiohw.h4
-rw-r--r--firmware/export/config/ibassodx50.h82
-rw-r--r--firmware/export/config/ibassodx90.h61
-rw-r--r--firmware/export/hosted_codec.h2
-rw-r--r--firmware/export/pcm_mixer.h6
-rw-r--r--firmware/export/rbpaths.h7
-rw-r--r--firmware/powermgmt.c2
-rw-r--r--firmware/target/hosted/android/dx50/adc-target.h0
-rw-r--r--firmware/target/hosted/android/dx50/backlight-dx50.c76
-rw-r--r--firmware/target/hosted/android/dx50/button-dx50.c316
-rw-r--r--firmware/target/hosted/android/dx50/lcd-dx50.c120
-rw-r--r--firmware/target/hosted/android/dx50/pcm-dx50.c364
-rw-r--r--firmware/target/hosted/android/dx50/powermgmt-dx50.c97
-rw-r--r--firmware/target/hosted/android/system-android.c54
-rw-r--r--firmware/target/hosted/filesystem-app.c2
-rw-r--r--firmware/target/hosted/ibasso/android_ndk.make49
-rw-r--r--firmware/target/hosted/ibasso/audiohw-ibasso.c81
-rw-r--r--firmware/target/hosted/ibasso/backlight-ibasso.c132
-rw-r--r--firmware/target/hosted/ibasso/backlight-target.h (renamed from firmware/target/hosted/android/dx50/backlight-target.h)20
-rw-r--r--firmware/target/hosted/ibasso/button-ibasso.c420
-rw-r--r--firmware/target/hosted/ibasso/button-ibasso.h61
-rw-r--r--firmware/target/hosted/ibasso/button-target.h (renamed from firmware/target/hosted/android/dx50/button-target.h)47
-rw-r--r--firmware/target/hosted/ibasso/debug-ibasso.c70
-rw-r--r--firmware/target/hosted/ibasso/debug-ibasso.h38
-rw-r--r--firmware/target/hosted/ibasso/dx50/audiohw-dx50.c68
-rw-r--r--firmware/target/hosted/ibasso/dx50/button-dx50.c96
-rw-r--r--firmware/target/hosted/ibasso/dx50/codec-dx50.h51
-rw-r--r--firmware/target/hosted/ibasso/dx90/audiohw-dx90.c63
-rw-r--r--firmware/target/hosted/ibasso/dx90/button-dx90.c104
-rw-r--r--firmware/target/hosted/ibasso/dx90/codec-dx90.h35
-rw-r--r--firmware/target/hosted/ibasso/hostfs-ibasso.c47
-rw-r--r--firmware/target/hosted/ibasso/lcd-ibasso.c195
-rw-r--r--firmware/target/hosted/ibasso/lcd-target.h44
-rw-r--r--firmware/target/hosted/ibasso/pcm-ibasso.c488
-rw-r--r--firmware/target/hosted/ibasso/pcm-ibasso.h33
-rw-r--r--firmware/target/hosted/ibasso/power-ibasso.c97
-rw-r--r--firmware/target/hosted/ibasso/powermgmt-ibasso.c122
-rw-r--r--firmware/target/hosted/ibasso/sysfs-ibasso.c404
-rw-r--r--firmware/target/hosted/ibasso/sysfs-ibasso.h111
-rw-r--r--firmware/target/hosted/ibasso/system-ibasso.c101
-rw-r--r--firmware/target/hosted/ibasso/system-target.h (renamed from firmware/target/hosted/android/dx50/lcd-target.h)24
-rw-r--r--firmware/target/hosted/ibasso/tinyalsa/include/sound/asound.h (renamed from firmware/target/hosted/android/dx50/tinyalsa/asound.h)1
-rw-r--r--firmware/target/hosted/ibasso/tinyalsa/include/tinyalsa/asoundlib.h (renamed from firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h)45
-rw-r--r--firmware/target/hosted/ibasso/tinyalsa/mixer.c (renamed from firmware/target/hosted/android/dx50/tinyalsa/mixer.c)23
-rw-r--r--firmware/target/hosted/ibasso/tinyalsa/pcm.c (renamed from firmware/target/hosted/android/dx50/tinyalsa/pcm.c)106
-rw-r--r--firmware/target/hosted/ibasso/usb-ibasso.c92
-rw-r--r--firmware/target/hosted/ibasso/usb-ibasso.h54
-rw-r--r--firmware/target/hosted/ibasso/vold-ibasso.c203
-rw-r--r--firmware/target/hosted/ibasso/vold-ibasso.h42
-rw-r--r--lib/rbcodec/dsp/compressor.c10
-rwxr-xr-xtools/configure83
-rw-r--r--tools/root.make8
69 files changed, 3908 insertions, 1401 deletions
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 <stdio.h>
#include <string.h>
@@ -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
- */
-
-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 },
+ Button Code Definitions for iBasso DX50 & DX90.
+
+ 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_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 },
+};
+
+
+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 },
+
LAST_ITEM_IN_LIST
-}; /* button_context_wps */
-
-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
+};
+
+
+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 },
+
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_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_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 },
+
+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_settings_right_is_inc[] =
+{
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_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[] = {
- 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_colorchooser[] =
+{
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 },
+static const struct button_mapping button_context_eq[] =
+{
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS),
+};
- { 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,29 +1815,51 @@ 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
+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/android/debug-android.c
+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
-target/hosted/android/system-android.c
-drivers/audio/android.c
#endif
#else /* defined(SIMULATOR) */
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
--- a/firmware/target/hosted/android/dx50/adc-target.h
+++ /dev/null
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 <fcntl.h>
-#include <stdio.h>
-#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 <stdbool.h>
-#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 <linux/input.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/inotify.h>
-#include <sys/limits.h>
-#include <sys/poll.h>
-#include <errno.h>
-
-
-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 <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <linux/fb.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#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 <stdlib.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <errno.h>
-#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 <pthread.h>
-#include <signal.h>
-
-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 <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#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 <setjmp.h>
#include <jni.h>
#include <pthread.h>
-#if defined(DX50) || defined(DX90)
-#include <stdlib.h>
-#include <sys/reboot.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#endif /* DX50 || DX90 */
#include <unistd.h>
#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 <stdbool.h>
+
+#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
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 <stdbool.h>
+
+/* 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 <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/input.h>
+#include <sys/inotify.h>
+#include <sys/limits.h>
+#include <sys/poll.h>
+
+#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 <sys/types.h>
+
+
+/* /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
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 <stdbool.h>
-
-#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 <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <android/log.h>
+
+#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 <unistd.h>
+
+#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 <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <linux/fb.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#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 <pthread.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+#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 <stdbool.h>
+#include <stdlib.h>
+#include <sys/reboot.h>
+
+#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 <stdio.h>
+
+#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 <stdio.h>
+#include <string.h>
+
+#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 <stdbool.h>
+
+
+/*
+ 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 <stdint.h>
+#include <stdlib.h>
+#include <sys/reboot.h>
+
+#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
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
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
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
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 <tinyalsa/asound.h>
+#include <sound/asound.h>
#include <tinyalsa/asoundlib.h>
@@ -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 = 100;
- else if (percent < 0)
- percent = 0;
+ if ((percent > 100) || (percent < 0)) {
+ return -EINVAL;
+ }
- 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
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 <tinyalsa/asound.h>
+#include <sound/asound.h>
#include <tinyalsa/asoundlib.h>
@@ -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 <stdlib.h>
+
+#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 <pthread.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#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)))