summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rothen <rothen@gmx.net>2014-08-30 13:15:53 +0200
committerMichael Giacomelli <giac2000@hotmail.com>2014-09-18 18:19:01 +0200
commit0b5ad60c26f30dc5363c21e436b73292c09ac567 (patch)
tree2d7cee2b2133218d59e0f462c9dbdbec8e88b2e2
parent1f0fa0546647a191c52784a4a225982ffbd1af11 (diff)
downloadrockbox-0b5ad60.tar.gz
rockbox-0b5ad60.zip
Introducing Targets iBasso DX50 & iBasso DX90
The port to for this two targets has been entirely developped by Ilia Sergachev (alias Il or xzcc). His source can be found at https://bitbucket.org/isergachev/rockbox . The few necesary modifications for the DX90 port was done by headwhacker form head-fi.org. Unfortunately i could not try out the final state of the DX90 port. The port is hosted on android (without java) as standalone app. The official Firmware is required to run this port. Ilia did modify the source files for the "android" target in the rockbox source to make the DX port work. The work I did was to separate the code for DX50 (&DX90) from the android target. On this Target Ilia used source from tinyalsa from AOSP. I did not touch that part of the code because I do not understand it. What else I changed from Ilias sources besides the separation from the target "android": * removed a dirty hack to keep backlight off * changed value battery meter to voltage battery meter * made all plugins compile (named target as "standalone") and added keymaps * i added the graphics for the manual but did not do anything else for the manual yet * minor optimizations known bugs: * timers are slowed donw when playback is active (tinyalsa related?) * some minor bugs Things to do: * The main prolem will be how to install the app correctly. A guy called DOC2008 added a CWM (by androtab.info) to the official firmware and Ilia made a CWM installation script and a dualboot selector (rbutils/ibassoboot, build with ndk-build). We will have to find a way to install rockbox in a proper way without breaking any copyrights. Maybe ADB is an option but it is not enable with OF by default. Patching the OF is probably the way to go. * All the wiki and manual to build: needed: android ndk installed, android sdk installed with additional build-tools 19.1.0 installed ./tools/configure select iBasso DX50 or iBasso DX90 make -j apk the content of rockbox.zip/.rockbox needs to be copied to /system/rockbox/app_rockbox/rockbox/ (rockbox app not needed) the content of libs/armeabi to /system/rockbox/lib/ (rockbox app needed) The boot selector is needed as /system/bin/MangoPlayer and the iBasso app as /system/bin/MangoPlayer_original. There is also the "vold" file. The one from OF does not work with DX50 rockbox (DX90 works!?), the one from Ilia is necessary. Until we have found a proper way to install it, it can only be installed following the instructions of Ilia on his bitbucket page, using the CWM-OF and his installation script package. Change-Id: Ic4faaf84824c162aabcc08e492cee6e0068719d0 Reviewed-on: http://gerrit.rockbox.org/941 Tested: Chiwen Chang <rock1104.tw@yahoo.com.tw> Reviewed-by: Michael Giacomelli <giac2000@hotmail.com>
-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