From 2a471e288c16b91a7186a60b3fb84dd55a494c7a Mon Sep 17 00:00:00 2001 From: Solomon Peachy Date: Thu, 8 Oct 2020 09:47:40 -0400 Subject: New port: AIGO EROS Q / EROS K The Q and K have a slightly different case, but the hardware under the shell is completely identical. These models are rebadged versions: * Hifiwalker H2 (== Q) * AGPTek H3 (== K) * Surfans F20 (== K) Other notes: * Significant improvements in the shared Hiby-platform launcher/loader * SD card can theoretically be hot-swapped now * Support external USB mass storage! * Some consolidation of Hiby-platform targets * Some consolidation of plugin keymaps Todo/known issues: * Keymaps need to be gone over properly * Convert to HAVE_SCROLLWHEEL? Change-Id: I5a8a4f22c38a5b69392ca7c0a8ad8c4e07d9523c --- firmware/SOURCES | 12 +- firmware/asm/SOURCES | 4 +- firmware/drivers/audio/erosqlinux_codec.c | 181 +++++++++++++++++++++++++ firmware/export/audiohw.h | 2 + firmware/export/config.h | 3 + firmware/export/config/agptekrocker.h | 1 + firmware/export/config/aigoerosq.h | 132 ++++++++++++++++++ firmware/export/config/fiiom3k.h | 2 + firmware/export/config/xduoox20.h | 2 + firmware/export/config/xduoox3ii.h | 1 + firmware/export/erosqlinux_codec.h | 13 ++ firmware/export/rbpaths.h | 6 +- firmware/export/system.h | 2 +- firmware/font.c | 2 +- firmware/target/hosted/aigo/adc-target.h | 0 firmware/target/hosted/aigo/button-erosq.c | 188 ++++++++++++++++++++++++++ firmware/target/hosted/aigo/button-target.h | 45 ++++++ firmware/target/hosted/aigo/debug-erosq.c | 1 + firmware/target/hosted/aigo/erosq.make | 49 +++++++ firmware/target/hosted/aigo/lcd-target.h | 32 +++++ firmware/target/hosted/aigo/power-erosq.c | 74 ++++++++++ firmware/target/hosted/aigo/power-erosq.h | 31 +++++ firmware/target/hosted/aigo/powermgmt-erosq.c | 61 +++++++++ firmware/target/hosted/aigo/system-target.h | 28 ++++ firmware/target/hosted/aigo/usb-erosq.c | 118 ++++++++++++++++ firmware/target/hosted/filesystem-app.c | 6 +- firmware/target/hosted/xduoo/button-target.h | 1 - 27 files changed, 985 insertions(+), 12 deletions(-) create mode 100644 firmware/drivers/audio/erosqlinux_codec.c create mode 100644 firmware/export/config/aigoerosq.h create mode 100644 firmware/export/erosqlinux_codec.h create mode 100644 firmware/target/hosted/aigo/adc-target.h create mode 100644 firmware/target/hosted/aigo/button-erosq.c create mode 100644 firmware/target/hosted/aigo/button-target.h create mode 100644 firmware/target/hosted/aigo/debug-erosq.c create mode 100644 firmware/target/hosted/aigo/erosq.make create mode 100644 firmware/target/hosted/aigo/lcd-target.h create mode 100644 firmware/target/hosted/aigo/power-erosq.c create mode 100644 firmware/target/hosted/aigo/power-erosq.h create mode 100644 firmware/target/hosted/aigo/powermgmt-erosq.c create mode 100644 firmware/target/hosted/aigo/system-target.h create mode 100644 firmware/target/hosted/aigo/usb-erosq.c (limited to 'firmware') diff --git a/firmware/SOURCES b/firmware/SOURCES index cbbebbc66f..8bf3d96bdf 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -115,7 +115,7 @@ target/hosted/sonynwz/nvp-nwz.c target/hosted/sonynwz/nwz-db.c #endif -#if ((defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K)) && !defined(SIMULATOR)) +#if ((defined(HIBY_LINUX) || defined(FIIO_M3K)) && !defined(SIMULATOR)) drivers/lcd-memframe.c target/hosted/alsa-controls.c target/hosted/pcm-alsa.c @@ -155,6 +155,14 @@ target/hosted/fiio/system-fiio.c target/hosted/fiio/usb-fiio.c #endif +#if (defined(EROS_Q)) && !defined(SIMULATOR) +target/hosted/aigo/button-erosq.c +target/hosted/aigo/debug-erosq.c +target/hosted/aigo/power-erosq.c +target/hosted/aigo/powermgmt-erosq.c +target/hosted/aigo/usb-erosq.c +#endif + #if defined(SAMSUNG_YPR0) && !defined(SIMULATOR) drivers/adc-as3514.c #if (CONFIG_RTC == RTC_AS3514) @@ -513,6 +521,8 @@ drivers/audio/rocker_codec.c drivers/audio/xduoolinux_codec.c #elif defined(HAVE_FIIO_LINUX_CODEC) && !defined(SIMULATOR) drivers/audio/fiiolinux_codec.c +#elif defined(HAVE_EROSQ_LINUX_CODEC) && !defined(SIMULATOR) +drivers/audio/erosqlinux_codec.c #elif defined(HAVE_SDL_AUDIO) drivers/audio/sdl.c diff --git a/firmware/asm/SOURCES b/firmware/asm/SOURCES index e93f77c770..2b18ea2026 100644 --- a/firmware/asm/SOURCES +++ b/firmware/asm/SOURCES @@ -15,8 +15,8 @@ mempcpy.c defined(CREATIVE_ZVx) || defined(SANSA_CONNECT) || defined(SANSA_FUZEPLUS) || \ defined(COWON_D2) || defined(MINI2440) || defined(SAMSUNG_YPR0) || \ defined(SAMSUNG_YPR1) || defined(DX50) || defined(DX90) || (defined(MROBE_500) && !defined(LCD_USE_DMA)) || \ - defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX) || defined(AGPTEK_ROCKER) || \ - defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K)) && \ + defined(CREATIVE_ZEN) || defined(CREATIVE_ZENXFI) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || \ + defined(FIIO_M3K)) && \ !defined(SIMULATOR) #if LCD_DEPTH >= 24 lcd-as-memframe-24bit.c diff --git a/firmware/drivers/audio/erosqlinux_codec.c b/firmware/drivers/audio/erosqlinux_codec.c new file mode 100644 index 0000000000..deb3bb4b87 --- /dev/null +++ b/firmware/drivers/audio/erosqlinux_codec.c @@ -0,0 +1,181 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * + * Copyright (c) 2018 Marcin Bukat + * Copyright (c) 2020 Solomon Peachy + * + * 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. + * + ****************************************************************************/ + +//#define LOGF_ENABLE + +#include "config.h" +#include "audio.h" +#include "audiohw.h" +#include "button.h" +#include "system.h" +#include "kernel.h" +#include "panic.h" +#include "sysfs.h" +#include "alsa-controls.h" +#include "pcm-alsa.h" +#include "pcm_sw_volume.h" + +#include "logf.h" + +static int fd_hw; +static int inited = 0; + +static long int vol_l_hw = 255; +static long int vol_r_hw = 255; +static long int last_ps = 0; + +static void hw_open(void) +{ + fd_hw = open("/dev/snd/controlC0", O_RDWR); + if(fd_hw < 0) + panicf("Cannot open '/dev/snd/controlC0'"); +} + +static void hw_close(void) +{ + close(fd_hw); +} + +void audiohw_mute(int mute) +{ + logf("mute %d", mute); + + if(mute) + { + long int ps0 = 0; + alsa_controls_set_ints("Output Port Switch", 1, &ps0); + } + else + { + last_ps = 0; + erosq_get_outputs(); + } +} + +int erosq_get_outputs(void) { + long int ps = 0; // Muted, if nothing is plugged in! + + int status = 0; + + if (!inited) return ps; + + const char * const sysfs_lo_switch = "/sys/class/switch/lineout/state"; + const char * const sysfs_hs_switch = "/sys/class/switch/headset/state"; + + sysfs_get_int(sysfs_lo_switch, &status); + if (status) ps = 1; // lineout + + sysfs_get_int(sysfs_hs_switch, &status); + if (status) ps = 2; // headset + + erosq_set_output(ps); + + return ps; +} + +void erosq_set_output(int ps) +{ + if (!inited) return; + + if (last_ps != ps) + { + logf("set out %d/%d", ps, last_ps); + /* Output port switch */ + last_ps = ps; + alsa_controls_set_ints("Output Port Switch", 1, &last_ps); + audiohw_set_volume(vol_l_hw, vol_r_hw); + } +} + +void audiohw_preinit(void) +{ + logf("hw preinit"); + alsa_controls_init(); + hw_open(); + audiohw_mute(true); /* Start muted to avoid the POP */ + inited = 1; +} + +void audiohw_postinit(void) +{ + logf("hw postinit"); + erosq_set_output(erosq_get_outputs()); /* Unmute */ +} + +void audiohw_close(void) +{ + logf("hw close"); + inited = 0; + hw_close(); + alsa_controls_close(); +} + +void audiohw_set_frequency(int fsel) +{ + (void)fsel; +} + +void audiohw_set_volume(int vol_l, int vol_r) +{ + logf("hw vol %d %d", vol_l, vol_r); + + long l,r; + + vol_l_hw = vol_l; + vol_r_hw = vol_r; + + if (lineout_inserted()) { + l = 0; + r = 0; + } else { + l = vol_l_hw; + r = vol_r_hw; + } + + /* SW volume for <= 1.0 gain, HW at unity, < -740 == MUTE */ + int sw_volume_l = l <= -740 ? PCM_MUTE_LEVEL : MIN(l, 0); + int sw_volume_r = r <= -740 ? PCM_MUTE_LEVEL : MIN(r, 0); + pcm_set_master_volume(sw_volume_l, sw_volume_r); +} + +void audiohw_set_lineout_volume(int vol_l, int vol_r) +{ + long l,r; + + logf("lo vol %d %d", vol_l, vol_r); + + (void)vol_l; + (void)vol_r; + + if (lineout_inserted()) { + l = 0; + r = 0; + } else { + l = vol_l_hw; + r = vol_r_hw; + } + + int sw_volume_l = l <= -740 ? PCM_MUTE_LEVEL : MIN(l, 0); + int sw_volume_r = r <= -740 ? PCM_MUTE_LEVEL : MIN(r, 0); + pcm_set_master_volume(sw_volume_l, sw_volume_r); +} diff --git a/firmware/export/audiohw.h b/firmware/export/audiohw.h index 1ff220e403..8a46cbea78 100644 --- a/firmware/export/audiohw.h +++ b/firmware/export/audiohw.h @@ -226,6 +226,8 @@ struct sound_settings_info #include "xduoolinux_codec.h" #elif defined(HAVE_FIIO_LINUX_CODEC) #include "fiiolinux_codec.h" +#elif defined(HAVE_EROSQ_LINUX_CODEC) +#include "erosqlinux_codec.h" #endif /* convert caps into defines */ diff --git a/firmware/export/config.h b/firmware/export/config.h index a9753e3cf8..7e8d751090 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -162,6 +162,7 @@ #define XDUOO_X3II_PAD 69 #define XDUOO_X20_PAD 70 #define FIIO_M3K_PAD 71 +#define EROSQ_PAD 72 /* CONFIG_REMOTE_KEYPAD */ #define H100_REMOTE 1 @@ -602,6 +603,8 @@ Lyre prototype 1 */ #include "config/xduoox20.h" #elif defined(FIIO_M3K) #include "config/fiiom3k.h" +#elif defined(EROS_Q) +#include "config/aigoerosq.h" #else //#error "unknown hwardware platform!" #endif diff --git a/firmware/export/config/agptekrocker.h b/firmware/export/config/agptekrocker.h index a97522d976..230dc6cac4 100644 --- a/firmware/export/config/agptekrocker.h +++ b/firmware/export/config/agptekrocker.h @@ -17,6 +17,7 @@ #define CONFIG_PLATFORM (PLATFORM_HOSTED) #endif +#define HIBY_LINUX #define HAVE_FPU /* define this if you have a colour LCD */ diff --git a/firmware/export/config/aigoerosq.h b/firmware/export/config/aigoerosq.h new file mode 100644 index 0000000000..9207b5548f --- /dev/null +++ b/firmware/export/config/aigoerosq.h @@ -0,0 +1,132 @@ +/* + * This config file is for the AIGO EROS Q / EROS K (and its clones) + */ + +/* For Rolo and boot loader */ +#define MODEL_NUMBER 113 + +#define MODEL_NAME "AIGO Eros Q" + +/* LCD dimensions */ +#define LCD_WIDTH 320 +#define LCD_HEIGHT 240 +/* sqrt(240^2 + 320^2) / 2.0 = 200 */ +#define LCD_DPI 200 + +#ifndef SIMULATOR +#define CONFIG_PLATFORM (PLATFORM_HOSTED) +#endif + +#define HIBY_LINUX +#define HAVE_FPU + +/* define this if you have a colour LCD */ +#define HAVE_LCD_COLOR + +#define HAVE_LCD_ENABLE + +/* Define this if the LCD can shut down */ +#define HAVE_LCD_SHUTDOWN + +/* define this if you want album art for this target */ +#define HAVE_ALBUMART + +/* define this to enable bitmap scaling */ +#define HAVE_BMP_SCALING + +/* define this to enable JPEG decoding */ +#define HAVE_JPEG + +/* define this if you have access to the quickscreen */ +#define HAVE_QUICKSCREEN + +/* define this if you would like tagcache to build on this target */ +#define HAVE_TAGCACHE + +#define LCD_DEPTH 32 +/* Check that but should not matter */ +#define LCD_PIXELFORMAT XRGB8888 + +#define HAVE_BACKLIGHT +#define HAVE_BACKLIGHT_BRIGHTNESS + +/* Main LCD backlight brightness range and defaults: the backlight driver + * has levels from 0 to 255. But 0 is off so start at 1. + */ +#define MIN_BRIGHTNESS_SETTING 1 +#define MAX_BRIGHTNESS_SETTING 255 +#define BRIGHTNESS_STEP 5 +#define DEFAULT_BRIGHTNESS_SETTING 70 + +/* Which backlight fading type? */ +#define CONFIG_BACKLIGHT_FADING BACKLIGHT_FADING_SW_SETTING + +/* define this if you have a real-time clock */ +#define CONFIG_RTC APPLICATION + +/* The number of bytes reserved for loadable codecs */ +#define CODEC_SIZE 0x80000 + +/* The number of bytes reserved for loadable plugins */ +#define PLUGIN_BUFFER_SIZE 0x100000 + +#define HAVE_HEADPHONE_DETECTION +#define HAVE_LINEOUT_DETECTION + +/* KeyPad configuration for plugins */ +#define CONFIG_KEYPAD EROSQ_PAD + +/* define this if the target has volume keys which can be used in the lists */ +#define HAVE_VOLUME_IN_LIST + +#ifndef SIMULATOR +/* We have usb power and can detect usb but it is handled by Linux */ +#define HAVE_USB_POWER + +#endif + +#define CONFIG_BATTERY_MEASURE VOLTAGE_MEASURE + +/* Linux controlls charging, we can monitor */ +#define CONFIG_CHARGING CHARGING_MONITOR + +/* define this if the hardware can be powered off while charging */ +#define HAVE_POWEROFF_WHILE_CHARGING + +/* same dimensions as gigabeats */ +#define CONFIG_LCD LCD_INGENIC_LINUX + +/* Define this if you have a software controlled poweroff */ +#define HAVE_SW_POWEROFF + +/* Define this to the CPU frequency */ +#define CPU_FREQ 108000000 + +/* No special storage */ +#define CONFIG_STORAGE STORAGE_HOSTFS +#define HAVE_STORAGE_FLUSH + +/* Battery */ +#define BATTERY_TYPES_COUNT 1 + +/* Audio codec */ +#define HAVE_EROSQ_LINUX_CODEC +/* Rockbox has to handle the volume level */ +#define HAVE_SW_VOLUME_CONTROL + +/* We don't have hardware controls */ +#define HAVE_SW_TONE_CONTROLS + +/* HW codec is flexible */ +#define HW_SAMPR_CAPS SAMPR_CAP_ALL_192 + +/* Battery */ +#define BATTERY_CAPACITY_DEFAULT 2000 /* default battery capacity */ +#define BATTERY_CAPACITY_MIN 2000 /* min. capacity selectable */ +#define BATTERY_CAPACITY_MAX 2000 /* max. capacity selectable */ +#define BATTERY_CAPACITY_INC 0 /* capacity increment */ + +/* ROLO */ +#define BOOTFILE_EXT "erosq" +#define BOOTFILE "rockbox." BOOTFILE_EXT +#define BOOTDIR "/.rockbox" diff --git a/firmware/export/config/fiiom3k.h b/firmware/export/config/fiiom3k.h index 5b68f3738e..88652b633f 100644 --- a/firmware/export/config/fiiom3k.h +++ b/firmware/export/config/fiiom3k.h @@ -17,6 +17,8 @@ #define CONFIG_PLATFORM (PLATFORM_HOSTED) #endif +#define HAVE_FPU + #define HW_SAMPR_CAPS (SAMPR_CAP_44 | SAMPR_CAP_48 | SAMPR_CAP_88 | SAMPR_CAP_96 | SAMPR_CAP_176 | SAMPR_CAP_192) /* define this if you have a bitmap LCD display */ diff --git a/firmware/export/config/xduoox20.h b/firmware/export/config/xduoox20.h index a8d2175719..70e6131cb7 100644 --- a/firmware/export/config/xduoox20.h +++ b/firmware/export/config/xduoox20.h @@ -17,6 +17,8 @@ #define CONFIG_PLATFORM (PLATFORM_HOSTED) #endif +#define HIBY_LINUX + #define HAVE_FPU /* define this if you have a colour LCD */ diff --git a/firmware/export/config/xduoox3ii.h b/firmware/export/config/xduoox3ii.h index 143d4442fd..d19165114a 100644 --- a/firmware/export/config/xduoox3ii.h +++ b/firmware/export/config/xduoox3ii.h @@ -17,6 +17,7 @@ #define CONFIG_PLATFORM (PLATFORM_HOSTED) #endif +#define HIBY_LINUX #define HAVE_FPU /* define this if you have a colour LCD */ diff --git a/firmware/export/erosqlinux_codec.h b/firmware/export/erosqlinux_codec.h new file mode 100644 index 0000000000..8a3afbfe3c --- /dev/null +++ b/firmware/export/erosqlinux_codec.h @@ -0,0 +1,13 @@ +#ifndef __EROSQLINUX_CODEC__ +#define __EROSQLINUX_CODEC__ + +#define AUDIOHW_CAPS (LINEOUT_CAP) + +AUDIOHW_SETTING(VOLUME, "dB", 0, 1, -74, 6, -25) + + +void audiohw_mute(int mute); +void erosq_set_output(int ps); +int erosq_get_outputs(void); + +#endif diff --git a/firmware/export/rbpaths.h b/firmware/export/rbpaths.h index 6b686eec0e..215b4c0c4b 100644 --- a/firmware/export/rbpaths.h +++ b/firmware/export/rbpaths.h @@ -42,7 +42,7 @@ #if !defined(APPLICATION) || defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \ defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || \ - defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K) + defined(HIBY_LINUX) || defined(FIIO_M3K) #if defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) #define HOME_DIR "/mnt/media0" @@ -51,7 +51,7 @@ #elif defined(DX50) || defined(DX90) /* Where to put save files like recordings, playlists, screen dumps ...*/ #define HOME_DIR "/mnt/sdcard" -#elif defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) +#elif defined(HIBY_LINUX) #define HOME_DIR "/mnt/sd_0" #elif defined(FIIO_M3K) #define HOME_DIR "/mnt" @@ -92,7 +92,7 @@ #define VIEWERS_DIR PLUGIN_DIR "/viewers" #if defined(APPLICATION) && !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || \ - defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)) + defined(DX50) || defined(DX90) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX)) #define PLUGIN_DATA_DIR ROCKBOX_DIR "/rocks.data" #define PLUGIN_GAMES_DATA_DIR PLUGIN_DATA_DIR #define PLUGIN_APPS_DATA_DIR PLUGIN_DATA_DIR diff --git a/firmware/export/system.h b/firmware/export/system.h index cfec235bc4..1885acfffd 100644 --- a/firmware/export/system.h +++ b/firmware/export/system.h @@ -347,7 +347,7 @@ static inline void cpu_boost_unlock(void) #ifndef SIMULATOR bool dbg_ports(void); #endif -#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SONY_NWZ_LINUX) || defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20) +#if (CONFIG_PLATFORM & PLATFORM_NATIVE) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || defined(FIIO_M3K) bool dbg_hw_info(void); #endif diff --git a/firmware/font.c b/firmware/font.c index 3208125a6a..b2ac1a3c3c 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -85,7 +85,7 @@ /* compiled-in font */ extern struct font sysfont; -#if !defined(BOOTLOADER) || defined(SONY_NWZ_LINUX) +#if !defined(BOOTLOADER) || defined(SONY_NWZ_LINUX) || defined(HIBY_LINUX) || defined(FIIO_M3K) struct buflib_alloc_data { struct font font; /* must be the first member! */ diff --git a/firmware/target/hosted/aigo/adc-target.h b/firmware/target/hosted/aigo/adc-target.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/firmware/target/hosted/aigo/button-erosq.c b/firmware/target/hosted/aigo/button-erosq.c new file mode 100644 index 0000000000..2735c48c71 --- /dev/null +++ b/firmware/target/hosted/aigo/button-erosq.c @@ -0,0 +1,188 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 Marcin Bukat + * Copyright (C) 2020 Solomon Peachy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +//#include +#include +#include +#include +#include +#include +#include +#include + +#include "sysfs.h" +#include "button.h" +#include "button-target.h" +#include "panic.h" + +#include "kernel.h" +#include "backlight.h" +#include "backlight-target.h" +#include "erosqlinux_codec.h" + +#define NR_POLL_DESC 3 +static struct pollfd poll_fds[NR_POLL_DESC]; + +static int button_map(int keycode) +{ + switch(keycode) + { + case KEY_POWER: + return BUTTON_POWER; + + case KEY_MENU: + return BUTTON_MENU; + + case KEY_BACK: + return BUTTON_BACK; + + case KEY_NEXTSONG: + return BUTTON_PREV; + + case KEY_PREVIOUSSONG: + return BUTTON_NEXT; // Yes, backwards! + + case KEY_PLAYPAUSE: + return BUTTON_PLAY; + + case KEY_LEFT: + return BUTTON_SCROLL_BACK; + + case KEY_RIGHT: + return BUTTON_SCROLL_FWD; + + case KEY_VOLUMEUP: + return BUTTON_VOL_UP; + + case KEY_VOLUMEDOWN: + return BUTTON_VOL_DOWN; + + default: + return 0; + } +} + +void button_init_device(void) +{ + const char * const input_devs[] = { + "/dev/input/event0", // Rotary encoder + "/dev/input/event1" // Keys + }; + + for(int i = 0; i < NR_POLL_DESC; i++) + { + int fd = open(input_devs[i], O_RDWR | O_CLOEXEC); + + if(fd < 0) + { + panicf("Cannot open input device: %s\n", input_devs[i]); + } + + poll_fds[i].fd = fd; + poll_fds[i].events = POLLIN; + poll_fds[i].revents = 0; + } +} + +int button_read_device(void) +{ + static int button_bitmap = 0; + struct input_event event; + + // FIXME TODO: Make this work via HAVE_SCROLL_WHEEL instead + + /* Wheel gives us press+release back to back, clear them after time elapses */ + static long last_tick = 0; + if (button_bitmap & (BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD) && + current_tick - last_tick >= 2) + { + button_bitmap &= ~(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD); + } + + /* check if there are any events pending and process them */ + while(poll(poll_fds, NR_POLL_DESC, 0)) + { + for(int i = 0; i < NR_POLL_DESC; i++) + { + /* read only if non-blocking */ + if(poll_fds[i].revents & POLLIN) + { + int size = read(poll_fds[i].fd, &event, sizeof(event)); + if(size == (int)sizeof(event)) + { + int keycode = event.code; + /* event.value == 1 means press + * event.value == 0 means release + */ + bool press = event.value ? true : false; + + /* map linux event code to rockbox button bitmap */ + if(press) + { + int bmap = button_map(keycode); + if (bmap & (BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD)) + last_tick = current_tick; + button_bitmap |= bmap; + } + else + { + /* Wheel gives us press+release back to back; ignore the release */ + int bmap = button_map(keycode) & ~(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD); + button_bitmap &= ~bmap; + } + } + } + } + } + + return button_bitmap; +} + +bool headphones_inserted(void) +{ +#ifdef BOOTLOADER + int ps = 0; +#else + int ps = erosq_get_outputs(); +#endif + + return (ps == 2); +} + +bool lineout_inserted(void) +{ +#ifdef BOOTLOADER + int ps = 0; +#else + int ps = erosq_get_outputs(); +#endif + + return (ps == 1); +} + +void button_close_device(void) +{ + /* close descriptors */ + for(int i = 0; i < NR_POLL_DESC; i++) + { + close(poll_fds[i].fd); + } +} diff --git a/firmware/target/hosted/aigo/button-target.h b/firmware/target/hosted/aigo/button-target.h new file mode 100644 index 0000000000..f59f491d2f --- /dev/null +++ b/firmware/target/hosted/aigo/button-target.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2020 Solomon Peachy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _BUTTON_TARGET_H_ +#define _BUTTON_TARGET_H_ + +/* Main unit's buttons */ +#define BUTTON_POWER 0x00000001 +#define BUTTON_MENU 0x00000002 +#define BUTTON_BACK 0x00000004 +#define BUTTON_PLAY 0x00000008 +#define BUTTON_NEXT 0x00000010 +#define BUTTON_PREV 0x00000020 +#define BUTTON_VOL_UP 0x00000040 +#define BUTTON_VOL_DOWN 0x00000080 +#define BUTTON_SCROLL_BACK 0x00000100 +#define BUTTON_SCROLL_FWD 0x00000200 + +#define BUTTON_MAIN (BUTTON_POWER | BUTTON_MENU | BUTTON_BACK | BUTTON_PREV | \ + BUTTON_NEXT | BUTTON_PLAY | BUTTON_VOL_UP | BUTTON_VOL_DOWN | BUTTON_SCROLL_BACK | BUTTON_SCROLL_FWD) + +#define BUTTON_LEFT BUTTON_PREV +#define BUTTON_RIGHT BUTTON_NEXT + +/* Software power-off */ +#define POWEROFF_BUTTON BUTTON_POWER +#define POWEROFF_COUNT 25 + +#endif /* _BUTTON_TARGET_H_ */ diff --git a/firmware/target/hosted/aigo/debug-erosq.c b/firmware/target/hosted/aigo/debug-erosq.c new file mode 100644 index 0000000000..9812b8f8b9 --- /dev/null +++ b/firmware/target/hosted/aigo/debug-erosq.c @@ -0,0 +1 @@ +#include "../agptek/debug-agptek.c" diff --git a/firmware/target/hosted/aigo/erosq.make b/firmware/target/hosted/aigo/erosq.make new file mode 100644 index 0000000000..d159db77f3 --- /dev/null +++ b/firmware/target/hosted/aigo/erosq.make @@ -0,0 +1,49 @@ +# __________ __ ___. +# Open \______ \ ____ ____ | | _\_ |__ _______ ___ +# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / +# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < +# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ +# \/ \/ \/ \/ \/ +# $Id$ +# + +INCLUDES += -I$(FIRMDIR)/include -I$(FIRMDIR)/export $(TARGET_INC) -I$(BUILDDIR) -I$(APPSDIR) + +SIMFLAGS += $(INCLUDES) $(DEFINES) -DHAVE_CONFIG_H $(GCCOPTS) + +# bootloader build is sligtly different +ifneq (,$(findstring bootloader,$(APPSDIR))) + +SRC += $(call preprocess, $(APPSDIR)/SOURCES) +CLEANOBJS += $(BUILDDIR)/bootloader.* + +endif #bootloader + +.SECONDEXPANSION: # $$(OBJ) is not populated until after this + +ifneq (,$(findstring bootloader,$(APPSDIR))) +# bootloader build + +$(BUILDDIR)/bootloader.elf : $$(OBJ) $(FIRMLIB) $(CORE_LIBS) + $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ + -L$(BUILDDIR)/firmware -lfirmware \ + -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \ + $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,--gc-sections -Wl,-Map,$(BUILDDIR)/bootloader.map + +$(BUILDDIR)/$(BINARY): $(BUILDDIR)/bootloader.elf + $(call PRINTS,OC $(@F))$(call objcopy,$^,$@) + +else +# rockbox app build + +$(BUILDDIR)/rockbox.elf : $$(OBJ) $(FIRMLIB) $(VOICESPEEXLIB) $(CORE_LIBS) + $(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -o $@ $(OBJ) \ + -L$(BUILDDIR)/firmware -lfirmware \ + -L$(RBCODEC_BLD)/codecs $(call a2lnk, $(VOICESPEEXLIB)) \ + -L$(BUILDDIR)/lib $(call a2lnk,$(CORE_LIBS)) \ + $(LDOPTS) $(GLOBAL_LDOPTS) -Wl,-Map,$(BUILDDIR)/rockbox.map + +$(BUILDDIR)/$(BINARY): $(BUILDDIR)/rockbox.elf + $(call PRINTS,OC $(@F))$(call objcopy,$^,$@) + +endif diff --git a/firmware/target/hosted/aigo/lcd-target.h b/firmware/target/hosted/aigo/lcd-target.h new file mode 100644 index 0000000000..808df3c60a --- /dev/null +++ b/firmware/target/hosted/aigo/lcd-target.h @@ -0,0 +1,32 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2016 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef __LCD_TARGET_H__ +#define __LCD_TARGET_H__ + +/* needs special ioctl() to redraw updated framebuffer content */ +#define LCD_OPTIMIZED_UPDATE +#define LCD_OPTIMIZED_UPDATE_RECT + +extern fb_data *framebuffer; /* see lcd-erosq.c */ +#define LCD_FRAMEBUF_ADDR(col, row) (framebuffer + (row)*LCD_WIDTH + (col)) + +extern void lcd_set_active(bool active); +#endif /* __LCD_TARGET_H__ */ diff --git a/firmware/target/hosted/aigo/power-erosq.c b/firmware/target/hosted/aigo/power-erosq.c new file mode 100644 index 0000000000..0a4f820337 --- /dev/null +++ b/firmware/target/hosted/aigo/power-erosq.c @@ -0,0 +1,74 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include +#include +#include +#include +#include + +#include "system.h" +#include "power-erosq.h" +#include "power.h" +#include "panic.h" +#include "sysfs.h" + +const char * const sysfs_bat_voltage = + "/sys/class/power_supply/battery/voltage_now"; + +const char * const sysfs_bat_capacity = + "/sys/class/power_supply/battery/capacity"; + +const char * const sysfs_bat_status = + "/sys/class/power_supply/battery/status"; + +const char * const sysfs_pow_supply = + "/sys/class/power_supply/usb/present"; + +unsigned int erosq_power_input_status(void) +{ + int present = 0; + sysfs_get_int(sysfs_pow_supply, &present); + + return present ? POWER_INPUT_USB_CHARGER : POWER_INPUT_NONE; +} + +bool erosq_power_charging_status(void) +{ + char buf[12] = {0}; + sysfs_get_string(sysfs_bat_status, buf, sizeof(buf)); + + return (strncmp(buf, "Charging", 8) == 0); +} + +unsigned int erosq_power_get_battery_voltage(void) +{ + int battery_voltage; + sysfs_get_int(sysfs_bat_voltage, &battery_voltage); + + return battery_voltage/1000; +} + +unsigned int erosq_power_get_battery_capacity(void) +{ + int battery_capacity; + sysfs_get_int(sysfs_bat_capacity, &battery_capacity); + + return battery_capacity; +} diff --git a/firmware/target/hosted/aigo/power-erosq.h b/firmware/target/hosted/aigo/power-erosq.h new file mode 100644 index 0000000000..d06b956924 --- /dev/null +++ b/firmware/target/hosted/aigo/power-erosq.h @@ -0,0 +1,31 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _POWER_XDUOO_H_ +#define _POWER_XDUOO_H_ + +#include +#include "config.h" + +unsigned int erosq_power_input_status(void); +bool erosq_power_charging_status(void); +unsigned int erosq_power_get_battery_voltage(void); +unsigned int erosq_power_get_battery_capacity(void); +#endif /* _POWER_XDUOO_H_ */ + diff --git a/firmware/target/hosted/aigo/powermgmt-erosq.c b/firmware/target/hosted/aigo/powermgmt-erosq.c new file mode 100644 index 0000000000..14286de3fd --- /dev/null +++ b/firmware/target/hosted/aigo/powermgmt-erosq.c @@ -0,0 +1,61 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "powermgmt.h" +#include "power.h" +#include "power-erosq.h" + +const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = +{ + 3470 +}; + +/* the OF shuts down at this voltage */ +const unsigned short battery_level_shutoff[BATTERY_TYPES_COUNT] = +{ + 3400 +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging disabled */ +const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = +{ + { 3400, 3639, 3697, 3723, 3757, 3786, 3836, 3906, 3980, 4050, 4159 } +}; + +/* voltages (millivolt) of 0%, 10%, ... 100% when charging enabled */ +const unsigned short const percent_to_volt_charge[11] = +{ + 3485, 3780, 3836, 3857, 3890, 3930, 3986, 4062, 4158, 4185, 4196 +}; + +unsigned int power_input_status(void) +{ + /* POWER_INPUT_USB_CHARGER, POWER_INPUT_NONE */ + return erosq_power_input_status(); +} + +int _battery_voltage(void) +{ + return erosq_power_get_battery_voltage(); +} + +bool charging_state(void) +{ + return erosq_power_charging_status(); +} diff --git a/firmware/target/hosted/aigo/system-target.h b/firmware/target/hosted/aigo/system-target.h new file mode 100644 index 0000000000..830f19fde4 --- /dev/null +++ b/firmware/target/hosted/aigo/system-target.h @@ -0,0 +1,28 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2017 Marcin Bukat + * Copyright (C) 2016 Amaury Pouly + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef __SYSTEM_TARGET_H__ +#define __SYSTEM_TARGET_H__ + +#include "kernel-unix.h" +#include "system-hosted.h" + +#define NEED_GENERIC_BYTESWAPS +#endif /* __SYSTEM_TARGET_H__ */ diff --git a/firmware/target/hosted/aigo/usb-erosq.c b/firmware/target/hosted/aigo/usb-erosq.c new file mode 100644 index 0000000000..2a3acf4d62 --- /dev/null +++ b/firmware/target/hosted/aigo/usb-erosq.c @@ -0,0 +1,118 @@ +/*************************************************************************** + * __________ __ ___ + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2018 by Marcin Bukat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include "config.h" +#include "disk.h" +#include "usb.h" +#include "sysfs.h" +#include "power.h" +#include "power-erosq.h" + +static bool adb_mode = false; + +/* TODO: implement usb detection properly */ +int usb_detect(void) +{ + return power_input_status() == POWER_INPUT_USB_CHARGER ? USB_INSERTED : USB_EXTRACTED; +} + +void usb_enable(bool on) +{ + /* Ignore usb enable/disable when ADB is enabled so we can fireup adb shell + * without entering ums mode + */ + if (!adb_mode) + { + sysfs_set_int("/sys/class/android_usb/android0/enable", on ? 1 : 0); + } +} + +/* This is called by usb thread after usb extract in order to return + * regular FS access + * + * returns the # of successful mounts +*/ +int disk_mount_all(void) +{ + const char *dev[] = {"/dev/mmcblk0p1", "/dev/mmcblk0"}; + const char *fs[] = {"vfat", "exfat"}; + + sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", ""); + + for (int i=0; i<2; i++) + { + for (int j=0; j<2; j++) + { + if (mount(dev[i], "/mnt/sd_0", fs[j], 0, NULL) == 0) + { + return 1; + } + } + } + + return 0; +} + +/* This is called by usb thread after all threads ACKs usb inserted message + * + * returns the # of successful unmounts + */ +int disk_unmount_all(void) +{ + if (umount("/mnt/sd_0") == 0) + { + sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/lun/file", "/dev/mmcblk0"); + return 1; + } + + return 0; +} + +void usb_init_device(void) +{ + char functions[32] = {0}; + + /* Check if ADB was activated in bootloader */ + sysfs_get_string("/sys/class/android_usb/android0/functions", functions, sizeof(functions)); + adb_mode = (strstr(functions, "adb") == NULL) ? false : true; + + usb_enable(false); + + if (adb_mode) + { + sysfs_set_string("/sys/class/android_usb/android0/functions", "mass_storage,adb"); + sysfs_set_string("/sys/class/android_usb/android0/idVendor", "18D1"); + sysfs_set_string("/sys/class/android_usb/android0/idProduct", "D002"); + } + else + { + sysfs_set_string("/sys/class/android_usb/android0/functions", "mass_storage"); + sysfs_set_string("/sys/class/android_usb/android0/idVendor", "C502"); + sysfs_set_string("/sys/class/android_usb/android0/idProduct", "0023"); + } + + sysfs_set_string("/sys/class/android_usb/android0/iManufacturer", "Rockbox.org"); + sysfs_set_string("/sys/class/android_usb/android0/iProduct", "Rockbox media player"); + sysfs_set_string("/sys/class/android_usb/android0/iSerial", "0123456789ABCDEF"); + sysfs_set_string("/sys/class/android_usb/android0/f_mass_storage/inquiry_string", "ErosQ 0100"); +} diff --git a/firmware/target/hosted/filesystem-app.c b/firmware/target/hosted/filesystem-app.c index 4e2fa8db7b..24c5a7e062 100644 --- a/firmware/target/hosted/filesystem-app.c +++ b/firmware/target/hosted/filesystem-app.c @@ -37,7 +37,7 @@ #include "logf.h" #if !(defined(BOOTLOADER) || defined(CHECKWPS) || defined(SIMULATOR)) -#if (defined(AGPTEK_ROCKER) || defined(XDUOO_X3II) || defined(XDUOO_X20)) +#if defined(HIBY_LINUX) #define PIVOT_ROOT "/mnt/sd_0" #elif defined(FIIO_M3K) #define PIVOT_ROOT "/mnt" // XXX check this! @@ -56,8 +56,8 @@ static const char rbhome[] = HOME_DIR; #endif #if !(defined(SAMSUNG_YPR0) || defined(SAMSUNG_YPR1) || defined(DX50) || \ - defined(SONY_NWZ_LINUX) || defined(DX90) || defined(AGPTEK_ROCKER) || \ - defined(XDUOO_X3II) || defined(XDUOO_X20) || defined(FIIO_M3K) || defined(FIIO_M3K_PRO)) && \ + defined(SONY_NWZ_LINUX) || defined(DX90) || defined(HIBY_LINUX) || \ + defined(FIIO_M3K)) && \ !defined(__PCTOOL__) /* Special dirs are user-accessible (and user-writable) dirs which take priority * over the ones where Rockbox is installed to. Classic example would be diff --git a/firmware/target/hosted/xduoo/button-target.h b/firmware/target/hosted/xduoo/button-target.h index d41b33894a..3240d3df8e 100644 --- a/firmware/target/hosted/xduoo/button-target.h +++ b/firmware/target/hosted/xduoo/button-target.h @@ -41,4 +41,3 @@ #define POWEROFF_COUNT 25 #endif /* _BUTTON_TARGET_H_ */ - -- cgit v1.2.3