summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES6
-rw-r--r--apps/keymaps/keymap-dx50.c219
-rw-r--r--apps/main.c2
-rw-r--r--apps/plugins/battery_bench.c6
-rw-r--r--apps/plugins/blackjack.c14
-rw-r--r--apps/plugins/brickmania.c7
-rw-r--r--apps/plugins/calculator.c3
-rw-r--r--apps/plugins/calendar.c10
-rw-r--r--apps/plugins/chessbox/chessbox_pgn.h13
-rw-r--r--apps/plugins/chessclock.c9
-rw-r--r--apps/plugins/chip8.c3
-rw-r--r--apps/plugins/clix.c3
-rw-r--r--apps/plugins/cube.c8
-rw-r--r--apps/plugins/doom/i_video.c6
-rw-r--r--apps/plugins/fft/fft.c5
-rw-r--r--apps/plugins/flipit.c12
-rw-r--r--apps/plugins/fractals/fractal.h3
-rw-r--r--apps/plugins/goban/goban.h3
-rw-r--r--apps/plugins/imageviewer/imageviewer_button.h8
-rw-r--r--apps/plugins/invadrox.c7
-rw-r--r--apps/plugins/jewels.c4
-rw-r--r--apps/plugins/lib/pluginlib_actions.c7
-rw-r--r--apps/plugins/midi/midiplay.c7
-rw-r--r--apps/plugins/minesweeper.c3
-rw-r--r--apps/plugins/mp3_encoder.c5
-rw-r--r--apps/plugins/mpegplayer/mpeg_settings.c8
-rw-r--r--apps/plugins/mpegplayer/mpegplayer.c9
-rw-r--r--apps/plugins/oscilloscope.c5
-rw-r--r--apps/plugins/pacbox/pacbox.h3
-rw-r--r--apps/plugins/pegbox.c5
-rw-r--r--apps/plugins/plugins.make4
-rw-r--r--apps/plugins/pong.c3
-rw-r--r--apps/plugins/reversi/reversi-gui.h4
-rw-r--r--apps/plugins/rockblox.c8
-rw-r--r--apps/plugins/rockboy/rockboy.c9
-rw-r--r--apps/plugins/rockpaint.c3
-rw-r--r--apps/plugins/sliding_puzzle.c6
-rw-r--r--apps/plugins/snake.c8
-rw-r--r--apps/plugins/snake2.c9
-rw-r--r--apps/plugins/sokoban.c8
-rw-r--r--apps/plugins/solitaire.c3
-rw-r--r--apps/plugins/spacerocks.c8
-rw-r--r--apps/plugins/star.c4
-rw-r--r--apps/plugins/sudoku/sudoku.h3
-rw-r--r--apps/plugins/text_viewer/tv_button.h10
-rw-r--r--apps/plugins/vu_meter.c8
-rw-r--r--apps/plugins/wormlet.c9
-rw-r--r--apps/plugins/xobox.c8
-rw-r--r--apps/plugins/zxbox/keymaps.h8
-rw-r--r--apps/root_menu.c4
-rw-r--r--firmware/SOURCES18
-rw-r--r--firmware/asm/SOURCES2
-rw-r--r--firmware/asm/arm/thread.h4
-rw-r--r--firmware/drivers/audio/android.c24
-rw-r--r--firmware/drivers/touchscreen.c2
-rw-r--r--firmware/export/config.h5
-rw-r--r--firmware/export/config/ibassodx50.h136
-rw-r--r--firmware/export/config/ibassodx90.h136
-rw-r--r--firmware/export/hosted_codec.h4
-rw-r--r--firmware/powermgmt.c2
-rw-r--r--firmware/target/hosted/android/dx50/adc-target.h0
-rw-r--r--firmware/target/hosted/android/dx50/backlight-dx50.c76
-rw-r--r--firmware/target/hosted/android/dx50/backlight-target.h31
-rw-r--r--firmware/target/hosted/android/dx50/button-dx50.c314
-rw-r--r--firmware/target/hosted/android/dx50/button-target.h72
-rw-r--r--firmware/target/hosted/android/dx50/lcd-dx50.c120
-rw-r--r--firmware/target/hosted/android/dx50/lcd-target.h29
-rw-r--r--firmware/target/hosted/android/dx50/pcm-dx50.c364
-rw-r--r--firmware/target/hosted/android/dx50/powermgmt-dx50.c72
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/asound.h821
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h257
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/mixer.c497
-rw-r--r--firmware/target/hosted/android/dx50/tinyalsa/pcm.c973
-rw-r--r--firmware/target/hosted/android/system-android.c54
-rw-r--r--firmware/target/hosted/filesystem-app.c1
-rw-r--r--manual/rockbox_interface/images/ibassodx50-front.pdfbin0 -> 41904 bytes
-rw-r--r--manual/rockbox_interface/images/ibassodx50-front.pngbin0 -> 32802 bytes
-rw-r--r--manual/rockbox_interface/images/ibassodx50-front.svg1966
-rw-r--r--rbutil/ibassoboot/jni/Android.mk6
-rw-r--r--rbutil/ibassoboot/jni/chooser.bmpbin0 -> 230454 bytes
-rw-r--r--rbutil/ibassoboot/jni/ibassodualboot.c439
-rw-r--r--rbutil/ibassoboot/jni/qdbmp.c798
-rw-r--r--rbutil/ibassoboot/jni/qdbmp.h133
-rwxr-xr-xtools/configure80
84 files changed, 7939 insertions, 27 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 1aa4955205..6118438b40 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -100,7 +100,7 @@ gui/statusbar.c
#ifdef HAVE_LCD_BITMAP
gui/statusbar-skinned.c
#endif
-#if (CONFIG_PLATFORM&PLATFORM_ANDROID)
+#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined (DX50) && !defined(DX90)
hosted/android/yesno.c
hosted/android/notification.c
#else
@@ -129,7 +129,7 @@ player/keyboard.c
#ifdef HAVE_LCD_BITMAP
recorder/bmp.c
recorder/icons.c
-#if (CONFIG_PLATFORM&PLATFORM_ANDROID)
+#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined (DX50) && !defined(DX90)
hosted/android/keyboard.c
#else
recorder/keyboard.c
@@ -305,4 +305,6 @@ keymaps/keymap-ypz5.c
keymaps/keymap-ihifi.c
#elif CONFIG_KEYPAD == SAMSUNG_YPR1_PAD
keymaps/keymap-ypr1.c
+#elif CONFIG_KEYPAD == DX50_PAD
+keymaps/keymap-dx50.c
#endif
diff --git a/apps/keymaps/keymap-dx50.c b/apps/keymaps/keymap-dx50.c
new file mode 100644
index 0000000000..ee3b32005a
--- /dev/null
+++ b/apps/keymaps/keymap-dx50.c
@@ -0,0 +1,219 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Maurus Cuelenaere
+ *
+ * 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 iBasso DX50 & DX90 */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "config.h"
+#include "action.h"
+#include "button.h"
+#include "settings.h"
+
+/*
+ * The format of the list is as follows
+ * { Action Code, Button code, Prereq button code }
+ * if there's no need to check the previous button's value, use BUTTON_NONE
+ * Insert LAST_ITEM_IN_LIST at the end of each mapping
+ */
+
+static const struct button_mapping button_context_standard[] = {
+ { ACTION_STD_PREV, BUTTON_LEFT, BUTTON_NONE },
+ { ACTION_STD_NEXT, BUTTON_RIGHT, BUTTON_NONE },
+ { ACTION_STD_PREVREPEAT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_NEXTREPEAT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_STD_OK, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY },
+ { ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_STD_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST
+}; /* button_context_standard */
+
+static const struct button_mapping button_context_wps[] = {
+ { ACTION_WPS_MENU, BUTTON_POWER, BUTTON_NONE },
+ { ACTION_WPS_CONTEXT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_NONE },
+ { ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE },
+ { ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT },
+ { ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT },
+ { ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE },
+ { ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE },
+ { ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ LAST_ITEM_IN_LIST
+}; /* button_context_wps */
+
+static const struct button_mapping button_context_list[] = {
+#ifdef HAVE_VOLUME_IN_LIST
+ { ACTION_LIST_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_LIST_VOLUP, BUTTON_VOL_UP, BUTTON_NONE },
+ { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE },
+ { ACTION_LIST_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+#endif
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
+}; /* button_context_list */
+
+static const struct button_mapping button_context_tree[] = {
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST),
+}; /* button_context_tree */
+
+static const struct button_mapping button_context_listtree_scroll_with_combo[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE),
+};
+
+static const struct button_mapping button_context_listtree_scroll_without_combo[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE),
+};
+
+static const struct button_mapping button_context_settings[] = {
+ { ACTION_SETTINGS_INC, BUTTON_VOL_UP|BUTTON_REL, BUTTON_NONE },
+ { ACTION_SETTINGS_INCREPEAT, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_SETTINGS_DEC, BUTTON_VOL_DOWN|BUTTON_REL, BUTTON_NONE },
+ { ACTION_SETTINGS_DECREPEAT, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
+}; /* button_context_settings */
+
+static const struct button_mapping button_context_settings_right_is_inc[] = {
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
+}; /* button_context_settingsgraphical */
+
+static const struct button_mapping button_context_mainmenu[] = {
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_TREE),
+}; /* button_context_mainmenu */
+
+static const struct button_mapping button_context_yesno[] = {
+ { ACTION_YESNO_ACCEPT, BUTTON_PLAY, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD),
+}; /* button_context_settings_yesno */
+
+static const struct button_mapping button_context_colorchooser[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS),
+}; /* button_context_colorchooser */
+
+static const struct button_mapping button_context_eq[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS),
+}; /* button_context_eq */
+
+static const struct button_mapping button_context_keyboard[] = {
+ { ACTION_KBD_LEFT, BUTTON_LEFT, BUTTON_NONE },
+ { ACTION_KBD_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_RIGHT, BUTTON_RIGHT, BUTTON_NONE },
+ { ACTION_KBD_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+
+ { ACTION_KBD_CURSOR_LEFT, BUTTON_PLAY|BUTTON_LEFT, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_LEFT, BUTTON_PLAY|BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_RIGHT, BUTTON_NONE },
+ { ACTION_KBD_CURSOR_RIGHT, BUTTON_PLAY|BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_SELECT, BUTTON_PLAY, BUTTON_NONE },
+
+ { ACTION_KBD_UP, BUTTON_VOL_UP, BUTTON_NONE },
+ { ACTION_KBD_UP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE },
+ { ACTION_KBD_DOWN, BUTTON_VOL_DOWN, BUTTON_NONE },
+ { ACTION_KBD_DOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST
+}; /* button_context_keyboard */
+
+/** Bookmark Screen **/
+static const struct button_mapping button_context_bmark[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST),
+}; /* button_context_bmark */
+
+static const struct button_mapping button_context_time[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS),
+}; /* button_context_time */
+
+static const struct button_mapping button_context_quickscreen[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_quickscreen */
+
+static const struct button_mapping button_context_pitchscreen[] = {
+
+ { ACTION_PS_INC_SMALL, BUTTON_VOL_UP|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_DEC_SMALL, BUTTON_VOL_DOWN|BUTTON_REL, BUTTON_NONE },
+ { ACTION_PS_EXIT, BUTTON_POWER, BUTTON_NONE },
+
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD)
+}; /* button_context_pitchcreen */
+
+
+static const struct button_mapping button_context_radio[] = {
+ LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_SETTINGS)
+}; /* button_context_radio */
+
+const struct button_mapping* target_get_context_mapping(int context)
+{
+ switch (context)
+ {
+ case CONTEXT_STD:
+ return button_context_standard;
+ case CONTEXT_WPS:
+ return button_context_wps;
+
+ case CONTEXT_LIST:
+ return button_context_list;
+ case CONTEXT_MAINMENU:
+ return button_context_mainmenu;
+ case CONTEXT_TREE:
+ if (global_settings.hold_lr_for_scroll_in_list)
+ return button_context_listtree_scroll_without_combo;
+ else
+ return button_context_listtree_scroll_with_combo;
+ case CONTEXT_CUSTOM|CONTEXT_TREE:
+ return button_context_tree;
+
+ case CONTEXT_SETTINGS:
+ return button_context_settings;
+ case CONTEXT_CUSTOM|CONTEXT_SETTINGS:
+ case CONTEXT_SETTINGS_RECTRIGGER:
+ return button_context_settings_right_is_inc;
+
+ case CONTEXT_SETTINGS_COLOURCHOOSER:
+ return button_context_colorchooser;
+ case CONTEXT_SETTINGS_EQ:
+ return button_context_eq;
+
+ case CONTEXT_SETTINGS_TIME:
+ return button_context_time;
+
+ case CONTEXT_KEYBOARD:
+ return button_context_keyboard;
+
+ case CONTEXT_FM:
+ return button_context_radio;
+ case CONTEXT_BOOKMARKSCREEN:
+ return button_context_bmark;
+ case CONTEXT_QUICKSCREEN:
+ return button_context_quickscreen;
+ case CONTEXT_PITCHSCREEN:
+ return button_context_pitchscreen;
+ }
+ return button_context_standard;
+}
diff --git a/apps/main.c b/apps/main.c
index 9098180fb8..60164515fa 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -340,7 +340,7 @@ static void init(void)
#ifdef SIMULATOR
sim_tasks_init();
#endif
-#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
+#if (CONFIG_PLATFORM & PLATFORM_ANDROID) && !defined(DX50) && !defined(DX90)
notification_init();
#endif
lang_init(core_language_builtin, language_strings,
diff --git a/apps/plugins/battery_bench.c b/apps/plugins/battery_bench.c
index 930d56f29a..b0976d5e10 100644
--- a/apps/plugins/battery_bench.c
+++ b/apps/plugins/battery_bench.c
@@ -261,6 +261,12 @@
#define BATTERY_ON_TXT "PLAY - start"
#define BATTERY_OFF_TXT "Power"
+#elif CONFIG_KEYPAD == DX50_PAD
+#define BATTERY_ON BUTTON_PLAY
+#define BATTERY_OFF BUTTON_POWER
+#define BATTERY_OFF_TXT "POWER"
+#define BATTERY_ON_TXT "PLAY - start"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/blackjack.c b/apps/plugins/blackjack.c
index 2211f88620..4022696a1f 100644
--- a/apps/plugins/blackjack.c
+++ b/apps/plugins/blackjack.c
@@ -541,6 +541,20 @@ enum {
#define BJACK_QUIT_NAME "Back"
#define BJACK_DOUBLE_NAME "Shortcut"
+#elif CONFIG_KEYPAD == DX50_PAD
+#define BJACK_QUIT BUTTON_POWER
+#define BJACK_DOUBLEDOWN BUTTON_RIGHT
+#define BJACK_SELECT BUTTON_PLAY
+#define BJACK_QUIT BUTTON_POWER
+#define BJACK_STAY BUTTON_LEFT
+#define BJACK_UP BUTTON_VOL_UP
+#define BJACK_DOWN BUTTON_VOL_DOWN
+#define BJACK_LEFT BUTTON_LEFT
+#define BJACK_SELECT_NAME "Play"
+#define BJACK_STAY_NAME "Left"
+#define BJACK_QUIT_NAME "Power"
+#define BJACK_DOUBLE_NAME "Right"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/brickmania.c b/apps/plugins/brickmania.c
index ee72e0bf37..0c9223d398 100644
--- a/apps/plugins/brickmania.c
+++ b/apps/plugins/brickmania.c
@@ -311,6 +311,13 @@ CONFIG_KEYPAD == SANSA_CONNECT_PAD
#define UP BUTTON_UP
#define DOWN BUTTON_DOWN
+#elif CONFIG_KEYPAD == DX50_PAD
+#define QUIT BUTTON_POWER
+#define LEFT BUTTON_LEFT
+#define RIGHT BUTTON_RIGHT
+#define SELECT BUTTON_PLAY
+#define UP BUTTON_VOL_UP
+#define DOWN BUTTON_VOL_DOWN
#else
#error No keymap defined!
diff --git a/apps/plugins/calculator.c b/apps/plugins/calculator.c
index 6c75595f9e..c378ecbb81 100644
--- a/apps/plugins/calculator.c
+++ b/apps/plugins/calculator.c
@@ -497,6 +497,9 @@ F3: equal to "="
#define CALCULATOR_CALC BUTTON_PLAYPAUSE
#define CALCULATOR_CLEAR BUTTON_SHORTCUT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define CALCULATOR_QUIT BUTTON_POWER
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/calendar.c b/apps/plugins/calendar.c
index 2e0577fc73..91613fcf88 100644
--- a/apps/plugins/calendar.c
+++ b/apps/plugins/calendar.c
@@ -369,6 +369,16 @@
#define CALENDAR_NEXT_MONTH BUTTON_SHORTCUT
#define CALENDAR_PREV_MONTH BUTTON_MENU
+#elif CONFIG_KEYPAD == DX50_PAD
+#define CALENDAR_QUIT (BUTTON_POWER|BUTTON_REL)
+#define CALENDAR_SELECT BUTTON_PLAY
+#define CALENDAR_NEXT_WEEK BUTTON_VOL_DOWN
+#define CALENDAR_PREV_WEEK BUTTON_VOL_UP
+#define CALENDAR_NEXT_DAY BUTTON_RIGHT
+#define CALENDAR_PREV_DAY BUTTON_LEFT
+#define CALENDAR_NEXT_MONTH BUTTON_BOTTOMRIGHT
+#define CALENDAR_PREV_MONTH BUTTON_BOTTOMLEFT
+
#else
#error "No keypad setting."
#endif
diff --git a/apps/plugins/chessbox/chessbox_pgn.h b/apps/plugins/chessbox/chessbox_pgn.h
index c7aca0f939..df6a01c891 100644
--- a/apps/plugins/chessbox/chessbox_pgn.h
+++ b/apps/plugins/chessbox/chessbox_pgn.h
@@ -485,6 +485,19 @@
#define CB_MENU BUTTON_MENU
#define CB_LEVEL BUTTON_BACK
+#elif CONFIG_KEYPAD == DX50_PAD
+#define CB_SELECT BUTTON_PLAY
+#define CB_UP BUTTON_VOL_UP
+#define CB_DOWN BUTTON_VOL_DOWN
+#define CB_LEFT BUTTON_LEFT
+#define CB_RIGHT BUTTON_RIGHT
+#define CB_PLAY (BUTTON_PLAY|BUTTON_REPEAT)
+#define CB_MENU BUTTON_POWER
+#define CB_SCROLL_UP (BUTTON_VOL_UP|BUTTON_REPEAT)
+#define CB_SCROLL_DOWN (BUTTON_VOL_DOWN|BUTTON_REPEAT)
+#define CB_SCROLL_LEFT (BUTTON_LEFT|BUTTON_REPEAT)
+#define CB_SCROLL_RIGHT (BUTTON_RIGHT|BUTTON_REPEAT)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/chessclock.c b/apps/plugins/chessclock.c
index cacfbbe939..01895d20f8 100644
--- a/apps/plugins/chessclock.c
+++ b/apps/plugins/chessclock.c
@@ -387,6 +387,15 @@
#define CHC_SETTINGS_OK BUTTON_SELECT
#define CHC_SETTINGS_CANCEL BUTTON_BACK
+#elif CONFIG_KEYPAD == DX50_PAD
+#define CHC_QUIT (BUTTON_POWER|BUTTON_REPEAT)
+#define CHC_RESET (BUTTON_PLAY|BUTTON_REPEAT)
+#define CHC_MENU BUTTON_RIGHT
+#define CHC_STARTSTOP BUTTON_PLAY
+#define CHC_SETTINGS_INC BUTTON_VOL_UP
+#define CHC_SETTINGS_DEC BUTTON_VOL_DOWN
+#define CHC_SETTINGS_CANCEL BUTTON_RIGHT
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/chip8.c b/apps/plugins/chip8.c
index d1a8285ace..efb62eb27e 100644
--- a/apps/plugins/chip8.c
+++ b/apps/plugins/chip8.c
@@ -1259,6 +1259,9 @@ CONFIG_KEYPAD == MROBE500_PAD
#define CHIP8_KEY8 BUTTON_PLAY
#define CHIP8_KEY9 BUTTON_POWER
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define CHIP8_OFF BUTTON_POWER
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/clix.c b/apps/plugins/clix.c
index c204663cf5..ffbb01abb8 100644
--- a/apps/plugins/clix.c
+++ b/apps/plugins/clix.c
@@ -253,6 +253,9 @@
#elif (CONFIG_KEYPAD == SAMSUNG_YPR1_PAD)
#define CLIX_BUTTON_QUIT BUTTON_POWER
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define CLIX_BUTTON_QUIT BUTTON_POWER
+
#else
#error "no keymap"
#endif
diff --git a/apps/plugins/cube.c b/apps/plugins/cube.c
index 5331d531db..09993204cd 100644
--- a/apps/plugins/cube.c
+++ b/apps/plugins/cube.c
@@ -390,6 +390,14 @@
#define CUBE_PAUSE BUTTON_PLAYPAUSE
#define CUBE_HIGHSPEED BUTTON_SHORTCUT
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define CUBE_QUIT (BUTTON_POWER|BUTTON_REL)
+#define CUBE_NEXT BUTTON_RIGHT
+#define CUBE_PREV BUTTON_LEFT
+#define CUBE_INC BUTTON_VOL_UP
+#define CUBE_DEC BUTTON_VOL_DOWN
+#define CUBE_MODE BUTTON_PLAY
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/doom/i_video.c b/apps/plugins/doom/i_video.c
index c285215e50..11aa712d33 100644
--- a/apps/plugins/doom/i_video.c
+++ b/apps/plugins/doom/i_video.c
@@ -523,6 +523,12 @@ void I_ShutdownGraphics(void)
#define DOOMBUTTON_WEAPON BUTTON_SHORTCUT
#define DOOMBUTTON_MAP BUTTON_MENU
+#elif CONFIG_KEYPAD == DX50_PAD
+#define DOOMBUTTON_ESC BUTTON_POWER
+#define DOOMBUTTON_SHOOT BUTTON_VOL_UP
+#define DOOMBUTTON_WEAPON BUTTON_VOL_DOWN
+#define DOOMBUTTON_MAP BUTTON_PLAY
+
#else
#error Keymap not defined!
#endif
diff --git a/apps/plugins/fft/fft.c b/apps/plugins/fft/fft.c
index d4b79b2ea7..9871c31eb9 100644
--- a/apps/plugins/fft/fft.c
+++ b/apps/plugins/fft/fft.c
@@ -320,6 +320,11 @@ GREY_INFO_STRUCT
# define FFT_ORIENTATION BUTTON_SELECT
# define FFT_WINDOW BUTTON_MENU
+#elif (CONFIG_KEYPAD == DX50_PAD)
+# define FFT_QUIT (BUTTON_POWER|BUTTON_REL)
+# define FFT_PREV_GRAPH BUTTON_VOL_UP
+# define FFT_NEXT_GRAPH BUTTON_VOL_DOWN
+
#elif !defined(HAVE_TOUCHSCREEN)
#error No keymap defined!
#endif
diff --git a/apps/plugins/flipit.c b/apps/plugins/flipit.c
index 6274af4f1d..d3dc98aa54 100644
--- a/apps/plugins/flipit.c
+++ b/apps/plugins/flipit.c
@@ -453,6 +453,18 @@
#define FLIPIT_STEP_BY_STEP BUTTON_PLAY
#define FLIPIT_TOGGLE BUTTON_SELECT
+#elif CONFIG_KEYPAD == DX50_PAD
+
+#define FLIPIT_LEFT BUTTON_LEFT
+#define FLIPIT_RIGHT BUTTON_RIGHT
+#define FLIPIT_UP BUTTON_VOL_UP
+#define FLIPIT_DOWN BUTTON_VOL_DOWN
+#define FLIPIT_QUIT (BUTTON_POWER|BUTTON_REL)
+#define FLIPIT_SHUFFLE (BUTTON_VOL_UP|BUTTON_POWER)
+#define FLIPIT_SOLVE (BUTTON_VOL_DOWN|BUTTON_POWER)
+#define FLIPIT_STEP_BY_STEP (BUTTON_LEFT|BUTTON_POWER)
+#define FLIPIT_TOGGLE BUTTON_PLAY
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/fractals/fractal.h b/apps/plugins/fractals/fractal.h
index b5ab0d31c9..7e13657595 100644
--- a/apps/plugins/fractals/fractal.h
+++ b/apps/plugins/fractals/fractal.h
@@ -451,6 +451,9 @@
#define FRACTAL_PRECISION_DEC (BUTTON_POWER|BUTTON_MENU)
#define FRACTAL_RESET BUTTON_SHORTCUT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define FRACTAL_QUIT (BUTTON_POWER|BUTTON_REL)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/goban/goban.h b/apps/plugins/goban/goban.h
index c709df3281..531b137556 100644
--- a/apps/plugins/goban/goban.h
+++ b/apps/plugins/goban/goban.h
@@ -432,6 +432,9 @@
#define GBN_BUTTON_CONTEXT BUTTON_PLAY
#define GBN_BUTTON_NEXT_VAR BUTTON_NEXT
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define GBN_BUTTON_MENU (BUTTON_POWER|BUTTON_REL)
+
#else
#error Unsupported keypad
#endif
diff --git a/apps/plugins/imageviewer/imageviewer_button.h b/apps/plugins/imageviewer/imageviewer_button.h
index dd3b35041f..c5fb9730c1 100644
--- a/apps/plugins/imageviewer/imageviewer_button.h
+++ b/apps/plugins/imageviewer/imageviewer_button.h
@@ -452,6 +452,14 @@
#define IMGVIEW_PREVIOUS BUTTON_BACK
#define IMGVIEW_MENU BUTTON_MENU
+#elif CONFIG_KEYPAD == DX50_PAD
+#define IMGVIEW_ZOOM_IN BUTTON_VOL_UP
+#define IMGVIEW_ZOOM_OUT BUTTON_VOL_DOWN
+#define IMGVIEW_NEXT BUTTON_RIGHT
+#define IMGVIEW_PREVIOUS BUTTON_LEFT
+#define IMGVIEW_QUIT (BUTTON_POWER|BUTTON_REL)
+#define IMGVIEW_MENU (BUTTON_PLAY|BUTTON_REL)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/invadrox.c b/apps/plugins/invadrox.c
index e77fe1e4a6..c1da3a6338 100644
--- a/apps/plugins/invadrox.c
+++ b/apps/plugins/invadrox.c
@@ -259,6 +259,13 @@ CONFIG_KEYPAD == MROBE500_PAD
#define RIGHT BUTTON_RIGHT
#define FIRE BUTTON_SELECT
+#elif CONFIG_KEYPAD == DX50_PAD
+
+#define QUIT (BUTTON_POWER|BUTTON_REL)
+#define LEFT BUTTON_LEFT
+#define RIGHT BUTTON_PLAY
+#define FIRE BUTTON_RIGHT
+
#else
#error INVADROX: Unsupported keypad
#endif
diff --git a/apps/plugins/jewels.c b/apps/plugins/jewels.c
index b4c53a96c4..d8a3cc39b5 100644
--- a/apps/plugins/jewels.c
+++ b/apps/plugins/jewels.c
@@ -359,6 +359,10 @@ CONFIG_KEYPAD == MROBE500_PAD
#define HK_SELECT "SELECT"
#define HK_CANCEL "POWER"
+#elif CONFIG_KEYPAD == DX50_PAD
+#define JEWELS_CANCEL BUTTON_POWER
+#define HK_CANCEL "Power"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/lib/pluginlib_actions.c b/apps/plugins/lib/pluginlib_actions.c
index 97dde57fbe..3113f64667 100644
--- a/apps/plugins/lib/pluginlib_actions.c
+++ b/apps/plugins/lib/pluginlib_actions.c
@@ -434,6 +434,13 @@ 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 == DX50_PAD)
+ {PLA_CANCEL, BUTTON_LEFT|BUTTON_REL, BUTTON_NONE},
+ {PLA_EXIT, BUTTON_POWER|BUTTON_REL, BUTTON_NONE},
+ {PLA_SELECT, BUTTON_PLAY, BUTTON_NONE},
+ {PLA_SELECT_REL, BUTTON_PLAY|BUTTON_REL, BUTTON_NONE},
+ {PLA_SELECT_REPEAT, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_NONE},
+
#else
# ifndef HAVE_TOUCHSCREEN
# error pluginlib_actions: No actions defined
diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c
index f5edc83f9a..2f4a698fad 100644
--- a/apps/plugins/midi/midiplay.c
+++ b/apps/plugins/midi/midiplay.c
@@ -275,6 +275,13 @@
#define BTN_DOWN BUTTON_DOWN
#define BTN_PLAY BUTTON_PLAYPAUSE
+#elif CONFIG_KEYPAD == DX50_PAD
+#define BTN_QUIT BUTTON_POWER
+#define BTN_RIGHT BUTTON_RIGHT
+#define BTN_LEFT BUTTON_LEFT
+#define BTN_UP BUTTON_VOL_UP
+#define BTN_DOWN BUTTON_VOL_DOWN
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/minesweeper.c b/apps/plugins/minesweeper.c
index 4758a1f911..982bb8b67c 100644
--- a/apps/plugins/minesweeper.c
+++ b/apps/plugins/minesweeper.c
@@ -377,6 +377,9 @@ CONFIG_KEYPAD == MROBE500_PAD
#define MINESWP_DISCOVER BUTTON_SELECT
#define MINESWP_INFO BUTTON_MENU
+#elif (CONFIG_KEYPAD == DX50_PAD)
+# define MINESWP_QUIT (BUTTON_POWER|BUTTON_REL)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/mp3_encoder.c b/apps/plugins/mp3_encoder.c
index 7b3c18bea2..7da00ad23b 100644
--- a/apps/plugins/mp3_encoder.c
+++ b/apps/plugins/mp3_encoder.c
@@ -2540,6 +2540,11 @@ CONFIG_KEYPAD == MROBE500_PAD
#define MP3ENC_DONE BUTTON_PLAYPAUSE
#define MP3ENC_SELECT BUTTON_SELECT
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define MP3ENC_PREV BUTTON_LEFT
+#define MP3ENC_NEXT BUTTON_RIGHT
+#define MP3ENC_DONE BUTTON_POWER
+#define MP3ENC_SELECT BUTTON_PLAY
#else
#error No keymap defined!
diff --git a/apps/plugins/mpegplayer/mpeg_settings.c b/apps/plugins/mpegplayer/mpeg_settings.c
index 7b259395b9..1a9636e8d8 100644
--- a/apps/plugins/mpegplayer/mpeg_settings.c
+++ b/apps/plugins/mpegplayer/mpeg_settings.c
@@ -289,6 +289,14 @@ struct mpeg_settings settings;
#define MPEG_START_TIME_DOWN BUTTON_DOWN
#define MPEG_START_TIME_EXIT BUTTON_BACK
+#elif CONFIG_KEYPAD == DX50_PAD
+#define MPEG_START_TIME_EXIT BUTTON_POWER
+#define MPEG_START_TIME_SELECT BUTTON_PLAY
+#define MPEG_START_TIME_LEFT BUTTON_LEFT
+#define MPEG_START_TIME_RIGHT BUTTON_RIGHT
+#define MPEG_START_TIME_UP BUTTON_VOL_UP
+#define MPEG_START_TIME_DOWN BUTTON_VOL_DOWN
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/mpegplayer/mpegplayer.c b/apps/plugins/mpegplayer/mpegplayer.c
index b041094e25..945d906d8b 100644
--- a/apps/plugins/mpegplayer/mpegplayer.c
+++ b/apps/plugins/mpegplayer/mpegplayer.c
@@ -417,6 +417,15 @@ CONFIG_KEYPAD == SANSA_M200_PAD
#define MPEG_RW BUTTON_LEFT
#define MPEG_FF BUTTON_RIGHT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define MPEG_MENU BUTTON_POWER
+#define MPEG_VOLDOWN BUTTON_VOL_DOWN
+#define MPEG_VOLUP BUTTON_VOL_UP
+#define MPEG_RW BUTTON_LEFT
+#define MPEG_FF BUTTON_RIGHT
+#define MPEG_PAUSE BUTTON_PLAY
+#define MPEG_STOP (BUTTON_PLAY|BUTTON_REPEAT)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/oscilloscope.c b/apps/plugins/oscilloscope.c
index 559d52ea06..a0b976f466 100644
--- a/apps/plugins/oscilloscope.c
+++ b/apps/plugins/oscilloscope.c
@@ -486,6 +486,11 @@
#define OSCILLOSCOPE_VOL_UP BUTTON_UP
#define OSCILLOSCOPE_VOL_DOWN BUTTON_DOWN
+#elif CONFIG_KEYPAD == DX50_PAD
+#define OSCILLOSCOPE_QUIT (BUTTON_POWER|BUTTON_REL)
+#define OSCILLOSCOPE_VOL_UP BUTTON_VOL_UP
+#define OSCILLOSCOPE_VOL_DOWN BUTTON_VOL_DOWN
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/pacbox/pacbox.h b/apps/plugins/pacbox/pacbox.h
index 1854006a91..5da7a8b099 100644
--- a/apps/plugins/pacbox/pacbox.h
+++ b/apps/plugins/pacbox/pacbox.h
@@ -328,6 +328,9 @@
#define PACMAN_1UP BUTTON_SELECT
#define PACMAN_COIN BUTTON_PLAYPAUSE
+#elif CONFIG_KEYPAD == DX50_PAD
+#define PACMAN_MENU BUTTON_POWER
+
#else
#error Keymap not defined!
diff --git a/apps/plugins/pegbox.c b/apps/plugins/pegbox.c
index fc0019fc26..1048138136 100644
--- a/apps/plugins/pegbox.c
+++ b/apps/plugins/pegbox.c
@@ -616,6 +616,11 @@ CONFIG_KEYPAD == MROBE500_PAD
#define LVL_DOWN_TEXT "PLAY/PAUSE"
#define SELECT_TEXT "SELECT"
+#elif CONFIG_KEYPAD == DX50_PAD
+#define PEGBOX_QUIT BUTTON_POWER
+
+#define QUIT_TEXT "Power"
+
#else
#error Unsupported keymap!
#endif
diff --git a/apps/plugins/plugins.make b/apps/plugins/plugins.make
index 92769d770a..1edbd37306 100644
--- a/apps/plugins/plugins.make
+++ b/apps/plugins/plugins.make
@@ -11,7 +11,9 @@
is_app_build =
ifdef APP_TYPE
ifneq ($(APP_TYPE),sdl-sim)
- is_app_build = yes
+ifeq (,$(findstring standalone, $(APP_TYPE)))
+ is_app_build = yes
+endif
endif
endif
diff --git a/apps/plugins/pong.c b/apps/plugins/pong.c
index eb5adb3351..4ec62e01be 100644
--- a/apps/plugins/pong.c
+++ b/apps/plugins/pong.c
@@ -287,6 +287,9 @@ CONFIG_KEYPAD == MROBE500_PAD
#define PONG_RIGHT_UP BUTTON_RIGHT
#define PONG_RIGHT_DOWN BUTTON_LEFT
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define PONG_QUIT (BUTTON_POWER|BUTTON_REL)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/reversi/reversi-gui.h b/apps/plugins/reversi/reversi-gui.h
index 5c43ce2373..3932b688ef 100644
--- a/apps/plugins/reversi/reversi-gui.h
+++ b/apps/plugins/reversi/reversi-gui.h
@@ -312,6 +312,10 @@
#define REVERSI_BUTTON_MAKE_MOVE BUTTON_SELECT
#define REVERSI_BUTTON_MENU BUTTON_MENU
+#elif CONFIG_KEYPAD == DX50_PAD
+#define REVERSI_BUTTON_QUIT BUTTON_POWER
+#define REVERSI_BUTTON_MENU BUTTON_PLAY
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/rockblox.c b/apps/plugins/rockblox.c
index 5647b0a719..cde542a1c0 100644
--- a/apps/plugins/rockblox.c
+++ b/apps/plugins/rockblox.c
@@ -449,6 +449,14 @@
#define ROCKBLOX_DROP BUTTON_SELECT
#define ROCKBLOX_RESTART BUTTON_SHORTCUT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define ROCKBLOX_OFF BUTTON_POWER
+#define ROCKBLOX_ROTATE BUTTON_RIGHT
+#define ROCKBLOX_LEFT BUTTON_LEFT
+#define ROCKBLOX_RIGHT BUTTON_PLAY
+#define ROCKBLOX_DROP BUTTON_VOL_DOWN
+#define ROCKBLOX_RESTART BUTTON_VOL_UP
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c
index c12df07140..12feabb8e1 100644
--- a/apps/plugins/rockboy/rockboy.c
+++ b/apps/plugins/rockboy/rockboy.c
@@ -402,6 +402,13 @@ static void setoptions (void)
options.A = BUTTON_SHORTCUT;
options.B = BUTTON_PLAYPAUSE;
+#elif CONFIG_KEYPAD == DX50_PAD
+ options.A = BUTTON_VOL_UP;
+ options.B = BUTTON_VOL_DOWN;
+ options.MENU = BUTTON_POWER;
+ options.START = BUTTON_LEFT;
+ options.SELECT = BUTTON_RIGHT;
+
#else
#error No Keymap Defined!
#endif
@@ -414,7 +421,7 @@ static void setoptions (void)
#if CONFIG_KEYPAD == MROBE500_PAD
options.A = BUTTON_BOTTOMLEFT;
options.B = BUTTON_BOTTOMRIGHT;
-#elif CONFIG_KEYPAD != COWON_D2_PAD
+#elif (CONFIG_KEYPAD != COWON_D2_PAD ) || (CONFIG_KEYPAD != DX50_PAD )
options.A = BUTTON_BOTTOMLEFT;
options.B = BUTTON_BOTTOMRIGHT;
options.MENU = BUTTON_TOPLEFT;
diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c
index af6ce20eec..f3647c6024 100644
--- a/apps/plugins/rockpaint.c
+++ b/apps/plugins/rockpaint.c
@@ -310,6 +310,9 @@
#define ROCKPAINT_TOOLBAR BUTTON_SHORTCUT
#define ROCKPAINT_TOOLBAR2 BUTTON_PLAYPAUSE
+#elif ( CONFIG_KEYPAD == DX50_PAD )
+#define ROCKPAINT_QUIT (BUTTON_POWER|BUTTON_REL)
+
#else
#error "Please define keys for this keypad"
#endif
diff --git a/apps/plugins/sliding_puzzle.c b/apps/plugins/sliding_puzzle.c
index 39c60628c7..d4dd01f948 100644
--- a/apps/plugins/sliding_puzzle.c
+++ b/apps/plugins/sliding_puzzle.c
@@ -310,6 +310,12 @@ CONFIG_KEYPAD == MROBE500_PAD
#define PUZZLE_SHUFFLE BUTTON_SHORTCUT
#define PUZZLE_PICTURE BUTTON_PLAYPAUSE
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define PUZZLE_QUIT (BUTTON_POWER|BUTTON_REL)
+#define PUZZLE_SHUFFLE BUTTON_PLAY
+#define PUZZLE_PICTURE BUTTON_RIGHT
+#define PUZZLE_QUIT_TEXT "[Power]"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/snake.c b/apps/plugins/snake.c
index 55d91cb5f9..a22ecf4c70 100644
--- a/apps/plugins/snake.c
+++ b/apps/plugins/snake.c
@@ -269,6 +269,14 @@ dir is the current direction of the snake - 0=up, 1=right, 2=down, 3=left;
#define SNAKE_DOWN BUTTON_DOWN
#define SNAKE_PLAYPAUSE BUTTON_PLAYPAUSE
+#elif CONFIG_KEYPAD == DX50_PAD
+#define SNAKE_QUIT BUTTON_POWER
+#define SNAKE_LEFT BUTTON_LEFT
+#define SNAKE_RIGHT BUTTON_PLAY
+#define SNAKE_UP BUTTON_VOL_UP
+#define SNAKE_DOWN BUTTON_VOL_DOWN
+#define SNAKE_PLAYPAUSE BUTTON_RIGHT
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/snake2.c b/apps/plugins/snake2.c
index 2fb5521a79..b695dc9abd 100644
--- a/apps/plugins/snake2.c
+++ b/apps/plugins/snake2.c
@@ -383,6 +383,15 @@ CONFIG_KEYPAD == MROBE500_PAD
#define SNAKE2_PLAYPAUSE BUTTON_PLAYPAUSE
#define SNAKE2_PLAYPAUSE_TEXT "Play/Pause"
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define SNAKE2_QUIT (BUTTON_POWER|BUTTON_REL)
+#define SNAKE2_LEFT BUTTON_LEFT
+#define SNAKE2_RIGHT BUTTON_PLAY
+#define SNAKE2_UP BUTTON_VOL_UP
+#define SNAKE2_DOWN BUTTON_VOL_DOWN
+#define SNAKE2_PLAYPAUSE BUTTON_RIGHT
+#define SNAKE2_PLAYPAUSE_TEXT "Right"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/sokoban.c b/apps/plugins/sokoban.c
index 07b5856240..f3c4f9c8f6 100644
--- a/apps/plugins/sokoban.c
+++ b/apps/plugins/sokoban.c
@@ -611,6 +611,14 @@
#define BUTTON_SAVE (BUTTON_POWER | BUTTON_PLAY)
#define BUTTON_SAVE_NAME "POWER + PLAY"
+#elif CONFIG_KEYPAD == DX50_PAD
+#define SOKOBAN_MENU (BUTTON_POWER|BUTTON_REL)
+#define SOKOBAN_PAUSE BUTTON_PLAY
+#define SOKOBAN_LEVEL_DOWN BUTTON_LEFT
+#define SOKOBAN_LEVEL_UP BUTTON_RIGHT
+#define SOKOBAN_MENU_NAME "Power"
+#define SOKOBAN_PAUSE_NAME "Play"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c
index 04e3c15d56..541b42de42 100644
--- a/apps/plugins/solitaire.c
+++ b/apps/plugins/solitaire.c
@@ -651,6 +651,9 @@ CONFIG_KEYPAD == MROBE500_PAD
#define HK_CUR2STACK "Menu"
#define HK_REM2STACK "Shortcut"
+#elif (CONFIG_KEYPAD == DX50_PAD)
+# define SOL_QUIT (BUTTON_POWER | BUTTON_REL)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/spacerocks.c b/apps/plugins/spacerocks.c
index 68f47caa4a..a7e9912cf4 100644
--- a/apps/plugins/spacerocks.c
+++ b/apps/plugins/spacerocks.c
@@ -333,6 +333,14 @@
#define AST_RIGHT BUTTON_RIGHT
#define AST_FIRE BUTTON_SELECT
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define AST_QUIT BUTTON_POWER
+#define AST_THRUST BUTTON_VOL_UP
+#define AST_HYPERSPACE BUTTON_VOL_DOWN
+#define AST_LEFT BUTTON_LEFT
+#define AST_RIGHT BUTTON_PLAY
+#define AST_FIRE BUTTON_RIGHT
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/star.c b/apps/plugins/star.c
index b43c05ebf5..a1367e9044 100644
--- a/apps/plugins/star.c
+++ b/apps/plugins/star.c
@@ -581,6 +581,10 @@
#define STAR_TOGGLE_CONTROL_NAME "Select"
#define STAR_QUIT_NAME "Back"
+#elif (CONFIG_KEYPAD == DX50_PAD)
+#define STAR_QUIT BUTTON_POWER
+#define STAR_QUIT_NAME "Power"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/sudoku/sudoku.h b/apps/plugins/sudoku/sudoku.h
index 2bc65eeaa7..2caa75fbbe 100644
--- a/apps/plugins/sudoku/sudoku.h
+++ b/apps/plugins/sudoku/sudoku.h
@@ -398,6 +398,9 @@
#define SUDOKU_BUTTON_TOGGLE BUTTON_SELECT
#define SUDOKU_BUTTON_POSSIBLE BUTTON_SHORTCUT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define SUDOKU_BUTTON_QUIT (BUTTON_POWER|BUTTON_REL)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/text_viewer/tv_button.h b/apps/plugins/text_viewer/tv_button.h
index bcaa593cea..7c0cfab519 100644
--- a/apps/plugins/text_viewer/tv_button.h
+++ b/apps/plugins/text_viewer/tv_button.h
@@ -506,6 +506,16 @@
#define TV_AUTOSCROLL BUTTON_PLAYPAUSE
#define TV_BOOKMARK BUTTON_SHORTCUT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define TV_QUIT (BUTTON_POWER | BUTTON_REL)
+#define TV_SCROLL_UP BUTTON_VOL_UP
+#define TV_SCROLL_DOWN BUTTON_VOL_DOWN
+#define TV_SCREEN_LEFT BUTTON_LEFT
+#define TV_SCREEN_RIGHT BUTTON_RIGHT
+#define TV_MENU (BUTTON_PLAY | BUTTON_REL)
+#define TV_AUTOSCROLL (BUTTON_POWER | BUTTON_PLAY)
+#define TV_BOOKMARK (BUTTON_POWER | BUTTON_VOL_UP)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/vu_meter.c b/apps/plugins/vu_meter.c
index 6d8922cd4b..43a7b917a9 100644
--- a/apps/plugins/vu_meter.c
+++ b/apps/plugins/vu_meter.c
@@ -395,6 +395,14 @@
#define LABEL_MENU "Menu"
#define LABEL_VOLUME "Up/Down"
+#elif CONFIG_KEYPAD == DX50_PAD
+#define VUMETER_QUIT (BUTTON_POWER|BUTTON_REL)
+#define VUMETER_MENU BUTTON_PLAY
+#define VUMETER_UP BUTTON_RIGHT
+#define VUMETER_DOWN BUTTON_LEFT
+#define LABEL_QUIT "Power"
+#define LABEL_MENU "Play"
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/wormlet.c b/apps/plugins/wormlet.c
index 51021dfac4..26b97c7748 100644
--- a/apps/plugins/wormlet.c
+++ b/apps/plugins/wormlet.c
@@ -370,6 +370,15 @@ CONFIG_KEYPAD == MROBE500_PAD
#define BTN_QUIT BUTTON_BACK
#define BTN_STOPRESET BUTTON_SHORTCUT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define BTN_DIR_UP BUTTON_VOL_UP
+#define BTN_DIR_DOWN BUTTON_VOL_DOWN
+#define BTN_DIR_LEFT BUTTON_LEFT
+#define BTN_DIR_RIGHT BUTTON_RIGHT
+#define BTN_STARTPAUSE BUTTON_PLAY
+#define BTN_QUIT BUTTON_POWER
+#define BTN_STOPRESET (BUTTON_PLAY|BUTTON_REPEAT)
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/xobox.c b/apps/plugins/xobox.c
index 3cf3b2a434..f3ed96f282 100644
--- a/apps/plugins/xobox.c
+++ b/apps/plugins/xobox.c
@@ -322,6 +322,14 @@ CONFIG_KEYPAD == MROBE500_PAD
#define DOWN BUTTON_DOWN
#define PAUSE BUTTON_PLAYPAUSE
+#elif CONFIG_KEYPAD == DX50_PAD
+#define QUIT BUTTON_POWER
+#define LEFT BUTTON_LEFT
+#define RIGHT BUTTON_RIGHT
+#define UP BUTTON_VOL_UP
+#define DOWN BUTTON_VOL_DOWN
+#define PAUSE BUTTON_PLAY
+
#else
#error No keymap defined!
#endif
diff --git a/apps/plugins/zxbox/keymaps.h b/apps/plugins/zxbox/keymaps.h
index d8be7f832b..bdbe4f93ad 100644
--- a/apps/plugins/zxbox/keymaps.h
+++ b/apps/plugins/zxbox/keymaps.h
@@ -262,6 +262,14 @@
#define ZX_RIGHT BUTTON_RIGHT
#define ZX_SELECT BUTTON_SELECT
+#elif CONFIG_KEYPAD == DX50_PAD
+#define ZX_MENU BUTTON_POWER
+#define ZX_UP BUTTON_VOL_UP
+#define ZX_DOWN BUTTON_VOL_DOWN
+#define ZX_SELECT BUTTON_PLAY
+#define ZX_LEFT BUTTON_LEFT
+#define ZX_RIGHT BUTTON_RIGHT
+
#else
#error Keymap not defined!
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 7ec803f585..f1b5017751 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -792,13 +792,13 @@ void root_menu(void)
case GO_TO_ROOT:
if (last_screen != GO_TO_ROOT)
selected = get_selection(last_screen);
-#if (CONFIG_PLATFORM&PLATFORM_ANDROID)
+#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined(DX50) && !defined(DX90)
/* When we are in the main menu we want the hardware BACK
* button to be handled by Android instead of rockbox */
android_ignore_back_button(true);
#endif
next_screen = do_menu(&root_menu_, &selected, NULL, false);
-#if (CONFIG_PLATFORM&PLATFORM_ANDROID)
+#if (CONFIG_PLATFORM&PLATFORM_ANDROID) && !defined(DX50) && !defined(DX90)
android_ignore_back_button(false);
#endif
if (next_screen != GO_TO_PREVIOUS)
diff --git a/firmware/SOURCES b/firmware/SOURCES
index 070f0d4a62..950e4f2bcf 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1811,18 +1811,28 @@ target/arm/rk27xx/ihifi/powermgmt-ihifi960.c
target/hosted/kernel-unix.c
target/hosted/filesystem-unix.c
target/hosted/lc-unix.c
+#if !defined(DX50) && !defined(DX90)
target/hosted/android/lcd-android.c
target/hosted/android/button-android.c
-#ifdef DEBUG
-target/hosted/android/debug-android.c
-#endif
target/hosted/android/pcm-android.c
target/hosted/android/powermgmt-android.c
-target/hosted/android/system-android.c
target/hosted/android/telephony-android.c
#ifdef APPLICATION
target/hosted/android/app/button-application.c
#endif
+#else
+drivers/lcd-memframe.c
+target/hosted/android/dx50/pcm-dx50.c
+target/hosted/android/dx50/tinyalsa/pcm.c
+target/hosted/android/dx50/powermgmt-dx50.c
+target/hosted/android/dx50/backlight-dx50.c
+target/hosted/android/dx50/button-dx50.c
+target/hosted/android/dx50/lcd-dx50.c
+#endif
+#ifdef DEBUG
+target/hosted/android/debug-android.c
+#endif
+target/hosted/android/system-android.c
drivers/audio/android.c
#endif
diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES
index ebb6951071..f16285e623 100644
--- a/firmware/asm/SOURCES
+++ b/firmware/asm/SOURCES
@@ -14,7 +14,7 @@ mempcpy.c
#if (defined(SANSA_E200) || defined(GIGABEAT_F) || defined(GIGABEAT_S) || \
defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \
defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \
- defined(SAMSUNG_YPR1) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \
+ defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \
defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI)) && \
!defined(SIMULATOR)
#if LCD_DEPTH == 24
diff --git a/firmware/asm/arm/thread.h b/firmware/asm/arm/thread.h
index 7b8ebc2041..533a088979 100644
--- a/firmware/asm/arm/thread.h
+++ b/firmware/asm/arm/thread.h
@@ -31,7 +31,11 @@ struct regs
#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
#include <errno.h>
+#if defined(DX50) || defined (DX90)
+ #define DEFAULT_STACK_SIZE 0x2000 /* Bytes */
+#else
#define DEFAULT_STACK_SIZE 0x1000 /* Bytes */
+#endif
#else
#define DEFAULT_STACK_SIZE 0x400 /* Bytes */
#endif
diff --git a/firmware/drivers/audio/android.c b/firmware/drivers/audio/android.c
index 7a5f34ea48..f26087470b 100644
--- a/firmware/drivers/audio/android.c
+++ b/firmware/drivers/audio/android.c
@@ -22,12 +22,34 @@
#include "config.h"
#include "audiohw.h"
+#if defined(DX50) || defined(DX90)
+#include "system.h"
+#include "pcm_sw_volume.h"
+#endif
+#if defined(DX50) || defined(DX90)
+void audiohw_set_volume(int vol_l, int vol_r)
+{
+ int hw_volume;
+ hw_volume = MAX(vol_l, vol_r);
+
+#ifdef HAVE_SW_VOLUME_CONTROL
+ vol_l-=hw_volume;
+ vol_r-=hw_volume;
+ pcm_set_master_volume(vol_l, vol_r);
+#endif
+
+ extern void pcm_set_mixer_volume(int);
+ pcm_set_mixer_volume(hw_volume);
+
+}
+#else
void audiohw_set_volume(int volume)
{
extern void pcm_set_mixer_volume(int);
pcm_set_mixer_volume(volume);
}
+#endif
void audiohw_set_balance(int balance)
{
@@ -36,6 +58,8 @@ void audiohw_set_balance(int balance)
void audiohw_close(void)
{
+#if !defined(DX50) && !defined(DX90)
extern void pcm_shutdown(void);
pcm_shutdown();
+#endif
}
diff --git a/firmware/drivers/touchscreen.c b/firmware/drivers/touchscreen.c
index 42ddf7ec47..572f05ab7f 100644
--- a/firmware/drivers/touchscreen.c
+++ b/firmware/drivers/touchscreen.c
@@ -188,7 +188,7 @@ bool touchscreen_is_enabled(void)
}
#endif
-#if ((CONFIG_PLATFORM & PLATFORM_ANDROID) == 0)
+#if ((CONFIG_PLATFORM & PLATFORM_ANDROID) == 0) || defined(DX50) || defined(DX90)
/* android has an API for this */
#define TOUCH_SLOP 16u
diff --git a/firmware/export/config.h b/firmware/export/config.h
index a56dd32303..bf95dc4c09 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -164,6 +164,7 @@
#define IHIFI_PAD 60
#define SAMSUNG_YPR1_PAD 61
#define SAMSUNG_YH920_PAD 62
+#define DX50_PAD 63
/* CONFIG_REMOTE_KEYPAD */
#define H100_REMOTE 1
@@ -575,6 +576,10 @@ Lyre prototype 1 */
#include "config/creativezenxfistyle.h"
#elif defined(SAMSUNG_YPR1)
#include "config/samsungypr1.h"
+#elif defined(DX50)
+#include "config/ibassodx50.h"
+#elif defined(DX90)
+#include "config/ibassodx90.h"
#else
/* no known platform */
#endif
diff --git a/firmware/export/config/ibassodx50.h b/firmware/export/config/ibassodx50.h
new file mode 100644
index 0000000000..652377cc6c
--- /dev/null
+++ b/firmware/export/config/ibassodx50.h
@@ -0,0 +1,136 @@
+/*
+ * This config file is for Rockbox as an application on Android
+ */
+
+/* We don't run on hardware directly */
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
+
+/* For Rolo and boot loader */
+#define MODEL_NUMBER 94
+
+#define MODEL_NAME "iBasso DX50"
+
+#define USB_NONE
+
+/* define this if you have a bitmap LCD display */
+#define HAVE_LCD_BITMAP
+
+/* define this if you have a colour LCD */
+#define HAVE_LCD_COLOR
+
+/* define this if 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
+
+/* LCD dimensions */
+#define LCD_WIDTH 320
+#define LCD_HEIGHT 240
+#define LCD_DPI 166
+#define LCD_DEPTH 16
+#define LCD_PIXELFORMAT RGB565
+
+#define HAVE_LCD_ENABLE
+
+/* define this to indicate your device's keypad */
+#define HAVE_TOUCHSCREEN
+#define HAVE_BUTTON_DATA
+
+/* define this if you have RTC RAM available for settings */
+//#define HAVE_RTC_RAM
+
+/* define this if you have a real-time clock */
+//#define CONFIG_RTC APPLICATION
+
+/* Define this if you have a software controlled poweroff */
+#define HAVE_SW_POWEROFF
+
+/* The number of bytes reserved for loadable codecs */
+#define CODEC_SIZE 0x100000
+
+/* The number of bytes reserved for loadable plugins */
+#define PLUGIN_BUFFER_SIZE 0x160000
+
+#define AB_REPEAT_ENABLE
+
+/* Define this for LCD backlight available */
+#define HAVE_BACKLIGHT
+#define HAVE_BACKLIGHT_BRIGHTNESS
+
+/* Main LCD backlight brightness range and defaults */
+#define MIN_BRIGHTNESS_SETTING 4
+#define MAX_BRIGHTNESS_SETTING 255
+#define DEFAULT_BRIGHTNESS_SETTING 255
+
+/* Which backlight fading type? */
+#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
+
+/* Define this if you do software codec */
+#define CONFIG_CODEC SWCODEC
+
+//#define HAVE_MULTIMEDIA_KEYS
+#define CONFIG_KEYPAD DX50_PAD
+
+/* define this if the target has volume keys which can be used in the lists */
+#define HAVE_VOLUME_IN_LIST
+
+/* define this if the host platform can change volume outside of rockbox */
+//#define PLATFORM_HAS_VOLUME_CHANGE
+
+#define HAVE_SW_TONE_CONTROLS
+
+#define HAVE_SW_VOLUME_CONTROL
+
+#define BATTERY_CAPACITY_DEFAULT 2100 /* default battery capacity */
+#define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC 50 /* capacity increment */
+#define BATTERY_TYPES_COUNT 1 /* only one type */
+
+#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE
+
+#define CONFIG_CHARGING CHARGING_SIMPLE
+
+#define NO_LOW_BATTERY_SHUTDOWN
+
+/* Define current usage levels. */
+#define CURRENT_NORMAL 210 /* 10 hours from a 2100 mAh battery */
+#define CURRENT_BACKLIGHT 30 /* TBD */
+#define CURRENT_RECORD 0 /* no recording */
+
+/* Define this to the CPU frequency */
+/*
+#define CPU_FREQ 48000000
+*/
+
+/* define this if the hardware can be powered off while charging */
+#define HAVE_POWEROFF_WHILE_CHARGING
+
+
+/* Offset ( in the firmware file's header ) to the file CRC */
+#define FIRMWARE_OFFSET_FILE_CRC 0
+
+/* Offset ( in the firmware file's header ) to the real data */
+#define FIRMWARE_OFFSET_FILE_DATA 8
+
+#define CONFIG_LCD LCD_COWOND2
+
+/* Define this if a programmable hotkey is mapped */
+#define HAVE_HOTKEY
+
+#define BOOTDIR "/.rockbox"
+
+/* No special storage */
+#define CONFIG_STORAGE STORAGE_HOSTFS
+#define HAVE_STORAGE_FLUSH
+
diff --git a/firmware/export/config/ibassodx90.h b/firmware/export/config/ibassodx90.h
new file mode 100644
index 0000000000..d560f3e10b
--- /dev/null
+++ b/firmware/export/config/ibassodx90.h
@@ -0,0 +1,136 @@
+/*
+ * This config file is for Rockbox as an application on Android
+ */
+
+/* We don't run on hardware directly */
+#define CONFIG_PLATFORM (PLATFORM_HOSTED|PLATFORM_ANDROID)
+
+/* For Rolo and boot loader */
+#define MODEL_NUMBER 95
+
+#define MODEL_NAME "iBasso DX90"
+
+#define USB_NONE
+
+/* define this if you have a bitmap LCD display */
+#define HAVE_LCD_BITMAP
+
+/* define this if you have a colour LCD */
+#define HAVE_LCD_COLOR
+
+/* define this if 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
+
+/* LCD dimensions */
+#define LCD_WIDTH 320
+#define LCD_HEIGHT 240
+#define LCD_DPI 166
+#define LCD_DEPTH 16
+#define LCD_PIXELFORMAT RGB565
+
+#define HAVE_LCD_ENABLE
+
+/* define this to indicate your device's keypad */
+#define HAVE_TOUCHSCREEN
+#define HAVE_BUTTON_DATA
+
+/* define this if you have RTC RAM available for settings */
+//#define HAVE_RTC_RAM
+
+/* define this if you have a real-time clock */
+//#define CONFIG_RTC APPLICATION
+
+/* Define this if you have a software controlled poweroff */
+#define HAVE_SW_POWEROFF
+
+/* The number of bytes reserved for loadable codecs */
+#define CODEC_SIZE 0x100000
+
+/* The number of bytes reserved for loadable plugins */
+#define PLUGIN_BUFFER_SIZE 0x160000
+
+#define AB_REPEAT_ENABLE
+
+/* Define this for LCD backlight available */
+#define HAVE_BACKLIGHT
+#define HAVE_BACKLIGHT_BRIGHTNESS
+
+/* Main LCD backlight brightness range and defaults */
+#define MIN_BRIGHTNESS_SETTING 4
+#define MAX_BRIGHTNESS_SETTING 255
+#define DEFAULT_BRIGHTNESS_SETTING 255
+
+/* Which backlight fading type? */
+#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING
+
+/* Define this if you do software codec */
+#define CONFIG_CODEC SWCODEC
+
+//#define HAVE_MULTIMEDIA_KEYS
+#define CONFIG_KEYPAD DX50_PAD
+
+/* define this if the target has volume keys which can be used in the lists */
+#define HAVE_VOLUME_IN_LIST
+
+/* define this if the host platform can change volume outside of rockbox */
+//#define PLATFORM_HAS_VOLUME_CHANGE
+
+#define HAVE_SW_TONE_CONTROLS
+
+#define HAVE_SW_VOLUME_CONTROL
+
+#define BATTERY_CAPACITY_DEFAULT 2100 /* default battery capacity */
+#define BATTERY_CAPACITY_MIN 1700 /* min. capacity selectable */
+#define BATTERY_CAPACITY_MAX 3200 /* max. capacity selectable */
+#define BATTERY_CAPACITY_INC 50 /* capacity increment */
+#define BATTERY_TYPES_COUNT 1 /* only one type */
+
+#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE
+
+#define CONFIG_CHARGING CHARGING_SIMPLE
+
+#define NO_LOW_BATTERY_SHUTDOWN
+
+/* Define current usage levels. */
+#define CURRENT_NORMAL 210 /* 10 hours from a 2100 mAh battery */
+#define CURRENT_BACKLIGHT 30 /* TBD */
+#define CURRENT_RECORD 0 /* no recording */
+
+/* Define this to the CPU frequency */
+/*
+#define CPU_FREQ 48000000
+*/
+
+/* define this if the hardware can be powered off while charging */
+#define HAVE_POWEROFF_WHILE_CHARGING
+
+
+/* Offset ( in the firmware file's header ) to the file CRC */
+#define FIRMWARE_OFFSET_FILE_CRC 0
+
+/* Offset ( in the firmware file's header ) to the real data */
+#define FIRMWARE_OFFSET_FILE_DATA 8
+
+#define CONFIG_LCD LCD_COWOND2
+
+/* Define this if a programmable hotkey is mapped */
+#define HAVE_HOTKEY
+
+#define BOOTDIR "/.rockbox"
+
+/* No special storage */
+#define CONFIG_STORAGE STORAGE_HOSTFS
+#define HAVE_STORAGE_FLUSH
+
diff --git a/firmware/export/hosted_codec.h b/firmware/export/hosted_codec.h
index f5e92ed297..00ab099772 100644
--- a/firmware/export/hosted_codec.h
+++ b/firmware/export/hosted_codec.h
@@ -25,7 +25,9 @@
&& !(CONFIG_PLATFORM & PLATFORM_MAEMO5)
AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -80, 0, 0)
#else
+#if !defined(DX50) && !defined(DX90)
#define AUDIOHW_CAPS (MONO_VOL_CAP)
+#endif
AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -99, 0, 0)
#endif /* CONFIG_PLATFORM & PLATFORM_SDL */
@@ -50,4 +52,4 @@ AUDIOHW_SETTING(TREBLE_CUTOFF, "", 0, 1, 1, 4, 1)
#endif
#endif /* CONFIG_PLATFORM & PLATFORM_ANDROID */
-#endif /* HOSTED_CODEC_H */ \ No newline at end of file
+#endif /* HOSTED_CODEC_H */
diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c
index b6d4b9f66e..a4b260b315 100644
--- a/firmware/powermgmt.c
+++ b/firmware/powermgmt.c
@@ -679,6 +679,8 @@ static void power_thread(void)
/* Delay reading the first battery level */
#ifdef MROBE_100
while (_battery_voltage() > 4200) /* gives false readings initially */
+#elif defined(DX50) || defined(DX90)
+ while (_battery_voltage() < 1) /* can give false readings initially */
#endif
{
sleep(HZ/100);
diff --git a/firmware/target/hosted/android/dx50/adc-target.h b/firmware/target/hosted/android/dx50/adc-target.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/adc-target.h
diff --git a/firmware/target/hosted/android/dx50/backlight-dx50.c b/firmware/target/hosted/android/dx50/backlight-dx50.c
new file mode 100644
index 0000000000..98dbcb8abe
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/backlight-dx50.c
@@ -0,0 +1,76 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2011 by Lorenzo Miori
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include "system.h"
+#include "backlight.h"
+#include "backlight-target.h"
+#include "lcd.h"
+#include "lcd-target.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include "unistd.h"
+
+bool _backlight_init(void)
+{
+ /* We have nothing to do */
+ return true;
+}
+
+void _backlight_on(void)
+{
+ FILE *f = fopen("/sys/power/state", "w");
+ fputs("on", f);
+ fclose(f);
+ lcd_enable(true);
+}
+
+void _backlight_off(void)
+{
+ FILE * f;
+
+ /* deny the player to sleep deep */
+ f = fopen("/sys/power/wake_lock", "w");
+ fputs("player", f);
+ fclose(f);
+
+ /* deny the player to mute */
+ f = fopen("/sys/class/codec/wm8740_mute", "w");
+ fputc(0, f);
+ fclose(f);
+
+ /* turn off backlight */
+ f = fopen("/sys/power/state", "w");
+ fputs("mem", f);
+ fclose(f);
+
+}
+
+void _backlight_set_brightness(int brightness)
+{
+ /* Just another check... */
+ if (brightness > MAX_BRIGHTNESS_SETTING)
+ brightness = MAX_BRIGHTNESS_SETTING;
+ if (brightness < MIN_BRIGHTNESS_SETTING)
+ brightness = MIN_BRIGHTNESS_SETTING;
+
+ FILE *f = fopen("/sys/devices/platform/rk29_backlight/backlight/rk28_bl/brightness", "w");
+ fprintf(f, "%d", brightness);
+ fclose(f);
+}
diff --git a/firmware/target/hosted/android/dx50/backlight-target.h b/firmware/target/hosted/android/dx50/backlight-target.h
new file mode 100644
index 0000000000..67836aa790
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/backlight-target.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Maurus Cuelenaere
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef BACKLIGHT_TARGET_H
+#define BACKLIGHT_TARGET_H
+
+#include <stdbool.h>
+
+bool _backlight_init(void);
+void _backlight_on(void);
+void _backlight_off(void);
+void _backlight_set_brightness(int brightness);
+
+#endif /* BACKLIGHT_TARGET_H */
diff --git a/firmware/target/hosted/android/dx50/button-dx50.c b/firmware/target/hosted/android/dx50/button-dx50.c
new file mode 100644
index 0000000000..5ab58ce420
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/button-dx50.c
@@ -0,0 +1,314 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#include <stdbool.h>
+#include "button.h"
+#include "buttonmap.h"
+#include "config.h"
+#include "kernel.h"
+#include "system.h"
+#include "touchscreen.h"
+#include "powermgmt.h"
+#include "backlight.h"
+
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/inotify.h>
+#include <sys/limits.h>
+#include <sys/poll.h>
+#include <errno.h>
+
+
+static struct pollfd *ufds;
+static char **device_names;
+static int nfds;
+
+enum {
+ PRINT_DEVICE_ERRORS = 1U << 0,
+ PRINT_DEVICE = 1U << 1,
+ PRINT_DEVICE_NAME = 1U << 2,
+ PRINT_DEVICE_INFO = 1U << 3,
+ PRINT_VERSION = 1U << 4,
+ PRINT_POSSIBLE_EVENTS = 1U << 5,
+ PRINT_INPUT_PROPS = 1U << 6,
+ PRINT_HID_DESCRIPTOR = 1U << 7,
+
+ PRINT_ALL_INFO = (1U << 8) - 1,
+
+ PRINT_LABELS = 1U << 16,
+};
+
+static int last_y, last_x;
+static int last_btns;
+
+static enum {
+ STATE_UNKNOWN,
+ STATE_UP,
+ STATE_DOWN
+} last_touch_state = STATE_UNKNOWN;
+
+
+static int open_device(const char *device, int print_flags)
+{
+ int fd;
+ struct pollfd *new_ufds;
+ char **new_device_names;
+
+ fd = open(device, O_RDWR);
+ if(fd < 0) {
+ if(print_flags & PRINT_DEVICE_ERRORS)
+ fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
+ return -1;
+ }
+
+ new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
+ if(new_ufds == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return -1;
+ }
+ ufds = new_ufds;
+ new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
+ if(new_device_names == NULL) {
+ fprintf(stderr, "out of memory\n");
+ return -1;
+ }
+ device_names = new_device_names;
+
+ ufds[nfds].fd = fd;
+ ufds[nfds].events = POLLIN;
+ device_names[nfds] = strdup(device);
+ nfds++;
+
+ return 0;
+}
+
+
+
+static int scan_dir(const char *dirname, int print_flags)
+{
+ char devname[PATH_MAX];
+ char *filename;
+ DIR *dir;
+ struct dirent *de;
+ dir = opendir(dirname);
+ if(dir == NULL)
+ return -1;
+ strcpy(devname, dirname);
+ filename = devname + strlen(devname);
+ *filename++ = '/';
+ while((de = readdir(dir))) {
+ if(de->d_name[0] == '.' &&
+ (de->d_name[1] == '\0' ||
+ (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+ continue;
+ strcpy(filename, de->d_name);
+ open_device(devname, print_flags);
+ }
+ closedir(dir);
+ return 0;
+}
+
+bool _hold;
+
+bool button_hold()
+{
+ FILE *f = fopen("/sys/class/axppower/holdkey", "r");
+ char x;
+ fscanf(f, "%c", &x);
+ fclose(f);
+ _hold = !(x&STATE_UNLOCKED);
+ return _hold;
+}
+
+
+void button_init_device(void)
+{
+ int res;
+ int print_flags = 0;
+ const char *device = NULL;
+ const char *device_path = "/dev/input";
+
+ nfds = 1;
+ ufds = calloc(1, sizeof(ufds[0]));
+ ufds[0].fd = inotify_init();
+ ufds[0].events = POLLIN;
+ if(device) {
+ res = open_device(device, print_flags);
+ if(res < 0) {
+ // return 1;
+ }
+ } else {
+ res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
+ if(res < 0) {
+ fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
+ // return 1;
+ }
+ res = scan_dir(device_path, print_flags);
+ if(res < 0) {
+ fprintf(stderr, "scan dir failed for %s\n", device_path);
+ // return 1;
+ }
+ }
+
+ button_hold(); //store state
+
+ set_rockbox_ready();
+}
+
+void touchscreen_enable_device(bool en)
+{
+ (void)en; /* FIXME: do something smart */
+}
+
+
+int keycode_to_button(int keyboard_key)
+{
+ switch(keyboard_key){
+ case KEYCODE_PWR:
+ return BUTTON_POWER;
+
+ case KEYCODE_PWR_LONG:
+ return BUTTON_POWER_LONG;
+
+ case KEYCODE_VOLPLUS:
+ return BUTTON_VOL_UP;
+
+ case KEYCODE_VOLMINUS:
+ return BUTTON_VOL_DOWN;
+
+ case KEYCODE_PREV:
+ return BUTTON_LEFT;
+
+ case KEYCODE_NEXT:
+ return BUTTON_RIGHT;
+
+ case KEYCODE_PLAY:
+ return BUTTON_PLAY;
+
+ case KEYCODE_HOLD:
+ button_hold(); /* store state */
+ backlight_hold_changed(_hold);
+ return BUTTON_NONE;
+
+ default:
+ return BUTTON_NONE;
+ }
+}
+
+
+int button_read_device(int *data)
+{
+ int i;
+ int res;
+ struct input_event event;
+ int read_more;
+ unsigned button = 0;
+
+ if(last_btns & BUTTON_POWER_LONG)
+ {
+ return last_btns; /* simulate repeat */
+ }
+
+ do {
+ read_more = 0;
+ poll(ufds, nfds, 10);
+ for(i = 1; i < nfds; i++) {
+ if(ufds[i].revents & POLLIN) {
+ res = read(ufds[i].fd, &event, sizeof(event));
+ if(res < (int)sizeof(event)) {
+ fprintf(stderr, "could not get event\n");
+ }
+
+ switch(event.type)
+ {
+ case 1: /* HW-Button */
+ button = keycode_to_button(event.code);
+ if (_hold) /* we have to wait for keycode_to_button() first to maybe clear hold state */
+ break;
+ if (button == BUTTON_NONE)
+ {
+ last_btns = button;
+ break;
+ }
+/* workaround for a wrong feedback, only present with DX90 */
+#if defined(DX90)
+ if (button == BUTTON_RIGHT && (last_btns & BUTTON_LEFT == BUTTON_LEFT) && !event.value)
+ {
+ button = BUTTON_LEFT;
+ }
+#endif
+ if (event.value)
+ last_btns |= button;
+ else
+ last_btns &= (~button);
+
+ break;
+
+ case 3: /* Touchscreen */
+ if(_hold)
+ break;
+
+ switch(event.code)
+ {
+ case 53: /* x -> next will be y */
+ last_x = event.value;
+ read_more = 1;
+ break;
+ case 54: /* y */
+ last_y = event.value;
+ break;
+ case 57: /* press -> next will be x */
+ if(event.value==1)
+ {
+ last_touch_state = STATE_DOWN;
+ read_more = 1;
+ }
+ else
+ last_touch_state = STATE_UP;
+ break;
+ }
+ break;
+ }
+ }
+ }
+ } while(read_more);
+
+
+ /* Get grid button/coordinates based on the current touchscreen mode
+ *
+ * Caveat: the caller seemingly depends on *data always being filled with
+ * the last known touchscreen position, so always call
+ * touchscreen_to_pixels() */
+ int touch = touchscreen_to_pixels(last_x, last_y, data);
+
+ if (last_touch_state == STATE_DOWN)
+ return last_btns | touch;
+
+ return last_btns;
+}
+
diff --git a/firmware/target/hosted/android/dx50/button-target.h b/firmware/target/hosted/android/dx50/button-target.h
new file mode 100644
index 0000000000..adc9cf6bfd
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/button-target.h
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Rob Purchase
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.r
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _BUTTON_TARGET_H_
+#define _BUTTON_TARGET_H_
+
+#include <stdbool.h>
+
+#define HAS_BUTTON_HOLD
+
+/* Main unit's buttons */
+#define BUTTON_LEFT 0x00000001
+#define BUTTON_RIGHT 0x00000002
+#define BUTTON_PLAY 0x00000004
+#define BUTTON_POWER 0x00000008
+#define BUTTON_VOL_UP 0x00000010
+#define BUTTON_VOL_DOWN 0x00000020
+#define BUTTON_POWER_LONG 0x00000040
+
+#define BUTTON_MAIN (BUTTON_LEFT|BUTTON_VOL_UP|BUTTON_VOL_DOWN\
+ |BUTTON_RIGHT|BUTTON_PLAY|BUTTON_POWER|BUTTON_POWER_LONG)
+
+#define KEYCODE_LINEOUT 113
+#define KEYCODE_SPDIF 114
+#define KEYCODE_HOLD 115
+#define KEYCODE_PWR 116
+#define KEYCODE_PWR_LONG 117
+#define KEYCODE_SD 143
+#define KEYCODE_VOLPLUS 158
+#define KEYCODE_VOLMINUS 159
+#define KEYCODE_PREV 160
+#define KEYCODE_NEXT 162
+#define KEYCODE_PLAY 161
+#define STATE_UNLOCKED 16
+#define STATE_SPDIF_UNPLUGGED 32
+#define STATE_LINEOUT_UNPLUGGED 64
+
+/* Touch Screen Area Buttons */
+#define BUTTON_TOPLEFT 0x00001000
+#define BUTTON_TOPMIDDLE 0x00002000
+#define BUTTON_TOPRIGHT 0x00004000
+#define BUTTON_MIDLEFT 0x00008000
+#define BUTTON_CENTER 0x00010000
+#define BUTTON_MIDRIGHT 0x00020000
+#define BUTTON_BOTTOMLEFT 0x00040000
+#define BUTTON_BOTTOMMIDDLE 0x00080000
+#define BUTTON_BOTTOMRIGHT 0x00100000
+
+
+/* Software power-off */
+#define POWEROFF_BUTTON BUTTON_POWER_LONG
+#define POWEROFF_COUNT 0
+
+#endif /* _BUTTON_TARGET_H_ */
diff --git a/firmware/target/hosted/android/dx50/lcd-dx50.c b/firmware/target/hosted/android/dx50/lcd-dx50.c
new file mode 100644
index 0000000000..4d78baaf00
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/lcd-dx50.c
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: lcd-bitmap.c 29248 2011-02-08 20:05:25Z thomasjfox $
+ *
+ * Copyright (C) 2011 Lorenzo Miori, Thomas Martitz
+ * Copyright (C) 2013 Lorenzo Miori
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <linux/fb.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "config.h"
+#include "file.h"
+#include "debug.h"
+#include "system.h"
+#include "screendump.h"
+#include "lcd.h"
+#include "lcd-target.h"
+
+static int dev_fd = 0;
+fb_data *dev_fb = 0;
+
+#ifdef HAVE_LCD_SHUTDOWN
+void lcd_shutdown(void)
+{
+ printf("FB closed.");
+ munmap(dev_fb, FRAMEBUFFER_SIZE);
+ close(dev_fd);
+}
+#endif
+
+void lcd_init_device(void)
+{
+ size_t screensize;
+ struct fb_var_screeninfo vinfo;
+ struct fb_fix_screeninfo finfo;
+
+ /* Open the framebuffer device */
+ dev_fd = open("/dev/graphics/fb0", O_RDWR);
+ if (dev_fd == -1) {
+ perror("Error: cannot open framebuffer device");
+ exit(1);
+ }
+
+ /* Get the fixed properties */
+ if (ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo) == -1) {
+ perror("Error reading fixed information");
+ exit(2);
+ }
+
+
+ /* Now we get the settable settings, and we set 16 bit bpp */
+ if (ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) == -1) {
+ perror("Error reading variable information");
+ exit(3);
+ }
+ /* framebuffer does not fit the screen, a bug of iBassos Firmware, not rockbox.
+ cannot be solved with parameters */
+ vinfo.bits_per_pixel = LCD_DEPTH;
+ vinfo.xres = vinfo.xres_virtual = vinfo.width = LCD_WIDTH;
+ vinfo.yres = vinfo.yres_virtual = vinfo.height = LCD_HEIGHT;
+
+ if (ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo)) {
+ perror("fbset(ioctl)");
+ exit(4);
+ }
+
+ /* Figure out the size of the screen in bytes */
+ screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
+ if (screensize != FRAMEBUFFER_SIZE) {
+ exit(4);
+ perror("Display and framebuffer mismatch!\n");
+ }
+
+ /* Map the device to memory */
+ dev_fb = mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0);
+ if ((int)dev_fb == -1) {
+ perror("Error: failed to map framebuffer device to memory");
+ exit(4);
+ }
+
+ /* Be sure to turn on display at startup */
+ ioctl(dev_fd, FBIOBLANK, VESA_NO_BLANKING);
+#ifdef HAVE_LCD_ENABLE
+ lcd_set_active(true);
+#endif
+}
+
+#ifdef HAVE_LCD_ENABLE
+void lcd_enable(bool enable)
+ {
+ if (lcd_active() == enable)
+ return;
+
+ lcd_set_active(enable);
+
+ /* Turn on or off the display using Linux interface */
+ ioctl(dev_fd, FBIOBLANK, enable ? VESA_NO_BLANKING : VESA_POWERDOWN);
+
+ if (enable)
+ send_event(LCD_EVENT_ACTIVATION, NULL);
+}
+#endif
diff --git a/firmware/target/hosted/android/dx50/lcd-target.h b/firmware/target/hosted/android/dx50/lcd-target.h
new file mode 100644
index 0000000000..900350eca2
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/lcd-target.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * 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__
+
+extern fb_data *dev_fb;
+#define LCD_FRAMEBUF_ADDR(col, row) (dev_fb + row*LCD_WIDTH + col)
+#ifdef HAVE_LCD_ENABLE
+extern void lcd_set_active(bool active);
+extern void lcd_enable(bool enable);
+#endif
+#endif
diff --git a/firmware/target/hosted/android/dx50/pcm-dx50.c b/firmware/target/hosted/android/dx50/pcm-dx50.c
new file mode 100644
index 0000000000..e7695873a0
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/pcm-dx50.c
@@ -0,0 +1,364 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+/*
+ * Based, but heavily modified, on the example given at
+ * http://www.alsa-project.org/alsa-doc/alsa-lib/_2test_2pcm_8c-example.html
+ *
+ * This driver uses the so-called unsafe async callback method and hardcoded device
+ * names. It fails when the audio device is busy by other apps.
+ *
+ * To make the async callback safer, an alternative stack is installed, since
+ * it's run from a signal hanlder (which otherwise uses the user stack). If
+ * tick tasks are run from a signal handler too, please install
+ * an alternative stack for it too.
+ *
+ * TODO: Rewrite this to do it properly with multithreading
+ *
+ * Alternatively, a version using polling in a tick task is provided. While
+ * supposedly safer, it appears to use more CPU (however I didn't measure it
+ * accurately, only looked at htop). At least, in this mode the "default"
+ * device works which doesnt break with other apps running.
+ */
+
+
+#include "autoconf.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <errno.h>
+#include "tinyalsa/asoundlib.h"
+#include "tinyalsa/asound.h"
+#include "system.h"
+#include "debug.h"
+#include "kernel.h"
+
+#include "pcm.h"
+#include "pcm-internal.h"
+#include "pcm_mixer.h"
+#include "pcm_sampr.h"
+#include "audiohw.h"
+
+#include <pthread.h>
+#include <signal.h>
+
+static const snd_pcm_format_t format = PCM_FORMAT_S16_LE; /* sample format */
+static const int channels = 2; /* count of channels */
+static unsigned int rate = 44100; /* stream rate */
+
+typedef struct pcm snd_pcm_t;
+static snd_pcm_t *handle;
+struct pcm_config config;
+
+static snd_pcm_sframes_t period_size = 512; /* if set to >= 1024, all timers become even slower */
+static char *frames;
+
+static const void *pcm_data = 0;
+static size_t pcm_size = 0;
+
+static int recursion;
+
+static int set_hwparams(snd_pcm_t *handle)
+{
+ int err;
+ if (!frames)
+ frames = malloc(pcm_frames_to_bytes(handle, pcm_get_buffer_size(handle)));
+ err = 0; /* success */
+ return err;
+}
+
+
+/* copy pcm samples to a spare buffer, suitable for snd_pcm_writei() */
+static bool fill_frames(void)
+{
+ size_t copy_n, frames_left = period_size;
+ bool new_buffer = false;
+
+ while (frames_left > 0)
+ {
+ if (!pcm_size)
+ {
+ new_buffer = true;
+ if (!pcm_play_dma_complete_callback(PCM_DMAST_OK, &pcm_data,
+ &pcm_size))
+ {
+ return false;
+ }
+ }
+ copy_n = MIN((size_t)pcm_size, pcm_frames_to_bytes(handle, frames_left));
+ memcpy(&frames[pcm_frames_to_bytes(handle, period_size-frames_left)], pcm_data, copy_n);
+
+ pcm_data += copy_n;
+ pcm_size -= copy_n;
+ frames_left -= pcm_bytes_to_frames(handle, copy_n);
+
+ if (new_buffer)
+ {
+ new_buffer = false;
+ pcm_play_dma_status_callback(PCM_DMAST_STARTED);
+ }
+ }
+ return true;
+}
+
+
+static void pcm_tick(void)
+{
+ if (fill_frames())
+ {
+ if (pcm_write(handle, frames, pcm_frames_to_bytes(handle, period_size))) {
+ printf("Error playing sample\n");
+ return;//break;
+ }
+
+ }
+ else
+ {
+ DEBUGF("%s: No Data.\n", __func__);
+ return;//break;
+ }
+}
+
+static int async_rw(snd_pcm_t *handle)
+{
+ int err;
+ snd_pcm_sframes_t sample_size;
+ char *samples;
+
+ /* fill buffer with silence to initiate playback without noisy click */
+ sample_size = pcm_frames_to_bytes(handle, pcm_get_buffer_size(handle));
+ samples = malloc(sample_size);
+
+ memset(samples, 0, sample_size);
+
+ err = pcm_write(handle, samples, sample_size);
+ free(samples);
+
+ if (err != 0)
+ {
+ DEBUGF("Initial write error: %d\n", err);
+ return err;
+ }
+ if (pcm_state(handle) == PCM_STATE_PREPARED)
+ {
+ err = pcm_start(handle);
+ if (err < 0)
+ {
+ DEBUGF("Start error: %d\n", err);
+ return err;
+ }
+ }
+ return 0;
+}
+
+void cleanup(void)
+{
+ free(frames);
+ frames = NULL;
+ pcm_close(handle);
+}
+
+void pcm_play_dma_init(void)
+{
+ config.channels = channels;
+ config.rate = rate;
+ config.period_size = period_size;
+ config.period_count = 4;
+ config.format = format;
+ config.start_threshold = 0;
+ config.stop_threshold = 0;
+ config.silence_threshold = 0;
+
+
+ handle = pcm_open(0, 0, PCM_OUT, &config);
+ if (!handle || !pcm_is_ready(handle)) {
+ printf("Unable to open PCM device: %s\n", pcm_get_error(handle));
+ return;
+ }
+
+ pcm_dma_apply_settings();
+
+ tick_add_task(pcm_tick);
+
+ atexit(cleanup);
+ return;
+}
+
+
+void pcm_play_lock(void)
+{
+ if (recursion++ == 0)
+ tick_remove_task(pcm_tick);
+}
+
+void pcm_play_unlock(void)
+{
+ if (--recursion == 0)
+ tick_add_task(pcm_tick);
+}
+
+static void pcm_dma_apply_settings_nolock(void)
+{
+ set_hwparams(handle);
+}
+
+void pcm_dma_apply_settings(void)
+{
+ pcm_play_lock();
+ pcm_dma_apply_settings_nolock();
+ pcm_play_unlock();
+}
+
+
+void pcm_play_dma_pause(bool pause)
+{
+ (void)pause;
+}
+
+
+void pcm_play_dma_stop(void)
+{
+ pcm_stop(handle);
+}
+
+void pcm_play_dma_start(const void *addr, size_t size)
+{
+#if defined(DX50) || defined(DX90)
+ /* headphone output relay: if this is done at startup already, a loud click is audible on headphones. Here, some time later,
+ the output caps are charged a bit and the click is much softer */
+ system("/system/bin/muteopen");
+#endif
+ pcm_dma_apply_settings_nolock();
+
+ pcm_data = addr;
+ pcm_size = size;
+
+ while (1)
+ {
+ snd_pcm_state_t state = pcm_state(handle);
+ switch (state)
+ {
+ case PCM_STATE_RUNNING:
+ return;
+ case PCM_STATE_XRUN:
+ {
+ printf("No handler for STATE_XRUN!\n");
+ continue;
+ }
+ case PCM_STATE_PREPARED:
+ { /* prepared state, we need to fill the buffer with silence before
+ * starting */
+ int err = async_rw(handle);
+ if (err < 0)
+ printf("Start error: %d\n", err);
+ return;
+ }
+ case PCM_STATE_PAUSED:
+ { /* paused, simply resume */
+ pcm_play_dma_pause(0);
+ return;
+ }
+ case PCM_STATE_DRAINING:
+ /* run until drained */
+ continue;
+ default:
+ DEBUGF("Unhandled state: %d\n", state);
+ return;
+ }
+ }
+}
+
+size_t pcm_get_bytes_waiting(void)
+{
+ return pcm_size;
+}
+
+const void * pcm_play_dma_get_peak_buffer(int *count)
+{
+ uintptr_t addr = (uintptr_t)pcm_data;
+ *count = pcm_size / 4;
+ return (void *)((addr + 3) & ~3);
+}
+
+void pcm_play_dma_postinit(void)
+{
+ return;
+}
+
+void pcm_set_mixer_volume(int volume)
+{
+#if defined(DX50) || defined(DX90)
+ /* -990 to 0 -> 0 to 255 */
+ int val = (volume+990)*255/990;
+#if defined(DX50)
+ FILE *f = fopen("/dev/codec_volume", "w");
+#else /* DX90 */
+ FILE *f = fopen("/sys/class/codec/es9018_volume", "w");
+#endif /* DX50 */
+ fprintf(f, "%d", val);
+ fclose(f);
+#else
+ (void)volume;
+#endif /* DX50 || DX90 */
+}
+
+#ifdef HAVE_RECORDING
+void pcm_rec_lock(void)
+{
+}
+
+void pcm_rec_unlock(void)
+{
+}
+
+void pcm_rec_dma_init(void)
+{
+}
+
+void pcm_rec_dma_close(void)
+{
+}
+
+void pcm_rec_dma_start(void *start, size_t size)
+{
+ (void)start;
+ (void)size;
+}
+
+void pcm_rec_dma_stop(void)
+{
+}
+
+const void * pcm_rec_dma_get_peak_buffer(void)
+{
+ return NULL;
+}
+
+void audiohw_set_recvol(int left, int right, int type)
+{
+ (void)left;
+ (void)right;
+ (void)type;
+}
+
+#endif /* HAVE_RECORDING */
diff --git a/firmware/target/hosted/android/dx50/powermgmt-dx50.c b/firmware/target/hosted/android/dx50/powermgmt-dx50.c
new file mode 100644
index 0000000000..45756cb8e8
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/powermgmt-dx50.c
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdbool.h>
+#include <stdio.h>
+#include "config.h"
+#include "power.h"
+#include "powermgmt.h"
+
+unsigned int power_input_status(void)
+{
+ int val;
+ FILE *f = fopen("/sys/class/power_supply/ac/present", "r");
+ fscanf(f, "%d", &val);
+ fclose(f);
+ return val?POWER_INPUT_MAIN_CHARGER:POWER_INPUT_NONE;
+}
+
+/* Values for stock PISEN battery. TODO: Needs optimization */
+
+const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] =
+{
+ 3380
+};
+
+const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] =
+{
+ 3100
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */
+const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] =
+{
+ { 3370, 3650, 3700, 3740, 3780, 3820, 3870, 3930, 4000, 4090, 4190 }
+};
+
+/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */
+const unsigned short percent_to_volt_charge[11] =
+{
+ 3540, 3860, 3930, 3980, 4000, 4020, 4040, 4080, 4130, 4180, 4220 /* LiPo */
+};
+
+
+/* Returns battery voltage from android measurement [millivolts] */
+int _battery_voltage(void)
+{
+ int val;
+ FILE *f = fopen("/sys/class/power_supply/battery/voltage_now", "r");
+ fscanf(f, "%d", &val);
+ fclose(f);
+ return (val/1000);
+}
+
+
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/asound.h b/firmware/target/hosted/android/dx50/tinyalsa/asound.h
new file mode 100644
index 0000000000..fc1e4f6d67
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/asound.h
@@ -0,0 +1,821 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __SOUND_ASOUND_H
+#define __SOUND_ASOUND_H
+
+#include <linux/types.h>
+
+#define SNDRV_PROTOCOL_VERSION(major, minor, subminor) (((major)<<16)|((minor)<<8)|(subminor))
+#define SNDRV_PROTOCOL_MAJOR(version) (((version)>>16)&0xffff)
+#define SNDRV_PROTOCOL_MINOR(version) (((version)>>8)&0xff)
+#define SNDRV_PROTOCOL_MICRO(version) ((version)&0xff)
+#define SNDRV_PROTOCOL_INCOMPATIBLE(kversion, uversion) (SNDRV_PROTOCOL_MAJOR(kversion) != SNDRV_PROTOCOL_MAJOR(uversion) || (SNDRV_PROTOCOL_MAJOR(kversion) == SNDRV_PROTOCOL_MAJOR(uversion) && SNDRV_PROTOCOL_MINOR(kversion) != SNDRV_PROTOCOL_MINOR(uversion)))
+
+struct snd_aes_iec958 {
+ unsigned char status[24];
+ unsigned char subcode[147];
+ unsigned char pad;
+ unsigned char dig_subframe[4];
+};
+
+#define SNDRV_HWDEP_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
+
+enum {
+ SNDRV_HWDEP_IFACE_OPL2 = 0,
+ SNDRV_HWDEP_IFACE_OPL3,
+ SNDRV_HWDEP_IFACE_OPL4,
+ SNDRV_HWDEP_IFACE_SB16CSP,
+ SNDRV_HWDEP_IFACE_EMU10K1,
+ SNDRV_HWDEP_IFACE_YSS225,
+ SNDRV_HWDEP_IFACE_ICS2115,
+ SNDRV_HWDEP_IFACE_SSCAPE,
+ SNDRV_HWDEP_IFACE_VX,
+ SNDRV_HWDEP_IFACE_MIXART,
+ SNDRV_HWDEP_IFACE_USX2Y,
+ SNDRV_HWDEP_IFACE_EMUX_WAVETABLE,
+ SNDRV_HWDEP_IFACE_BLUETOOTH,
+ SNDRV_HWDEP_IFACE_USX2Y_PCM,
+ SNDRV_HWDEP_IFACE_PCXHR,
+ SNDRV_HWDEP_IFACE_SB_RC,
+ SNDRV_HWDEP_IFACE_HDA,
+ SNDRV_HWDEP_IFACE_USB_STREAM,
+
+ SNDRV_HWDEP_IFACE_LAST = SNDRV_HWDEP_IFACE_USB_STREAM
+};
+
+struct snd_hwdep_info {
+ unsigned int device;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ int iface;
+ unsigned char reserved[64];
+};
+
+struct snd_hwdep_dsp_status {
+ unsigned int version;
+ unsigned char id[32];
+ unsigned int num_dsps;
+ unsigned int dsp_loaded;
+ unsigned int chip_ready;
+ unsigned char reserved[16];
+};
+
+struct snd_hwdep_dsp_image {
+ unsigned int index;
+ unsigned char name[64];
+ unsigned char __user *image;
+ size_t length;
+ unsigned long driver_data;
+};
+
+#define SNDRV_HWDEP_IOCTL_PVERSION _IOR ('H', 0x00, int)
+#define SNDRV_HWDEP_IOCTL_INFO _IOR ('H', 0x01, struct snd_hwdep_info)
+#define SNDRV_HWDEP_IOCTL_DSP_STATUS _IOR('H', 0x02, struct snd_hwdep_dsp_status)
+#define SNDRV_HWDEP_IOCTL_DSP_LOAD _IOW('H', 0x03, struct snd_hwdep_dsp_image)
+
+#define SNDRV_PCM_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 10)
+
+typedef unsigned long snd_pcm_uframes_t;
+typedef signed long snd_pcm_sframes_t;
+
+enum {
+ SNDRV_PCM_CLASS_GENERIC = 0,
+ SNDRV_PCM_CLASS_MULTI,
+ SNDRV_PCM_CLASS_MODEM,
+ SNDRV_PCM_CLASS_DIGITIZER,
+
+ SNDRV_PCM_CLASS_LAST = SNDRV_PCM_CLASS_DIGITIZER,
+};
+
+enum {
+ SNDRV_PCM_SUBCLASS_GENERIC_MIX = 0,
+ SNDRV_PCM_SUBCLASS_MULTI_MIX,
+
+ SNDRV_PCM_SUBCLASS_LAST = SNDRV_PCM_SUBCLASS_MULTI_MIX,
+};
+
+enum {
+ SNDRV_PCM_STREAM_PLAYBACK = 0,
+ SNDRV_PCM_STREAM_CAPTURE,
+ SNDRV_PCM_STREAM_LAST = SNDRV_PCM_STREAM_CAPTURE,
+};
+
+typedef int __bitwise snd_pcm_access_t;
+#define SNDRV_PCM_ACCESS_MMAP_INTERLEAVED ((__force snd_pcm_access_t) 0)
+#define SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED ((__force snd_pcm_access_t) 1)
+#define SNDRV_PCM_ACCESS_MMAP_COMPLEX ((__force snd_pcm_access_t) 2)
+#define SNDRV_PCM_ACCESS_RW_INTERLEAVED ((__force snd_pcm_access_t) 3)
+#define SNDRV_PCM_ACCESS_RW_NONINTERLEAVED ((__force snd_pcm_access_t) 4)
+#define SNDRV_PCM_ACCESS_LAST SNDRV_PCM_ACCESS_RW_NONINTERLEAVED
+
+typedef int __bitwise snd_pcm_format_t;
+#define SNDRV_PCM_FORMAT_S8 ((__force snd_pcm_format_t) 0)
+#define SNDRV_PCM_FORMAT_U8 ((__force snd_pcm_format_t) 1)
+#define SNDRV_PCM_FORMAT_S16_LE ((__force snd_pcm_format_t) 2)
+#define SNDRV_PCM_FORMAT_S16_BE ((__force snd_pcm_format_t) 3)
+#define SNDRV_PCM_FORMAT_U16_LE ((__force snd_pcm_format_t) 4)
+#define SNDRV_PCM_FORMAT_U16_BE ((__force snd_pcm_format_t) 5)
+#define SNDRV_PCM_FORMAT_S24_LE ((__force snd_pcm_format_t) 6)
+#define SNDRV_PCM_FORMAT_S24_BE ((__force snd_pcm_format_t) 7)
+#define SNDRV_PCM_FORMAT_U24_LE ((__force snd_pcm_format_t) 8)
+#define SNDRV_PCM_FORMAT_U24_BE ((__force snd_pcm_format_t) 9)
+#define SNDRV_PCM_FORMAT_S32_LE ((__force snd_pcm_format_t) 10)
+#define SNDRV_PCM_FORMAT_S32_BE ((__force snd_pcm_format_t) 11)
+#define SNDRV_PCM_FORMAT_U32_LE ((__force snd_pcm_format_t) 12)
+#define SNDRV_PCM_FORMAT_U32_BE ((__force snd_pcm_format_t) 13)
+#define SNDRV_PCM_FORMAT_FLOAT_LE ((__force snd_pcm_format_t) 14)
+#define SNDRV_PCM_FORMAT_FLOAT_BE ((__force snd_pcm_format_t) 15)
+#define SNDRV_PCM_FORMAT_FLOAT64_LE ((__force snd_pcm_format_t) 16)
+#define SNDRV_PCM_FORMAT_FLOAT64_BE ((__force snd_pcm_format_t) 17)
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE ((__force snd_pcm_format_t) 18)
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE ((__force snd_pcm_format_t) 19)
+#define SNDRV_PCM_FORMAT_MU_LAW ((__force snd_pcm_format_t) 20)
+#define SNDRV_PCM_FORMAT_A_LAW ((__force snd_pcm_format_t) 21)
+#define SNDRV_PCM_FORMAT_IMA_ADPCM ((__force snd_pcm_format_t) 22)
+#define SNDRV_PCM_FORMAT_MPEG ((__force snd_pcm_format_t) 23)
+#define SNDRV_PCM_FORMAT_GSM ((__force snd_pcm_format_t) 24)
+#define SNDRV_PCM_FORMAT_SPECIAL ((__force snd_pcm_format_t) 31)
+#define SNDRV_PCM_FORMAT_S24_3LE ((__force snd_pcm_format_t) 32)
+#define SNDRV_PCM_FORMAT_S24_3BE ((__force snd_pcm_format_t) 33)
+#define SNDRV_PCM_FORMAT_U24_3LE ((__force snd_pcm_format_t) 34)
+#define SNDRV_PCM_FORMAT_U24_3BE ((__force snd_pcm_format_t) 35)
+#define SNDRV_PCM_FORMAT_S20_3LE ((__force snd_pcm_format_t) 36)
+#define SNDRV_PCM_FORMAT_S20_3BE ((__force snd_pcm_format_t) 37)
+#define SNDRV_PCM_FORMAT_U20_3LE ((__force snd_pcm_format_t) 38)
+#define SNDRV_PCM_FORMAT_U20_3BE ((__force snd_pcm_format_t) 39)
+#define SNDRV_PCM_FORMAT_S18_3LE ((__force snd_pcm_format_t) 40)
+#define SNDRV_PCM_FORMAT_S18_3BE ((__force snd_pcm_format_t) 41)
+#define SNDRV_PCM_FORMAT_U18_3LE ((__force snd_pcm_format_t) 42)
+#define SNDRV_PCM_FORMAT_U18_3BE ((__force snd_pcm_format_t) 43)
+#define SNDRV_PCM_FORMAT_G723_24 ((__force snd_pcm_format_t) 44)
+#define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45)
+#define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46)
+#define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47)
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B
+
+#ifdef SNDRV_LITTLE_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_LE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_LE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_LE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_LE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_LE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_LE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_LE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE
+#endif
+#ifdef SNDRV_BIG_ENDIAN
+#define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_BE
+#define SNDRV_PCM_FORMAT_U16 SNDRV_PCM_FORMAT_U16_BE
+#define SNDRV_PCM_FORMAT_S24 SNDRV_PCM_FORMAT_S24_BE
+#define SNDRV_PCM_FORMAT_U24 SNDRV_PCM_FORMAT_U24_BE
+#define SNDRV_PCM_FORMAT_S32 SNDRV_PCM_FORMAT_S32_BE
+#define SNDRV_PCM_FORMAT_U32 SNDRV_PCM_FORMAT_U32_BE
+#define SNDRV_PCM_FORMAT_FLOAT SNDRV_PCM_FORMAT_FLOAT_BE
+#define SNDRV_PCM_FORMAT_FLOAT64 SNDRV_PCM_FORMAT_FLOAT64_BE
+#define SNDRV_PCM_FORMAT_IEC958_SUBFRAME SNDRV_PCM_FORMAT_IEC958_SUBFRAME_BE
+#endif
+
+typedef int __bitwise snd_pcm_subformat_t;
+#define SNDRV_PCM_SUBFORMAT_STD ((__force snd_pcm_subformat_t) 0)
+#define SNDRV_PCM_SUBFORMAT_LAST SNDRV_PCM_SUBFORMAT_STD
+
+#define SNDRV_PCM_INFO_MMAP 0x00000001
+#define SNDRV_PCM_INFO_MMAP_VALID 0x00000002
+#define SNDRV_PCM_INFO_DOUBLE 0x00000004
+#define SNDRV_PCM_INFO_BATCH 0x00000010
+#define SNDRV_PCM_INFO_INTERLEAVED 0x00000100
+#define SNDRV_PCM_INFO_NONINTERLEAVED 0x00000200
+#define SNDRV_PCM_INFO_COMPLEX 0x00000400
+#define SNDRV_PCM_INFO_BLOCK_TRANSFER 0x00010000
+#define SNDRV_PCM_INFO_OVERRANGE 0x00020000
+#define SNDRV_PCM_INFO_RESUME 0x00040000
+#define SNDRV_PCM_INFO_PAUSE 0x00080000
+#define SNDRV_PCM_INFO_HALF_DUPLEX 0x00100000
+#define SNDRV_PCM_INFO_JOINT_DUPLEX 0x00200000
+#define SNDRV_PCM_INFO_SYNC_START 0x00400000
+#define SNDRV_PCM_INFO_NO_PERIOD_WAKEUP 0x00800000
+#define SNDRV_PCM_INFO_FIFO_IN_FRAMES 0x80000000
+
+typedef int __bitwise snd_pcm_state_t;
+#define SNDRV_PCM_STATE_OPEN ((__force snd_pcm_state_t) 0)
+#define SNDRV_PCM_STATE_SETUP ((__force snd_pcm_state_t) 1)
+#define SNDRV_PCM_STATE_PREPARED ((__force snd_pcm_state_t) 2)
+#define SNDRV_PCM_STATE_RUNNING ((__force snd_pcm_state_t) 3)
+#define SNDRV_PCM_STATE_XRUN ((__force snd_pcm_state_t) 4)
+#define SNDRV_PCM_STATE_DRAINING ((__force snd_pcm_state_t) 5)
+#define SNDRV_PCM_STATE_PAUSED ((__force snd_pcm_state_t) 6)
+#define SNDRV_PCM_STATE_SUSPENDED ((__force snd_pcm_state_t) 7)
+#define SNDRV_PCM_STATE_DISCONNECTED ((__force snd_pcm_state_t) 8)
+#define SNDRV_PCM_STATE_LAST SNDRV_PCM_STATE_DISCONNECTED
+
+enum {
+ SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
+ SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
+ SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+};
+
+union snd_pcm_sync_id {
+ unsigned char id[16];
+ unsigned short id16[8];
+ unsigned int id32[4];
+};
+
+struct snd_pcm_info {
+ unsigned int device;
+ unsigned int subdevice;
+ int stream;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned char subname[32];
+ int dev_class;
+ int dev_subclass;
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ union snd_pcm_sync_id sync;
+ unsigned char reserved[64];
+};
+
+typedef int snd_pcm_hw_param_t;
+#define SNDRV_PCM_HW_PARAM_ACCESS 0
+#define SNDRV_PCM_HW_PARAM_FORMAT 1
+#define SNDRV_PCM_HW_PARAM_SUBFORMAT 2
+#define SNDRV_PCM_HW_PARAM_FIRST_MASK SNDRV_PCM_HW_PARAM_ACCESS
+#define SNDRV_PCM_HW_PARAM_LAST_MASK SNDRV_PCM_HW_PARAM_SUBFORMAT
+
+#define SNDRV_PCM_HW_PARAM_SAMPLE_BITS 8
+#define SNDRV_PCM_HW_PARAM_FRAME_BITS 9
+#define SNDRV_PCM_HW_PARAM_CHANNELS 10
+#define SNDRV_PCM_HW_PARAM_RATE 11
+#define SNDRV_PCM_HW_PARAM_PERIOD_TIME 12
+#define SNDRV_PCM_HW_PARAM_PERIOD_SIZE 13
+#define SNDRV_PCM_HW_PARAM_PERIOD_BYTES 14
+#define SNDRV_PCM_HW_PARAM_PERIODS 15
+#define SNDRV_PCM_HW_PARAM_BUFFER_TIME 16
+#define SNDRV_PCM_HW_PARAM_BUFFER_SIZE 17
+#define SNDRV_PCM_HW_PARAM_BUFFER_BYTES 18
+#define SNDRV_PCM_HW_PARAM_TICK_TIME 19
+#define SNDRV_PCM_HW_PARAM_FIRST_INTERVAL SNDRV_PCM_HW_PARAM_SAMPLE_BITS
+#define SNDRV_PCM_HW_PARAM_LAST_INTERVAL SNDRV_PCM_HW_PARAM_TICK_TIME
+
+#define SNDRV_PCM_HW_PARAMS_NORESAMPLE (1<<0)
+#define SNDRV_PCM_HW_PARAMS_EXPORT_BUFFER (1<<1)
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2)
+
+struct snd_interval {
+ unsigned int min, max;
+ unsigned int openmin:1,
+ openmax:1,
+ integer:1,
+ empty:1;
+};
+
+#define SNDRV_MASK_MAX 256
+
+struct snd_mask {
+ __u32 bits[(SNDRV_MASK_MAX+31)/32];
+};
+
+struct snd_pcm_hw_params {
+ unsigned int flags;
+ struct snd_mask masks[SNDRV_PCM_HW_PARAM_LAST_MASK -
+ SNDRV_PCM_HW_PARAM_FIRST_MASK + 1];
+ struct snd_mask mres[5];
+ struct snd_interval intervals[SNDRV_PCM_HW_PARAM_LAST_INTERVAL -
+ SNDRV_PCM_HW_PARAM_FIRST_INTERVAL + 1];
+ struct snd_interval ires[9];
+ unsigned int rmask;
+ unsigned int cmask;
+ unsigned int info;
+ unsigned int msbits;
+ unsigned int rate_num;
+ unsigned int rate_den;
+ snd_pcm_uframes_t fifo_size;
+ unsigned char reserved[64];
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_NONE = 0,
+ SNDRV_PCM_TSTAMP_ENABLE,
+ SNDRV_PCM_TSTAMP_LAST = SNDRV_PCM_TSTAMP_ENABLE,
+};
+
+struct snd_pcm_sw_params {
+ int tstamp_mode;
+ unsigned int period_step;
+ unsigned int sleep_min;
+ snd_pcm_uframes_t avail_min;
+ snd_pcm_uframes_t xfer_align;
+ snd_pcm_uframes_t start_threshold;
+ snd_pcm_uframes_t stop_threshold;
+ snd_pcm_uframes_t silence_threshold;
+ snd_pcm_uframes_t silence_size;
+ snd_pcm_uframes_t boundary;
+ unsigned char reserved[64];
+};
+
+struct snd_pcm_channel_info {
+ unsigned int channel;
+ __kernel_off_t offset;
+ unsigned int first;
+ unsigned int step;
+};
+
+struct snd_pcm_status {
+ snd_pcm_state_t state;
+ struct timespec trigger_tstamp;
+ struct timespec tstamp;
+ snd_pcm_uframes_t appl_ptr;
+ snd_pcm_uframes_t hw_ptr;
+ snd_pcm_sframes_t delay;
+ snd_pcm_uframes_t avail;
+ snd_pcm_uframes_t avail_max;
+ snd_pcm_uframes_t overrange;
+ snd_pcm_state_t suspended_state;
+ unsigned char reserved[60];
+};
+
+struct snd_pcm_mmap_status {
+ snd_pcm_state_t state;
+ int pad1;
+ snd_pcm_uframes_t hw_ptr;
+ struct timespec tstamp;
+ snd_pcm_state_t suspended_state;
+};
+
+struct snd_pcm_mmap_control {
+ snd_pcm_uframes_t appl_ptr;
+ snd_pcm_uframes_t avail_min;
+};
+
+#define SNDRV_PCM_SYNC_PTR_HWSYNC (1<<0)
+#define SNDRV_PCM_SYNC_PTR_APPL (1<<1)
+#define SNDRV_PCM_SYNC_PTR_AVAIL_MIN (1<<2)
+
+struct snd_pcm_sync_ptr {
+ unsigned int flags;
+ union {
+ struct snd_pcm_mmap_status status;
+ unsigned char reserved[64];
+ } s;
+ union {
+ struct snd_pcm_mmap_control control;
+ unsigned char reserved[64];
+ } c;
+};
+
+struct snd_xferi {
+ snd_pcm_sframes_t result;
+ void __user *buf;
+ snd_pcm_uframes_t frames;
+};
+
+struct snd_xfern {
+ snd_pcm_sframes_t result;
+ void __user * __user *bufs;
+ snd_pcm_uframes_t frames;
+};
+
+enum {
+ SNDRV_PCM_TSTAMP_TYPE_GETTIMEOFDAY = 0,
+ SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+ SNDRV_PCM_TSTAMP_TYPE_LAST = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC,
+};
+
+#define SNDRV_PCM_IOCTL_PVERSION _IOR('A', 0x00, int)
+#define SNDRV_PCM_IOCTL_INFO _IOR('A', 0x01, struct snd_pcm_info)
+#define SNDRV_PCM_IOCTL_TSTAMP _IOW('A', 0x02, int)
+#define SNDRV_PCM_IOCTL_TTSTAMP _IOW('A', 0x03, int)
+#define SNDRV_PCM_IOCTL_HW_REFINE _IOWR('A', 0x10, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_PARAMS _IOWR('A', 0x11, struct snd_pcm_hw_params)
+#define SNDRV_PCM_IOCTL_HW_FREE _IO('A', 0x12)
+#define SNDRV_PCM_IOCTL_SW_PARAMS _IOWR('A', 0x13, struct snd_pcm_sw_params)
+#define SNDRV_PCM_IOCTL_STATUS _IOR('A', 0x20, struct snd_pcm_status)
+#define SNDRV_PCM_IOCTL_DELAY _IOR('A', 0x21, snd_pcm_sframes_t)
+#define SNDRV_PCM_IOCTL_HWSYNC _IO('A', 0x22)
+#define SNDRV_PCM_IOCTL_SYNC_PTR _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
+#define SNDRV_PCM_IOCTL_CHANNEL_INFO _IOR('A', 0x32, struct snd_pcm_channel_info)
+#define SNDRV_PCM_IOCTL_PREPARE _IO('A', 0x40)
+#define SNDRV_PCM_IOCTL_RESET _IO('A', 0x41)
+#define SNDRV_PCM_IOCTL_START _IO('A', 0x42)
+#define SNDRV_PCM_IOCTL_DROP _IO('A', 0x43)
+#define SNDRV_PCM_IOCTL_DRAIN _IO('A', 0x44)
+#define SNDRV_PCM_IOCTL_PAUSE _IOW('A', 0x45, int)
+#define SNDRV_PCM_IOCTL_REWIND _IOW('A', 0x46, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_RESUME _IO('A', 0x47)
+#define SNDRV_PCM_IOCTL_XRUN _IO('A', 0x48)
+#define SNDRV_PCM_IOCTL_FORWARD _IOW('A', 0x49, snd_pcm_uframes_t)
+#define SNDRV_PCM_IOCTL_WRITEI_FRAMES _IOW('A', 0x50, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_READI_FRAMES _IOR('A', 0x51, struct snd_xferi)
+#define SNDRV_PCM_IOCTL_WRITEN_FRAMES _IOW('A', 0x52, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_READN_FRAMES _IOR('A', 0x53, struct snd_xfern)
+#define SNDRV_PCM_IOCTL_LINK _IOW('A', 0x60, int)
+#define SNDRV_PCM_IOCTL_UNLINK _IO('A', 0x61)
+
+#define SNDRV_RAWMIDI_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 0)
+
+enum {
+ SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
+ SNDRV_RAWMIDI_STREAM_INPUT,
+ SNDRV_RAWMIDI_STREAM_LAST = SNDRV_RAWMIDI_STREAM_INPUT,
+};
+
+#define SNDRV_RAWMIDI_INFO_OUTPUT 0x00000001
+#define SNDRV_RAWMIDI_INFO_INPUT 0x00000002
+#define SNDRV_RAWMIDI_INFO_DUPLEX 0x00000004
+
+struct snd_rawmidi_info {
+ unsigned int device;
+ unsigned int subdevice;
+ int stream;
+ int card;
+ unsigned int flags;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned char subname[32];
+ unsigned int subdevices_count;
+ unsigned int subdevices_avail;
+ unsigned char reserved[64];
+};
+
+struct snd_rawmidi_params {
+ int stream;
+ size_t buffer_size;
+ size_t avail_min;
+ unsigned int no_active_sensing: 1;
+ unsigned char reserved[16];
+};
+
+struct snd_rawmidi_status {
+ int stream;
+ struct timespec tstamp;
+ size_t avail;
+ size_t xruns;
+ unsigned char reserved[16];
+};
+
+#define SNDRV_RAWMIDI_IOCTL_PVERSION _IOR('W', 0x00, int)
+#define SNDRV_RAWMIDI_IOCTL_INFO _IOR('W', 0x01, struct snd_rawmidi_info)
+#define SNDRV_RAWMIDI_IOCTL_PARAMS _IOWR('W', 0x10, struct snd_rawmidi_params)
+#define SNDRV_RAWMIDI_IOCTL_STATUS _IOWR('W', 0x20, struct snd_rawmidi_status)
+#define SNDRV_RAWMIDI_IOCTL_DROP _IOW('W', 0x30, int)
+#define SNDRV_RAWMIDI_IOCTL_DRAIN _IOW('W', 0x31, int)
+
+#define SNDRV_TIMER_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+enum {
+ SNDRV_TIMER_CLASS_NONE = -1,
+ SNDRV_TIMER_CLASS_SLAVE = 0,
+ SNDRV_TIMER_CLASS_GLOBAL,
+ SNDRV_TIMER_CLASS_CARD,
+ SNDRV_TIMER_CLASS_PCM,
+ SNDRV_TIMER_CLASS_LAST = SNDRV_TIMER_CLASS_PCM,
+};
+
+enum {
+ SNDRV_TIMER_SCLASS_NONE = 0,
+ SNDRV_TIMER_SCLASS_APPLICATION,
+ SNDRV_TIMER_SCLASS_SEQUENCER,
+ SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+ SNDRV_TIMER_SCLASS_LAST = SNDRV_TIMER_SCLASS_OSS_SEQUENCER,
+};
+
+#define SNDRV_TIMER_GLOBAL_SYSTEM 0
+#define SNDRV_TIMER_GLOBAL_RTC 1
+#define SNDRV_TIMER_GLOBAL_HPET 2
+#define SNDRV_TIMER_GLOBAL_HRTIMER 3
+
+#define SNDRV_TIMER_FLG_SLAVE (1<<0)
+
+struct snd_timer_id {
+ int dev_class;
+ int dev_sclass;
+ int card;
+ int device;
+ int subdevice;
+};
+
+struct snd_timer_ginfo {
+ struct snd_timer_id tid;
+ unsigned int flags;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned long reserved0;
+ unsigned long resolution;
+ unsigned long resolution_min;
+ unsigned long resolution_max;
+ unsigned int clients;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gparams {
+ struct snd_timer_id tid;
+ unsigned long period_num;
+ unsigned long period_den;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_gstatus {
+ struct snd_timer_id tid;
+ unsigned long resolution;
+ unsigned long resolution_num;
+ unsigned long resolution_den;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_select {
+ struct snd_timer_id id;
+ unsigned char reserved[32];
+};
+
+struct snd_timer_info {
+ unsigned int flags;
+ int card;
+ unsigned char id[64];
+ unsigned char name[80];
+ unsigned long reserved0;
+ unsigned long resolution;
+ unsigned char reserved[64];
+};
+
+#define SNDRV_TIMER_PSFLG_AUTO (1<<0)
+#define SNDRV_TIMER_PSFLG_EXCLUSIVE (1<<1)
+#define SNDRV_TIMER_PSFLG_EARLY_EVENT (1<<2)
+
+struct snd_timer_params {
+ unsigned int flags;
+ unsigned int ticks;
+ unsigned int queue_size;
+ unsigned int reserved0;
+ unsigned int filter;
+ unsigned char reserved[60];
+};
+
+struct snd_timer_status {
+ struct timespec tstamp;
+ unsigned int resolution;
+ unsigned int lost;
+ unsigned int overrun;
+ unsigned int queue;
+ unsigned char reserved[64];
+};
+
+#define SNDRV_TIMER_IOCTL_PVERSION _IOR('T', 0x00, int)
+#define SNDRV_TIMER_IOCTL_NEXT_DEVICE _IOWR('T', 0x01, struct snd_timer_id)
+#define SNDRV_TIMER_IOCTL_TREAD _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_GINFO _IOWR('T', 0x03, struct snd_timer_ginfo)
+#define SNDRV_TIMER_IOCTL_GPARAMS _IOW('T', 0x04, struct snd_timer_gparams)
+#define SNDRV_TIMER_IOCTL_GSTATUS _IOWR('T', 0x05, struct snd_timer_gstatus)
+#define SNDRV_TIMER_IOCTL_SELECT _IOW('T', 0x10, struct snd_timer_select)
+#define SNDRV_TIMER_IOCTL_INFO _IOR('T', 0x11, struct snd_timer_info)
+#define SNDRV_TIMER_IOCTL_PARAMS _IOW('T', 0x12, struct snd_timer_params)
+#define SNDRV_TIMER_IOCTL_STATUS _IOR('T', 0x14, struct snd_timer_status)
+
+#define SNDRV_TIMER_IOCTL_START _IO('T', 0xa0)
+#define SNDRV_TIMER_IOCTL_STOP _IO('T', 0xa1)
+#define SNDRV_TIMER_IOCTL_CONTINUE _IO('T', 0xa2)
+#define SNDRV_TIMER_IOCTL_PAUSE _IO('T', 0xa3)
+
+struct snd_timer_read {
+ unsigned int resolution;
+ unsigned int ticks;
+};
+
+enum {
+ SNDRV_TIMER_EVENT_RESOLUTION = 0,
+ SNDRV_TIMER_EVENT_TICK,
+ SNDRV_TIMER_EVENT_START,
+ SNDRV_TIMER_EVENT_STOP,
+ SNDRV_TIMER_EVENT_CONTINUE,
+ SNDRV_TIMER_EVENT_PAUSE,
+ SNDRV_TIMER_EVENT_EARLY,
+ SNDRV_TIMER_EVENT_SUSPEND,
+ SNDRV_TIMER_EVENT_RESUME,
+
+ SNDRV_TIMER_EVENT_MSTART = SNDRV_TIMER_EVENT_START + 10,
+ SNDRV_TIMER_EVENT_MSTOP = SNDRV_TIMER_EVENT_STOP + 10,
+ SNDRV_TIMER_EVENT_MCONTINUE = SNDRV_TIMER_EVENT_CONTINUE + 10,
+ SNDRV_TIMER_EVENT_MPAUSE = SNDRV_TIMER_EVENT_PAUSE + 10,
+ SNDRV_TIMER_EVENT_MSUSPEND = SNDRV_TIMER_EVENT_SUSPEND + 10,
+ SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
+};
+
+struct snd_timer_tread {
+ int event;
+ struct timespec tstamp;
+ unsigned int val;
+};
+
+#define SNDRV_CTL_VERSION SNDRV_PROTOCOL_VERSION(2, 0, 6)
+
+struct snd_ctl_card_info {
+ int card;
+ int pad;
+ unsigned char id[16];
+ unsigned char driver[16];
+ unsigned char name[32];
+ unsigned char longname[80];
+ unsigned char reserved_[16];
+ unsigned char mixername[80];
+ unsigned char components[128];
+};
+
+typedef int __bitwise snd_ctl_elem_type_t;
+#define SNDRV_CTL_ELEM_TYPE_NONE ((__force snd_ctl_elem_type_t) 0)
+#define SNDRV_CTL_ELEM_TYPE_BOOLEAN ((__force snd_ctl_elem_type_t) 1)
+#define SNDRV_CTL_ELEM_TYPE_INTEGER ((__force snd_ctl_elem_type_t) 2)
+#define SNDRV_CTL_ELEM_TYPE_ENUMERATED ((__force snd_ctl_elem_type_t) 3)
+#define SNDRV_CTL_ELEM_TYPE_BYTES ((__force snd_ctl_elem_type_t) 4)
+#define SNDRV_CTL_ELEM_TYPE_IEC958 ((__force snd_ctl_elem_type_t) 5)
+#define SNDRV_CTL_ELEM_TYPE_INTEGER64 ((__force snd_ctl_elem_type_t) 6)
+#define SNDRV_CTL_ELEM_TYPE_LAST SNDRV_CTL_ELEM_TYPE_INTEGER64
+
+typedef int __bitwise snd_ctl_elem_iface_t;
+#define SNDRV_CTL_ELEM_IFACE_CARD ((__force snd_ctl_elem_iface_t) 0)
+#define SNDRV_CTL_ELEM_IFACE_HWDEP ((__force snd_ctl_elem_iface_t) 1)
+#define SNDRV_CTL_ELEM_IFACE_MIXER ((__force snd_ctl_elem_iface_t) 2)
+#define SNDRV_CTL_ELEM_IFACE_PCM ((__force snd_ctl_elem_iface_t) 3)
+#define SNDRV_CTL_ELEM_IFACE_RAWMIDI ((__force snd_ctl_elem_iface_t) 4)
+#define SNDRV_CTL_ELEM_IFACE_TIMER ((__force snd_ctl_elem_iface_t) 5)
+#define SNDRV_CTL_ELEM_IFACE_SEQUENCER ((__force snd_ctl_elem_iface_t) 6)
+#define SNDRV_CTL_ELEM_IFACE_LAST SNDRV_CTL_ELEM_IFACE_SEQUENCER
+
+#define SNDRV_CTL_ELEM_ACCESS_READ (1<<0)
+#define SNDRV_CTL_ELEM_ACCESS_WRITE (1<<1)
+#define SNDRV_CTL_ELEM_ACCESS_READWRITE (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_VOLATILE (1<<2)
+#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP (1<<3)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READ (1<<4)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE (1<<5)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND (1<<6)
+#define SNDRV_CTL_ELEM_ACCESS_INACTIVE (1<<8)
+#define SNDRV_CTL_ELEM_ACCESS_LOCK (1<<9)
+#define SNDRV_CTL_ELEM_ACCESS_OWNER (1<<10)
+#define SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK (1<<28)
+#define SNDRV_CTL_ELEM_ACCESS_USER (1<<29)
+
+#define SNDRV_CTL_POWER_D0 0x0000
+#define SNDRV_CTL_POWER_D1 0x0100
+#define SNDRV_CTL_POWER_D2 0x0200
+#define SNDRV_CTL_POWER_D3 0x0300
+#define SNDRV_CTL_POWER_D3hot (SNDRV_CTL_POWER_D3|0x0000)
+#define SNDRV_CTL_POWER_D3cold (SNDRV_CTL_POWER_D3|0x0001)
+
+struct snd_ctl_elem_id {
+ unsigned int numid;
+ snd_ctl_elem_iface_t iface;
+ unsigned int device;
+ unsigned int subdevice;
+ unsigned char name[44];
+ unsigned int index;
+};
+
+struct snd_ctl_elem_list {
+ unsigned int offset;
+ unsigned int space;
+ unsigned int used;
+ unsigned int count;
+ struct snd_ctl_elem_id __user *pids;
+ unsigned char reserved[50];
+};
+
+struct snd_ctl_elem_info {
+ struct snd_ctl_elem_id id;
+ snd_ctl_elem_type_t type;
+ unsigned int access;
+ unsigned int count;
+ __kernel_pid_t owner;
+ union {
+ struct {
+ long min;
+ long max;
+ long step;
+ } integer;
+ struct {
+ long long min;
+ long long max;
+ long long step;
+ } integer64;
+ struct {
+ unsigned int items;
+ unsigned int item;
+ char name[64];
+ } enumerated;
+ unsigned char reserved[128];
+ } value;
+ union {
+ unsigned short d[4];
+ unsigned short *d_ptr;
+ } dimen;
+ unsigned char reserved[64-4*sizeof(unsigned short)];
+};
+
+struct snd_ctl_elem_value {
+ struct snd_ctl_elem_id id;
+ unsigned int indirect: 1;
+ union {
+ union {
+ long value[128];
+ long *value_ptr;
+ } integer;
+ union {
+ long long value[64];
+ long long *value_ptr;
+ } integer64;
+ union {
+ unsigned int item[128];
+ unsigned int *item_ptr;
+ } enumerated;
+ union {
+ unsigned char data[512];
+ unsigned char *data_ptr;
+ } bytes;
+ struct snd_aes_iec958 iec958;
+ } value;
+ struct timespec tstamp;
+ unsigned char reserved[128-sizeof(struct timespec)];
+};
+
+struct snd_ctl_tlv {
+ unsigned int numid;
+ unsigned int length;
+ unsigned int tlv[0];
+};
+
+#define SNDRV_CTL_IOCTL_PVERSION _IOR('U', 0x00, int)
+#define SNDRV_CTL_IOCTL_CARD_INFO _IOR('U', 0x01, struct snd_ctl_card_info)
+#define SNDRV_CTL_IOCTL_ELEM_LIST _IOWR('U', 0x10, struct snd_ctl_elem_list)
+#define SNDRV_CTL_IOCTL_ELEM_INFO _IOWR('U', 0x11, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_READ _IOWR('U', 0x12, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_WRITE _IOWR('U', 0x13, struct snd_ctl_elem_value)
+#define SNDRV_CTL_IOCTL_ELEM_LOCK _IOW('U', 0x14, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_ELEM_UNLOCK _IOW('U', 0x15, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS _IOWR('U', 0x16, int)
+#define SNDRV_CTL_IOCTL_ELEM_ADD _IOWR('U', 0x17, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REPLACE _IOWR('U', 0x18, struct snd_ctl_elem_info)
+#define SNDRV_CTL_IOCTL_ELEM_REMOVE _IOWR('U', 0x19, struct snd_ctl_elem_id)
+#define SNDRV_CTL_IOCTL_TLV_READ _IOWR('U', 0x1a, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_WRITE _IOWR('U', 0x1b, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_TLV_COMMAND _IOWR('U', 0x1c, struct snd_ctl_tlv)
+#define SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE _IOWR('U', 0x20, int)
+#define SNDRV_CTL_IOCTL_HWDEP_INFO _IOR('U', 0x21, struct snd_hwdep_info)
+#define SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE _IOR('U', 0x30, int)
+#define SNDRV_CTL_IOCTL_PCM_INFO _IOWR('U', 0x31, struct snd_pcm_info)
+#define SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE _IOW('U', 0x32, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE _IOWR('U', 0x40, int)
+#define SNDRV_CTL_IOCTL_RAWMIDI_INFO _IOWR('U', 0x41, struct snd_rawmidi_info)
+#define SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE _IOW('U', 0x42, int)
+#define SNDRV_CTL_IOCTL_POWER _IOWR('U', 0xd0, int)
+#define SNDRV_CTL_IOCTL_POWER_STATE _IOR('U', 0xd1, int)
+
+enum sndrv_ctl_event_type {
+ SNDRV_CTL_EVENT_ELEM = 0,
+ SNDRV_CTL_EVENT_LAST = SNDRV_CTL_EVENT_ELEM,
+};
+
+#define SNDRV_CTL_EVENT_MASK_VALUE (1<<0)
+#define SNDRV_CTL_EVENT_MASK_INFO (1<<1)
+#define SNDRV_CTL_EVENT_MASK_ADD (1<<2)
+#define SNDRV_CTL_EVENT_MASK_TLV (1<<3)
+#define SNDRV_CTL_EVENT_MASK_REMOVE (~0U)
+
+struct snd_ctl_event {
+ int type;
+ union {
+ struct {
+ unsigned int mask;
+ struct snd_ctl_elem_id id;
+ } elem;
+ unsigned char data8[60];
+ } data;
+};
+
+#define SNDRV_CTL_NAME_NONE ""
+#define SNDRV_CTL_NAME_PLAYBACK "Playback "
+#define SNDRV_CTL_NAME_CAPTURE "Capture "
+
+#define SNDRV_CTL_NAME_IEC958_NONE ""
+#define SNDRV_CTL_NAME_IEC958_SWITCH "Switch"
+#define SNDRV_CTL_NAME_IEC958_VOLUME "Volume"
+#define SNDRV_CTL_NAME_IEC958_DEFAULT "Default"
+#define SNDRV_CTL_NAME_IEC958_MASK "Mask"
+#define SNDRV_CTL_NAME_IEC958_CON_MASK "Con Mask"
+#define SNDRV_CTL_NAME_IEC958_PRO_MASK "Pro Mask"
+#define SNDRV_CTL_NAME_IEC958_PCM_STREAM "PCM Stream"
+#define SNDRV_CTL_NAME_IEC958(expl,direction,what) "IEC958 " expl SNDRV_CTL_NAME_##direction SNDRV_CTL_NAME_IEC958_##what
+
+#endif
+
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h b/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h
new file mode 100644
index 0000000000..6aacae46d6
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/asoundlib.h
@@ -0,0 +1,257 @@
+/* asoundlib.h
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of The Android Open Source Project nor the names of
+** its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+** DAMAGE.
+*/
+
+#ifndef ASOUNDLIB_H
+#define ASOUNDLIB_H
+
+#include <sys/time.h>
+#include <stddef.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*
+ * PCM API
+ */
+
+struct pcm;
+
+#define PCM_OUT 0x00000000
+#define PCM_IN 0x10000000
+#define PCM_MMAP 0x00000001
+#define PCM_NOIRQ 0x00000002
+#define PCM_NORESTART 0x00000004 /* PCM_NORESTART - when set, calls to
+ * pcm_write for a playback stream will not
+ * attempt to restart the stream in the case
+ * of an underflow, but will return -EPIPE
+ * instead. After the first -EPIPE error, the
+ * stream is considered to be stopped, and a
+ * second call to pcm_write will attempt to
+ * restart the stream.
+ */
+
+/* PCM runtime states */
+#define PCM_STATE_OPEN 0
+#define PCM_STATE_SETUP 1
+#define PCM_STATE_PREPARED 2
+#define PCM_STATE_RUNNING 3
+#define PCM_STATE_XRUN 4
+#define PCM_STATE_DRAINING 5
+#define PCM_STATE_PAUSED 6
+#define PCM_STATE_SUSPENDED 7
+#define PCM_STATE_DISCONNECTED 8
+
+/* Bit formats */
+enum pcm_format {
+ PCM_FORMAT_S16_LE = 0,
+ PCM_FORMAT_S32_LE,
+ PCM_FORMAT_S8,
+ PCM_FORMAT_S24_LE,
+
+ PCM_FORMAT_MAX,
+};
+
+/* Configuration for a stream */
+struct pcm_config {
+ unsigned int channels;
+ unsigned int rate;
+ unsigned int period_size;
+ unsigned int period_count;
+ enum pcm_format format;
+
+ /* Values to use for the ALSA start, stop and silence thresholds. Setting
+ * any one of these values to 0 will cause the default tinyalsa values to be
+ * used instead. Tinyalsa defaults are as follows.
+ *
+ * start_threshold : period_count * period_size
+ * stop_threshold : period_count * period_size
+ * silence_threshold : 0
+ */
+ unsigned int start_threshold;
+ unsigned int stop_threshold;
+ unsigned int silence_threshold;
+};
+
+/* PCM parameters */
+enum pcm_param
+{
+ PCM_PARAM_SAMPLE_BITS,
+ PCM_PARAM_FRAME_BITS,
+ PCM_PARAM_CHANNELS,
+ PCM_PARAM_RATE,
+ PCM_PARAM_PERIOD_TIME,
+ PCM_PARAM_PERIOD_SIZE,
+ PCM_PARAM_PERIOD_BYTES,
+ PCM_PARAM_PERIODS,
+ PCM_PARAM_BUFFER_TIME,
+ PCM_PARAM_BUFFER_SIZE,
+ PCM_PARAM_BUFFER_BYTES,
+ PCM_PARAM_TICK_TIME,
+};
+
+/* Mixer control types */
+enum mixer_ctl_type {
+ MIXER_CTL_TYPE_BOOL,
+ MIXER_CTL_TYPE_INT,
+ MIXER_CTL_TYPE_ENUM,
+ MIXER_CTL_TYPE_BYTE,
+ MIXER_CTL_TYPE_IEC958,
+ MIXER_CTL_TYPE_INT64,
+ MIXER_CTL_TYPE_UNKNOWN,
+
+ MIXER_CTL_TYPE_MAX,
+};
+
+/* Open and close a stream */
+struct pcm *pcm_open(unsigned int card, unsigned int device,
+ unsigned int flags, struct pcm_config *config);
+int pcm_close(struct pcm *pcm);
+int pcm_is_ready(struct pcm *pcm);
+
+/* Obtain the parameters for a PCM */
+struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
+ unsigned int flags);
+void pcm_params_free(struct pcm_params *pcm_params);
+unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
+ enum pcm_param param);
+unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
+ enum pcm_param param);
+
+/* Set and get config */
+int pcm_get_config(struct pcm *pcm, struct pcm_config *config);
+int pcm_set_config(struct pcm *pcm, struct pcm_config *config);
+
+/* Returns a human readable reason for the last error */
+const char *pcm_get_error(struct pcm *pcm);
+
+/* Returns the sample size in bits for a PCM format.
+ * As with ALSA formats, this is the storage size for the format, whereas the
+ * format represents the number of significant bits. For example,
+ * PCM_FORMAT_S24_LE uses 32 bits of storage.
+ */
+unsigned int pcm_format_to_bits(enum pcm_format format);
+
+/* Returns the buffer size (int frames) that should be used for pcm_write. */
+unsigned int pcm_get_buffer_size(struct pcm *pcm);
+unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames);
+unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes);
+
+/* Returns the pcm latency in ms */
+unsigned int pcm_get_latency(struct pcm *pcm);
+
+/* Returns available frames in pcm buffer and corresponding time stamp.
+ * For an input stream, frames available are frames ready for the
+ * application to read.
+ * For an output stream, frames available are the number of empty frames available
+ * for the application to write.
+ */
+int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
+ struct timespec *tstamp);
+
+/* Write data to the fifo.
+ * Will start playback on the first write or on a write that
+ * occurs after a fifo underrun.
+ */
+int pcm_write(struct pcm *pcm, const void *data, unsigned int count);
+int pcm_read(struct pcm *pcm, void *data, unsigned int count);
+
+/*
+ * mmap() support.
+ */
+int pcm_mmap_write(struct pcm *pcm, const void *data, unsigned int count);
+int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
+ unsigned int *frames);
+int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);
+
+
+/* Start and stop a PCM channel that doesn't transfer data */
+int pcm_start(struct pcm *pcm);
+int pcm_stop(struct pcm *pcm);
+
+/* Interrupt driven API */
+int pcm_wait(struct pcm *pcm, int timeout);
+
+int pcm_avail_update(struct pcm *pcm);
+
+int pcm_state(struct pcm *pcm);
+
+
+/*
+ * MIXER API
+ */
+
+struct mixer;
+struct mixer_ctl;
+
+/* Open and close a mixer */
+struct mixer *mixer_open(unsigned int card);
+void mixer_close(struct mixer *mixer);
+
+/* Get info about a mixer */
+const char *mixer_get_name(struct mixer *mixer);
+
+/* Obtain mixer controls */
+unsigned int mixer_get_num_ctls(struct mixer *mixer);
+struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id);
+struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name);
+
+/* Get info about mixer controls */
+const char *mixer_ctl_get_name(struct mixer_ctl *ctl);
+enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl);
+const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl);
+unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl);
+unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl);
+const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
+ unsigned int enum_id);
+
+/* Some sound cards update their controls due to external events,
+ * such as HDMI EDID byte data changing when an HDMI cable is
+ * connected. This API allows the count of elements to be updated.
+ */
+void mixer_ctl_update(struct mixer_ctl *ctl);
+
+/* Set and get mixer controls */
+int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id);
+int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent);
+
+int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id);
+int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count);
+int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value);
+int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count);
+int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string);
+
+/* Determe range of integer mixer controls */
+int mixer_ctl_get_range_min(struct mixer_ctl *ctl);
+int mixer_ctl_get_range_max(struct mixer_ctl *ctl);
+
+#if defined(__cplusplus)
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/mixer.c b/firmware/target/hosted/android/dx50/tinyalsa/mixer.c
new file mode 100644
index 0000000000..f75dec488a
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/mixer.c
@@ -0,0 +1,497 @@
+/* mixer.c
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of The Android Open Source Project nor the names of
+** its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+** DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include <sys/ioctl.h>
+
+#include <linux/ioctl.h>
+#define __force
+#define __bitwise
+#define __user
+#include <tinyalsa/asound.h>
+
+#include <tinyalsa/asoundlib.h>
+
+struct mixer_ctl {
+ struct mixer *mixer;
+ struct snd_ctl_elem_info *info;
+ char **ename;
+};
+
+struct mixer {
+ int fd;
+ struct snd_ctl_card_info card_info;
+ struct snd_ctl_elem_info *elem_info;
+ struct mixer_ctl *ctl;
+ unsigned int count;
+};
+
+void mixer_close(struct mixer *mixer)
+{
+ unsigned int n,m;
+
+ if (!mixer)
+ return;
+
+ if (mixer->fd >= 0)
+ close(mixer->fd);
+
+ if (mixer->ctl) {
+ for (n = 0; n < mixer->count; n++) {
+ if (mixer->ctl[n].ename) {
+ unsigned int max = mixer->ctl[n].info->value.enumerated.items;
+ for (m = 0; m < max; m++)
+ free(mixer->ctl[n].ename[m]);
+ free(mixer->ctl[n].ename);
+ }
+ }
+ free(mixer->ctl);
+ }
+
+ if (mixer->elem_info)
+ free(mixer->elem_info);
+
+ free(mixer);
+
+ /* TODO: verify frees */
+}
+
+struct mixer *mixer_open(unsigned int card)
+{
+ struct snd_ctl_elem_list elist;
+ struct snd_ctl_elem_info tmp;
+ struct snd_ctl_elem_id *eid = NULL;
+ struct mixer *mixer = NULL;
+ unsigned int n, m;
+ int fd;
+ char fn[256];
+
+ snprintf(fn, sizeof(fn), "/dev/snd/controlC%u", card);
+ fd = open(fn, O_RDWR);
+ if (fd < 0)
+ return 0;
+
+ memset(&elist, 0, sizeof(elist));
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+ goto fail;
+
+ mixer = calloc(1, sizeof(*mixer));
+ if (!mixer)
+ goto fail;
+
+ mixer->ctl = calloc(elist.count, sizeof(struct mixer_ctl));
+ mixer->elem_info = calloc(elist.count, sizeof(struct snd_ctl_elem_info));
+ if (!mixer->ctl || !mixer->elem_info)
+ goto fail;
+
+ if (ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, &mixer->card_info) < 0)
+ goto fail;
+
+ eid = calloc(elist.count, sizeof(struct snd_ctl_elem_id));
+ if (!eid)
+ goto fail;
+
+ mixer->count = elist.count;
+ mixer->fd = fd;
+ elist.space = mixer->count;
+ elist.pids = eid;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_LIST, &elist) < 0)
+ goto fail;
+
+ for (n = 0; n < mixer->count; n++) {
+ struct snd_ctl_elem_info *ei = mixer->elem_info + n;
+ ei->id.numid = eid[n].numid;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, ei) < 0)
+ goto fail;
+ mixer->ctl[n].info = ei;
+ mixer->ctl[n].mixer = mixer;
+ if (ei->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
+ char **enames = calloc(ei->value.enumerated.items, sizeof(char*));
+ if (!enames)
+ goto fail;
+ mixer->ctl[n].ename = enames;
+ for (m = 0; m < ei->value.enumerated.items; m++) {
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.id.numid = ei->id.numid;
+ tmp.value.enumerated.item = m;
+ if (ioctl(fd, SNDRV_CTL_IOCTL_ELEM_INFO, &tmp) < 0)
+ goto fail;
+ enames[m] = strdup(tmp.value.enumerated.name);
+ if (!enames[m])
+ goto fail;
+ }
+ }
+ }
+
+ free(eid);
+ return mixer;
+
+fail:
+ /* TODO: verify frees in failure case */
+ if (eid)
+ free(eid);
+ if (mixer)
+ mixer_close(mixer);
+ else if (fd >= 0)
+ close(fd);
+ return 0;
+}
+
+const char *mixer_get_name(struct mixer *mixer)
+{
+ return (const char *)mixer->card_info.name;
+}
+
+unsigned int mixer_get_num_ctls(struct mixer *mixer)
+{
+ if (!mixer)
+ return 0;
+
+ return mixer->count;
+}
+
+struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id)
+{
+ if (mixer && (id < mixer->count))
+ return mixer->ctl + id;
+
+ return NULL;
+}
+
+struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name)
+{
+ unsigned int n;
+
+ if (!mixer)
+ return NULL;
+
+ for (n = 0; n < mixer->count; n++)
+ if (!strcmp(name, (char*) mixer->elem_info[n].id.name))
+ return mixer->ctl + n;
+
+ return NULL;
+}
+
+void mixer_ctl_update(struct mixer_ctl *ctl)
+{
+ ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_INFO, ctl->info);
+}
+
+const char *mixer_ctl_get_name(struct mixer_ctl *ctl)
+{
+ if (!ctl)
+ return NULL;
+
+ return (const char *)ctl->info->id.name;
+}
+
+enum mixer_ctl_type mixer_ctl_get_type(struct mixer_ctl *ctl)
+{
+ if (!ctl)
+ return MIXER_CTL_TYPE_UNKNOWN;
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return MIXER_CTL_TYPE_BOOL;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: return MIXER_CTL_TYPE_INT;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return MIXER_CTL_TYPE_ENUM;
+ case SNDRV_CTL_ELEM_TYPE_BYTES: return MIXER_CTL_TYPE_BYTE;
+ case SNDRV_CTL_ELEM_TYPE_IEC958: return MIXER_CTL_TYPE_IEC958;
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return MIXER_CTL_TYPE_INT64;
+ default: return MIXER_CTL_TYPE_UNKNOWN;
+ };
+}
+
+const char *mixer_ctl_get_type_string(struct mixer_ctl *ctl)
+{
+ if (!ctl)
+ return "";
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN: return "BOOL";
+ case SNDRV_CTL_ELEM_TYPE_INTEGER: return "INT";
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED: return "ENUM";
+ case SNDRV_CTL_ELEM_TYPE_BYTES: return "BYTE";
+ case SNDRV_CTL_ELEM_TYPE_IEC958: return "IEC958";
+ case SNDRV_CTL_ELEM_TYPE_INTEGER64: return "INT64";
+ default: return "Unknown";
+ };
+}
+
+unsigned int mixer_ctl_get_num_values(struct mixer_ctl *ctl)
+{
+ if (!ctl)
+ return 0;
+
+ return ctl->info->count;
+}
+
+static int percent_to_int(struct snd_ctl_elem_info *ei, int percent)
+{
+ int range;
+
+ if (percent > 100)
+ percent = 100;
+ else if (percent < 0)
+ percent = 0;
+
+ range = (ei->value.integer.max - ei->value.integer.min);
+
+ return ei->value.integer.min + (range * percent) / 100;
+}
+
+static int int_to_percent(struct snd_ctl_elem_info *ei, int value)
+{
+ int range = (ei->value.integer.max - ei->value.integer.min);
+
+ if (range == 0)
+ return 0;
+
+ return ((value - ei->value.integer.min) / range) * 100;
+}
+
+int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id)
+{
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ return -EINVAL;
+
+ return int_to_percent(ctl->info, mixer_ctl_get_value(ctl, id));
+}
+
+int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent)
+{
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ return -EINVAL;
+
+ return mixer_ctl_set_value(ctl, id, percent_to_int(ctl->info, percent));
+}
+
+int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id)
+{
+ struct snd_ctl_elem_value ev;
+ int ret;
+
+ if (!ctl || (id >= ctl->info->count))
+ return -EINVAL;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+ if (ret < 0)
+ return ret;
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ return !!ev.value.integer.value[id];
+
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ return ev.value.integer.value[id];
+
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ return ev.value.enumerated.item[id];
+
+ case SNDRV_CTL_ELEM_TYPE_BYTES:
+ return ev.value.bytes.data[id];
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int mixer_ctl_get_array(struct mixer_ctl *ctl, void *array, size_t count)
+{
+ struct snd_ctl_elem_value ev;
+ int ret;
+ size_t size;
+ void *source;
+
+ if (!ctl || (count > ctl->info->count) || !count || !array)
+ return -EINVAL;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+
+ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+ if (ret < 0)
+ return ret;
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ size = sizeof(ev.value.integer.value[0]);
+ source = ev.value.integer.value;
+ break;
+
+ case SNDRV_CTL_ELEM_TYPE_BYTES:
+ size = sizeof(ev.value.bytes.data[0]);
+ source = ev.value.bytes.data;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ memcpy(array, source, size * count);
+
+ return 0;
+}
+
+int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
+{
+ struct snd_ctl_elem_value ev;
+ int ret;
+
+ if (!ctl || (id >= ctl->info->count))
+ return -EINVAL;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
+ if (ret < 0)
+ return ret;
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ ev.value.integer.value[id] = !!value;
+ break;
+
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ ev.value.integer.value[id] = value;
+ break;
+
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ ev.value.enumerated.item[id] = value;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+}
+
+int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
+{
+ struct snd_ctl_elem_value ev;
+ size_t size;
+ void *dest;
+
+ if (!ctl || (count > ctl->info->count) || !count || !array)
+ return -EINVAL;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.id.numid = ctl->info->id.numid;
+
+ switch (ctl->info->type) {
+ case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+ case SNDRV_CTL_ELEM_TYPE_INTEGER:
+ size = sizeof(ev.value.integer.value[0]);
+ dest = ev.value.integer.value;
+ break;
+
+ case SNDRV_CTL_ELEM_TYPE_BYTES:
+ size = sizeof(ev.value.bytes.data[0]);
+ dest = ev.value.bytes.data;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ memcpy(dest, array, size * count);
+
+ return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+}
+
+int mixer_ctl_get_range_min(struct mixer_ctl *ctl)
+{
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ return -EINVAL;
+
+ return ctl->info->value.integer.min;
+}
+
+int mixer_ctl_get_range_max(struct mixer_ctl *ctl)
+{
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER))
+ return -EINVAL;
+
+ return ctl->info->value.integer.max;
+}
+
+unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl)
+{
+ if (!ctl)
+ return 0;
+
+ return ctl->info->value.enumerated.items;
+}
+
+const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl,
+ unsigned int enum_id)
+{
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) ||
+ (enum_id >= ctl->info->value.enumerated.items))
+ return NULL;
+
+ return (const char *)ctl->ename[enum_id];
+}
+
+int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string)
+{
+ unsigned int i, num_enums;
+ struct snd_ctl_elem_value ev;
+ int ret;
+
+ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED))
+ return -EINVAL;
+
+ num_enums = ctl->info->value.enumerated.items;
+ for (i = 0; i < num_enums; i++) {
+ if (!strcmp(string, ctl->ename[i])) {
+ memset(&ev, 0, sizeof(ev));
+ ev.value.enumerated.item[0] = i;
+ ev.id.numid = ctl->info->id.numid;
+ ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
+ if (ret < 0)
+ return ret;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
diff --git a/firmware/target/hosted/android/dx50/tinyalsa/pcm.c b/firmware/target/hosted/android/dx50/tinyalsa/pcm.c
new file mode 100644
index 0000000000..bd44dce52f
--- /dev/null
+++ b/firmware/target/hosted/android/dx50/tinyalsa/pcm.c
@@ -0,0 +1,973 @@
+/* pcm.c
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+** * Neither the name of The Android Open Source Project nor the names of
+** its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
+** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
+** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+** DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <limits.h>
+
+#include <linux/ioctl.h>
+#define __force
+#define __bitwise
+#define __user
+#include <tinyalsa/asound.h>
+
+#include <tinyalsa/asoundlib.h>
+
+#define PARAM_MAX SNDRV_PCM_HW_PARAM_LAST_INTERVAL
+#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2)
+
+static inline int param_is_mask(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_MASK) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_MASK);
+}
+
+static inline int param_is_interval(int p)
+{
+ return (p >= SNDRV_PCM_HW_PARAM_FIRST_INTERVAL) &&
+ (p <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL);
+}
+
+static inline struct snd_interval *param_to_interval(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->intervals[n - SNDRV_PCM_HW_PARAM_FIRST_INTERVAL]);
+}
+
+static inline struct snd_mask *param_to_mask(struct snd_pcm_hw_params *p, int n)
+{
+ return &(p->masks[n - SNDRV_PCM_HW_PARAM_FIRST_MASK]);
+}
+
+static void param_set_mask(struct snd_pcm_hw_params *p, int n, unsigned int bit)
+{
+ if (bit >= SNDRV_MASK_MAX)
+ return;
+ if (param_is_mask(n)) {
+ struct snd_mask *m = param_to_mask(p, n);
+ m->bits[0] = 0;
+ m->bits[1] = 0;
+ m->bits[bit >> 5] |= (1 << (bit & 31));
+ }
+}
+
+static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = val;
+ }
+}
+
+static unsigned int param_get_min(struct snd_pcm_hw_params *p, int n)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ return i->min;
+ }
+ return 0;
+}
+
+static unsigned int param_get_max(struct snd_pcm_hw_params *p, int n)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ return i->max;
+ }
+ return 0;
+}
+
+static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = val;
+ i->max = val;
+ i->integer = 1;
+ }
+}
+
+static unsigned int param_get_int(struct snd_pcm_hw_params *p, int n)
+{
+ if (param_is_interval(n)) {
+ struct snd_interval *i = param_to_interval(p, n);
+ if (i->integer)
+ return i->max;
+ }
+ return 0;
+}
+
+static void param_init(struct snd_pcm_hw_params *p)
+{
+ int n;
+
+ memset(p, 0, sizeof(*p));
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_MASK;
+ n <= SNDRV_PCM_HW_PARAM_LAST_MASK; n++) {
+ struct snd_mask *m = param_to_mask(p, n);
+ m->bits[0] = ~0;
+ m->bits[1] = ~0;
+ }
+ for (n = SNDRV_PCM_HW_PARAM_FIRST_INTERVAL;
+ n <= SNDRV_PCM_HW_PARAM_LAST_INTERVAL; n++) {
+ struct snd_interval *i = param_to_interval(p, n);
+ i->min = 0;
+ i->max = ~0;
+ }
+ p->rmask = ~0U;
+ p->cmask = 0;
+ p->info = ~0U;
+}
+
+#define PCM_ERROR_MAX 128
+
+struct pcm {
+ int fd;
+ unsigned int flags;
+ int running:1;
+ int underruns;
+ unsigned int buffer_size;
+ unsigned int boundary;
+ char error[PCM_ERROR_MAX];
+ struct pcm_config config;
+ struct snd_pcm_mmap_status *mmap_status;
+ struct snd_pcm_mmap_control *mmap_control;
+ struct snd_pcm_sync_ptr *sync_ptr;
+ void *mmap_buffer;
+ unsigned int noirq_frames_per_msec;
+};
+
+unsigned int pcm_get_buffer_size(struct pcm *pcm)
+{
+ return pcm->buffer_size;
+}
+
+const char* pcm_get_error(struct pcm *pcm)
+{
+ return pcm->error;
+}
+
+static int oops(struct pcm *pcm, int e, const char *fmt, ...)
+{
+ va_list ap;
+ int sz;
+
+ va_start(ap, fmt);
+ vsnprintf(pcm->error, PCM_ERROR_MAX, fmt, ap);
+ va_end(ap);
+ sz = strlen(pcm->error);
+
+ if (errno)
+ snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
+ ": %s", strerror(e));
+ return -1;
+}
+
+static unsigned int pcm_format_to_alsa(enum pcm_format format)
+{
+ switch (format) {
+ case PCM_FORMAT_S32_LE:
+ return SNDRV_PCM_FORMAT_S32_LE;
+ case PCM_FORMAT_S8:
+ return SNDRV_PCM_FORMAT_S8;
+ case PCM_FORMAT_S24_LE:
+ return SNDRV_PCM_FORMAT_S24_LE;
+ default:
+ case PCM_FORMAT_S16_LE:
+ return SNDRV_PCM_FORMAT_S16_LE;
+ };
+}
+
+unsigned int pcm_format_to_bits(enum pcm_format format)
+{
+ switch (format) {
+ case PCM_FORMAT_S32_LE:
+ case PCM_FORMAT_S24_LE:
+ return 32;
+ default:
+ case PCM_FORMAT_S16_LE:
+ return 16;
+ };
+}
+
+unsigned int pcm_bytes_to_frames(struct pcm *pcm, unsigned int bytes)
+{
+ return bytes / (pcm->config.channels *
+ (pcm_format_to_bits(pcm->config.format) >> 3));
+}
+
+unsigned int pcm_frames_to_bytes(struct pcm *pcm, unsigned int frames)
+{
+ return frames * pcm->config.channels *
+ (pcm_format_to_bits(pcm->config.format) >> 3);
+}
+
+static int pcm_sync_ptr(struct pcm *pcm, int flags) {
+ if (pcm->sync_ptr) {
+ pcm->sync_ptr->flags = flags;
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SYNC_PTR, pcm->sync_ptr) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int pcm_hw_mmap_status(struct pcm *pcm) {
+
+ if (pcm->sync_ptr)
+ return 0;
+
+ int page_size = sysconf(_SC_PAGE_SIZE);
+ pcm->mmap_status = mmap(NULL, page_size, PROT_READ, MAP_FILE | MAP_SHARED,
+ pcm->fd, SNDRV_PCM_MMAP_OFFSET_STATUS);
+ if (pcm->mmap_status == MAP_FAILED)
+ pcm->mmap_status = NULL;
+ if (!pcm->mmap_status)
+ goto mmap_error;
+
+ pcm->mmap_control = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
+ MAP_FILE | MAP_SHARED, pcm->fd, SNDRV_PCM_MMAP_OFFSET_CONTROL);
+ if (pcm->mmap_control == MAP_FAILED)
+ pcm->mmap_control = NULL;
+ if (!pcm->mmap_control) {
+ munmap(pcm->mmap_status, page_size);
+ pcm->mmap_status = NULL;
+ goto mmap_error;
+ }
+ pcm->mmap_control->avail_min = 1;
+
+ return 0;
+
+mmap_error:
+
+ pcm->sync_ptr = calloc(1, sizeof(*pcm->sync_ptr));
+ if (!pcm->sync_ptr)
+ return -ENOMEM;
+ pcm->mmap_status = &pcm->sync_ptr->s.status;
+ pcm->mmap_control = &pcm->sync_ptr->c.control;
+ pcm->mmap_control->avail_min = 1;
+ pcm_sync_ptr(pcm, 0);
+
+ return 0;
+}
+
+static void pcm_hw_munmap_status(struct pcm *pcm) {
+ if (pcm->sync_ptr) {
+ free(pcm->sync_ptr);
+ pcm->sync_ptr = NULL;
+ } else {
+ int page_size = sysconf(_SC_PAGE_SIZE);
+ if (pcm->mmap_status)
+ munmap(pcm->mmap_status, page_size);
+ if (pcm->mmap_control)
+ munmap(pcm->mmap_control, page_size);
+ }
+ pcm->mmap_status = NULL;
+ pcm->mmap_control = NULL;
+}
+
+static int pcm_areas_copy(struct pcm *pcm, unsigned int pcm_offset,
+ const char *src, unsigned int src_offset,
+ unsigned int frames)
+{
+ int size_bytes = pcm_frames_to_bytes(pcm, frames);
+ int pcm_offset_bytes = pcm_frames_to_bytes(pcm, pcm_offset);
+ int src_offset_bytes = pcm_frames_to_bytes(pcm, src_offset);
+
+ /* interleaved only atm */
+ memcpy((char*)pcm->mmap_buffer + pcm_offset_bytes,
+ src + src_offset_bytes, size_bytes);
+ return 0;
+}
+
+static int pcm_mmap_write_areas(struct pcm *pcm, const char *src,
+ unsigned int offset, unsigned int size)
+{
+ void *pcm_areas;
+ int commit;
+ unsigned int pcm_offset, frames, count = 0;
+
+ while (size > 0) {
+ frames = size;
+ pcm_mmap_begin(pcm, &pcm_areas, &pcm_offset, &frames);
+ pcm_areas_copy(pcm, pcm_offset, src, offset, frames);
+ commit = pcm_mmap_commit(pcm, pcm_offset, frames);
+ if (commit < 0) {
+ oops(pcm, commit, "failed to commit %d frames\n", frames);
+ return commit;
+ }
+
+ offset += commit;
+ count += commit;
+ size -= commit;
+ }
+ return count;
+}
+
+int pcm_get_htimestamp(struct pcm *pcm, unsigned int *avail,
+ struct timespec *tstamp)
+{
+ int frames;
+ int rc;
+ snd_pcm_uframes_t hw_ptr;
+
+ if (!pcm_is_ready(pcm))
+ return -1;
+
+ rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_HWSYNC);
+ if (rc < 0)
+ return -1;
+
+ if ((pcm->mmap_status->state != PCM_STATE_RUNNING) &&
+ (pcm->mmap_status->state != PCM_STATE_DRAINING))
+ return -1;
+
+ *tstamp = pcm->mmap_status->tstamp;
+ if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0)
+ return -1;
+
+ hw_ptr = pcm->mmap_status->hw_ptr;
+ if (pcm->flags & PCM_IN)
+ frames = hw_ptr - pcm->mmap_control->appl_ptr;
+ else
+ frames = hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
+
+ if (frames < 0)
+ return -1;
+
+ *avail = (unsigned int)frames;
+
+ return 0;
+}
+
+int pcm_write(struct pcm *pcm, const void *data, unsigned int count)
+{
+ struct snd_xferi x;
+
+ if (pcm->flags & PCM_IN)
+ return -EINVAL;
+
+ x.buf = (void*)data;
+ x.frames = count / (pcm->config.channels *
+ pcm_format_to_bits(pcm->config.format) / 8);
+
+ for (;;) {
+ if (!pcm->running) {
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE))
+ return oops(pcm, errno, "cannot prepare channel");
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x))
+ return oops(pcm, errno, "cannot write initial data");
+ pcm->running = 1;
+ return 0;
+ }
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_WRITEI_FRAMES, &x)) {
+ pcm->running = 0;
+ if (errno == EPIPE) {
+ /* we failed to make our window -- try to restart if we are
+ * allowed to do so. Otherwise, simply allow the EPIPE error to
+ * propagate up to the app level */
+ pcm->underruns++;
+ if (pcm->flags & PCM_NORESTART)
+ return -EPIPE;
+ continue;
+ }
+ return oops(pcm, errno, "cannot write stream data");
+ }
+ return 0;
+ }
+}
+
+int pcm_read(struct pcm *pcm, void *data, unsigned int count)
+{
+ struct snd_xferi x;
+
+ if (!(pcm->flags & PCM_IN))
+ return -EINVAL;
+
+ x.buf = data;
+ x.frames = count / (pcm->config.channels *
+ pcm_format_to_bits(pcm->config.format) / 8);
+
+ for (;;) {
+ if (!pcm->running) {
+ if (pcm_start(pcm) < 0) {
+ fprintf(stderr, "start error");
+ return -errno;
+ }
+ }
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_READI_FRAMES, &x)) {
+ pcm->running = 0;
+ if (errno == EPIPE) {
+ /* we failed to make our window -- try to restart */
+ pcm->underruns++;
+ continue;
+ }
+ return oops(pcm, errno, "cannot read stream data");
+ }
+ return 0;
+ }
+}
+
+static struct pcm bad_pcm = {
+ .fd = -1,
+};
+
+struct pcm_params *pcm_params_get(unsigned int card, unsigned int device,
+ unsigned int flags)
+{
+ struct snd_pcm_hw_params *params;
+ char fn[256];
+ int fd;
+
+ snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
+ flags & PCM_IN ? 'c' : 'p');
+
+ fd = open(fn, O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "cannot open device '%s'\n", fn);
+ goto err_open;
+ }
+
+ params = calloc(1, sizeof(struct snd_pcm_hw_params));
+ if (!params)
+ goto err_calloc;
+
+ param_init(params);
+ if (ioctl(fd, SNDRV_PCM_IOCTL_HW_REFINE, params)) {
+ fprintf(stderr, "SNDRV_PCM_IOCTL_HW_REFINE error (%d)\n", errno);
+ goto err_hw_refine;
+ }
+
+ close(fd);
+
+ return (struct pcm_params *)params;
+
+err_hw_refine:
+ free(params);
+err_calloc:
+ close(fd);
+err_open:
+ return NULL;
+}
+
+void pcm_params_free(struct pcm_params *pcm_params)
+{
+ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
+
+ if (params)
+ free(params);
+}
+
+static int pcm_param_to_alsa(enum pcm_param param)
+{
+ switch (param) {
+ case PCM_PARAM_SAMPLE_BITS:
+ return SNDRV_PCM_HW_PARAM_SAMPLE_BITS;
+ break;
+ case PCM_PARAM_FRAME_BITS:
+ return SNDRV_PCM_HW_PARAM_FRAME_BITS;
+ break;
+ case PCM_PARAM_CHANNELS:
+ return SNDRV_PCM_HW_PARAM_CHANNELS;
+ break;
+ case PCM_PARAM_RATE:
+ return SNDRV_PCM_HW_PARAM_RATE;
+ break;
+ case PCM_PARAM_PERIOD_TIME:
+ return SNDRV_PCM_HW_PARAM_PERIOD_TIME;
+ break;
+ case PCM_PARAM_PERIOD_SIZE:
+ return SNDRV_PCM_HW_PARAM_PERIOD_SIZE;
+ break;
+ case PCM_PARAM_PERIOD_BYTES:
+ return SNDRV_PCM_HW_PARAM_PERIOD_BYTES;
+ break;
+ case PCM_PARAM_PERIODS:
+ return SNDRV_PCM_HW_PARAM_PERIODS;
+ break;
+ case PCM_PARAM_BUFFER_TIME:
+ return SNDRV_PCM_HW_PARAM_BUFFER_TIME;
+ break;
+ case PCM_PARAM_BUFFER_SIZE:
+ return SNDRV_PCM_HW_PARAM_BUFFER_SIZE;
+ break;
+ case PCM_PARAM_BUFFER_BYTES:
+ return SNDRV_PCM_HW_PARAM_BUFFER_BYTES;
+ break;
+ case PCM_PARAM_TICK_TIME:
+ return SNDRV_PCM_HW_PARAM_TICK_TIME;
+ break;
+
+ default:
+ return -1;
+ }
+}
+
+unsigned int pcm_params_get_min(struct pcm_params *pcm_params,
+ enum pcm_param param)
+{
+ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
+ int p;
+
+ if (!params)
+ return 0;
+
+ p = pcm_param_to_alsa(param);
+ if (p < 0)
+ return 0;
+
+ return param_get_min(params, p);
+}
+
+unsigned int pcm_params_get_max(struct pcm_params *pcm_params,
+ enum pcm_param param)
+{
+ struct snd_pcm_hw_params *params = (struct snd_pcm_hw_params *)pcm_params;
+ int p;
+
+ if (!params)
+ return 0;
+
+ p = pcm_param_to_alsa(param);
+ if (p < 0)
+ return 0;
+
+ return param_get_max(params, p);
+}
+
+int pcm_close(struct pcm *pcm)
+{
+ if (pcm == &bad_pcm)
+ return 0;
+
+ pcm_hw_munmap_status(pcm);
+
+ if (pcm->flags & PCM_MMAP) {
+ pcm_stop(pcm);
+ munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
+ }
+
+ if (pcm->fd >= 0)
+ close(pcm->fd);
+ pcm->running = 0;
+ pcm->buffer_size = 0;
+ pcm->fd = -1;
+ free(pcm);
+ return 0;
+}
+
+struct pcm *pcm_open(unsigned int card, unsigned int device,
+ unsigned int flags, struct pcm_config *config)
+{
+ struct pcm *pcm;
+ struct snd_pcm_info info;
+ struct snd_pcm_hw_params params;
+ struct snd_pcm_sw_params sparams;
+ char fn[256];
+ int rc;
+
+ pcm = calloc(1, sizeof(struct pcm));
+ if (!pcm || !config)
+ return &bad_pcm; /* TODO: could support default config here */
+
+ pcm->config = *config;
+
+ snprintf(fn, sizeof(fn), "/dev/snd/pcmC%uD%u%c", card, device,
+ flags & PCM_IN ? 'c' : 'p');
+
+ pcm->flags = flags;
+ pcm->fd = open(fn, O_RDWR);
+ if (pcm->fd < 0) {
+ oops(pcm, errno, "cannot open device '%s'", fn);
+ return pcm;
+ }
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_INFO, &info)) {
+ oops(pcm, errno, "cannot get info");
+ goto fail_close;
+ }
+
+ param_init(&params);
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_FORMAT,
+ pcm_format_to_alsa(config->format));
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
+ SNDRV_PCM_SUBFORMAT_STD);
+ param_set_min(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, config->period_size);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ pcm_format_to_bits(config->format));
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
+ pcm_format_to_bits(config->format) * config->channels);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_CHANNELS,
+ config->channels);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_PERIODS, config->period_count);
+ param_set_int(&params, SNDRV_PCM_HW_PARAM_RATE, config->rate);
+
+ if (flags & PCM_NOIRQ) {
+
+ if (!(flags & PCM_MMAP)) {
+ oops(pcm, -EINVAL, "noirq only currently supported with mmap().");
+ goto fail;
+ }
+
+ params.flags |= SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP;
+ pcm->noirq_frames_per_msec = config->rate / 1000;
+ }
+
+ if (flags & PCM_MMAP)
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
+ SNDRV_PCM_ACCESS_MMAP_INTERLEAVED);
+ else
+ param_set_mask(&params, SNDRV_PCM_HW_PARAM_ACCESS,
+ SNDRV_PCM_ACCESS_RW_INTERLEAVED);
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_HW_PARAMS, &params)) {
+ oops(pcm, errno, "cannot set hw params");
+ goto fail_close;
+ }
+
+ /* get our refined hw_params */
+ config->period_size = param_get_int(&params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+ config->period_count = param_get_int(&params, SNDRV_PCM_HW_PARAM_PERIODS);
+ pcm->buffer_size = config->period_count * config->period_size;
+
+ if (flags & PCM_MMAP) {
+ pcm->mmap_buffer = mmap(NULL, pcm_frames_to_bytes(pcm, pcm->buffer_size),
+ PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, pcm->fd, 0);
+ if (pcm->mmap_buffer == MAP_FAILED) {
+ oops(pcm, -errno, "failed to mmap buffer %d bytes\n",
+ pcm_frames_to_bytes(pcm, pcm->buffer_size));
+ goto fail_close;
+ }
+ }
+
+
+ memset(&sparams, 0, sizeof(sparams));
+ sparams.tstamp_mode = SNDRV_PCM_TSTAMP_ENABLE;
+ sparams.period_step = 1;
+ sparams.avail_min = 1;
+
+ if (!config->start_threshold) {
+ if (pcm->flags & PCM_IN)
+ pcm->config.start_threshold = sparams.start_threshold = 1;
+ else
+ pcm->config.start_threshold = sparams.start_threshold =
+ config->period_count * config->period_size / 2;
+ } else
+ sparams.start_threshold = config->start_threshold;
+
+ /* pick a high stop threshold - todo: does this need further tuning */
+ if (!config->stop_threshold) {
+ if (pcm->flags & PCM_IN)
+ pcm->config.stop_threshold = sparams.stop_threshold =
+ config->period_count * config->period_size * 10;
+ else
+ pcm->config.stop_threshold = sparams.stop_threshold =
+ config->period_count * config->period_size;
+ }
+ else
+ sparams.stop_threshold = config->stop_threshold;
+
+ sparams.xfer_align = config->period_size / 2; /* needed for old kernels */
+ sparams.silence_size = 0;
+ sparams.silence_threshold = config->silence_threshold;
+ pcm->boundary = sparams.boundary = pcm->buffer_size;
+
+ while (pcm->boundary * 2 <= INT_MAX - pcm->buffer_size)
+ pcm->boundary *= 2;
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_SW_PARAMS, &sparams)) {
+ oops(pcm, errno, "cannot set sw params");
+ goto fail;
+ }
+
+ rc = pcm_hw_mmap_status(pcm);
+ if (rc < 0) {
+ oops(pcm, rc, "mmap status failed");
+ goto fail;
+ }
+
+ pcm->underruns = 0;
+ return pcm;
+
+fail:
+ if (flags & PCM_MMAP)
+ munmap(pcm->mmap_buffer, pcm_frames_to_bytes(pcm, pcm->buffer_size));
+fail_close:
+ close(pcm->fd);
+ pcm->fd = -1;
+ return pcm;
+}
+
+int pcm_is_ready(struct pcm *pcm)
+{
+ return pcm->fd >= 0;
+}
+
+int pcm_start(struct pcm *pcm)
+{
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_PREPARE) < 0)
+ return oops(pcm, errno, "cannot prepare channel");
+
+ if (pcm->flags & PCM_MMAP)
+ pcm_sync_ptr(pcm, 0);
+
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_START) < 0)
+ return oops(pcm, errno, "cannot start channel");
+
+ pcm->running = 1;
+ return 0;
+}
+
+int pcm_stop(struct pcm *pcm)
+{
+ if (ioctl(pcm->fd, SNDRV_PCM_IOCTL_DROP) < 0)
+ return oops(pcm, errno, "cannot stop channel");
+
+ pcm->running = 0;
+ return 0;
+}
+
+static inline int pcm_mmap_playback_avail(struct pcm *pcm)
+{
+ int avail;
+
+ avail = pcm->mmap_status->hw_ptr + pcm->buffer_size - pcm->mmap_control->appl_ptr;
+
+ if (avail < 0)
+ avail += pcm->boundary;
+ else if (avail > (int)pcm->boundary)
+ avail -= pcm->boundary;
+
+ return avail;
+}
+
+static inline int pcm_mmap_capture_avail(struct pcm *pcm)
+{
+ int avail = pcm->mmap_status->hw_ptr - pcm->mmap_control->appl_ptr;
+ if (avail < 0)
+ avail += pcm->boundary;
+ return avail;
+}
+
+static inline int pcm_mmap_avail(struct pcm *pcm)
+{
+ pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
+ if (pcm->flags & PCM_IN)
+ return pcm_mmap_capture_avail(pcm);
+ else
+ return pcm_mmap_playback_avail(pcm);
+}
+
+static void pcm_mmap_appl_forward(struct pcm *pcm, int frames)
+{
+ unsigned int appl_ptr = pcm->mmap_control->appl_ptr;
+ appl_ptr += frames;
+
+ /* check for boundary wrap */
+ if (appl_ptr > pcm->boundary)
+ appl_ptr -= pcm->boundary;
+ pcm->mmap_control->appl_ptr = appl_ptr;
+}
+
+int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset,
+ unsigned int *frames)
+{
+ unsigned int continuous, copy_frames, avail;
+
+ /* return the mmap buffer */
+ *areas = pcm->mmap_buffer;
+
+ /* and the application offset in frames */
+ *offset = pcm->mmap_control->appl_ptr % pcm->buffer_size;
+
+ avail = pcm_mmap_avail(pcm);
+ if (avail > pcm->buffer_size)
+ avail = pcm->buffer_size;
+ continuous = pcm->buffer_size - *offset;
+
+ /* we can only copy frames if the are availabale and continuos */
+ copy_frames = *frames;
+ if (copy_frames > avail)
+ copy_frames = avail;
+ if (copy_frames > continuous)
+ copy_frames = continuous;
+ *frames = copy_frames;
+
+ return 0;
+}
+
+int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames)
+{
+ (void)offset;
+ /* update the application pointer in userspace and kernel */
+ pcm_mmap_appl_forward(pcm, frames);
+ pcm_sync_ptr(pcm, 0);
+
+ return frames;
+}
+
+int pcm_avail_update(struct pcm *pcm)
+{
+ pcm_sync_ptr(pcm, 0);
+ return pcm_mmap_avail(pcm);
+}
+
+int pcm_state(struct pcm *pcm)
+{
+ int err = pcm_sync_ptr(pcm, 0);
+ if (err < 0)
+ return err;
+
+ return pcm->mmap_status->state;
+}
+
+int pcm_wait(struct pcm *pcm, int timeout)
+{
+ struct pollfd pfd;
+ int err;
+
+ pfd.fd = pcm->fd;
+ pfd.events = POLLOUT | POLLERR | POLLNVAL;
+
+ do {
+ /* let's wait for avail or timeout */
+ err = poll(&pfd, 1, timeout);
+ if (err < 0)
+ return -errno;
+
+ /* timeout ? */
+ if (err == 0)
+ return 0;
+
+ /* have we been interrupted ? */
+ if (errno == -EINTR)
+ continue;
+
+ /* check for any errors */
+ if (pfd.revents & (POLLERR | POLLNVAL)) {
+ switch (pcm_state(pcm)) {
+ case PCM_STATE_XRUN:
+ return -EPIPE;
+ case PCM_STATE_SUSPENDED:
+ return -ESTRPIPE;
+ case PCM_STATE_DISCONNECTED:
+ return -ENODEV;
+ default:
+ return -EIO;
+ }
+ }
+ /* poll again if fd not ready for IO */
+ } while (!(pfd.revents & (POLLIN | POLLOUT)));
+
+ return 1;
+}
+
+int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes)
+{
+ int err = 0, frames, avail;
+ unsigned int offset = 0, count;
+
+ if (bytes == 0)
+ return 0;
+
+ count = pcm_bytes_to_frames(pcm, bytes);
+
+ while (count > 0) {
+
+ /* get the available space for writing new frames */
+ avail = pcm_avail_update(pcm);
+ if (avail < 0) {
+ fprintf(stderr, "cannot determine available mmap frames");
+ return err;
+ }
+
+ /* start the audio if we reach the threshold */
+ if (!pcm->running &&
+ (pcm->buffer_size - avail) >= pcm->config.start_threshold) {
+ if (pcm_start(pcm) < 0) {
+ fprintf(stderr, "start error: hw 0x%x app 0x%x avail 0x%x\n",
+ (unsigned int)pcm->mmap_status->hw_ptr,
+ (unsigned int)pcm->mmap_control->appl_ptr,
+ avail);
+ return -errno;
+ }
+ }
+
+ /* sleep until we have space to write new frames */
+ if (pcm->running &&
+ (unsigned int)avail < pcm->mmap_control->avail_min) {
+ int time = -1;
+
+ if (pcm->flags & PCM_NOIRQ)
+ time = (pcm->buffer_size - avail - pcm->mmap_control->avail_min)
+ / pcm->noirq_frames_per_msec;
+
+ err = pcm_wait(pcm, time);
+ if (err < 0) {
+ pcm->running = 0;
+ fprintf(stderr, "wait error: hw 0x%x app 0x%x avail 0x%x\n",
+ (unsigned int)pcm->mmap_status->hw_ptr,
+ (unsigned int)pcm->mmap_control->appl_ptr,
+ avail);
+ pcm->mmap_control->appl_ptr = 0;
+ return err;
+ }
+ continue;
+ }
+
+ frames = count;
+ if (frames > avail)
+ frames = avail;
+
+ if (!frames)
+ break;
+
+ /* copy frames from buffer */
+ frames = pcm_mmap_write_areas(pcm, buffer, offset, frames);
+ if (frames < 0) {
+ fprintf(stderr, "write error: hw 0x%x app 0x%x avail 0x%x\n",
+ (unsigned int)pcm->mmap_status->hw_ptr,
+ (unsigned int)pcm->mmap_control->appl_ptr,
+ avail);
+ return frames;
+ }
+
+ offset += frames;
+ count -= frames;
+ }
+
+ return 0;
+}
diff --git a/firmware/target/hosted/android/system-android.c b/firmware/target/hosted/android/system-android.c
index d13b8d6462..6279504e48 100644
--- a/firmware/target/hosted/android/system-android.c
+++ b/firmware/target/hosted/android/system-android.c
@@ -23,6 +23,12 @@
#include <setjmp.h>
#include <jni.h>
#include <pthread.h>
+#if defined(DX50) || defined(DX90)
+#include <stdlib.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#endif /* DX50 || DX90 */
#include <unistd.h>
#include "config.h"
#include "system.h"
@@ -31,40 +37,83 @@
+#if !defined(DX50) && !defined(DX90)
/* global fields for use with various JNI calls */
static JavaVM *vm_ptr;
JNIEnv *env_ptr;
jobject RockboxService_instance;
jclass RockboxService_class;
+#endif /* !DX50 && !DX90 */
uintptr_t *stackbegin;
uintptr_t *stackend;
extern int main(void);
+#if !defined(DX50) && !defined(DX90)
extern void telephony_init_device(void);
-
+#endif
void system_exception_wait(void)
{
+#if defined(DX50) || defined(DX90)
+ while(1);
+#else
intptr_t dummy = 0;
while(button_read_device(&dummy) != BUTTON_BACK);
+#endif /* DX50 || DX90 */
}
void system_reboot(void)
{
+#if defined(DX50) || defined(DX90)
+ reboot(RB_AUTOBOOT);
+#else
power_off();
+#endif /* DX50 || DX90 */
}
+#if !defined(DX50) && !defined(DX90)
/* this is used to return from the entry point of the native library. */
static jmp_buf poweroff_buf;
+#endif
+
void power_off(void)
{
+#if defined(DX50) || defined(DX90)
+ reboot(RB_POWER_OFF);
+#else
longjmp(poweroff_buf, 1);
+#endif /* DX50 || DX90 */
}
void system_init(void)
{
+#if defined(DX50) || defined(DX90)
+ volatile uintptr_t stack = 0;
+ stackbegin = stackend = (uintptr_t*) &stack;
+
+ struct stat m1, m2;
+ stat("/mnt/", &m1);
+ do
+ {
+ /* waiting for storage to get mounted */
+ stat("/sdcard/", &m2);
+ usleep(100000);
+ }
+ while(m1.st_dev == m2.st_dev);
+/* here would be the correct place for 'system("/system/bin/muteopen");' (headphone-out relay) but in pcm-dx50.c, pcm_play_dma_start()
+ the output capacitors are charged already a bit and the click of the headphone-connection-relay is softer */
+
+#if defined(DX90)
+ /* DAC needs to be unmuted on DX90 */
+ FILE * f = fopen("/sys/class/codec/wm8740_mute", "w");
+ fputc(0, f);
+ fclose(f);
+#endif /* DX90 */
+
+#else
/* no better place yet */
telephony_init_device();
+#endif /* DX50 || DX90 */
}
int hostfs_init(void)
@@ -79,6 +128,7 @@ int hostfs_flush(void)
return 0;
}
+#if !defined(DX50) && !defined(DX90)
JNIEXPORT jint JNICALL
JNI_OnLoad(JavaVM *vm, void* reserved)
{
@@ -119,7 +169,7 @@ Java_org_rockbox_RockboxService_main(JNIEnv *env, jobject this)
/* simply return here. this will allow the VM to clean up objects and do
* garbage collection */
}
-
+#endif /* !DX50 && !DX90 */
/* below is the facility for external (from other java threads) to safely call
* into our snative code. When extracting rockbox.zip the main function is
diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c
index a4730a07d9..93fadc6d6e 100644
--- a/firmware/target/hosted/filesystem-app.c
+++ b/firmware/target/hosted/filesystem-app.c
@@ -104,6 +104,7 @@ void paths_init(void)
#if (CONFIG_PLATFORM & PLATFORM_ANDROID)
os_mkdir("/sdcard/rockbox" __MKDIR_MODE_ARG);
os_mkdir("/sdcard/rockbox/rocks.data" __MKDIR_MODE_ARG);
+ os_mkdir("/sdcard/rockbox/eqs" __MKDIR_MODE_ARG);
#else
char config_dir[MAX_PATH];
diff --git a/manual/rockbox_interface/images/ibassodx50-front.pdf b/manual/rockbox_interface/images/ibassodx50-front.pdf
new file mode 100644
index 0000000000..ab35104b47
--- /dev/null
+++ b/manual/rockbox_interface/images/ibassodx50-front.pdf
Binary files differ
diff --git a/manual/rockbox_interface/images/ibassodx50-front.png b/manual/rockbox_interface/images/ibassodx50-front.png
new file mode 100644
index 0000000000..cb81b0dab1
--- /dev/null
+++ b/manual/rockbox_interface/images/ibassodx50-front.png
Binary files differ
diff --git a/manual/rockbox_interface/images/ibassodx50-front.svg b/manual/rockbox_interface/images/ibassodx50-front.svg
new file mode 100644
index 0000000000..81f9c8ee8c
--- /dev/null
+++ b/manual/rockbox_interface/images/ibassodx50-front.svg
@@ -0,0 +1,1966 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="444.54602"
+ height="378.26721"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="manual-rockbox_interface-images-ibassodx50-front.svg"
+ style="display:inline"
+ inkscape:export-filename="/home/simon/Desktop/DX50 graph/manual-rockbox_interface-images-ibassodx50-front.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96">
+ <title
+ id="title6374">iBasso DX50</title>
+ <defs
+ id="defs4">
+ <linearGradient
+ id="linearGradient8592">
+ <stop
+ id="stop8594"
+ offset="0"
+ style="stop-color:#141414;stop-opacity:1;" />
+ <stop
+ id="stop8596"
+ offset="0.14162582"
+ style="stop-color:#070707;stop-opacity:1;" />
+ <stop
+ id="stop8598"
+ offset="0.87554538"
+ style="stop-color:#070707;stop-opacity:1;" />
+ <stop
+ style="stop-color:#020202;stop-opacity:1;"
+ offset="1"
+ id="stop8600" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient7455"
+ osb:paint="solid">
+ <stop
+ style="stop-color:#4f4f4f;stop-opacity:1;"
+ offset="0"
+ id="stop7457" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5151">
+ <stop
+ style="stop-color:#040404;stop-opacity:1;"
+ offset="0"
+ id="stop5153" />
+ <stop
+ id="stop5155"
+ offset="0.62867177"
+ style="stop-color:#191919;stop-opacity:1;" />
+ <stop
+ style="stop-color:#383838;stop-opacity:1;"
+ offset="0.88642782"
+ id="stop5157" />
+ <stop
+ id="stop5159"
+ offset="1"
+ style="stop-color:#434343;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient7633">
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1;"
+ offset="0"
+ id="stop7635" />
+ <stop
+ style="stop-color:#1e1e1e;stop-opacity:1;"
+ offset="0.14162582"
+ id="stop7637" />
+ <stop
+ style="stop-color:#191919;stop-opacity:1;"
+ offset="0.87554538"
+ id="stop7641" />
+ <stop
+ id="stop7643"
+ offset="1"
+ style="stop-color:#2a2a2a;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6376">
+ <stop
+ style="stop-color:#000000;stop-opacity:1"
+ offset="0"
+ id="stop6378" />
+ <stop
+ id="stop6380"
+ offset="0.54196042"
+ style="stop-color:#1a1a1a;stop-opacity:1" />
+ <stop
+ id="stop6382"
+ offset="0.60085368"
+ style="stop-color:#1a1a1a;stop-opacity:1" />
+ <stop
+ id="stop6384"
+ offset="0.65499872"
+ style="stop-color:#1a1a1a;stop-opacity:1" />
+ <stop
+ style="stop-color:#1a1a1a;stop-opacity:1"
+ offset="0.65499872"
+ id="stop6386" />
+ <stop
+ style="stop-color:#4d4d4d;stop-opacity:1"
+ offset="0.75479239"
+ id="stop6388" />
+ <stop
+ style="stop-color:#333333;stop-opacity:1"
+ offset="0.80990416"
+ id="stop6390" />
+ <stop
+ id="stop6392"
+ offset="1"
+ style="stop-color:#000000;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4">
+ <stop
+ style="stop-color:#3c3c3c;stop-opacity:1;"
+ offset="0"
+ id="stop6427-1" />
+ <stop
+ style="stop-color:#272727;stop-opacity:1;"
+ offset="1"
+ id="stop6429-8" />
+ </linearGradient>
+ <linearGradient
+ y2="3934.3799"
+ x2="4910.75"
+ y1="3743.74"
+ x1="4877.3301"
+ gradientUnits="userSpaceOnUse"
+ id="id2-33-6-4">
+ <stop
+ id="stop2999-7-3-7"
+ style="stop-color:#EFB000"
+ offset="0" />
+ <stop
+ id="stop3001-98-0-8"
+ style="stop-color:#A5732B"
+ offset="0.6" />
+ <stop
+ id="stop3003-6-2-7"
+ style="stop-color:#492A28"
+ offset="1" />
+ <stop
+ id="stop3005-7-0-4"
+ style="stop-color:#492A28"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient4997">
+ <stop
+ id="stop4999"
+ offset="0"
+ style="stop-color:#cccccc;stop-opacity:1" />
+ <stop
+ style="stop-color:#ffffff;stop-opacity:1"
+ offset="0.64489639"
+ id="stop5005" />
+ <stop
+ id="stop5001"
+ offset="1"
+ style="stop-color:#808080;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6077-8">
+ <stop
+ style="stop-color:#222222;stop-opacity:1;"
+ offset="0"
+ id="stop6079-3" />
+ <stop
+ id="stop6085-1"
+ offset="0.5"
+ style="stop-color:#353535;stop-opacity:1;" />
+ <stop
+ style="stop-color:#141414;stop-opacity:1;"
+ offset="1"
+ id="stop6081-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4-3-4">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9" />
+ <stop
+ id="stop5246"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9" />
+ </linearGradient>
+ <linearGradient
+ y2="6768.9199"
+ x2="-64.68"
+ y1="9531.0195"
+ x1="10064.7"
+ gradientUnits="userSpaceOnUse"
+ id="id11-5-1-5"
+ gradientTransform="translate(-15385.399,557.13145)">
+ <stop
+ id="stop129-5-8-9"
+ stop-color="#484A4C"
+ offset="0"
+ style="stop-color:#1e1e20;stop-opacity:1;" />
+ <stop
+ id="stop131-1-3-78"
+ stop-color="#252425"
+ offset="0.50980401"
+ style="stop-color:#312f31;stop-opacity:1;" />
+ <stop
+ id="stop133-0-3-1"
+ stop-color="#494747"
+ offset="1"
+ style="stop-color:#4d4b4b;stop-opacity:1;" />
+ <stop
+ id="stop135-8-4-9"
+ stop-color="#494747"
+ offset="1"
+ style="stop-color:#2c2c2c;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15570-9-9-5-1-8">
+ <stop
+ id="stop15572-8-1-4-9-6"
+ offset="0"
+ style="stop-color:#333333;stop-opacity:1" />
+ <stop
+ style="stop-color:#484848;stop-opacity:1"
+ offset="0.17310488"
+ id="stop15584-3-9-1-4-5" />
+ <stop
+ style="stop-color:#3b3b3b;stop-opacity:1"
+ offset="0.28851423"
+ id="stop15582-8-0-9-2-7" />
+ <stop
+ style="stop-color:#2f2f2f;stop-opacity:1"
+ offset="0.47606128"
+ id="stop15574-2-4-7-9-5" />
+ <stop
+ id="stop15576-8-6-0-6-5"
+ offset="0.7130661"
+ style="stop-color:#161616;stop-opacity:1" />
+ <stop
+ style="stop-color:#161616;stop-opacity:1"
+ offset="0.91021168"
+ id="stop15578-1-1-0-0-7" />
+ <stop
+ id="stop15580-4-6-1-6-2"
+ offset="1"
+ style="stop-color:#1d1d1d;stop-opacity:1" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ id="filter5226"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2194559"
+ id="feGaussianBlur5228" />
+ </filter>
+ <linearGradient
+ id="linearGradient6425-4-3-4-9">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9-3" />
+ <stop
+ id="stop5246-5"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248-37" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9-05" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4-3-4-1">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9-8" />
+ <stop
+ id="stop5246-24"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248-370" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4-3-4-1-0">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9-8-5" />
+ <stop
+ id="stop5246-24-8"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248-370-9" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9-6-6" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4-3-4-9-5">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9-3-9" />
+ <stop
+ id="stop5246-5-3"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248-37-1" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9-05-8" />
+ </linearGradient>
+ <filter
+ inkscape:collect="always"
+ id="filter6851"
+ x="-0.30888385"
+ width="1.6177677"
+ y="-0.27776667"
+ height="1.5555333"
+ color-interpolation-filters="sRGB">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.1547718"
+ id="feGaussianBlur6853" />
+ </filter>
+ <linearGradient
+ id="linearGradient5151-0">
+ <stop
+ style="stop-color:#040404;stop-opacity:1;"
+ offset="0"
+ id="stop5153-4" />
+ <stop
+ id="stop5155-8"
+ offset="0.62867177"
+ style="stop-color:#191919;stop-opacity:1;" />
+ <stop
+ style="stop-color:#383838;stop-opacity:1;"
+ offset="0.88642782"
+ id="stop5157-7" />
+ <stop
+ id="stop5159-5"
+ offset="1"
+ style="stop-color:#434343;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4-3-4-09">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9-0" />
+ <stop
+ id="stop5246-7"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248-8" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9-7" />
+ </linearGradient>
+ <filter
+ color-interpolation-filters="sRGB"
+ inkscape:collect="always"
+ id="filter5226-7">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2194559"
+ id="feGaussianBlur5228-7" />
+ </filter>
+ <linearGradient
+ y2="6768.9199"
+ x2="-64.68"
+ y1="9531.0195"
+ x1="10064.7"
+ gradientUnits="userSpaceOnUse"
+ id="id11-5-1-5-1"
+ gradientTransform="translate(-15385.399,557.13145)">
+ <stop
+ id="stop129-5-8-9-6"
+ stop-color="#484A4C"
+ offset="0"
+ style="stop-color:#1e1e20;stop-opacity:1;" />
+ <stop
+ id="stop131-1-3-78-5"
+ stop-color="#252425"
+ offset="0.50980401"
+ style="stop-color:#312f31;stop-opacity:1;" />
+ <stop
+ id="stop133-0-3-1-7"
+ stop-color="#494747"
+ offset="1"
+ style="stop-color:#4d4b4b;stop-opacity:1;" />
+ <stop
+ id="stop135-8-4-9-9"
+ stop-color="#494747"
+ offset="1"
+ style="stop-color:#2c2c2c;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15570-9-9-5-1-8-8">
+ <stop
+ id="stop15572-8-1-4-9-6-1"
+ offset="0"
+ style="stop-color:#333333;stop-opacity:1" />
+ <stop
+ style="stop-color:#484848;stop-opacity:1"
+ offset="0.17310488"
+ id="stop15584-3-9-1-4-5-8" />
+ <stop
+ style="stop-color:#3b3b3b;stop-opacity:1"
+ offset="0.28851423"
+ id="stop15582-8-0-9-2-7-9" />
+ <stop
+ style="stop-color:#2f2f2f;stop-opacity:1"
+ offset="0.47606128"
+ id="stop15574-2-4-7-9-5-85" />
+ <stop
+ id="stop15576-8-6-0-6-5-66"
+ offset="0.7130661"
+ style="stop-color:#161616;stop-opacity:1" />
+ <stop
+ style="stop-color:#161616;stop-opacity:1"
+ offset="0.91021168"
+ id="stop15578-1-1-0-0-7-1" />
+ <stop
+ id="stop15580-4-6-1-6-2-6"
+ offset="1"
+ style="stop-color:#1d1d1d;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient5151-3">
+ <stop
+ style="stop-color:#040404;stop-opacity:1;"
+ offset="0"
+ id="stop5153-8" />
+ <stop
+ id="stop5155-1"
+ offset="0.62867177"
+ style="stop-color:#191919;stop-opacity:1;" />
+ <stop
+ style="stop-color:#383838;stop-opacity:1;"
+ offset="0.88642782"
+ id="stop5157-6" />
+ <stop
+ id="stop5159-51"
+ offset="1"
+ style="stop-color:#434343;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient6425-4-3-4-5">
+ <stop
+ style="stop-color:#757575;stop-opacity:1"
+ offset="0"
+ id="stop6427-1-6-9-1" />
+ <stop
+ id="stop5246-28"
+ offset="0.07079889"
+ style="stop-color:#6d6d6d;stop-opacity:1;" />
+ <stop
+ style="stop-color:#2e2e2e;stop-opacity:1;"
+ offset="0.21239667"
+ id="stop5248-79" />
+ <stop
+ style="stop-color:#1b1b1b;stop-opacity:1"
+ offset="1"
+ id="stop6429-8-1-9-58" />
+ </linearGradient>
+ <filter
+ color-interpolation-filters="sRGB"
+ inkscape:collect="always"
+ id="filter5226-8">
+ <feGaussianBlur
+ inkscape:collect="always"
+ stdDeviation="1.2194559"
+ id="feGaussianBlur5228-51" />
+ </filter>
+ <linearGradient
+ y2="6768.9199"
+ x2="-64.68"
+ y1="9531.0195"
+ x1="10064.7"
+ gradientUnits="userSpaceOnUse"
+ id="id11-5-1-5-41"
+ gradientTransform="translate(-15385.399,557.13145)">
+ <stop
+ id="stop129-5-8-9-4"
+ stop-color="#484A4C"
+ offset="0"
+ style="stop-color:#1e1e20;stop-opacity:1;" />
+ <stop
+ id="stop131-1-3-78-18"
+ stop-color="#252425"
+ offset="0.50980401"
+ style="stop-color:#312f31;stop-opacity:1;" />
+ <stop
+ id="stop133-0-3-1-79"
+ stop-color="#494747"
+ offset="1"
+ style="stop-color:#4d4b4b;stop-opacity:1;" />
+ <stop
+ id="stop135-8-4-9-6"
+ stop-color="#494747"
+ offset="1"
+ style="stop-color:#2c2c2c;stop-opacity:1;" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient15570-9-9-5-1-8-5">
+ <stop
+ id="stop15572-8-1-4-9-6-4"
+ offset="0"
+ style="stop-color:#333333;stop-opacity:1" />
+ <stop
+ style="stop-color:#484848;stop-opacity:1"
+ offset="0.17310488"
+ id="stop15584-3-9-1-4-5-80" />
+ <stop
+ style="stop-color:#3b3b3b;stop-opacity:1"
+ offset="0.28851423"
+ id="stop15582-8-0-9-2-7-3" />
+ <stop
+ style="stop-color:#2f2f2f;stop-opacity:1"
+ offset="0.47606128"
+ id="stop15574-2-4-7-9-5-9" />
+ <stop
+ id="stop15576-8-6-0-6-5-60"
+ offset="0.7130661"
+ style="stop-color:#161616;stop-opacity:1" />
+ <stop
+ style="stop-color:#161616;stop-opacity:1"
+ offset="0.91021168"
+ id="stop15578-1-1-0-0-7-3" />
+ <stop
+ id="stop15580-4-6-1-6-2-9"
+ offset="1"
+ style="stop-color:#1d1d1d;stop-opacity:1" />
+ </linearGradient>
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7633"
+ id="linearGradient3472"
+ gradientUnits="userSpaceOnUse"
+ x1="55.85672"
+ y1="335.20624"
+ x2="66.763878"
+ y2="335.20624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4997"
+ id="linearGradient3474"
+ gradientUnits="userSpaceOnUse"
+ spreadMethod="pad"
+ x1="55.90625"
+ y1="316.375"
+ x2="66.71875"
+ y2="316.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151"
+ id="linearGradient3478"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient3480"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5"
+ id="linearGradient3482"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8"
+ id="linearGradient3484"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151-3"
+ id="linearGradient3486"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-5"
+ id="linearGradient3488"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5-41"
+ id="linearGradient3490"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8-5"
+ id="linearGradient3492"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id2-33-6-4"
+ id="linearGradient3498"
+ gradientUnits="userSpaceOnUse"
+ x1="4877.3301"
+ y1="3743.74"
+ x2="4910.75"
+ y2="3934.3799" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151-0"
+ id="linearGradient3500"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-09"
+ id="linearGradient3502"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5-1"
+ id="linearGradient3504"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8-8"
+ id="linearGradient3506"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1-0"
+ id="linearGradient3446"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,117.00472)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9"
+ id="linearGradient3449"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.36298039,1.1528432,0,49.539774,111.72068)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient3452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.38527708,0.78727403,0,58.433234,56.29863)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6376"
+ id="linearGradient3483"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566734,-139.2058)"
+ x1="48.236862"
+ y1="215.45312"
+ x2="279.76315"
+ y2="304.45312" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4"
+ id="linearGradient3495"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0132067,-8.433266,-96.898305)"
+ x1="100.82813"
+ y1="319.75"
+ x2="298.17188"
+ y2="319.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8592"
+ id="linearGradient3501"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566734,-139.2058)"
+ x1="271.37906"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6077-8"
+ id="linearGradient3505"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566734,-139.2058)"
+ x1="55.419907"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1"
+ id="linearGradient3509"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,66.045134)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9-5"
+ id="linearGradient3513"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.36298039,0,0,-1.1528432,249.0045,382.24845)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9-5"
+ id="linearGradient4338"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.36298039,0,0,-1.1528432,249.0045,382.24845)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1"
+ id="linearGradient4340"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,66.045134)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6077-8"
+ id="linearGradient4342"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566734,-139.2058)"
+ x1="55.419907"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8592"
+ id="linearGradient4344"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566734,-139.2058)"
+ x1="271.37906"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7633"
+ id="linearGradient4346"
+ gradientUnits="userSpaceOnUse"
+ x1="55.85672"
+ y1="335.20624"
+ x2="66.763878"
+ y2="335.20624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4997"
+ id="linearGradient4348"
+ gradientUnits="userSpaceOnUse"
+ spreadMethod="pad"
+ x1="55.90625"
+ y1="316.375"
+ x2="66.71875"
+ y2="316.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4"
+ id="linearGradient4350"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0132067,-8.433266,-96.898305)"
+ x1="100.82813"
+ y1="319.75"
+ x2="298.17188"
+ y2="319.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151"
+ id="linearGradient4352"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient4354"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5"
+ id="linearGradient4356"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8"
+ id="linearGradient4358"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151-3"
+ id="linearGradient4360"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-5"
+ id="linearGradient4362"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5-41"
+ id="linearGradient4364"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8-5"
+ id="linearGradient4366"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6376"
+ id="linearGradient4368"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566734,-139.2058)"
+ x1="48.236862"
+ y1="215.45312"
+ x2="279.76315"
+ y2="304.45312" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id2-33-6-4"
+ id="linearGradient4370"
+ gradientUnits="userSpaceOnUse"
+ x1="4877.3301"
+ y1="3743.74"
+ x2="4910.75"
+ y2="3934.3799" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151-0"
+ id="linearGradient4372"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-09"
+ id="linearGradient4374"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5-1"
+ id="linearGradient4376"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8-8"
+ id="linearGradient4378"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient4380"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.38527708,0.78727403,0,58.433234,56.29863)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9"
+ id="linearGradient4382"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.36298039,1.1528432,0,49.539774,111.72068)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1-0"
+ id="linearGradient4384"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,117.00472)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1-0"
+ id="linearGradient4397"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,117.00472)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9"
+ id="linearGradient4400"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.36298039,1.1528432,0,49.539772,111.72068)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient4403"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.38527708,0.78727403,0,58.433232,56.29863)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6376"
+ id="linearGradient4430"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566732,-139.2058)"
+ x1="48.236862"
+ y1="215.45312"
+ x2="279.76315"
+ y2="304.45312" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4"
+ id="linearGradient4441"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0132067,-8.4332679,-96.898305)"
+ x1="100.82813"
+ y1="319.75"
+ x2="298.17188"
+ y2="319.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8592"
+ id="linearGradient4446"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566732,-139.2058)"
+ x1="271.37906"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6077-8"
+ id="linearGradient4449"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566732,-139.2058)"
+ x1="55.419907"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1"
+ id="linearGradient4452"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,66.045134)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9-5"
+ id="linearGradient4455"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.36298039,0,0,-1.1528432,249.0045,382.24845)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9-5"
+ id="linearGradient4530"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(-0.36298039,0,0,-1.1528432,249.0045,382.24845)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1"
+ id="linearGradient4532"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,66.045134)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6077-8"
+ id="linearGradient4534"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566732,-139.2058)"
+ x1="55.419907"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient8592"
+ id="linearGradient4536"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566732,-139.2058)"
+ x1="271.37906"
+ y1="316.37115"
+ x2="283.19156"
+ y2="316.37115" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient7633"
+ id="linearGradient4538"
+ gradientUnits="userSpaceOnUse"
+ x1="55.85672"
+ y1="335.20624"
+ x2="66.763878"
+ y2="335.20624" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient4997"
+ id="linearGradient4540"
+ gradientUnits="userSpaceOnUse"
+ spreadMethod="pad"
+ x1="55.90625"
+ y1="316.375"
+ x2="66.71875"
+ y2="316.375" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4"
+ id="linearGradient4542"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(1,0,0,1.0132067,-8.4332679,-96.898305)"
+ x1="100.82813"
+ y1="319.75"
+ x2="298.17188"
+ y2="319.75" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151"
+ id="linearGradient4544"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient4546"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5"
+ id="linearGradient4548"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8"
+ id="linearGradient4550"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151-3"
+ id="linearGradient4552"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-5"
+ id="linearGradient4554"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5-41"
+ id="linearGradient4556"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8-5"
+ id="linearGradient4558"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6376"
+ id="linearGradient4560"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(21.566732,-139.2058)"
+ x1="48.236862"
+ y1="215.45312"
+ x2="279.76315"
+ y2="304.45312" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id2-33-6-4"
+ id="linearGradient4562"
+ gradientUnits="userSpaceOnUse"
+ x1="4877.3301"
+ y1="3743.74"
+ x2="4910.75"
+ y2="3934.3799" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient5151-0"
+ id="linearGradient4564"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54877,627.16011)"
+ x1="-174.27351"
+ y1="-332.50967"
+ x2="-117.25081"
+ y2="-275.30774" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-09"
+ id="linearGradient4566"
+ gradientUnits="userSpaceOnUse"
+ x1="228.29796"
+ y1="351.85236"
+ x2="171.27525"
+ y2="294.65045" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#id11-5-1-5-1"
+ id="linearGradient4568"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient15570-9-9-5-1-8-8"
+ id="linearGradient4570"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="translate(345.54875,627.16011)"
+ x1="-169.15022"
+ y1="-321.3381"
+ x2="-120.44732"
+ y2="-285.0881" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4"
+ id="linearGradient4572"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.38527708,0.78727403,0,58.433232,56.29863)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-9"
+ id="linearGradient4574"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.36298039,1.1528432,0,49.539772,111.72068)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ <linearGradient
+ inkscape:collect="always"
+ xlink:href="#linearGradient6425-4-3-4-1-0"
+ id="linearGradient4576"
+ gradientUnits="userSpaceOnUse"
+ gradientTransform="matrix(0,-0.59788346,-0.78727403,0,323.3037,117.00472)"
+ x1="50.204582"
+ y1="24.731405"
+ x2="50.204582"
+ y2="21.0718" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="1"
+ inkscape:cx="277.79436"
+ inkscape:cy="98.864744"
+ inkscape:document-units="mm"
+ inkscape:current-layer="svg2"
+ showgrid="false"
+ inkscape:snap-bbox="false"
+ inkscape:object-nodes="false"
+ inkscape:snap-smooth-nodes="false"
+ inkscape:snap-bbox-midpoints="false"
+ inkscape:snap-bbox-edge-midpoints="true"
+ inkscape:bbox-nodes="true"
+ inkscape:bbox-paths="true"
+ inkscape:snap-object-midpoints="true"
+ inkscape:snap-center="false"
+ showguides="true"
+ inkscape:guide-bbox="true"
+ inkscape:window-width="1351"
+ inkscape:window-height="925"
+ inkscape:window-x="116"
+ inkscape:window-y="239"
+ inkscape:window-maximized="0"
+ inkscape:snap-nodes="true"
+ inkscape:snap-to-guides="true"
+ inkscape:snap-global="false"
+ units="mm"
+ fit-margin-top="0"
+ fit-margin-left="0.8"
+ fit-margin-right="0"
+ fit-margin-bottom="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>iBasso DX50</dc:title>
+ <cc:license
+ rdf:resource="http://creativecommons.org/licenses/by-sa/3.0/" />
+ <dc:date>2014-05-01</dc:date>
+ <dc:creator>
+ <cc:Agent>
+ <dc:title>Simon Rothen</dc:title>
+ </cc:Agent>
+ </dc:creator>
+ </cc:Work>
+ <cc:License
+ rdf:about="http://creativecommons.org/licenses/by-sa/3.0/">
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Reproduction" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#Distribution" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Notice" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#Attribution" />
+ <cc:permits
+ rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+ <cc:requires
+ rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+ </cc:License>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="Text"
+ transform="translate(-10.784083,-93.2058)">
+ <text
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000012px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Palatino Linotype;-inkscape-font-specification:Palatino Linotype"
+ xml:space="preserve"
+ id="text2869"
+ y="187.98181"
+ x="322.31253"
+ sodipodi:linespacing="100%"
+ inkscape:export-filename="/home/marko/Dropbox/Public/clipplus.png"
+ inkscape:export-xdpi="96.824623"
+ inkscape:export-ydpi="96.824623"><tspan
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000012px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Palatino Linotype;-inkscape-font-specification:Palatino Linotype"
+ id="tspan2871"
+ y="187.98181"
+ x="322.31253">Volume down</tspan></text>
+ <text
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000012px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Palatino Linotype;-inkscape-font-specification:Palatino Linotype"
+ xml:space="preserve"
+ id="text2875"
+ y="137.01501"
+ x="322.31253"
+ sodipodi:linespacing="100%"
+ inkscape:export-filename="/home/marko/Dropbox/Public/clipplus.png"
+ inkscape:export-xdpi="96.824623"
+ inkscape:export-ydpi="96.824623"><tspan
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-indent:0;text-align:start;text-decoration:none;line-height:100%;letter-spacing:normal;word-spacing:normal;text-transform:none;direction:ltr;block-progression:tb;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000012px;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;font-family:Palatino Linotype;-inkscape-font-specification:Palatino Linotype"
+ id="tspan2877"
+ y="137.01501"
+ x="322.31253">Volume up</tspan></text>
+ </g>
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="C:\cygwin\home\Marianne\rockbox-patched\trunk\manual\rockbox_interface\images\mrobe100-front.png"
+ sodipodi:linespacing="125%"
+ id="text2289"
+ y="44.155655"
+ x="2.5209403"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Palatino Linotype"
+ xml:space="preserve"><tspan
+ y="44.155655"
+ x="2.5209403"
+ id="tspan2291"
+ sodipodi:role="line"
+ style="font-size:20px">Power</tspan></text>
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="C:\cygwin\home\Marianne\rockbox-patched\trunk\manual\rockbox_interface\images\mrobe100-front.png"
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Palatino Linotype"
+ x="14.358284"
+ y="99.973114"
+ id="text3263"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3265"
+ x="14.358284"
+ y="99.973114"
+ style="font-size:20px">Hold</tspan></text>
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="C:\cygwin\home\Marianne\rockbox-patched\trunk\manual\rockbox_interface\images\mrobe100-front.png"
+ xml:space="preserve"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Palatino Linotype"
+ x="0.87175506"
+ y="226.6767"
+ id="text3271"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3273"
+ x="0.87175506"
+ y="226.6767"
+ style="font-size:20px">Prev</tspan></text>
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="C:\cygwin\home\Marianne\rockbox-patched\trunk\manual\rockbox_interface\images\mrobe100-front.png"
+ sodipodi:linespacing="125%"
+ id="text3283"
+ y="315.7233"
+ x="318.98553"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Palatino Linotype"
+ xml:space="preserve"><tspan
+ y="315.7233"
+ x="318.98553"
+ id="tspan3285"
+ sodipodi:role="line"
+ style="font-size:20px">Play</tspan></text>
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="C:\cygwin\home\Marianne\rockbox-patched\trunk\manual\rockbox_interface\images\mrobe100-front.png"
+ xml:space="preserve"
+ style="font-size:30px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Palatino Linotype"
+ x="321.58533"
+ y="240.20337"
+ id="text3287"
+ sodipodi:linespacing="125%"><tspan
+ sodipodi:role="line"
+ id="tspan3289"
+ x="321.58533"
+ y="240.20337"
+ style="font-size:20px">Next</tspan></text>
+ <text
+ inkscape:export-ydpi="72"
+ inkscape:export-xdpi="72"
+ inkscape:export-filename="C:\cygwin\home\Marianne\rockbox-patched\trunk\manual\rockbox_interface\images\mrobe100-front.png"
+ sodipodi:linespacing="125%"
+ id="text3291-4"
+ y="377.98401"
+ x="204.79172"
+ style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;display:inline;enable-background:new;font-family:Palatino Linotype"
+ xml:space="preserve"><tspan
+ id="tspan3489"
+ y="377.98401"
+ x="204.79172"
+ sodipodi:role="line"
+ style="font-size:20px">Gain</tspan></text>
+ <g
+ id="g4475"
+ transform="translate(-2.3508149,0)">
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ sodipodi:nodetypes="ccccc"
+ id="path6390-4-7-2"
+ d="m 236.75674,354.31344 c 0,0 0.0286,3.10604 -0.56816,3.05693 l -10.63689,0.0625 c -0.8278,-0.0129 -0.74597,-3.11944 -0.74597,-3.11944 z"
+ style="fill:url(#linearGradient4530);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ sodipodi:nodetypes="ccccc"
+ id="path6390-4-2"
+ d="m 304.22694,45.87121 c 0,0 2.22674,-0.92481 2.08757,-1.98171 l 0,-15.21964 c -0.0696,-1.4797 -2.08758,-2.48378 -2.08758,-2.48378 l 1e-5,19.68513 z"
+ style="fill:url(#linearGradient4532);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ id="rect4585-1"
+ d="M 87.652992,0 294.09195,0 c 5.63216,0 10.16635,4.53419 10.16635,10.16634 l 0,333.99803 c 0,5.63215 -4.53419,10.16634 -10.16635,10.16634 l -206.438958,0 c -5.63216,0 -10.16635,-4.53419 -10.16635,-10.16634 l 0,-333.99803 C 77.486642,4.53419 82.020832,0 87.652992,0 z"
+ style="fill:url(#linearGradient4534);fill-opacity:1;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ id="rect4585-6"
+ d="m 294.0708,0.00911 c 5.63216,0 10.1875,4.5241 10.1875,10.15625 l 0,334 c 0,5.63215 -4.55534,10.15625 -10.1875,10.15625 l -0.625,0 0,-354.3125 0.625,0 z"
+ style="fill:url(#linearGradient4536);fill-opacity:1;stroke:none;display:inline"
+ inkscape:connector-curvature="0" />
+ <g
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ transform="translate(21.566732,-139.2058)"
+ style="fill:url(#linearGradient4540);fill-opacity:1;stroke:none"
+ id="g7480">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient4538);fill-opacity:1;stroke:none"
+ d="m 66.09375,139.21875 c -5.632157,0 -10.1875,4.5241 -10.1875,10.15625 l 0,334 c 0,5.63215 4.555343,10.15625 10.1875,10.15625 l 0.625,0 0,-354.3125 -0.625,0 z"
+ id="rect4585" />
+ </g>
+ <path
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:connector-curvature="0"
+ id="rect3520"
+ d="m 92.394952,186.38795 0,59.49423 0.0937,0 0,16.5596 c 0,2.94489 2.34349,5.31933 5.25,5.31933 l 186.656258,0 c 2.90652,0 5.25,-2.37444 5.25,-5.31933 l 0,-16.5596 0.0937,0 0,-59.49423 -197.343748,0 z"
+ style="fill:url(#linearGradient4542);fill-opacity:1;stroke:#101010;stroke-width:0.70866144;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <g
+ transform="translate(-8.4332679,-93.2058)"
+ id="g6938">
+ <rect
+ style="fill:url(#linearGradient4544);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4546);stroke-width:0.99212599;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="rect4922-1-1-7"
+ width="56.692913"
+ height="56.692913"
+ x="171.15355"
+ y="294.72559"
+ ry="13.143503"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;filter:url(#filter5226)"
+ d="m 186.09375,300.59375 c -5.02091,0 -9.09375,4.03754 -9.09375,9.0625 l 0,26.8125 c 0,5.02496 4.06879,9.09375 9.09375,9.09375 l 26.8125,0 c 5.02496,0 9.09375,-4.06879 9.09375,-9.09375 l 0,-26.8125 c 0,-5.02496 -4.07284,-9.0625 -9.09375,-9.0625 l -26.8125,0 z"
+ id="path4397" />
+ <rect
+ style="fill:url(#linearGradient4548);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4550);stroke-width:0.99921262;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="rect4922-5-6-6-7"
+ width="40.202908"
+ height="40.202908"
+ x="179.39854"
+ y="302.97058"
+ ry="6.6378174"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96" />
+ </g>
+ <g
+ id="g6938-4"
+ style="display:inline"
+ transform="translate(-71.417325,-93.2058)">
+ <rect
+ style="fill:url(#linearGradient4552);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4554);stroke-width:0.99212599;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="rect4922-1-1-7-3"
+ width="56.692913"
+ height="56.692913"
+ x="171.15355"
+ y="294.72559"
+ ry="13.143503"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;filter:url(#filter5226-8)"
+ d="m 186.09375,300.59375 c -5.02091,0 -9.09375,4.03754 -9.09375,9.0625 l 0,26.8125 c 0,5.02496 4.06879,9.09375 9.09375,9.09375 l 26.8125,0 c 5.02496,0 9.09375,-4.06879 9.09375,-9.09375 l 0,-26.8125 c 0,-5.02496 -4.07284,-9.0625 -9.09375,-9.0625 l -26.8125,0 z"
+ id="path4397-3" />
+ <rect
+ style="fill:url(#linearGradient4556);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4558);stroke-width:0.99921262;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="rect4922-5-6-6-7-31"
+ width="40.202908"
+ height="40.202908"
+ x="179.39854"
+ y="302.97058"
+ ry="6.6378174"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96" />
+ </g>
+ <path
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:connector-curvature="0"
+ id="rect4587"
+ d="m 96.910482,10.1067 c -2.52849,0 -4.5625,2.06526 -4.5625,4.59375 l 0,33.21875 -0.0625,0 0,138.46875 197.562508,0 0,-138.46875 -0.0312,0 0,-33.21875 c 0,-2.52849 -2.03402,-4.59375 -4.5625,-4.59375 l -188.343758,0 z"
+ style="fill:url(#linearGradient4560);fill-opacity:1;stroke:#101010;stroke-width:0.70866144;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <path
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:connector-curvature="0"
+ id="rect4587-8"
+ d="m 96.910482,10.106696 c -2.52849,0 -4.5625,2.065259 -4.5625,4.593749 l 0,33.218751 -0.0625,0 0,138.468754 197.562508,0 0,-138.468754 -0.0312,0 0,-33.218751 c 0,-2.52849 -2.03402,-4.593749 -4.5625,-4.593749 l -188.343758,0 z"
+ style="fill:#111111;fill-opacity:1;stroke:#101010;stroke-width:0.70866144;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" />
+ <rect
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ ry="0"
+ y="25.918993"
+ x="104.78932"
+ height="130.0571"
+ width="172.57677"
+ id="rect4589"
+ style="fill:#212121;fill-opacity:1;stroke:none" />
+ <g
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ id="g3054"
+ style="fill-rule:evenodd;display:inline;enable-background:new"
+ transform="matrix(0.08694953,0,0,0.08694953,-168.36562,-265.39841)">
+ <path
+ style="fill:#131516"
+ id="path3056"
+ d="m 3141.69,4007.74 1984.33,0 0,-614.37 -1984.33,0 0,614.37 0,0 z"
+ class="fil6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#ffffff"
+ id="path3058"
+ d="m 3267.19,3972.16 c 0,-8.6299 -7,-15.626 -15.6299,-15.626 -8.6299,0 -15.626,6.9961 -15.626,15.626 0,8.6339 6.9961,15.6299 15.626,15.6299 8.6299,0 15.6299,-6.9961 15.6299,-15.6299 z m 49.0866,-13.0787 c 6.2795,-4.2756 14.626,-3.063 19.5472,2.8307 4.9252,5.8977 4.9252,14.6811 0,20.5787 -4.9213,5.8977 -13.2677,7.1063 -19.5472,2.8347 l 0,12.9488 -8.2795,0 0,-40.9803 8.2795,0 0,1.7874 0,0 z m 94.5079,13.0787 c 0,-8.6299 -7,-15.6299 -15.6299,-15.6299 -8.6299,0 -15.626,7 -15.626,15.6299 0,8.6339 6.9961,15.6299 15.626,15.6299 4.4449,0 8.4646,-1.8583 11.311,-4.8425 l -5.9803,-5.7047 5.9803,5.7047 -5.9803,-5.7047 c -1.5315,1.6063 -3.7126,2.437 -5.9331,2.2559 -2.2126,-0.1851 -4.2244,-1.3622 -5.4764,-3.2008 l 21.1535,0 c 0.3622,-1.3189 0.5552,-2.7047 0.5552,-4.1378 l 0,0 z m 519.035,0 c 0,-8.6299 -6.9961,-15.6299 -15.626,-15.6299 -8.6299,0 -15.626,7 -15.626,15.6299 0,8.6339 6.9961,15.6299 15.626,15.6299 4.4488,0 8.4646,-1.8583 11.311,-4.8425 l -5.9803,-5.7047 5.9803,5.7047 -5.9803,-5.7047 c -1.5354,1.6063 -3.7126,2.437 -5.9291,2.2559 -2.2166,-0.1851 -4.2284,-1.3622 -5.4803,-3.2008 l 21.1574,0 c 0.3583,-1.3189 0.5473,-2.7047 0.5473,-4.1378 l 0,0 z m 308.854,0 c 0,-8.6299 -6.9961,-15.6299 -15.6299,-15.6299 -8.626,0 -15.626,7 -15.626,15.6299 0,8.6339 7,15.6299 15.626,15.6299 4.4488,0 8.4646,-1.8583 11.311,-4.8425 l -5.9764,-5.7047 5.9764,5.7047 -5.9764,-5.7047 c -1.5354,1.6063 -3.7126,2.437 -5.9331,2.2559 -2.2126,-0.1851 -4.2283,-1.3622 -5.4803,-3.2008 l 21.1575,0 c 0.3622,-1.3189 0.5512,-2.7047 0.5512,-4.1378 l 0,0 z m 789.339,0 c 0,-8.6299 -6.9961,-15.6299 -15.6299,-15.6299 -8.626,0 -15.622,7 -15.622,15.6299 0,8.6339 6.9961,15.6299 15.622,15.6299 4.4528,0 8.4685,-1.8583 11.315,-4.8425 l -5.9803,-5.7047 5.9803,5.7047 -5.9803,-5.7047 c -1.5354,1.6063 -3.7166,2.437 -5.9291,2.2559 -2.2166,-0.1851 -4.2284,-1.3622 -5.4804,-3.2008 l 21.1535,0 c 0.3623,-1.3189 0.5512,-2.7047 0.5512,-4.1378 l 0,0 z m -1549.48,-2.3189 c 0,-5.0079 -2.4331,-9.5906 -6.3071,-11.8583 -3.874,-2.2717 -8.5197,-1.8465 -12.0354,1.0984 l 0,-1.7874 -8.2795,0 0,29.8189 8.2795,0 0,-17.2717 c 0,-2.7834 2.252,-5.0393 5.0315,-5.0393 2.7835,0 5.0354,2.2559 5.0354,5.0393 l 0,17.2717 8.2756,0 0,-17.2717 0,1e-4 z m 119.693,-3.8622 c 0,-3.9606 -2.9882,-7.5 -7.4764,-8.8622 -4.4882,-1.3661 -9.5315,-0.2756 -12.6299,2.7402 -3.1023,3.0196 -3.5984,7.3149 -1.248,10.7598 1.185,1.6614 2.8779,2.8897 4.8228,3.496 2.2008,0.7362 4.4528,1.3386 6.7284,1.7992 1.8661,0.3622 2.8464,1.2914 2.3031,2.1772 -0.5433,0.8819 -2.4527,1.4488 -4.4646,1.3228 -2.0118,-0.122 -3.5157,-0.9015 -3.5157,-1.8189 l 0,-0.8819 -8.2677,0 0,0.8819 c 0,4.3898 3.3464,8.2953 8.3307,9.7205 4.9803,1.4252 10.5039,0.055 13.7362,-3.4095 3.2362,-3.4566 3.4764,-8.2559 0.5905,-11.9331 -1.6653,-1.9448 -3.9606,-3.248 -6.4842,-3.6732 -2,-0.374 -3.9764,-0.8582 -5.9252,-1.4409 -1.0787,-0.3583 -1.3701,-0.9449 -0.6969,-1.4252 0.6772,-0.4764 2.1339,-0.7205 3.5355,-0.5945 1.4015,0.1299 2.3897,0.6024 2.3897,1.1417 l 0,0.4095 8.2717,0 0,-0.4095 0,1e-4 z m 71.9921,6.1811 c 0,-8.6299 -6.9961,-15.626 -15.626,-15.626 -8.6339,0 -15.626,6.9961 -15.626,15.626 0,8.6339 6.9921,15.6299 15.626,15.6299 8.6299,0 15.626,-6.9961 15.626,-15.6299 z m 40.9843,2.4055 0,-17.2717 8.2795,0 0,17.2717 c 0,2.7835 2.2559,5.0354 5.0315,5.0354 2.7835,0 5.0355,-2.2519 5.0355,-5.0354 l 0,-17.2717 8.2755,0 0,29.8189 -8.2755,0 0,-1.7874 c -3.5119,2.9449 -8.1615,3.3701 -12.0354,1.0984 -3.8701,-2.2716 -6.3111,-6.8504 -6.3111,-11.8583 l 0,1e-4 z m 76.5787,-15.4843 0,-1.7874 -8.2756,0 0,29.8189 8.2756,0 0,-14.9528 c 0,-1.9488 0.7756,-3.8228 2.1535,-5.2008 1.378,-1.3819 3.252,-2.1575 5.2048,-2.1575 l 0,-8.2441 c -2.6221,0.1575 -5.1575,1.0237 -7.3583,2.5237 l 0,0 z m 72.8228,2.2913 c -2.8465,-2.9803 -6.8622,-4.8425 -11.311,-4.8425 -8.626,0 -15.622,6.9961 -15.626,15.626 0,0 0,0 0,0 0,8.6299 7,15.626 15.626,15.626 4.4488,0 8.4646,-1.8583 11.311,-4.8426 l -5.9803,-5.7047 c -1.3386,1.4016 -3.2284,2.2756 -5.3189,2.2756 -4.063,0 -7.3583,-3.2913 -7.3583,-7.3543 0,0 0,0 0,0 0,-4.059 3.2953,-7.3543 7.3583,-7.3543 2.0905,0 3.9803,0.878 5.3189,2.2795 l 5.9803,-5.7086 0,-1e-4 z m 958.004,10.7677 -4.2677,-14.8465 -7.3859,0 -4.2677,14.8465 -4.2638,-14.8465 -8.6063,0 8.567,29.8189 8.6063,0 3.6575,-12.7323 3.6574,12.7323 8.6063,0 8.5709,-29.8189 -8.6063,0 -4.2677,14.8465 m -210.098,-24.5551 -8.2756,0 0,8.2717 8.2756,0 0,-8.2717 m 0,9.7087 -8.2756,0 0,29.8189 8.2756,0 0,-29.8189 m -171.508,14.9213 9.2126,14.8976 -9.748,0 -4.3386,-7.0197 -4.3425,7.0197 -9.7441,0 9.2126,-14.8976 -9.2284,-14.9213 9.7441,0 4.3583,7.0472 4.3582,-7.0472 9.7441,0 -9.2283,14.9213 m -277.26,-14.9213 -7.5866,12.2717 0,-21.9803 -8.2756,0 0,39.5276 8.2756,0 0,-12.437 9.3228,12.437 10.3386,0 -11.3819,-15.1811 9.0551,-14.6378 -9.748,0 m -126.098,-9.7087 -8.2795,0 0,8.2717 8.2795,0 0,-8.2717 m 0,40.9803 0,-31.2717 -8.2795,0 0,31.2795 c 0,0.7875 -0.6418,1.4292 -1.4292,1.4292 l -2.3425,0 0,8.2716 2.3425,0 c 5.3662,0 9.7087,-4.3464 9.7087,-9.7086 m 348.524,-16.4055 c 0,-8.6299 -6.9961,-15.626 -15.626,-15.626 -8.6299,0 -15.626,6.996 -15.626,15.626 0,8.6338 6.9961,15.6299 15.626,15.6299 8.6299,0 15.626,-6.9961 15.626,-15.6299 z m -288.228,13.1654 0,1.7874 8.2756,0 0,-29.8189 -8.2756,0 0,17.2717 c 0,2.7834 -2.2559,5.0354 -5.0354,5.0354 -2.7796,0 -5.0355,-2.252 -5.0355,-5.0354 l 0,-17.2717 -8.2756,0 0,17.2717 c 0,5.0078 2.4371,9.5866 6.3071,11.8583 3.8741,2.2716 8.5237,1.8464 12.0394,-1.0985 l 0,0 z m 193.657,-26.2441 0,-11.4961 -8.2795,0 0,39.5276 8.2795,0 0,-1.7874 c 6.2795,4.2716 14.626,3.063 19.5472,-2.8347 4.9252,-5.8976 4.9252,-14.6811 0,-20.5787 -4.9213,-5.8937 -13.2677,-7.1063 -19.5472,-2.8307 l 0,0 z m 271.61,-3.2244 -6.874,0 c -0.1851,-0.02 -0.3662,0.047 -0.4961,0.1811 -0.1299,0.1299 -0.1968,0.311 -0.1771,0.496 l 0,0.7599 0,0 3.7716,0 0,8.2716 -3.7716,0 0,21.5472 -8.2796,0 0,-21.5472 -3.7756,0 0,-8.2716 3.7756,0 c 0,-5.3622 4.3425,-9.7087 9.7047,-9.7087 l 6.1221,0 0,8.2717 0,0 z m 106.752,0.7007 0,8.2441 c -1.9488,0 -3.8189,0.7756 -5.2008,2.1575 -1.3819,1.378 -2.1535,3.252 -2.1535,5.2008 l 0,14.9528 -8.2796,0 0,-29.8189 8.2796,0 0,1.7874 c 2.2008,-1.5 4.7362,-2.3661 7.3543,-2.5236 l 0,-10e-5 z m 48.5236,2.5237 0,-1.7874 -8.2756,0 0,29.8189 8.2756,0 0,-17.2717 c 0,-2.7835 2.252,-5.0394 5.0354,-5.0394 2.7796,0 5.0315,2.2559 5.0315,5.0394 l 0,17.2717 8.2796,0 0,-17.2717 c 0,-2.7835 2.2559,-5.0394 5.0354,-5.0394 2.7795,0 5.0315,2.2559 5.0315,5.0394 l 0,17.2717 8.2756,0 0,-17.2717 c 0,-5.252 -3.0866,-10.0118 -7.8819,-12.1575 -4.7953,-2.1378 -10.3976,-1.2599 -14.3071,2.2401 -4.0591,-4.1811 -10.0984,-4.5315 -14.5,-0.8425 l 0,10e-5 z m 177.079,0 0,-1.7874 8.2795,0 0,29.8189 -8.2795,0 0,-1.7874 c -6.2795,4.2716 -14.626,3.063 -19.5472,-2.8347 -4.9252,-5.8976 -4.9252,-14.6811 0,-20.5787 4.9213,-5.8937 13.2677,-7.1063 19.5472,-2.8307 l 0,0 z m 66.7402,-2.5237 0,8.2441 c -1.9528,0 -3.8268,0.7756 -5.2047,2.1575 -1.3819,1.378 -2.1575,3.252 -2.1575,5.2008 l 0,14.9528 -8.2756,0 0,-29.8189 8.2756,0 0,1.7874 c 2.2008,-1.5 4.7362,-2.3661 7.3622,-2.5236 l 0,-10e-5 z"
+ class="fil8"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#131516"
+ id="path3060"
+ d="m 3258.91,3972.16 c 0,-4.0591 -3.2953,-7.3583 -7.3583,-7.3583 -4.063,0 -7.3543,3.2992 -7.3543,7.3583 0,4.063 3.2913,7.3622 7.3543,7.3622 4.063,0 7.3583,-3.2992 7.3583,-7.3622 z m 958.043,-4.1339 12.1732,0 c -1.3701,-2.0157 -3.6457,-3.2244 -6.0866,-3.2244 -2.437,0 -4.7166,1.2087 -6.0866,3.2244 m -308.846,0 12.1693,0 c -1.3662,-2.0157 -3.6457,-3.2244 -6.0827,-3.2244 -2.437,0 -4.7165,1.2087 -6.0866,3.2244 m -246.161,4.1339 c 0,-4.0591 -3.2953,-7.3583 -7.3583,-7.3583 -4.063,0 -7.3543,3.2992 -7.3543,7.3583 0,4.063 3.2913,7.3622 7.3543,7.3622 4.063,0 7.3583,-3.2992 7.3583,-7.3622 z m 711.949,0 c 0,-4.0591 -3.2953,-7.3583 -7.3583,-7.3583 -4.063,0 -7.3583,3.2992 -7.3583,7.3583 0,4.063 3.2953,7.3622 7.3583,7.3622 4.063,0 7.3583,-3.2992 7.3583,-7.3622 z m -71.5866,0 c 0,-4.0591 -3.2953,-7.3583 -7.3622,-7.3583 -4.0591,0 -7.3543,3.2992 -7.3543,7.3583 0,4.063 3.2952,7.3622 7.3543,7.3622 4.0669,0 7.3622,-3.2992 7.3622,-7.3622 z m -971.327,0.083 c 0,-4.063 -3.2914,-7.3583 -7.3583,-7.3583 -4.059,0 -7.3543,3.2953 -7.3543,7.3583 0,4.063 3.2953,7.3582 7.3543,7.3582 4.0669,0 7.3583,-3.2952 7.3583,-7.3582 z m 58.0866,-4.2166 12.1732,0 c -1.3701,-2.0157 -3.6496,-3.2244 -6.0866,-3.2244 -2.437,0 -4.7166,1.2087 -6.0866,3.2244 m 1617.23,0 12.1732,0 c -1.3741,-2.0157 -3.6496,-3.2244 -6.0906,-3.2244 -2.437,0 -4.7126,1.2087 -6.0827,3.2244 m -114.74,4.1339 c 0,-4.0591 -3.2913,-7.3583 -7.3543,-7.3583 -4.0669,0 -7.3622,3.2992 -7.3622,7.3583 0,4.063 3.2953,7.3622 7.3622,7.3622 4.063,0 7.3543,-3.2992 7.3543,-7.3622 z"
+ class="fil6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#efaf04"
+ id="path3062"
+ d="m 3153.44,3407.72 1958.88,0 0,521.831 -1958.88,0 0,-521.831 0,0 z"
+ class="fil9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:url(#linearGradient4562)"
+ id="path3064"
+ d="m 4692.99,3898.2 0,0 m 414.071,-85.7402 5.2598,0 0,2.9921 -2.2716,0 0,11.9488 -2.9882,0 0,-14.9409 m -14.937,0 8.9646,0 0,2.9922 -8.9646,0 0,-2.9922 m 0,11.9528 8.9646,0 0,2.9882 -8.9646,0 0,-2.9882 m -20.9094,-11.9528 0,0 0,0 0,0 0,0 m 5.9724,2.9922 2.9882,0 0,11.9488 -2.9882,0 0,-11.9488 m 2.9882,-2.9922 2.9882,0 0,2.9922 -2.9882,0 0,-2.9922 m 2.9882,2.9922 2.9882,0 0,11.9488 -2.9882,0 0,-11.9488 m -11.9488,-2.9922 5.9725,0 0,2.9922 -2.9882,0 0,11.9488 -2.9843,0 0,-14.9409 m -5.9764,-2.9882 2.9882,0 0,5.9803 -2.9882,0 0,-5.9803 m 0,8.9645 2.9882,0 0,5.9764 -2.9882,0 0,-5.9764 m -23.8976,-5.9763 2.9882,0 0,5.9763 -2.9882,0 0,-5.9763 m -21.3898,0 2.9882,0 0,2.9921 -2.9882,0 0,-2.9921 m -8.9606,5.9763 2.9843,0 0,5.9764 -2.9843,0 0,-5.9764 m -11.4961,5.9764 11.4961,0 0,2.9882 -11.4961,0 0,-2.9882 m -11.9488,-8.9606 2.9843,0 0,2.9842 -2.9843,0 0,-2.9842 m -2.9921,-8.9646 8.9645,0 0,2.9843 -8.9645,0 0,-2.9843 m 0,17.9252 8.9645,0 0,2.9882 -8.9645,0 0,-2.9882 m -14.9331,-17.9252 5.9724,0 0,2.9843 -5.9724,0 0,-2.9843 m -2.9882,2.9843 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m 8.9606,8.9645 2.9921,0 0,5.9764 -2.9921,0 0,-5.9764 m 80.685,-38.5118 11.9488,0 0,2.9843 -11.9488,0 0,-2.9843 m -2.9882,2.9843 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m 2.9882,2.9882 8.9606,0 0,2.9882 -8.9606,0 0,-2.9882 m 8.9606,2.9882 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m -11.9488,2.9882 11.9488,0 0,2.9881 -11.9488,0 0,-2.9881 m 17.9252,-11.9488 2.9843,0 0,11.9488 -2.9843,0 0,-11.9488 m 2.9843,17.9252 8.9646,0 0,2.9842 -8.9646,0 0,-2.9842 m 14.9409,-5.9764 11.9488,0 0,2.9882 -11.9488,0 0,-2.9882 m 11.9488,-2.9882 2.9842,0 0,2.9882 -2.9842,0 0,-2.9882 m -8.9646,-2.9882 8.9646,0 0,2.9882 -8.9646,0 0,-2.9882 m -2.9842,-2.9882 2.9842,0 0,2.9882 -2.9842,0 0,-2.9882 m 2.9842,-2.9842 11.9488,0 0,2.9842 -11.9488,0 0,-2.9842 m -35.8465,65.0748 11.9488,0 0,2.9881 -11.9488,0 0,-2.9881 m -2.9882,2.9881 2.9882,0 0,2.9843 -2.9882,0 0,-2.9843 m 2.9882,2.9843 8.9607,0 0,2.9921 -8.9607,0 0,-2.9921 m 8.9607,2.9921 2.9881,0 0,2.9882 -2.9881,0 0,-2.9882 m -11.9488,2.9882 11.9488,0 0,2.9843 -11.9488,0 0,-2.9843 m -71.8071,0 11.9528,0 0,2.9843 -11.9528,0 0,-2.9843 m 11.9528,-2.9882 2.9842,0 0,2.9882 -2.9842,0 0,-2.9882 m -8.9646,-2.9921 8.9646,0 0,2.9921 -8.9646,0 0,-2.9921 m -2.9882,-2.9843 2.9882,0 0,2.9843 -2.9882,0 0,-2.9843 m 2.9882,-2.9881 11.9488,0 0,2.9881 -11.9488,0 0,-2.9881 m -89.7913,32.5394 11.9488,0 0,2.9842 -11.9488,0 0,-2.9842 m -2.9882,2.9842 2.9882,0 0,2.9921 -2.9882,0 0,-2.9921 m 2.9882,2.9921 8.9606,0 0,2.9843 -8.9606,0 0,-2.9843 m 8.9606,2.9843 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m -11.9488,2.9882 11.9488,0 0,2.9882 -11.9488,0 0,-2.9882 m -198.457,0 11.9488,0 0,2.9882 -11.9488,0 0,-2.9882 m 11.9488,-2.9882 2.9921,0 0,2.9882 -2.9921,0 0,-2.9882 m -8.9606,-2.9843 8.9606,0 0,2.9843 -8.9606,0 0,-2.9843 m -2.9882,-2.9921 2.9882,0 0,2.9921 -2.9882,0 0,-2.9921 m 2.9882,-2.9842 11.9528,0 0,2.9842 -11.9528,0 0,-2.9842 m 321.22,0 5.9724,0 0,2.9842 -2.9882,0 0,11.9528 -2.9842,0 0,-14.937 m 11.9488,2.9843 2.9842,0 0,11.9528 -2.9842,0 0,-11.9528 m -2.9882,-2.9843 2.9882,0 0,2.9843 -2.9882,0 0,-2.9843 m -2.9882,2.9843 2.9882,0 0,11.9528 -2.9882,0 0,-11.9528 m -5.9724,-2.9843 0,0 0,0 0,0 0,0 m -287.87,0 0,0 0,0 0,0 0,0 m 5.9763,2.9843 2.9882,0 0,11.9528 -2.9882,0 0,-11.9528 m 2.9882,-2.9843 2.9843,0 0,2.9843 -2.9843,0 0,-2.9843 m 2.9843,2.9843 2.9882,0 0,11.9528 -2.9882,0 0,-11.9528 m -11.9488,-2.9843 5.9764,0 0,2.9843 -2.9882,0 0,11.9528 -2.9882,0 0,-14.937 m 353.591,-85.6654 0,-11.9488 2.9882,0 0,17.9252 -2.9882,0 0,-2.9882 -8.9646,0 0,-2.9882 8.9646,0 m -233.701,97.1654 0,-11.9528 2.9882,0 0,17.9252 -2.9882,0 0,-2.9882 -8.9646,0 0,-2.9843 8.9646,0 m -8.9646,5.9725 8.9646,0 0,2.9882 -8.9646,0 0,-2.9882 m -2.9842,-17.9252 2.9842,0 0,11.9528 -2.9842,0 0,-11.9528 m 251.626,-61.6339 2.9842,0 0,2.9842 8.9646,0 0,-2.9842 2.9842,0 0,5.9724 -11.9488,0 0,2.9882 -2.9842,0 0,-8.9606 m -53.7756,32.5354 2.9882,0 0,2.9842 8.9645,0 0,-2.9842 2.9843,0 0,5.9764 -11.9488,0 0,2.9882 -2.9882,0 0,-8.9646 m 2.9882,8.9646 8.9646,0 0,2.9842 -8.9646,0 0,-2.9842 m 0,-11.9528 8.9646,0 0,2.9881 -8.9646,0 0,-2.9881 m -71.8071,0 8.9646,0 0,2.9881 -8.9646,0 0,-2.9881 m 0,11.9528 8.9646,0 0,2.9842 -8.9646,0 0,-2.9842 m -2.9882,-8.9646 2.9882,0 0,2.9842 8.9646,0 0,-2.9842 2.9842,0 0,5.9764 -11.9488,0 0,2.9882 -2.9882,0 0,-8.9646 m 107.657,32.5354 2.9843,0 0,2.9921 8.9645,0 0,-2.9921 2.9882,0 0,5.9764 -11.9528,0 0,2.9882 -2.9842,0 0,-8.9646 m 2.9842,8.9646 8.9646,0 0,2.9881 -8.9646,0 0,-2.9881 m 0,-11.9488 8.9646,0 0,2.9842 -8.9646,0 0,-2.9842 m 35.8504,0 2.2717,0 0,2.9842 -2.2717,0 0,-2.9842 m 0,11.9488 2.2717,0 0,2.9881 -2.2717,0 0,-2.9881 m -2.9881,-8.9646 2.9881,0 0,2.9921 2.2717,0 0,0 0,0 0,2.9843 -2.2717,0 0,2.9882 -2.9881,0 0,-8.9646 m -428.307,-2.9843 8.9606,0 0,2.9843 -8.9606,0 0,-2.9843 m 0,11.9488 8.9606,0 0,2.9882 -8.9606,0 0,-2.9882 m -2.9922,-8.9645 2.9922,0 0,2.9921 8.9606,0 0,-2.9921 2.9842,0 0,5.9763 -11.9449,0 0,2.9882 -2.9921,0 0,-8.9645 m 38.3819,5.9763 5.9764,0 0,5.5237 -5.9764,0 0,-5.5237 m 360.055,-41.5 8.9646,0 0,2.9882 -8.9646,0 0,-2.9882 m -2.9842,2.9882 2.9842,0 0,8.9646 -2.9842,0 0,-8.9646 m 2.9842,8.9646 8.9646,0 0,2.9843 -8.9646,0 0,-2.9843 m 8.9646,-2.9882 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m 8.9606,-8.9646 8.9646,0 0,2.9882 -8.9646,0 0,-2.9882 m -2.9842,8.9646 2.9842,0 0,2.9882 -2.9842,0 0,-2.9882 m -239.933,0 2.9881,0 0,2.9882 -2.9881,0 0,-2.9882 m -8.9607,2.9882 8.9607,0 0,2.9843 -8.9607,0 0,-2.9843 m -2.9882,-8.9646 2.9882,0 0,8.9646 -2.9882,0 0,-8.9646 m 2.9882,-2.9882 8.9607,0 0,2.9882 -8.9607,0 0,-2.9882 m 165.248,-5.9724 2.9882,0 0,2.9843 -2.9882,0 0,-2.9843 m 17.9213,11.9449 2.9882,0 0,2.9921 -2.9882,0 0,-2.9921 m -89.7323,-5.9724 5.9803,0 0,2.9882 -5.9803,0 0,-2.9882 m 5.9803,2.9882 2.9843,0 0,11.9488 -2.9843,0 0,-11.9488 m -81.4961,-2.9882 8.5118,0 0,2.9882 -8.5118,0 0,-2.9882 m -2.9842,2.9882 2.9842,0 0,8.9645 -2.9842,0 0,-8.9645 m 2.9842,8.9645 8.5118,0 0,2.9843 -8.5118,0 0,-2.9843 m 8.5118,-8.9645 2.9882,0 0,8.9645 -2.9882,0 0,-8.9645 m 144.055,32.5354 2.9843,0 0,8.9645 -2.9843,0 0,-8.9645 m -8.5118,8.9645 8.5118,0 0,2.9882 -8.5118,0 0,-2.9882 m -2.9842,-8.9645 2.9842,0 0,8.9645 -2.9842,0 0,-8.9645 m 2.9842,-2.9843 8.5118,0 0,2.9843 -8.5118,0 0,-2.9843 m -74.5157,-32.5394 2.9922,0 0,2.9882 2.9842,0 0,2.9842 -2.9842,0 0,8.9646 -2.9922,0 0,-14.937 m 179.354,0 2.9882,0 0,2.9882 2.2717,0 0,2.9843 -2.2717,0 0,8.9645 -2.9882,0 0,-14.937 m -146.492,14.937 -2.9842,0 0,-2.9842 -2.9882,0 0,-2.9882 2.9882,0 0,-8.9646 2.9842,0 0,14.937 m -11.9449,-2.9842 -2.9921,0 0,-11.9528 2.9921,0 0,11.9528 m 5.9725,2.9842 -5.9725,0 0,-2.9842 5.9725,0 0,2.9842 m -80.6575,-14.937 2.9882,0 0,2.9882 2.9842,0 0,2.9843 -2.9842,0 0,8.9645 -2.9882,0 0,-14.937 m 11.9488,2.9882 2.9842,0 0,11.9488 -2.9842,0 0,-11.9488 m -5.9764,-2.9882 5.9764,0 0,2.9882 -5.9764,0 0,-2.9882 m 89.4528,32.5394 5.9724,0 0,2.9843 -5.9724,0 0,-2.9843 m 5.9724,2.9843 2.9882,0 0,11.9528 -2.9882,0 0,-11.9528 m -11.9488,-2.9843 2.9843,0 0,2.9843 2.9921,0 0,2.9921 -2.9921,0 0,8.9606 -2.9843,0 0,-14.937 m 98.8661,14.937 -5.9764,0 0,-2.9882 5.9764,0 0,2.9882 m -5.9764,-2.9882 -2.9881,0 0,-11.9488 2.9881,0 0,11.9488 m 11.9488,2.9882 -2.9881,0 0,-2.9882 -2.9843,0 0,-2.9881 2.9843,0 0,-8.9607 2.9881,0 0,14.937 m 35.8465,0 -2.9842,0 0,-2.9882 -2.9882,0 0,-2.9882 2.9882,0 0,-8.9606 2.9842,0 0,14.937 m -11.9488,-2.9882 -2.9842,0 0,-11.9488 2.9842,0 0,11.9488 m 5.9764,2.9882 -5.9764,0 0,-2.9882 5.9764,0 0,2.9882 m 2.9882,-44.4882 2.9843,0 0,11.9488 -11.9488,0 0,-2.9842 8.9645,0 0,-2.9882 -8.9645,0 0,-2.9922 8.9645,0 0,-2.9842 m -143.677,32.5354 2.9922,0 0,11.9528 -11.9567,0 0,-2.9882 8.9645,0 0,-2.9882 -8.9645,0 0,-2.9842 8.9645,0 0,-2.9922 m -11.9488,5.9764 2.9843,0 0,2.9882 -2.9843,0 0,-2.9882 m 2.9843,-8.9606 8.9646,0 0,2.9842 -8.9646,0 0,-2.9842 m -125.87,0 8.9606,0 0,2.9842 -8.9606,0 0,-2.9842 m -2.9882,8.9606 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m 11.9488,-5.9764 2.9882,0 0,11.9528 -11.9488,0 0,-2.9882 8.9606,0 0,-2.9881 -8.9606,0 0,-2.9843 8.9606,0 0,-2.9921 m 233.701,-74.0354 -11.9488,0 0,20.9134 11.9488,0 0,-2.9882 -8.9606,0 0,-5.9764 8.9606,0 0,-2.9842 -8.9606,0 0,-5.9804 8.9606,0 0,-2.9842 m -29.874,0 0,20.9134 2.9882,0 0,-14.9409 2.9882,0 0,-2.9882 -2.9882,0 0,-2.9842 -2.9882,0 m 14.937,0 0,20.9134 -2.9842,0 0,-14.9409 -2.9882,0 0,-2.9882 2.9882,0 0,-2.9843 2.9842,0 m -24.374,0 2.9882,0 0,11.9488 2.9843,0 0,2.9882 -2.9843,0 0,5.9764 -2.9882,0 0,-5.9764 -8.9646,0 0,-5.9724 2.9882,0 0,2.9842 5.9764,0 0,-5.9764 -2.9882,0 0,-2.9882 2.9882,0 0,-2.9842 m -26.4331,0 0,2.9842 8.5079,0 0,2.9882 2.9882,0 0,-2.9882 2.9842,0 0,-2.9842 -14.4803,0 m 8.5079,5.9724 -2.9882,0 0,2.9922 -2.9842,0 0,2.9842 8.9606,0 0,-2.9842 -2.9882,0 0,-2.9922 m -26.4331,-2.9882 0,14.9409 2.9842,0 0,-2.9881 2.9922,0 0,-2.9882 -2.9922,0 0,-8.9646 -2.9842,0 m 11.9488,0 0,2.9882 -2.9882,0 0,2.9921 2.9882,0 0,8.9606 2.9882,0 0,-14.9409 -2.9882,0 m -29.874,2.9882 0,11.9528 2.9882,0 0,-5.9763 8.9606,0 0,-2.9843 -8.9606,0 0,-2.9921 -2.9882,0 m 2.9882,11.9528 8.9606,0 0,2.9882 -8.9606,0 0,-2.9882 m -192.248,53.126 -2.9882,0 0,2.9842 -2.9882,0 0,2.9922 8.9646,0 0,-2.9922 -2.9882,0 0,-2.9842 m -8.5118,-5.9764 0,2.9882 8.5118,0 0,2.9882 2.9882,0 0,-2.9882 2.9842,0 0,-2.9882 -14.4843,0 m 0,17.9252 11.5,0 0,2.9882 -11.5,0 0,-2.9882 m 11.5,-5.9724 2.9843,0 0,5.9724 -2.9843,0 0,-5.9724 m 240.071,-38.5157 0,2.9881 8.9607,0 0,2.9843 2.9882,0 0,-2.9843 2.9842,0 0,-2.9881 -14.9331,0 m 2.9843,8.9645 2.9881,0 0,2.9882 8.9607,0 0,2.9843 -14.9331,0 0,-2.9843 2.9842,0 0,-2.9882 m -17.9213,-8.9645 5.9764,0 0,11.9528 2.9843,0 0,2.9842 -8.9607,0 0,-2.9842 2.9882,0 0,-8.9646 -2.9882,0 0,-2.9882 m -89.7323,0 5.9725,0 0,11.9528 2.9921,0 0,2.9842 -8.9646,0 0,-2.9842 2.9882,0 0,-8.9646 -2.9882,0 0,-2.9882 m 2.9882,-5.9724 2.9843,0 0,2.9842 -2.9843,0 0,-2.9842 m -36.0197,32.5354 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m -2.9882,5.9764 5.9764,0 0,11.9488 2.9882,0 0,2.9882 -8.9646,0 0,-2.9882 2.9882,0 0,-8.9646 -2.9882,0 0,-2.9842 m 27.0591,-23.5748 2.9843,0 0,2.9881 -2.9843,0 0,-2.9881 m -2.9882,2.9881 2.9882,0 0,2.9843 -2.9882,0 0,-2.9843 m -2.9882,-17.9252 2.9882,0 0,5.9725 2.9882,0 0,2.9882 -2.9882,0 0,8.9645 -2.9882,0 0,-8.9645 -2.9881,0 0,-2.9882 2.9881,0 0,-5.9725 m 17.7559,32.5354 2.9843,0 0,5.9764 2.9882,0 0,2.9843 -2.9882,0 0,8.9645 -2.9843,0 0,-8.9645 -2.9921,0 0,-2.9843 2.9921,0 0,-5.9764 m 2.9843,17.9252 2.9882,0 0,2.9882 -2.9882,0 0,-2.9882 m 2.9882,-2.9881 2.9882,0 0,2.9881 -2.9882,0 0,-2.9881 m 5.9764,-8.9607 2.9842,0 0,2.9843 2.9882,0 0,2.9921 -2.9882,0 0,8.9606 -2.9842,0 0,-14.937 m 11.9449,2.9843 2.9921,0 0,3.4449 -2.9921,0 0,-3.4449 m -5.9725,-2.9843 5.9725,0 0,2.9843 -5.9725,0 0,-2.9843 m -75.0906,-5.9763 5.5236,0 0,17.9252 2.9882,0 0,2.5354 -8.5118,0 0,-2.5354 2.9882,0 0,-14.937 -2.9882,0 0,-2.9882 m -53.3189,0 5.5236,0 0,17.9252 2.9882,0 0,2.5354 -8.5118,0 0,-2.5354 2.9843,0 0,-14.937 -2.9843,0 0,-2.9882 m 179.193,5.9764 5.9764,0 0,2.9842 -5.9764,0 0,-2.9842 m -2.9842,2.9842 2.9842,0 0,8.9646 -2.9842,0 0,-8.9646 m 8.9606,0 2.9843,0 0,-8.9606 2.9921,0 0,20.4606 -11.9528,0 0,-2.5355 8.9606,0 0,-5.9724 -2.9842,0 0,-2.9921 m 45.0906,0 2.9882,0 0,8.9645 -2.9882,0 0,-8.9645 m 2.9882,-2.9843 5.9763,0 0,2.9843 -5.9763,0 0,-2.9843 m 5.9763,2.9843 2.9882,0 0,-2.9843 2.9843,0 0,20.4606 -2.9843,0 0,-5.9764 -8.9645,0 0,-2.5354 8.9645,0 0,-5.9724 -2.9882,0 0,-2.9922 m -248.638,-2.9842 -5.9724,0 0,2.9842 5.9724,0 0,-2.9842 m -5.9724,2.9842 -2.9882,0 0,-2.9842 -2.9921,0 0,20.4606 2.9921,0 0,-5.9764 8.9606,0 0,-2.5354 -8.9606,0 0,-5.9725 2.9882,0 0,-2.9921 m 8.9606,0 -2.9882,0 0,8.9646 2.9882,0 0,-8.9646 m -36.248,0 -2.9842,0 0,8.9646 2.9842,0 0,-8.9646 m -8.9606,0 -2.9882,0 0,-2.9842 -2.9842,0 0,20.4606 2.9842,0 0,-5.9764 8.9646,0 0,-2.5354 -8.9646,0 0,-5.9725 2.9882,0 0,-2.9921 m 5.9764,-2.9843 -5.9764,0 0,2.9843 5.9764,0 0,-2.9843 m -66.4567,20.6614 0,0 z"
+ class="fil10"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#131516"
+ id="path3066"
+ d="m 3661.04,3557.69 c -26.9764,-117.386 -96.8268,-122.492 -113.248,-122.492 l 0,-6.8622 c 36.4213,0 95.2874,25.9921 116.681,115.201 27.4016,-89.0236 74.2008,-112.917 107.047,-113.37 31.2992,-0.4331 50.6063,6.8661 80.2717,22.3228 l 0,-13.9291 85.6496,0 0,-11.748 6.8622,0 0,11.748 14.5236,0 0,6.8622 -14.5236,0 0,167.843 61.5945,-155.705 59.0157,0 5.1378,-12.1378 -73.5315,0 0,-6.8622 76.4409,0 8.0827,-19.0787 6.3189,2.6811 -6.9488,16.3976 16.2677,0 0,6.8622 -19.1732,0 -48,113.291 63.5709,0 0,84.9094 c 59.4961,-29.2835 130.681,-7.7953 166.559,49.5315 35.5866,-54.8622 105.11,-76.7205 165.685,-52.1024 l -2.4095,-3.8937 102.382,0 20.4528,33.063 19.9764,-32.2953 c 0.2992,-0.4803 0.8189,-0.7677 1.378,-0.7677 l 0,0 c 0.5905,0 1.1299,0.3149 1.4173,0.8307 0.2874,0.5118 0.2716,1.1417 -0.039,1.6417 l -20.8228,33.6772 2.6693,4.315 24.5512,-39.6969 c 0.2913,-0.4803 0.815,-0.7677 1.3779,-0.7677 l 0,0 c 0.5867,0 1.13,0.3149 1.4174,0.8307 0.2834,0.5118 0.2677,1.1417 -0.039,1.6417 l -25.4055,41.0709 2.6732,4.3189 29.6024,-47.8622 102.378,0 -80.7913,130.63 2.6654,4.311 85.2559,-137.835 -106.358,0 c -0.5906,0 -1.1299,-0.3189 -1.4173,-0.8307 -0.2874,-0.5157 -0.2717,-1.1417 0.039,-1.6457 l 0,0 c 0.2914,-0.4724 0.815,-0.7677 1.378,-0.7677 l 112.173,0 -84.5866,136.768 79.1299,127.941 c 0.311,0.4961 0.3228,1.1299 0.035,1.6418 -0.2835,0.5118 -0.8228,0.8307 -1.4134,0.8307 -0.563,0 -1.0827,-0.2874 -1.3779,-0.7678 l -78.2795,-126.567 -2.6693,4.3189 76.0827,123.016 -102.378,0 -19.5591,-31.6181 -19.0827,30.8504 c -0.2914,0.4804 -0.815,0.7678 -1.378,0.7678 l 0,0 c -0.2677,0 -0.5236,-0.063 -0.7598,-0.189 -0.2362,0.126 -0.5,0.189 -0.7638,0.189 -0.5905,0 -1.126,-0.3189 -1.4173,-0.8307 -0.2874,-0.5119 -0.2717,-1.1457 0.035,-1.6418 l 20.6969,-33.4606 -2.6693,-4.3149 -24.4173,39.4803 c -0.2952,0.4803 -0.8149,0.7677 -1.3779,0.7677 -0.5866,0 -1.1299,-0.3189 -1.4173,-0.8307 -0.2874,-0.5118 -0.2717,-1.1457 0.039,-1.6418 l 25.2677,-40.8583 -2.6653,-4.3149 -29.4724,47.6457 -102.382,0 2.996,-4.8465 c -60.626,25.0472 -130.488,3.3622 -166.283,-51.6102 -35.8307,57.4685 -107.106,78.4961 -166.681,49.1732 l 0,7.2835 -86.9921,0 0,-0.6496 -14.3622,0 6.2717,17.7008 -6.4646,2.2953 -7.0827,-19.9961 -27.5787,0 0,-6.8662 25.1457,0 -51.2362,-144.638 -3.0315,7.378 0,144.776 -56.7402,0 0,-440.642 56.7402,0 0,197.547 9.693,-24.4961 0,-185.189 -78.7874,0 0,20.0591 c -34.1772,-22.9843 -57.0787,-28.4488 -87.1339,-28.4488 -23.7953,0 -76.0157,17.3425 -103.618,120.657 l -6.8622,0 -7e-4,3e-4 z m 122.902,349.776 -108.181,0 0,-6.8661 73.878,0 c -56.2992,-24.9961 -80.8307,-115.469 -80.8307,-222.724 0,-126.453 34.0866,-229.587 114.154,-229.587 36.7953,0 57.7008,18.9016 75.6929,36.1299 l 0,11.2362 c 0.01,0.01 0.012,0.02 0.02,0.028 l 0,95.2244 -6.1102,0 c -13.2677,-24.1772 -37.6575,-58.122 -62.8465,-58.122 -41.9764,0 -62.7441,65.0236 -62.2165,145.091 -0.5276,80.0748 20.2402,145.094 62.2165,145.094 25.189,0 49.5787,-33.9488 62.8465,-58.122 l 6.1102,0 0,95.2244 c -0.01,0.012 -0.012,0.016 -0.02,0.032 l 0,11.2323 c -17.8307,17.0748 -38.5276,35.7913 -74.7126,36.126 l -6e-4,-10e-5 z m -236.98,-459.173 c 79.3819,0 113.173,108.268 113.173,229.587 0,121.323 -33.7913,229.591 -113.173,229.591 -79.3819,0 -113.173,-103.134 -113.173,-229.591 0,-126.453 33.7913,-229.587 113.173,-229.587 l 0,0 z m -197.626,9.2677 -103.358,0 0,255.894 c 0.6693,1.7874 1.3307,3.5827 1.9921,5.374 4.6378,-1.2716 9.4528,-1.7874 14.2598,-1.5315 9.3977,0.5079 17.8661,5.8347 22.378,14.0984 4.0827,7.4646 6.0236,15.9134 5.6142,24.4094 -0.1693,3.5473 -1.1063,7.0197 -2.7402,10.1772 -4.0157,7.7559 -10.2126,14.1693 -17.8268,18.4409 2.5788,8.7481 5.0394,17.5236 7.3859,26.3307 4.4921,16.8504 6.6023,34.248 6.2638,51.689 -0.087,4.4961 -1.0591,8.9331 -2.8701,13.0512 -1.8544,4.2205 -5.1024,7.6733 -9.2008,9.7874 -2.9764,1.5315 -6.4449,1.7835 -9.6103,0.7008 -3.1614,-1.0827 -5.748,-3.4094 -7.1614,-6.4449 -1.6417,-3.5315 -2.4488,-7.3937 -2.3464,-11.2874 0.051,-2.1929 1.1102,-4.2401 2.87,-5.5472 2.2166,-1.6535 4.941,-2.4842 7.7008,-2.3543 1.8111,0.091 3.437,1.1496 4.2481,2.7716 0.811,1.626 0.6811,3.5591 -0.3347,5.063 -1.252,1.8504 -3.0905,3.2284 -5.2205,3.9173 l 0.7284,1.5906 c 0.3425,0.8976 1.1063,1.5748 2.0433,1.8071 0.937,0.2323 1.9291,-0.012 2.6535,-0.6457 3.567,-3.0394 5.7874,-7.3622 6.1772,-12.0315 0.5158,-8.0472 0.3465,-16.122 -0.5079,-24.1378 -2.5118,-17.122 -6.2401,-34.0433 -11.1654,-50.6299 -1.2637,0.4016 -2.5472,0.7441 -3.8425,1.0315 -3.7953,0.8465 -7.626,1.5039 -11.4882,1.9685 l 0,107.15 69.1772,0 0,14.3307 6.8622,0 0,-14.3307 14.7362,0 0,-6.8622 -14.7362,0 0,-154.508 6.626,0 60.3661,161.37 66.2992,0 5.9921,15.2913 6.3859,-2.5039 -5.9567,-15.2008 20.685,0 0,-6.8622 -23.374,0 -71.3898,-182.217 c 26.2795,-27.1063 41.3543,-67.9055 41.3543,-119.717 0,-69.4449 -18.7992,-129.433 -79.6693,-129.433 l -1e-4,4e-4 z m -91.0472,320.823 c -3.9409,1.626 -8.0787,2.7126 -12.311,3.2362 l 0,-39.0512 c 4.2598,11.8346 8.3504,23.7323 12.2677,35.685 0.016,0.043 0.032,0.087 0.043,0.13 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 0,0 m -6.4803,-48.9213 c 1.3504,-0.3701 2.7165,-0.6851 4.0905,-0.941 4.3071,-0.8031 8.7638,0.2441 12.2677,2.874 3.193,2.3937 5.4882,5.7914 6.5315,9.6457 2.315,8.5945 1.8111,17.7047 -1.4409,25.9843 -0.6811,1.7441 -1.811,3.2717 -3.2638,4.4409 -1.1141,0.8977 -2.2716,1.7441 -3.4645,2.5355 -4.5788,-14.9528 -9.4843,-29.8031 -14.7205,-44.5394 m -5.8308,52.1575 c -1.0826,0.1299 -2.1692,0.2283 -3.2598,0.2874 -11.8858,0.6456 -22.9409,-6.1024 -27.8031,-16.9685 -8.626,-19.2874 -9.8779,-41.063 -3.5236,-61.2165 2.2362,-7.0709 4.5394,-14.1181 6.9212,-21.1417 0.6536,-1.9449 1.3229,-3.8859 1.9961,-5.8268 6.378,15.1575 12.4764,30.4252 18.2913,45.811 -8.2835,4.4331 -14.9685,11.3583 -19.1142,19.7953 -0.685,1.3898 -0.4173,3.0669 0.6693,4.1772 1.0866,1.1063 2.7559,1.4094 4.1614,0.7559 1.2244,-0.8819 2.3583,-1.878 3.3937,-2.9764 4.1851,-4.6457 9.2047,-8.4764 14.7992,-11.2835 1.1654,3.1732 2.3228,6.3543 3.4685,9.5354 l 0,-29.1142 c -5.5,-14.7283 -11.3307,-29.3268 -17.4882,-43.7953 -1.0197,-2.3976 -2.059,-4.7834 -3.122,-7.1614 1.2795,-3.5157 2.5826,-7.0275 3.9055,-10.5276 1.8858,-4.996 3.3307,-10.1496 4.3071,-15.3976 1.1063,-5.9409 0.6102,-12.0669 -1.4331,-17.752 -4.6654,-12.9528 -13.6535,-23.9016 -25.4528,-31 -5.189,-3.122 -11.1772,-4.6653 -17.2283,-4.4409 -5.0709,0.1929 -9.1693,4.2008 -9.4606,9.2716 -0.2717,4.5945 0.7992,9.1733 3.0669,13.1811 2.1024,3.7087 4.3661,7.3229 6.7835,10.8346 7.4685,10.8228 13.9252,22.315 19.2835,34.3268 1.0551,2.3622 2.1023,4.7284 3.1417,7.0945 -1.6378,4.5 -3.2362,9.0079 -4.8032,13.5276 -7.2716,20.9764 -11.9606,42.7598 -13.9685,64.8701 -0.9448,10.437 -0.016,20.9567 2.7441,31.063 3.7835,13.8701 16.1142,23.689 30.4764,24.2795 6.4252,0.2638 12.8661,0 19.248,-0.7756 l 0,-9.433 m 93.9921,-342.409 -106.854,0 0,-16.6496 -6.8622,0 0,16.6496 -15.9843,0 0,6.8622 15.9843,0 0,76.4528 6.8622,0 0,-76.4528 106.854,0 0,-6.8622 z"
+ class="fil6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#a9becd"
+ id="path3068"
+ d="m 4668.85,3647.2 -78.748,0 -35.2008,56.9173 -35.2047,-56.9173 -78.748,0 14.7677,23.874 c -30.0551,-25.5157 -70.3071,-35.5276 -108.815,-27.0669 -38.5039,8.4567 -70.8504,34.4213 -87.4449,70.185 -14.8701,-33.2717 -42.8622,-58.1772 -76.7087,-68.2559 -33.8543,-10.0827 -70.2362,-4.3504 -99.7244,15.7126 l 0,-94.4646 -66.8819,0 0,319.39 66.8819,0 0,-12.8819 c 29.5394,20.0984 65.9921,25.815 99.8898,15.6614 33.8976,-10.1496 61.8898,-35.1654 76.6929,-68.5394 16.7795,35.9016 49.4409,61.8465 88.2087,70.0669 38.7677,8.2165 79.1457,-2.248 109.047,-28.2559 l -15.7795,25.5157 78.748,0 35.0709,-56.7047 35.0669,56.7047 78.748,0 -74.4449,-120.362 74.5787,-120.579 3e-4,0 z"
+ class="fil11"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#131516"
+ id="path3070"
+ d="m 4201.93,3767.35 c 0,-32.8386 -26.622,-59.4567 -59.4528,-59.4567 -32.8307,0 -59.4488,26.6181 -59.4488,59.4567 0,32.8346 26.6181,59.4528 59.4488,59.4528 32.8307,0 59.4528,-26.6181 59.4528,-59.4528 z m 294.693,-30.1339 c 4.9843,20.2913 4.8583,41.5 -0.3701,61.7283 l 19.2756,-31.1614 -18.9055,-30.5669 m -63.1772,30.1339 c 0,-32.8386 -26.6142,-59.4567 -59.4449,-59.4567 -32.8346,0 -59.4528,26.6181 -59.4528,59.4567 0,32.8346 26.6181,59.4528 59.4528,59.4528 32.8307,0 59.4449,-26.6181 59.4449,-59.4528 z"
+ class="fil6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#efaf04"
+ id="path3072"
+ d="m 3302.71,3891.33 12.437,0 0,-154.508 -12.437,0 0,154.508 m 25.6732,-251.902 c 20.9685,0 24.252,-26.5827 24.2323,-44.8268 -0.024,-18.2441 -2.6732,-38.0433 -20.9685,-38.0433 l -28.937,0 0,100.823 12.437,0 0,-17.9528 13.2362,0 0,-1e-4 z m 0,6.8661 -6.374,0 0,11.0866 0.437,0 c 46.7283,0 46.7283,-41.8465 46.7283,-56.3858 l 0,-9.3858 c 0,-14.0945 -0.095,-52.9961 -39.4409,-52.9961 l -27.0236,0 0,11.0827 25.6732,0 c 13.3543,0 31.2638,1.8977 31.2638,46.6811 0,44.7756 -18,49.5433 -31.2638,49.9173 l 0,0 z m -111.276,-1.2244 c -5.3779,-10.7362 -11.1929,-21.2441 -17.4409,-31.5 -1.9882,-3.2598 -3.7835,-6.6299 -5.3779,-10.0984 -1.0434,-2.2598 -1.6615,-4.6929 -1.8308,-7.1771 -0.032,-0.5355 0.1615,-1.063 0.5315,-1.4489 0.3741,-0.3858 0.8937,-0.5905 1.4292,-0.5748 2.5787,0.087 5.0945,0.8307 7.3071,2.1536 9.5236,5.6968 16.3071,15.0315 18.7953,25.8425 0.7244,3.1535 0.748,6.433 0.067,9.5945 -0.9606,4.4527 -2.1221,8.8582 -3.4803,13.2087 l 0,0 m 1155.26,171.65 3.2401,0 c 26.9528,-0.8898 48.2165,-23.2244 47.7717,-50.189 -0.4409,-26.9606 -22.4252,-48.5866 -49.3898,-48.5866 -26.9685,0 -48.9488,21.626 -49.3937,48.5866 -0.4409,26.9646 20.8189,49.2992 47.7717,50.189 l 0,0 z m -231.52,0 3.2401,0 c 26.9528,-0.8898 48.2126,-23.2244 47.7717,-50.189 -0.4409,-26.9606 -22.4291,-48.5866 -49.3937,-48.5866 -26.9646,0 -48.9488,21.626 -49.3898,48.5866 -0.4409,26.9646 20.8189,49.2992 47.7717,50.189 l 0,0 z m -154.866,-155.323 20.0945,51.9843 0,-99.4134 -20.0945,47.4291 m 3.3031,229.28 -54.6102,-154.161 6.4055,-15.5945 63.1024,169.756 -14.8976,0 m -442.339,-359.386 c 38.2244,0 54.4882,69.1181 54.4882,146.579 0,77.4646 -16.2638,146.583 -54.4882,146.583 -38.2205,0 -54.4843,-65.8504 -54.4843,-146.583 0,-80.7283 16.2638,-146.579 54.4843,-146.579 z"
+ class="fil9"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#131516"
+ id="path3074"
+ d="m 4372.37,3816.72 c 1.0787,0.079 2.1575,0.071 3.2402,0 l 0,-4.5433 c 24.4488,-0.8819 43.6811,-21.1969 43.2323,-45.6575 -0.4489,-24.4646 -20.4173,-44.0551 -44.8858,-44.0394 -0.5867,-0.01 -1.0709,0.2992 -1.3622,0.8031 -0.2993,0.5079 -0.2993,1.1339 0,1.6418 0.2953,0.5039 0.7835,0.8071 1.3701,0.8031 15.063,-0.016 28.9606,8.1181 36.3307,21.2598 7.3661,13.1378 7.0591,29.2402 -0.8071,42.0866 -7.8622,12.8465 -22.0591,20.4449 -37.1142,19.8583 l 0,7.7874 0,10e-5 z m -229.902,-12.2953 c -0.8937,0 -1.6181,-0.7283 -1.6181,-1.6221 0,-0.8976 0.7244,-1.622 1.6181,-1.622 18.689,0 33.8346,-15.1496 33.8346,-33.8346 0,-18.6929 -15.1457,-33.8386 -33.8346,-33.8386 -0.8937,0 -1.6181,-0.7283 -1.6181,-1.6221 0,-0.8976 0.7244,-1.6181 1.6181,-1.6181 20.4803,0 37.0748,16.5945 37.0748,37.0787 0,20.4764 -16.5945,37.0787 -37.0748,37.0787 l 0,1e-4 z m 231.524,0 c -0.8976,0 -1.622,-0.7283 -1.622,-1.6221 0,-0.8976 0.7244,-1.622 1.622,-1.622 18.685,0 33.8346,-15.1496 33.8346,-33.8346 0,-18.6929 -15.1496,-33.8386 -33.8346,-33.8386 -0.8976,0 -1.622,-0.7283 -1.622,-1.6221 0,-0.8976 0.7244,-1.6181 1.622,-1.6181 20.4764,0 37.0748,16.5945 37.0748,37.0787 0,20.4764 -16.5984,37.0787 -37.0748,37.0787 l 0,1e-4 z M 4140.85,3816.72 c 1.0787,0.051 2.1575,0.035 3.2402,0 l 0,-4.5433 c 24.4488,-0.8819 43.6772,-21.1969 43.2323,-45.6575 -0.4528,-24.4646 -20.4213,-44.0551 -44.8858,-44.0394 -0.5827,-0.01 -1.067,0.2992 -1.3662,0.8031 -0.2953,0.5079 -0.2953,1.1339 0,1.6418 0.2953,0.5039 0.7835,0.8071 1.3701,0.8031 15.063,-0.016 28.9606,8.1181 36.3268,21.2598 7.3701,13.1378 7.0591,29.2402 -0.8071,42.0866 -7.8622,12.8465 -22.0591,20.4449 -37.1102,19.8583 l 0,7.7874 -10e-5,10e-5 z m -593.898,-12.8976 0,-16.9528 -6.8661,0 0,18.0551 0,6.8622 c 37.1024,0 47.9921,-63.0039 48.248,-130.484 l 156.142,0 c 0.37,47.5039 10.7874,120.209 41.7992,125.224 l 0,17.9252 6.8622,0 0,-143.15 27.3228,0 0,-6.8661 -27.3228,0 0,-24.7598 -6.8622,0 0,24.7598 -34.9094,0 c 0.7401,-47.0787 13.8937,-115.913 38.3386,-117.031 l 0,-6.8662 c -32.0669,1.2441 -44.5276,74.7126 -45.2087,123.898 l -156.173,0 c -0.4449,-67.1575 -11.2874,-129.65 -48.2362,-129.65 l 0,6.5866 0,123.063 -20.9724,0 0,6.8662 20.9724,0 0,23.9685 6.8661,0 0,-23.9685 34.5079,0 c -0.3425,43.1929 -5.7874,112.988 -34.5079,122.52 l -5e-4,-2e-4 z"
+ class="fil6"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#efaf04"
+ id="path3076"
+ d="m 3751.34,3681.31 c 0.4449,44.9685 11.8307,112.11 34.937,118.209 l 0,-118.209 -34.937,0 z m -169.866,-6.8661 -34.5197,0 0,-121.953 c 28.5748,9.496 34.315,78.689 34.5197,121.953 z"
+ class="fil9"
+ inkscape:connector-curvature="0" />
+ </g>
+ <g
+ id="g6938-8"
+ style="display:inline"
+ transform="translate(54.936222,-93.2058)">
+ <rect
+ style="fill:url(#linearGradient4564);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4566);stroke-width:0.99212599;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="rect4922-1-1-7-5"
+ width="56.692913"
+ height="56.692913"
+ x="171.15355"
+ y="294.72559"
+ ry="13.143503"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;display:inline;filter:url(#filter5226-7)"
+ d="m 186.09375,300.59375 c -5.02091,0 -9.09375,4.03754 -9.09375,9.0625 l 0,26.8125 c 0,5.02496 4.06879,9.09375 9.09375,9.09375 l 26.8125,0 c 5.02496,0 9.09375,-4.06879 9.09375,-9.09375 l 0,-26.8125 c 0,-5.02496 -4.07284,-9.0625 -9.09375,-9.0625 l -26.8125,0 z"
+ id="path4397-6" />
+ <rect
+ style="fill:url(#linearGradient4568);fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient4570);stroke-width:0.99921262;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="rect4922-5-6-6-7-6"
+ width="40.202908"
+ height="40.202908"
+ x="179.39854"
+ y="302.97058"
+ ry="6.6378174"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ inkscape:export-xdpi="96"
+ inkscape:export-ydpi="96" />
+ </g>
+ <g
+ transform="translate(-204.10139,-35.936746)"
+ id="g8585">
+ <path
+ style="fill:#323232;fill-opacity:1;stroke:none"
+ d="m 399.7843,265.81185 c -2.28956,-1.32188 -4.57912,-2.64375 -6.86868,-3.96563 0,2.63785 0,5.27569 0,7.91354 2.28956,-1.31597 4.57912,-2.63194 6.86868,-3.94791 z"
+ id="path8455"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#282828;fill-opacity:1;stroke:none"
+ d="m 392.94938,261.88269 c 0.32292,0.69792 0.64583,1.39583 0.96875,2.09375 1.01042,0.67708 2.02083,1.35417 3.03125,2.03125 0.92708,-0.0521 1.85417,-0.10417 2.78125,-0.15625 0.14211,-0.0564 -0.15675,-0.12586 -0.21013,-0.18806 -2.19036,-1.26024 -4.38083,-2.52041 -6.57112,-3.78069 z"
+ id="path6411"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#595959;fill-opacity:1;stroke:none"
+ d="m 392.91813,261.85144 c 0,2.63542 0,5.27083 0,7.90625 0.3125,-0.65625 0.625,-1.3125 0.9375,-1.96875 0.0224,-1.21914 0.0159,-2.44053 0.10149,-3.6573 0.0533,-0.15391 -0.0896,-0.29031 -0.13306,-0.43614 -0.27072,-0.59385 -0.54145,-1.18771 -0.81218,-1.78156 -0.0312,-0.0208 -0.0625,-0.0417 -0.0937,-0.0625 z"
+ id="path6413"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#1a1a1a;stroke:none"
+ d="m 399.73063,265.85144 c -0.92708,0.0521 -1.85417,0.10417 -2.78125,0.15625 -1.01042,0.5625 -2.02083,1.125 -3.03125,1.6875 -0.33333,0.67708 -0.66667,1.35417 -1,2.03125 0.0492,0.0442 0.21494,-0.11256 0.30924,-0.14612 2.16774,-1.24293 4.33559,-2.48607 6.50326,-3.72888 z"
+ id="path6415"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#2b2b2b;fill-opacity:1;stroke:none;display:inline"
+ d="m 398.30055,265.87526 c -1.60242,-0.92516 -3.20484,-1.85031 -4.80726,-2.77547 0,1.84618 0,3.69236 0,5.53854 1.60242,-0.92102 3.20484,-1.84205 4.80726,-2.76307 z"
+ id="path8455-6"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ sodipodi:nodetypes="ccccc"
+ id="path6390-4"
+ d="m 77.509982,43.29852 c 0,0 -2.22674,-0.59595 -2.08757,-1.27702 l 0,-9.80756 c 0.0696,-0.95352 2.08758,-1.60055 2.08758,-1.60055 l -1e-5,12.68513 z"
+ style="fill:url(#linearGradient4572);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ sodipodi:nodetypes="ccccc"
+ id="path6390-4-7"
+ d="m 77.474772,99.472927 c 0,0 -3.10604,0.0286 -3.05693,-0.56816 l -0.0625,-10.636893 c 0.0129,-0.8278 3.11945,-0.74597 3.11945,-0.74597 z"
+ style="fill:url(#linearGradient4574);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ inkscape:export-ydpi="96"
+ inkscape:export-xdpi="96"
+ inkscape:export-filename="/home/simon/Desktop/DX50.png"
+ sodipodi:nodetypes="ccccc"
+ id="path6390-4-2-1"
+ d="m 304.22694,96.830807 c 0,0 2.22674,-0.924813 2.08757,-1.981713 l 0,-15.21964 c -0.0696,-1.4797 -2.08758,-2.48378 -2.08758,-2.48378 l 1e-5,19.685133 z"
+ style="fill:url(#linearGradient4576);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" />
+ <path
+ transform="translate(-8.4564067,-93.209401)"
+ d="m 197.125,318.09375 a 1.0346626,1.0346626 0 0 0 -0.90625,1.03125 l 0,7.875 0,0.0312 a 1.0346626,1.0346626 0 0 0 1.53125,0.90625 l 6.78125,-3.875 0.0312,-0.0312 0.0312,0 a 1.0346626,1.0346626 0 0 0 0.0625,-1.84375 l -6.75,-3.875 a 1.0346626,1.0346626 0 0 0 -0.0312,-0.0312 1.0346626,1.0346626 0 0 0 -0.0625,-0.0312 1.0346626,1.0346626 0 0 0 -0.0625,-0.0312 1.0346626,1.0346626 0 0 0 -0.625,-0.125 z"
+ id="path6837"
+ style="opacity:0.19620254;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter6851)"
+ inkscape:original="M 197.25 319.125 L 197.25 327 L 197.25 327.03125 L 204.0625 323.125 L 204.125 323.09375 L 197.34375 319.1875 L 197.28125 319.15625 L 197.25 319.125 z "
+ inkscape:radius="1.0345591"
+ sodipodi:type="inkscape:offset" />
+ <g
+ transform="translate(-204.10139,-35.936746)"
+ id="g8542">
+ <path
+ style="fill:#232323;fill-opacity:1;stroke:none;display:inline"
+ d="m 327.00633,269.44125 c 0,-1.11084 0,-2.22167 0,-3.33251 1.72734,1.10675 3.45467,2.21349 5.18201,3.32024 0,-1.11356 0,-2.22712 0,-3.34068 1.73872,1.11356 3.47743,2.22712 5.21615,3.34068 0,-2.40022 0,-4.80044 0,-7.20066 -1.73872,1.05359 -3.47743,2.10718 -5.21615,3.16077 0,-1.05359 0,-2.10718 0,-3.16077 -1.72734,1.04677 -3.45467,2.09354 -5.18201,3.14031 0,-1.05086 0,-2.10173 0,-3.15259 -0.45237,0 -0.90474,0 -1.35711,0 0,2.4084 0,4.81681 0,7.22521 0.45237,0 0.90474,0 1.35711,0 z"
+ id="path7889-0-2-1-4"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#1f1f1f;fill-opacity:1;stroke:none;display:inline"
+ d="m 332.24812,262.10464 c -0.10841,0.14556 -0.21682,0.29111 -0.32523,0.43667 0.23534,0.0406 0.16,0.26734 0.16948,0.44327 10e-4,0.8304 0.002,1.66079 0.003,2.49119 0.17839,-0.17839 0.35677,-0.35678 0.53516,-0.53517 -0.0797,-0.6842 -0.0168,-1.37586 -0.0326,-2.06341 0.008,-0.29242 0.0376,-0.63321 -0.24068,-0.82327 -0.0365,0.0169 -0.0731,0.0338 -0.10962,0.0507 z m -4.82032,0.14453 c -0.16141,0.10162 -0.32282,0.20325 -0.48423,0.30487 -1e-5,0.97356 -1e-5,1.94712 -2e-5,2.92068 0.26207,-0.14668 0.37661,-0.43001 0.54362,-0.66474 -0.0308,-0.85054 -0.004,-1.7031 -0.0398,-2.5529 l -0.0196,-0.008 z m 4.60614,3.74231 c 0.20835,0.33784 0.19209,0.84621 0.629,0.99034 1.46558,0.86307 2.91963,1.7481 4.39244,2.59739 0.44409,0.21608 0.66901,-0.45455 0.14477,-0.50907 -0.30256,-0.21825 -0.69163,-0.41829 -1.02983,-0.62826 -1.37879,-0.8168 -2.75759,-1.6336 -4.13638,-2.4504 z m -5.10031,0.0153 c 0.097,0.26439 0.19403,0.52879 0.29105,0.79318 1.54358,0.91636 3.09222,1.82783 4.63794,2.74209 0.66335,0.22026 0.2732,-0.59301 -0.11379,-0.65415 -1.60507,-0.96037 -3.21013,-1.92075 -4.8152,-2.88112 z"
+ id="path6567-3"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#595959;fill-opacity:1;stroke:none;display:inline"
+ d="m 337.53829,262.07146 c -0.10787,0.15263 -0.31294,0.26738 -0.35547,0.44548 0,2.17833 0,4.35666 0,6.53499 0.0729,0.16667 0.14583,0.33333 0.21875,0.5 0.42015,-0.19158 0.29245,-0.69003 0.3125,-1.05824 -0.002,-2.05345 0.003,-4.10716 -0.002,-6.16046 -0.004,-0.11255 -0.0791,-0.2083 -0.17347,-0.26177 z m -10.63672,3.91797 c 0,1.02083 0,2.04167 0,3.0625 -0.40625,0 -0.8125,0 -1.21875,0 -0.11458,0.15625 -0.22917,0.3125 -0.34375,0.46875 0.36996,0.12045 0.77333,0.0385 1.15894,0.0625 0.3255,0.006 0.74566,0.0428 0.89187,-0.33037 0.0869,-0.41956 0.0197,-0.85938 0.0371,-1.28796 -0.0114,-0.37548 0.0147,-0.76063 -0.0199,-1.13014 -0.16072,-0.27127 -0.28808,-0.5771 -0.46928,-0.82715 l -0.0263,-0.0131 -0.01,-0.005 -2e-5,-5e-5 z m 5.14844,0.0156 c -0.008,1.01562 -0.0156,2.03125 -0.0234,3.04687 0.025,0.14812 0.14073,0.33271 0.20046,0.49479 0.43549,-0.15196 0.31286,-0.66549 0.3308,-1.02333 0,-0.53205 0,-1.0641 0,-1.59615 0.12647,0.0484 -0.14412,-0.2712 -0.17884,-0.37221 -0.10967,-0.18333 -0.21935,-0.36665 -0.32902,-0.54997 z"
+ id="path6567-4-7"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#141414;fill-opacity:1;stroke:none;display:inline"
+ d="m 325.59064,262.0246 c -0.41417,0.0673 -0.46651,0.51397 -0.4375,0.85444 0,2.09019 0,4.18037 0,6.27056 0.0227,0.43912 0.27928,0.37645 0.42348,0.0747 0.19113,-0.16833 0.0772,-0.44216 0.10777,-0.66602 0,-2.0008 0,-4.0016 0,-6.0024 0.4553,-0.009 0.92023,0.0189 1.36954,-0.0141 0.16509,-0.11541 0.59641,-0.20156 0.29562,-0.44703 -0.34143,-0.12983 -0.72414,-0.0462 -1.08537,-0.0701 -0.2245,-3e-5 -0.44917,8e-5 -0.67354,-7e-5 z m 6.40625,0 c -1.47016,0.848 -2.95976,1.66428 -4.43745,2.5 -0.2047,0.32234 -0.40941,0.64468 -0.61411,0.96702 1.69429,-0.95776 3.38857,-1.91551 5.08286,-2.87327 0.11458,-0.1875 0.22917,-0.375 0.34375,-0.5625 -0.11568,-0.0556 -0.25182,-0.0668 -0.37505,-0.0312 z m 5.125,0 c -1.54469,0.91549 -3.10534,1.80536 -4.6562,2.71094 -0.1224,0.25 -0.24479,0.5 -0.36719,0.75 1.73698,-0.97656 3.47396,-1.95313 5.21094,-2.92969 0.0757,-0.14715 0.38209,-0.30796 0.28793,-0.44505 -0.13014,-0.10717 -0.31597,-0.1492 -0.47548,-0.0862 z"
+ id="path6567-4-3-5"
+ inkscape:connector-curvature="0" />
+ </g>
+ <path
+ inkscape:connector-curvature="0"
+ id="path7889-0-2-1-4-4"
+ d="m 258.99449,226.22799 c 0,1.11084 0,2.22167 0,3.33251 -1.72734,-1.10675 -3.45467,-2.21349 -5.18201,-3.32024 0,1.11356 0,2.22712 0,3.34068 -1.73872,-1.11356 -3.47743,-2.22712 -5.21615,-3.34068 0,2.40022 0,4.80044 0,7.20066 1.73872,-1.05359 3.47743,-2.10718 5.21615,-3.16077 0,1.05359 0,2.10718 0,3.16077 1.72734,-1.04677 3.45467,-2.09354 5.18201,-3.14031 0,1.05086 0,2.10173 0,3.15259 0.45237,0 0.90474,0 1.35711,0 0,-2.4084 0,-4.81681 0,-7.22521 -0.45237,0 -0.90474,0 -1.35711,0 z"
+ style="fill:#232323;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path6567-3-4"
+ d="m 253.7527,233.5646 c 0.10841,-0.14555 0.21682,-0.29111 0.32523,-0.43666 -0.23534,-0.0406 -0.16,-0.26734 -0.16948,-0.44327 -10e-4,-0.8304 -0.002,-1.66079 -0.003,-2.49119 -0.17839,0.17839 -0.35677,0.35678 -0.53516,0.53517 0.0797,0.68419 0.0168,1.37585 0.0326,2.0634 -0.008,0.29242 -0.0376,0.63321 0.24068,0.82327 0.0365,-0.0169 0.0731,-0.0338 0.10962,-0.0507 z m 4.82032,-0.14453 c 0.16141,-0.10162 0.32282,-0.20325 0.48423,-0.30487 10e-6,-0.97356 10e-6,-1.94712 2e-5,-2.92068 -0.26207,0.14668 -0.37661,0.43001 -0.54362,0.66474 0.0308,0.85054 0.004,1.7031 0.0398,2.5529 l 0.0196,0.008 z m -4.60614,-3.74231 c -0.20835,-0.33784 -0.19209,-0.84621 -0.629,-0.99034 -1.46558,-0.86307 -2.91963,-1.7481 -4.39244,-2.59739 -0.44409,-0.21608 -0.66901,0.45455 -0.14477,0.50907 0.30256,0.21825 0.69163,0.41829 1.02983,0.62826 1.37879,0.8168 2.75759,1.6336 4.13638,2.4504 z m 5.10031,-0.0153 c -0.097,-0.26439 -0.19403,-0.52879 -0.29105,-0.79318 -1.54358,-0.91636 -3.09222,-1.82783 -4.63794,-2.74209 -0.66335,-0.22026 -0.2732,0.59301 0.11379,0.65415 1.60507,0.96037 3.21013,1.92075 4.8152,2.88112 z"
+ style="fill:#1c1c1c;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path6567-4-7-4"
+ d="m 248.46253,233.59778 c 0.10787,-0.15263 0.31294,-0.26738 0.35547,-0.44548 0,-2.17833 0,-4.35666 0,-6.53499 -0.0729,-0.16667 -0.14583,-0.33333 -0.21875,-0.5 -0.42015,0.19158 -0.29245,0.69003 -0.3125,1.05824 0.002,2.05345 -0.003,4.10717 0.002,6.16046 0.004,0.11255 0.0791,0.2083 0.17347,0.26177 z m 10.63672,-3.91797 c 0,-1.02083 0,-2.04167 0,-3.0625 0.40625,0 0.8125,0 1.21875,0 0.11458,-0.15625 0.22917,-0.3125 0.34375,-0.46875 -0.36996,-0.12045 -0.77333,-0.0385 -1.15894,-0.0625 -0.3255,-0.006 -0.74566,-0.0428 -0.89187,0.33038 -0.0869,0.41955 -0.0197,0.85937 -0.0371,1.28795 0.0114,0.37548 -0.0147,0.76063 0.0199,1.13014 0.16072,0.27127 0.28808,0.5771 0.46928,0.82715 l 0.0263,0.0131 0.01,0.005 2e-5,5e-5 z m -5.14844,-0.0156 c 0.008,-1.01563 0.0156,-2.03125 0.0234,-3.04688 -0.025,-0.14812 -0.14073,-0.33271 -0.20046,-0.49479 -0.43549,0.15196 -0.31288,0.66549 -0.33081,1.02334 0,0.53204 0,1.06409 0,1.59614 -0.12647,-0.0484 0.14412,0.2712 0.17884,0.37221 0.10968,0.18333 0.21935,0.36665 0.32903,0.54998 z"
+ style="fill:#141414;fill-opacity:1;stroke:none;display:inline" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path6567-4-3-5-7"
+ d="m 260.41018,233.64464 c 0.41418,-0.0673 0.46651,-0.51397 0.4375,-0.85444 0,-2.09019 0,-4.18037 0,-6.27056 -0.0227,-0.43912 -0.27928,-0.37645 -0.42348,-0.0747 -0.19113,0.16833 -0.0772,0.44216 -0.10777,0.66603 0,2.00079 0,4.00159 0,6.00239 -0.4553,0.009 -0.92023,-0.0189 -1.36954,0.0141 -0.16508,0.11541 -0.59641,0.20156 -0.29562,0.44703 0.34143,0.12985 0.72414,0.0462 1.08537,0.0701 0.2245,3e-5 0.44915,-7e-5 0.67354,6e-5 z m -6.40625,0 c 1.47016,-0.848 2.95976,-1.66428 4.43745,-2.5 0.2047,-0.32234 0.40941,-0.64468 0.61411,-0.96702 -1.69429,0.95776 -3.38857,1.91551 -5.08286,2.87327 -0.11458,0.1875 -0.22917,0.375 -0.34375,0.5625 0.11568,0.0555 0.25182,0.0668 0.37505,0.0312 z m -5.125,0 c 1.54469,-0.91549 3.10534,-1.80536 4.6562,-2.71094 0.1224,-0.25 0.24479,-0.5 0.36719,-0.75 -1.73698,0.97656 -3.47396,1.95313 -5.21094,2.92969 -0.0757,0.14715 -0.38209,0.30797 -0.28793,0.44506 0.13014,0.10717 0.31597,0.1492 0.47548,0.0862 z"
+ style="fill:#595959;fill-opacity:1;stroke:none;display:inline" />
+ </g>
+ <path
+ style="fill:#4d4d4d;stroke:#4d4d4d;stroke-width:1.23570383;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path3725-79"
+ d="m 189.38243,239.75116 124.33073,69.71405"
+ inkscape:export-filename="/home/marko/Dropbox/Public/clipplus.png"
+ inkscape:export-xdpi="96.824623"
+ inkscape:export-ydpi="96.824623"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:#4d4d4d;stroke:#4d4d4d;stroke-width:1.23570383;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path3725-0"
+ d="m 259.7611,236.54405 54.45205,-1.57884"
+ inkscape:export-filename="/home/marko/Dropbox/Public/clipplus.png"
+ inkscape:export-xdpi="96.824623"
+ inkscape:export-ydpi="96.824623"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:#4d4d4d;stroke:#4d4d4d;stroke-width:1.23570383;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline"
+ id="path3725-79-2"
+ d="m 45.792482,222.25228 69.883508,6.42799"
+ inkscape:export-filename="/home/marko/Dropbox/Public/clipplus.png"
+ inkscape:export-xdpi="96.824623"
+ inkscape:export-ydpi="96.824623"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+</svg>
diff --git a/rbutil/ibassoboot/jni/Android.mk b/rbutil/ibassoboot/jni/Android.mk
new file mode 100644
index 0000000000..1d1566d8c0
--- /dev/null
+++ b/rbutil/ibassoboot/jni/Android.mk
@@ -0,0 +1,6 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := MangoPlayer
+LOCAL_SRC_FILES := ibassodualboot.c qdbmp.c
+include $(BUILD_EXECUTABLE)
diff --git a/rbutil/ibassoboot/jni/chooser.bmp b/rbutil/ibassoboot/jni/chooser.bmp
new file mode 100644
index 0000000000..3e6742d600
--- /dev/null
+++ b/rbutil/ibassoboot/jni/chooser.bmp
Binary files differ
diff --git a/rbutil/ibassoboot/jni/ibassodualboot.c b/rbutil/ibassoboot/jni/ibassodualboot.c
new file mode 100644
index 0000000000..3f20bbeecf
--- /dev/null
+++ b/rbutil/ibassoboot/jni/ibassodualboot.c
@@ -0,0 +1,439 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2014 by Ilia Sergachev
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <linux/fb.h>
+#include <linux/input.h>
+#include <linux/reboot.h>
+
+#include <stdbool.h>
+#include <string.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <time.h>
+
+#include <sys/limits.h>
+#include <sys/mman.h>
+#include <sys/inotify.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include <unistd.h>
+
+#include "qdbmp.h"
+
+
+#define MIN_TIME 1395606821
+#define TIME_FILE "/data/time_store"
+#define TIME_CHECK_PERIOD 60 /* seconds */
+#define VOLD_LINK "/data/vold"
+#define PLAYER_FILE "/data/chosen_player"
+#define NOASK_FLAG "/data/no_ask_once"
+#define POLL_MS 10
+
+
+#define KEYCODE_HEADPHONES 114
+#define KEYCODE_HOLD 115
+#define KEYCODE_PWR 116
+#define KEYCODE_PWR_LONG 117
+#define KEYCODE_SD 143
+#define KEYCODE_VOLPLUS 158
+#define KEYCODE_VOLMINUS 159
+#define KEYCODE_PREV 160
+#define KEYCODE_NEXT 162
+#define KEYCODE_PLAY 161
+
+#define KEY_HOLD_OFF 16
+
+void checktime()
+{
+ time_t t_stored=0, t_current=time(NULL);
+
+ FILE *f = fopen(TIME_FILE, "r");
+ if(f!=NULL)
+ {
+ fscanf(f, "%ld", &t_stored);
+ fclose(f);
+ }
+
+ printf("stored time: %ld, current time: %ld\n", t_stored, t_current);
+
+ if(t_stored<MIN_TIME)
+ t_stored=MIN_TIME;
+
+ if(t_stored<t_current)
+ {
+ f = fopen(TIME_FILE, "w");
+ fprintf(f, "%ld", t_current);
+ fclose(f);
+ }
+ else
+ {
+ t_stored += TIME_CHECK_PERIOD;
+ struct tm *t = localtime(&t_stored);
+ struct timeval tv = {mktime(t), 0};
+ settimeofday(&tv, 0);
+ }
+}
+
+
+static struct pollfd *ufds;
+static char **device_names;
+static int nfds;
+
+
+
+static int open_device(const char *device, int print_flags)
+{
+ int fd;
+ struct pollfd *new_ufds;
+ char **new_device_names;
+
+ fd = open(device, O_RDWR);
+ if(fd < 0)
+ {
+ fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
+ return -1;
+ }
+
+ new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1));
+ if(new_ufds == NULL)
+ {
+ fprintf(stderr, "out of memory\n");
+ return -1;
+ }
+ ufds = new_ufds;
+ new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1));
+ if(new_device_names == NULL)
+ {
+ fprintf(stderr, "out of memory\n");
+ return -1;
+ }
+ device_names = new_device_names;
+
+ ufds[nfds].fd = fd;
+ ufds[nfds].events = POLLIN;
+ device_names[nfds] = strdup(device);
+ nfds++;
+
+ return 0;
+}
+
+
+
+static int scan_dir(const char *dirname, int print_flags)
+{
+ char devname[PATH_MAX];
+ char *filename;
+ DIR *dir;
+ struct dirent *de;
+ dir = opendir(dirname);
+ if(dir == NULL)
+ return -1;
+ strcpy(devname, dirname);
+ filename = devname + strlen(devname);
+ *filename++ = '/';
+ while((de = readdir(dir)))
+ {
+ if(de->d_name[0] == '.' &&
+ (de->d_name[1] == '\0' ||
+ (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+ continue;
+ strcpy(filename, de->d_name);
+ open_device(devname, print_flags);
+ }
+ closedir(dir);
+ return 0;
+}
+
+
+
+void button_init_device(void)
+{
+ int res;
+ int print_flags = 0;
+ const char *device = NULL;
+ const char *device_path = "/dev/input";
+
+ nfds = 1;
+ ufds = calloc(1, sizeof(ufds[0]));
+ ufds[0].fd = inotify_init();
+ ufds[0].events = POLLIN;
+ if(device)
+ {
+ res = open_device(device, print_flags);
+ if(res < 0) {
+ fprintf(stderr, "open device failed\n");
+ }
+ }
+ else
+ {
+ res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE);
+ if(res < 0)
+ {
+ fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
+ }
+ res = scan_dir(device_path, print_flags);
+ if(res < 0)
+ {
+ fprintf(stderr, "scan dir failed for %s\n", device_path);
+ }
+ }
+}
+
+
+int draw()
+{
+ int fbfd = 0;
+ struct fb_var_screeninfo vinfo;
+ struct fb_fix_screeninfo finfo;
+ long int screensize = 0;
+ char *fbp = 0;
+ int x = 0, y = 0;
+ long int location = 0;
+
+ /* Open the file for reading and writing */
+ fbfd = open("/dev/graphics/fb0", O_RDWR);
+ if (fbfd == -1)
+ {
+ perror("Error: cannot open framebuffer device");
+ exit(1);
+ }
+ /* Get fixed screen information */
+ if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1)
+ {
+ perror("Error reading fixed information");
+ exit(2);
+ }
+
+ /* Get variable screen information */
+ if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1)
+ {
+ perror("Error reading variable information");
+ exit(3);
+ }
+
+ /* Figure out the size of the screen in bytes */
+ screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
+
+ vinfo.xres = vinfo.xres_virtual = vinfo.width = 320;
+ vinfo.yres = vinfo.yres_virtual = vinfo.height = 240;
+ vinfo.xoffset = vinfo.yoffset = vinfo.sync = vinfo.vmode = 0;
+ vinfo.pixclock = 104377;
+ vinfo.left_margin = 20;
+ vinfo.right_margin = 50;
+ vinfo.upper_margin = 2;
+ vinfo.lower_margin = 4;
+ vinfo.hsync_len = 10;
+ vinfo.vsync_len = 2;
+ vinfo.red.offset = 11;
+ vinfo.red.length = 5;
+ vinfo.red.msb_right = 0;
+ vinfo.green.offset = 5;
+ vinfo.green.length = 6;
+ vinfo.green.msb_right = 0;
+ vinfo.blue.offset = 0;
+ vinfo.blue.length = 5;
+ vinfo.blue.msb_right = 0;
+ vinfo.transp.offset = vinfo.transp.length = vinfo.transp.msb_right = 0;
+ vinfo.nonstd = 4;
+
+ if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
+ {
+ perror("fbset(ioctl)");
+ exit(4);
+ }
+
+
+ /* Map the device to memory */
+ fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fbfd, 0);
+ if ((int)fbp == -1)
+ {
+ perror("Error: failed to map framebuffer device to memory");
+ exit(4);
+ }
+
+ BMP* bmp = BMP_ReadFile("/system/rockbox/chooser.bmp");
+ BMP_CHECK_ERROR( stderr, -1 );
+
+ UCHAR r, g, b;
+ unsigned short int t;
+
+ for (y = 0; y < 240; y++)
+ for (x = 0; x < 320; x++)
+ {
+ location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
+ (y+vinfo.yoffset) * finfo.line_length;
+
+ BMP_GetPixelRGB(bmp, x, y, &r, &g, &b);
+ t = (r>>3)<<11 | (g>>2) << 5 | (b>>3);
+ *((unsigned short int*)(fbp + location)) = t;
+ }
+
+ BMP_Free( bmp );
+
+ munmap(fbp, screensize);
+ close(fbfd);
+ return 0;
+}
+
+
+int choose_player()
+{
+ int i;
+ int res;
+ struct input_event event;
+
+ while(true)
+ {
+ poll(ufds, nfds, POLL_MS);
+ for(i = 1; i < nfds; i++)
+ {
+ if(ufds[i].revents & POLLIN)
+ {
+ res = read(ufds[i].fd, &event, sizeof(event));
+ if(res < (int)sizeof(event))
+ {
+ fprintf(stderr, "could not get event\n");
+ }
+ if(event.type==1)
+ {
+ if(event.code==KEYCODE_NEXT)
+ {
+ puts("rockbox!");
+ return 1;
+ }
+ else if(event.code==KEYCODE_PREV)
+ {
+ puts("mango!");
+ return 0;
+ }
+ else if(event.code==KEYCODE_PWR || event.code==KEYCODE_PWR_LONG)
+ {
+ reboot(LINUX_REBOOT_CMD_POWER_OFF);
+ }
+ }
+ else if(event.type==3)
+ {
+ if(event.code==53) //x coord
+ {
+ if(event.value<160)
+ {
+ puts("mango!");
+ return 0;
+ }
+ else
+ {
+ puts("rockbox!");
+ return 1;
+ }
+ }
+ }
+ }
+ }
+ }
+ return true;
+}
+
+bool check_for_hold()
+{
+ FILE *f = fopen("/sys/class/axppower/holdkey", "r");
+ char x;
+ fscanf(f, "%c", &x);
+ fclose(f);
+
+ if(x & KEY_HOLD_OFF)
+ return false;
+ else
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ FILE *f;
+ int last_chosen_player = -1;
+
+ f = fopen(PLAYER_FILE, "r");
+ if(f!=NULL)
+ {
+ fscanf(f, "%d", &last_chosen_player);
+ fclose(f);
+ }
+ bool ask = (access(VOLD_LINK, F_OK) == -1) || ((access(NOASK_FLAG, F_OK) == -1) && check_for_hold()) || (last_chosen_player==-1);
+
+ if(ask)
+ {
+ draw();
+ button_init_device();
+ int player_chosen_now = choose_player();
+
+ if(last_chosen_player!=player_chosen_now)
+ {
+ f = fopen(PLAYER_FILE, "w");
+ fprintf(f, "%d", player_chosen_now);
+ fclose(f);
+ }
+
+ if(last_chosen_player!=player_chosen_now || (access(VOLD_LINK, F_OK) == -1))
+ {
+ system("rm "VOLD_LINK);
+
+ if(player_chosen_now)
+ system("ln -s /system/bin/vold_rockbox "VOLD_LINK);
+ else
+ system("ln -s /system/bin/vold_original "VOLD_LINK);
+
+ system("touch "NOASK_FLAG);
+ system("reboot");
+ }
+ last_chosen_player = player_chosen_now;
+ }
+
+ system("rm "NOASK_FLAG);
+
+ while(1)
+ {
+ if(last_chosen_player)
+ {
+// system("/system/bin/openadb");
+ system("/system/rockbox/lib/rockbox");
+ }
+ else
+// system("/system/bin/closeadb");
+ system("/system/bin/MangoPlayer_original");
+
+ sleep(1);
+ }
+
+ return 0;
+}
+
+
+
diff --git a/rbutil/ibassoboot/jni/qdbmp.c b/rbutil/ibassoboot/jni/qdbmp.c
new file mode 100644
index 0000000000..fd1337277d
--- /dev/null
+++ b/rbutil/ibassoboot/jni/qdbmp.c
@@ -0,0 +1,798 @@
+#include "qdbmp.h"
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Bitmap header */
+typedef struct _BMP_Header
+{
+ USHORT Magic; /* Magic identifier: "BM" */
+ UINT FileSize; /* Size of the BMP file in bytes */
+ USHORT Reserved1; /* Reserved */
+ USHORT Reserved2; /* Reserved */
+ UINT DataOffset; /* Offset of image data relative to the file's start */
+ UINT HeaderSize; /* Size of the header in bytes */
+ UINT Width; /* Bitmap's width */
+ UINT Height; /* Bitmap's height */
+ USHORT Planes; /* Number of color planes in the bitmap */
+ USHORT BitsPerPixel; /* Number of bits per pixel */
+ UINT CompressionType; /* Compression type */
+ UINT ImageDataSize; /* Size of uncompressed image's data */
+ UINT HPixelsPerMeter; /* Horizontal resolution (pixels per meter) */
+ UINT VPixelsPerMeter; /* Vertical resolution (pixels per meter) */
+ UINT ColorsUsed; /* Number of color indexes in the color table that are actually used by the bitmap */
+ UINT ColorsRequired; /* Number of color indexes that are required for displaying the bitmap */
+} BMP_Header;
+
+
+/* Private data structure */
+struct _BMP
+{
+ BMP_Header Header;
+ UCHAR* Palette;
+ UCHAR* Data;
+};
+
+
+/* Holds the last error code */
+static BMP_STATUS BMP_LAST_ERROR_CODE = 0;
+
+
+/* Error description strings */
+static const char* BMP_ERROR_STRING[] =
+{
+ "",
+ "General error",
+ "Could not allocate enough memory to complete the operation",
+ "File input/output error",
+ "File not found",
+ "File is not a supported BMP variant (must be uncompressed 8, 24 or 32 BPP)",
+ "File is not a valid BMP image",
+ "An argument is invalid or out of range",
+ "The requested action is not compatible with the BMP's type"
+};
+
+
+/* Size of the palette data for 8 BPP bitmaps */
+#define BMP_PALETTE_SIZE ( 256 * 4 )
+
+
+
+/*********************************** Forward declarations **********************************/
+int ReadHeader ( BMP* bmp, FILE* f );
+int WriteHeader ( BMP* bmp, FILE* f );
+
+int ReadUINT ( UINT* x, FILE* f );
+int ReadUSHORT ( USHORT *x, FILE* f );
+
+int WriteUINT ( UINT x, FILE* f );
+int WriteUSHORT ( USHORT x, FILE* f );
+
+
+
+
+
+
+/*********************************** Public methods **********************************/
+
+
+/**************************************************************
+ Creates a blank BMP image with the specified dimensions
+ and bit depth.
+**************************************************************/
+BMP* BMP_Create( UINT width, UINT height, USHORT depth )
+{
+ BMP* bmp;
+ int bytes_per_pixel = depth >> 3;
+ UINT bytes_per_row;
+
+ if ( height <= 0 || width <= 0 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ return NULL;
+ }
+
+ if ( depth != 8 && depth != 24 && depth != 32 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
+ return NULL;
+ }
+
+
+ /* Allocate the bitmap data structure */
+ bmp = calloc( 1, sizeof( BMP ) );
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+
+ /* Set header' default values */
+ bmp->Header.Magic = 0x4D42;
+ bmp->Header.Reserved1 = 0;
+ bmp->Header.Reserved2 = 0;
+ bmp->Header.HeaderSize = 40;
+ bmp->Header.Planes = 1;
+ bmp->Header.CompressionType = 0;
+ bmp->Header.HPixelsPerMeter = 0;
+ bmp->Header.VPixelsPerMeter = 0;
+ bmp->Header.ColorsUsed = 0;
+ bmp->Header.ColorsRequired = 0;
+
+
+ /* Calculate the number of bytes used to store a single image row. This is always
+ rounded up to the next multiple of 4. */
+ bytes_per_row = width * bytes_per_pixel;
+ bytes_per_row += ( bytes_per_row % 4 ? 4 - bytes_per_row % 4 : 0 );
+
+
+ /* Set header's image specific values */
+ bmp->Header.Width = width;
+ bmp->Header.Height = height;
+ bmp->Header.BitsPerPixel = depth;
+ bmp->Header.ImageDataSize = bytes_per_row * height;
+ bmp->Header.FileSize = bmp->Header.ImageDataSize + 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
+ bmp->Header.DataOffset = 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
+
+
+ /* Allocate palette */
+ if ( bmp->Header.BitsPerPixel == 8 )
+ {
+ bmp->Palette = (UCHAR*) calloc( BMP_PALETTE_SIZE, sizeof( UCHAR ) );
+ if ( bmp->Palette == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
+ free( bmp );
+ return NULL;
+ }
+ }
+ else
+ {
+ bmp->Palette = NULL;
+ }
+
+
+ /* Allocate pixels */
+ bmp->Data = (UCHAR*) calloc( bmp->Header.ImageDataSize, sizeof( UCHAR ) );
+ if ( bmp->Data == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
+ free( bmp->Palette );
+ free( bmp );
+ return NULL;
+ }
+
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ return bmp;
+}
+
+
+/**************************************************************
+ Frees all the memory used by the specified BMP image.
+**************************************************************/
+void BMP_Free( BMP* bmp )
+{
+ if ( bmp == NULL )
+ {
+ return;
+ }
+
+ if ( bmp->Palette != NULL )
+ {
+ free( bmp->Palette );
+ }
+
+ if ( bmp->Data != NULL )
+ {
+ free( bmp->Data );
+ }
+
+ free( bmp );
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+}
+
+
+/**************************************************************
+ Reads the specified BMP image file.
+**************************************************************/
+BMP* BMP_ReadFile( const char* filename )
+{
+ BMP* bmp;
+ FILE* f;
+
+ if ( filename == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ return NULL;
+ }
+
+
+ /* Allocate */
+ bmp = calloc( 1, sizeof( BMP ) );
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
+ return NULL;
+ }
+
+
+ /* Open file */
+ f = fopen( filename, "rb" );
+ if ( f == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
+ free( bmp );
+ return NULL;
+ }
+
+
+ /* Read header */
+ if ( ReadHeader( bmp, f ) != BMP_OK || bmp->Header.Magic != 0x4D42 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
+ fclose( f );
+ free( bmp );
+ return NULL;
+ }
+
+
+ /* Verify that the bitmap variant is supported */
+ if ( ( bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 8 )
+ || bmp->Header.CompressionType != 0 || bmp->Header.HeaderSize != 40 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
+ fclose( f );
+ free( bmp );
+ return NULL;
+ }
+
+
+ /* Allocate and read palette */
+ if ( bmp->Header.BitsPerPixel == 8 )
+ {
+ bmp->Palette = (UCHAR*) malloc( BMP_PALETTE_SIZE * sizeof( UCHAR ) );
+ if ( bmp->Palette == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
+ fclose( f );
+ free( bmp );
+ return NULL;
+ }
+
+ if ( fread( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
+ fclose( f );
+ free( bmp->Palette );
+ free( bmp );
+ return NULL;
+ }
+ }
+ else /* Not an indexed image */
+ {
+ bmp->Palette = NULL;
+ }
+
+
+ /* Allocate memory for image data */
+ bmp->Data = (UCHAR*) malloc( bmp->Header.ImageDataSize );
+ if ( bmp->Data == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
+ fclose( f );
+ free( bmp->Palette );
+ free( bmp );
+ return NULL;
+ }
+
+
+ /* Read image data */
+ if ( fread( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
+ fclose( f );
+ free( bmp->Data );
+ free( bmp->Palette );
+ free( bmp );
+ return NULL;
+ }
+
+
+ fclose( f );
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ return bmp;
+}
+
+
+/**************************************************************
+ Writes the BMP image to the specified file.
+**************************************************************/
+void BMP_WriteFile( BMP* bmp, const char* filename )
+{
+ FILE* f;
+
+ if ( filename == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ return;
+ }
+
+
+ /* Open file */
+ f = fopen( filename, "wb" );
+ if ( f == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
+ return;
+ }
+
+
+ /* Write header */
+ if ( WriteHeader( bmp, f ) != BMP_OK )
+ {
+ BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
+ fclose( f );
+ return;
+ }
+
+
+ /* Write palette */
+ if ( bmp->Palette )
+ {
+ if ( fwrite( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
+ {
+ BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
+ fclose( f );
+ return;
+ }
+ }
+
+
+ /* Write data */
+ if ( fwrite( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
+ {
+ BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
+ fclose( f );
+ return;
+ }
+
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+ fclose( f );
+}
+
+
+/**************************************************************
+ Returns the image's width.
+**************************************************************/
+UINT BMP_GetWidth( BMP* bmp )
+{
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ return -1;
+ }
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ return ( bmp->Header.Width );
+}
+
+
+/**************************************************************
+ Returns the image's height.
+**************************************************************/
+UINT BMP_GetHeight( BMP* bmp )
+{
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ return -1;
+ }
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ return ( bmp->Header.Height );
+}
+
+
+/**************************************************************
+ Returns the image's color depth (bits per pixel).
+**************************************************************/
+USHORT BMP_GetDepth( BMP* bmp )
+{
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ return -1;
+ }
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ return ( bmp->Header.BitsPerPixel );
+}
+
+
+/**************************************************************
+ Populates the arguments with the specified pixel's RGB
+ values.
+**************************************************************/
+void BMP_GetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b )
+{
+ UCHAR* pixel;
+ UINT bytes_per_row;
+ UCHAR bytes_per_pixel;
+
+ if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ }
+ else
+ {
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
+
+ /* Row's size is rounded up to the next multiple of 4 bytes */
+ bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
+
+ /* Calculate the location of the relevant pixel (rows are flipped) */
+ pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
+
+
+ /* In indexed color mode the pixel's value is an index within the palette */
+ if ( bmp->Header.BitsPerPixel == 8 )
+ {
+ pixel = bmp->Palette + *pixel * 4;
+ }
+
+ /* Note: colors are stored in BGR order */
+ if ( r ) *r = *( pixel + 2 );
+ if ( g ) *g = *( pixel + 1 );
+ if ( b ) *b = *( pixel + 0 );
+ }
+}
+
+
+/**************************************************************
+ Sets the specified pixel's RGB values.
+**************************************************************/
+void BMP_SetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b )
+{
+ UCHAR* pixel;
+ UINT bytes_per_row;
+ UCHAR bytes_per_pixel;
+
+ if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ }
+
+ else if ( bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 32 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
+ }
+
+ else
+ {
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
+
+ /* Row's size is rounded up to the next multiple of 4 bytes */
+ bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
+
+ /* Calculate the location of the relevant pixel (rows are flipped) */
+ pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
+
+ /* Note: colors are stored in BGR order */
+ *( pixel + 2 ) = r;
+ *( pixel + 1 ) = g;
+ *( pixel + 0 ) = b;
+ }
+}
+
+
+/**************************************************************
+ Gets the specified pixel's color index.
+**************************************************************/
+void BMP_GetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR* val )
+{
+ UCHAR* pixel;
+ UINT bytes_per_row;
+
+ if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ }
+
+ else if ( bmp->Header.BitsPerPixel != 8 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
+ }
+
+ else
+ {
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ /* Row's size is rounded up to the next multiple of 4 bytes */
+ bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
+
+ /* Calculate the location of the relevant pixel */
+ pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
+
+
+ if ( val ) *val = *pixel;
+ }
+}
+
+
+/**************************************************************
+ Sets the specified pixel's color index.
+**************************************************************/
+void BMP_SetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR val )
+{
+ UCHAR* pixel;
+ UINT bytes_per_row;
+
+ if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ }
+
+ else if ( bmp->Header.BitsPerPixel != 8 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
+ }
+
+ else
+ {
+ BMP_LAST_ERROR_CODE = BMP_OK;
+
+ /* Row's size is rounded up to the next multiple of 4 bytes */
+ bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
+
+ /* Calculate the location of the relevant pixel */
+ pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
+
+ *pixel = val;
+ }
+}
+
+
+/**************************************************************
+ Gets the color value for the specified palette index.
+**************************************************************/
+void BMP_GetPaletteColor( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b )
+{
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ }
+
+ else if ( bmp->Header.BitsPerPixel != 8 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
+ }
+
+ else
+ {
+ if ( r ) *r = *( bmp->Palette + index * 4 + 2 );
+ if ( g ) *g = *( bmp->Palette + index * 4 + 1 );
+ if ( b ) *b = *( bmp->Palette + index * 4 + 0 );
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+ }
+}
+
+
+/**************************************************************
+ Sets the color value for the specified palette index.
+**************************************************************/
+void BMP_SetPaletteColor( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b )
+{
+ if ( bmp == NULL )
+ {
+ BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
+ }
+
+ else if ( bmp->Header.BitsPerPixel != 8 )
+ {
+ BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
+ }
+
+ else
+ {
+ *( bmp->Palette + index * 4 + 2 ) = r;
+ *( bmp->Palette + index * 4 + 1 ) = g;
+ *( bmp->Palette + index * 4 + 0 ) = b;
+
+ BMP_LAST_ERROR_CODE = BMP_OK;
+ }
+}
+
+
+/**************************************************************
+ Returns the last error code.
+**************************************************************/
+BMP_STATUS BMP_GetError()
+{
+ return BMP_LAST_ERROR_CODE;
+}
+
+
+/**************************************************************
+ Returns a description of the last error code.
+**************************************************************/
+const char* BMP_GetErrorDescription()
+{
+ if ( BMP_LAST_ERROR_CODE > 0 && BMP_LAST_ERROR_CODE < BMP_ERROR_NUM )
+ {
+ return BMP_ERROR_STRING[ BMP_LAST_ERROR_CODE ];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+
+
+
+
+/*********************************** Private methods **********************************/
+
+
+/**************************************************************
+ Reads the BMP file's header into the data structure.
+ Returns BMP_OK on success.
+**************************************************************/
+int ReadHeader( BMP* bmp, FILE* f )
+{
+ if ( bmp == NULL || f == NULL )
+ {
+ return BMP_INVALID_ARGUMENT;
+ }
+
+ /* The header's fields are read one by one, and converted from the format's
+ little endian to the system's native representation. */
+ if ( !ReadUSHORT( &( bmp->Header.Magic ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.FileSize ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUSHORT( &( bmp->Header.Reserved1 ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUSHORT( &( bmp->Header.Reserved2 ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.DataOffset ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.HeaderSize ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.Width ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.Height ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUSHORT( &( bmp->Header.Planes ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUSHORT( &( bmp->Header.BitsPerPixel ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.CompressionType ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.ImageDataSize ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.HPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.VPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.ColorsUsed ), f ) ) return BMP_IO_ERROR;
+ if ( !ReadUINT( &( bmp->Header.ColorsRequired ), f ) ) return BMP_IO_ERROR;
+
+ return BMP_OK;
+}
+
+
+/**************************************************************
+ Writes the BMP file's header into the data structure.
+ Returns BMP_OK on success.
+**************************************************************/
+int WriteHeader( BMP* bmp, FILE* f )
+{
+ if ( bmp == NULL || f == NULL )
+ {
+ return BMP_INVALID_ARGUMENT;
+ }
+
+ /* The header's fields are written one by one, and converted to the format's
+ little endian representation. */
+ if ( !WriteUSHORT( bmp->Header.Magic, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.FileSize, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUSHORT( bmp->Header.Reserved1, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUSHORT( bmp->Header.Reserved2, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.DataOffset, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.HeaderSize, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.Width, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.Height, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUSHORT( bmp->Header.Planes, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUSHORT( bmp->Header.BitsPerPixel, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.CompressionType, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.ImageDataSize, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.HPixelsPerMeter, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.VPixelsPerMeter, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.ColorsUsed, f ) ) return BMP_IO_ERROR;
+ if ( !WriteUINT( bmp->Header.ColorsRequired, f ) ) return BMP_IO_ERROR;
+
+ return BMP_OK;
+}
+
+
+/**************************************************************
+ Reads a little-endian unsigned int from the file.
+ Returns non-zero on success.
+**************************************************************/
+int ReadUINT( UINT* x, FILE* f )
+{
+ UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
+
+ if ( x == NULL || f == NULL )
+ {
+ return 0;
+ }
+
+ if ( fread( little, 4, 1, f ) != 1 )
+ {
+ return 0;
+ }
+
+ *x = ( little[ 3 ] << 24 | little[ 2 ] << 16 | little[ 1 ] << 8 | little[ 0 ] );
+
+ return 1;
+}
+
+
+/**************************************************************
+ Reads a little-endian unsigned short int from the file.
+ Returns non-zero on success.
+**************************************************************/
+int ReadUSHORT( USHORT *x, FILE* f )
+{
+ UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
+
+ if ( x == NULL || f == NULL )
+ {
+ return 0;
+ }
+
+ if ( fread( little, 2, 1, f ) != 1 )
+ {
+ return 0;
+ }
+
+ *x = ( little[ 1 ] << 8 | little[ 0 ] );
+
+ return 1;
+}
+
+
+/**************************************************************
+ Writes a little-endian unsigned int to the file.
+ Returns non-zero on success.
+**************************************************************/
+int WriteUINT( UINT x, FILE* f )
+{
+ UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
+
+ little[ 3 ] = (UCHAR)( ( x & 0xff000000 ) >> 24 );
+ little[ 2 ] = (UCHAR)( ( x & 0x00ff0000 ) >> 16 );
+ little[ 1 ] = (UCHAR)( ( x & 0x0000ff00 ) >> 8 );
+ little[ 0 ] = (UCHAR)( ( x & 0x000000ff ) >> 0 );
+
+ return ( f && fwrite( little, 4, 1, f ) == 1 );
+}
+
+
+/**************************************************************
+ Writes a little-endian unsigned short int to the file.
+ Returns non-zero on success.
+**************************************************************/
+int WriteUSHORT( USHORT x, FILE* f )
+{
+ UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
+
+ little[ 1 ] = (UCHAR)( ( x & 0xff00 ) >> 8 );
+ little[ 0 ] = (UCHAR)( ( x & 0x00ff ) >> 0 );
+
+ return ( f && fwrite( little, 2, 1, f ) == 1 );
+}
+
diff --git a/rbutil/ibassoboot/jni/qdbmp.h b/rbutil/ibassoboot/jni/qdbmp.h
new file mode 100644
index 0000000000..d6c0e6c452
--- /dev/null
+++ b/rbutil/ibassoboot/jni/qdbmp.h
@@ -0,0 +1,133 @@
+#ifndef _BMP_H_
+#define _BMP_H_
+
+
+/**************************************************************
+
+ QDBMP - Quick n' Dirty BMP
+
+ v1.0.0 - 2007-04-07
+ http://qdbmp.sourceforge.net
+
+
+ The library supports the following BMP variants:
+ 1. Uncompressed 32 BPP (alpha values are ignored)
+ 2. Uncompressed 24 BPP
+ 3. Uncompressed 8 BPP (indexed color)
+
+ QDBMP is free and open source software, distributed
+ under the MIT licence.
+
+ Copyright (c) 2007 Chai Braudo (braudo@users.sourceforge.net)
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+**************************************************************/
+
+#include <stdio.h>
+
+
+
+/* Type definitions */
+#ifndef UINT
+ #define UINT unsigned long int
+#endif
+
+#ifndef USHORT
+ #define USHORT unsigned short
+#endif
+
+#ifndef UCHAR
+ #define UCHAR unsigned char
+#endif
+
+
+/* Version */
+#define QDBMP_VERSION_MAJOR 1
+#define QDBMP_VERSION_MINOR 0
+#define QDBMP_VERSION_PATCH 1
+
+
+/* Error codes */
+typedef enum
+{
+ BMP_OK = 0, /* No error */
+ BMP_ERROR, /* General error */
+ BMP_OUT_OF_MEMORY, /* Could not allocate enough memory to complete the operation */
+ BMP_IO_ERROR, /* General input/output error */
+ BMP_FILE_NOT_FOUND, /* File not found */
+ BMP_FILE_NOT_SUPPORTED, /* File is not a supported BMP variant */
+ BMP_FILE_INVALID, /* File is not a BMP image or is an invalid BMP */
+ BMP_INVALID_ARGUMENT, /* An argument is invalid or out of range */
+ BMP_TYPE_MISMATCH, /* The requested action is not compatible with the BMP's type */
+ BMP_ERROR_NUM
+} BMP_STATUS;
+
+
+/* Bitmap image */
+typedef struct _BMP BMP;
+
+
+
+
+/*********************************** Public methods **********************************/
+
+
+/* Construction/destruction */
+BMP* BMP_Create ( UINT width, UINT height, USHORT depth );
+void BMP_Free ( BMP* bmp );
+
+
+/* I/O */
+BMP* BMP_ReadFile ( const char* filename );
+void BMP_WriteFile ( BMP* bmp, const char* filename );
+
+
+/* Meta info */
+UINT BMP_GetWidth ( BMP* bmp );
+UINT BMP_GetHeight ( BMP* bmp );
+USHORT BMP_GetDepth ( BMP* bmp );
+
+
+/* Pixel access */
+void BMP_GetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b );
+void BMP_SetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b );
+void BMP_GetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR* val );
+void BMP_SetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR val );
+
+
+/* Palette handling */
+void BMP_GetPaletteColor ( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b );
+void BMP_SetPaletteColor ( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b );
+
+
+/* Error handling */
+BMP_STATUS BMP_GetError ();
+const char* BMP_GetErrorDescription ();
+
+
+/* Useful macro that may be used after each BMP operation to check for an error */
+#define BMP_CHECK_ERROR( output_file, return_value ) \
+ if ( BMP_GetError() != BMP_OK ) \
+ { \
+ fprintf( ( output_file ), "BMP error: %s\n", BMP_GetErrorDescription() ); \
+ return( return_value ); \
+ } \
+
+#endif
diff --git a/tools/configure b/tools/configure
index 12025ba942..20b9095f73 100755
--- a/tools/configure
+++ b/tools/configure
@@ -664,14 +664,19 @@ androidcc () {
exit
fi
if [ -z "$ANDROID_NDK_PATH" ]; then
- echo "ERROR: You need the Android NDK installed (r5 or higher) and have the ANDROID_NDK_PATH"
+ echo "ERROR: You need the Android NDK installed (r16 or higher) and have the ANDROID_NDK_PATH"
echo "environment variable point to the root directory of the Android NDK."
exit
fi
buildhost=$(uname | tr "[:upper:]" "[:lower:]")
GCCOPTS=`echo $CCOPTS | sed -e s/-ffreestanding// -e s/-nostdlib// -e s/-Wundef//`
- LDOPTS="$LDOPTS -Wl,-soname,librockbox.so -shared -ldl -llog"
- GLOBAL_LDOPTS="-Wl,-z,defs -Wl,-z,noexecstack -shared"
+ LDOPTS="$LDOPTS -ldl -llog"
+ if [ "$modelname" != "ibassodx50" ] && [ "$modelname" != "ibassodx90" ]; then
+ LDOPTS="$LDOPTS -Wl,-soname,librockbox.so -shared"
+ fi
+ SHARED_LDFLAG="-shared"
+ SHARED_CFLAGS=''
+ GLOBAL_LDOPTS="-Wl,-z,defs -Wl,-z,noexecstack"
ANDROID_ARCH=$1 # for android.make too
gccchoice="4.6"
# arch dependant stuff
@@ -683,8 +688,8 @@ androidcc () {
# threads work fine so far
thread_support="ASSEMBLER_THREADS"
GCCOPTS="$GCCOPTS -march=armv5te -mtune=xscale -msoft-float -fomit-frame-pointer \
- --sysroot=$ANDROID_NDK_PATH/platforms/android-5/arch-arm"
- LDOPTS="$LDOPTS --sysroot=$ANDROID_NDK_PATH/platforms/android-5/arch-arm"
+ --sysroot=$ANDROID_NDK_PATH/platforms/android-16/arch-arm"
+ LDOPTS="$LDOPTS --sysroot=$ANDROID_NDK_PATH/platforms/android-16/arch-arm"
;;
mips)
endian="little"
@@ -1336,13 +1341,10 @@ cat <<EOF
203) Nokia N900 212) MA8 220) NWZ-E370/E380 series
204) Pandora 213) MA8C 221) NWZ-E360 series
205) Samsung YP-R0
- 206) Android MIPS
- 207) Android x86
- 208) Samsung YP-R1
+ 206) Android MIPS ==IHIFI== ==iBasso==
+ 207) Android x86 230) 760 232) DX50
+ 208) Samsung YP-R1 231) 960 233) DX90
-==IHIFI==
- 230) 760
- 231) 960
EOF
@@ -3744,6 +3746,62 @@ fi
t_model="ihifi"
;;
+ 232|ibassodx50)
+ application="yes"
+ target_id=94
+ modelname="ibassodx50"
+ target="DX50"
+ app_type="android_standalone"
+ lcd_orientation="landscape"
+ sharedir="/system/rockbox/app_rockbox/rockbox"
+ bindir="/system/rockbox/lib"
+ libdir="/system/rockbox/app_rockbox"
+ memory=32
+ uname=`uname`
+ androidcc armeabi
+ tool="cp "
+ boottool="cp "
+ bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
+ bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
+ output="rockbox"
+ bootoutput="rockbox"
+ appextra="recorder:gui:radio:hosted/android"
+ plugins="yes"
+ swcodec="yes"
+ # architecture, manufacturer and model for the target-tree build
+ t_cpu="hosted"
+ t_manufacturer="android"
+ t_model="dx50"
+ ;;
+
+ 233|ibassodx90)
+ application="yes"
+ target_id=95
+ modelname="ibassodx90"
+ target="DX90"
+ app_type="android_standalone"
+ lcd_orientation="landscape"
+ sharedir="/system/rockbox/app_rockbox/rockbox"
+ bindir="/system/rockbox/lib"
+ libdir="/system/rockbox/app_rockbox"
+ memory=32
+ uname=`uname`
+ androidcc armeabi
+ tool="cp "
+ boottool="cp "
+ bmp2rb_mono="$rootdir/tools/bmp2rb -f 0"
+ bmp2rb_native="$rootdir/tools/bmp2rb -f 4"
+ output="rockbox"
+ bootoutput="rockbox"
+ appextra="recorder:gui:radio:hosted/android"
+ plugins="yes"
+ swcodec="yes"
+ # architecture, manufacturer and model for the target-tree build
+ t_cpu="hosted"
+ t_manufacturer="android"
+ t_model="dx50"
+ ;;
+
*)
echo "Please select a supported target platform!"
exit 7