summaryrefslogtreecommitdiff
path: root/utils/ibassoboot
diff options
context:
space:
mode:
Diffstat (limited to 'utils/ibassoboot')
-rw-r--r--utils/ibassoboot/jni/Android.mk14
-rw-r--r--utils/ibassoboot/jni/chooser.bmpbin0 -> 230454 bytes
-rw-r--r--utils/ibassoboot/jni/ibassodualboot.c771
-rw-r--r--utils/ibassoboot/jni/qdbmp.c798
-rw-r--r--utils/ibassoboot/jni/qdbmp.h133
-rw-r--r--utils/ibassoboot/jni/rbmissing.bmpbin0 -> 230454 bytes
-rw-r--r--utils/ibassoboot/jni/usb.bmpbin0 -> 230454 bytes
7 files changed, 1716 insertions, 0 deletions
diff --git a/utils/ibassoboot/jni/Android.mk b/utils/ibassoboot/jni/Android.mk
new file mode 100644
index 0000000000..9cd667c5b9
--- /dev/null
+++ b/utils/ibassoboot/jni/Android.mk
@@ -0,0 +1,14 @@
1LOCAL_PATH := $(call my-dir)
2include $(CLEAR_VARS)
3
4LOCAL_MODULE := MangoPlayer
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
14include $(BUILD_EXECUTABLE)
diff --git a/utils/ibassoboot/jni/chooser.bmp b/utils/ibassoboot/jni/chooser.bmp
new file mode 100644
index 0000000000..3e6742d600
--- /dev/null
+++ b/utils/ibassoboot/jni/chooser.bmp
Binary files differ
diff --git a/utils/ibassoboot/jni/ibassodualboot.c b/utils/ibassoboot/jni/ibassodualboot.c
new file mode 100644
index 0000000000..0458ff1b71
--- /dev/null
+++ b/utils/ibassoboot/jni/ibassodualboot.c
@@ -0,0 +1,771 @@
1/***************************************************************************
2 * __________ __ ___
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
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
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
20 * KIND, either express or implied.
21 *
22 ****************************************************************************/
23
24
25#include <dirent.h>
26#include <fcntl.h>
27#include <pthread.h>
28#include <stdbool.h>
29#include <stdlib.h>
30#include <unistd.h>
31#include <linux/fb.h>
32#include <linux/input.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>
39
40#include "qdbmp.h"
41
42
43/*- Android logcat ------------------------------------------------------------------------------*/
44
45
46#ifdef DEBUG
47#include <android/log.h>
48
49
50static const char log_tag[] = "Rockbox Boot";
51
52
53void debugf(const char *fmt, ...)
54{
55 va_list ap;
56 va_start(ap, fmt);
57 __android_log_vprint(ANDROID_LOG_DEBUG, log_tag, fmt, ap);
58 va_end(ap);
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 */
89
90
91/*- Vold monitor --------------------------------------------------------------------------------*/
92
93
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)
103{
104 TRACE;
105
106 unlink(VOLD_MONITOR_SOCKET_NAME);
107
108 _vold_monitor_socket_fd = socket(AF_UNIX, SOCK_STREAM, 0);
109
110 if(_vold_monitor_socket_fd < 0)
111 {
112 _vold_monitor_socket_fd = -1;
113 return;
114 }
115
116 struct sockaddr_un addr;
117 memset(&addr, 0, sizeof(addr));
118 addr.sun_family = AF_UNIX;
119 strncpy(addr.sun_path, VOLD_MONITOR_SOCKET_NAME, sizeof(addr.sun_path) - 1);
120
121 if(bind(_vold_monitor_socket_fd, (struct sockaddr*) &addr, sizeof(addr)) < 0)
122 {
123 close(_vold_monitor_socket_fd);
124 unlink(VOLD_MONITOR_SOCKET_NAME);
125 _vold_monitor_socket_fd = -1;
126 return;
127 }
128
129 if(listen(_vold_monitor_socket_fd, 1) < 0)
130 {
131 close(_vold_monitor_socket_fd);
132 unlink(VOLD_MONITOR_SOCKET_NAME);
133 _vold_monitor_socket_fd = -1;
134 return;
135 }
136}
137
138
139/*
140 bionic does not have pthread_cancel.
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;
153
154
155/* Signal condition for sdcard mounted flag. */
156static pthread_cond_t _sdcard_mount_cond = PTHREAD_COND_INITIALIZER;
157
158
159static void* vold_monitor_run(void* nothing)
160{
161 _vold_monitor_active = 1;
162
163 (void) nothing;
164
165 DEBUGF("DEBUG %s: Thread start.", __func__);
166
167 vold_monitor_open_socket();
168 if(_vold_monitor_socket_fd < 0)
169 {
170 DEBUGF("ERROR %s: Thread end: No socket.", __func__);
171
172 _vold_monitor_active = 0;
173 return 0;
174 }
175
176 struct pollfd fds[1];
177 fds[0].fd = _vold_monitor_socket_fd;
178 fds[0].events = POLLIN;
179
180 while(_vold_monitor_active == 1)
181 {
182 poll(fds, 1, 10);
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 }
219 }
220
221 close(_vold_monitor_socket_fd);
222 unlink(VOLD_MONITOR_SOCKET_NAME);
223 _vold_monitor_socket_fd = -1;
224
225 DEBUGF("DEBUG %s: Thread end.", __func__);
226
227 _vold_monitor_active = 0;
228 return 0;
229}
230
231
232/* Vold monitor thread. */
233static pthread_t _vold_monitor_thread;
234
235
236static void vold_monitor_start(void)
237{
238 TRACE;
239
240 if(_vold_monitor_active == 0)
241 {
242 pthread_create(&_vold_monitor_thread, NULL, vold_monitor_run, NULL);
243 }
244}
245
246
247static void vold_monitor_stop(void)
248{
249 TRACE;
250
251 if(_vold_monitor_active == 1)
252 {
253 _vold_monitor_active = 0;
254 int ret = pthread_join(_vold_monitor_thread, NULL);
255 DEBUGF("DEBUG %s: Thread joined: ret: %d.", __func__, ret);
256 }
257}
258
259
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)
277{
278 int fd = open(device_name, O_RDONLY);
279 if(fd == -1)
280 {
281 DEBUGF("ERROR %s: open failed on %s.", __func__, device_name);
282 exit(-1);
283 }
284
285 struct pollfd* new_fds = realloc(_fds, sizeof(struct pollfd) * (_nfds + 1));
286 if(new_fds == NULL)
287 {
288 DEBUGF("ERROR %s: realloc for _fds failed.", __func__);
289 exit(-1);
290 }
291
292 _fds = new_fds;
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)
298 {
299 DEBUGF("ERROR %s: realloc for _device_names failed.", __func__);
300 exit(-1);
301 }
302
303 _device_names = new_device_names;
304 _device_names[_nfds] = strdup(device_name);
305 if(_device_names[_nfds] == NULL)
306 {
307 DEBUGF("ERROR %s: strdup failed.", __func__);
308 exit(-1);
309 }
310
311 ++_nfds;
312
313 DEBUGF("DEBUG %s: Opened device %s.", __func__, device_name);
314}
315
316
317static void button_init_device(void)
318{
319 TRACE;
320
321 if((_fds != NULL) || (_nfds != 0) || (_device_names != NULL))
322 {
323 DEBUGF("ERROR %s: Allready initialized.", __func__);
324 return;
325 }
326
327 /* The input device directory. */
328 static const char device_path[] = "/dev/input";
329
330 /* Path delimeter. */
331 static const char delimeter[] = "/";
332
333 /* Open all devices in device_path. */
334 DIR* dir = opendir(device_path);
335 if(dir == NULL)
336 {
337 DEBUGF("ERROR %s: opendir failed: errno: %d.", __func__, errno);
338 exit(errno);
339 }
340
341 char device_name[PATH_MAX];
342 strcpy(device_name, device_path);
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;
353 }
354
355 strcpy(device_name_idx, dir_entry->d_name);
356
357 /* Open and add device to _fds. */
358 open_device(device_name);
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 }
369}
370
371
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
387{
388 CHOICE_NONE = -1,
389 CHOICE_MANGO,
390 CHOICE_ROCKBOX,
391 CHOICE_POWEROFF
392};
393
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)
404 {
405 /* Poll all input devices. */
406 poll(_fds, _nfds, 0);
407
408 nfds_t fds_idx = 0;
409 for( ; fds_idx < _nfds; ++fds_idx)
410 {
411 if(! (_fds[fds_idx].revents & POLLIN))
412 {
413 continue;
414 }
415
416 struct input_event event;
417 if(read(_fds[fds_idx].fd, &event, sizeof(event)) < (int) sizeof(event))
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)
428 {
429 case EVENT_CODE_BUTTON_REV:
430 {
431 choice = CHOICE_MANGO;
432 break;
433 }
434
435 case EVENT_CODE_BUTTON_NEXT:
436 {
437 choice = CHOICE_ROCKBOX;
438 break;
439 }
440
441 case EVENT_CODE_BUTTON_PWR_LONG:
442 {
443 choice = CHOICE_POWEROFF;
444 break;
445 }
446 }
447 }
448 else if((event.type == EVENT_TYPE_TOUCHSCREEN) && (event.code == EVENT_CODE_TOUCHSCREEN_X))
449 {
450 if(event.value < 160)
451 {
452 choice = CHOICE_MANGO;
453 }
454 else
455 {
456 choice = CHOICE_ROCKBOX;
457 }
458 }
459 }
460 }
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;
487}
488
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)
498{
499 TRACE;
500
501 char hold_state;
502
503 FILE* f = fopen("/sys/class/axppower/holdkey", "r");
504 fscanf(f, "%c", &hold_state);
505 fclose(f);
506
507 return(! (hold_state & HOLD_SWITCH_BIT));
508}
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
626int main(int argc, char **argv)
627{
628 TRACE;
629
630 /*
631 Create the iBasso Vold socket and monitor it.
632 Do this early to not block Vold.
633 */
634 vold_monitor_start();
635
636 int last_chosen_player = CHOICE_NONE;
637
638 FILE* f = fopen(PLAYER_FILE, "r");
639 if(f != NULL)
640 {
641 fscanf(f, "%d", &last_chosen_player);
642 fclose(f);
643 }
644
645 DEBUGF("DEBUG %s: Current player choice: %d.", __func__, last_chosen_player);
646
647 if(check_for_hold() || (last_chosen_player == CHOICE_NONE))
648 {
649 draw("/system/chooser.bmp");
650
651 enum user_choice choice = get_user_choice();
652
653 if(choice == CHOICE_POWEROFF)
654 {
655 reboot(RB_POWER_OFF);
656 while(true)
657 {
658 sleep(1);
659 }
660 }
661
662 if(choice != last_chosen_player)
663 {
664 last_chosen_player = choice;
665
666 f = fopen(PLAYER_FILE, "w");
667 fprintf(f, "%d", last_chosen_player);
668 fclose(f);
669 }
670
671 DEBUGF("DEBUG %s: New player choice: %d.", __func__, last_chosen_player);
672 }
673
674 /* true, Rockbox was started at least once. */
675 bool rockboxStarted = false;
676
677 while(true)
678 {
679 /* Excecute OF MangoPlayer or Rockbox and restart it if it crashes. */
680
681 if(last_chosen_player == CHOICE_ROCKBOX)
682 {
683 if(rockboxStarted)
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 }
757 }
758 else /* if(last_chosen_player == CHOICE_MANGO) */
759 {
760 vold_monitor_stop();
761
762 DEBUGF("DEBUG %s: Excecuting %s.", __func__, OF_PLAYER_BIN);
763
764 int ret_code = system(OF_PLAYER_BIN);
765
766 DEBUGF("DEBUG %s: ret_code: %d.", __func__, ret_code);
767 }
768 }
769
770 return 0;
771}
diff --git a/utils/ibassoboot/jni/qdbmp.c b/utils/ibassoboot/jni/qdbmp.c
new file mode 100644
index 0000000000..fd1337277d
--- /dev/null
+++ b/utils/ibassoboot/jni/qdbmp.c
@@ -0,0 +1,798 @@
1#include "qdbmp.h"
2#include <stdlib.h>
3#include <string.h>
4
5
6/* Bitmap header */
7typedef struct _BMP_Header
8{
9 USHORT Magic; /* Magic identifier: "BM" */
10 UINT FileSize; /* Size of the BMP file in bytes */
11 USHORT Reserved1; /* Reserved */
12 USHORT Reserved2; /* Reserved */
13 UINT DataOffset; /* Offset of image data relative to the file's start */
14 UINT HeaderSize; /* Size of the header in bytes */
15 UINT Width; /* Bitmap's width */
16 UINT Height; /* Bitmap's height */
17 USHORT Planes; /* Number of color planes in the bitmap */
18 USHORT BitsPerPixel; /* Number of bits per pixel */
19 UINT CompressionType; /* Compression type */
20 UINT ImageDataSize; /* Size of uncompressed image's data */
21 UINT HPixelsPerMeter; /* Horizontal resolution (pixels per meter) */
22 UINT VPixelsPerMeter; /* Vertical resolution (pixels per meter) */
23 UINT ColorsUsed; /* Number of color indexes in the color table that are actually used by the bitmap */
24 UINT ColorsRequired; /* Number of color indexes that are required for displaying the bitmap */
25} BMP_Header;
26
27
28/* Private data structure */
29struct _BMP
30{
31 BMP_Header Header;
32 UCHAR* Palette;
33 UCHAR* Data;
34};
35
36
37/* Holds the last error code */
38static BMP_STATUS BMP_LAST_ERROR_CODE = 0;
39
40
41/* Error description strings */
42static const char* BMP_ERROR_STRING[] =
43{
44 "",
45 "General error",
46 "Could not allocate enough memory to complete the operation",
47 "File input/output error",
48 "File not found",
49 "File is not a supported BMP variant (must be uncompressed 8, 24 or 32 BPP)",
50 "File is not a valid BMP image",
51 "An argument is invalid or out of range",
52 "The requested action is not compatible with the BMP's type"
53};
54
55
56/* Size of the palette data for 8 BPP bitmaps */
57#define BMP_PALETTE_SIZE ( 256 * 4 )
58
59
60
61/*********************************** Forward declarations **********************************/
62int ReadHeader ( BMP* bmp, FILE* f );
63int WriteHeader ( BMP* bmp, FILE* f );
64
65int ReadUINT ( UINT* x, FILE* f );
66int ReadUSHORT ( USHORT *x, FILE* f );
67
68int WriteUINT ( UINT x, FILE* f );
69int WriteUSHORT ( USHORT x, FILE* f );
70
71
72
73
74
75
76/*********************************** Public methods **********************************/
77
78
79/**************************************************************
80 Creates a blank BMP image with the specified dimensions
81 and bit depth.
82**************************************************************/
83BMP* BMP_Create( UINT width, UINT height, USHORT depth )
84{
85 BMP* bmp;
86 int bytes_per_pixel = depth >> 3;
87 UINT bytes_per_row;
88
89 if ( height <= 0 || width <= 0 )
90 {
91 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
92 return NULL;
93 }
94
95 if ( depth != 8 && depth != 24 && depth != 32 )
96 {
97 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
98 return NULL;
99 }
100
101
102 /* Allocate the bitmap data structure */
103 bmp = calloc( 1, sizeof( BMP ) );
104 if ( bmp == NULL )
105 {
106 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
107 return NULL;
108 }
109
110
111 /* Set header' default values */
112 bmp->Header.Magic = 0x4D42;
113 bmp->Header.Reserved1 = 0;
114 bmp->Header.Reserved2 = 0;
115 bmp->Header.HeaderSize = 40;
116 bmp->Header.Planes = 1;
117 bmp->Header.CompressionType = 0;
118 bmp->Header.HPixelsPerMeter = 0;
119 bmp->Header.VPixelsPerMeter = 0;
120 bmp->Header.ColorsUsed = 0;
121 bmp->Header.ColorsRequired = 0;
122
123
124 /* Calculate the number of bytes used to store a single image row. This is always
125 rounded up to the next multiple of 4. */
126 bytes_per_row = width * bytes_per_pixel;
127 bytes_per_row += ( bytes_per_row % 4 ? 4 - bytes_per_row % 4 : 0 );
128
129
130 /* Set header's image specific values */
131 bmp->Header.Width = width;
132 bmp->Header.Height = height;
133 bmp->Header.BitsPerPixel = depth;
134 bmp->Header.ImageDataSize = bytes_per_row * height;
135 bmp->Header.FileSize = bmp->Header.ImageDataSize + 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
136 bmp->Header.DataOffset = 54 + ( depth == 8 ? BMP_PALETTE_SIZE : 0 );
137
138
139 /* Allocate palette */
140 if ( bmp->Header.BitsPerPixel == 8 )
141 {
142 bmp->Palette = (UCHAR*) calloc( BMP_PALETTE_SIZE, sizeof( UCHAR ) );
143 if ( bmp->Palette == NULL )
144 {
145 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
146 free( bmp );
147 return NULL;
148 }
149 }
150 else
151 {
152 bmp->Palette = NULL;
153 }
154
155
156 /* Allocate pixels */
157 bmp->Data = (UCHAR*) calloc( bmp->Header.ImageDataSize, sizeof( UCHAR ) );
158 if ( bmp->Data == NULL )
159 {
160 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
161 free( bmp->Palette );
162 free( bmp );
163 return NULL;
164 }
165
166
167 BMP_LAST_ERROR_CODE = BMP_OK;
168
169 return bmp;
170}
171
172
173/**************************************************************
174 Frees all the memory used by the specified BMP image.
175**************************************************************/
176void BMP_Free( BMP* bmp )
177{
178 if ( bmp == NULL )
179 {
180 return;
181 }
182
183 if ( bmp->Palette != NULL )
184 {
185 free( bmp->Palette );
186 }
187
188 if ( bmp->Data != NULL )
189 {
190 free( bmp->Data );
191 }
192
193 free( bmp );
194
195 BMP_LAST_ERROR_CODE = BMP_OK;
196}
197
198
199/**************************************************************
200 Reads the specified BMP image file.
201**************************************************************/
202BMP* BMP_ReadFile( const char* filename )
203{
204 BMP* bmp;
205 FILE* f;
206
207 if ( filename == NULL )
208 {
209 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
210 return NULL;
211 }
212
213
214 /* Allocate */
215 bmp = calloc( 1, sizeof( BMP ) );
216 if ( bmp == NULL )
217 {
218 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
219 return NULL;
220 }
221
222
223 /* Open file */
224 f = fopen( filename, "rb" );
225 if ( f == NULL )
226 {
227 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
228 free( bmp );
229 return NULL;
230 }
231
232
233 /* Read header */
234 if ( ReadHeader( bmp, f ) != BMP_OK || bmp->Header.Magic != 0x4D42 )
235 {
236 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
237 fclose( f );
238 free( bmp );
239 return NULL;
240 }
241
242
243 /* Verify that the bitmap variant is supported */
244 if ( ( bmp->Header.BitsPerPixel != 32 && bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 8 )
245 || bmp->Header.CompressionType != 0 || bmp->Header.HeaderSize != 40 )
246 {
247 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_SUPPORTED;
248 fclose( f );
249 free( bmp );
250 return NULL;
251 }
252
253
254 /* Allocate and read palette */
255 if ( bmp->Header.BitsPerPixel == 8 )
256 {
257 bmp->Palette = (UCHAR*) malloc( BMP_PALETTE_SIZE * sizeof( UCHAR ) );
258 if ( bmp->Palette == NULL )
259 {
260 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
261 fclose( f );
262 free( bmp );
263 return NULL;
264 }
265
266 if ( fread( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
267 {
268 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
269 fclose( f );
270 free( bmp->Palette );
271 free( bmp );
272 return NULL;
273 }
274 }
275 else /* Not an indexed image */
276 {
277 bmp->Palette = NULL;
278 }
279
280
281 /* Allocate memory for image data */
282 bmp->Data = (UCHAR*) malloc( bmp->Header.ImageDataSize );
283 if ( bmp->Data == NULL )
284 {
285 BMP_LAST_ERROR_CODE = BMP_OUT_OF_MEMORY;
286 fclose( f );
287 free( bmp->Palette );
288 free( bmp );
289 return NULL;
290 }
291
292
293 /* Read image data */
294 if ( fread( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
295 {
296 BMP_LAST_ERROR_CODE = BMP_FILE_INVALID;
297 fclose( f );
298 free( bmp->Data );
299 free( bmp->Palette );
300 free( bmp );
301 return NULL;
302 }
303
304
305 fclose( f );
306
307 BMP_LAST_ERROR_CODE = BMP_OK;
308
309 return bmp;
310}
311
312
313/**************************************************************
314 Writes the BMP image to the specified file.
315**************************************************************/
316void BMP_WriteFile( BMP* bmp, const char* filename )
317{
318 FILE* f;
319
320 if ( filename == NULL )
321 {
322 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
323 return;
324 }
325
326
327 /* Open file */
328 f = fopen( filename, "wb" );
329 if ( f == NULL )
330 {
331 BMP_LAST_ERROR_CODE = BMP_FILE_NOT_FOUND;
332 return;
333 }
334
335
336 /* Write header */
337 if ( WriteHeader( bmp, f ) != BMP_OK )
338 {
339 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
340 fclose( f );
341 return;
342 }
343
344
345 /* Write palette */
346 if ( bmp->Palette )
347 {
348 if ( fwrite( bmp->Palette, sizeof( UCHAR ), BMP_PALETTE_SIZE, f ) != BMP_PALETTE_SIZE )
349 {
350 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
351 fclose( f );
352 return;
353 }
354 }
355
356
357 /* Write data */
358 if ( fwrite( bmp->Data, sizeof( UCHAR ), bmp->Header.ImageDataSize, f ) != bmp->Header.ImageDataSize )
359 {
360 BMP_LAST_ERROR_CODE = BMP_IO_ERROR;
361 fclose( f );
362 return;
363 }
364
365
366 BMP_LAST_ERROR_CODE = BMP_OK;
367 fclose( f );
368}
369
370
371/**************************************************************
372 Returns the image's width.
373**************************************************************/
374UINT BMP_GetWidth( BMP* bmp )
375{
376 if ( bmp == NULL )
377 {
378 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
379 return -1;
380 }
381
382 BMP_LAST_ERROR_CODE = BMP_OK;
383
384 return ( bmp->Header.Width );
385}
386
387
388/**************************************************************
389 Returns the image's height.
390**************************************************************/
391UINT BMP_GetHeight( BMP* bmp )
392{
393 if ( bmp == NULL )
394 {
395 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
396 return -1;
397 }
398
399 BMP_LAST_ERROR_CODE = BMP_OK;
400
401 return ( bmp->Header.Height );
402}
403
404
405/**************************************************************
406 Returns the image's color depth (bits per pixel).
407**************************************************************/
408USHORT BMP_GetDepth( BMP* bmp )
409{
410 if ( bmp == NULL )
411 {
412 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
413 return -1;
414 }
415
416 BMP_LAST_ERROR_CODE = BMP_OK;
417
418 return ( bmp->Header.BitsPerPixel );
419}
420
421
422/**************************************************************
423 Populates the arguments with the specified pixel's RGB
424 values.
425**************************************************************/
426void BMP_GetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b )
427{
428 UCHAR* pixel;
429 UINT bytes_per_row;
430 UCHAR bytes_per_pixel;
431
432 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
433 {
434 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
435 }
436 else
437 {
438 BMP_LAST_ERROR_CODE = BMP_OK;
439
440 bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
441
442 /* Row's size is rounded up to the next multiple of 4 bytes */
443 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
444
445 /* Calculate the location of the relevant pixel (rows are flipped) */
446 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
447
448
449 /* In indexed color mode the pixel's value is an index within the palette */
450 if ( bmp->Header.BitsPerPixel == 8 )
451 {
452 pixel = bmp->Palette + *pixel * 4;
453 }
454
455 /* Note: colors are stored in BGR order */
456 if ( r ) *r = *( pixel + 2 );
457 if ( g ) *g = *( pixel + 1 );
458 if ( b ) *b = *( pixel + 0 );
459 }
460}
461
462
463/**************************************************************
464 Sets the specified pixel's RGB values.
465**************************************************************/
466void BMP_SetPixelRGB( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b )
467{
468 UCHAR* pixel;
469 UINT bytes_per_row;
470 UCHAR bytes_per_pixel;
471
472 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
473 {
474 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
475 }
476
477 else if ( bmp->Header.BitsPerPixel != 24 && bmp->Header.BitsPerPixel != 32 )
478 {
479 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
480 }
481
482 else
483 {
484 BMP_LAST_ERROR_CODE = BMP_OK;
485
486 bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
487
488 /* Row's size is rounded up to the next multiple of 4 bytes */
489 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
490
491 /* Calculate the location of the relevant pixel (rows are flipped) */
492 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x * bytes_per_pixel );
493
494 /* Note: colors are stored in BGR order */
495 *( pixel + 2 ) = r;
496 *( pixel + 1 ) = g;
497 *( pixel + 0 ) = b;
498 }
499}
500
501
502/**************************************************************
503 Gets the specified pixel's color index.
504**************************************************************/
505void BMP_GetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR* val )
506{
507 UCHAR* pixel;
508 UINT bytes_per_row;
509
510 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
511 {
512 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
513 }
514
515 else if ( bmp->Header.BitsPerPixel != 8 )
516 {
517 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
518 }
519
520 else
521 {
522 BMP_LAST_ERROR_CODE = BMP_OK;
523
524 /* Row's size is rounded up to the next multiple of 4 bytes */
525 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
526
527 /* Calculate the location of the relevant pixel */
528 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
529
530
531 if ( val ) *val = *pixel;
532 }
533}
534
535
536/**************************************************************
537 Sets the specified pixel's color index.
538**************************************************************/
539void BMP_SetPixelIndex( BMP* bmp, UINT x, UINT y, UCHAR val )
540{
541 UCHAR* pixel;
542 UINT bytes_per_row;
543
544 if ( bmp == NULL || x < 0 || x >= bmp->Header.Width || y < 0 || y >= bmp->Header.Height )
545 {
546 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
547 }
548
549 else if ( bmp->Header.BitsPerPixel != 8 )
550 {
551 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
552 }
553
554 else
555 {
556 BMP_LAST_ERROR_CODE = BMP_OK;
557
558 /* Row's size is rounded up to the next multiple of 4 bytes */
559 bytes_per_row = bmp->Header.ImageDataSize / bmp->Header.Height;
560
561 /* Calculate the location of the relevant pixel */
562 pixel = bmp->Data + ( ( bmp->Header.Height - y - 1 ) * bytes_per_row + x );
563
564 *pixel = val;
565 }
566}
567
568
569/**************************************************************
570 Gets the color value for the specified palette index.
571**************************************************************/
572void BMP_GetPaletteColor( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b )
573{
574 if ( bmp == NULL )
575 {
576 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
577 }
578
579 else if ( bmp->Header.BitsPerPixel != 8 )
580 {
581 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
582 }
583
584 else
585 {
586 if ( r ) *r = *( bmp->Palette + index * 4 + 2 );
587 if ( g ) *g = *( bmp->Palette + index * 4 + 1 );
588 if ( b ) *b = *( bmp->Palette + index * 4 + 0 );
589
590 BMP_LAST_ERROR_CODE = BMP_OK;
591 }
592}
593
594
595/**************************************************************
596 Sets the color value for the specified palette index.
597**************************************************************/
598void BMP_SetPaletteColor( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b )
599{
600 if ( bmp == NULL )
601 {
602 BMP_LAST_ERROR_CODE = BMP_INVALID_ARGUMENT;
603 }
604
605 else if ( bmp->Header.BitsPerPixel != 8 )
606 {
607 BMP_LAST_ERROR_CODE = BMP_TYPE_MISMATCH;
608 }
609
610 else
611 {
612 *( bmp->Palette + index * 4 + 2 ) = r;
613 *( bmp->Palette + index * 4 + 1 ) = g;
614 *( bmp->Palette + index * 4 + 0 ) = b;
615
616 BMP_LAST_ERROR_CODE = BMP_OK;
617 }
618}
619
620
621/**************************************************************
622 Returns the last error code.
623**************************************************************/
624BMP_STATUS BMP_GetError()
625{
626 return BMP_LAST_ERROR_CODE;
627}
628
629
630/**************************************************************
631 Returns a description of the last error code.
632**************************************************************/
633const char* BMP_GetErrorDescription()
634{
635 if ( BMP_LAST_ERROR_CODE > 0 && BMP_LAST_ERROR_CODE < BMP_ERROR_NUM )
636 {
637 return BMP_ERROR_STRING[ BMP_LAST_ERROR_CODE ];
638 }
639 else
640 {
641 return NULL;
642 }
643}
644
645
646
647
648
649/*********************************** Private methods **********************************/
650
651
652/**************************************************************
653 Reads the BMP file's header into the data structure.
654 Returns BMP_OK on success.
655**************************************************************/
656int ReadHeader( BMP* bmp, FILE* f )
657{
658 if ( bmp == NULL || f == NULL )
659 {
660 return BMP_INVALID_ARGUMENT;
661 }
662
663 /* The header's fields are read one by one, and converted from the format's
664 little endian to the system's native representation. */
665 if ( !ReadUSHORT( &( bmp->Header.Magic ), f ) ) return BMP_IO_ERROR;
666 if ( !ReadUINT( &( bmp->Header.FileSize ), f ) ) return BMP_IO_ERROR;
667 if ( !ReadUSHORT( &( bmp->Header.Reserved1 ), f ) ) return BMP_IO_ERROR;
668 if ( !ReadUSHORT( &( bmp->Header.Reserved2 ), f ) ) return BMP_IO_ERROR;
669 if ( !ReadUINT( &( bmp->Header.DataOffset ), f ) ) return BMP_IO_ERROR;
670 if ( !ReadUINT( &( bmp->Header.HeaderSize ), f ) ) return BMP_IO_ERROR;
671 if ( !ReadUINT( &( bmp->Header.Width ), f ) ) return BMP_IO_ERROR;
672 if ( !ReadUINT( &( bmp->Header.Height ), f ) ) return BMP_IO_ERROR;
673 if ( !ReadUSHORT( &( bmp->Header.Planes ), f ) ) return BMP_IO_ERROR;
674 if ( !ReadUSHORT( &( bmp->Header.BitsPerPixel ), f ) ) return BMP_IO_ERROR;
675 if ( !ReadUINT( &( bmp->Header.CompressionType ), f ) ) return BMP_IO_ERROR;
676 if ( !ReadUINT( &( bmp->Header.ImageDataSize ), f ) ) return BMP_IO_ERROR;
677 if ( !ReadUINT( &( bmp->Header.HPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
678 if ( !ReadUINT( &( bmp->Header.VPixelsPerMeter ), f ) ) return BMP_IO_ERROR;
679 if ( !ReadUINT( &( bmp->Header.ColorsUsed ), f ) ) return BMP_IO_ERROR;
680 if ( !ReadUINT( &( bmp->Header.ColorsRequired ), f ) ) return BMP_IO_ERROR;
681
682 return BMP_OK;
683}
684
685
686/**************************************************************
687 Writes the BMP file's header into the data structure.
688 Returns BMP_OK on success.
689**************************************************************/
690int WriteHeader( BMP* bmp, FILE* f )
691{
692 if ( bmp == NULL || f == NULL )
693 {
694 return BMP_INVALID_ARGUMENT;
695 }
696
697 /* The header's fields are written one by one, and converted to the format's
698 little endian representation. */
699 if ( !WriteUSHORT( bmp->Header.Magic, f ) ) return BMP_IO_ERROR;
700 if ( !WriteUINT( bmp->Header.FileSize, f ) ) return BMP_IO_ERROR;
701 if ( !WriteUSHORT( bmp->Header.Reserved1, f ) ) return BMP_IO_ERROR;
702 if ( !WriteUSHORT( bmp->Header.Reserved2, f ) ) return BMP_IO_ERROR;
703 if ( !WriteUINT( bmp->Header.DataOffset, f ) ) return BMP_IO_ERROR;
704 if ( !WriteUINT( bmp->Header.HeaderSize, f ) ) return BMP_IO_ERROR;
705 if ( !WriteUINT( bmp->Header.Width, f ) ) return BMP_IO_ERROR;
706 if ( !WriteUINT( bmp->Header.Height, f ) ) return BMP_IO_ERROR;
707 if ( !WriteUSHORT( bmp->Header.Planes, f ) ) return BMP_IO_ERROR;
708 if ( !WriteUSHORT( bmp->Header.BitsPerPixel, f ) ) return BMP_IO_ERROR;
709 if ( !WriteUINT( bmp->Header.CompressionType, f ) ) return BMP_IO_ERROR;
710 if ( !WriteUINT( bmp->Header.ImageDataSize, f ) ) return BMP_IO_ERROR;
711 if ( !WriteUINT( bmp->Header.HPixelsPerMeter, f ) ) return BMP_IO_ERROR;
712 if ( !WriteUINT( bmp->Header.VPixelsPerMeter, f ) ) return BMP_IO_ERROR;
713 if ( !WriteUINT( bmp->Header.ColorsUsed, f ) ) return BMP_IO_ERROR;
714 if ( !WriteUINT( bmp->Header.ColorsRequired, f ) ) return BMP_IO_ERROR;
715
716 return BMP_OK;
717}
718
719
720/**************************************************************
721 Reads a little-endian unsigned int from the file.
722 Returns non-zero on success.
723**************************************************************/
724int ReadUINT( UINT* x, FILE* f )
725{
726 UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
727
728 if ( x == NULL || f == NULL )
729 {
730 return 0;
731 }
732
733 if ( fread( little, 4, 1, f ) != 1 )
734 {
735 return 0;
736 }
737
738 *x = ( little[ 3 ] << 24 | little[ 2 ] << 16 | little[ 1 ] << 8 | little[ 0 ] );
739
740 return 1;
741}
742
743
744/**************************************************************
745 Reads a little-endian unsigned short int from the file.
746 Returns non-zero on success.
747**************************************************************/
748int ReadUSHORT( USHORT *x, FILE* f )
749{
750 UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
751
752 if ( x == NULL || f == NULL )
753 {
754 return 0;
755 }
756
757 if ( fread( little, 2, 1, f ) != 1 )
758 {
759 return 0;
760 }
761
762 *x = ( little[ 1 ] << 8 | little[ 0 ] );
763
764 return 1;
765}
766
767
768/**************************************************************
769 Writes a little-endian unsigned int to the file.
770 Returns non-zero on success.
771**************************************************************/
772int WriteUINT( UINT x, FILE* f )
773{
774 UCHAR little[ 4 ]; /* BMPs use 32 bit ints */
775
776 little[ 3 ] = (UCHAR)( ( x & 0xff000000 ) >> 24 );
777 little[ 2 ] = (UCHAR)( ( x & 0x00ff0000 ) >> 16 );
778 little[ 1 ] = (UCHAR)( ( x & 0x0000ff00 ) >> 8 );
779 little[ 0 ] = (UCHAR)( ( x & 0x000000ff ) >> 0 );
780
781 return ( f && fwrite( little, 4, 1, f ) == 1 );
782}
783
784
785/**************************************************************
786 Writes a little-endian unsigned short int to the file.
787 Returns non-zero on success.
788**************************************************************/
789int WriteUSHORT( USHORT x, FILE* f )
790{
791 UCHAR little[ 2 ]; /* BMPs use 16 bit shorts */
792
793 little[ 1 ] = (UCHAR)( ( x & 0xff00 ) >> 8 );
794 little[ 0 ] = (UCHAR)( ( x & 0x00ff ) >> 0 );
795
796 return ( f && fwrite( little, 2, 1, f ) == 1 );
797}
798
diff --git a/utils/ibassoboot/jni/qdbmp.h b/utils/ibassoboot/jni/qdbmp.h
new file mode 100644
index 0000000000..d6c0e6c452
--- /dev/null
+++ b/utils/ibassoboot/jni/qdbmp.h
@@ -0,0 +1,133 @@
1#ifndef _BMP_H_
2#define _BMP_H_
3
4
5/**************************************************************
6
7 QDBMP - Quick n' Dirty BMP
8
9 v1.0.0 - 2007-04-07
10 http://qdbmp.sourceforge.net
11
12
13 The library supports the following BMP variants:
14 1. Uncompressed 32 BPP (alpha values are ignored)
15 2. Uncompressed 24 BPP
16 3. Uncompressed 8 BPP (indexed color)
17
18 QDBMP is free and open source software, distributed
19 under the MIT licence.
20
21 Copyright (c) 2007 Chai Braudo (braudo@users.sourceforge.net)
22
23 Permission is hereby granted, free of charge, to any person obtaining a copy
24 of this software and associated documentation files (the "Software"), to deal
25 in the Software without restriction, including without limitation the rights
26 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
27 copies of the Software, and to permit persons to whom the Software is
28 furnished to do so, subject to the following conditions:
29
30 The above copyright notice and this permission notice shall be included in
31 all copies or substantial portions of the Software.
32
33 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
39 THE SOFTWARE.
40
41**************************************************************/
42
43#include <stdio.h>
44
45
46
47/* Type definitions */
48#ifndef UINT
49 #define UINT unsigned long int
50#endif
51
52#ifndef USHORT
53 #define USHORT unsigned short
54#endif
55
56#ifndef UCHAR
57 #define UCHAR unsigned char
58#endif
59
60
61/* Version */
62#define QDBMP_VERSION_MAJOR 1
63#define QDBMP_VERSION_MINOR 0
64#define QDBMP_VERSION_PATCH 1
65
66
67/* Error codes */
68typedef enum
69{
70 BMP_OK = 0, /* No error */
71 BMP_ERROR, /* General error */
72 BMP_OUT_OF_MEMORY, /* Could not allocate enough memory to complete the operation */
73 BMP_IO_ERROR, /* General input/output error */
74 BMP_FILE_NOT_FOUND, /* File not found */
75 BMP_FILE_NOT_SUPPORTED, /* File is not a supported BMP variant */
76 BMP_FILE_INVALID, /* File is not a BMP image or is an invalid BMP */
77 BMP_INVALID_ARGUMENT, /* An argument is invalid or out of range */
78 BMP_TYPE_MISMATCH, /* The requested action is not compatible with the BMP's type */
79 BMP_ERROR_NUM
80} BMP_STATUS;
81
82
83/* Bitmap image */
84typedef struct _BMP BMP;
85
86
87
88
89/*********************************** Public methods **********************************/
90
91
92/* Construction/destruction */
93BMP* BMP_Create ( UINT width, UINT height, USHORT depth );
94void BMP_Free ( BMP* bmp );
95
96
97/* I/O */
98BMP* BMP_ReadFile ( const char* filename );
99void BMP_WriteFile ( BMP* bmp, const char* filename );
100
101
102/* Meta info */
103UINT BMP_GetWidth ( BMP* bmp );
104UINT BMP_GetHeight ( BMP* bmp );
105USHORT BMP_GetDepth ( BMP* bmp );
106
107
108/* Pixel access */
109void BMP_GetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR* r, UCHAR* g, UCHAR* b );
110void BMP_SetPixelRGB ( BMP* bmp, UINT x, UINT y, UCHAR r, UCHAR g, UCHAR b );
111void BMP_GetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR* val );
112void BMP_SetPixelIndex ( BMP* bmp, UINT x, UINT y, UCHAR val );
113
114
115/* Palette handling */
116void BMP_GetPaletteColor ( BMP* bmp, UCHAR index, UCHAR* r, UCHAR* g, UCHAR* b );
117void BMP_SetPaletteColor ( BMP* bmp, UCHAR index, UCHAR r, UCHAR g, UCHAR b );
118
119
120/* Error handling */
121BMP_STATUS BMP_GetError ();
122const char* BMP_GetErrorDescription ();
123
124
125/* Useful macro that may be used after each BMP operation to check for an error */
126#define BMP_CHECK_ERROR( output_file, return_value ) \
127 if ( BMP_GetError() != BMP_OK ) \
128 { \
129 fprintf( ( output_file ), "BMP error: %s\n", BMP_GetErrorDescription() ); \
130 return( return_value ); \
131 } \
132
133#endif
diff --git a/utils/ibassoboot/jni/rbmissing.bmp b/utils/ibassoboot/jni/rbmissing.bmp
new file mode 100644
index 0000000000..1e97066d8c
--- /dev/null
+++ b/utils/ibassoboot/jni/rbmissing.bmp
Binary files differ
diff --git a/utils/ibassoboot/jni/usb.bmp b/utils/ibassoboot/jni/usb.bmp
new file mode 100644
index 0000000000..c462de2236
--- /dev/null
+++ b/utils/ibassoboot/jni/usb.bmp
Binary files differ