summaryrefslogtreecommitdiff
path: root/rbutil
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil')
-rw-r--r--rbutil/ibassoboot/jni/Android.mk8
-rw-r--r--rbutil/ibassoboot/jni/ibassodualboot.c906
-rw-r--r--rbutil/ibassoboot/jni/rbmissing.bmpbin0 -> 230454 bytes
-rw-r--r--rbutil/ibassoboot/jni/usb.bmpbin0 -> 230454 bytes
4 files changed, 627 insertions, 287 deletions
diff --git a/rbutil/ibassoboot/jni/Android.mk b/rbutil/ibassoboot/jni/Android.mk
index 1d1566d8c0..9cd667c5b9 100644
--- a/rbutil/ibassoboot/jni/Android.mk
+++ b/rbutil/ibassoboot/jni/Android.mk
@@ -3,4 +3,12 @@ include $(CLEAR_VARS)
3 3
4LOCAL_MODULE := MangoPlayer 4LOCAL_MODULE := MangoPlayer
5LOCAL_SRC_FILES := ibassodualboot.c qdbmp.c 5LOCAL_SRC_FILES := ibassodualboot.c qdbmp.c
6
7TARGET_ARCH=arm
8TARGET_PLATFORM=android-14
9TARGET_ARCH_ABI=armeabi
10
11#LOCAL_CFLAGS := -DDEBUG
12#LOCAL_LDLIBS := -llog
13
6include $(BUILD_EXECUTABLE) 14include $(BUILD_EXECUTABLE)
diff --git a/rbutil/ibassoboot/jni/ibassodualboot.c b/rbutil/ibassoboot/jni/ibassodualboot.c
index 3f20bbeecf..0458ff1b71 100644
--- a/rbutil/ibassoboot/jni/ibassodualboot.c
+++ b/rbutil/ibassoboot/jni/ibassodualboot.c
@@ -1,13 +1,15 @@
1/*************************************************************************** 1/***************************************************************************
2 * __________ __ ___. 2 * __________ __ ___
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___ 3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / 4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$
9 * 8 *
10 * Copyright (C) 2014 by Ilia Sergachev 9 * Copyright (C) 2014 by Ilia Sergachev: Initial Rockbox port to iBasso DX50
10 * Copyright (C) 2014 by Mario Basister: iBasso DX90 port
11 * Copyright (C) 2014 by Simon Rothen: Initial Rockbox repository submission, additional features
12 * Copyright (C) 2014 by Udo Schläpfer: Code clean up, additional features
11 * 13 *
12 * This program is free software; you can redistribute it and/or 14 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License 15 * modify it under the terms of the GNU General Public License
@@ -19,421 +21,751 @@
19 * 21 *
20 ****************************************************************************/ 22 ****************************************************************************/
21 23
24
22#include <dirent.h> 25#include <dirent.h>
23#include <errno.h>
24#include <fcntl.h> 26#include <fcntl.h>
25 27#include <pthread.h>
28#include <stdbool.h>
29#include <stdlib.h>
30#include <unistd.h>
26#include <linux/fb.h> 31#include <linux/fb.h>
27#include <linux/input.h> 32#include <linux/input.h>
28#include <linux/reboot.h> 33#include <sys/mman.h>
34#include <sys/poll.h>
35#include <sys/reboot.h>
36#include <sys/socket.h>
37#include <sys/un.h>
38#include <sys/wait.h>
29 39
30#include <stdbool.h> 40#include "qdbmp.h"
31#include <string.h>
32#include <stdint.h>
33#include <stdio.h>
34#include <stdlib.h>
35 41
36#include <time.h>
37 42
38#include <sys/limits.h> 43/*- Android logcat ------------------------------------------------------------------------------*/
39#include <sys/mman.h>
40#include <sys/inotify.h>
41#include <sys/ioctl.h>
42#include <sys/poll.h>
43#include <sys/stat.h>
44#include <sys/time.h>
45#include <sys/types.h>
46 44
47#include <unistd.h>
48 45
49#include "qdbmp.h" 46#ifdef DEBUG
47#include <android/log.h>
48
49
50static const char log_tag[] = "Rockbox Boot";
50 51
51 52
52#define MIN_TIME 1395606821 53void debugf(const char *fmt, ...)
53#define TIME_FILE "/data/time_store" 54{
54#define TIME_CHECK_PERIOD 60 /* seconds */ 55 va_list ap;
55#define VOLD_LINK "/data/vold" 56 va_start(ap, fmt);
56#define PLAYER_FILE "/data/chosen_player" 57 __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, fmt, ap);
57#define NOASK_FLAG "/data/no_ask_once" 58 va_end(ap);
58#define POLL_MS 10 59}
60
61
62void ldebugf(const char* file, int line, const char *fmt, ...)
63{
64 va_list ap;
65 /* 13: 5 literal chars and 8 chars for the line number. */
66 char buf[strlen(file) + strlen(fmt) + 13];
67 snprintf(buf, sizeof(buf), "%s (%d): %s", file, line, fmt);
68 va_start(ap, fmt);
69 __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, buf, ap);
70 va_end(ap);
71}
72
73
74void debug_trace(const char* function)
75{
76 static const char trace_tag[] = "TRACE: ";
77 char msg[strlen(trace_tag) + strlen(function) + 1];
78 snprintf(msg, sizeof(msg), "%s%s", trace_tag, function);
79 __android_log_write(ANDROID_LOG_DEBUG, log_tag, msg);
80}
81
82
83#define DEBUGF debugf
84#define TRACE debug_trace(__func__)
85#else
86#define DEBUGF(...)
87#define TRACE
88#endif /* DEBUG */
59 89
60 90
61#define KEYCODE_HEADPHONES 114 91/*- Vold monitor --------------------------------------------------------------------------------*/
62#define KEYCODE_HOLD 115
63#define KEYCODE_PWR 116
64#define KEYCODE_PWR_LONG 117
65#define KEYCODE_SD 143
66#define KEYCODE_VOLPLUS 158
67#define KEYCODE_VOLMINUS 159
68#define KEYCODE_PREV 160
69#define KEYCODE_NEXT 162
70#define KEYCODE_PLAY 161
71 92
72#define KEY_HOLD_OFF 16
73 93
74void checktime() 94/*
95 Without this socket iBasso Vold will not start.
96 iBasso Vold uses this to send status messages about storage devices.
97*/
98static const char VOLD_MONITOR_SOCKET_NAME[] = "UNIX_domain";
99static int _vold_monitor_socket_fd = -1;
100
101
102static void vold_monitor_open_socket(void)
75{ 103{
76 time_t t_stored=0, t_current=time(NULL); 104 TRACE;
105
106 unlink(VOLD_MONITOR_SOCKET_NAME);
107
108 _vold_monitor_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
77 109
78 FILE *f = fopen(TIME_FILE, "r"); 110 if(_vold_monitor_socket_fd < 0)
79 if(f!=NULL)
80 { 111 {
81 fscanf(f, "%ld", &t_stored); 112 _vold_monitor_socket_fd = -1;
82 fclose(f); 113 return;
83 } 114 }
84 115
85 printf("stored time: %ld, current time: %ld\n", t_stored, t_current); 116 struct sockaddr_un addr;
86 117 memset(&addr, 0, sizeof(addr));
87 if(t_stored<MIN_TIME) 118 addr.sun_family = AF_UNIX;
88 t_stored=MIN_TIME; 119 strncpy(addr.sun_path, VOLD_MONITOR_SOCKET_NAME, sizeof(addr.sun_path) - 1);
89 120
90 if(t_stored<t_current) 121 if(bind(_vold_monitor_socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
91 { 122 {
92 f = fopen(TIME_FILE, "w"); 123 close(_vold_monitor_socket_fd);
93 fprintf(f, "%ld", t_current); 124 unlink(VOLD_MONITOR_SOCKET_NAME);
94 fclose(f); 125 _vold_monitor_socket_fd = -1;
126 return;
95 } 127 }
96 else 128
129 if(listen(_vold_monitor_socket_fd, 1) < 0)
97 { 130 {
98 t_stored += TIME_CHECK_PERIOD; 131 close(_vold_monitor_socket_fd);
99 struct tm *t = localtime(&t_stored); 132 unlink(VOLD_MONITOR_SOCKET_NAME);
100 struct timeval tv = {mktime(t), 0}; 133 _vold_monitor_socket_fd = -1;
101 settimeofday(&tv, 0); 134 return;
102 } 135 }
103} 136}
104 137
105 138
106static struct pollfd *ufds; 139/*
107static char **device_names; 140 bionic does not have pthread_cancel.
108static int nfds; 141 0: Vold monitor thread stopped/ending.
142 1: Vold monitor thread started/running.
143*/
144static volatile sig_atomic_t _vold_monitor_active = 0;
145
146
147/* true: sdcard not mounted. */
148static bool _sdcard_not_mounted = true;
149
150
151/* Mutex for sdcard mounted flag. */
152static pthread_mutex_t _sdcard_mount_mtx = PTHREAD_MUTEX_INITIALIZER;
109 153
110 154
155/* Signal condition for sdcard mounted flag. */
156static pthread_cond_t _sdcard_mount_cond = PTHREAD_COND_INITIALIZER;
111 157
112static int open_device(const char *device, int print_flags) 158
159static void* vold_monitor_run(void* nothing)
113{ 160{
114 int fd; 161 _vold_monitor_active = 1;
115 struct pollfd *new_ufds;
116 char **new_device_names;
117 162
118 fd = open(device, O_RDWR); 163 (void) nothing;
119 if(fd < 0) 164
120 { 165 DEBUGF("DEBUG %s: Thread start.", __func__);
121 fprintf(stderr, "could not open %s, %s\n", device, strerror(errno));
122 return -1;
123 }
124 166
125 new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1)); 167 vold_monitor_open_socket();
126 if(new_ufds == NULL) 168 if(_vold_monitor_socket_fd < 0)
127 { 169 {
128 fprintf(stderr, "out of memory\n"); 170 DEBUGF("ERROR %s: Thread end: No socket.", __func__);
129 return -1; 171
172 _vold_monitor_active = 0;
173 return 0;
130 } 174 }
131 ufds = new_ufds; 175
132 new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1)); 176 struct pollfd fds[1];
133 if(new_device_names == NULL) 177 fds[0].fd = _vold_monitor_socket_fd;
178 fds[0].events = POLLIN;
179
180 while(_vold_monitor_active == 1)
134 { 181 {
135 fprintf(stderr, "out of memory\n"); 182 poll(fds, 1, 10);
136 return -1; 183 if(! (fds[0].revents & POLLIN))
184 {
185 continue;
186 }
187
188 int socket_fd = accept(_vold_monitor_socket_fd, NULL, NULL);
189
190 if(socket_fd < 0)
191 {
192 DEBUGF("ERROR %s: accept failed.", __func__);
193
194 continue;
195 }
196
197 while(true)
198 {
199 char msg[1024];
200 memset(msg, 0, sizeof(msg));
201 int length = read(socket_fd, msg, sizeof(msg));
202
203 if(length <= 0)
204 {
205 close(socket_fd);
206 break;
207 }
208
209 DEBUGF("DEBUG %s: msg: %s", __func__, msg);
210
211 if(strcmp(msg, "Volume flash /mnt/sdcard state changed from 3 (Checking) to 4 (Mounted)") == 0)
212 {
213 pthread_mutex_lock(&_sdcard_mount_mtx);
214 _sdcard_not_mounted = false;
215 pthread_cond_signal(&_sdcard_mount_cond);
216 pthread_mutex_unlock(&_sdcard_mount_mtx);
217 }
218 }
137 } 219 }
138 device_names = new_device_names;
139 220
140 ufds[nfds].fd = fd; 221 close(_vold_monitor_socket_fd);
141 ufds[nfds].events = POLLIN; 222 unlink(VOLD_MONITOR_SOCKET_NAME);
142 device_names[nfds] = strdup(device); 223 _vold_monitor_socket_fd = -1;
143 nfds++; 224
225 DEBUGF("DEBUG %s: Thread end.", __func__);
144 226
227 _vold_monitor_active = 0;
145 return 0; 228 return 0;
146} 229}
147 230
148 231
232/* Vold monitor thread. */
233static pthread_t _vold_monitor_thread;
149 234
150static int scan_dir(const char *dirname, int print_flags) 235
236static void vold_monitor_start(void)
151{ 237{
152 char devname[PATH_MAX]; 238 TRACE;
153 char *filename; 239
154 DIR *dir; 240 if(_vold_monitor_active == 0)
155 struct dirent *de;
156 dir = opendir(dirname);
157 if(dir == NULL)
158 return -1;
159 strcpy(devname, dirname);
160 filename = devname + strlen(devname);
161 *filename++ = '/';
162 while((de = readdir(dir)))
163 { 241 {
164 if(de->d_name[0] == '.' && 242 pthread_create(&_vold_monitor_thread, NULL, vold_monitor_run, NULL);
165 (de->d_name[1] == '\0' ||
166 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
167 continue;
168 strcpy(filename, de->d_name);
169 open_device(devname, print_flags);
170 } 243 }
171 closedir(dir);
172 return 0;
173} 244}
174 245
175 246
176 247static void vold_monitor_stop(void)
177void button_init_device(void)
178{ 248{
179 int res; 249 TRACE;
180 int print_flags = 0; 250
181 const char *device = NULL; 251 if(_vold_monitor_active == 1)
182 const char *device_path = "/dev/input";
183
184 nfds = 1;
185 ufds = calloc(1, sizeof(ufds[0]));
186 ufds[0].fd = inotify_init();
187 ufds[0].events = POLLIN;
188 if(device)
189 {
190 res = open_device(device, print_flags);
191 if(res < 0) {
192 fprintf(stderr, "open device failed\n");
193 }
194 }
195 else
196 { 252 {
197 res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); 253 _vold_monitor_active = 0;
198 if(res < 0) 254 int ret = pthread_join(_vold_monitor_thread, NULL);
199 { 255 DEBUGF("DEBUG %s: Thread joined: ret: %d.", __func__, ret);
200 fprintf(stderr, "could not add watch for %s, %s\n", device_path, strerror(errno));
201 }
202 res = scan_dir(device_path, print_flags);
203 if(res < 0)
204 {
205 fprintf(stderr, "scan dir failed for %s\n", device_path);
206 }
207 } 256 }
208} 257}
209 258
210 259
211int draw() 260/*- Input handler -------------------------------------------------------------------------------*/
261
262
263/* Input devices monitored with poll API. */
264static struct pollfd* _fds = NULL;
265
266
267/* Number of input devices monitored with poll API. */
268static nfds_t _nfds = 0;
269
270
271/* The names of the devices in _fds. */
272static char** _device_names = NULL;
273
274
275/* Open device device_name and add it to the list of polled devices. */
276static void open_device(const char* device_name)
212{ 277{
213 int fbfd = 0; 278 int fd = open(device_name, O_RDONLY);
214 struct fb_var_screeninfo vinfo; 279 if(fd == -1)
215 struct fb_fix_screeninfo finfo;
216 long int screensize = 0;
217 char *fbp = 0;
218 int x = 0, y = 0;
219 long int location = 0;
220
221 /* Open the file for reading and writing */
222 fbfd = open("/dev/graphics/fb0", O_RDWR);
223 if (fbfd == -1)
224 { 280 {
225 perror("Error: cannot open framebuffer device"); 281 DEBUGF("ERROR %s: open failed on %s.", __func__, device_name);
226 exit(1); 282 exit(-1);
227 } 283 }
228 /* Get fixed screen information */ 284
229 if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) 285 struct pollfd* new_fds = realloc(_fds, sizeof(struct pollfd) * (_nfds + 1));
286 if(new_fds == NULL)
230 { 287 {
231 perror("Error reading fixed information"); 288 DEBUGF("ERROR %s: realloc for _fds failed.", __func__);
232 exit(2); 289 exit(-1);
233 } 290 }
234 291
235 /* Get variable screen information */ 292 _fds = new_fds;
236 if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) 293 _fds[_nfds].fd = fd;
294 _fds[_nfds].events = POLLIN;
295
296 char** new_device_names = realloc(_device_names, sizeof(char*) * (_nfds + 1));
297 if(new_device_names == NULL)
237 { 298 {
238 perror("Error reading variable information"); 299 DEBUGF("ERROR %s: realloc for _device_names failed.", __func__);
239 exit(3); 300 exit(-1);
240 } 301 }
241 302
242 /* Figure out the size of the screen in bytes */ 303 _device_names = new_device_names;
243 screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; 304 _device_names[_nfds] = strdup(device_name);
244 305 if(_device_names[_nfds] == NULL)
245 vinfo.xres = vinfo.xres_virtual = vinfo.width = 320;
246 vinfo.yres = vinfo.yres_virtual = vinfo.height = 240;
247 vinfo.xoffset = vinfo.yoffset = vinfo.sync = vinfo.vmode = 0;
248 vinfo.pixclock = 104377;
249 vinfo.left_margin = 20;
250 vinfo.right_margin = 50;
251 vinfo.upper_margin = 2;
252 vinfo.lower_margin = 4;
253 vinfo.hsync_len = 10;
254 vinfo.vsync_len = 2;
255 vinfo.red.offset = 11;
256 vinfo.red.length = 5;
257 vinfo.red.msb_right = 0;
258 vinfo.green.offset = 5;
259 vinfo.green.length = 6;
260 vinfo.green.msb_right = 0;
261 vinfo.blue.offset = 0;
262 vinfo.blue.length = 5;
263 vinfo.blue.msb_right = 0;
264 vinfo.transp.offset = vinfo.transp.length = vinfo.transp.msb_right = 0;
265 vinfo.nonstd = 4;
266
267 if (ioctl(fbfd, FBIOPUT_VSCREENINFO, &vinfo))
268 { 306 {
269 perror("fbset(ioctl)"); 307 DEBUGF("ERROR %s: strdup failed.", __func__);
270 exit(4); 308 exit(-1);
271 } 309 }
272 310
311 ++_nfds;
273 312
274 /* Map the device to memory */ 313 DEBUGF("DEBUG %s: Opened device %s.", __func__, device_name);
275 fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, 314}
276 fbfd, 0); 315
277 if ((int)fbp == -1) 316
317static void button_init_device(void)
318{
319 TRACE;
320
321 if((_fds != NULL) || (_nfds != 0) || (_device_names != NULL))
278 { 322 {
279 perror("Error: failed to map framebuffer device to memory"); 323 DEBUGF("ERROR %s: Allready initialized.", __func__);
280 exit(4); 324 return;
281 } 325 }
282 326
283 BMP* bmp = BMP_ReadFile("/system/rockbox/chooser.bmp"); 327 /* The input device directory. */
284 BMP_CHECK_ERROR( stderr, -1 ); 328 static const char device_path[] = "/dev/input";
285 329
286 UCHAR r, g, b; 330 /* Path delimeter. */
287 unsigned short int t; 331 static const char delimeter[] = "/";
288 332
289 for (y = 0; y < 240; y++) 333 /* Open all devices in device_path. */
290 for (x = 0; x < 320; x++) 334 DIR* dir = opendir(device_path);
291 { 335 if(dir == NULL)
292 location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + 336 {
293 (y+vinfo.yoffset) * finfo.line_length; 337 DEBUGF("ERROR %s: opendir failed: errno: %d.", __func__, errno);
338 exit(errno);
339 }
294 340
295 BMP_GetPixelRGB(bmp, x, y, &r, &g, &b); 341 char device_name[PATH_MAX];
296 t = (r>>3)<<11 | (g>>2) << 5 | (b>>3); 342 strcpy(device_name, device_path);
297 *((unsigned short int*)(fbp + location)) = t; 343 strcat(device_name, delimeter);
344 char* device_name_idx = device_name + strlen(device_name);
345
346 struct dirent* dir_entry;
347 while((dir_entry = readdir(dir)))
348 {
349 if( ((dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '\0'))
350 || ((dir_entry->d_name[0] == '.') && (dir_entry->d_name[1] == '.') && (dir_entry->d_name[2] == '\0')))
351 {
352 continue;
298 } 353 }
299 354
300 BMP_Free( bmp ); 355 strcpy(device_name_idx, dir_entry->d_name);
301 356
302 munmap(fbp, screensize); 357 /* Open and add device to _fds. */
303 close(fbfd); 358 open_device(device_name);
304 return 0; 359 }
360
361 closedir(dir);
362
363 /* Sanity check. */
364 if(_nfds < 2)
365 {
366 DEBUGF("ERROR %s: No input devices.", __func__);
367 exit(-1);
368 }
305} 369}
306 370
307 371
308int choose_player() 372#define EVENT_TYPE_BUTTON 1
373
374
375#define EVENT_CODE_BUTTON_PWR_LONG 117
376#define EVENT_CODE_BUTTON_REV 160
377#define EVENT_CODE_BUTTON_NEXT 162
378
379
380#define EVENT_TYPE_TOUCHSCREEN 3
381
382
383#define EVENT_CODE_TOUCHSCREEN_X 53
384
385
386enum user_choice
309{ 387{
310 int i; 388 CHOICE_NONE = -1,
311 int res; 389 CHOICE_MANGO,
312 struct input_event event; 390 CHOICE_ROCKBOX,
391 CHOICE_POWEROFF
392};
313 393
314 while(true) 394
395static int get_user_choice(void)
396{
397 TRACE;
398
399 button_init_device();
400
401 enum user_choice choice = CHOICE_NONE;
402
403 while(choice == CHOICE_NONE)
315 { 404 {
316 poll(ufds, nfds, POLL_MS); 405 /* Poll all input devices. */
317 for(i = 1; i < nfds; i++) 406 poll(_fds, _nfds, 0);
407
408 nfds_t fds_idx = 0;
409 for( ; fds_idx < _nfds; ++fds_idx)
318 { 410 {
319 if(ufds[i].revents & POLLIN) 411 if(! (_fds[fds_idx].revents & POLLIN))
320 { 412 {
321 res = read(ufds[i].fd, &event, sizeof(event)); 413 continue;
322 if(res < (int)sizeof(event)) 414 }
323 { 415
324 fprintf(stderr, "could not get event\n"); 416 struct input_event event;
325 } 417 if(read(_fds[fds_idx].fd, &event, sizeof(event)) < (int) sizeof(event))
326 if(event.type==1) 418 {
419 DEBUGF("ERROR %s: Read of input devices failed.", __func__);
420 continue;
421 }
422
423 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);
424
425 if(event.type == EVENT_TYPE_BUTTON)
426 {
427 switch(event.code)
327 { 428 {
328 if(event.code==KEYCODE_NEXT) 429 case EVENT_CODE_BUTTON_REV:
329 { 430 {
330 puts("rockbox!"); 431 choice = CHOICE_MANGO;
331 return 1; 432 break;
332 } 433 }
333 else if(event.code==KEYCODE_PREV) 434
435 case EVENT_CODE_BUTTON_NEXT:
334 { 436 {
335 puts("mango!"); 437 choice = CHOICE_ROCKBOX;
336 return 0; 438 break;
337 } 439 }
338 else if(event.code==KEYCODE_PWR || event.code==KEYCODE_PWR_LONG) 440
441 case EVENT_CODE_BUTTON_PWR_LONG:
339 { 442 {
340 reboot(LINUX_REBOOT_CMD_POWER_OFF); 443 choice = CHOICE_POWEROFF;
444 break;
341 } 445 }
342 } 446 }
343 else if(event.type==3) 447 }
448 else if((event.type == EVENT_TYPE_TOUCHSCREEN) && (event.code == EVENT_CODE_TOUCHSCREEN_X))
449 {
450 if(event.value < 160)
344 { 451 {
345 if(event.code==53) //x coord 452 choice = CHOICE_MANGO;
346 { 453 }
347 if(event.value<160) 454 else
348 { 455 {
349 puts("mango!"); 456 choice = CHOICE_ROCKBOX;
350 return 0;
351 }
352 else
353 {
354 puts("rockbox!");
355 return 1;
356 }
357 }
358 } 457 }
359 } 458 }
360 } 459 }
361 } 460 }
362 return true; 461
462 if(_fds)
463 {
464 nfds_t fds_idx = 0;
465 for( ; fds_idx < _nfds; ++fds_idx)
466 {
467 close(_fds[fds_idx].fd);
468 }
469 free(_fds);
470 _fds = NULL;
471 }
472
473 if(_device_names)
474 {
475 nfds_t fds_idx = 0;
476 for( ; fds_idx < _nfds; ++fds_idx)
477 {
478 free(_device_names[fds_idx]);
479 }
480 free(_device_names);
481 _device_names = NULL;
482 }
483
484 _nfds = 0;
485
486 return choice;
363} 487}
364 488
365bool check_for_hold() 489
490/*
491 Changing bit, when hold switch is toggled.
492 Bit is off when hold switch is engaged.
493*/
494#define HOLD_SWITCH_BIT 16
495
496
497static bool check_for_hold(void)
366{ 498{
367 FILE *f = fopen("/sys/class/axppower/holdkey", "r"); 499 TRACE;
368 char x; 500
369 fscanf(f, "%c", &x); 501 char hold_state;
502
503 FILE* f = fopen("/sys/class/axppower/holdkey", "r");
504 fscanf(f, "%c", &hold_state);
370 fclose(f); 505 fclose(f);
371 506
372 if(x & KEY_HOLD_OFF) 507 return(! (hold_state & HOLD_SWITCH_BIT));
373 return false;
374 else
375 return true;
376} 508}
377 509
510
511/*- Display -------------------------------------------------------------------------------------*/
512
513
514static void draw(const char* file)
515{
516 DEBUGF("DEBUG %s: file: %s.", __func__, file);
517
518 int dev_fd = open("/dev/graphics/fb0", O_RDWR);
519 if(dev_fd == -1)
520 {
521 DEBUGF("ERROR %s: open failed on /dev/graphics/fb0, errno: %d.", __func__, errno);
522 exit(errno);
523 }
524
525 /* Get fixed screen information. */
526 struct fb_fix_screeninfo finfo;
527 if(ioctl(dev_fd, FBIOGET_FSCREENINFO, &finfo) < 0)
528 {
529 DEBUGF("ERROR %s: ioctl FBIOGET_FSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno);
530 exit(errno);
531 }
532
533 /* Get the changeable information. */
534 struct fb_var_screeninfo vinfo;
535 if(ioctl(dev_fd, FBIOGET_VSCREENINFO, &vinfo) < 0)
536 {
537 DEBUGF("ERROR %s: ioctl FBIOGET_VSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno);
538 exit(errno);
539 }
540
541 DEBUGF("DEBUG %s: bits_per_pixel: %u, width: %u, height: %u.", __func__, vinfo.bits_per_pixel, vinfo.width, vinfo.height);
542
543 size_t screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
544
545 /* ToDo: Is this needed? */
546 vinfo.xres = 320;
547 vinfo.xres_virtual = 320;
548 vinfo.width = 320;
549 vinfo.yres = 240;
550 vinfo.yres_virtual = 240;
551 vinfo.height = 240;
552 vinfo.xoffset = 0;
553 vinfo.yoffset = 0;
554 vinfo.sync = 0;
555 vinfo.vmode = 0;
556 vinfo.pixclock = 104377;
557 vinfo.left_margin = 20;
558 vinfo.right_margin = 50;
559 vinfo.upper_margin = 2;
560 vinfo.lower_margin = 4;
561 vinfo.hsync_len = 10;
562 vinfo.vsync_len = 2;
563 vinfo.red.offset = 11;
564 vinfo.red.length = 5;
565 vinfo.red.msb_right = 0;
566 vinfo.green.offset = 5;
567 vinfo.green.length = 6;
568 vinfo.green.msb_right = 0;
569 vinfo.blue.offset = 0;
570 vinfo.blue.length = 5;
571 vinfo.blue.msb_right = 0;
572 vinfo.transp.offset = 0;
573 vinfo.transp.length = 0;
574 vinfo.transp.msb_right = 0;
575 vinfo.nonstd = 4;
576 if(ioctl(dev_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0)
577 {
578 DEBUGF("ERROR %s: ioctl FBIOPUT_VSCREENINFO failed on /dev/graphics/fb0, errno: %d.", __func__, errno);
579 exit(errno);
580 }
581
582 /* Map the device to memory. */
583 char* dev_fb = (char*) mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, dev_fd, 0);
584 if(dev_fb == MAP_FAILED)
585 {
586 DEBUGF("ERROR %s: mmap failed on /dev/graphics/fb0, errno: %d.", __func__, errno);
587 exit(errno);
588 }
589
590 BMP* bmp = BMP_ReadFile(file);
591 if(BMP_GetError() != BMP_OK )
592 {
593 DEBUGF("ERROR %s: BMP_ReadFile failed on %s: %d.", __func__, file, BMP_GetError());
594 exit(BMP_GetError());
595 }
596
597 int y = 0;
598 for( ; y < 240; ++y)
599 {
600 int x = 0;
601 for( ; x < 320; ++x)
602 {
603 long int position = (x + vinfo.xoffset) * (vinfo.bits_per_pixel / 8 )
604 + (y + vinfo.yoffset) * finfo.line_length;
605 UCHAR r, g, b;
606 BMP_GetPixelRGB(bmp, x, y, &r, &g, &b);
607 unsigned short int pixel = (r >> 3) << 11 | (g >> 2) << 5 | (b >> 3);
608 *((unsigned short int*)(dev_fb + position)) = pixel;
609 }
610 }
611
612 BMP_Free(bmp);
613 munmap(dev_fb, screensize);
614 close(dev_fd);
615}
616
617
618/*-----------------------------------------------------------------------------------------------*/
619
620
621static const char ROCKBOX_BIN[] = "/mnt/sdcard/.rockbox/rockbox";
622static const char OF_PLAYER_BIN[] = "/system/bin/MangoPlayer_original";
623static const char PLAYER_FILE[] = "/data/chosen_player";
624
625
378int main(int argc, char **argv) 626int main(int argc, char **argv)
379{ 627{
380 FILE *f; 628 TRACE;
381 int last_chosen_player = -1; 629
630 /*
631 Create the iBasso Vold socket and monitor it.
632 Do this early to not block Vold.
633 */
634 vold_monitor_start();
382 635
383 f = fopen(PLAYER_FILE, "r"); 636 int last_chosen_player = CHOICE_NONE;
384 if(f!=NULL) 637
638 FILE* f = fopen(PLAYER_FILE, "r");
639 if(f != NULL)
385 { 640 {
386 fscanf(f, "%d", &last_chosen_player); 641 fscanf(f, "%d", &last_chosen_player);
387 fclose(f); 642 fclose(f);
388 } 643 }
389 bool ask = (access(VOLD_LINK, F_OK) == -1) || ((access(NOASK_FLAG, F_OK) == -1) && check_for_hold()) || (last_chosen_player==-1);
390 644
391 if(ask) 645 DEBUGF("DEBUG %s: Current player choice: %d.", __func__, last_chosen_player);
646
647 if(check_for_hold() || (last_chosen_player == CHOICE_NONE))
392 { 648 {
393 draw(); 649 draw("/system/chooser.bmp");
394 button_init_device();
395 int player_chosen_now = choose_player();
396 650
397 if(last_chosen_player!=player_chosen_now) 651 enum user_choice choice = get_user_choice();
652
653 if(choice == CHOICE_POWEROFF)
398 { 654 {
399 f = fopen(PLAYER_FILE, "w"); 655 reboot(RB_POWER_OFF);
400 fprintf(f, "%d", player_chosen_now); 656 while(true)
401 fclose(f); 657 {
658 sleep(1);
659 }
402 } 660 }
403 661
404 if(last_chosen_player!=player_chosen_now || (access(VOLD_LINK, F_OK) == -1)) 662 if(choice != last_chosen_player)
405 { 663 {
406 system("rm "VOLD_LINK); 664 last_chosen_player = choice;
407
408 if(player_chosen_now)
409 system("ln -s /system/bin/vold_rockbox "VOLD_LINK);
410 else
411 system("ln -s /system/bin/vold_original "VOLD_LINK);
412 665
413 system("touch "NOASK_FLAG); 666 f = fopen(PLAYER_FILE, "w");
414 system("reboot"); 667 fprintf(f, "%d", last_chosen_player);
668 fclose(f);
415 } 669 }
416 last_chosen_player = player_chosen_now; 670
671 DEBUGF("DEBUG %s: New player choice: %d.", __func__, last_chosen_player);
417 } 672 }
418 673
419 system("rm "NOASK_FLAG); 674 /* true, Rockbox was started at least once. */
675 bool rockboxStarted = false;
420 676
421 while(1) 677 while(true)
422 { 678 {
423 if(last_chosen_player) 679 /* Excecute OF MangoPlayer or Rockbox and restart it if it crashes. */
680
681 if(last_chosen_player == CHOICE_ROCKBOX)
424 { 682 {
425// system("/system/bin/openadb"); 683 if(rockboxStarted)
426 system("/system/rockbox/lib/rockbox"); 684 {
685 /*
686 At this point it is assumed, that Rockbox has exited due to a USB connection
687 triggering a remount of the internal storage for mass storage access.
688 Rockbox will eventually restart, when /mnt/sdcard becomes available again.
689 */
690 draw("/system/usb.bmp");
691 }
692
693 pthread_mutex_lock(&_sdcard_mount_mtx);
694 while(_sdcard_not_mounted)
695 {
696 DEBUGF("DEBUG %s: Waiting on /mnt/sdcard/.", __func__);
697
698 pthread_cond_wait(&_sdcard_mount_cond, &_sdcard_mount_mtx);
699
700 DEBUGF("DEBUG %s: /mnt/sdcard/ available.", __func__);
701 }
702 pthread_mutex_unlock(&_sdcard_mount_mtx);
703
704 /* To be able to execute rockbox. */
705 system("mount -o remount,exec /mnt/sdcard");
706
707 /* This symlink is needed mainly to keep themes functional. */
708 system("ln -s /mnt/sdcard/.rockbox /.rockbox");
709
710 if(access(ROCKBOX_BIN, X_OK) != -1)
711 {
712 /* Start Rockbox. */
713
714 /* Rockbox has its own vold monitor. */
715 vold_monitor_stop();
716
717 DEBUGF("DEBUG %s: Excecuting %s.", __func__, ROCKBOX_BIN);
718
719 int ret_code = system(ROCKBOX_BIN);
720 rockboxStarted = true;
721
722 DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code);
723
724 if(WIFEXITED(ret_code) && (WEXITSTATUS(ret_code) == 42))
725 {
726 /*
727 Rockbox terminated to prevent a froced shutdown due to a USB connection
728 triggering a remount of the internal storage for mass storage access.
729 */
730 _sdcard_not_mounted = true;
731 }
732 /* else Rockbox crashed ... */
733
734 vold_monitor_start();
735 }
736 else
737 {
738 /* Rockbox executable missing. Show info screen for 30 seconds. */
739 draw("/system/rbmissing.bmp");
740 sleep(30);
741
742 /* Do not block Vold, so stop after sleep. */
743 vold_monitor_stop();
744
745#ifdef DEBUG
746 system("setprop persist.sys.usb.config adb");
747 system("setprop persist.usb.debug 1");
748#endif
749
750 DEBUGF("DEBUG %s: Rockbox missing, excecuting %s.", __func__, OF_PLAYER_BIN);
751
752 /* Start OF MangoPlayer. */
753 int ret_code = system(OF_PLAYER_BIN);
754
755 DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code);
756 }
427 } 757 }
428 else 758 else /* if(last_chosen_player == CHOICE_MANGO) */
429// system("/system/bin/closeadb"); 759 {
430 system("/system/bin/MangoPlayer_original"); 760 vold_monitor_stop();
761
762 DEBUGF("DEBUG %s: Excecuting %s.", __func__, OF_PLAYER_BIN);
431 763
432 sleep(1); 764 int ret_code = system(OF_PLAYER_BIN);
765
766 DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code);
767 }
433 } 768 }
434 769
435 return 0; 770 return 0;
436} 771}
437
438
439
diff --git a/rbutil/ibassoboot/jni/rbmissing.bmp b/rbutil/ibassoboot/jni/rbmissing.bmp
new file mode 100644
index 0000000000..1e97066d8c
--- /dev/null
+++ b/rbutil/ibassoboot/jni/rbmissing.bmp
Binary files differ
diff --git a/rbutil/ibassoboot/jni/usb.bmp b/rbutil/ibassoboot/jni/usb.bmp
new file mode 100644
index 0000000000..c462de2236
--- /dev/null
+++ b/rbutil/ibassoboot/jni/usb.bmp
Binary files differ