summaryrefslogtreecommitdiff
path: root/firmware/include
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/include')
-rw-r--r--firmware/include/dir.h91
-rw-r--r--firmware/include/dir_uncached.h107
-rw-r--r--firmware/include/dircache.h209
-rw-r--r--firmware/include/dircache_redirect.h198
-rw-r--r--firmware/include/disk_cache.h83
-rw-r--r--firmware/include/file.h125
-rw-r--r--firmware/include/file_internal.h371
-rw-r--r--firmware/include/fileobj_mgr.h56
-rw-r--r--firmware/include/filesystem-native.h107
-rw-r--r--firmware/include/fs_attr.h39
-rw-r--r--firmware/include/rb-loader.h1
-rw-r--r--firmware/include/rbunicode.h18
12 files changed, 1133 insertions, 272 deletions
diff --git a/firmware/include/dir.h b/firmware/include/dir.h
index 6e8b705..f771982 100644
--- a/firmware/include/dir.h
+++ b/firmware/include/dir.h
@@ -18,46 +18,71 @@
* KIND, either express or implied.
*
****************************************************************************/
-
#ifndef _DIR_H_
#define _DIR_H_
+#include <sys/types.h>
+#include <fcntl.h>
+#include <time.h>
#include "config.h"
+#include "fs_attr.h"
-#define ATTR_READ_ONLY 0x01
-#define ATTR_HIDDEN 0x02
-#define ATTR_SYSTEM 0x04
-#define ATTR_VOLUME_ID 0x08
-#define ATTR_DIRECTORY 0x10
-#define ATTR_ARCHIVE 0x20
-#define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
-#define ATTR_LINK 0x80
-
-#ifdef HAVE_DIRCACHE
-# include "dircache.h"
-# define DIR DIR_CACHED
-# define dirent dirent_cached
-# define opendir opendir_cached
-# define closedir closedir_cached
-# define readdir readdir_cached
-# define closedir closedir_cached
-# define mkdir mkdir_cached
-# define rmdir rmdir_cached
+#if defined (APPLICATION)
+#include "filesystem-app.h"
+#elif defined(SIMULATOR) || defined(__PCTOOL__)
+#include "../../uisimulator/common/filesystem-sim.h"
#else
-# include "dir_uncached.h"
-# define DIR DIR_UNCACHED
-# define dirent dirent_uncached
-# define opendir opendir_uncached
-# define closedir closedir_uncached
-# define readdir readdir_uncached
-# define closedir closedir_uncached
-# define mkdir mkdir_uncached
-# define rmdir rmdir_uncached
+#include "filesystem-native.h"
+#endif
+
+#ifndef DIRFUNCTIONS_DEFINED
+#ifndef opendir
+#define opendir FS_PREFIX(opendir)
+#endif
+#ifndef readdir
+#define readdir FS_PREFIX(readdir)
+#endif
+#ifndef readdir_r
+#define readdir_r FS_PREFIX(readdir_r)
+#endif
+#ifndef rewinddir
+#define rewinddir FS_PREFIX(rewinddir)
#endif
+#ifndef closedir
+#define closedir FS_PREFIX(closedir)
+#endif
+#ifndef mkdir
+#define mkdir FS_PREFIX(mkdir)
+#endif
+#ifndef rmdir
+#define rmdir FS_PREFIX(rmdir)
+#endif
+#ifndef samedir
+#define samedir FS_PREFIX(samedir)
+#endif
+#ifndef dir_exists
+#define dir_exists FS_PREFIX(dir_exists)
+#endif
+#endif /* !DIRFUNCTIONS_DEFINED */
+#ifndef DIRENT_DEFINED
+struct DIRENT
+{
+ struct dirinfo_native info; /* platform extra info */
+ char d_name[MAX_PATH]; /* UTF-8 name of entry (last!) */
+};
+#endif /* DIRENT_DEFINED */
-typedef DIR* (*opendir_func)(const char* name);
-typedef int (*closedir_func)(DIR* dir);
-typedef struct dirent* (*readdir_func)(DIR* dir);
+struct dirinfo
+{
+ unsigned int attribute; /* attribute bits of file */
+ off_t size; /* binary size of file */
+ time_t mtime; /* local file time */
+};
-#endif
+#ifndef DIRFUNCTIONS_DECLARED
+/* TIP: set errno to zero before calling to see if anything failed */
+struct dirinfo dir_get_info(DIR *dirp, struct DIRENT *entry);
+#endif /* !DIRFUNCTIONS_DECLARED */
+
+#endif /* _DIR_H_ */
diff --git a/firmware/include/dir_uncached.h b/firmware/include/dir_uncached.h
deleted file mode 100644
index 6443d5b..0000000
--- a/firmware/include/dir_uncached.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id: dir.h 13741 2007-06-30 02:08:27Z jethead71 $
- *
- * Copyright (C) 2002 by Björn Stenberg
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-#ifndef _DIR_UNCACHED_H_
-#define _DIR_UNCACHED_H_
-
-#include "config.h"
-
-struct dirinfo {
- int attribute;
- long size;
- unsigned short wrtdate;
- unsigned short wrttime;
-};
-
-#include <stdbool.h>
-#include "file.h"
-
-#if defined(SIMULATOR) || defined(__PCTOOL__)
-# define dirent_uncached sim_dirent
-# define DIR_UNCACHED SIM_DIR
-# define opendir_uncached sim_opendir
-# define readdir_uncached sim_readdir
-# define closedir_uncached sim_closedir
-# define mkdir_uncached sim_mkdir
-# define rmdir_uncached sim_rmdir
-#elif defined(APPLICATION)
-# include "rbpaths.h"
-# define DIRENT_DEFINED
-# define DIR_DEFINED
-# define dirent_uncached dirent
-# define DIR_UNCACHED DIR
-# define opendir_uncached app_opendir
-# define readdir_uncached app_readdir
-# define closedir_uncached app_closedir
-# define mkdir_uncached app_mkdir
-# define rmdir_uncached app_rmdir
-#endif
-
-
-#ifndef DIRENT_DEFINED
-struct dirent_uncached {
- unsigned char d_name[MAX_PATH];
- struct dirinfo info;
- long startcluster;
-};
-#endif
-
-#include "fat.h"
-
-#ifndef DIR_DEFINED
-typedef struct {
-#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
- struct fat_dir fatdir CACHEALIGN_ATTR;
- bool busy;
- long startcluster;
- struct dirent_uncached theent;
-#ifdef HAVE_MULTIVOLUME
- int volumecounter; /* running counter for faked volume entries */
-#endif
-#else
- /* simulator/application: */
- void *dir; /* actually a DIR* dir */
- char *name;
-#endif
-} DIR_UNCACHED CACHEALIGN_ATTR;
-#endif
-
-#ifdef HAVE_HOTSWAP
-char *get_volume_name(int volume);
-#endif
-
-#ifdef HAVE_MULTIVOLUME
- int strip_volume(const char*, char*);
-#endif
-
-#ifndef DIRFUNCTIONS_DEFINED
-
-extern DIR_UNCACHED* opendir_uncached(const char* name);
-extern int closedir_uncached(DIR_UNCACHED* dir);
-extern int mkdir_uncached(const char* name);
-extern int rmdir_uncached(const char* name);
-
-extern struct dirent_uncached* readdir_uncached(DIR_UNCACHED* dir);
-
-extern int release_dirs(int volume);
-
-#endif /* DIRFUNCTIONS_DEFINED */
-
-#endif
diff --git a/firmware/include/dircache.h b/firmware/include/dircache.h
index 019ccf4..7e8c764 100644
--- a/firmware/include/dircache.h
+++ b/firmware/include/dircache.h
@@ -8,6 +8,7 @@
* $Id$
*
* Copyright (C) 2005 by Miika Pekkarinen
+ * Copyright (C) 2014 by Michael Sevakis
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -21,84 +22,154 @@
#ifndef _DIRCACHE_H
#define _DIRCACHE_H
-#include "config.h"
-#include "dir_uncached.h"
-#include <string.h> /* size_t */
+#include "mv.h"
+#include <string.h> /* size_t */
+#include <sys/types.h> /* ssize_t */
#ifdef HAVE_DIRCACHE
-#define DIRCACHE_RESERVE (1024*64)
-#define DIRCACHE_LIMIT (1024*1024*6)
-
-#define DIRCACHE_APPFLAG_TAGCACHE 0x0001
-#define DIRCACHE_APPFLAG_PLAYLIST 0x0002
-
-/* Internal structures. */
-struct travel_data {
- struct dircache_entry *first;
- struct dircache_entry *ce;
- struct dircache_entry *down_entry;
-#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
- DIR_UNCACHED *dir, *newdir;
- struct dirent_uncached *entry;
-#else
- struct fat_dir *dir;
- struct fat_dir newdir;
- struct fat_direntry entry;
+/****************************************************************************
+ ** Configurable values
+ **/
+
+#if 0
+/* enable dumping code */
+#define DIRCACHE_DUMPSTER
+#define DIRCACHE_DUMPSTER_BIN "/dircache_dump.bin"
+#define DIRCACHE_DUMPSTER_CSV "/dircache_dump.csv"
#endif
- int pathpos;
+
+/* dircache builds won't search below this but will work down to this point
+ while below it the cache will just pass requests through to the storage;
+ the limiting factor is the scanning thread stack size, not the
+ implementation -- tune the two together */
+#define DIRCACHE_MAX_DEPTH 15
+#define DIRCACHE_STACK_SIZE (DEFAULT_STACK_SIZE + 0x100)
+
+/* memory buffer constants that control allocation */
+#define DIRCACHE_RESERVE (1024*64) /* 64 KB - new entry slack */
+#define DIRCACHE_MIN (1024*1024*1) /* 1 MB - provision min size */
+#define DIRCACHE_LIMIT (1024*1024*6) /* 6 MB - provision max size */
+
+/* make it easy to change serialnumber size without modifying anything else;
+ 32 bits allows 21845 builds before wrapping in a 6MB cache that is filled
+ exclusively with entries and nothing else (32 byte entries), making that
+ figure pessimistic */
+typedef uint32_t dc_serial_t;
+
+/**
+ ****************************************************************************/
+
+#if CONFIG_PLATFORM & PLATFORM_NATIVE
+/* native dircache is lower-level than on a hosted target */
+#define DIRCACHE_NATIVE
+#endif
+
+struct dircache_file
+{
+ int idx; /* this file's cache index */
+ dc_serial_t serialnum; /* this file's serial number */
};
-struct dirent_cached {
- struct dirinfo info;
- char *d_name;
- long startcluster;
+enum dircache_status
+{
+ DIRCACHE_IDLE = 0, /* no volume is initialized */
+ DIRCACHE_SCANNING = 1, /* dircache is scanning a volume */
+ DIRCACHE_READY = 2, /* dircache is ready to be used */
+};
+
+/** Dircache control **/
+void dircache_wait(void);
+void dircache_suspend(void);
+int dircache_resume(void);
+int dircache_enable(void);
+void dircache_disable(void);
+void dircache_free_buffer(void);
+
+/** Volume mounting **/
+void dircache_mount(void); /* always tries building everything it can */
+void dircache_unmount(IF_MV_NONVOID(int volume));
+
+
+/** File API service functions **/
+
+/* avoid forcing #include of file_internal.h, fat.h and dir.h */
+struct filestr_base;
+struct file_base_info;
+struct file_base_binding;
+struct dirent;
+struct dirscan_info;
+struct dirinfo_native;
+
+int dircache_readdir_dirent(struct filestr_base *stream,
+ struct dirscan_info *scanp,
+ struct dirent *entry);
+void dircache_rewinddir_dirent(struct dirscan_info *scanp);
+
+#ifdef DIRCACHE_NATIVE
+struct fat_direntry;
+int dircache_readdir_internal(struct filestr_base *stream,
+ struct file_base_info *infop,
+ struct fat_direntry *fatent);
+void dircache_rewinddir_internal(struct file_base_info *info);
+#endif /* DIRCACHE_NATIVE */
+
+
+/** Dircache live updating **/
+
+void dircache_get_rootinfo(struct file_base_info *infop);
+void dircache_bind_file(struct file_base_binding *bindp);
+void dircache_unbind_file(struct file_base_binding *bindp);
+void dircache_fileop_create(struct file_base_info *dirinfop,
+ struct file_base_binding *bindp,
+ const char *basename,
+ const struct dirinfo_native *dinp);
+void dircache_fileop_rename(struct file_base_info *dirinfop,
+ struct file_base_binding *bindp,
+ const char *basename);
+void dircache_fileop_remove(struct file_base_binding *bindp);
+void dircache_fileop_sync(struct file_base_binding *infop,
+ const struct dirinfo_native *dinp);
+
+
+/** Dircache paths and files **/
+ssize_t dircache_get_path(const struct dircache_file *dcfilep, char *buf,
+ size_t size);
+int dircache_get_file(const char *path, struct dircache_file *dcfilep);
+
+
+/** Debug screen/info stuff **/
+
+struct dircache_info
+{
+ enum dircache_status status; /* current composite status value */
+ const char *statusdesc; /* pointer to string describing 'status' */
+ size_t last_size; /* cache size after last build */
+ size_t size; /* total size of entries (with holes) */
+ size_t sizeused; /* bytes of 'size' actually utilized */
+ size_t size_limit; /* maximum possible size */
+ size_t reserve; /* size of reserve area */
+ size_t reserve_used; /* amount of reserve used */
+ unsigned int entry_count; /* number of cache entries */
+ long build_ticks; /* total time used to build cache */
};
-typedef struct {
- bool busy;
- struct dirent_cached theent; /* .attribute is set to -1 on init(opendir) */
- int internal_entry; /* the current entry in the directory */
- DIR_UNCACHED *regulardir;
-} DIR_CACHED;
+void dircache_get_info(struct dircache_info *info);
+#ifdef DIRCACHE_DUMPSTER
+void dircache_dump(void);
+#endif /* DIRCACHE_DUMPSTER */
+
-void dircache_init(void) INIT_ATTR;
+/** Misc. stuff **/
+void dircache_dcfile_init(struct dircache_file *dcfilep);
+
+#ifdef HAVE_EEPROM_SETTINGS
int dircache_load(void);
int dircache_save(void);
-int dircache_build(int last_size);
-void* dircache_steal_buffer(size_t *size);
-bool dircache_is_enabled(void);
-bool dircache_is_initializing(void);
-void dircache_set_appflag(long mask);
-bool dircache_get_appflag(long mask);
-int dircache_get_entry_count(void);
-int dircache_get_cache_size(void);
-int dircache_get_reserve_used(void);
-int dircache_get_build_ticks(void);
-void dircache_disable(void);
-void dircache_suspend(void);
-bool dircache_resume(void);
-int dircache_get_entry_id(const char *filename);
-size_t dircache_copy_path(int index, char *buf, size_t size);
-
-/* the next two are internal for file.c */
-long _dircache_get_entry_startcluster(int id);
-struct dirinfo* _dircache_get_entry_dirinfo(int id);
-
-void dircache_bind(int fd, const char *path);
-void dircache_update_filesize(int fd, long newsize, long startcluster);
-void dircache_update_filetime(int fd);
-void dircache_mkdir(const char *path);
-void dircache_rmdir(const char *path);
-void dircache_remove(const char *name);
-void dircache_rename(const char *oldpath, const char *newpath);
-void dircache_add_file(const char *path, long startcluster);
-
-DIR_CACHED* opendir_cached(const char* name);
-struct dirent_cached* readdir_cached(DIR_CACHED* dir);
-int closedir_cached(DIR_CACHED *dir);
-int mkdir_cached(const char *name);
-int rmdir_cached(const char* name);
-#endif /* !HAVE_DIRCACHE */
+#endif /* HAVE_EEPROM_SETTINGS */
-#endif
+void dircache_init(size_t last_size) INIT_ATTR;
+
+#endif /* HAVE_DIRCACHE */
+
+#endif /* _DIRCACHE_H */
diff --git a/firmware/include/dircache_redirect.h b/firmware/include/dircache_redirect.h
new file mode 100644
index 0000000..15fb4bc
--- /dev/null
+++ b/firmware/include/dircache_redirect.h
@@ -0,0 +1,198 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2014 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _DIRCACHE_REDIRECT_H_
+
+#include "dir.h"
+
+/***
+ ** Internal redirects that depend upon whether or not dircache is made
+ **/
+
+/** File binding **/
+
+static inline void get_rootinfo_internal(struct file_base_info *infop)
+{
+#ifdef HAVE_DIRCACHE
+ dircache_get_rootinfo(infop);
+#else
+ (void)infop;
+#endif
+}
+
+static inline void fileobj_bind_file(struct file_base_binding *bindp)
+{
+#ifdef HAVE_DIRCACHE
+ dircache_bind_file(bindp);
+#else
+ file_binding_insert_last(bindp);
+#endif
+}
+
+static inline void fileobj_unbind_file(struct file_base_binding *bindp)
+{
+#ifdef HAVE_DIRCACHE
+ dircache_unbind_file(bindp);
+#else
+ file_binding_remove(bindp);
+#endif
+}
+
+
+/** File event handlers **/
+
+static inline void fileop_onopen_internal(struct filestr_base *stream,
+ struct file_base_info *srcinfop,
+ unsigned int callflags)
+{
+ fileobj_fileop_open(stream, srcinfop, callflags);
+}
+
+static inline void fileop_onclose_internal(struct filestr_base *stream)
+{
+ fileobj_fileop_close(stream);
+}
+
+static inline void fileop_oncreate_internal(struct filestr_base *stream,
+ struct file_base_info *srcinfop,
+ unsigned int callflags,
+ struct file_base_info *dirinfop,
+ const char *basename)
+{
+#ifdef HAVE_DIRCACHE
+ dircache_dcfile_init(&srcinfop->dcfile);
+#endif
+ fileobj_fileop_create(stream, srcinfop, callflags);
+#ifdef HAVE_DIRCACHE
+ struct dirinfo_native din;
+ fill_dirinfo_native(&din);
+ dircache_fileop_create(dirinfop, stream->bindp, basename, &din);
+#endif
+ (void)dirinfop; (void)basename;
+}
+
+static inline void fileop_onremove_internal(struct filestr_base *stream,
+ struct file_base_info *oldinfop)
+{
+ fileobj_fileop_remove(stream, oldinfop);
+#ifdef HAVE_DIRCACHE
+ dircache_fileop_remove(stream->bindp);
+#endif
+}
+
+static inline void fileop_onrename_internal(struct filestr_base *stream,
+ struct file_base_info *oldinfop,
+ struct file_base_info *dirinfop,
+ const char *basename)
+{
+ fileobj_fileop_rename(stream, oldinfop);
+#ifdef HAVE_DIRCACHE
+ dircache_fileop_rename(dirinfop, stream->bindp, basename);
+#endif
+ (void)dirinfop; (void)basename;
+}
+
+static inline void fileop_onsync_internal(struct filestr_base *stream)
+{
+ fileobj_fileop_sync(stream);
+#ifdef HAVE_DIRCACHE
+ struct dirinfo_native din;
+ fill_dirinfo_native(&din);
+ dircache_fileop_sync(stream->bindp, &din);
+#endif
+}
+
+static inline void fileop_ontruncate_internal(struct filestr_base *stream)
+{
+ fileobj_fileop_truncate(stream);
+}
+
+static inline void volume_onmount_internal(IF_MV_NONVOID(int volume))
+{
+#ifdef HAVE_DIRCACHE
+ dircache_mount();
+#endif
+ IF_MV( (void)volume; )
+}
+
+static inline void volume_onunmount_internal(IF_MV_NONVOID(int volume))
+{
+ fileobj_mgr_unmount(IF_MV(volume));
+#ifdef HAVE_DIRCACHE
+ dircache_unmount(IF_MV(volume));
+#endif
+}
+
+
+/** Directory reading **/
+
+static inline int readdir_dirent(struct filestr_base *stream,
+ struct dirscan_info *scanp,
+ struct dirent *entry)
+{
+#ifdef HAVE_DIRCACHE
+ return dircache_readdir_dirent(stream, scanp, entry);
+#else
+ return uncached_readdir_dirent(stream, scanp, entry);
+#endif
+}
+
+static inline void rewinddir_dirent(struct dirscan_info *scanp)
+{
+#ifdef HAVE_DIRCACHE
+ dircache_rewinddir_dirent(scanp);
+#else
+ uncached_rewinddir_dirent(scanp);
+#endif
+}
+
+static inline int readdir_internal(struct filestr_base *stream,
+ struct file_base_info *infop,
+ struct fat_direntry *fatent)
+{
+#ifdef HAVE_DIRCACHE
+ return dircache_readdir_internal(stream, infop, fatent);
+#else
+ return uncached_readdir_internal(stream, infop, fatent);
+#endif
+}
+
+static inline void rewinddir_internal(struct file_base_info *infop)
+{
+#ifdef HAVE_DIRCACHE
+ dircache_rewinddir_internal(infop);
+#else
+ uncached_rewinddir_internal(infop);
+#endif
+}
+
+
+/** Misc. stuff **/
+
+static inline struct fat_direntry *get_dir_fatent_dircache(void)
+{
+#ifdef HAVE_DIRCACHE
+ return get_dir_fatent();
+#else
+ return NULL;
+#endif
+}
+
+#endif /* _DIRCACHE_REDIRECT_H_ */
diff --git a/firmware/include/disk_cache.h b/firmware/include/disk_cache.h
new file mode 100644
index 0000000..725b377
--- /dev/null
+++ b/firmware/include/disk_cache.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2014 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef DISK_CACHE_H
+#define DISK_CACHE_H
+
+/* This needs enough for all file handles to have a buffer in the worst case
+ * plus at least one reserved exclusively for the cache client and a couple
+ * for other file system code. The buffers are put to use by the cache if not
+ * taken for another purpose (meaning nothing is wasted sitting fallow).
+ *
+ * One map per volume is maintained in order to avoid collisions between
+ * volumes that would slow cache probing. DC_MAP_NUM_ENTRIES is the number
+ * for each map per volume. The buffers themselves are shared.
+ */
+#if MEMORYSIZE < 8
+#define DC_NUM_ENTRIES 32
+#define DC_MAP_NUM_ENTRIES 128
+#elif MEMORYSIZE <= 32
+#define DC_NUM_ENTRIES 48
+#define DC_MAP_NUM_ENTRIES 128
+#else /* MEMORYSIZE > 32 */
+#define DC_NUM_ENTRIES 64
+#define DC_MAP_NUM_ENTRIES 256
+#endif /* MEMORYSIZE */
+
+/* this _could_ be larger than a sector if that would ever be useful */
+#define DC_CACHE_BUFSIZE SECTOR_SIZE
+
+#include "mutex.h"
+#include "mv.h"
+
+static inline void dc_lock_cache(void)
+{
+ extern struct mutex disk_cache_mutex;
+ mutex_lock(&disk_cache_mutex);
+}
+
+static inline void dc_unlock_cache(void)
+{
+ extern struct mutex disk_cache_mutex;
+ mutex_unlock(&disk_cache_mutex);
+}
+
+void * dc_cache_probe(IF_MV(int volume,) unsigned long secnum,
+ unsigned int *flags);
+void dc_dirty_buf(void *buf);
+void dc_discard_buf(void *buf);
+void dc_commit_all(IF_MV_NONVOID(int volume));
+void dc_discard_all(IF_MV_NONVOID(int volume));
+
+void dc_init(void) INIT_ATTR;
+
+/* in addition to filling, writeback is implemented by the client */
+extern void dc_writeback_callback(IF_MV(int volume, ) unsigned long sector,
+ void *buf);
+
+
+/** These synchronize and can be called by anyone **/
+
+/* expropriate a buffer from the cache of DC_CACHE_BUFSIZE bytes */
+void * dc_get_buffer(void);
+/* return buffer to the cache by buffer */
+void dc_release_buffer(void *buf);
+
+#endif /* DISK_CACHE_H */
diff --git a/firmware/include/file.h b/firmware/include/file.h
index 7793086..8e5bace 100644
--- a/firmware/include/file.h
+++ b/firmware/include/file.h
@@ -18,81 +18,88 @@
* KIND, either express or implied.
*
****************************************************************************/
-
#ifndef _FILE_H_
#define _FILE_H_
#include <sys/types.h>
-#include "config.h"
-#include "gcc_extensions.h"
+#include <stdbool.h>
#include <fcntl.h>
#ifdef WIN32
/* this has SEEK_SET et al */
#include <stdio.h>
#endif
-
+#include "config.h"
+#include "gcc_extensions.h"
#undef MAX_PATH /* this avoids problems when building simulator */
#define MAX_PATH 260
-#define MAX_OPEN_FILES 11
-#if !defined(PLUGIN) && !defined(CODEC)
-#if defined(APPLICATION) && !defined(__PCTOOL__)
-#include "rbpaths.h"
-# define open(x, ...) app_open(x, __VA_ARGS__)
-# define creat(x,m) app_creat(x, m)
-# define remove(x) app_remove(x)
-# define rename(x,y) app_rename(x,y)
-# define readlink(x,y,z) app_readlink(x,y,z)
-# if (CONFIG_PLATFORM & (PLATFORM_SDL|PLATFORM_MAEMO|PLATFORM_PANDORA))
-/* SDL overrides a few more */
-# define read(x,y,z) sim_read(x,y,z)
-# define write(x,y,z) sim_write(x,y,z)
-# endif
-#elif defined(SIMULATOR) || defined(DBTOOL)
-# define open(x, ...) sim_open(x, __VA_ARGS__)
-# define creat(x,m) sim_creat(x,m)
-# define remove(x) sim_remove(x)
-# define rename(x,y) sim_rename(x,y)
-# define fsync(x) sim_fsync(x)
-# define ftruncate(x,y) sim_ftruncate(x,y)
-# define lseek(x,y,z) sim_lseek(x,y,z)
-# define read(x,y,z) sim_read(x,y,z)
-# define write(x,y,z) sim_write(x,y,z)
-# define close(x) sim_close(x)
-/* readlink() not used in the sim yet */
-extern int sim_open(const char *name, int o, ...);
-extern int sim_creat(const char *name, mode_t mode);
-#endif
+enum relate_result
+{
+ /* < 0 == failure */
+ RELATE_DIFFERENT = 0, /* the two paths are different objects */
+ RELATE_SAME, /* the two paths are the same object */
+ RELATE_PREFIX, /* the path2 contains path1 as a prefix */
+};
-typedef int (*open_func)(const char* pathname, int flags, ...);
-typedef ssize_t (*read_func)(int fd, void *buf, size_t count);
-typedef int (*creat_func)(const char *pathname, mode_t mode);
-typedef ssize_t (*write_func)(int fd, const void *buf, size_t count);
-typedef void (*qsort_func)(void *base, size_t nmemb, size_t size,
- int(*_compar)(const void *, const void *));
+#if defined(APPLICATION)
+#include "filesystem-app.h"
+#elif defined(SIMULATOR) || defined(__PCTOOL__)
+#include "../../uisimulator/common/filesystem-sim.h"
+#else
+#include "filesystem-native.h"
+#endif
-extern int file_open(const char* pathname, int flags);
-extern int close(int fd);
-extern int fsync(int fd);
-extern ssize_t read(int fd, void *buf, size_t count);
-extern off_t lseek(int fildes, off_t offset, int whence);
-extern int file_creat(const char *pathname);
-#if ((CONFIG_PLATFORM & PLATFORM_NATIVE) && !defined(__PCTOOL__)) || \
- defined(TEST_FAT)
-#define creat(x, y) file_creat(x)
+#ifndef FILEFUNCTIONS_DECLARED
+int fdprintf(int fildes, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
+#endif /* FILEFUNCTIONS_DECLARED */
-#if !defined(CODEC) && !defined(PLUGIN)
-#define open(x, y, ...) file_open(x,y)
+#ifndef FILEFUNCTIONS_DEFINED
+#ifndef open
+#define open FS_PREFIX(open)
#endif
+#ifndef creat
+#define creat FS_PREFIX(creat)
#endif
-
-extern ssize_t write(int fd, const void *buf, size_t count);
-extern int remove(const char* pathname);
-extern int rename(const char* path, const char* newname);
-extern int ftruncate(int fd, off_t length);
-extern off_t filesize(int fd);
-extern int release_files(int volume);
-int fdprintf (int fd, const char *fmt, ...) ATTRIBUTE_PRINTF(2, 3);
-#endif /* !CODEC && !PLUGIN */
+#ifndef close
+#define close FS_PREFIX(close)
+#endif
+#ifndef ftruncate
+#define ftruncate FS_PREFIX(ftruncate)
+#endif
+#ifndef fsync
+#define fsync FS_PREFIX(fsync)
#endif
+#ifndef lseek
+#define lseek FS_PREFIX(lseek)
+#endif
+#ifndef read
+#define read FS_PREFIX(read)
+#endif
+#ifndef write
+#define write FS_PREFIX(write)
+#endif
+#ifndef remove
+#define remove FS_PREFIX(remove)
+#endif
+#ifndef rename
+#define rename FS_PREFIX(rename)
+#endif
+#ifndef filesize
+#define filesize FS_PREFIX(filesize)
+#endif
+#ifndef fsamefile
+#define fsamefile FS_PREFIX(fsamefile)
+#endif
+#ifndef file_exists
+#define file_exists FS_PREFIX(file_exists)
+#endif
+#ifndef relate
+#define relate FS_PREFIX(relate)
+#endif
+#ifndef readlink
+#define readlink FS_PREFIX(readlink)
+#endif
+#endif /* FILEFUNCTIONS_DEFINED */
+
+#endif /* _FILE_H_ */
diff --git a/firmware/include/file_internal.h b/firmware/include/file_internal.h
new file mode 100644
index 0000000..d1bb674
--- /dev/null
+++ b/firmware/include/file_internal.h
@@ -0,0 +1,371 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2014 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FILE_INTERNAL_H_
+#define _FILE_INTERNAL_H_
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include "mv.h"
+#include "linked_list.h"
+#include "mutex.h"
+#include "mrsw_lock.h"
+#include "fs_attr.h"
+#include "fat.h"
+#ifdef HAVE_DIRCACHE
+#include "dircache.h"
+#endif
+
+/** Tuneable parameters **/
+
+/* limits for number of open descriptors - if you increase these values, make
+ certain that the disk cache has enough available buffers */
+#define MAX_OPEN_FILES 11
+#define MAX_OPEN_DIRS 12
+#define MAX_OPEN_HANDLES (MAX_OPEN_FILES+MAX_OPEN_DIRS)
+
+/* internal functions open streams as well; make sure they don't fail if all
+ user descs are busy; this needs to be at least the greatest quantity needed
+ at once by all internal functions */
+#ifdef HAVE_DIRCACHE
+#define AUX_FILEOBJS 3
+#else
+#define AUX_FILEOBJS 2
+#endif
+
+/* number of components statically allocated to handle the vast majority
+ of path depths; should maybe be tuned for >= 90th percentile but for now,
+ imma just guessing based on something like:
+ root + 'Music' + 'Artist' + 'Album' + 'Disc N' + filename */
+#define STATIC_PATHCOMP_NUM 6
+
+#define MAX_NAME 255
+
+/* unsigned value that will also hold the off_t range we need without
+ overflow */
+#define file_size_t uint32_t
+
+#ifdef __USE_FILE_OFFSET64
+/* if we want, we can deal with files up to 2^32-1 bytes-- the full FAT16/32
+ range */
+#define FILE_SIZE_MAX (0xffffffffu)
+#else
+/* file contents and size will be preserved by the APIs so long as ftruncate()
+ isn't used; bytes passed 2^31-1 will not accessible nor will writes succeed
+ that would extend the file beyond the max for a 32-bit off_t */
+#define FILE_SIZE_MAX (0x7fffffffu)
+#endif
+
+/* if file is "large(ish)", then get rid of the contents now rather than
+ lazily when the file is synced or closed in order to free-up space */
+#define O_TRUNC_THRESH 65536
+
+/* default attributes when creating new files and directories */
+#define ATTR_NEW_FILE (ATTR_ARCHIVE)
+#define ATTR_NEW_DIRECTORY (ATTR_DIRECTORY)
+
+#define ATTR_MOUNT_POINT (ATTR_VOLUME | ATTR_DIRECTORY)
+
+/** File sector cache **/
+
+enum filestr_cache_flags
+{
+ FSC_DIRTY = 0x1, /* buffer is dirty (needs writeback) */
+ FSC_NEW = 0x2, /* buffer is new (never yet written) */
+};
+
+struct filestr_cache
+{
+ uint8_t *buffer; /* buffer to hold sector */
+ unsigned long sector; /* file sector that is in buffer */
+ unsigned int flags; /* FSC_* bits */
+};
+
+void file_cache_init(struct filestr_cache *cachep);
+void file_cache_reset(struct filestr_cache *cachep);
+void file_cache_alloc(struct filestr_cache *cachep);
+void file_cache_free(struct filestr_cache *cachep);
+
+
+/** Common bitflags used throughout **/
+
+/* bitflags used by open files and descriptors */
+enum fildes_and_obj_flags
+{
+ /* used in descriptor and common */
+ FDO_BUSY = 0x0001, /* descriptor/object is in use */
+ /* only used in individual stream descriptor */
+ FD_WRITE = 0x0002, /* descriptor has write mode */
+ FD_WRONLY = 0x0004, /* descriptor is write mode only */
+ FD_APPEND = 0x0008, /* descriptor is append mode */
+ /* only used as common flags */
+ FO_DIRECTORY = 0x0010, /* fileobj is a directory */
+ FO_TRUNC = 0x0020, /* fileobj is opened to be truncated */
+ FO_REMOVED = 0x0040, /* fileobj was deleted while open */
+ FO_SINGLE = 0x0080, /* fileobj has only one stream open */
+ FDO_MASK = 0x00ff,
+ /* bitflags that instruct various 'open' functions how to behave */
+ FF_FILE = 0x0000, /* expect file; accept file only */
+ FF_DIR = 0x0100, /* expect dir; accept dir only */
+ FF_ANYTYPE = 0x0200, /* succeed if either file or dir */
+ FF_TYPEMASK = 0x0300, /* mask of typeflags */
+ FF_CREAT = 0x0400, /* create if file doesn't exist */
+ FF_EXCL = 0x0800, /* fail if creating and file exists */
+ FF_CHECKPREFIX = 0x1000, /* detect if file is prefix of path */
+ FF_NOISO = 0x2000, /* do not decode ISO filenames to UTF-8 */
+ FF_MASK = 0x3f00,
+ /* special values used in isolation */
+ FV_NONEXIST = 0x8000, /* closed but not freed (unmounted) */
+ FV_OPENSYSROOT = 0xc001, /* open sysroot, volume 0 not mounted */
+};
+
+
+/** Common data structures used throughout **/
+
+/* basic file information about its location */
+struct file_base_info
+{
+ union {
+#ifdef HAVE_MULTIVOLUME
+ int volume; /* file's volume (overlaps fatfile.volume) */
+#endif
+#if CONFIG_PLATFORM & PLATFORM_NATIVE
+ struct fat_file fatfile; /* FS driver file info */
+#endif
+ };
+#ifdef HAVE_DIRCACHE
+ struct dircache_file dcfile; /* dircache file info */
+#endif
+};
+
+#define BASEINFO_VOL(infop) \
+ IF_MV_VOL((infop)->volume)
+
+/* open files binding item */
+struct file_base_binding
+{
+ struct ll_node node; /* list item node (first!) */
+ struct file_base_info info; /* basic file info */
+};
+
+#define BASEBINDING_VOL(bindp) \
+ BASEINFO_VOL(&(bindp)->info)
+
+/* directory scanning position info */
+struct dirscan_info
+{
+#if CONFIG_PLATFORM & PLATFORM_NATIVE
+ struct fat_dirscan_info fatscan; /* FS driver scan info */
+#endif
+#ifdef HAVE_DIRCACHE
+ struct dircache_file dcscan; /* dircache scan info */
+#endif
+};
+
+/* describes the file as an open stream */
+struct filestr_base
+{
+ struct ll_node node; /* list item node (first!) */
+ uint16_t flags; /* FD_* bits of this stream */
+ uint16_t unused; /* not used */
+ struct filestr_cache cache; /* stream-local cache */
+ struct filestr_cache *cachep; /* the cache in use (local or shared) */
+ struct file_base_info *infop; /* base file information */
+ struct fat_filestr fatstr; /* FS driver information */
+ struct file_base_binding *bindp; /* common binding for file/dir */
+ struct mutex *mtx; /* serialization for this stream */
+};
+
+void filestr_base_init(struct filestr_base *stream);
+void filestr_base_destroy(struct filestr_base *stream);
+void filestr_alloc_cache(struct filestr_base *stream);
+void filestr_free_cache(struct filestr_base *stream);
+void filestr_assign_cache(struct filestr_base *stream,
+ struct filestr_cache *cachep);
+void filestr_copy_cache(struct filestr_base *stream,
+ struct filestr_cache *cachep);
+void filestr_discard_cache(struct filestr_base *stream);
+
+/* allocates a cache buffer if needed and returns the cache pointer */
+static inline struct filestr_cache *
+filestr_get_cache(struct filestr_base *stream)
+{
+ struct filestr_cache *cachep = stream->cachep;
+
+ if (!cachep->buffer)
+ filestr_alloc_cache(stream);
+
+ return cachep;
+}
+
+static inline void filestr_lock(struct filestr_base *stream)
+{
+ mutex_lock(stream->mtx);
+}
+
+static inline void filestr_unlock(struct filestr_base *stream)
+{
+ mutex_unlock(stream->mtx);
+}
+
+/* stream lock doesn't have to be used if getting RW lock writer access */
+#define FILESTR_WRITER 0
+#define FILESTR_READER 1
+
+#define FILESTR_LOCK(type, stream) \
+ ({ if (FILESTR_##type) filestr_lock(stream); })
+
+#define FILESTR_UNLOCK(type, stream) \
+ ({ if (FILESTR_##type) filestr_unlock(stream); })
+
+#define ATTR_PREFIX (0x8000) /* out of the way of all ATTR_* bits */
+
+/* structure to return detailed information about what you opened */
+struct path_component_info
+{
+ const char *name; /* pointer to name within 'path' */
+ size_t length; /* length of component within 'path' */
+ file_size_t filesize; /* size of the opened file (0 if dir) */
+ unsigned int attr; /* attributes of this component */
+ struct file_base_info *prefixp; /* base info to check as prefix (IN) */
+ struct file_base_info parentinfo; /* parent directory info of file */
+};
+
+int open_stream_internal(const char *path, unsigned int callflags,
+ struct filestr_base *stream,
+ struct path_component_info *compinfo);
+int close_stream_internal(struct filestr_base *stream);
+int create_stream_internal(struct file_base_info *parentinfop,
+ const char *basename, size_t length,
+ unsigned int attr, unsigned int callflags,
+ struct filestr_base *stream);
+int remove_stream_internal(const char *path, struct filestr_base *stream,
+ unsigned int callflags);
+int test_stream_exists_internal(const char *path, unsigned int callflags);
+
+int open_noiso_internal(const char *path, int oflag); /* file.c */
+
+struct dirent;
+int uncached_readdir_dirent(struct filestr_base *stream,
+ struct dirscan_info *scanp,
+ struct dirent *entry);
+void uncached_rewinddir_dirent(struct dirscan_info *scanp);
+
+int uncached_readdir_internal(struct filestr_base *stream,
+ struct file_base_info *infop,
+ struct fat_direntry *fatent);
+void uncached_rewinddir_internal(struct file_base_info *infop);
+
+int test_dir_empty_internal(struct filestr_base *stream);
+
+struct dirinfo_internal
+{
+ unsigned int attr;
+ file_size_t size;
+ uint16_t wrtdate;
+ uint16_t wrttime;
+};
+
+/** Synchronization used throughout **/
+
+/* acquire the filesystem lock as READER */
+static inline void file_internal_lock_READER(void)
+{
+ extern struct mrsw_lock file_internal_mrsw;
+ mrsw_read_acquire(&file_internal_mrsw);
+}
+
+/* release the filesystem lock as READER */
+static inline void file_internal_unlock_READER(void)
+{
+ extern struct mrsw_lock file_internal_mrsw;
+ mrsw_read_release(&file_internal_mrsw);
+}
+
+/* acquire the filesystem lock as WRITER */
+static inline void file_internal_lock_WRITER(void)
+{
+ extern struct mrsw_lock file_internal_mrsw;
+ mrsw_write_acquire(&file_internal_mrsw);
+}
+
+/* release the filesystem lock as WRITER */
+static inline void file_internal_unlock_WRITER(void)
+{
+ extern struct mrsw_lock file_internal_mrsw;
+ mrsw_write_release(&file_internal_mrsw);
+}
+
+#define ERRNO 0 /* maintain errno value */
+#define RC 0 /* maintain rc value */
+
+/* NOTES: if _errno is a non-constant expression, it must set an error
+ * number and not return the ERRNO constant which will merely set
+ * errno to zero, not preserve the current value; if you must set
+ * errno to zero, set it explicitly, not in the macro
+ *
+ * if _rc is constant-expression evaluation to 'RC', then rc will
+ * NOT be altered; i.e. if you must set rc to zero, set it explicitly,
+ * not in the macro
+ */
+
+/* set errno and rc and proceed to the "file_error:" label */
+#define FILE_ERROR(_errno, _rc) \
+ ({ __builtin_constant_p(_errno) ? \
+ ({ if ((_errno) != ERRNO) errno = (_errno); }) : \
+ ({ errno = (_errno); }); \
+ __builtin_constant_p(_rc) ? \
+ ({ if ((_rc) != RC) rc = (_rc); }) : \
+ ({ rc = (_rc); }); \
+ goto file_error; })
+
+/* set errno and return a value at the point of invocation */
+#define FILE_ERROR_RETURN(_errno, _rc...) \
+ ({ __builtin_constant_p(_errno) ? \
+ ({ if ((_errno) != ERRNO) errno = (_errno); }) : \
+ ({ errno = (_errno); }); \
+ return _rc; })
+
+
+/** Misc. stuff **/
+
+/* iterate through all the volumes if volume < 0, else just the given volume */
+#define FOR_EACH_VOLUME(volume, i) \
+ for (int i = (IF_MV_VOL(volume) >= 0 ? IF_MV_VOL(volume) : 0), \
+ _end = (IF_MV_VOL(volume) >= 0 ? i : NUM_VOLUMES-1); \
+ i <= _end; i++)
+
+/* return a pointer to the static struct fat_direntry */
+static inline struct fat_direntry *get_dir_fatent(void)
+{
+ extern struct fat_direntry dir_fatent;
+ return &dir_fatent;
+}
+
+void iso_decode_d_name(char *d_name);
+
+#ifdef HAVE_DIRCACHE
+void empty_dirent(struct dirent *entry);
+void fill_dirinfo_native(struct dirinfo_native *din);
+#endif /* HAVE_DIRCACHE */
+
+void filesystem_init(void) INIT_ATTR;
+
+#endif /* _FILE_INTERNAL_H_ */
diff --git a/firmware/include/fileobj_mgr.h b/firmware/include/fileobj_mgr.h
new file mode 100644
index 0000000..c90a59b
--- /dev/null
+++ b/firmware/include/fileobj_mgr.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2014 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FILEOBJ_MGR_H_
+#define _FILEOBJ_MGR_H_
+
+#include "file_internal.h"
+
+void file_binding_insert_first(struct file_base_binding *bindp);
+void file_binding_insert_last(struct file_base_binding *bindp);
+void file_binding_remove(struct file_base_binding *bindp);
+void file_binding_remove_next(struct file_base_binding *prevp,
+ struct file_base_binding *bindp);
+
+void fileobj_fileop_open(struct filestr_base *stream,
+ const struct file_base_info *srcinfop,
+ unsigned int callflags);
+void fileobj_fileop_close(struct filestr_base *stream);
+void fileobj_fileop_create(struct filestr_base *stream,
+ const struct file_base_info *srcinfop,
+ unsigned int callflags);
+void fileobj_fileop_rename(struct filestr_base *stream,
+ const struct file_base_info *oldinfop);
+void fileobj_fileop_remove(struct filestr_base *stream,
+ const struct file_base_info *oldinfop);
+void fileobj_fileop_sync(struct filestr_base *stream);
+void fileobj_fileop_truncate(struct filestr_base *stream);
+extern void ftruncate_internal_callback(struct filestr_base *stream,
+ struct filestr_base *s);
+
+file_size_t * fileobj_get_sizep(const struct filestr_base *stream);
+unsigned int fileobj_get_flags(const struct filestr_base *stream);
+void fileobj_change_flags(struct filestr_base *stream,
+ unsigned int flags, unsigned int mask);
+void fileobj_mgr_unmount(IF_MV_NONVOID(int volume));
+
+void fileobj_mgr_init(void) INIT_ATTR;
+
+#endif /* _FILEOBJ_MGR_H_ */
diff --git a/firmware/include/filesystem-native.h b/firmware/include/filesystem-native.h
new file mode 100644
index 0000000..640e179
--- /dev/null
+++ b/firmware/include/filesystem-native.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Björn Stenberg
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FILESYSTEM_NATIVE_H_
+#define _FILESYSTEM_NATIVE_H_
+
+#if defined(PLUGIN) || defined(CODEC)
+#define FILEFUNCTIONS_DECLARED
+#define FILEFUNCTIONS_DEFINED
+#define DIRFUNCTIONS_DECLARED
+#define DIRFUNCTIONS_DEFINED
+#endif /* PLUGIN || CODEC */
+
+#define FS_PREFIX(_x_) _x_
+#endif /* _FILESYSTEM_NATIVE_H_ */
+
+#ifdef _FILE_H_
+#ifndef _FILESYSTEM_NATIVE__FILE_H_
+#define _FILESYSTEM_NATIVE__FILE_H_
+
+#ifdef RB_FILESYSTEM_OS
+#define FILEFUNCTIONS_DEFINED
+#endif
+
+#ifndef FILEFUNCTIONS_DECLARED
+#define __OPEN_MODE_ARG
+#define __CREAT_MODE_ARG
+
+int open(const char *name, int oflag);
+int creat(const char *name);
+int close(int fildes);
+int ftruncate(int fildes, off_t length);
+int fsync(int fildes);
+off_t lseek(int fildes, off_t offset, int whence);
+ssize_t read(int fildes, void *buf, size_t nbyte);
+ssize_t write(int fildes, const void *buf, size_t nbyte);
+int remove(const char *path);
+int rename(const char *old, const char *new);
+off_t filesize(int fildes);
+int fsamefile(int fildes1, int fildes2);
+int relate(const char *path1, const char *path2);
+bool file_exists(const char *path);
+#endif /* !FILEFUNCTIONS_DECLARED */
+
+#if !defined(RB_FILESYSTEM_OS) && !defined (FILEFUNCTIONS_DEFINED)
+#define open(path, oflag, ...) open(path, oflag)
+#define creat(path, mode) creat(path)
+#endif /* FILEFUNCTIONS_DEFINED */
+
+#endif /* _FILESYSTEM_NATIVE__FILE_H_ */
+#endif /* _FILE_H_ */
+
+#ifdef _DIR_H_
+#ifndef _FILESYSTEM_NATIVE__DIR_H_
+#define _FILESYSTEM_NATIVE__DIR_H_
+
+#define DIRENT dirent
+struct dirent;
+
+struct dirinfo_native
+{
+ unsigned int attr;
+ off_t size;
+ uint16_t wrtdate;
+ uint16_t wrttime;
+};
+
+typedef struct {} DIR;
+
+#ifndef DIRFUNCTIONS_DECLARED
+#define __MKDIR_MODE_ARG
+
+#ifdef RB_FILESYSTEM_OS
+#define DIRFUNCTIONS_DEFINED
+#endif
+
+DIR * opendir(const char *dirname);
+struct dirent * readdir(DIR *dirp);
+int readdir_r(DIR *dirp, struct dirent *entry,
+ struct dirent **result);
+void rewinddir(DIR *dirp);
+int closedir(DIR *dirp);
+int mkdir(const char *path);
+int rmdir(const char *path);
+int samedir(DIR *dirp1, DIR *dirp2);
+bool dir_exists(const char *dirname);
+#endif /* !DIRFUNCTIONS_DECLARED */
+
+#endif /* _FILESYSTEM_NATIVE__DIR_H_ */
+#endif /* _DIR_H_ */
diff --git a/firmware/include/fs_attr.h b/firmware/include/fs_attr.h
new file mode 100644
index 0000000..0e1d25e
--- /dev/null
+++ b/firmware/include/fs_attr.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Kévin Ferrare
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _FS_ATTR_H_
+#define _FS_ATTR_H_
+
+#include <stdbool.h>
+
+#undef MAX_PATH /* this avoids problems when building simulator */
+#define MAX_PATH 260
+
+/* also used by fat.c so values must not change */
+#define ATTR_READ_ONLY 0x01
+#define ATTR_HIDDEN 0x02
+#define ATTR_SYSTEM 0x04
+#define ATTR_VOLUME_ID 0x08
+#define ATTR_DIRECTORY 0x10
+#define ATTR_ARCHIVE 0x20
+#define ATTR_VOLUME 0x40 /* this is a volume, not a real directory */
+#define ATTR_LINK 0x80
+
+#endif /* _FS_ATTR_H_ */
diff --git a/firmware/include/rb-loader.h b/firmware/include/rb-loader.h
index e1e756d..86c5026 100644
--- a/firmware/include/rb-loader.h
+++ b/firmware/include/rb-loader.h
@@ -18,5 +18,4 @@
*
****************************************************************************/
-const char *rb_strerror(int8_t errno);
int load_firmware(unsigned char* buf, const char* firmware, int buffer_size);
diff --git a/firmware/include/rbunicode.h b/firmware/include/rbunicode.h
index 3c28b30..0770293 100644
--- a/firmware/include/rbunicode.h
+++ b/firmware/include/rbunicode.h
@@ -51,7 +51,8 @@ enum codepages {
KSX_1001, /* Korean */
BIG_5, /* Trad. Chinese */
UTF_8, /* Unicode */
- NUM_CODEPAGES
+ NUM_CODEPAGES,
+ INIT_CODEPAGE = ISO_8859_1,
};
#else /* !HAVE_LCD_BITMAP, reduced support */
@@ -65,7 +66,8 @@ enum codepages {
WIN_1250, /* Central European */
WIN_1252, /* Western European */
UTF_8, /* Unicode */
- NUM_CODEPAGES
+ NUM_CODEPAGES,
+ INIT_CODEPAGE = ISO_8859_1,
};
#endif
@@ -78,9 +80,19 @@ unsigned char* utf16BEdecode(const unsigned char *utf16, unsigned char *utf8, in
unsigned long utf8length(const unsigned char *utf8);
const unsigned char* utf8decode(const unsigned char *utf8, unsigned short *ucs);
void set_codepage(int cp);
+int get_codepage(void);
int utf8seek(const unsigned char* utf8, int offset);
const char* get_codepage_name(int cp);
-#if defined(APPLICATION) && defined(__linux__)
+#ifdef APPLICATION
+#if defined(__linux__)
const char *get_current_codepage_name_linux(void);
#endif
+#endif /* APPLICATION */
+
+#if 0 /* not needed just now */
+void unicode_init(void);
+#else
+#define unicode_init() do {} while (0)
+#endif
+
#endif /* _RBUNICODE_H_ */