Add platform file for Ipod 1G / 2G. Now only the front image is missing for building...
[Rockbox.git] / apps / plugin.c
blobfee3a518512d1192ba0e437f0ed9bf24f8821ee5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Björn Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
19 #include "plugin.h"
20 #include <ctype.h>
21 #include <string.h>
22 #include <sprintf.h>
23 #include <atoi.h>
24 #include "debug.h"
25 #include "i2c.h"
26 #include "lang.h"
27 #include "led.h"
28 #include "keyboard.h"
29 #include "buffer.h"
30 #include "backlight.h"
31 #include "sound_menu.h"
32 #include "mp3data.h"
33 #include "powermgmt.h"
34 #include "splash.h"
35 #include "logf.h"
36 #include "option_select.h"
38 #if CONFIG_CHARGING
39 #include "power.h"
40 #endif
42 #ifdef HAVE_LCD_BITMAP
43 #include "scrollbar.h"
44 #include "peakmeter.h"
45 #include "bmp.h"
46 #include "bidi.h"
47 #endif
49 #ifdef SIMULATOR
50 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
51 void *sim_plugin_load(char *plugin, void **pd);
52 void sim_plugin_close(void *pd);
53 void sim_lcd_ex_init(int shades, unsigned long (*getpixel)(int, int));
54 void sim_lcd_ex_update_rect(int x, int y, int width, int height);
55 #else
56 #define sim_plugin_close(x)
57 extern unsigned char pluginbuf[];
58 #include "bitswap.h"
59 #endif
61 /* for actual plugins only, not for codecs */
62 static bool plugin_loaded = false;
63 static int plugin_size = 0;
64 static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */
65 static char current_plugin[MAX_PATH];
67 extern struct thread_entry threads[MAXTHREADS];
69 static const struct plugin_api rockbox_api = {
71 /* lcd */
72 lcd_set_contrast,
73 lcd_update,
74 lcd_clear_display,
75 lcd_setmargins,
76 lcd_getstringsize,
77 lcd_putsxy,
78 lcd_puts,
79 lcd_puts_scroll,
80 lcd_stop_scroll,
81 #ifdef HAVE_LCD_CHARCELLS
82 lcd_define_pattern,
83 lcd_get_locked_pattern,
84 lcd_unlock_pattern,
85 lcd_putc,
86 lcd_put_cursor,
87 lcd_remove_cursor,
88 lcd_icon,
89 lcd_double_height,
90 #else
91 lcd_set_drawmode,
92 lcd_get_drawmode,
93 lcd_setfont,
94 lcd_drawpixel,
95 lcd_drawline,
96 lcd_hline,
97 lcd_vline,
98 lcd_drawrect,
99 lcd_fillrect,
100 lcd_mono_bitmap_part,
101 lcd_mono_bitmap,
102 #if LCD_DEPTH > 1
103 lcd_set_foreground,
104 lcd_get_foreground,
105 lcd_set_background,
106 lcd_get_background,
107 lcd_bitmap_part,
108 lcd_bitmap,
109 lcd_get_backdrop,
110 lcd_set_backdrop,
111 #endif
112 #if LCD_DEPTH == 16
113 lcd_bitmap_transparent_part,
114 lcd_bitmap_transparent,
115 #endif
116 bidi_l2v,
117 font_get_bits,
118 font_load,
119 lcd_puts_style,
120 lcd_puts_scroll_style,
121 &lcd_framebuffer[0][0],
122 lcd_blit,
123 lcd_update_rect,
124 gui_scrollbar_draw,
125 font_get,
126 font_getstringsize,
127 font_get_width,
128 #endif
129 backlight_on,
130 backlight_off,
131 backlight_set_timeout,
132 gui_syncsplash,
133 #ifdef HAVE_REMOTE_LCD
134 /* remote lcd */
135 lcd_remote_set_contrast,
136 lcd_remote_clear_display,
137 lcd_remote_puts,
138 lcd_remote_puts_scroll,
139 lcd_remote_stop_scroll,
140 lcd_remote_set_drawmode,
141 lcd_remote_get_drawmode,
142 lcd_remote_setfont,
143 lcd_remote_getstringsize,
144 lcd_remote_drawpixel,
145 lcd_remote_drawline,
146 lcd_remote_hline,
147 lcd_remote_vline,
148 lcd_remote_drawrect,
149 lcd_remote_fillrect,
150 lcd_remote_mono_bitmap_part,
151 lcd_remote_mono_bitmap,
152 lcd_remote_putsxy,
153 lcd_remote_puts_style,
154 lcd_remote_puts_scroll_style,
155 &lcd_remote_framebuffer[0][0],
156 lcd_remote_update,
157 lcd_remote_update_rect,
159 remote_backlight_on,
160 remote_backlight_off,
161 #endif
162 #if NB_SCREENS == 2
163 {&screens[SCREEN_MAIN], &screens[SCREEN_REMOTE]},
164 #else
165 {&screens[SCREEN_MAIN]},
166 #endif
167 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
168 lcd_remote_set_foreground,
169 lcd_remote_get_foreground,
170 lcd_remote_set_background,
171 lcd_remote_get_background,
172 lcd_remote_bitmap_part,
173 lcd_remote_bitmap,
174 #endif
176 #if defined(HAVE_LCD_COLOR) && !defined(SIMULATOR)
177 lcd_yuv_blit,
178 #endif
179 /* list */
180 gui_synclist_init,
181 gui_synclist_set_nb_items,
182 gui_synclist_set_icon_callback,
183 gui_synclist_get_nb_items,
184 gui_synclist_get_sel_pos,
185 gui_synclist_draw,
186 gui_synclist_select_item,
187 gui_synclist_add_item,
188 gui_synclist_del_item,
189 gui_synclist_limit_scroll,
190 gui_synclist_flash,
191 gui_synclist_do_button,
192 gui_synclist_set_title,
194 /* button */
195 button_get,
196 button_get_w_tmo,
197 button_status,
198 button_clear_queue,
199 #ifdef HAS_BUTTON_HOLD
200 button_hold,
201 #endif
203 /* file */
204 (open_func)PREFIX(open),
205 close,
206 (read_func)read,
207 PREFIX(lseek),
208 (creat_func)PREFIX(creat),
209 (write_func)write,
210 PREFIX(remove),
211 PREFIX(rename),
212 PREFIX(ftruncate),
213 PREFIX(filesize),
214 fdprintf,
215 read_line,
216 settings_parseline,
217 #ifndef SIMULATOR
218 ata_sleep,
219 ata_disk_is_active,
220 #endif
221 ata_spindown,
222 reload_directory,
223 create_numbered_filename,
225 /* dir */
226 opendir,
227 closedir,
228 readdir,
229 mkdir,
230 rmdir,
232 /* kernel/ system */
233 PREFIX(sleep),
234 yield,
235 #ifdef HAVE_PRIORITY_SCHEDULING
236 priority_yield,
237 #endif
238 &current_tick,
239 default_event_handler,
240 default_event_handler_ex,
241 threads,
242 create_thread,
243 remove_thread,
244 reset_poweroff_timer,
245 #ifndef SIMULATOR
246 system_memory_guard,
247 &cpu_frequency,
249 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
250 #ifdef CPU_BOOST_LOGGING
251 cpu_boost_,
252 #else
253 cpu_boost,
254 #endif
255 #endif
256 #endif
257 timer_register,
258 timer_unregister,
259 timer_set_period,
261 queue_init,
262 queue_delete,
263 queue_post,
264 queue_wait_w_tmo,
265 usb_acknowledge,
266 #ifdef RB_PROFILE
267 profile_thread,
268 profstop,
269 profile_func_enter,
270 profile_func_exit,
271 #endif
273 #ifdef SIMULATOR
274 /* special simulator hooks */
275 #if defined(HAVE_LCD_BITMAP) && LCD_DEPTH < 8
276 sim_lcd_ex_init,
277 sim_lcd_ex_update_rect,
278 #endif
279 #endif
281 /* strings and memory */
282 snprintf,
283 vsnprintf,
284 strcpy,
285 strncpy,
286 strlen,
287 strrchr,
288 strcmp,
289 strncmp,
290 strcasecmp,
291 strncasecmp,
292 memset,
293 memcpy,
294 memmove,
295 _ctype_,
296 atoi,
297 strchr,
298 strcat,
299 memchr,
300 memcmp,
301 strcasestr,
302 strtok_r,
303 /* unicode stuff */
304 utf8decode,
305 iso_decode,
306 utf16LEdecode,
307 utf16BEdecode,
308 utf8encode,
309 utf8length,
310 utf8seek,
312 /* sound */
313 #if CONFIG_CODEC == SWCODEC
314 sound_default,
315 #endif
316 sound_set,
318 sound_min,
319 sound_max,
320 #ifndef SIMULATOR
321 mp3_play_data,
322 mp3_play_pause,
323 mp3_play_stop,
324 mp3_is_playing,
325 #if CONFIG_CODEC != SWCODEC
326 bitswap,
327 #endif
328 #endif
329 #if CONFIG_CODEC == SWCODEC
330 &audio_master_sampr_list[0],
331 &hw_freq_sampr[0],
332 pcm_apply_settings,
333 pcm_play_data,
334 pcm_play_stop,
335 pcm_set_frequency,
336 pcm_is_playing,
337 pcm_is_paused,
338 pcm_play_pause,
339 pcm_get_bytes_waiting,
340 pcm_calculate_peaks,
341 #ifdef HAVE_RECORDING
342 &rec_freq_sampr[0],
343 pcm_init_recording,
344 pcm_close_recording,
345 pcm_record_data,
346 pcm_record_more,
347 pcm_stop_recording,
348 pcm_calculate_rec_peaks,
349 audio_set_recording_gain,
350 #endif /* HAVE_RECORDING */
351 #if INPUT_SRC_CAPS != 0
352 audio_set_output_source,
353 audio_set_input_source,
354 #endif
355 #endif /* CONFIG_CODEC == SWCODEC */
357 /* playback control */
358 playlist_amount,
359 playlist_resume,
360 playlist_start,
361 PREFIX(audio_play),
362 audio_stop,
363 audio_pause,
364 audio_resume,
365 audio_next,
366 audio_prev,
367 audio_ff_rewind,
368 audio_next_track,
369 audio_status,
370 audio_has_changed_track,
371 audio_current_track,
372 audio_flush_and_reload_tracks,
373 audio_get_file_pos,
374 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
375 mpeg_get_last_header,
376 #endif
377 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) || \
378 (CONFIG_CODEC == SWCODEC)
379 sound_set_pitch,
380 #endif
382 #if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC)
383 /* MAS communication */
384 mas_readmem,
385 mas_writemem,
386 mas_readreg,
387 mas_writereg,
388 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
389 mas_codec_writereg,
390 mas_codec_readreg,
391 i2c_begin,
392 i2c_end,
393 i2c_write,
394 #endif
395 #endif /* !SIMULATOR && CONFIG_CODEC != SWCODEC */
397 /* menu */
398 do_menu,
399 /* statusbars */
400 &statusbars,
401 gui_syncstatusbar_draw,
402 /* options */
403 find_setting,
404 option_screen,
405 set_option,
406 set_bool_options,
407 set_int,
408 set_bool,
409 #ifdef HAVE_LCD_COLOR
410 set_color,
411 #endif
413 /* action handling */
414 get_custom_action,
415 get_action,
416 action_userabort,
418 /* power */
419 battery_level,
420 battery_level_safe,
421 battery_time,
422 #ifndef SIMULATOR
423 battery_voltage,
424 #endif
425 #if CONFIG_CHARGING
426 charger_inserted,
427 # if CONFIG_CHARGING == CHARGING_MONITOR
428 charging_state,
429 # endif
430 #endif
431 #ifdef HAVE_USB_POWER
432 usb_powered,
433 #endif
435 /* misc */
436 srand,
437 rand,
438 (qsort_func)qsort,
439 kbd_input,
440 get_time,
441 set_time,
442 #if CONFIG_RTC
443 mktime,
444 #endif
445 plugin_get_buffer,
446 plugin_get_audio_buffer,
447 plugin_tsr,
448 #ifdef IRAM_STEAL
449 plugin_iram_init,
450 #endif
451 #if defined(DEBUG) || defined(SIMULATOR)
452 debugf,
453 #endif
454 #ifdef ROCKBOX_HAS_LOGF
455 _logf,
456 #endif
457 &global_settings,
458 &global_status,
459 mp3info,
460 count_mp3_frames,
461 create_xing_header,
462 find_next_frame,
463 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
464 peak_meter_scale_value,
465 peak_meter_set_use_dbfs,
466 peak_meter_get_use_dbfs,
467 #endif
468 #ifdef HAVE_LCD_BITMAP
469 read_bmp_file,
470 screen_dump_set_hook,
471 #endif
472 show_logo,
473 tree_get_context,
475 #ifdef HAVE_WHEEL_POSITION
476 wheel_status,
477 wheel_send_events,
478 #endif
480 #ifdef IRIVER_H100_SERIES
481 /* Routines for the iriver_flash -plugin. */
482 detect_original_firmware,
483 detect_flashed_ramimage,
484 detect_flashed_romimage,
485 #endif
486 /* new stuff at the end, sort into place next time
487 the API gets incompatible */
489 #if (CONFIG_CODEC == SWCODEC)
490 spinlock_init,
491 spinlock_lock,
492 spinlock_unlock,
494 codec_load_file,
495 get_codec_filename,
496 get_metadata,
497 #endif
498 #ifdef HAVE_LCD_BITMAP
499 screen_clear_area,
500 #endif
501 led,
504 int plugin_load(const char* plugin, void* parameter)
506 int rc;
507 struct plugin_header *hdr;
508 const char *p = strrchr(plugin,'/');
509 #ifdef SIMULATOR
510 void *pd;
511 #else
512 int fd;
513 ssize_t readsize;
514 #endif
515 int xm, ym;
516 #ifdef HAVE_REMOTE_LCD
517 int rxm, rym;
518 #endif
520 #if LCD_DEPTH > 1
521 fb_data* old_backdrop;
522 #endif
524 if (!p)
525 p = plugin;
527 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
529 if (pfn_tsr_exit(!strcmp(current_plugin,p)) == false )
531 /* not allowing another plugin to load */
532 return PLUGIN_OK;
534 pfn_tsr_exit = NULL;
535 plugin_loaded = false;
538 gui_syncsplash(0, str(LANG_WAIT));
539 strcpy(current_plugin,p);
541 #ifdef SIMULATOR
542 hdr = sim_plugin_load((char *)plugin, &pd);
543 if (pd == NULL) {
544 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
545 return -1;
547 if (hdr == NULL
548 || hdr->magic != PLUGIN_MAGIC
549 || hdr->target_id != TARGET_ID) {
550 sim_plugin_close(pd);
551 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
552 return -1;
554 if (hdr->api_version > PLUGIN_API_VERSION
555 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
556 sim_plugin_close(pd);
557 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
558 return -1;
560 #else
561 fd = open(plugin, O_RDONLY);
562 if (fd < 0) {
563 gui_syncsplash(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin);
564 return fd;
567 readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE);
568 close(fd);
570 if (readsize < 0) {
571 gui_syncsplash(HZ*2, str(LANG_READ_FAILED), plugin);
572 return -1;
574 hdr = (struct plugin_header *)pluginbuf;
576 if ((unsigned)readsize <= sizeof(struct plugin_header)
577 || hdr->magic != PLUGIN_MAGIC
578 || hdr->target_id != TARGET_ID
579 || hdr->load_addr != pluginbuf
580 || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) {
581 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL));
582 return -1;
584 if (hdr->api_version > PLUGIN_API_VERSION
585 || hdr->api_version < PLUGIN_MIN_API_VERSION) {
586 gui_syncsplash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION));
587 return -1;
589 plugin_size = hdr->end_addr - pluginbuf;
591 /* zero out bss area only, above guards end of pluginbuf */
592 if (plugin_size > readsize)
593 memset(pluginbuf + readsize, 0, plugin_size - readsize);
594 #endif
596 plugin_loaded = true;
598 xm = lcd_getxmargin();
599 ym = lcd_getymargin();
600 lcd_setmargins(0,0);
602 #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1
603 old_backdrop = lcd_get_backdrop();
604 #endif
605 lcd_clear_display();
606 lcd_update();
608 #ifdef HAVE_REMOTE_LCD
609 rxm = lcd_remote_getxmargin();
610 rym = lcd_remote_getymargin();
611 lcd_remote_setmargins(0, 0);
612 lcd_remote_clear_display();
613 lcd_remote_update();
614 #endif
616 invalidate_icache();
618 rc = hdr->entry_point((struct plugin_api*) &rockbox_api, parameter);
619 /* explicitly casting the pointer here to avoid touching every plugin. */
621 button_clear_queue();
623 #ifdef HAVE_LCD_BITMAP
624 #if LCD_DEPTH > 1
625 lcd_set_backdrop(old_backdrop);
626 #ifdef HAVE_LCD_COLOR
627 lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color,
628 global_settings.bg_color);
629 #else
630 lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG);
631 #endif
632 #else /* LCD_DEPTH == 1 */
633 lcd_set_drawmode(DRMODE_SOLID);
634 #endif /* LCD_DEPTH */
635 #endif /* HAVE_LCD_BITMAP */
637 /* restore margins */
638 lcd_setmargins(xm,ym);
639 lcd_clear_display();
640 lcd_update();
642 #ifdef HAVE_REMOTE_LCD
643 #if LCD_REMOTE_DEPTH > 1
644 lcd_remote_set_drawinfo(DRMODE_SOLID, LCD_REMOTE_DEFAULT_FG,
645 LCD_REMOTE_DEFAULT_BG);
646 #else
647 lcd_remote_set_drawmode(DRMODE_SOLID);
648 #endif
649 lcd_remote_setmargins(rxm, rym);
650 lcd_remote_clear_display();
651 lcd_remote_update();
652 #endif
654 if (pfn_tsr_exit == NULL)
655 plugin_loaded = false;
657 sim_plugin_close(pd);
659 switch (rc) {
660 case PLUGIN_OK:
661 break;
663 case PLUGIN_USB_CONNECTED:
664 return PLUGIN_USB_CONNECTED;
666 default:
667 gui_syncsplash(HZ*2, str(LANG_PLUGIN_ERROR));
668 break;
670 return PLUGIN_OK;
673 /* Returns a pointer to the portion of the plugin buffer that is not already
674 being used. If no plugin is loaded, returns the entire plugin buffer */
675 void* plugin_get_buffer(size_t *buffer_size)
677 int buffer_pos;
679 if (plugin_loaded)
681 if (plugin_size >= PLUGIN_BUFFER_SIZE)
682 return NULL;
684 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
685 buffer_pos = plugin_size;
687 else
689 *buffer_size = PLUGIN_BUFFER_SIZE;
690 buffer_pos = 0;
693 return &pluginbuf[buffer_pos];
696 /* Returns a pointer to the mp3 buffer.
697 Playback gets stopped, to avoid conflicts.
698 Talk buffer is stolen as well.
700 void* plugin_get_audio_buffer(size_t *buffer_size)
702 #if CONFIG_CODEC == SWCODEC
703 return audio_get_buffer(true, buffer_size);
704 #else
705 audio_stop();
706 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
707 *buffer_size = audiobufend - audiobuf;
708 return audiobuf;
709 #endif
712 #ifdef IRAM_STEAL
713 /* Initializes plugin IRAM */
714 void plugin_iram_init(char *iramstart, char *iramcopy, size_t iram_size,
715 char *iedata, size_t iedata_size)
717 audio_iram_steal();
718 memcpy(iramstart, iramcopy, iram_size);
719 memset(iedata, 0, iedata_size);
720 memset(iramcopy, 0, iram_size);
722 #endif /* IRAM_STEAL */
724 /* The plugin wants to stay resident after leaving its main function, e.g.
725 runs from timer or own thread. The callback is registered to later
726 instruct it to free its resources before a new plugin gets loaded. */
727 void plugin_tsr(bool (*exit_callback)(bool))
729 pfn_tsr_exit = exit_callback; /* remember the callback for later */