diff options
author | Thomas Martitz <kugel@rockbox.org> | 2010-08-27 00:29:50 +0000 |
---|---|---|
committer | Thomas Martitz <kugel@rockbox.org> | 2010-08-27 00:29:50 +0000 |
commit | 194174a371b16dfc24960d1e33371c0a7ef1c2c2 (patch) | |
tree | b924bf74a96bb7dedcaebb45319569c003d81e8b /apps/plugin.c | |
parent | 97d2a6ec5ca8ace8daed29c8c69aab9595147b3a (diff) | |
download | rockbox-194174a371b16dfc24960d1e33371c0a7ef1c2c2.tar.gz rockbox-194174a371b16dfc24960d1e33371c0a7ef1c2c2.zip |
2nd try: Introduce a small api for loading code (codecs,plugins) from disk/memory.
It's a used by codec/plugin loading and vastly reduces code duplication. It's also a step forward in getting rid of libuisimulator in the application ports.
Apparently sh needs linker symbols prefixed with _ even if they're referenced without from C code.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27902 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugin.c')
-rw-r--r-- | apps/plugin.c | 102 |
1 files changed, 31 insertions, 71 deletions
diff --git a/apps/plugin.c b/apps/plugin.c index cc540cd988..53a05bf527 100644 --- a/apps/plugin.c +++ b/apps/plugin.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include "errno.h" | 42 | #include "errno.h" |
43 | #include "diacritic.h" | 43 | #include "diacritic.h" |
44 | #include "filefuncs.h" | 44 | #include "filefuncs.h" |
45 | #include "load_code.h" | ||
45 | 46 | ||
46 | #if CONFIG_CHARGING | 47 | #if CONFIG_CHARGING |
47 | #include "power.h" | 48 | #include "power.h" |
@@ -75,21 +76,19 @@ static unsigned int open_files; | |||
75 | 76 | ||
76 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 77 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) |
77 | static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; | 78 | static unsigned char pluginbuf[PLUGIN_BUFFER_SIZE]; |
78 | void *sim_plugin_load(char *plugin, void **pd); | ||
79 | void sim_plugin_close(void *pd); | ||
80 | void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); | 79 | void sim_lcd_ex_init(unsigned long (*getpixel)(int, int)); |
81 | void sim_lcd_ex_update_rect(int x, int y, int width, int height); | 80 | void sim_lcd_ex_update_rect(int x, int y, int width, int height); |
82 | #else | 81 | #else |
83 | #define sim_plugin_close(x) | ||
84 | extern unsigned char pluginbuf[]; | 82 | extern unsigned char pluginbuf[]; |
85 | #include "bitswap.h" | 83 | #include "bitswap.h" |
86 | #endif | 84 | #endif |
87 | 85 | ||
88 | /* for actual plugins only, not for codecs */ | 86 | /* for actual plugins only, not for codecs */ |
89 | static bool plugin_loaded = false; | ||
90 | static int plugin_size = 0; | 87 | static int plugin_size = 0; |
91 | static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ | 88 | static bool (*pfn_tsr_exit)(bool reenter) = NULL; /* TSR exit callback */ |
92 | static char current_plugin[MAX_PATH]; | 89 | static char current_plugin[MAX_PATH]; |
90 | /* NULL if no plugin is loaded, otherwise the handle that lc_open() returned */ | ||
91 | static void *current_plugin_handle; | ||
93 | 92 | ||
94 | char *plugin_get_current_filename(void); | 93 | char *plugin_get_current_filename(void); |
95 | 94 | ||
@@ -728,98 +727,60 @@ int plugin_load(const char* plugin, const void* parameter) | |||
728 | { | 727 | { |
729 | int rc, i; | 728 | int rc, i; |
730 | struct plugin_header *hdr; | 729 | struct plugin_header *hdr; |
731 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | ||
732 | void *pd; | ||
733 | #else /* PLATFOR_NATIVE */ | ||
734 | int fd; | ||
735 | ssize_t readsize; | ||
736 | #if NUM_CORES > 1 | ||
737 | unsigned my_core; | ||
738 | #endif | ||
739 | #endif /* CONFIG_PLATFORM */ | ||
740 | 730 | ||
741 | #if LCD_DEPTH > 1 | 731 | #if LCD_DEPTH > 1 |
742 | fb_data* old_backdrop; | 732 | fb_data* old_backdrop; |
743 | #endif | 733 | #endif |
744 | 734 | ||
745 | if (pfn_tsr_exit != NULL) /* if we have a resident old plugin: */ | 735 | if (current_plugin_handle && pfn_tsr_exit) |
746 | { | 736 | { /* if we have a resident old plugin and a callback */ |
747 | if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) | 737 | if (pfn_tsr_exit(!strcmp(current_plugin, plugin)) == false ) |
748 | { | 738 | { |
749 | /* not allowing another plugin to load */ | 739 | /* not allowing another plugin to load */ |
750 | return PLUGIN_OK; | 740 | return PLUGIN_OK; |
751 | } | 741 | } |
752 | pfn_tsr_exit = NULL; | 742 | lc_close(current_plugin_handle); |
753 | plugin_loaded = false; | 743 | current_plugin_handle = pfn_tsr_exit = NULL; |
754 | } | 744 | } |
755 | 745 | ||
756 | splash(0, ID2P(LANG_WAIT)); | 746 | splash(0, ID2P(LANG_WAIT)); |
757 | strcpy(current_plugin, plugin); | 747 | strcpy(current_plugin, plugin); |
758 | 748 | ||
759 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 749 | current_plugin_handle = lc_open(plugin, pluginbuf, PLUGIN_BUFFER_SIZE); |
760 | hdr = sim_plugin_load((char *)plugin, &pd); | 750 | if (current_plugin_handle == NULL) { |
761 | if (pd == NULL) { | ||
762 | splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); | 751 | splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); |
763 | return -1; | 752 | return -1; |
764 | } | 753 | } |
765 | if (hdr == NULL | ||
766 | || hdr->magic != PLUGIN_MAGIC | ||
767 | || hdr->target_id != TARGET_ID) { | ||
768 | sim_plugin_close(pd); | ||
769 | splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); | ||
770 | return -1; | ||
771 | } | ||
772 | if (hdr->api_version > PLUGIN_API_VERSION | ||
773 | || hdr->api_version < PLUGIN_MIN_API_VERSION) { | ||
774 | sim_plugin_close(pd); | ||
775 | splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); | ||
776 | return -1; | ||
777 | } | ||
778 | #else | ||
779 | fd = open(plugin, O_RDONLY); | ||
780 | if (fd < 0) { | ||
781 | splashf(HZ*2, str(LANG_PLUGIN_CANT_OPEN), plugin); | ||
782 | return fd; | ||
783 | } | ||
784 | #if NUM_CORES > 1 | ||
785 | /* Make sure COP cache is flushed and invalidated before loading */ | ||
786 | my_core = switch_core(CURRENT_CORE ^ 1); | ||
787 | cpucache_invalidate(); | ||
788 | switch_core(my_core); | ||
789 | #endif | ||
790 | 754 | ||
791 | readsize = read(fd, pluginbuf, PLUGIN_BUFFER_SIZE); | 755 | hdr = lc_get_header(current_plugin_handle); |
792 | close(fd); | ||
793 | 756 | ||
794 | if (readsize < 0) { | 757 | if (hdr == NULL |
795 | splashf(HZ*2, str(LANG_READ_FAILED), plugin); | ||
796 | return -1; | ||
797 | } | ||
798 | hdr = (struct plugin_header *)pluginbuf; | ||
799 | |||
800 | if ((unsigned)readsize <= sizeof(struct plugin_header) | ||
801 | || hdr->magic != PLUGIN_MAGIC | 758 | || hdr->magic != PLUGIN_MAGIC |
802 | || hdr->target_id != TARGET_ID | 759 | || hdr->target_id != TARGET_ID |
760 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
803 | || hdr->load_addr != pluginbuf | 761 | || hdr->load_addr != pluginbuf |
804 | || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE) { | 762 | || hdr->end_addr > pluginbuf + PLUGIN_BUFFER_SIZE |
763 | #endif | ||
764 | ) | ||
765 | { | ||
766 | lc_close(current_plugin_handle); | ||
805 | splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); | 767 | splash(HZ*2, str(LANG_PLUGIN_WRONG_MODEL)); |
806 | return -1; | 768 | return -1; |
807 | } | 769 | } |
808 | if (hdr->api_version > PLUGIN_API_VERSION | 770 | if (hdr->api_version > PLUGIN_API_VERSION |
809 | || hdr->api_version < PLUGIN_MIN_API_VERSION) { | 771 | || hdr->api_version < PLUGIN_MIN_API_VERSION) |
772 | { | ||
773 | lc_close(current_plugin_handle); | ||
810 | splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); | 774 | splash(HZ*2, str(LANG_PLUGIN_WRONG_VERSION)); |
811 | return -1; | 775 | return -1; |
812 | } | 776 | } |
777 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | ||
813 | plugin_size = hdr->end_addr - pluginbuf; | 778 | plugin_size = hdr->end_addr - pluginbuf; |
814 | 779 | #else | |
815 | /* zero out bss area only, above guards end of pluginbuf */ | 780 | plugin_size = 0; |
816 | if (plugin_size > readsize) | ||
817 | memset(pluginbuf + readsize, 0, plugin_size - readsize); | ||
818 | #endif | 781 | #endif |
819 | 782 | ||
820 | *(hdr->api) = &rockbox_api; | 783 | *(hdr->api) = &rockbox_api; |
821 | plugin_loaded = true; | ||
822 | |||
823 | 784 | ||
824 | #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 | 785 | #if defined HAVE_LCD_BITMAP && LCD_DEPTH > 1 |
825 | old_backdrop = lcd_get_backdrop(); | 786 | old_backdrop = lcd_get_backdrop(); |
@@ -834,8 +795,6 @@ int plugin_load(const char* plugin, const void* parameter) | |||
834 | 795 | ||
835 | FOR_NB_SCREENS(i) | 796 | FOR_NB_SCREENS(i) |
836 | viewportmanager_theme_enable(i, false, NULL); | 797 | viewportmanager_theme_enable(i, false, NULL); |
837 | |||
838 | cpucache_invalidate(); | ||
839 | 798 | ||
840 | #ifdef HAVE_TOUCHSCREEN | 799 | #ifdef HAVE_TOUCHSCREEN |
841 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); | 800 | touchscreen_set_mode(TOUCHSCREEN_BUTTON); |
@@ -847,6 +806,12 @@ int plugin_load(const char* plugin, const void* parameter) | |||
847 | 806 | ||
848 | rc = hdr->entry_point(parameter); | 807 | rc = hdr->entry_point(parameter); |
849 | 808 | ||
809 | if (!pfn_tsr_exit) | ||
810 | { /* close handle if plugin is no tsr one */ | ||
811 | lc_close(current_plugin_handle); | ||
812 | current_plugin_handle = NULL; | ||
813 | } | ||
814 | |||
850 | /* Go back to the global setting in case the plugin changed it */ | 815 | /* Go back to the global setting in case the plugin changed it */ |
851 | #ifdef HAVE_TOUCHSCREEN | 816 | #ifdef HAVE_TOUCHSCREEN |
852 | touchscreen_set_mode(global_settings.touch_mode); | 817 | touchscreen_set_mode(global_settings.touch_mode); |
@@ -887,11 +852,8 @@ int plugin_load(const char* plugin, const void* parameter) | |||
887 | FOR_NB_SCREENS(i) | 852 | FOR_NB_SCREENS(i) |
888 | viewportmanager_theme_undo(i, false); | 853 | viewportmanager_theme_undo(i, false); |
889 | 854 | ||
890 | if (pfn_tsr_exit == NULL) | ||
891 | plugin_loaded = false; | ||
892 | |||
893 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE | 855 | #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE |
894 | if(open_files != 0 && !plugin_loaded) | 856 | if(open_files != 0 && !current_plugin_handle) |
895 | { | 857 | { |
896 | int fd; | 858 | int fd; |
897 | logf("Plugin '%s' leaks file handles", plugin); | 859 | logf("Plugin '%s' leaks file handles", plugin); |
@@ -909,8 +871,6 @@ int plugin_load(const char* plugin, const void* parameter) | |||
909 | } | 871 | } |
910 | #endif | 872 | #endif |
911 | 873 | ||
912 | sim_plugin_close(pd); | ||
913 | |||
914 | if (rc == PLUGIN_ERROR) | 874 | if (rc == PLUGIN_ERROR) |
915 | splash(HZ*2, str(LANG_PLUGIN_ERROR)); | 875 | splash(HZ*2, str(LANG_PLUGIN_ERROR)); |
916 | 876 | ||
@@ -923,7 +883,7 @@ void* plugin_get_buffer(size_t *buffer_size) | |||
923 | { | 883 | { |
924 | int buffer_pos; | 884 | int buffer_pos; |
925 | 885 | ||
926 | if (plugin_loaded) | 886 | if (current_plugin_handle) |
927 | { | 887 | { |
928 | if (plugin_size >= PLUGIN_BUFFER_SIZE) | 888 | if (plugin_size >= PLUGIN_BUFFER_SIZE) |
929 | return NULL; | 889 | return NULL; |