Added .S files in drivers
[kugel-rb.git] / apps / plugin.c
blob9ac9f85915380c96d958a349c9c6cf9f450783d1
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 <stdbool.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <atoi.h>
23 #include <timefuncs.h>
24 #include "button.h"
25 #include "lcd.h"
26 #include "dir.h"
27 #include "file.h"
28 #include "kernel.h"
29 #include "sprintf.h"
30 #include "screens.h"
31 #include "misc.h"
32 #include "mas.h"
33 #include "plugin.h"
34 #include "lang.h"
35 #include "keyboard.h"
36 #include "mpeg.h"
37 #include "buffer.h"
38 #include "mp3_playback.h"
39 #include "backlight.h"
40 #include "ata.h"
41 #include "talk.h"
43 #ifdef HAVE_LCD_BITMAP
44 #include "widgets.h"
45 #endif
47 #ifdef SIMULATOR
48 #include <debug.h>
49 #ifdef WIN32
50 #include "plugin-win32.h"
51 #define PREFIX(_x_) _x_
52 #else
53 #include <dlfcn.h>
54 #define PREFIX(_x_) x11_ ## _x_
55 #endif
56 #else
57 #define PREFIX(_x_) _x_
58 #endif
60 #define PLUGIN_BUFFER_SIZE 0x8000
62 #ifdef SIMULATOR
63 static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE];
64 #else
65 extern unsigned char pluginbuf[];
66 extern void bitswap(unsigned char *data, int length);
67 #endif
69 static bool plugin_loaded = false;
70 static int plugin_size = 0;
71 #ifndef SIMULATOR
72 static void (*pfn_timer)(void) = NULL; /* user timer handler */
73 #endif
74 static void (*pfn_tsr_exit)(void) = NULL; /* TSR exit callback */
76 static int plugin_test(int api_version, int model, int memsize);
78 static struct plugin_api rockbox_api = {
79 PLUGIN_API_VERSION,
81 plugin_test,
83 /* lcd */
84 lcd_clear_display,
85 lcd_puts,
86 lcd_puts_scroll,
87 lcd_stop_scroll,
88 #ifdef HAVE_LCD_CHARCELLS
89 lcd_define_pattern,
90 lcd_get_locked_pattern,
91 lcd_unlock_pattern,
92 lcd_putc,
93 #else
94 lcd_putsxy,
95 lcd_bitmap,
96 lcd_drawline,
97 lcd_clearline,
98 lcd_drawpixel,
99 lcd_clearpixel,
100 lcd_setfont,
101 lcd_clearrect,
102 lcd_fillrect,
103 lcd_drawrect,
104 lcd_invertrect,
105 lcd_getstringsize,
106 lcd_update,
107 lcd_update_rect,
108 progressbar,
109 slidebar,
110 scrollbar,
111 #ifndef SIMULATOR
112 lcd_roll,
113 #endif
114 #endif
116 /* button */
117 button_get,
118 button_get_w_tmo,
120 /* file */
121 (open_func)PREFIX(open),
122 PREFIX(close),
123 (read_func)read,
124 lseek,
125 (creat_func)PREFIX(creat),
126 (write_func)write,
127 remove,
128 rename,
129 ftruncate,
130 PREFIX(filesize),
131 fprintf,
132 read_line,
134 /* dir */
135 PREFIX(opendir),
136 PREFIX(closedir),
137 PREFIX(readdir),
139 /* kernel */
140 PREFIX(sleep),
141 usb_screen,
142 &current_tick,
144 /* strings and memory */
145 snprintf,
146 strcpy,
147 strlen,
148 memset,
149 memcpy,
151 /* sound */
152 #ifndef SIMULATOR
153 #ifdef HAVE_MAS3587F
154 mas_codec_readreg,
155 #endif
156 #endif
158 /* misc */
159 srand,
160 rand,
161 splash,
162 (qsort_func)qsort,
163 kbd_input,
164 mpeg_current_track,
165 atoi,
166 get_time,
167 plugin_get_buffer,
169 /* new stuff at the end, sort into place next time the API gets incompatible */
171 #ifndef HAVE_LCD_CHARCELLS
172 &lcd_framebuffer[0][0],
173 lcd_blit,
174 #endif
175 yield,
177 plugin_get_mp3_buffer,
178 mpeg_sound_set,
179 #ifndef SIMULATOR
180 mp3_play_init,
181 mp3_play_data,
182 mp3_play_pause,
183 mp3_play_stop,
184 mp3_is_playing,
185 bitswap,
186 #endif
187 &global_settings,
188 backlight_set_timeout,
189 #ifndef SIMULATOR
190 ata_sleep,
191 #endif
192 #ifdef HAVE_LCD_BITMAP
193 checkbox,
194 #endif
195 #ifndef SIMULATOR
196 plugin_register_timer,
197 plugin_unregister_timer,
198 #endif
199 plugin_tsr,
200 create_thread,
201 remove_thread,
202 lcd_set_contrast,
203 mpeg_play,
204 mpeg_stop,
205 mpeg_pause,
206 mpeg_resume,
207 mpeg_next,
208 mpeg_prev,
209 mpeg_ff_rewind,
210 mpeg_next_track,
211 mpeg_has_changed_track,
212 mpeg_status,
215 int plugin_load(char* plugin, void* parameter)
217 enum plugin_status (*plugin_start)(struct plugin_api* api, void* param);
218 int rc;
219 char buf[64];
220 #ifdef SIMULATOR
221 void* pd;
222 char path[256];
223 #else
224 int fd;
225 #endif
226 #ifdef HAVE_LCD_BITMAP
227 int xm,ym;
228 #endif
230 if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */
232 pfn_tsr_exit(); /* force it to exit now */
233 pfn_tsr_exit = NULL;
236 #ifdef HAVE_LCD_BITMAP
237 lcd_clear_display();
238 xm = lcd_getxmargin();
239 ym = lcd_getymargin();
240 lcd_setmargins(0,0);
241 lcd_update();
242 #else
243 lcd_clear_display();
244 #endif
245 #ifdef SIMULATOR
246 #ifdef WIN32
247 snprintf(path, sizeof path, "%s", plugin);
248 #else
249 snprintf(path, sizeof path, "archos%s", plugin);
250 #endif
251 pd = dlopen(path, RTLD_NOW);
252 if (!pd) {
253 snprintf(buf, sizeof buf, "Can't open %s", plugin);
254 splash(HZ*2, true, buf);
255 DEBUGF("dlopen(%s): %s\n",path,dlerror());
256 dlclose(pd);
257 return -1;
260 plugin_start = dlsym(pd, "plugin_start");
261 if (!plugin_start) {
262 plugin_start = dlsym(pd, "_plugin_start");
263 if (!plugin_start) {
264 splash(HZ*2, true, "Can't find entry point");
265 dlclose(pd);
266 return -1;
269 #else
270 fd = open(plugin, O_RDONLY);
271 if (fd < 0) {
272 snprintf(buf, sizeof buf, str(LANG_PLUGIN_CANT_OPEN), plugin);
273 splash(HZ*2, true, buf);
274 return fd;
277 plugin_start = (void*)&pluginbuf;
278 plugin_size = read(fd, plugin_start, PLUGIN_BUFFER_SIZE);
279 close(fd);
280 if (plugin_size < 0) {
281 /* read error */
282 snprintf(buf, sizeof buf, str(LANG_READ_FAILED), plugin);
283 splash(HZ*2, true, buf);
284 return -1;
286 if (plugin_size == 0) {
287 /* loaded a 0-byte plugin, implying it's not for this model */
288 splash(HZ*2, true, str(LANG_PLUGIN_WRONG_MODEL));
289 return -1;
291 #endif
293 plugin_loaded = true;
294 rc = plugin_start(&rockbox_api, parameter);
295 plugin_loaded = false;
297 switch (rc) {
298 case PLUGIN_OK:
299 break;
301 case PLUGIN_USB_CONNECTED:
302 return PLUGIN_USB_CONNECTED;
304 case PLUGIN_WRONG_API_VERSION:
305 splash(HZ*2, true, str(LANG_PLUGIN_WRONG_VERSION));
306 break;
308 case PLUGIN_WRONG_MODEL:
309 splash(HZ*2, true, str(LANG_PLUGIN_WRONG_MODEL));
310 break;
312 default:
313 splash(HZ*2, true, str(LANG_PLUGIN_ERROR));
314 break;
317 #ifdef SIMULATOR
318 dlclose(pd);
319 #endif
321 #ifdef HAVE_LCD_BITMAP
322 /* restore margins */
323 lcd_setmargins(xm,ym);
324 #endif
326 return PLUGIN_OK;
329 /* Returns a pointer to the portion of the plugin buffer that is not already
330 being used. If no plugin is loaded, returns the entire plugin buffer */
331 void* plugin_get_buffer(int* buffer_size)
333 int buffer_pos;
335 if (plugin_loaded)
337 if (plugin_size >= PLUGIN_BUFFER_SIZE)
338 return NULL;
340 *buffer_size = PLUGIN_BUFFER_SIZE-plugin_size;
341 buffer_pos = plugin_size;
343 else
345 *buffer_size = PLUGIN_BUFFER_SIZE;
346 buffer_pos = 0;
349 return &pluginbuf[buffer_pos];
352 /* Returns a pointer to the mp3 buffer.
353 Playback gets stopped, to avoid conflicts. */
354 void* plugin_get_mp3_buffer(int* buffer_size)
356 #ifdef SIMULATOR
357 static unsigned char buf[1700*1024];
358 *buffer_size = sizeof(buf);
359 return buf;
360 #else
361 mpeg_stop();
362 talk_buffer_steal(); /* we use the mp3 buffer, need to tell */
363 *buffer_size = mp3end - mp3buf;
364 return mp3buf;
365 #endif
368 #ifndef SIMULATOR
369 /* Register a periodic time callback, called every "cycles" CPU clocks.
370 Note that this function will be called in interrupt context! */
371 int plugin_register_timer(int cycles, int prio, void (*timer_callback)(void))
373 int phi = 0; /* bits for the prescaler */
374 int prescale = 1;
376 while (cycles > 0x10000)
377 { /* work out the smallest prescaler that makes it fit */
378 phi++;
379 prescale *= 2;
380 cycles /= 2;
383 if (prescale > 8 || cycles == 0 || prio < 1 || prio > 15)
384 return 0; /* error, we can't do such period, bad argument */
386 and_b(~0x10, &TSTR); /* Stop the timer 4 */
387 and_b(~0x10, &TSNC); /* No synchronization */
388 and_b(~0x10, &TMDR); /* Operate normally */
390 pfn_timer = timer_callback; /* install 2nd level ISR */
392 and_b(~0x01, &TSR4);
393 TIER4 = 0xF9; /* Enable GRA match interrupt */
395 GRA4 = (unsigned short)(cycles - 1);
396 TCR4 = 0x20 | phi; /* clear at GRA match, set prescaler */
397 IPRD = (IPRD & 0xFF0F) | prio << 4; /* interrupt priority */
398 or_b(0x10, &TSTR); /* start timer 4 */
400 return cycles * prescale; /* return the actual period, in CPU clocks */
403 /* disable the user timer */
404 void plugin_unregister_timer(void)
406 and_b(~0x10, &TSTR); /* stop the timer 4 */
407 IPRD = (IPRD & 0xFF0F); /* disable interrupt */
408 pfn_timer = NULL;
411 /* interrupt handler for user timer */
412 #pragma interrupt
413 void IMIA4(void)
415 if (pfn_timer != NULL)
416 pfn_timer(); /* call the user timer function */
417 and_b(~0x01, &TSR4); /* clear the interrupt */
419 #endif /* #ifndef SIMULATOR */
421 /* The plugin wants to stay resident after leaving its main function, e.g.
422 runs from timer or own thread. The callback is registered to later
423 instruct it to free its resources before a new plugin gets loaded. */
424 void plugin_tsr(void (*exit_callback)(void))
426 pfn_tsr_exit = exit_callback; /* remember the callback for later */
430 static int plugin_test(int api_version, int model, int memsize)
432 if (api_version < PLUGIN_MIN_API_VERSION ||
433 api_version > PLUGIN_API_VERSION)
434 return PLUGIN_WRONG_API_VERSION;
436 if (model != MODEL)
437 return PLUGIN_WRONG_MODEL;
439 if (memsize != MEM)
440 return PLUGIN_WRONG_MODEL;
442 return PLUGIN_OK;