diff --git a/apps/SOURCES b/apps/SOURCES
index ba36bc3ef6..54f7461e05 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -300,4 +300,6 @@ keymaps/keymap-xduoox3.c
keymaps/keymap-xduoox3ii.c
#elif CONFIG_KEYPAD == XDUOO_X20_PAD
keymaps/keymap-xduoox20.c
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+keymaps/keymap-fiiom3k.c
#endif
diff --git a/apps/bitmaps/native/SOURCES b/apps/bitmaps/native/SOURCES
index 8f42607a0c..201ffc4ad3 100644
--- a/apps/bitmaps/native/SOURCES
+++ b/apps/bitmaps/native/SOURCES
@@ -38,7 +38,7 @@ rockboxlogo.640x198x16.bmp
#endif
/* The Sony NWZ linux bootloader needs icons to display a menu */
-#if defined(BOOTLOADER)
+#if defined(BOOTLOADER)
#if defined(SONY_NWZ_LINUX)
rockboxicon.130x130x16.bmp
toolsicon.130x130x16.bmp
@@ -50,6 +50,10 @@ toolsicon.70x70x16.bmp
hibyicon.130x130x16.bmp
rockboxicon.130x130x16.bmp
toolsicon.130x130x16.bmp
+#elif defined(FIIO_M3K)
+fiioicon.130x130x16.bmp
+rockboxicon.130x130x16.bmp
+toolsicon.130x130x16.bmp
#endif
#endif
diff --git a/apps/bitmaps/native/fiioicon.130x130x16.bmp b/apps/bitmaps/native/fiioicon.130x130x16.bmp
new file mode 100644
index 0000000000..15e1f7b37f
Binary files /dev/null and b/apps/bitmaps/native/fiioicon.130x130x16.bmp differ
diff --git a/apps/features.txt b/apps/features.txt
index 4b7a66099e..f0c2e4a12b 100644
--- a/apps/features.txt
+++ b/apps/features.txt
@@ -183,7 +183,7 @@ depth_3d
#endif
/* This should be AUDIOHW_HAVE_FILTER_ROLL_OFF but that is only defined later */
-#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC)
+#if defined(DX50) || defined(HAVE_DF1704_CODEC) || defined(HAVE_PCM1792_CODEC) || defined(HAVE_CS4398) || defined(HAVE_WM8740) || defined(HAVE_ES9018) || defined(HAVE_XDUOO_LINUX_CODEC) || defined(HAVE_FIIO_LINUX_CODEC)
filter_roll_off
#endif
diff --git a/apps/keymaps/keymap-fiiom3k.c b/apps/keymaps/keymap-fiiom3k.c
new file mode 100644
index 0000000000..4fa97e9435
--- /dev/null
+++ b/apps/keymaps/keymap-fiiom3k.c
@@ -0,0 +1,224 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2019 by Roman Stolyarov
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+/* Button Code Definitions for FiiO M3K target */
+
+#include "config.h"
+#include "action.h"
+#include "button.h"
+#include "settings.h"
+
+/* {Action Code, Button code, Prereq button code } */
+
+/*
+ * The format of the list is as follows
+ * { Action Code, Button code, Prereq button code }
+ * if there's no need to check the previous button's value, use BUTTON_NONE
+ * Insert LAST_ITEM_IN_LIST at the end of each mapping
+ */
+static const struct button_mapping button_context_standard[] = {
+ { ACTION_STD_PREV, BUTTON_UP, BUTTON_NONE },
+ { ACTION_STD_PREV, BUTTON_PREV, BUTTON_NONE },
+ { ACTION_STD_PREVREPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_NEXT, BUTTON_DOWN, BUTTON_NONE },
+ { ACTION_STD_NEXT, BUTTON_NEXT, BUTTON_NONE },
+ { ACTION_STD_NEXTREPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
+ { ACTION_STD_CANCEL, BUTTON_HOME|BUTTON_REL, BUTTON_HOME },
+ { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
+ { ACTION_STD_MENU, BUTTON_OPTION|BUTTON_REL, BUTTON_OPTION },
+
+ LAST_ITEM_IN_LIST
+}; /* button_context_standard */
+
+static const struct button_mapping button_context_wps[] = {
+ { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
+// { ACTION_WPS_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
+ { ACTION_WPS_SKIPPREV, BUTTON_PREV|BUTTON_REL, BUTTON_PREV },
+ { ACTION_WPS_SEEKBACK, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_WPS_STOPSEEK, BUTTON_PREV|BUTTON_REL, BUTTON_PREV|BUTTON_REPEAT },
+ { ACTION_WPS_SKIPNEXT, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT },
+ { ACTION_WPS_SEEKFWD, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_WPS_STOPSEEK, BUTTON_NEXT|BUTTON_REL, BUTTON_NEXT|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 },
+ { ACTION_WPS_BROWSE, BUTTON_HOME|BUTTON_REL, BUTTON_HOME },
+ { ACTION_WPS_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
+ { ACTION_WPS_MENU, BUTTON_OPTION|BUTTON_REL, BUTTON_OPTION },
+ { ACTION_WPS_QUICKSCREEN, BUTTON_OPTION|BUTTON_REPEAT, BUTTON_OPTION },
+ { ACTION_WPS_HOTKEY, BUTTON_HOME|BUTTON_REPEAT, BUTTON_HOME },
+
+// XXX BUTTON_UP and BUTTON_DOWN aren't on here.
+
+ { ACTION_STD_KEYLOCK, BUTTON_POWER, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST
+}; /* button_context_wps */
+
+static const struct button_mapping button_context_list[] = {
+ { ACTION_LIST_VOLUP, BUTTON_VOL_UP, BUTTON_NONE },
+ { ACTION_LIST_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, 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 */
+
+/** Bookmark Screen **/
+static const struct button_mapping button_context_bmark[] = {
+ { ACTION_BMS_DELETE, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST)
+}; /* button_context_bmark */
+
+/** Keyboard **/
+static const struct button_mapping button_context_keyboard[] = {
+ { ACTION_KBD_LEFT, BUTTON_PREV, BUTTON_NONE },
+ { ACTION_KBD_LEFT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_RIGHT, BUTTON_NEXT, BUTTON_NONE },
+ { ACTION_KBD_RIGHT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_DOWN, BUTTON_DOWN, BUTTON_NONE },
+ { ACTION_KBD_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_LEFT, BUTTON_VOL_UP, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_LEFT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_RIGHT, BUTTON_VOL_DOWN, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_RIGHT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_BACKSPACE, BUTTON_HOME, BUTTON_NONE },
+ { ACTION_KBD_BACKSPACE, BUTTON_HOME|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_SELECT, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
+ { ACTION_KBD_DONE, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY },
+ { ACTION_KBD_ABORT, BUTTON_POWER|BUTTON_REL, BUTTON_POWER },
+
+ LAST_ITEM_IN_LIST
+}; /* button_context_keyboard */
+
+/** Pitchscreen **/
+static const struct button_mapping button_context_pitchscreen[] = {
+ { ACTION_PS_INC_SMALL, BUTTON_UP, BUTTON_NONE },
+ { ACTION_PS_INC_BIG, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_DEC_SMALL, BUTTON_DOWN, BUTTON_NONE },
+ { ACTION_PS_DEC_BIG, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_NUDGE_LEFT, BUTTON_PREV, BUTTON_NONE },
+ { ACTION_PS_NUDGE_LEFTOFF, BUTTON_PREV|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_NUDGE_RIGHT, BUTTON_NEXT, BUTTON_NONE },
+ { ACTION_PS_NUDGE_RIGHTOFF, BUTTON_NEXT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_TOGGLE_MODE, BUTTON_PLAY|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_RESET, BUTTON_POWER|BUTTON_REL, BUTTON_POWER },
+ { ACTION_PS_EXIT, BUTTON_HOME|BUTTON_REL, BUTTON_HOME },
+ { ACTION_PS_SLOWER, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_PS_FASTER, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_pitchscreen */
+
+/** Quickscreen **/
+static const struct button_mapping button_context_quickscreen[] = {
+ { ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE },
+ { ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE },
+ { ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_QS_LEFT, BUTTON_PREV, BUTTON_NONE },
+ { ACTION_QS_LEFT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_QS_RIGHT, BUTTON_NEXT, BUTTON_NONE },
+ { ACTION_QS_RIGHT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_CANCEL, BUTTON_HOME|BUTTON_REL, BUTTON_HOME },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_quickscreen */
+
+/** Settings - General Mappings **/
+static const struct button_mapping button_context_settings[] = {
+ { ACTION_SETTINGS_RESET, BUTTON_POWER|BUTTON_REL, BUTTON_POWER },
+ { ACTION_STD_PREV, BUTTON_PREV, BUTTON_NONE },
+ { ACTION_STD_PREVREPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_NEXT, BUTTON_NEXT, BUTTON_NONE },
+ { ACTION_STD_NEXTREPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
+ { ACTION_STD_CANCEL, BUTTON_HOME|BUTTON_REL, BUTTON_HOME },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_settings */
+
+static const struct button_mapping button_context_settings_vol_is_inc[] = {
+ { ACTION_SETTINGS_INC, BUTTON_UP, BUTTON_NONE },
+ { ACTION_SETTINGS_INCREPEAT,BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_SETTINGS_INC, BUTTON_VOL_UP, BUTTON_NONE },
+ { ACTION_SETTINGS_INCREPEAT,BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_SETTINGS_DEC, BUTTON_DOWN, BUTTON_NONE },
+ { ACTION_SETTINGS_DECREPEAT,BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN, BUTTON_NONE },
+ { ACTION_SETTINGS_DECREPEAT,BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_settings_right_is_inc */
+
+/** Tree **/
+static const struct button_mapping button_context_tree[] = {
+ { ACTION_TREE_WPS, BUTTON_OPTION|BUTTON_REL, BUTTON_OPTION },
+ { ACTION_TREE_HOTKEY, BUTTON_HOME|BUTTON_REPEAT, BUTTON_HOME },
+ { ACTION_STD_MENU, BUTTON_OPTION|BUTTON_REPEAT, BUTTON_OPTION },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST)
+}; /* button_context_tree */
+
+/** Yes/No Screen **/
+static const struct button_mapping button_context_yesnoscreen[] = {
+ { ACTION_YESNO_ACCEPT, BUTTON_PLAY, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_settings_yesnoscreen */
+
+/* get_context_mapping returns a pointer to one of the above defined arrays depending on the context */
+const struct button_mapping* get_context_mapping(int context)
+{
+ switch (context)
+ {
+ case CONTEXT_LIST:
+ return button_context_list;
+ case CONTEXT_STD:
+ return button_context_standard;
+ case CONTEXT_BOOKMARKSCREEN:
+ return button_context_bmark;
+ case CONTEXT_KEYBOARD:
+ return button_context_keyboard;
+ case CONTEXT_PITCHSCREEN:
+ return button_context_pitchscreen;
+ case CONTEXT_QUICKSCREEN:
+ return button_context_quickscreen;
+ case CONTEXT_SETTINGS:
+ return button_context_settings;
+ case CONTEXT_SETTINGS_TIME:
+ case CONTEXT_SETTINGS_COLOURCHOOSER:
+ case CONTEXT_SETTINGS_EQ:
+ case CONTEXT_SETTINGS_RECTRIGGER:
+ return button_context_settings_vol_is_inc;
+ case CONTEXT_TREE:
+ case CONTEXT_MAINMENU:
+ return button_context_tree;
+ case CONTEXT_WPS:
+ return button_context_wps;
+ case CONTEXT_YESNOSCREEN:
+ return button_context_yesnoscreen;
+ }
+ return button_context_standard;
+}
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 3f3bd26e30..55f89161a1 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -12533,6 +12533,40 @@
filter_roll_off: "Slow"
+
+ id: LANG_FILTER_SHORT_SHARP
+ desc: in sound settings
+ user: core
+
+
+ *: none
+ filter_roll_off: "Short Sharp"
+
+
+ *: none
+ filter_roll_off: "Short Sharp"
+
+
+
+ id: LANG_FILTER_SHORT_SLOW
+ desc: in sound settings
+ user: core
+
+
+ *: none
+ filter_roll_off: "Short Slow"
+
+
+ *: none
+ filter_roll_off: "Short Slow"
+
+
id: LANG_FILTER_SHORT
desc: in sound settings
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index ff979abd8e..f68e3ed5a3 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -281,6 +281,12 @@
#define BATTERY_ON_TXT "Play - start"
#define BATTERY_OFF_TXT "POWER"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define BATTERY_ON BUTTON_PLAY
+#define BATTERY_OFF BUTTON_POWER
+#define BATTERY_ON_TXT "Play - start"
+#define BATTERY_OFF_TXT "POWER"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c
index 93b577462b..b2e0383187 100644
--- a/apps/plugins/blackjack.c
+++ b/apps/plugins/blackjack.c
@@ -591,6 +591,22 @@ enum {
#define BJACK_RIGHT BUTTON_NEXT
#define BJACK_LEFT BUTTON_PREV
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define BJACK_SELECT_NAME "PLAY"
+#define BJACK_STAY_NAME "NEXT"
+#define BJACK_QUIT_NAME "POWER"
+#define BJACK_DOUBLE_NAME "PREV"
+#define BJACK_SELECT BUTTON_PLAY
+#define BJACK_QUIT BUTTON_POWER
+#define BJACK_MAX BUTTON_VOL_UP
+#define BJACK_MIN BUTTON_VOL_DOWN
+#define BJACK_STAY BUTTON_NEXT
+#define BJACK_DOUBLEDOWN BUTTON_PREV
+#define BJACK_UP BUTTON_HOME
+#define BJACK_DOWN BUTTON_OPTION
+#define BJACK_RIGHT BUTTON_NEXT
+#define BJACK_LEFT BUTTON_PREV
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define BJACK_SELECT_NAME "PLAY"
#define BJACK_STAY_NAME "NEXT"
diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c
index 5764c6869d..4452f23357 100644
--- a/apps/plugins/brickmania.c
+++ b/apps/plugins/brickmania.c
@@ -337,6 +337,16 @@ CONFIG_KEYPAD == SANSA_CONNECT_PAD
#define UP BUTTON_HOME
#define DOWN BUTTON_OPTION
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define QUIT BUTTON_POWER
+#define LEFT BUTTON_PREV
+#define RIGHT BUTTON_NEXT
+#define ALTLEFT BUTTON_VOL_DOWN
+#define ALTRIGHT BUTTON_VOL_UP
+#define SELECT BUTTON_PLAY
+#define UP BUTTON_HOME
+#define DOWN BUTTON_OPTION
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define QUIT BUTTON_POWER
#define LEFT BUTTON_HOME
diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c
index ac5a6ed7cd..f02f99ee0d 100644
--- a/apps/plugins/calculator.c
+++ b/apps/plugins/calculator.c
@@ -526,6 +526,17 @@ F3: equal to "="
#define CALCULATOR_CALC (BUTTON_PLAY|BUTTON_REPEAT)
#define CALCULATOR_CLEAR (BUTTON_POWER|BUTTON_REPEAT)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define CALCULATOR_LEFT BUTTON_PREV
+#define CALCULATOR_RIGHT BUTTON_NEXT
+#define CALCULATOR_UP BUTTON_HOME
+#define CALCULATOR_DOWN BUTTON_OPTION
+#define CALCULATOR_QUIT BUTTON_POWER
+#define CALCULATOR_INPUT_CALC_PRE (BUTTON_OPTION|BUTTON_REPEAT)
+#define CALCULATOR_INPUT (BUTTON_PLAY|BUTTON_REL)
+#define CALCULATOR_CALC (BUTTON_PLAY|BUTTON_REPEAT)
+#define CALCULATOR_CLEAR (BUTTON_POWER|BUTTON_REPEAT)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define CALCULATOR_LEFT BUTTON_HOME
#define CALCULATOR_RIGHT BUTTON_VOL_DOWN
diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c
index 7e2472ffc9..89dcc61714 100644
--- a/apps/plugins/calendar.c
+++ b/apps/plugins/calendar.c
@@ -411,6 +411,16 @@
#define CALENDAR_NEXT_MONTH BUTTON_VOL_UP
#define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define CALENDAR_QUIT BUTTON_POWER
+#define CALENDAR_SELECT BUTTON_PLAY
+#define CALENDAR_NEXT_WEEK BUTTON_OPTION
+#define CALENDAR_PREV_WEEK BUTTON_HOME
+#define CALENDAR_NEXT_DAY BUTTON_NEXT
+#define CALENDAR_PREV_DAY BUTTON_PREV
+#define CALENDAR_NEXT_MONTH BUTTON_VOL_UP
+#define CALENDAR_PREV_MONTH BUTTON_VOL_DOWN
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define CALENDAR_QUIT BUTTON_POWER
#define CALENDAR_SELECT BUTTON_PLAY
diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h
index ab0adbb706..567dcb1acb 100644
--- a/apps/plugins/chessbox/chessbox_pgn.h
+++ b/apps/plugins/chessbox/chessbox_pgn.h
@@ -553,6 +553,20 @@
#define CB_SCROLL_LEFT (BUTTON_PREV|BUTTON_REPEAT)
#define CB_SCROLL_RIGHT (BUTTON_NEXT|BUTTON_REPEAT)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define CB_SELECT BUTTON_PLAY
+#define CB_UP BUTTON_HOME
+#define CB_DOWN BUTTON_OPTION
+#define CB_LEFT BUTTON_PREV
+#define CB_RIGHT BUTTON_NEXT
+#define CB_PLAY BUTTON_VOL_UP
+#define CB_LEVEL BUTTON_VOL_DOWN
+#define CB_MENU BUTTON_POWER
+#define CB_SCROLL_UP (BUTTON_HOME|BUTTON_REPEAT)
+#define CB_SCROLL_DOWN (BUTTON_OPTION|BUTTON_REPEAT)
+#define CB_SCROLL_LEFT (BUTTON_PREV|BUTTON_REPEAT)
+#define CB_SCROLL_RIGHT (BUTTON_NEXT|BUTTON_REPEAT)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define CB_SELECT BUTTON_PLAY
#define CB_UP BUTTON_PREV
diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c
index 649ab164d0..aee9c9f8e7 100644
--- a/apps/plugins/chessclock.c
+++ b/apps/plugins/chessclock.c
@@ -396,6 +396,16 @@
#define CHC_SETTINGS_OK BUTTON_PLAY
#define CHC_SETTINGS_CANCEL BUTTON_POWER
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define CHC_QUIT BUTTON_POWER
+#define CHC_STARTSTOP BUTTON_PLAY
+#define CHC_RESET BUTTON_OPTION
+#define CHC_MENU BUTTON_HOME
+#define CHC_SETTINGS_INC BUTTON_NEXT
+#define CHC_SETTINGS_DEC BUTTON_PREV
+#define CHC_SETTINGS_OK BUTTON_PLAY
+#define CHC_SETTINGS_CANCEL BUTTON_POWER
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define CHC_QUIT BUTTON_POWER
#define CHC_STARTSTOP BUTTON_PLAY
diff --git a/apps/plugins/chip8.c b/apps/plugins/chip8.c
index cb7b85786f..bbea442d8e 100644
--- a/apps/plugins/chip8.c
+++ b/apps/plugins/chip8.c
@@ -1275,6 +1275,14 @@ CONFIG_KEYPAD == MROBE500_PAD
#define CHIP8_KEY6 BUTTON_NEXT
#define CHIP8_KEY8 BUTTON_OPTION
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define CHIP8_OFF BUTTON_POWER
+#define CHIP8_KEY2 BUTTON_HOME
+#define CHIP8_KEY4 BUTTON_PREV
+#define CHIP8_KEY5 BUTTON_PLAY
+#define CHIP8_KEY6 BUTTON_NEXT
+#define CHIP8_KEY8 BUTTON_OPTION
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define CHIP8_OFF BUTTON_POWER
#define CHIP8_KEY2 BUTTON_NEXT
diff --git a/apps/plugins/chopper.c b/apps/plugins/chopper.c
index 37fed5dd01..6e9f923460 100644
--- a/apps/plugins/chopper.c
+++ b/apps/plugins/chopper.c
@@ -213,6 +213,11 @@ CONFIG_KEYPAD == MROBE500_PAD
#define ACTION BUTTON_PLAY
#define ACTIONTEXT "PLAY"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define QUIT BUTTON_POWER
+#define ACTION BUTTON_PLAY
+#define ACTIONTEXT "PLAY"
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define QUIT BUTTON_POWER
#define ACTION BUTTON_PLAY
diff --git a/apps/plugins/clix.c b/apps/plugins/clix.c
index 748090358c..d6b28b54b9 100644
--- a/apps/plugins/clix.c
+++ b/apps/plugins/clix.c
@@ -300,6 +300,14 @@
#define CLIX_BUTTON_RIGHT BUTTON_NEXT
#define CLIX_BUTTON_CLICK BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define CLIX_BUTTON_QUIT BUTTON_POWER
+#define CLIX_BUTTON_UP BUTTON_HOME
+#define CLIX_BUTTON_DOWN BUTTON_OPTION
+#define CLIX_BUTTON_LEFT BUTTON_PREV
+#define CLIX_BUTTON_RIGHT BUTTON_NEXT
+#define CLIX_BUTTON_CLICK BUTTON_PLAY
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define CLIX_BUTTON_QUIT BUTTON_POWER
#define CLIX_BUTTON_UP BUTTON_PREV
diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c
index d2d831f81b..87ab5c1102 100644
--- a/apps/plugins/cube.c
+++ b/apps/plugins/cube.c
@@ -400,6 +400,16 @@
#define CUBE_PAUSE BUTTON_HOME
#define CUBE_HIGHSPEED BUTTON_PLAY
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define CUBE_QUIT BUTTON_POWER
+#define CUBE_NEXT BUTTON_NEXT
+#define CUBE_PREV BUTTON_PREV
+#define CUBE_INC BUTTON_VOL_UP
+#define CUBE_DEC BUTTON_VOL_DOWN
+#define CUBE_MODE BUTTON_OPTION
+#define CUBE_PAUSE BUTTON_HOME
+#define CUBE_HIGHSPEED BUTTON_PLAY
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define CUBE_QUIT BUTTON_POWER
#define CUBE_NEXT BUTTON_NEXT
diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c
index fb328639bf..cd3cd90edd 100644
--- a/apps/plugins/doom/i_video.c
+++ b/apps/plugins/doom/i_video.c
@@ -588,6 +588,17 @@ void I_ShutdownGraphics(void)
#define DOOMBUTTON_ENTER BUTTON_PLAY
#define DOOMBUTTON_WEAPON BUTTON_VOL_UP
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define DOOMBUTTON_UP BUTTON_UP
+#define DOOMBUTTON_DOWN BUTTON_DOWN
+#define DOOMBUTTON_LEFT BUTTON_PREV
+#define DOOMBUTTON_RIGHT BUTTON_NEXT
+#define DOOMBUTTON_SHOOT BUTTON_PLAY
+#define DOOMBUTTON_OPEN BUTTON_OPTION
+#define DOOMBUTTON_ESC BUTTON_HOME
+#define DOOMBUTTON_ENTER BUTTON_PLAY
+#define DOOMBUTTON_WEAPON BUTTON_VOL_UP
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define DOOMBUTTON_UP BUTTON_PREV
#define DOOMBUTTON_DOWN BUTTON_NEXT
diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c
index 2ed0263d75..eeb6611488 100644
--- a/apps/plugins/fft/fft.c
+++ b/apps/plugins/fft/fft.c
@@ -352,6 +352,15 @@ GREY_INFO_STRUCT
# define FFT_AMP_SCALE BUTTON_PLAY
# define FFT_QUIT BUTTON_POWER
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+# define FFT_PREV_GRAPH BUTTON_PREV
+# define FFT_NEXT_GRAPH BUTTON_NEXT
+# define FFT_ORIENTATION BUTTON_HOME
+# define FFT_FREQ_SCALE BUTTON_OPTION
+# define FFT_WINDOW (BUTTON_HOME|BUTTON_POWER)
+# define FFT_AMP_SCALE BUTTON_PLAY
+# define FFT_QUIT BUTTON_POWER
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
# define FFT_PREV_GRAPH BUTTON_PREV
# define FFT_NEXT_GRAPH BUTTON_NEXT
diff --git a/apps/plugins/flipit.c b/apps/plugins/flipit.c
index 91d83e9291..4fe0681417 100644
--- a/apps/plugins/flipit.c
+++ b/apps/plugins/flipit.c
@@ -472,6 +472,18 @@
#define FLIPIT_STEP_BY_STEP (BUTTON_HOME | BUTTON_PLAY)
#define FLIPIT_TOGGLE BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+
+#define FLIPIT_LEFT BUTTON_PREV
+#define FLIPIT_RIGHT BUTTON_NEXT
+#define FLIPIT_UP BUTTON_HOME
+#define FLIPIT_DOWN BUTTON_OPTION
+#define FLIPIT_QUIT BUTTON_POWER
+#define FLIPIT_SHUFFLE (BUTTON_HOME | BUTTON_PREV)
+#define FLIPIT_SOLVE (BUTTON_HOME | BUTTON_NEXT)
+#define FLIPIT_STEP_BY_STEP (BUTTON_HOME | BUTTON_PLAY)
+#define FLIPIT_TOGGLE BUTTON_PLAY
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define FLIPIT_LEFT BUTTON_HOME
diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h
index 92a0b87c48..45de45c5cd 100644
--- a/apps/plugins/fractals/fractal.h
+++ b/apps/plugins/fractals/fractal.h
@@ -482,6 +482,18 @@
#define FRACTAL_PRECISION_DEC (BUTTON_PLAY | BUTTON_PREV)
#define FRACTAL_RESET (BUTTON_HOME | BUTTON_POWER)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define FRACTAL_QUIT BUTTON_POWER
+#define FRACTAL_UP BUTTON_HOME
+#define FRACTAL_DOWN BUTTON_OPTION
+#define FRACTAL_LEFT BUTTON_PREV
+#define FRACTAL_RIGHT BUTTON_NEXT
+#define FRACTAL_ZOOM_IN BUTTON_VOL_UP
+#define FRACTAL_ZOOM_OUT BUTTON_VOL_DOWN
+#define FRACTAL_PRECISION_INC (BUTTON_PLAY | BUTTON_NEXT)
+#define FRACTAL_PRECISION_DEC (BUTTON_PLAY | BUTTON_PREV)
+#define FRACTAL_RESET (BUTTON_HOME | BUTTON_POWER)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define FRACTAL_QUIT BUTTON_POWER
#define FRACTAL_UP BUTTON_PREV
diff --git a/apps/plugins/goban/goban.h b/apps/plugins/goban/goban.h
index ac02d74f50..c6a10e3944 100644
--- a/apps/plugins/goban/goban.h
+++ b/apps/plugins/goban/goban.h
@@ -467,6 +467,18 @@
#define GBN_BUTTON_CONTEXT BUTTON_PLAY | BUTTON_REPEAT
#define GBN_BUTTON_NEXT_VAR BUTTON_HOME | BUTTON_POWER
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define GBN_BUTTON_UP BUTTON_HOME
+#define GBN_BUTTON_DOWN BUTTON_OPTION
+#define GBN_BUTTON_LEFT BUTTON_PREV
+#define GBN_BUTTON_RIGHT BUTTON_NEXT
+#define GBN_BUTTON_RETREAT BUTTON_VOL_DOWN
+#define GBN_BUTTON_ADVANCE BUTTON_VOL_UP
+#define GBN_BUTTON_MENU BUTTON_POWER
+#define GBN_BUTTON_PLAY BUTTON_PLAY | BUTTON_REL
+#define GBN_BUTTON_CONTEXT BUTTON_PLAY | BUTTON_REPEAT
+#define GBN_BUTTON_NEXT_VAR BUTTON_HOME | BUTTON_POWER
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define GBN_BUTTON_UP BUTTON_PREV
diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h
index 7aa96023c6..e637a09ca9 100644
--- a/apps/plugins/imageviewer/imageviewer_button.h
+++ b/apps/plugins/imageviewer/imageviewer_button.h
@@ -506,6 +506,21 @@
#define IMGVIEW_MENU BUTTON_POWER
#define IMGVIEW_SLIDE_SHOW (BUTTON_HOME|BUTTON_POWER)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define IMGVIEW_ZOOM_PRE BUTTON_PLAY
+#define IMGVIEW_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
+#define IMGVIEW_ZOOM_OUT (BUTTON_PLAY | BUTTON_REPEAT)
+#define IMGVIEW_UP BUTTON_HOME
+#define IMGVIEW_DOWN BUTTON_OPTION
+#define IMGVIEW_LEFT BUTTON_PREV
+#define IMGVIEW_RIGHT BUTTON_NEXT
+#define IMGVIEW_NEXT BUTTON_VOL_UP
+#define IMGVIEW_NEXT_REPEAT (BUTTON_VOL_UP|BUTTON_REPEAT)
+#define IMGVIEW_PREVIOUS BUTTON_VOL_DOWN
+#define IMGVIEW_PREVIOUS_REPEAT (BUTTON_VOL_DOWN|BUTTON_REPEAT)
+#define IMGVIEW_MENU BUTTON_POWER
+#define IMGVIEW_SLIDE_SHOW (BUTTON_HOME|BUTTON_POWER)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define IMGVIEW_ZOOM_PRE BUTTON_PLAY
#define IMGVIEW_ZOOM_IN (BUTTON_PLAY | BUTTON_REL)
diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c
index e275129d27..5e3cb12163 100644
--- a/apps/plugins/invadrox.c
+++ b/apps/plugins/invadrox.c
@@ -282,6 +282,13 @@ CONFIG_KEYPAD == MROBE500_PAD
#define RIGHT BUTTON_VOL_DOWN
#define FIRE BUTTON_VOL_UP
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+
+#define QUIT BUTTON_POWER
+#define LEFT BUTTON_HOME
+#define RIGHT BUTTON_VOL_DOWN
+#define FIRE BUTTON_VOL_UP
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define QUIT BUTTON_POWER
diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c
index f94825650f..64a15ff4fc 100644
--- a/apps/plugins/jewels.c
+++ b/apps/plugins/jewels.c
@@ -377,6 +377,16 @@ CONFIG_KEYPAD == MROBE500_PAD
#define HK_SELECT "PLAY"
#define HK_CANCEL "POWER"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define JEWELS_UP BUTTON_HOME
+#define JEWELS_DOWN BUTTON_OPTION
+#define JEWELS_LEFT BUTTON_PREV
+#define JEWELS_RIGHT BUTTON_NEXT
+#define JEWELS_SELECT BUTTON_PLAY
+#define JEWELS_CANCEL BUTTON_POWER
+#define HK_SELECT "PLAY"
+#define HK_CANCEL "POWER"
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define JEWELS_UP BUTTON_PREV
#define JEWELS_DOWN BUTTON_NEXT
diff --git a/apps/plugins/lib/keymaps.h b/apps/plugins/lib/keymaps.h
index e3de03f222..2865f9cdd7 100644
--- a/apps/plugins/lib/keymaps.h
+++ b/apps/plugins/lib/keymaps.h
@@ -239,6 +239,14 @@
#define BTN_FIRE BUTTON_PLAY
#define BTN_PAUSE BUTTON_POWER
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define BTN_UP BUTTON_VOL_UP
+#define BTN_DOWN BUTTON_VOL_DOWN
+#define BTN_LEFT BUTTON_PREV
+#define BTN_RIGHT BUTTON_NEXT
+#define BTN_FIRE BUTTON_PLAY
+#define BTN_PAUSE BUTTON_POWER
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define BTN_UP BUTTON_PREV
#define BTN_DOWN BUTTON_NEXT
diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c
index c580074d5e..480dc446cb 100644
--- a/apps/plugins/lib/pluginlib_actions.c
+++ b/apps/plugins/lib/pluginlib_actions.c
@@ -233,6 +233,15 @@ const struct button_mapping pla_main_ctx[] =
{ PLA_DOWN_REPEAT, BUTTON_OPTION|BUTTON_REPEAT, BUTTON_NONE },
{ PLA_LEFT_REPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
{ PLA_RIGHT_REPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+ { PLA_UP, BUTTON_HOME, BUTTON_NONE },
+ { PLA_DOWN, BUTTON_OPTION, BUTTON_NONE },
+ { PLA_LEFT, BUTTON_PREV, BUTTON_NONE },
+ { PLA_RIGHT, BUTTON_NEXT, BUTTON_NONE },
+ { PLA_UP_REPEAT, BUTTON_HOME|BUTTON_REPEAT, BUTTON_NONE },
+ { PLA_DOWN_REPEAT, BUTTON_OPTION|BUTTON_REPEAT, BUTTON_NONE },
+ { PLA_LEFT_REPEAT, BUTTON_PREV|BUTTON_REPEAT, BUTTON_NONE },
+ { PLA_RIGHT_REPEAT, BUTTON_NEXT|BUTTON_REPEAT, BUTTON_NONE },
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
{ PLA_UP, BUTTON_PREV, BUTTON_NONE },
{ PLA_DOWN, BUTTON_NEXT, BUTTON_NONE },
@@ -464,6 +473,12 @@ const struct button_mapping pla_main_ctx[] =
{PLA_SELECT, BUTTON_PLAY, BUTTON_NONE},
{PLA_SELECT_REL, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY},
{PLA_SELECT_REPEAT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE},
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+ {PLA_CANCEL, BUTTON_POWER|BUTTON_REL, BUTTON_POWER},
+ {PLA_EXIT, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE},
+ {PLA_SELECT, BUTTON_PLAY, BUTTON_NONE},
+ {PLA_SELECT_REL, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY},
+ {PLA_SELECT_REPEAT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE},
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
{PLA_CANCEL, BUTTON_POWER|BUTTON_REL, BUTTON_POWER},
{PLA_EXIT, BUTTON_POWER|BUTTON_REPEAT, BUTTON_NONE},
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c
index e6e2b4bf51..e34cedde21 100644
--- a/apps/plugins/midi/midiplay.c
+++ b/apps/plugins/midi/midiplay.c
@@ -317,6 +317,14 @@
#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
#define MIDI_PLAYPAUSE BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define MIDI_QUIT BUTTON_POWER
+#define MIDI_FFWD BUTTON_NEXT
+#define MIDI_REWIND BUTTON_PREV
+#define MIDI_VOL_UP BUTTON_VOL_UP
+#define MIDI_VOL_DOWN BUTTON_VOL_DOWN
+#define MIDI_PLAYPAUSE BUTTON_PLAY
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define MIDI_QUIT BUTTON_POWER
#define MIDI_FFWD BUTTON_VOL_DOWN
diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c
index 01659dbfd2..5872973a45 100644
--- a/apps/plugins/minesweeper.c
+++ b/apps/plugins/minesweeper.c
@@ -408,6 +408,19 @@ CONFIG_KEYPAD == MROBE500_PAD
# define MINESWP_DISCOVER2 BUTTON_VOL_UP
# define MINESWP_INFO (BUTTON_PLAY | BUTTON_OPTION)
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+# define MINESWP_LEFT BUTTON_PREV
+# define MINESWP_RIGHT BUTTON_NEXT
+# define MINESWP_UP BUTTON_HOME
+# define MINESWP_DOWN BUTTON_OPTION
+# define MINESWP_QUIT BUTTON_POWER
+# define MINESWP_TOGGLE_PRE BUTTON_PLAY
+# define MINESWP_TOGGLE (BUTTON_PLAY | BUTTON_REL)
+# define MINESWP_TOGGLE2 BUTTON_VOL_DOWN
+# define MINESWP_DISCOVER (BUTTON_PLAY | BUTTON_REPEAT)
+# define MINESWP_DISCOVER2 BUTTON_VOL_UP
+# define MINESWP_INFO (BUTTON_PLAY | BUTTON_OPTION)
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
# define MINESWP_LEFT BUTTON_HOME
# define MINESWP_RIGHT BUTTON_VOL_DOWN
diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c
index 3b912ba606..0368edbc88 100644
--- a/apps/plugins/mp3_encoder.c
+++ b/apps/plugins/mp3_encoder.c
@@ -2574,6 +2574,11 @@ CONFIG_KEYPAD == MROBE500_PAD
#define MP3ENC_DONE BUTTON_POWER
#define MP3ENC_SELECT BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define MP3ENC_PREV BUTTON_HOME
+#define MP3ENC_NEXT BUTTON_OPTION
+#define MP3ENC_DONE BUTTON_POWER
+#define MP3ENC_SELECT BUTTON_PLAY
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define MP3ENC_PREV BUTTON_PREV
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index 25eb313591..43143bdaee 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -336,6 +336,16 @@ struct mpeg_settings settings;
#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN
#define MPEG_START_TIME_EXIT BUTTON_POWER
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define MPEG_START_TIME_SELECT BUTTON_PLAY
+#define MPEG_START_TIME_LEFT BUTTON_PREV
+#define MPEG_START_TIME_RIGHT BUTTON_NEXT
+#define MPEG_START_TIME_UP BUTTON_HOME
+#define MPEG_START_TIME_DOWN BUTTON_OPTION
+#define MPEG_START_TIME_LEFT2 BUTTON_VOL_UP
+#define MPEG_START_TIME_RIGHT2 BUTTON_VOL_DOWN
+#define MPEG_START_TIME_EXIT BUTTON_POWER
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define MPEG_START_TIME_SELECT BUTTON_PLAY
#define MPEG_START_TIME_LEFT BUTTON_HOME
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index 5c06fe257d..8028913c94 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -468,6 +468,15 @@ CONFIG_KEYPAD == SANSA_M200_PAD
#define MPEG_RW BUTTON_PREV
#define MPEG_FF BUTTON_NEXT
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define MPEG_MENU BUTTON_PLAY
+#define MPEG_STOP BUTTON_POWER
+#define MPEG_PAUSE BUTTON_HOME
+#define MPEG_VOLDOWN BUTTON_VOL_DOWN
+#define MPEG_VOLUP BUTTON_VOL_UP
+#define MPEG_RW BUTTON_PREV
+#define MPEG_FF BUTTON_NEXT
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define MPEG_MENU BUTTON_PLAY
#define MPEG_STOP BUTTON_POWER
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index 4fd1883f82..2cf9b96409 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -512,6 +512,19 @@
#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
#define NEED_LASTBUTTON
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define OSCILLOSCOPE_QUIT BUTTON_POWER
+#define OSCILLOSCOPE_DRAWMODE_PRE BUTTON_PLAY
+#define OSCILLOSCOPE_DRAWMODE (BUTTON_PLAY | BUTTON_REL)
+#define OSCILLOSCOPE_ORIENTATION_PRE BUTTON_PLAY
+#define OSCILLOSCOPE_ORIENTATION (BUTTON_PLAY | BUTTON_REPEAT)
+#define OSCILLOSCOPE_ADVMODE BUTTON_HOME
+#define OSCILLOSCOPE_PAUSE BUTTON_OPTION
+#define OSCILLOSCOPE_SPEED_UP BUTTON_NEXT
+#define OSCILLOSCOPE_SPEED_DOWN BUTTON_PREV
+#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
+#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
+#define NEED_LASTBUTTON
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define OSCILLOSCOPE_QUIT BUTTON_POWER
diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h
index 78a171467a..a687806d96 100644
--- a/apps/plugins/pacbox/pacbox.h
+++ b/apps/plugins/pacbox/pacbox.h
@@ -382,6 +382,14 @@
#define PACMAN_1UP BUTTON_VOL_UP
#define PACMAN_COIN BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define PACMAN_UP BUTTON_PREV
+#define PACMAN_DOWN BUTTON_NEXT
+#define PACMAN_LEFT BUTTON_HOME
+#define PACMAN_RIGHT BUTTON_VOL_DOWN
+#define PACMAN_MENU BUTTON_POWER
+#define PACMAN_1UP BUTTON_VOL_UP
+#define PACMAN_COIN BUTTON_PLAY
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define PACMAN_UP BUTTON_PREV
diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c
index 0a299c995f..5f947fe5f2 100644
--- a/apps/plugins/pegbox.c
+++ b/apps/plugins/pegbox.c
@@ -660,6 +660,23 @@ CONFIG_KEYPAD == MROBE500_PAD
#define LVL_UP_TEXT "VOL+"
#define LVL_DOWN_TEXT "VOL-"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define PEGBOX_SELECT BUTTON_PLAY
+#define PEGBOX_QUIT BUTTON_POWER
+#define PEGBOX_RESTART (BUTTON_POWER | BUTTON_HOME)
+#define PEGBOX_LVL_UP BUTTON_VOL_UP
+#define PEGBOX_LVL_DOWN BUTTON_VOL_DOWN
+#define PEGBOX_UP BUTTON_HOME
+#define PEGBOX_DOWN BUTTON_OPTION
+#define PEGBOX_RIGHT BUTTON_NEXT
+#define PEGBOX_LEFT BUTTON_PREV
+
+#define SELECT_TEXT "PLAY"
+#define QUIT_TEXT "POWER"
+#define RESTART_TEXT "HOME"
+#define LVL_UP_TEXT "VOL+"
+#define LVL_DOWN_TEXT "VOL-"
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define PEGBOX_SELECT BUTTON_PLAY
#define PEGBOX_QUIT BUTTON_POWER
diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c
index a000a88fe7..41525f3ffe 100644
--- a/apps/plugins/pong.c
+++ b/apps/plugins/pong.c
@@ -309,6 +309,14 @@ CONFIG_KEYPAD == MROBE500_PAD
#define PONG_RIGHT_UP BUTTON_HOME
#define PONG_RIGHT_DOWN BUTTON_NEXT
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define PONG_QUIT BUTTON_POWER
+#define PONG_PAUSE BUTTON_PLAY
+#define PONG_LEFT_UP BUTTON_PREV
+#define PONG_LEFT_DOWN BUTTON_OPTION
+#define PONG_RIGHT_UP BUTTON_HOME
+#define PONG_RIGHT_DOWN BUTTON_NEXT
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define PONG_QUIT BUTTON_POWER
#define PONG_PAUSE BUTTON_PREV
diff --git a/apps/plugins/reversi/reversi-gui.h b/apps/plugins/reversi/reversi-gui.h
index ceeabeebc8..1547e52573 100644
--- a/apps/plugins/reversi/reversi-gui.h
+++ b/apps/plugins/reversi/reversi-gui.h
@@ -341,6 +341,17 @@
#define REVERSI_BUTTON_MENU BUTTON_PLAY
#define REVERSI_BUTTON_MENU_LONGPRESS
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define REVERSI_BUTTON_QUIT BUTTON_POWER
+#define REVERSI_BUTTON_UP BUTTON_HOME
+#define REVERSI_BUTTON_DOWN BUTTON_OPTION
+#define REVERSI_BUTTON_LEFT BUTTON_PREV
+#define REVERSI_BUTTON_RIGHT BUTTON_NEXT
+#define REVERSI_BUTTON_MAKE_MOVE BUTTON_PLAY
+#define REVERSI_BUTTON_MAKE_MOVE_SHORTPRESS
+#define REVERSI_BUTTON_MENU BUTTON_PLAY
+#define REVERSI_BUTTON_MENU_LONGPRESS
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define REVERSI_BUTTON_QUIT BUTTON_POWER
#define REVERSI_BUTTON_UP BUTTON_PREV
diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c
index f1f260a55d..ec6d892a0b 100644
--- a/apps/plugins/rockblox.c
+++ b/apps/plugins/rockblox.c
@@ -467,6 +467,18 @@
#define ROCKBLOX_DROP (BUTTON_PLAY|BUTTON_REL)
#define ROCKBLOX_RESTART (BUTTON_PLAY|BUTTON_REPEAT)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+
+#define ROCKBLOX_OFF BUTTON_POWER
+#define ROCKBLOX_ROTATE_CCW BUTTON_HOME
+#define ROCKBLOX_ROTATE_CCW2 BUTTON_VOL_DOWN
+#define ROCKBLOX_ROTATE_CW BUTTON_VOL_UP
+#define ROCKBLOX_DOWN BUTTON_OPTION
+#define ROCKBLOX_LEFT BUTTON_PREV
+#define ROCKBLOX_RIGHT BUTTON_NEXT
+#define ROCKBLOX_DROP (BUTTON_PLAY|BUTTON_REL)
+#define ROCKBLOX_RESTART (BUTTON_PLAY|BUTTON_REPEAT)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define ROCKBLOX_OFF BUTTON_POWER
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
index 29269f18fb..c96946cf7d 100644
--- a/apps/plugins/rockboy/rockboy.c
+++ b/apps/plugins/rockboy/rockboy.c
@@ -445,6 +445,16 @@ static void setoptions (void)
options.SELECT = BUTTON_VOL_UP;
options.MENU = BUTTON_POWER;
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+ options.UP = BUTTON_PREV;
+ options.DOWN = BUTTON_NEXT;
+
+ options.A = BUTTON_HOME;
+ options.B = BUTTON_OPTION;
+ options.START = BUTTON_VOL_DOWN;
+ options.SELECT = BUTTON_VOL_UP;
+ options.MENU = BUTTON_POWER;
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
options.UP = BUTTON_PREV;
options.DOWN = BUTTON_NEXT;
diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c
index 8e4df10280..f28fbdf622 100644
--- a/apps/plugins/rockpaint.c
+++ b/apps/plugins/rockpaint.c
@@ -338,6 +338,39 @@
#define ROCKPAINT_LEFT BUTTON_PREV
#define ROCKPAINT_RIGHT BUTTON_NEXT
+#elif CONFIG_KEYPAD == XDUOO_X3II_PAD
+#define ROCKPAINT_QUIT BUTTON_POWER
+#define ROCKPAINT_DRAW BUTTON_PLAY
+#define ROCKPAINT_MENU (BUTTON_HOME | BUTTON_POWER)
+#define ROCKPAINT_TOOLBAR BUTTON_VOL_UP
+#define ROCKPAINT_TOOLBAR2 BUTTON_VOL_DOWN
+#define ROCKPAINT_UP BUTTON_HOME
+#define ROCKPAINT_DOWN BUTTON_OPTION
+#define ROCKPAINT_LEFT BUTTON_PREV
+#define ROCKPAINT_RIGHT BUTTON_NEXT
+
+#elif CONFIG_KEYPAD == XDUOO_X20_PAD
+#define ROCKPAINT_QUIT BUTTON_POWER
+#define ROCKPAINT_DRAW BUTTON_PLAY
+#define ROCKPAINT_MENU (BUTTON_HOME | BUTTON_POWER)
+#define ROCKPAINT_TOOLBAR BUTTON_VOL_UP
+#define ROCKPAINT_TOOLBAR2 BUTTON_VOL_DOWN
+#define ROCKPAINT_UP BUTTON_HOME
+#define ROCKPAINT_DOWN BUTTON_OPTION
+#define ROCKPAINT_LEFT BUTTON_PREV
+#define ROCKPAINT_RIGHT BUTTON_NEXT
+
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define ROCKPAINT_QUIT BUTTON_POWER
+#define ROCKPAINT_DRAW BUTTON_PLAY
+#define ROCKPAINT_MENU (BUTTON_HOME | BUTTON_POWER)
+#define ROCKPAINT_TOOLBAR BUTTON_VOL_UP
+#define ROCKPAINT_TOOLBAR2 BUTTON_VOL_DOWN
+#define ROCKPAINT_UP BUTTON_HOME
+#define ROCKPAINT_DOWN BUTTON_OPTION
+#define ROCKPAINT_LEFT BUTTON_PREV
+#define ROCKPAINT_RIGHT BUTTON_NEXT
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define ROCKPAINT_QUIT BUTTON_POWER
#define ROCKPAINT_DRAW BUTTON_PLAY
diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c
index e8d349defd..7683016066 100644
--- a/apps/plugins/sliding_puzzle.c
+++ b/apps/plugins/sliding_puzzle.c
@@ -330,6 +330,14 @@ CONFIG_KEYPAD == MROBE500_PAD
#define PUZZLE_SHUFFLE (BUTTON_HOME | BUTTON_POWER)
#define PUZZLE_PICTURE BUTTON_PLAY
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define PUZZLE_QUIT BUTTON_POWER
+#define PUZZLE_LEFT BUTTON_PREV
+#define PUZZLE_RIGHT BUTTON_NEXT
+#define PUZZLE_UP BUTTON_HOME
+#define PUZZLE_DOWN BUTTON_OPTION
+#define PUZZLE_SHUFFLE (BUTTON_HOME | BUTTON_POWER)
+#define PUZZLE_PICTURE BUTTON_PLAY
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define PUZZLE_QUIT BUTTON_POWER
diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c
index 4471cd12a6..ebfb39c9a7 100644
--- a/apps/plugins/snake.c
+++ b/apps/plugins/snake.c
@@ -289,6 +289,14 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left;
#define SNAKE_DOWN BUTTON_OPTION
#define SNAKE_PLAYPAUSE BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define SNAKE_QUIT BUTTON_POWER
+#define SNAKE_LEFT BUTTON_PREV
+#define SNAKE_RIGHT BUTTON_NEXT
+#define SNAKE_UP BUTTON_HOME
+#define SNAKE_DOWN BUTTON_OPTION
+#define SNAKE_PLAYPAUSE BUTTON_PLAY
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define SNAKE_QUIT BUTTON_POWER
#define SNAKE_LEFT BUTTON_HOME
diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c
index bfff0bf870..77400dfff1 100644
--- a/apps/plugins/snake2.c
+++ b/apps/plugins/snake2.c
@@ -419,6 +419,15 @@ CONFIG_KEYPAD == MROBE500_PAD
#define SNAKE2_PLAYPAUSE BUTTON_PLAY
#define SNAKE2_PLAYPAUSE_TEXT "PLAY"
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define SNAKE2_LEFT BUTTON_PREV
+#define SNAKE2_RIGHT BUTTON_NEXT
+#define SNAKE2_UP BUTTON_HOME
+#define SNAKE2_DOWN BUTTON_OPTION
+#define SNAKE2_QUIT BUTTON_POWER
+#define SNAKE2_PLAYPAUSE BUTTON_PLAY
+#define SNAKE2_PLAYPAUSE_TEXT "PLAY"
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define SNAKE2_LEFT BUTTON_HOME
#define SNAKE2_RIGHT BUTTON_VOL_DOWN
diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c
index 08359d9fcc..da3c303ace 100644
--- a/apps/plugins/sokoban.c
+++ b/apps/plugins/sokoban.c
@@ -663,6 +663,22 @@
#define BUTTON_SAVE BUTTON_PLAY
#define BUTTON_SAVE_NAME "PLAY"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define SOKOBAN_LEFT BUTTON_PREV
+#define SOKOBAN_RIGHT BUTTON_NEXT
+#define SOKOBAN_UP BUTTON_HOME
+#define SOKOBAN_DOWN BUTTON_OPTION
+#define SOKOBAN_MENU BUTTON_POWER
+#define SOKOBAN_UNDO_PRE BUTTON_PLAY
+#define SOKOBAN_UNDO (BUTTON_PLAY | BUTTON_REL)
+#define SOKOBAN_REDO (BUTTON_POWER | BUTTON_PLAY)
+#define SOKOBAN_LEVEL_DOWN BUTTON_VOL_DOWN
+#define SOKOBAN_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_NEXT)
+#define SOKOBAN_LEVEL_UP BUTTON_VOL_UP
+#define SOKOBAN_PAUSE BUTTON_PLAY
+#define BUTTON_SAVE BUTTON_PLAY
+#define BUTTON_SAVE_NAME "PLAY"
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define SOKOBAN_LEFT BUTTON_HOME
#define SOKOBAN_RIGHT BUTTON_VOL_DOWN
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c
index a7844fba92..1996dc97e7 100644
--- a/apps/plugins/solitaire.c
+++ b/apps/plugins/solitaire.c
@@ -684,6 +684,25 @@ CONFIG_KEYPAD == MROBE500_PAD
# define HK_CUR2STACK "DBL PLAY"
# define HK_REM2STACK "NEXT"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+# define SOL_QUIT BUTTON_POWER
+# define SOL_UP BUTTON_HOME
+# define SOL_DOWN BUTTON_OPTION
+# define SOL_LEFT BUTTON_PREV
+# define SOL_RIGHT BUTTON_NEXT
+# define SOL_MOVE_PRE BUTTON_PLAY
+# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)
+# define SOL_DRAW (BUTTON_POWER | BUTTON_REPEAT)
+# define SOL_REM2CUR BUTTON_VOL_DOWN
+# define SOL_CUR2STACK_PRE BUTTON_PLAY
+# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)
+# define SOL_REM2STACK BUTTON_VOL_UP
+# define HK_MOVE "PLAY"
+# define HK_DRAW "DBL HOME"
+# define HK_REM2CUR "PREV"
+# define HK_CUR2STACK "DBL PLAY"
+# define HK_REM2STACK "NEXT"
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
# define SOL_QUIT BUTTON_POWER
# define SOL_UP BUTTON_PREV
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c
index b366da0d60..1b3bdda0d1 100644
--- a/apps/plugins/spacerocks.c
+++ b/apps/plugins/spacerocks.c
@@ -354,6 +354,15 @@
#define AST_RIGHT BUTTON_NEXT
#define AST_FIRE BUTTON_PLAY
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define AST_PAUSE BUTTON_VOL_UP
+#define AST_QUIT BUTTON_POWER
+#define AST_THRUST BUTTON_HOME
+#define AST_HYPERSPACE BUTTON_OPTION
+#define AST_LEFT BUTTON_PREV
+#define AST_RIGHT BUTTON_NEXT
+#define AST_FIRE BUTTON_PLAY
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define AST_PAUSE BUTTON_PLAY
#define AST_QUIT BUTTON_POWER
diff --git a/apps/plugins/star.c b/apps/plugins/star.c
index ea1d5b8bf8..cf8522fbac 100644
--- a/apps/plugins/star.c
+++ b/apps/plugins/star.c
@@ -620,6 +620,22 @@
#define STAR_LEVEL_DOWN_NAME "PLAY + PREV"
#define STAR_LEVEL_REPEAT_NAME "PLAY + OPTION"
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define STAR_QUIT BUTTON_POWER
+#define STAR_LEFT BUTTON_PREV
+#define STAR_RIGHT BUTTON_NEXT
+#define STAR_UP BUTTON_HOME
+#define STAR_DOWN BUTTON_OPTION
+#define STAR_TOGGLE_CONTROL BUTTON_PLAY
+#define STAR_LEVEL_UP (BUTTON_PLAY | BUTTON_NEXT)
+#define STAR_LEVEL_DOWN (BUTTON_PLAY | BUTTON_PREV)
+#define STAR_LEVEL_REPEAT (BUTTON_PLAY | BUTTON_OPTION)
+#define STAR_TOGGLE_CONTROL_NAME "PLAY"
+#define STAR_QUIT_NAME "POWER"
+#define STAR_LEVEL_UP_NAME "PLAY + NEXT"
+#define STAR_LEVEL_DOWN_NAME "PLAY + PREV"
+#define STAR_LEVEL_REPEAT_NAME "PLAY + OPTION"
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define STAR_QUIT BUTTON_POWER
#define STAR_LEFT BUTTON_HOME
diff --git a/apps/plugins/stopwatch.c b/apps/plugins/stopwatch.c
index 6fca37d06f..801c735f00 100644
--- a/apps/plugins/stopwatch.c
+++ b/apps/plugins/stopwatch.c
@@ -301,6 +301,14 @@
#define STOPWATCH_SCROLL_UP BUTTON_HOME
#define STOPWATCH_SCROLL_DOWN BUTTON_OPTION
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define STOPWATCH_QUIT BUTTON_POWER
+#define STOPWATCH_START_STOP BUTTON_NEXT
+#define STOPWATCH_RESET_TIMER BUTTON_PREV
+#define STOPWATCH_LAP_TIMER BUTTON_PLAY
+#define STOPWATCH_SCROLL_UP BUTTON_HOME
+#define STOPWATCH_SCROLL_DOWN BUTTON_OPTION
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define STOPWATCH_QUIT BUTTON_POWER
#define STOPWATCH_START_STOP BUTTON_NEXT
diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h
index 434223ef68..749087260d 100644
--- a/apps/plugins/sudoku/sudoku.h
+++ b/apps/plugins/sudoku/sudoku.h
@@ -432,6 +432,20 @@
#define SUDOKU_BUTTON_MENU (BUTTON_POWER | BUTTON_REL)
#define SUDOKU_BUTTON_POSSIBLE (BUTTON_HOME | BUTTON_POWER)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define SUDOKU_BUTTON_QUIT_PRE BUTTON_POWER
+#define SUDOKU_BUTTON_QUIT (BUTTON_POWER | BUTTON_REPEAT)
+#define SUDOKU_BUTTON_UP BUTTON_HOME
+#define SUDOKU_BUTTON_DOWN BUTTON_OPTION
+#define SUDOKU_BUTTON_LEFT BUTTON_PREV
+#define SUDOKU_BUTTON_RIGHT BUTTON_NEXT
+#define SUDOKU_BUTTON_TOGGLEBACK BUTTON_VOL_DOWN
+#define SUDOKU_BUTTON_TOGGLE BUTTON_VOL_UP
+#define SUDOKU_BUTTON_ALTTOGGLE BUTTON_PLAY
+#define SUDOKU_BUTTON_MENU_PRE BUTTON_POWER
+#define SUDOKU_BUTTON_MENU (BUTTON_POWER | BUTTON_REL)
+#define SUDOKU_BUTTON_POSSIBLE (BUTTON_HOME | BUTTON_POWER)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define SUDOKU_BUTTON_QUIT_PRE BUTTON_POWER
#define SUDOKU_BUTTON_QUIT (BUTTON_POWER | BUTTON_REPEAT)
diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h
index 6fcfc24e4f..dea87ebd52 100644
--- a/apps/plugins/text_viewer/tv_button.h
+++ b/apps/plugins/text_viewer/tv_button.h
@@ -533,6 +533,18 @@
#define TV_LINE_DOWN BUTTON_OPTION
#define TV_BOOKMARK (BUTTON_OPTION | BUTTON_PLAY)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define TV_QUIT BUTTON_POWER
+#define TV_SCROLL_UP BUTTON_VOL_UP
+#define TV_SCROLL_DOWN BUTTON_VOL_DOWN
+#define TV_SCREEN_LEFT BUTTON_PREV
+#define TV_SCREEN_RIGHT BUTTON_NEXT
+#define TV_MENU BUTTON_PLAY
+#define TV_AUTOSCROLL (BUTTON_POWER | BUTTON_HOME)
+#define TV_LINE_UP BUTTON_HOME
+#define TV_LINE_DOWN BUTTON_OPTION
+#define TV_BOOKMARK (BUTTON_OPTION | BUTTON_PLAY)
+
/* Xuelin 770/770c keys */
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define TV_QUIT BUTTON_POWER
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index d2ba8c992c..66ddf03dd8 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -419,6 +419,17 @@
#define LABEL_MENU "PLAY"
#define LABEL_VOLUME "VOL UP/DN"
+#elif (CONFIG_KEYPAD == FIIO_M3K_PAD)
+#define VUMETER_QUIT BUTTON_POWER
+#define VUMETER_HELP BUTTON_HOME
+#define VUMETER_MENU BUTTON_PLAY
+#define VUMETER_UP BUTTON_VOL_UP
+#define VUMETER_DOWN BUTTON_VOL_DOWN
+#define LABEL_HELP "HOME"
+#define LABEL_QUIT "POWER"
+#define LABEL_MENU "PLAY"
+#define LABEL_VOLUME "VOL UP/DN"
+
#elif (CONFIG_KEYPAD == IHIFI_770_PAD)
#define VUMETER_QUIT BUTTON_POWER
#define VUMETER_HELP BUTTON_HOME
diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c
index 59f3138c0a..6cf03dfaff 100644
--- a/apps/plugins/wormlet.c
+++ b/apps/plugins/wormlet.c
@@ -380,6 +380,15 @@ CONFIG_KEYPAD == MROBE500_PAD
#define BTN_QUIT BUTTON_POWER
#define BTN_STOPRESET (BUTTON_HOME | BUTTON_POWER)
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define BTN_DIR_UP BUTTON_HOME
+#define BTN_DIR_DOWN BUTTON_OPTION
+#define BTN_DIR_LEFT BUTTON_PREV
+#define BTN_DIR_RIGHT BUTTON_NEXT
+#define BTN_STARTPAUSE BUTTON_PLAY
+#define BTN_QUIT BUTTON_POWER
+#define BTN_STOPRESET (BUTTON_HOME | BUTTON_POWER)
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define BTN_DIR_UP BUTTON_PREV
#define BTN_DIR_DOWN BUTTON_NEXT
diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c
index 5ed1fbb612..94161c683d 100644
--- a/apps/plugins/xobox.c
+++ b/apps/plugins/xobox.c
@@ -342,6 +342,15 @@ CONFIG_KEYPAD == MROBE500_PAD
#define DOWN BUTTON_OPTION
#define PAUSE BUTTON_PLAY
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+
+#define QUIT BUTTON_POWER
+#define LEFT BUTTON_PREV
+#define RIGHT BUTTON_NEXT
+#define UP BUTTON_HOME
+#define DOWN BUTTON_OPTION
+#define PAUSE BUTTON_PLAY
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define QUIT BUTTON_POWER
diff --git a/apps/plugins/zxbox/keymaps.h b/apps/plugins/zxbox/keymaps.h
index 967b979883..eae20e7976 100644
--- a/apps/plugins/zxbox/keymaps.h
+++ b/apps/plugins/zxbox/keymaps.h
@@ -282,6 +282,14 @@
#define ZX_UP BUTTON_HOME
#define ZX_DOWN BUTTON_OPTION
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+#define ZX_SELECT BUTTON_PLAY
+#define ZX_MENU BUTTON_POWER
+#define ZX_LEFT BUTTON_PREV
+#define ZX_RIGHT BUTTON_NEXT
+#define ZX_UP BUTTON_HOME
+#define ZX_DOWN BUTTON_OPTION
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define ZX_SELECT BUTTON_PLAY
#define ZX_MENU BUTTON_POWER
diff --git a/apps/plugins/zxbox/zxbox_keyb.c b/apps/plugins/zxbox/zxbox_keyb.c
index 4dc50e2ae8..c16c3cd20a 100644
--- a/apps/plugins/zxbox/zxbox_keyb.c
+++ b/apps/plugins/zxbox/zxbox_keyb.c
@@ -275,6 +275,15 @@
#define KBD_UP BUTTON_HOME
#define KBD_DOWN BUTTON_OPTION
+#elif CONFIG_KEYPAD == FIIO_M3K_PAD
+
+#define KBD_SELECT BUTTON_PLAY
+#define KBD_ABORT BUTTON_POWER
+#define KBD_LEFT BUTTON_PREV
+#define KBD_RIGHT BUTTON_NEXT
+#define KBD_UP BUTTON_HOME
+#define KBD_DOWN BUTTON_OPTION
+
#elif CONFIG_KEYPAD == IHIFI_770_PAD
#define KBD_SELECT BUTTON_PLAY
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 41c20c7809..0ad638746a 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -845,7 +845,10 @@ const struct settings_list settings[] = {
#ifdef AUDIOHW_HAVE_FILTER_ROLL_OFF
CHOICE_SETTING(F_SOUNDSETTING, roll_off, LANG_FILTER_ROLL_OFF, 0,
-#ifndef AUDIOHW_HAVE_SHORT_ROLL_OFF
+#if defined(AUDIOHW_HAVE_SHORT2_ROLL_OFF)
+ "roll_off", "sharp,slow,short sharp,short slow", sound_set_filter_roll_off,
+ 4, ID2P(LANG_FILTER_SHARP), ID2P(LANG_FILTER_SLOW), ID2P(LANG_FILTER_SHORT_SHARP), ID2P(LANG_FILTER_SHORT_SLOW)),
+#elif defined(AUDIOHW_HAVE_SHORT_ROLL_OFF)
"roll_off", "sharp,slow", sound_set_filter_roll_off,
2, ID2P(LANG_FILTER_SHARP), ID2P(LANG_FILTER_SLOW)),
#else
diff --git a/bootloader/SOURCES b/bootloader/SOURCES
index b0d3e26e07..e52c6e782a 100644
--- a/bootloader/SOURCES
+++ b/bootloader/SOURCES
@@ -76,7 +76,7 @@ show_logo.c
mpio_hd200_hd300.c
#elif defined(SONY_NWZ_LINUX)
nwz_linux.c
-#elif defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)
+#elif defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K)
rocker_linux.c
#elif defined(RK27_GENERIC) || defined(HM60X) || defined(HM801) \
|| defined(MA9) || defined(MA9C) || defined(MA8) || defined(MA8C) \
diff --git a/bootloader/rocker_linux.c b/bootloader/rocker_linux.c
index e3985ce100..4abc88c413 100644
--- a/bootloader/rocker_linux.c
+++ b/bootloader/rocker_linux.c
@@ -51,23 +51,42 @@
#define ICON_WIDTH 70
#define ICON_HEIGHT 70
#define RBFILE "rockbox.rocker"
+#define ICON_NAME bm_hibyicon
+#define OF_NAME "HIBY PLAYER"
+#include "bitmaps/hibyicon.h"
#elif defined(XDUOO_X3II)
#define ICON_WIDTH 130
#define ICON_HEIGHT 130
#define RBFILE "rockbox.x3ii"
+#define ICON_NAME bm_hibyicon
+#define OF_NAME "HIBY PLAYER"
+#include "bitmaps/hibyicon.h"
#elif defined(XDUOO_X20)
#define ICON_WIDTH 130
#define ICON_HEIGHT 130
#define RBFILE "rockbox.x20"
+#define ICON_NAME bm_hibyicon
+#define OF_NAME "HIBY PLAYER"
+#include "bitmaps/hibyicon.h"
+#elif defined(FIIO_M3K)
+#define ICON_WIDTH 130
+#define ICON_HEIGHT 130
+#define RBFILE "rockbox.fiiom3k"
+#define ICON_NAME bm_fiioicon
+#define OF_NAME "FIIO PLAYER"
+#include "bitmaps/fiioicon.h"
#else
#error "must define ICON_WIDTH/HEIGHT"
#endif
+#ifdef FIIO_M3K
+#define BASE_DIR "/mnt"
+#else
#define BASE_DIR "/mnt/sd_0"
+#endif
/* images */
#include "bitmaps/rockboxicon.h"
-#include "bitmaps/hibyicon.h"
#include "bitmaps/toolsicon.h"
/* don't issue an error when parsing the file for dependencies */
@@ -79,6 +98,10 @@
BMPHEIGHT_hibyicon != ICON_HEIGHT)
#error hibyicon has the wrong resolution
#endif
+#if defined(BMPWIDTH_fiioicon) && (BMPWIDTH_fiioicon != ICON_WIDTH || \
+ BMPHEIGHT_fiioicon != ICON_HEIGHT)
+#error fiioicon has the wrong resolution
+#endif
#if defined(BMPWIDTH_toolsicon) && (BMPWIDTH_toolsicon != ICON_WIDTH || \
BMPHEIGHT_toolsicon != ICON_HEIGHT)
#error toolsicon has the wrong resolution
@@ -148,6 +171,8 @@ static int get_inactivity_tmo(void)
else
#endif
return 10 * HZ; /* Inactivity timeout when not on hold */
+
+ // XXX if booting the last selection, use a short timeout?
}
/* return action on idle timeout */
@@ -229,11 +254,11 @@ static enum boot_mode get_boot_mode(void)
}
lcd_set_foreground(LCD_RGBPACK(255, 201, 0));
/* display icon */
- const struct bitmap *icon = (mode == BOOT_OF) ? &bm_hibyicon :
+ const struct bitmap *icon = (mode == BOOT_OF) ? &ICON_NAME :
(mode == BOOT_ROCKBOX) ? &bm_rockboxicon : &bm_toolsicon;
lcd_bmp(icon, (LCD_WIDTH - ICON_WIDTH) / 2, get_icon_y());
/* display bottom description */
- const char *desc = (mode == BOOT_OF) ? "HIBY PLAYER" :
+ const char *desc = (mode == BOOT_OF) ? OF_NAME :
(mode == BOOT_ROCKBOX) ? "ROCKBOX" : "TOOLS";
int desc_height;
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 1471eb7b94..42677725fc 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -111,7 +111,7 @@ target/hosted/sonynwz/nvp-nwz.c
target/hosted/sonynwz/nwz-db.c
#endif
-#if ((defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)) && !defined(SIMULATOR))
+#if ((defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K)) && !defined(SIMULATOR))
drivers/lcd-memframe.c
target/hosted/alsa-controls.c
target/hosted/pcm-alsa.c
@@ -133,15 +133,24 @@ target/hosted/agptek/powermgmt-agptek.c
target/hosted/agptek/usb-agptek.c
#endif
-#if ((defined(XDUOO_X3II)||defined(XDUOO_X20)) && !defined(SIMULATOR))
+#if (defined(XDUOO_X3II) || defined(XDUOO_X20)) && !defined(SIMULATOR)
target/hosted/xduoo/button-xduoo.c
target/hosted/xduoo/debug-xduoo.c
-
target/hosted/xduoo/power-xduoo.c
target/hosted/xduoo/powermgmt-xduoo.c
target/hosted/xduoo/usb-xduoo.c
#endif
+#if (defined(FIIO_M3K)) && !defined(SIMULATOR)
+target/hosted/fiio/buttonlight-fiio.c
+target/hosted/fiio/button-fiio.c
+target/hosted/fiio/debug-fiio.c
+target/hosted/fiio/power-fiio.c
+target/hosted/fiio/powermgmt-fiio.c
+target/hosted/fiio/system-fiio.c
+target/hosted/fiio/usb-fiio.c
+#endif
+
#if defined(SAMSUNG_YPR0) && !defined(SIMULATOR)
drivers/adc-as3514.c
#if (CONFIG_RTC == RTC_AS3514)
@@ -498,6 +507,8 @@ target/hosted/pcm-alsa.c
drivers/audio/rocker_codec.c
#elif defined(HAVE_XDUOO_LINUX_CODEC) && !defined(SIMULATOR)
drivers/audio/xduoolinux_codec.c
+#elif defined(HAVE_FIIO_LINUX_CODEC) && !defined(SIMULATOR)
+drivers/audio/fiiolinux_codec.c
#elif defined(HAVE_SDL_AUDIO)
drivers/audio/sdl.c
diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES
index 085b6351a5..e93f77c770 100644
--- a/firmware/asm/SOURCES
+++ b/firmware/asm/SOURCES
@@ -15,7 +15,8 @@ mempcpy.c
defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \
defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \
defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \
- defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX) || defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)) && \
+ defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX) || defined(AGPTEK_ROCKER) || \
+ defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K)) && \
!defined(SIMULATOR)
#if LCD_DEPTH >= 24
lcd-as-memframe-24bit.c
diff --git a/firmware/drivers/audio/fiiolinux_codec.c b/firmware/drivers/audio/fiiolinux_codec.c
new file mode 100644
index 0000000000..d8024e3c32
--- /dev/null
+++ b/firmware/drivers/audio/fiiolinux_codec.c
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ *
+ * Copyright (c) 2018 Marcin Bukat
+ * Copyright (c) 2019 Roman Stolyarov
+ *
+ * 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 "audio.h"
+#include "audiohw.h"
+#include "system.h"
+#include "kernel.h"
+#include "panic.h"
+#include "sysfs.h"
+#include "alsa-controls.h"
+#include "pcm-alsa.h"
+#include
+
+static int fd_hw;
+static int ak_hw;
+
+static int vol_sw[2] = {0};
+static long int vol_hw[2] = {0};
+
+static void hw_open(void)
+{
+ fd_hw = open("/dev/snd/controlC0", O_RDWR);
+ if(fd_hw < 0)
+ panicf("Cannot open '/dev/snd/controlC0'");
+
+ ak_hw = open("/dev/ak4376", O_RDWR);
+ if(ak_hw < 0)
+ panicf("Cannot open '/dev/ak4376'");
+
+ if(ioctl(ak_hw, 0x20003424, 0) < 0)
+ {
+ panicf("Call cmd AK4376_POWER_ON fail");
+ }
+}
+
+static void hw_close(void)
+{
+ if(ioctl(ak_hw, 0x20003425, 0) < 0)
+ {
+ panicf("Call cmd AK4376_POWER_OFF fail");
+ }
+ close(ak_hw);
+
+ close(fd_hw);
+}
+
+void audiohw_preinit(void)
+{
+ alsa_controls_init();
+ hw_open();
+}
+
+void audiohw_postinit(void)
+{
+}
+
+void audiohw_close(void)
+{
+ hw_close();
+ alsa_controls_close();
+}
+
+void audiohw_set_frequency(int fsel)
+{
+ (void)fsel;
+}
+
+void audiohw_set_volume(int vol_l, int vol_r)
+{
+ int vol[2];
+
+ vol[0] = vol_l / 20;
+ vol[1] = vol_r / 20;
+
+ for (int i = 0; i < 2; i++)
+ {
+ if (vol[i] > -56)
+ {
+ if (vol[i] < -12)
+ {
+ vol_hw[i] = 1;
+ vol_sw[i] = vol[i] + 12;
+ }
+ else
+ {
+ vol_hw[i] = 25 - (-vol[i] * 2);
+ vol_sw[i] = 0;
+ }
+ }
+ else
+ {
+ // Mute
+ vol_hw[i] = 0;
+ vol_sw[i] = 0;
+ }
+ }
+
+ alsa_controls_set_ints("DACL Playback Volume", 1, &vol_hw[0]);
+ alsa_controls_set_ints("DACR Playback Volume", 1, &vol_hw[1]);
+ pcm_alsa_set_digital_volume(vol_sw[0], vol_sw[1]);
+}
+
+void audiohw_mute(int mute)
+{
+ long int vol0 = 0;
+
+ if(mute)
+ {
+ alsa_controls_set_ints("DACL Playback Volume", 1, &vol0);
+ alsa_controls_set_ints("DACR Playback Volume", 1, &vol0);
+ pcm_alsa_set_digital_volume(0, 0);
+ }
+ else
+ {
+ alsa_controls_set_ints("DACL Playback Volume", 1, &vol_hw[0]);
+ alsa_controls_set_ints("DACR Playback Volume", 1, &vol_hw[1]);
+ pcm_alsa_set_digital_volume(vol_sw[0], vol_sw[1]);
+ }
+}
+
+void audiohw_set_filter_roll_off(int value)
+{
+ /* 0 = Sharp;
+ 1 = Slow;
+ 2 = Short Sharp
+ 3 = Short Slow */
+#if defined(FIIO_M3K)
+ long int value_hw = value;
+ alsa_controls_set_ints("AK4376 Digital Filter", 1, &value_hw);
+#else
+ (void)value;
+#endif
+}
diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h
index 31be0555f8..1ff220e403 100644
--- a/firmware/export/audiohw.h
+++ b/firmware/export/audiohw.h
@@ -224,6 +224,8 @@ struct sound_settings_info
#include "rocker_codec.h"
#elif defined(HAVE_XDUOO_LINUX_CODEC)
#include "xduoolinux_codec.h"
+#elif defined(HAVE_FIIO_LINUX_CODEC)
+#include "fiiolinux_codec.h"
#endif
/* convert caps into defines */
diff --git a/firmware/export/config.h b/firmware/export/config.h
index 7c57d9a120..a9753e3cf8 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -161,6 +161,7 @@
#define IHIFI_800_PAD 68
#define XDUOO_X3II_PAD 69
#define XDUOO_X20_PAD 70
+#define FIIO_M3K_PAD 71
/* CONFIG_REMOTE_KEYPAD */
#define H100_REMOTE 1
@@ -599,6 +600,8 @@ Lyre prototype 1 */
#include "config/xduoox3ii.h"
#elif defined(XDUOO_X20)
#include "config/xduoox20.h"
+#elif defined(FIIO_M3K)
+#include "config/fiiom3k.h"
#else
//#error "unknown hwardware platform!"
#endif
diff --git a/firmware/export/config/fiiom3k.h b/firmware/export/config/fiiom3k.h
new file mode 100644
index 0000000000..5b68f3738e
--- /dev/null
+++ b/firmware/export/config/fiiom3k.h
@@ -0,0 +1,127 @@
+/*
+ * This config file is for the FiiO M3K
+ */
+
+/* For Rolo and boot loader */
+#define MODEL_NUMBER 112
+
+#define MODEL_NAME "FiiO M3K"
+
+/* LCD dimensions */
+#define LCD_WIDTH 240
+#define LCD_HEIGHT 320
+/* sqrt(240^2 + 320^2) / 2.0 = 200 */
+#define LCD_DPI 200
+
+#ifndef SIMULATOR
+#define CONFIG_PLATFORM (PLATFORM_HOSTED)
+#endif
+
+#define HW_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_48 | SAMPR_CAP_88 | SAMPR_CAP_96 | SAMPR_CAP_176 | SAMPR_CAP_192)
+
+/* define this if you have a bitmap LCD display */
+#define HAVE_LCD_BITMAP
+
+/* define this if you have a colour LCD */
+#define HAVE_LCD_COLOR
+
+#define HAVE_LCD_ENABLE
+
+/* define this if you want album art for this target */
+#define HAVE_ALBUMART
+
+/* define this to enable bitmap scaling */
+#define HAVE_BMP_SCALING
+
+/* define this to enable JPEG decoding */
+#define HAVE_JPEG
+
+/* define this if you have access to the quickscreen */
+#define HAVE_QUICKSCREEN
+
+/* define this if you would like tagcache to build on this target */
+#define HAVE_TAGCACHE
+
+#define LCD_DEPTH 16
+/* Check that but should not matter */
+#define LCD_PIXELFORMAT RGB565
+
+#define HAVE_BACKLIGHT
+#define HAVE_BACKLIGHT_BRIGHTNESS
+
+/* define this if you have a light associated with the buttons */
+#define HAVE_BUTTON_LIGHT
+#define HAVE_BUTTONLIGHT_BRIGHTNESS
+
+/* Main LCD backlight brightness range and defaults: the backlight driver
+ * has levels from 0 to 32. But 0 is off so start at 1.
+ */
+#define MIN_BRIGHTNESS_SETTING 1
+#define MAX_BRIGHTNESS_SETTING 255
+#define BRIGHTNESS_STEP 5
+#define DEFAULT_BRIGHTNESS_SETTING 70
+
+/* Which backlight fading type? */
+#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
+
+/* define this if you have a real-time clock */
+#define CONFIG_RTC APPLICATION
+
+/* The number of bytes reserved for loadable codecs */
+#define CODEC_SIZE 0x80000
+
+/* The number of bytes reserved for loadable plugins */
+#define PLUGIN_BUFFER_SIZE 0x100000
+
+#define HAVE_HEADPHONE_DETECTION
+
+/* KeyPad configuration for plugins */
+#define CONFIG_KEYPAD FIIO_M3K_PAD
+
+/* Define this if a programmable hotkey is mapped */
+#define HAVE_HOTKEY
+
+/* define this if the target has volume keys which can be used in the lists */
+#define HAVE_VOLUME_IN_LIST
+
+#ifndef SIMULATOR
+/* We have usb power and can detect usb but it is handled by Linux */
+#define HAVE_USB_POWER
+
+#endif
+
+#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE
+
+/* Linux controlls charging, we can monitor */
+#define CONFIG_CHARGING CHARGING_MONITOR
+
+/* define this if the hardware can be powered off while charging */
+#define HAVE_POWEROFF_WHILE_CHARGING
+
+/* same dimensions as gigabeats */
+#define CONFIG_LCD LCD_INGENIC_LINUX
+
+/* Define this if you have a software controlled poweroff */
+#define HAVE_SW_POWEROFF
+
+/* Define this to the CPU frequency */
+#define CPU_FREQ 1008000000
+
+/* No special storage */
+#define CONFIG_STORAGE STORAGE_HOSTFS
+#define HAVE_STORAGE_FLUSH
+
+/* Battery */
+#define BATTERY_TYPES_COUNT 1
+
+/* Audio codec */
+#define HAVE_FIIO_LINUX_CODEC
+
+/* We don't have hardware controls */
+#define HAVE_SW_TONE_CONTROLS
+
+/* Battery */
+#define BATTERY_CAPACITY_DEFAULT 1100 /* default battery capacity */
+#define BATTERY_CAPACITY_MIN 1100 /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX 1100 /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC 0 /* capacity increment */
diff --git a/firmware/export/fiiolinux_codec.h b/firmware/export/fiiolinux_codec.h
index 22c2263046..118a0928d7 100644
--- a/firmware/export/fiiolinux_codec.h
+++ b/firmware/export/fiiolinux_codec.h
@@ -2,8 +2,11 @@
#define __FIIOLINUX_CODEC__
#define AUDIOHW_CAPS (FILTER_ROLL_OFF_CAP)
+#define AUDIOHW_HAVE_SHORT2_ROLL_OFF
AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -100, 0, -30)
AUDIOHW_SETTING(FILTER_ROLL_OFF, "", 0, 1, 0, 4, 0)
#endif
+#define AUDIOHW_MUTE_ON_PAUSE
+
void audiohw_mute(int mute);
diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h
index 87a6dd91ff..6b686eec0e 100644
--- a/firmware/export/rbpaths.h
+++ b/firmware/export/rbpaths.h
@@ -42,7 +42,7 @@
#if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \
defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || \
- defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)
+ defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K)
#if defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1)
#define HOME_DIR "/mnt/media0"
@@ -53,6 +53,8 @@
#define HOME_DIR "/mnt/sdcard"
#elif defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)
#define HOME_DIR "/mnt/sd_0"
+#elif defined(FIIO_M3K)
+#define HOME_DIR "/mnt"
#else
#define HOME_DIR "/"
#endif
diff --git a/firmware/target/hosted/backlight-target.h b/firmware/target/hosted/backlight-target.h
index e3b8a7bd78..261af09d72 100644
--- a/firmware/target/hosted/backlight-target.h
+++ b/firmware/target/hosted/backlight-target.h
@@ -21,16 +21,20 @@
#ifndef _BACKLIGHT_TARGET_H_
#define _BACKLIGHT_TARGET_H_
-
#include
-
/* See backlight.c */
bool backlight_hw_init(void);
void backlight_hw_on(void);
void backlight_hw_off(void);
void backlight_hw_brightness(int brightness);
-
+#ifdef HAVE_BUTTON_LIGHT
+void buttonlight_hw_on(void);
+void buttonlight_hw_off(void);
+#ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
+void buttonlight_hw_brightness(int brightness);
+#endif
#endif
+#endif
diff --git a/firmware/target/hosted/fiio/adc-target.h b/firmware/target/hosted/fiio/adc-target.h
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/firmware/target/hosted/fiio/button-fiio.c b/firmware/target/hosted/fiio/button-fiio.c
new file mode 100644
index 0000000000..fcc7480e11
--- /dev/null
+++ b/firmware/target/hosted/fiio/button-fiio.c
@@ -0,0 +1,308 @@
+/***************************************************************************
+ * __________ __ ___
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 Marcin Bukat
+ * Copyright (C) 2019 Roman Stolyarov
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include
+//#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "sysfs.h"
+#include "button.h"
+#include "button-target.h"
+#include "panic.h"
+
+#include "kernel.h"
+#include "backlight.h"
+#include "backlight-target.h"
+
+static int key_enter_delay = 0;
+static int key_right_delay = 0;
+static int key_left_delay = 0;
+static int key_power_delay = 0;
+static int key_home_delay = 0;
+static int key_backspace_delay = 0;
+static int key_leftbrace_delay = 0;
+static int key_rightbrace_delay = 0;
+static int key_up_delay = 0;
+static int key_down_delay = 0;
+static int key_f12_delay = 0;
+
+#define NR_POLL_DESC 2
+static struct pollfd poll_fds[NR_POLL_DESC];
+
+#define DEF_DELAY 5
+
+static int button_map_on(int keycode)
+{
+ switch(keycode)
+ {
+ case KEY_ENTER:
+ key_enter_delay = DEF_DELAY;
+ return BUTTON_PLAY;
+ case KEY_F10:
+ key_enter_delay = 0;
+ return BUTTON_PLAY;
+
+ case KEY_RIGHT:
+ key_right_delay = DEF_DELAY;
+ return BUTTON_VOL_DOWN;
+ case KEY_F7:
+ key_right_delay = 0;
+ return BUTTON_VOL_DOWN;
+
+ case KEY_LEFT:
+ key_left_delay = DEF_DELAY;
+ return BUTTON_VOL_UP;
+ case KEY_F6:
+ key_left_delay = 0;
+ return BUTTON_VOL_UP;
+
+ case KEY_POWER:
+ key_power_delay = DEF_DELAY;
+ return BUTTON_POWER;
+ case KEY_F8:
+ key_power_delay = 0;
+ return BUTTON_POWER;
+
+ case KEY_HOME:
+ key_home_delay = DEF_DELAY;
+ return BUTTON_OPTION;
+ case KEY_F9:
+ key_home_delay = 0;
+ return BUTTON_OPTION;
+
+ case KEY_BACKSPACE:
+ key_backspace_delay = DEF_DELAY;
+ return BUTTON_HOME;
+ case KEY_NUMLOCK:
+ key_backspace_delay = 0;
+ return BUTTON_HOME;
+
+ case KEY_LEFTBRACE:
+ key_leftbrace_delay = DEF_DELAY;
+ return BUTTON_PREV;
+ case KEY_F5:
+ key_leftbrace_delay = 0;
+ return BUTTON_PREV;
+
+ case KEY_RIGHTBRACE:
+ key_rightbrace_delay = DEF_DELAY;
+ return BUTTON_NEXT;
+ case KEY_F4:
+ key_rightbrace_delay = 0;
+ return BUTTON_NEXT;
+
+ case KEY_UP:
+ if (!key_up_delay) key_up_delay = DEF_DELAY;
+ return BUTTON_UP;
+
+ case KEY_DOWN:
+ if (!key_down_delay) key_down_delay = DEF_DELAY;
+ return BUTTON_DOWN;
+
+ case KEY_F12:
+ key_f12_delay = DEF_DELAY;
+ //return BUTTON_UNLOCK;
+ return 0;
+
+ default:
+ return 0;
+ }
+}
+
+static int button_map_off(int keycode)
+{
+ switch(keycode)
+ {
+ case KEY_F10:
+ return BUTTON_PLAY;
+
+ case KEY_F7:
+ return BUTTON_VOL_DOWN;
+
+ case KEY_F6:
+ return BUTTON_VOL_UP;
+
+ case KEY_F8:
+ return BUTTON_POWER;
+
+ case KEY_F9:
+ return BUTTON_OPTION;
+
+ case KEY_NUMLOCK:
+ return BUTTON_HOME;
+
+ case KEY_F5:
+ return BUTTON_PREV;
+
+ case KEY_F4:
+ return BUTTON_NEXT;
+
+ default:
+ return 0;
+ }
+}
+
+static int button_map_timer(void)
+{
+ int map = 0;
+
+ if (key_enter_delay)
+ {
+ if (--key_enter_delay == 0) map |= BUTTON_PLAY;
+ }
+ if (key_right_delay)
+ {
+ if (--key_right_delay == 0) map |= BUTTON_VOL_DOWN;
+ }
+ if (key_left_delay)
+ {
+ if (--key_left_delay == 0) map |= BUTTON_VOL_UP;
+ }
+ if (key_power_delay)
+ {
+ if (--key_power_delay == 0) map |= BUTTON_POWER;
+ }
+ if (key_home_delay)
+ {
+ if (--key_home_delay == 0) map |= BUTTON_OPTION;
+ }
+ if (key_backspace_delay)
+ {
+ if (--key_backspace_delay == 0) map |= BUTTON_HOME;
+ }
+ if (key_leftbrace_delay)
+ {
+ if (--key_leftbrace_delay == 0) map |= BUTTON_PREV;
+ }
+ if (key_rightbrace_delay)
+ {
+ if (--key_rightbrace_delay == 0) map |= BUTTON_NEXT;
+ }
+ if (key_up_delay)
+ {
+ if (--key_up_delay == 0) map |= BUTTON_UP;
+ }
+ if (key_down_delay)
+ {
+ if (--key_down_delay == 0) map |= BUTTON_DOWN;
+ }
+ if (key_f12_delay)
+ {
+ if (--key_f12_delay == 0) map |= 0; //BUTTON_UNLOCK
+ }
+
+ return map;
+}
+
+void button_init_device(void)
+{
+ const char * const input_devs[] = {
+ "/dev/input/event0",
+ "/dev/input/event1",
+ };
+
+ for(int i = 0; i < NR_POLL_DESC; i++)
+ {
+ int fd = open(input_devs[i], O_RDWR);
+
+ if(fd < 0)
+ {
+ panicf("Cannot open input device: %s\n", input_devs[i]);
+ }
+
+ poll_fds[i].fd = fd;
+ poll_fds[i].events = POLLIN;
+ poll_fds[i].revents = 0;
+ }
+}
+
+int button_read_device(void)
+{
+ static int button_bitmap = 0;
+ static int map;
+ struct input_event event;
+
+ /* check if there are any events pending and process them */
+ while(poll(poll_fds, NR_POLL_DESC, 0))
+ {
+ for(int i = 0; i < NR_POLL_DESC; i++)
+ {
+ /* read only if non-blocking */
+ if(poll_fds[i].revents & POLLIN)
+ {
+ int size = read(poll_fds[i].fd, &event, sizeof(event));
+ if(size == (int)sizeof(event))
+ {
+ if(event.type == EV_KEY)
+ {
+ int keycode = event.code;
+
+ /* event.value == 1 means press
+ * event.value == 0 means release
+ */
+ bool press = event.value ? true : false;
+
+ if(press)
+ {
+ map = button_map_on(keycode);
+ if(map) button_bitmap |= map;
+ }
+ else
+ {
+ map = button_map_off(keycode);
+ if(map) button_bitmap &= ~map;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ map = button_map_timer();
+ if(map) button_bitmap &= ~map;
+
+ return button_bitmap;
+}
+
+bool headphones_inserted(void)
+{
+ int status = 0;
+ const char * const sysfs_hs_switch = "/sys/class/misc/axp173/headset_state";
+
+ sysfs_get_int(sysfs_hs_switch, &status);
+ if (status) return true;
+
+ return false;
+}
+
+void button_close_device(void)
+{
+ /* close descriptors */
+ for(int i = 0; i < NR_POLL_DESC; i++)
+ {
+ close(poll_fds[i].fd);
+ }
+}
diff --git a/firmware/target/hosted/fiio/button-target.h b/firmware/target/hosted/fiio/button-target.h
new file mode 100644
index 0000000000..8ed3b7ba0f
--- /dev/null
+++ b/firmware/target/hosted/fiio/button-target.h
@@ -0,0 +1,50 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2019 by Roman Stolyarov
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _BUTTON_TARGET_H_
+#define _BUTTON_TARGET_H_
+
+/* Main unit's buttons */
+#define BUTTON_POWER 0x00000001
+#define BUTTON_HOME 0x00000002
+#define BUTTON_OPTION 0x00000004
+#define BUTTON_PREV 0x00000008
+#define BUTTON_NEXT 0x00000010
+#define BUTTON_PLAY 0x00000020
+#define BUTTON_VOL_UP 0x00000040
+#define BUTTON_VOL_DOWN 0x00000080
+#define BUTTON_UP 0x00000100
+#define BUTTON_DOWN 0x00000200
+
+#define BUTTON_LEFT 0
+#define BUTTON_RIGHT 0
+
+#define BUTTON_MAIN (BUTTON_POWER | BUTTON_HOME | BUTTON_OPTION | BUTTON_PREV | \
+ BUTTON_NEXT | BUTTON_PLAY | BUTTON_VOL_UP | BUTTON_VOL_DOWN | \
+ BUTTON_UP | BUTTON_DOWN)
+
+#define BUTTON_LEFT BUTTON_PREV
+#define BUTTON_RIGHT BUTTON_NEXT
+
+/* Software power-off */
+#define POWEROFF_BUTTON BUTTON_POWER
+#define POWEROFF_COUNT 25
+
+#endif /* _BUTTON_TARGET_H_ */
+
diff --git a/firmware/target/hosted/fiio/buttonlight-fiio.c b/firmware/target/hosted/fiio/buttonlight-fiio.c
new file mode 100644
index 0000000000..37961f7b63
--- /dev/null
+++ b/firmware/target/hosted/fiio/buttonlight-fiio.c
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * __________ __ ___
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "config.h"
+#include "backlight-target.h"
+#include "sysfs.h"
+#include "panic.h"
+#include "lcd.h"
+
+static const char * const sysfs_kb_brightness =
+ "/sys/class/jz_pwm_dev/jz_pwm_dev4/duty_ratio";
+
+static const char * const sysfs_kb_power =
+ "/sys/class/jz_pwm_dev/jz_pwm_dev4/enable";
+
+void buttonlight_hw_on(void)
+{
+ sysfs_set_int(sysfs_kb_power, 1);
+}
+
+void buttonlight_hw_off(void)
+{
+ sysfs_set_int(sysfs_kb_power, 0);
+}
+
+void buttonlight_hw_brightness(int brightness)
+{
+ if (brightness > MAX_BRIGHTNESS_SETTING)
+ brightness = MAX_BRIGHTNESS_SETTING;
+ if (brightness < MIN_BRIGHTNESS_SETTING)
+ brightness = MIN_BRIGHTNESS_SETTING;
+
+ sysfs_set_int(sysfs_kb_brightness, brightness);
+}
diff --git a/firmware/target/hosted/fiio/debug-fiio.c b/firmware/target/hosted/fiio/debug-fiio.c
new file mode 100644
index 0000000000..9812b8f8b9
--- /dev/null
+++ b/firmware/target/hosted/fiio/debug-fiio.c
@@ -0,0 +1 @@
+#include "../agptek/debug-agptek.c"
diff --git a/firmware/target/hosted/fiio/fiio.make b/firmware/target/hosted/fiio/fiio.make
new file mode 100644
index 0000000000..d159db77f3
--- /dev/null
+++ b/firmware/target/hosted/fiio/fiio.make
@@ -0,0 +1,49 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+INCLUDES += -I$(FIRMDIR)/include -I$(FIRMDIR)/export $(TARGET_INC) -I$(BUILDDIR) -I$(APPSDIR)
+
+SIMFLAGS += $(INCLUDES) $(DEFINES) -DHAVE_CONFIG_H $(GCCOPTS)
+
+# bootloader build is sligtly different
+ifneq (,$(findstring bootloader,$(APPSDIR)))
+
+SRC += $(call preprocess, $(APPSDIR)/SOURCES)
+CLEANOBJS += $(BUILDDIR)/bootloader.*
+
+endif #bootloader
+
+.SECONDEXPANSION: # $$(OBJ) is not populated until after this
+
+ifneq (,$(findstring bootloader,$(APPSDIR)))
+# bootloader build
+
+$(BUILDDIR)/bootloader.elf : $$(OBJ) $(FIRMLIB) $(CORE_LIBS)
+ $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \
+ -L$(BUILDDIR)/firmware -lfirmware \
+ -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \
+ $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,--gc-sections -Wl,-Map,$(BUILDDIR)/bootloader.map
+
+$(BUILDDIR)/$(BINARY): $(BUILDDIR)/bootloader.elf
+ $(call PRINTS,OC $(@F))$(call objcopy,$^,$@)
+
+else
+# rockbox app build
+
+$(BUILDDIR)/rockbox.elf : $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS)
+ $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \
+ -L$(BUILDDIR)/firmware -lfirmware \
+ -L$(RBCODEC_BLD)/codecs $(call a2lnk, $(VOICESPEEXLIB)) \
+ -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \
+ $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map
+
+$(BUILDDIR)/$(BINARY): $(BUILDDIR)/rockbox.elf
+ $(call PRINTS,OC $(@F))$(call objcopy,$^,$@)
+
+endif
diff --git a/firmware/target/hosted/fiio/lcd-target.h b/firmware/target/hosted/fiio/lcd-target.h
new file mode 100644
index 0000000000..be5427322e
--- /dev/null
+++ b/firmware/target/hosted/fiio/lcd-target.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2016 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCD_TARGET_H__
+#define __LCD_TARGET_H__
+
+/* needs special ioctl() to redraw updated framebuffer content */
+#define LCD_OPTIMIZED_UPDATE
+#define LCD_OPTIMIZED_UPDATE_RECT
+
+extern fb_data *framebuffer; /* see lcd-fiio.c */
+#define LCD_FRAMEBUF_ADDR(col, row) (framebuffer + (row)*LCD_WIDTH + (col))
+
+extern void lcd_set_active(bool active);
+#endif /* __LCD_TARGET_H__ */
diff --git a/firmware/target/hosted/fiio/power-fiio.c b/firmware/target/hosted/fiio/power-fiio.c
new file mode 100644
index 0000000000..a2b19ce550
--- /dev/null
+++ b/firmware/target/hosted/fiio/power-fiio.c
@@ -0,0 +1,78 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include
+#include
+#include
+#include
+#include
+
+#include "system.h"
+#include "power.h"
+#include "panic.h"
+#include "sysfs.h"
+#include "usb.h"
+
+#include "power-fiio.h"
+
+const char * const sysfs_bat_voltage =
+ "/sys/class/power_supply/battery/voltage_now";
+
+const char * const sysfs_bat_capacity =
+ "/sys/class/power_supply/battery/capacity";
+
+const char * const sysfs_bat_status =
+ "/sys/class/power_supply/battery/status";
+
+const char * const sysfs_pow_supply =
+ "/sys/class/power_supply/ac/online";
+
+unsigned int fiio_power_input_status(void)
+{
+ int present = 0;
+ sysfs_get_int(sysfs_pow_supply, &present);
+
+ usb_enable(present ? true : false);
+
+ return present ? POWER_INPUT_USB_CHARGER : POWER_INPUT_NONE;
+}
+
+bool fiio_power_charging_status(void)
+{
+ char buf[12] = {0};
+ sysfs_get_string(sysfs_bat_status, buf, sizeof(buf));
+
+ return (strncmp(buf, "Charging", 8) == 0);
+}
+
+unsigned int fiio_power_get_battery_voltage(void)
+{
+ int battery_voltage;
+ sysfs_get_int(sysfs_bat_voltage, &battery_voltage);
+
+ return battery_voltage;
+}
+
+unsigned int fiio_power_get_battery_capacity(void)
+{
+ int battery_capacity;
+ sysfs_get_int(sysfs_bat_capacity, &battery_capacity);
+
+ return battery_capacity * 20;
+}
diff --git a/firmware/target/hosted/fiio/power-fiio.h b/firmware/target/hosted/fiio/power-fiio.h
new file mode 100644
index 0000000000..c3085e9569
--- /dev/null
+++ b/firmware/target/hosted/fiio/power-fiio.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _POWER_FIIO_H_
+#define _POWER_FIIO_H_
+
+#include
+#include "config.h"
+
+unsigned int fiio_power_input_status(void);
+bool fiio_power_charging_status(void);
+unsigned int fiio_power_get_battery_voltage(void);
+unsigned int fiio_power_get_battery_capacity(void);
+#endif /* _POWER_FIIO_H_ */
+
diff --git a/firmware/target/hosted/fiio/powermgmt-fiio.c b/firmware/target/hosted/fiio/powermgmt-fiio.c
new file mode 100644
index 0000000000..b7c1b5fde2
--- /dev/null
+++ b/firmware/target/hosted/fiio/powermgmt-fiio.c
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "powermgmt.h"
+#include "power.h"
+#include "power-fiio.h"
+
+const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
+{
+ 3470
+};
+
+/* the OF shuts down at this voltage */
+const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
+{
+ 3400
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
+const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
+{
+ { 3400, 3639, 3697, 3723, 3757, 3786, 3836, 3906, 3980, 4050, 4159 }
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
+const unsigned short const percent_to_volt_charge[11] =
+{
+ 3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196
+};
+
+unsigned int power_input_status(void)
+{
+ /* POWER_INPUT_USB_CHARGER, POWER_INPUT_NONE */
+ return fiio_power_input_status();
+}
+
+int _battery_voltage(void)
+{
+ return fiio_power_get_battery_voltage();
+}
+
+#if 0
+int _battery_level(void)
+{
+ return fiio_power_get_battery_capacity();
+}
+#endif
+
+bool charging_state(void)
+{
+ return fiio_power_charging_status();
+}
diff --git a/firmware/target/hosted/fiio/system-fiio.c b/firmware/target/hosted/fiio/system-fiio.c
new file mode 100644
index 0000000000..5e638989a1
--- /dev/null
+++ b/firmware/target/hosted/fiio/system-fiio.c
@@ -0,0 +1,205 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 Marcin Bukat
+ * Copyright (C) 2016 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include
+#include
+#include
+#include
+#include
+
+#include "system.h"
+#include "mv.h"
+#include "font.h"
+#include "power.h"
+#include "button.h"
+#include "backlight-target.h"
+#include "lcd.h"
+
+#include "panic.h"
+#include
+#include
+
+/* to make thread-internal.h happy */
+uintptr_t *stackbegin;
+uintptr_t *stackend;
+
+static void sig_handler(int sig, siginfo_t *siginfo, void *context)
+{
+ /* safe guard variable - we call backtrace() only on first
+ * UIE call. This prevent endless loop if backtrace() touches
+ * memory regions which cause abort
+ */
+ static bool triggered = false;
+
+ lcd_set_backdrop(NULL);
+ lcd_set_drawmode(DRMODE_SOLID);
+ lcd_set_foreground(LCD_BLACK);
+ lcd_set_background(LCD_WHITE);
+ unsigned line = 0;
+
+ lcd_setfont(FONT_SYSFIXED);
+ lcd_set_viewport(NULL);
+ lcd_clear_display();
+
+ /* get context info */
+ ucontext_t *uc = (ucontext_t *)context;
+ unsigned long pc = uc->uc_mcontext.pc;
+ unsigned long sp = uc->uc_mcontext.gregs[29];
+
+ lcd_putsf(0, line++, "%s at %08x", strsignal(sig), pc);
+
+ if(sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS || sig == SIGTRAP)
+ lcd_putsf(0, line++, "address 0x%08x", siginfo->si_addr);
+
+ if(!triggered)
+ {
+ triggered = true;
+ rb_backtrace(pc, sp, &line);
+ }
+
+#ifdef ROCKBOX_HAS_LOGF
+ lcd_putsf(0, line++, "logf:");
+ logf_panic_dump(&line);
+#endif
+
+ lcd_update();
+
+ system_exception_wait(); /* If this returns, try to reboot */
+
+ backlight_hw_off();
+ system_reboot();
+ while (1); /* halt */
+}
+
+static int axp_hw;
+
+void power_off(void)
+{
+ backlight_hw_off();
+
+ axp_hw = open("/dev/axp173", O_RDWR);
+ if(axp_hw < 0)
+ panicf("Cannot open '/dev/axp173'");
+
+ if(ioctl(axp_hw, 0x20003323, 0) < 0)
+ {
+ panicf("Call AXP173_SHUTDOWN fail");
+ }
+
+ close(axp_hw);
+}
+
+void system_init(void)
+{
+ int *s;
+ /* fake stack, to make thread-internal.h happy */
+ stackbegin = stackend = (uintptr_t*)&s;
+ /* catch some signals for easier debugging */
+ struct sigaction sa;
+ sigfillset(&sa.sa_mask);
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = &sig_handler;
+ sigaction(SIGILL, &sa, NULL);
+ sigaction(SIGABRT, &sa, NULL);
+ sigaction(SIGFPE, &sa, NULL);
+ sigaction(SIGSEGV, &sa, NULL);
+ sigaction(SIGPIPE, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGBUS, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+}
+
+void system_reboot(void)
+{
+ backlight_hw_off();
+ system("/sbin/reboot");
+ while (1); /* halt */
+}
+
+void system_exception_wait(void)
+{
+ backlight_hw_on();
+ backlight_hw_brightness(DEFAULT_BRIGHTNESS_SETTING);
+ /* wait until button press and release */
+ while(button_read_device() != 0) {}
+ while(button_read_device() == 0) {}
+ while(button_read_device() != 0) {}
+ while(button_read_device() == 0) {}
+}
+
+bool hostfs_removable(IF_MD_NONVOID(int drive))
+{
+#ifdef HAVE_MULTIDRIVE
+ if (drive > 0) /* Active LOW */
+ return true;
+ else
+#endif
+ return false; /* internal: always present */
+}
+
+bool hostfs_present(IF_MD_NONVOID(int drive))
+{
+#ifdef HAVE_MULTIDRIVE
+ if (drive > 0) /* Active LOW */
+ return true; //FIXME
+ else
+#endif
+ return true; /* internal: always present */
+}
+
+#ifdef HAVE_MULTIDRIVE
+int volume_drive(int drive)
+{
+ return drive;
+}
+#endif /* HAVE_MULTIDRIVE */
+
+#ifdef CONFIG_STORAGE_MULTI
+int hostfs_driver_type(int drive)
+{
+ return drive > 0 ? STORAGE_SD_NUM : STORAGE_HOSTFS_NUM;
+}
+#endif /* CONFIG_STORAGE_MULTI */
+
+int hostfs_init(void)
+{
+ return 0;
+}
+
+int hostfs_flush(void)
+{
+ sync();
+ return 0;
+}
+
+#ifdef HAVE_HOTSWAP
+bool volume_removable(int volume)
+{
+ /* don't support more than one partition yet, so volume == drive */
+ return hostfs_removable(volume);
+}
+
+bool volume_present(int volume)
+{
+ /* don't support more than one partition yet, so volume == drive */
+ return hostfs_present(volume);
+}
+#endif
+
diff --git a/firmware/target/hosted/fiio/system-target.h b/firmware/target/hosted/fiio/system-target.h
new file mode 100644
index 0000000000..830f19fde4
--- /dev/null
+++ b/firmware/target/hosted/fiio/system-target.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2017 Marcin Bukat
+ * Copyright (C) 2016 Amaury Pouly
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef __SYSTEM_TARGET_H__
+#define __SYSTEM_TARGET_H__
+
+#include "kernel-unix.h"
+#include "system-hosted.h"
+
+#define NEED_GENERIC_BYTESWAPS
+#endif /* __SYSTEM_TARGET_H__ */
diff --git a/firmware/target/hosted/fiio/usb-fiio.c b/firmware/target/hosted/fiio/usb-fiio.c
new file mode 100644
index 0000000000..76a0ec5a2b
--- /dev/null
+++ b/firmware/target/hosted/fiio/usb-fiio.c
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * __________ __ ___
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2018 by Marcin Bukat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include
+#include
+#include
+#include "config.h"
+#include "disk.h"
+#include "usb.h"
+#include "sysfs.h"
+#include "power.h"
+#include "power-fiio.h"
+
+const char * const sysfs_usb_online =
+ "/sys/class/power_supply/usb/online";
+
+int usb_detect(void)
+{
+ int present = 0;
+ sysfs_get_int(sysfs_usb_online, &present);
+
+ return present ? USB_INSERTED : USB_EXTRACTED;
+}
+
+void usb_enable(bool on)
+{
+ if (on)
+ {
+ system ("insmod /lib/modules/3.10.14/kernel/driver/usb/gadget/libcomposite.ko");
+ system ("insmod /lib/modules/3.10.14/kernel/driver/usb/gadget/usb_f_mass_storage.ko");
+ system ("insmod /lib/modules/3.10.14/kernel/driver/usb/gadget/g_mass_storage.ko file=/dev/mmcblk0 removable=1");
+ }
+ else
+ {
+ system ("rmmod g_mass_storage");
+ system ("rmmod usb_f_mass_storage");
+ system ("rmmod libcomposite");
+ }
+}
+
+/* This is called by usb thread after usb extract in order to return
+ * regular FS access
+ *
+ * returns the # of successful mounts
+*/
+int disk_mount_all(void)
+{
+ return 1;
+}
+
+/* This is called by usb thread after all threads ACKs usb inserted message
+ *
+ * returns the # of successful unmounts
+ */
+int disk_unmount_all(void)
+{
+ return 1;
+}
+
+void usb_init_device(void)
+{
+ system ("insmod /lib/modules/3.10.14/kernel/driver/staging/dwc2/dwc2.ko");
+ usb_enable(true);
+}
diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c
index 57f9b47282..f291ece06d 100644
--- a/firmware/target/hosted/filesystem-app.c
+++ b/firmware/target/hosted/filesystem-app.c
@@ -36,9 +36,14 @@
#include "rbpaths.h"
#include "logf.h"
-#if (defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)) && !(defined(BOOTLOADER) || defined(CHECKWPS) || defined(SIMULATOR))
-#define PIVOT_ROOT HOME_DIR
+#if !(defined(BOOTLOADER) || defined(CHECKWPS) || defined(SIMULATOR))
+#if (defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20))
+#define PIVOT_ROOT "/mnt/sd_0"
+#elif defined(FIIO_M3K)
+#define PIVOT_ROOT "/mnt" // XXX check this!
+#else
#endif
+#endif // !(BOOTLOADER|WPS|SIM)
#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
static const char rbhome[] = "/sdcard";
@@ -52,7 +57,7 @@ static const char rbhome[] = HOME_DIR;
#if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || \
defined(SONY_NWZ_LINUX) || defined(DX90) || defined(AGPTEK_ROCKER) || \
- defined(XDUOO_X3II) || defined(XDUOO_X20)) && \
+ defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K) || defined(FIIO_M3K_PRO)) && \
!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
diff --git a/tools/builds.pm b/tools/builds.pm
index d46aa83495..6f0c4d0445 100644
--- a/tools/builds.pm
+++ b/tools/builds.pm
@@ -444,6 +444,10 @@ $releasenotes="/wiki/ReleaseNotes315";
name => 'xDuoo X20',
status => 2,
},
+ 'fiiom3k' => {
+ name => 'FiiO M3K',
+ status => 1,
+ },
'ihifi770' => {
name => 'Xuelin iHIFI 770',
status => 2,
@@ -671,5 +675,4 @@ sub voicesforlang($) {
return @list;
}
-
1;
diff --git a/tools/configure b/tools/configure
index 9e29d84ed8..f5fb6351c0 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1588,7 +1588,8 @@ cat <