Index: firmware/export/config.h =================================================================== --- firmware/export/config.h (revision 16172) +++ firmware/export/config.h (working copy) @@ -304,7 +304,7 @@ /* Enable the directory cache and tagcache in RAM if we have * plenty of RAM. Both features can be enabled independently. */ #if ((defined(MEMORYSIZE) && (MEMORYSIZE > 8)) || MEM > 8) && \ - !defined(BOOTLOADER) && !defined(SANSA_E200) && !defined(SANSA_C200) + !defined(BOOTLOADER) #define HAVE_DIRCACHE #ifdef HAVE_TAGCACHE #define HAVE_TC_RAMCACHE Index: firmware/include/dir_uncached.h =================================================================== --- firmware/include/dir_uncached.h (revision 16172) +++ firmware/include/dir_uncached.h (working copy) @@ -75,6 +75,10 @@ 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); Index: firmware/include/dir.h =================================================================== --- firmware/include/dir.h (revision 16172) +++ firmware/include/dir.h (working copy) @@ -22,6 +22,23 @@ #include "config.h" +#ifdef HAVE_MULTIVOLUME + +/* how to name volumes, first char must be outside of legal file names, + a number gets appended to enumerate, if applicable */ +#ifdef HAVE_MMC +#define VOL_NAMES "" +#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ +#elif defined(HAVE_HOTSWAP) +#define VOL_NAMES "" +#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */ +#else +#define VOL_NAMES "" +#define VOL_ENUM_POS 3 +#endif + +#endif + #ifdef HAVE_DIRCACHE # include "dircache.h" # define DIR DIR_CACHED Index: firmware/common/dircache.c =================================================================== --- firmware/common/dircache.c (revision 16172) +++ firmware/common/dircache.c (working copy) @@ -37,6 +37,7 @@ #include "usb.h" #include "file.h" #include "buffer.h" +#include "dir.h" #if CONFIG_RTC #include "time.h" #include "timefuncs.h" @@ -70,6 +71,10 @@ static struct fdbind_queue fdbind_cache[MAX_PENDING_BINDINGS]; static int fdbind_idx = 0; +#ifdef HAVE_MULTIVOLUME +struct dircache_entry *append_position; +#endif /* #ifdef HAVE_MULTIVOLUME */ + /* --- Internal cache structure control functions --- */ /** @@ -155,6 +162,10 @@ { case DIRCACHE_STOP: case SYS_USB_CONNECTED: +#ifdef HAVE_HOTSWAP + case SYS_HOTSWAP_EXTRACTED: + case SYS_HOTSWAP_INSERTED: +#endif /* Put the event back into the queue. */ queue_post(&dircache_queue, ev.id, ev.data); return true; @@ -166,7 +177,7 @@ /** * Internal function to iterate a path. */ -static int dircache_scan(struct travel_data *td) +static int dircache_scan(IF_MV2(int volume,) struct travel_data *td) { #ifdef SIMULATOR while ( ( td->entry = readdir_uncached(td->dir) ) ) @@ -273,22 +284,35 @@ * Recursively scan the hard disk and build the cache. */ #ifdef SIMULATOR -static int dircache_travel(DIR_UNCACHED *dir, struct dircache_entry *ce) +static int dircache_travel(IF_MV2(int volume,) DIR_UNCACHED *dir, struct dircache_entry *ce) #else -static int dircache_travel(struct fat_dir *dir, struct dircache_entry *ce) +static int dircache_travel(IF_MV2(int volume,) struct fat_dir *dir, struct dircache_entry *ce) #endif { int depth = 0; int result; memset(ce, 0, sizeof(struct dircache_entry)); + +#if defined(HAVE_MULTIVOLUME) && !defined(SIMULATOR) + if (volume > 0) + { + snprintf(ce->d_name, VOL_ENUM_POS + 3, VOL_NAMES, volume); + ce->name_len = VOL_ENUM_POS + 3; + ce->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME; + ce->size = 0; + append_position = dircache_gen_next(ce); + ce = dircache_gen_down(ce); + } +#endif + dir_recursion[0].dir = dir; dir_recursion[0].ce = ce; dir_recursion[0].first = ce; do { //logf("=> %s", dircache_cur_path); - result = dircache_scan(&dir_recursion[depth]); + result = dircache_scan(IF_MV2(volume,) &dir_recursion[depth]); switch (result) { case 0: /* Leaving the current directory. */ /* Add the standard . and .. entries. */ @@ -536,7 +560,9 @@ start_tick = current_tick; dircache_initializing = true; appflags = 0; + entry_count = 0; +#if !defined(HAVE_MULTIVOLUME) || defined(SIMULATOR) #ifdef SIMULATOR pdir = opendir_uncached("/"); if (pdir == NULL) @@ -546,7 +572,7 @@ return -3; } #else - if ( fat_opendir(IF_MV2(volume,) &dir, 0, NULL) < 0 ) { + if ( fat_opendir(IF_MV2(0,) &dir, 0, NULL) < 0 ) { logf("Failed opening root dir"); dircache_initializing = false; return -3; @@ -558,7 +584,7 @@ dircache_size = sizeof(struct dircache_entry); cpu_boost(true); - if (dircache_travel(pdir, dircache_root) < 0) + if (dircache_travel(IF_MV2(0,) pdir, dircache_root) < 0) { logf("dircache_travel failed"); cpu_boost(false); @@ -567,7 +593,36 @@ return -2; } cpu_boost(false); +#else + memset(dircache_cur_path, 0, sizeof(dircache_cur_path)); + dircache_size = sizeof(struct dircache_entry); + append_position = dircache_root; + + for (i = NUM_VOLUMES; i >= 0; i--) + { + if (fat_ismounted(i)) + { + if ( fat_opendir(IF_MV2(i,) &dir, 0, NULL) < 0 ) { + logf("Failed opening root dir"); + dircache_initializing = false; + return -3; + } + pdir = &dir; + cpu_boost(true); + if (dircache_travel(IF_MV2(i,) pdir, append_position) < 0) + { + logf("dircache_travel failed"); + cpu_boost(false); + dircache_size = 0; + dircache_initializing = false; + return -2; + } + cpu_boost(false); + } + } +#endif + logf("Done, %ld KiB used", dircache_size / 1024); dircache_initialized = true; @@ -610,6 +665,12 @@ switch (ev.id) { +#ifdef HAVE_HOTSWAP + case SYS_HOTSWAP_EXTRACTED: + case SYS_HOTSWAP_INSERTED: + if (!dircache_initialized) + break; +#endif case DIRCACHE_BUILD: thread_enabled = true; dircache_do_rebuild(); Index: firmware/common/dir_uncached.c =================================================================== --- firmware/common/dir_uncached.c (revision 16172) +++ firmware/common/dir_uncached.c (working copy) @@ -24,7 +24,6 @@ #include "dir.h" #include "debug.h" #include "atoi.h" -//#include "dircache.h" #define MAX_OPEN_DIRS 8 @@ -32,22 +31,9 @@ #ifdef HAVE_MULTIVOLUME -/* how to name volumes, first char must be outside of legal file names, - a number gets appended to enumerate, if applicable */ -#ifdef HAVE_MMC -static const char* vol_names = ""; -#define VOL_ENUM_POS 4 /* position of %d, to avoid runtime calculation */ -#elif defined(HAVE_HOTSWAP) -static const char* vol_names = ""; -#define VOL_ENUM_POS 8 /* position of %d, to avoid runtime calculation */ -#else -static const char* vol_names = ""; -#define VOL_ENUM_POS 3 -#endif - /* returns on which volume this is, and copies the reduced name (sortof a preprocessor for volume-decorated pathnames) */ -static int strip_volume(const char* name, char* namecopy) +int strip_volume(const char* name, char* namecopy) { int volume = 0; const char *temp = name; @@ -55,7 +41,7 @@ while (*temp == '/') /* skip all leading slashes */ ++temp; - if (*temp && !strncmp(temp, vol_names, VOL_ENUM_POS)) + if (*temp && !strncmp(temp, VOL_NAMES, VOL_ENUM_POS)) { temp += VOL_ENUM_POS; /* behind special name */ volume = atoi(temp); /* number is following */ @@ -199,7 +185,7 @@ memset(theent, 0, sizeof(*theent)); theent->attribute = FAT_ATTR_DIRECTORY | FAT_ATTR_VOLUME; snprintf(theent->d_name, sizeof(theent->d_name), - vol_names, dir->volumecounter); + VOL_NAMES, dir->volumecounter); return theent; } } Index: firmware/common/file.c =================================================================== --- firmware/common/file.c (revision 16172) +++ firmware/common/file.c (working copy) @@ -114,7 +115,9 @@ return -7; } - fat_open(IF_MV2(unsupported at the moment,) + int volume = strip_volume(pathname, pathnamecopy); + + fat_open(IF_MV2(volume,) ce->startcluster, &(file->fatfile), NULL);