diff options
Diffstat (limited to 'rbutil/ibassoboot/jni/ibassodualboot.c')
-rw-r--r-- | rbutil/ibassoboot/jni/ibassodualboot.c | 771 |
1 files changed, 0 insertions, 771 deletions
diff --git a/rbutil/ibassoboot/jni/ibassodualboot.c b/rbutil/ibassoboot/jni/ibassodualboot.c deleted file mode 100644 index 0458ff1b71..0000000000 --- a/rbutil/ibassoboot/jni/ibassodualboot.c +++ /dev/null @@ -1,771 +0,0 @@ -/*************************************************************************** - * __________ __ ___ - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * - * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50 - * Copyright (C) 2014 by Mario Basister: iBasso DX90 port - * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features - * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - - -#include <dirent.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdbool.h> -#include <stdlib.h> -#include <unistd.h> -#include <linux/fb.h> -#include <linux/input.h> -#include <sys/mman.h> -#include <sys/poll.h> -#include <sys/reboot.h> -#include <sys/socket.h> -#include <sys/un.h> -#include <sys/wait.h> - -#include "qdbmp.h" - - -/*- Android logcat ------------------------------------------------------------------------------*/ - - -#ifdef DEBUG -#include <android/log.h> - - -static const char log_tag[] = "Rockbox Boot"; - - -void debugf(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, fmt, ap); - va_end(ap); -} - - -void ldebugf(const char* file, int line, const char *fmt, ...) -{ - va_list ap; - /* 13: 5 literal chars and 8 chars for the line number. */ - char buf[strlen(file) + strlen(fmt) + 13]; - snprintf(buf, sizeof(buf), "%s (%d): %s", file, line, fmt); - va_start(ap, fmt); - __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, buf, ap); - va_end(ap); -} - - -void debug_trace(const char* function) -{ - static const char trace_tag[] = "TRACE: "; - char msg[strlen(trace_tag) + strlen(function) + 1]; - snprintf(msg, sizeof(msg), "%s%s", trace_tag, function); - __android_log_write(ANDROID_LOG_DEBUG, log_tag, msg); -} - - -#define DEBUGF debugf -#define TRACE debug_trace(__func__) -#else -#define DEBUGF(...) -#define TRACE -#endif /* DEBUG */ - - -/*- Vold monitor --------------------------------------------------------------------------------*/ - - -/* - Without this socket iBasso Vold will not start. - iBasso Vold uses this to send status messages about storage devices. -*/ -static const char VOLD_MONITOR_SOCKET_NAME[] = "UNIX_domain"; -static int _vold_monitor_socket_fd = -1; - - -static void vold_monitor_open_socket(void) -{ - TRACE; - - unlink(VOLD_MONITOR_SOCKET_NAME); - - _vold_monitor_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0); - - if(_vold_monitor_socket_fd < 0) - { - _vold_monitor_socket_fd = -1; - return; - } - - struct sockaddr_un addr; - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, VOLD_MONITOR_SOCKET_NAME, sizeof(addr.sun_path) - 1); - - if(bind(_vold_monitor_socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0) - { - close(_vold_monitor_socket_fd); - unlink(VOLD_MONITOR_SOCKET_NAME); - _vold_monitor_socket_fd = -1; - return; - } - - if(listen(_vold_monitor_socket_fd, 1) < 0) - { - close(_vold_monitor_socket_fd); - unlink(VOLD_MONITOR_SOCKET_NAME); - _vold_monitor_socket_fd = -1; - return; - } -} - - -/* - bionic does not have pthread_cancel. - 0: Vold monitor thread stopped/ending. - 1: Vold monitor thread started/running. -*/ -static volatile sig_atomic_t _vold_monitor_active = 0; - - -/* true: sdcard not mounted. */ -static bool _sdcard_not_mounted = true; - - -/* Mutex for sdcard mounted flag. */ -static pthread_mutex_t _sdcard_mount_mtx = PTHREAD_MUTEX_INITIALIZER; - - -/* Signal condition for sdcard mounted flag. */ -static pthread_cond_t _sdcard_mount_cond = PTHREAD_COND_INITIALIZER; - - -static void* vold_monitor_run(void* nothing) -{ - _vold_monitor_active = 1; - - (void) nothing; - - DEBUGF("DEBUG %s: Thread start.", __func__); - - vold_monitor_open_socket(); - if(_vold_monitor_socket_fd < 0) - { - DEBUGF("ERROR %s: Thread end: No socket.", __func__); - - _vold_monitor_active = 0; - return 0; - } - - struct pollfd fds[1]; - fds[0].fd = _vold_monitor_socket_fd; - fds[0].events = POLLIN; - - while(_vold_monitor_active == 1) - { - poll(fds, 1, 10); - if(! (fds[0].revents & POLLIN)) - { - continue; - } - - int socket_fd = accept(_vold_monitor_socket_fd, NULL, NULL); - - if(socket_fd < 0) - { - DEBUGF("ERROR %s: accept failed.", __func__); - - continue; - } - - while(true) - { - char msg[1024]; - memset(msg, 0, sizeof(msg)); - int length = read(socket_fd, msg, sizeof(msg)); - - if(length <= 0) - { - close(socket_fd); - break; - } - - DEBUGF("DEBUG %s: msg: %s", __func__, msg); - - if(strcmp(msg, "Volume flash /mnt/sdcard state changed from 3 (Checking) to 4 (Mounted)") == 0) - { - pthread_mutex_lock(&_sdcard_mount_mtx); - _sdcard_not_mounted = false; - pthread_cond_signal(&_sdcard_mount_cond); - pthread_mutex_unlock(&_sdcard_mount_mtx); - } - } - } - - close(_vold_monitor_socket_fd); - unlink(VOLD_MONITOR_SOCKET_NAME); - _vold_monitor_socket_fd = -1; - - DEBUGF("DEBUG %s: Thread end.", __func__); - - _vold_monitor_active = 0; - return 0; -} - - -/* Vold monitor thread. */ -static pthread_t _vold_monitor_thread; - - -static void vold_monitor_start(void) -{ - TRACE; - - if(_vold_monitor_active == 0) - { - pthread_create(&_vold_monitor_thread, NULL, vold_monitor_run, NULL); - } -} - - -static void vold_monitor_stop(void) -{ - TRACE; - - if(_vold_monitor_active == 1) - { - _vold_monitor_active = 0; - int ret = pthread_join(_vold_monitor_thread, NULL); - DEBUGF("DEBUG %s: Thread joined: ret: %d.", __func__, ret); - } -} - - -/*- Input handler -------------------------------------------------------------------------------*/ - - -/* Input devices monitored with poll API. */ -static struct pollfd* _fds = NULL; - - -/* Number of input devices monitored with poll API. */ -static nfds_t _nfds = 0; - - -/* The names of the devices in _fds. */ -static char** _device_names = NULL; - - -/* Open device device_name and add it to the list of polled devices. */ -static void open_device(const char* device_name) -{ - int fd = open(device_name, O_RDONLY); - if(fd == -1) - { - DEBUGF("ERROR %s: open failed on %s.", __func__, device_name); - exit(-1); - } - - struct pollfd* new_fds = realloc(_fds, sizeof(struct pollfd) * (_nfds + 1)); - if(new_fds == NULL) - { - DEBUGF("ERROR %s: realloc for _fds failed.", __func__); - exit(-1); - } - - _fds = new_fds; - _fds[_nfds].fd = fd; - _fds[_nfds].events = POLLIN; - - char** new_device_names = realloc(_device_names, sizeof(char*) * (_nfds + 1)); - if(new_device_names == NULL) - { - DEBUGF("ERROR %s: realloc for _device_names failed.", __func__); - exit(-1); - } - - _device_names = new_device_names; - _device_names[_nfds] = strdup(device_name); - if(_device_names[_nfds] == NULL) - { - DEBUGF("ERROR %s: strdup failed.", __func__); - exit(-1); - } - - ++_nfds; - - DEBUGF("DEBUG %s: Opened device %s.", __func__, device_name); -} - - -static void button_init_device(void) -{ - TRACE; - - if((_fds != NULL) || (_nfds != 0) || (_device_names != NULL)) - { - DEBUGF("ERROR %s: Allready initialized.", __func__); - return; - } - - /* The input device directory. */ - static const char device_path[] = "/dev/input"; - - /* Path delimeter. */ - static const char delimeter[] = "/"; - - /* Open all devices in device_path. */ - DIR* dir = opendir(device_path); - if(dir == NULL) - { - DEBUGF("ERROR %s: opendir failed: errno: %d.", __func__, errno); - exit(errno); - } - - char device_name[PATH_MAX]; - strcpy(device_name, device_path); - strcat(device_name, delimeter); - char* device_name_idx = device_name + strlen(device_name); - - struct dirent* dir_entry; - while((dir_entry = readdir(dir))) - { - if( ((dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '\0')) - || ((dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '.') && (dir_entry->d_name[2] == '\0'))) - { - continue; - } - - strcpy(device_name_idx, dir_entry->d_name); - - /* Open and add device to _fds. */ - open_device(device_name); - } - - closedir(dir); - - /* Sanity check. */ - if(_nfds < 2) - { - DEBUGF("ERROR %s: No input devices.", __func__); - exit(-1); - } -} - - -#define EVENT_TYPE_BUTTON 1 - - -#define EVENT_CODE_BUTTON_PWR_LONG 117 -#define EVENT_CODE_BUTTON_REV 160 -#define EVENT_CODE_BUTTON_NEXT 162 - - -#define EVENT_TYPE_TOUCHSCREEN 3 - - -#define EVENT_CODE_TOUCHSCREEN_X 53 - - -enum user_choice -{ - CHOICE_NONE = -1, - CHOICE_MANGO, - CHOICE_ROCKBOX, - CHOICE_POWEROFF -}; - - -static int get_user_choice(void) -{ - TRACE; - - button_init_device(); - - enum user_choice choice = CHOICE_NONE; - - while(choice == CHOICE_NONE) - { - /* Poll all input devices. */ - poll(_fds, _nfds, 0); - - nfds_t fds_idx = 0; - for( ; fds_idx < _nfds; ++fds_idx) - { - if(! (_fds[fds_idx].revents & POLLIN)) - { - continue; - } - - struct input_event event; - if(read(_fds[fds_idx].fd, &event, sizeof(event)) < (int) sizeof(event)) - { - DEBUGF("ERROR %s: Read of input devices failed.", __func__); - continue; - } - - DEBUGF("DEBUG %s: device: %s, event.type: %d, event.code: %d, event.value: %d", __func__, _device_names[fds_idx], event.type, event.code, event.value); - - if(event.type == EVENT_TYPE_BUTTON) - { - switch(event.code) - { - case EVENT_CODE_BUTTON_REV: - { - choice = CHOICE_MANGO; - break; - } - - case EVENT_CODE_BUTTON_NEXT: - { - choice = CHOICE_ROCKBOX; - break; - } - - case EVENT_CODE_BUTTON_PWR_LONG: - { - choice = CHOICE_POWEROFF; - break; - } - } - } - else if((event.type == EVENT_TYPE_TOUCHSCREEN) && (event.code == EVENT_CODE_TOUCHSCREEN_X)) - { - if(event.value < 160) - { - choice = CHOICE_MANGO; - } - else - { - choice = CHOICE_ROCKBOX; - } - } - } - } - - if(_fds) - { - nfds_t fds_idx = 0; - for( ; fds_idx < _nfds; ++fds_idx) - { - close(_fds[fds_idx].fd); - } - free(_fds); - _fds = NULL; - } - - if(_device_names) - { - nfds_t fds_idx = 0; - for( ; fds_idx < _nfds; ++fds_idx) - { - free(_device_names[fds_idx]); - } - free(_device_names); - _device_names = NULL; - } - - _nfds = 0; - - return choice; -} - - -/* - Changing bit, when hold switch is toggled. - Bit is off when hold switch is engaged. -*/ -#define HOLD_SWITCH_BIT 16 - - -static bool check_for_hold(void) -{ - TRACE; - - char hold_state; - - FILE* f = fopen("/sys/class/axppower/holdkey", "r"); - fscanf(f, "%c", &hold_state); - fclose(f); - - return(! (hold_state & HOLD_SWITCH_BIT)); -} - - -/*- Display -------------------------------------------------------------------------------------*/ - - -static void draw(const char* file) -{ - DEBUGF("DEBUG %s: file: %s.", __func__, file); - - int dev_fd = open("/dev/graphics/fb0", O_RDWR); - if(dev_fd == -1) - { - DEBUGF("ERROR %s: open failed on /dev/graphics/fb0, errno: %d.", __func__, errno); - exit(errno); - } - - /* Get fixed screen information. */ - struct fb_fix_screeninfo finfo; - if(ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo) < 0) - { - DEBUGF("ERROR %s: ioctl FBIOGET_FSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno); - exit(errno); - } - - /* Get the changeable information. */ - struct fb_var_screeninfo vinfo; - if(ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) - { - DEBUGF("ERROR %s: ioctl FBIOGET_VSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno); - exit(errno); - } - - DEBUGF("DEBUG %s: bits_per_pixel: %u, width: %u, height: %u.", __func__, vinfo.bits_per_pixel, vinfo.width, vinfo.height); - - size_t screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; - - /* ToDo: Is this needed? */ - vinfo.xres = 320; - vinfo.xres_virtual = 320; - vinfo.width = 320; - vinfo.yres = 240; - vinfo.yres_virtual = 240; - vinfo.height = 240; - vinfo.xoffset = 0; - vinfo.yoffset = 0; - vinfo.sync = 0; - 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 = 0; - vinfo.transp.length = 0; - vinfo.transp.msb_right = 0; - vinfo.nonstd = 4; - if(ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) - { - DEBUGF("ERROR %s: ioctl FBIOPUT_VSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno); - exit(errno); - } - - /* Map the device to memory. */ - char* dev_fb = (char*) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0); - if(dev_fb == MAP_FAILED) - { - DEBUGF("ERROR %s: mmap failed on /dev/graphics/fb0, errno: %d.", __func__, errno); - exit(errno); - } - - BMP* bmp = BMP_ReadFile(file); - if(BMP_GetError() != BMP_OK ) - { - DEBUGF("ERROR %s: BMP_ReadFile failed on %s: %d.", __func__, file, BMP_GetError()); - exit(BMP_GetError()); - } - - int y = 0; - for( ; y < 240; ++y) - { - int x = 0; - for( ; x < 320; ++x) - { - long int position = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8 ) - + (y + vinfo.yoffset) * finfo.line_length; - UCHAR r, g, b; - BMP_GetPixelRGB(bmp, x, y, &r, &g, &b); - unsigned short int pixel = (r >> 3) << 11 | (g >> 2) << 5 | (b >> 3); - *((unsigned short int*)(dev_fb + position)) = pixel; - } - } - - BMP_Free(bmp); - munmap(dev_fb, screensize); - close(dev_fd); -} - - -/*-----------------------------------------------------------------------------------------------*/ - - -static const char ROCKBOX_BIN[] = "/mnt/sdcard/.rockbox/rockbox"; -static const char OF_PLAYER_BIN[] = "/system/bin/MangoPlayer_original"; -static const char PLAYER_FILE[] = "/data/chosen_player"; - - -int main(int argc, char **argv) -{ - TRACE; - - /* - Create the iBasso Vold socket and monitor it. - Do this early to not block Vold. - */ - vold_monitor_start(); - - int last_chosen_player = CHOICE_NONE; - - FILE* f = fopen(PLAYER_FILE, "r"); - if(f != NULL) - { - fscanf(f, "%d", &last_chosen_player); - fclose(f); - } - - DEBUGF("DEBUG %s: Current player choice: %d.", __func__, last_chosen_player); - - if(check_for_hold() || (last_chosen_player == CHOICE_NONE)) - { - draw("/system/chooser.bmp"); - - enum user_choice choice = get_user_choice(); - - if(choice == CHOICE_POWEROFF) - { - reboot(RB_POWER_OFF); - while(true) - { - sleep(1); - } - } - - if(choice != last_chosen_player) - { - last_chosen_player = choice; - - f = fopen(PLAYER_FILE, "w"); - fprintf(f, "%d", last_chosen_player); - fclose(f); - } - - DEBUGF("DEBUG %s: New player choice: %d.", __func__, last_chosen_player); - } - - /* true, Rockbox was started at least once. */ - bool rockboxStarted = false; - - while(true) - { - /* Excecute OF MangoPlayer or Rockbox and restart it if it crashes. */ - - if(last_chosen_player == CHOICE_ROCKBOX) - { - if(rockboxStarted) - { - /* - At this point it is assumed, that Rockbox has exited due to a USB connection - triggering a remount of the internal storage for mass storage access. - Rockbox will eventually restart, when /mnt/sdcard becomes available again. - */ - draw("/system/usb.bmp"); - } - - pthread_mutex_lock(&_sdcard_mount_mtx); - while(_sdcard_not_mounted) - { - DEBUGF("DEBUG %s: Waiting on /mnt/sdcard/.", __func__); - - pthread_cond_wait(&_sdcard_mount_cond, &_sdcard_mount_mtx); - - DEBUGF("DEBUG %s: /mnt/sdcard/ available.", __func__); - } - pthread_mutex_unlock(&_sdcard_mount_mtx); - - /* To be able to execute rockbox. */ - system("mount -o remount,exec /mnt/sdcard"); - - /* This symlink is needed mainly to keep themes functional. */ - system("ln -s /mnt/sdcard/.rockbox /.rockbox"); - - if(access(ROCKBOX_BIN, X_OK) != -1) - { - /* Start Rockbox. */ - - /* Rockbox has its own vold monitor. */ - vold_monitor_stop(); - - DEBUGF("DEBUG %s: Excecuting %s.", __func__, ROCKBOX_BIN); - - int ret_code = system(ROCKBOX_BIN); - rockboxStarted = true; - - DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code); - - if(WIFEXITED(ret_code) && (WEXITSTATUS(ret_code) == 42)) - { - /* - Rockbox terminated to prevent a froced shutdown due to a USB connection - triggering a remount of the internal storage for mass storage access. - */ - _sdcard_not_mounted = true; - } - /* else Rockbox crashed ... */ - - vold_monitor_start(); - } - else - { - /* Rockbox executable missing. Show info screen for 30 seconds. */ - draw("/system/rbmissing.bmp"); - sleep(30); - - /* Do not block Vold, so stop after sleep. */ - vold_monitor_stop(); - -#ifdef DEBUG - system("setprop persist.sys.usb.config adb"); - system("setprop persist.usb.debug 1"); -#endif - - DEBUGF("DEBUG %s: Rockbox missing, excecuting %s.", __func__, OF_PLAYER_BIN); - - /* Start OF MangoPlayer. */ - int ret_code = system(OF_PLAYER_BIN); - - DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code); - } - } - else /* if(last_chosen_player == CHOICE_MANGO) */ - { - vold_monitor_stop(); - - DEBUGF("DEBUG %s: Excecuting %s.", __func__, OF_PLAYER_BIN); - - int ret_code = system(OF_PLAYER_BIN); - - DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code); - } - } - - return 0; -} |