diff options
Diffstat (limited to 'rbutil/ibassoboot/jni/ibassodualboot.c')
-rw-r--r-- | rbutil/ibassoboot/jni/ibassodualboot.c | 439 |
1 files changed, 439 insertions, 0 deletions
diff --git a/rbutil/ibassoboot/jni/ibassodualboot.c b/rbutil/ibassoboot/jni/ibassodualboot.c new file mode 100644 index 0000000000..3f20bbeecf --- /dev/null +++ b/rbutil/ibassoboot/jni/ibassodualboot.c | |||
@@ -0,0 +1,439 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2014 by Ilia Sergachev | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | |||
22 | #include <dirent.h> | ||
23 | #include <errno.h> | ||
24 | #include <fcntl.h> | ||
25 | |||
26 | #include <linux/fb.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/reboot.h> | ||
29 | |||
30 | #include <stdbool.h> | ||
31 | #include <string.h> | ||
32 | #include <stdint.h> | ||
33 | #include <stdio.h> | ||
34 | #include <stdlib.h> | ||
35 | |||
36 | #include <time.h> | ||
37 | |||
38 | #include <sys/limits.h> | ||
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 | |||
47 | #include <unistd.h> | ||
48 | |||
49 | #include "qdbmp.h" | ||
50 | |||
51 | |||
52 | #define MIN_TIME 1395606821 | ||
53 | #define TIME_FILE "/data/time_store" | ||
54 | #define TIME_CHECK_PERIOD 60 /* seconds */ | ||
55 | #define VOLD_LINK "/data/vold" | ||
56 | #define PLAYER_FILE "/data/chosen_player" | ||
57 | #define NOASK_FLAG "/data/no_ask_once" | ||
58 | #define POLL_MS 10 | ||
59 | |||
60 | |||
61 | #define KEYCODE_HEADPHONES 114 | ||
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 | |||
72 | #define KEY_HOLD_OFF 16 | ||
73 | |||
74 | void checktime() | ||
75 | { | ||
76 | time_t t_stored=0, t_current=time(NULL); | ||
77 | |||
78 | FILE *f = fopen(TIME_FILE, "r"); | ||
79 | if(f!=NULL) | ||
80 | { | ||
81 | fscanf(f, "%ld", &t_stored); | ||
82 | fclose(f); | ||
83 | } | ||
84 | |||
85 | printf("stored time: %ld, current time: %ld\n", t_stored, t_current); | ||
86 | |||
87 | if(t_stored<MIN_TIME) | ||
88 | t_stored=MIN_TIME; | ||
89 | |||
90 | if(t_stored<t_current) | ||
91 | { | ||
92 | f = fopen(TIME_FILE, "w"); | ||
93 | fprintf(f, "%ld", t_current); | ||
94 | fclose(f); | ||
95 | } | ||
96 | else | ||
97 | { | ||
98 | t_stored += TIME_CHECK_PERIOD; | ||
99 | struct tm *t = localtime(&t_stored); | ||
100 | struct timeval tv = {mktime(t), 0}; | ||
101 | settimeofday(&tv, 0); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | |||
106 | static struct pollfd *ufds; | ||
107 | static char **device_names; | ||
108 | static int nfds; | ||
109 | |||
110 | |||
111 | |||
112 | static int open_device(const char *device, int print_flags) | ||
113 | { | ||
114 | int fd; | ||
115 | struct pollfd *new_ufds; | ||
116 | char **new_device_names; | ||
117 | |||
118 | fd = open(device, O_RDWR); | ||
119 | if(fd < 0) | ||
120 | { | ||
121 | fprintf(stderr, "could not open %s, %s\n", device, strerror(errno)); | ||
122 | return -1; | ||
123 | } | ||
124 | |||
125 | new_ufds = realloc(ufds, sizeof(ufds[0]) * (nfds + 1)); | ||
126 | if(new_ufds == NULL) | ||
127 | { | ||
128 | fprintf(stderr, "out of memory\n"); | ||
129 | return -1; | ||
130 | } | ||
131 | ufds = new_ufds; | ||
132 | new_device_names = realloc(device_names, sizeof(device_names[0]) * (nfds + 1)); | ||
133 | if(new_device_names == NULL) | ||
134 | { | ||
135 | fprintf(stderr, "out of memory\n"); | ||
136 | return -1; | ||
137 | } | ||
138 | device_names = new_device_names; | ||
139 | |||
140 | ufds[nfds].fd = fd; | ||
141 | ufds[nfds].events = POLLIN; | ||
142 | device_names[nfds] = strdup(device); | ||
143 | nfds++; | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | |||
149 | |||
150 | static int scan_dir(const char *dirname, int print_flags) | ||
151 | { | ||
152 | char devname[PATH_MAX]; | ||
153 | char *filename; | ||
154 | DIR *dir; | ||
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 | { | ||
164 | if(de->d_name[0] == '.' && | ||
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 | } | ||
171 | closedir(dir); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | |||
176 | |||
177 | void button_init_device(void) | ||
178 | { | ||
179 | int res; | ||
180 | int print_flags = 0; | ||
181 | const char *device = NULL; | ||
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 | { | ||
197 | res = inotify_add_watch(ufds[0].fd, device_path, IN_DELETE | IN_CREATE); | ||
198 | if(res < 0) | ||
199 | { | ||
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 | } | ||
208 | } | ||
209 | |||
210 | |||
211 | int draw() | ||
212 | { | ||
213 | int fbfd = 0; | ||
214 | struct fb_var_screeninfo vinfo; | ||
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 | { | ||
225 | perror("Error: cannot open framebuffer device"); | ||
226 | exit(1); | ||
227 | } | ||
228 | /* Get fixed screen information */ | ||
229 | if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo) == -1) | ||
230 | { | ||
231 | perror("Error reading fixed information"); | ||
232 | exit(2); | ||
233 | } | ||
234 | |||
235 | /* Get variable screen information */ | ||
236 | if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo) == -1) | ||
237 | { | ||
238 | perror("Error reading variable information"); | ||
239 | exit(3); | ||
240 | } | ||
241 | |||
242 | /* Figure out the size of the screen in bytes */ | ||
243 | screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8; | ||
244 | |||
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 | { | ||
269 | perror("fbset(ioctl)"); | ||
270 | exit(4); | ||
271 | } | ||
272 | |||
273 | |||
274 | /* Map the device to memory */ | ||
275 | fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, | ||
276 | fbfd, 0); | ||
277 | if ((int)fbp == -1) | ||
278 | { | ||
279 | perror("Error: failed to map framebuffer device to memory"); | ||
280 | exit(4); | ||
281 | } | ||
282 | |||
283 | BMP* bmp = BMP_ReadFile("/system/rockbox/chooser.bmp"); | ||
284 | BMP_CHECK_ERROR( stderr, -1 ); | ||
285 | |||
286 | UCHAR r, g, b; | ||
287 | unsigned short int t; | ||
288 | |||
289 | for (y = 0; y < 240; y++) | ||
290 | for (x = 0; x < 320; x++) | ||
291 | { | ||
292 | location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) + | ||
293 | (y+vinfo.yoffset) * finfo.line_length; | ||
294 | |||
295 | BMP_GetPixelRGB(bmp, x, y, &r, &g, &b); | ||
296 | t = (r>>3)<<11 | (g>>2) << 5 | (b>>3); | ||
297 | *((unsigned short int*)(fbp + location)) = t; | ||
298 | } | ||
299 | |||
300 | BMP_Free( bmp ); | ||
301 | |||
302 | munmap(fbp, screensize); | ||
303 | close(fbfd); | ||
304 | return 0; | ||
305 | } | ||
306 | |||
307 | |||
308 | int choose_player() | ||
309 | { | ||
310 | int i; | ||
311 | int res; | ||
312 | struct input_event event; | ||
313 | |||
314 | while(true) | ||
315 | { | ||
316 | poll(ufds, nfds, POLL_MS); | ||
317 | for(i = 1; i < nfds; i++) | ||
318 | { | ||
319 | if(ufds[i].revents & POLLIN) | ||
320 | { | ||
321 | res = read(ufds[i].fd, &event, sizeof(event)); | ||
322 | if(res < (int)sizeof(event)) | ||
323 | { | ||
324 | fprintf(stderr, "could not get event\n"); | ||
325 | } | ||
326 | if(event.type==1) | ||
327 | { | ||
328 | if(event.code==KEYCODE_NEXT) | ||
329 | { | ||
330 | puts("rockbox!"); | ||
331 | return 1; | ||
332 | } | ||
333 | else if(event.code==KEYCODE_PREV) | ||
334 | { | ||
335 | puts("mango!"); | ||
336 | return 0; | ||
337 | } | ||
338 | else if(event.code==KEYCODE_PWR || event.code==KEYCODE_PWR_LONG) | ||
339 | { | ||
340 | reboot(LINUX_REBOOT_CMD_POWER_OFF); | ||
341 | } | ||
342 | } | ||
343 | else if(event.type==3) | ||
344 | { | ||
345 | if(event.code==53) //x coord | ||
346 | { | ||
347 | if(event.value<160) | ||
348 | { | ||
349 | puts("mango!"); | ||
350 | return 0; | ||
351 | } | ||
352 | else | ||
353 | { | ||
354 | puts("rockbox!"); | ||
355 | return 1; | ||
356 | } | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | return true; | ||
363 | } | ||
364 | |||
365 | bool check_for_hold() | ||
366 | { | ||
367 | FILE *f = fopen("/sys/class/axppower/holdkey", "r"); | ||
368 | char x; | ||
369 | fscanf(f, "%c", &x); | ||
370 | fclose(f); | ||
371 | |||
372 | if(x & KEY_HOLD_OFF) | ||
373 | return false; | ||
374 | else | ||
375 | return true; | ||
376 | } | ||
377 | |||
378 | int main(int argc, char **argv) | ||
379 | { | ||
380 | FILE *f; | ||
381 | int last_chosen_player = -1; | ||
382 | |||
383 | f = fopen(PLAYER_FILE, "r"); | ||
384 | if(f!=NULL) | ||
385 | { | ||
386 | fscanf(f, "%d", &last_chosen_player); | ||
387 | fclose(f); | ||
388 | } | ||
389 | bool ask = (access(VOLD_LINK, F_OK) == -1) || ((access(NOASK_FLAG, F_OK) == -1) && check_for_hold()) || (last_chosen_player==-1); | ||
390 | |||
391 | if(ask) | ||
392 | { | ||
393 | draw(); | ||
394 | button_init_device(); | ||
395 | int player_chosen_now = choose_player(); | ||
396 | |||
397 | if(last_chosen_player!=player_chosen_now) | ||
398 | { | ||
399 | f = fopen(PLAYER_FILE, "w"); | ||
400 | fprintf(f, "%d", player_chosen_now); | ||
401 | fclose(f); | ||
402 | } | ||
403 | |||
404 | if(last_chosen_player!=player_chosen_now || (access(VOLD_LINK, F_OK) == -1)) | ||
405 | { | ||
406 | system("rm "VOLD_LINK); | ||
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 | |||
413 | system("touch "NOASK_FLAG); | ||
414 | system("reboot"); | ||
415 | } | ||
416 | last_chosen_player = player_chosen_now; | ||
417 | } | ||
418 | |||
419 | system("rm "NOASK_FLAG); | ||
420 | |||
421 | while(1) | ||
422 | { | ||
423 | if(last_chosen_player) | ||
424 | { | ||
425 | // system("/system/bin/openadb"); | ||
426 | system("/system/rockbox/lib/rockbox"); | ||
427 | } | ||
428 | else | ||
429 | // system("/system/bin/closeadb"); | ||
430 | system("/system/bin/MangoPlayer_original"); | ||
431 | |||
432 | sleep(1); | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | } | ||
437 | |||
438 | |||
439 | |||