summaryrefslogtreecommitdiff
path: root/firmware/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/drivers')
-rw-r--r--firmware/drivers/fat.c108
1 files changed, 49 insertions, 59 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c
index e6383787ca..f9d116eba8 100644
--- a/firmware/drivers/fat.c
+++ b/firmware/drivers/fat.c
@@ -16,7 +16,6 @@
16 * KIND, either express or implied. 16 * KIND, either express or implied.
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "config.h"
20#include <stdio.h> 19#include <stdio.h>
21#include <string.h> 20#include <string.h>
22#include <stdlib.h> 21#include <stdlib.h>
@@ -2159,7 +2158,6 @@ int fat_opendir(IF_MV2(int volume,)
2159 2158
2160 dir->entry = 0; 2159 dir->entry = 0;
2161 dir->sector = 0; 2160 dir->sector = 0;
2162 dir->bufindex = 0;
2163 2161
2164 if (startcluster == 0) 2162 if (startcluster == 0)
2165 startcluster = fat_bpb->bpb_rootclus; 2163 startcluster = fat_bpb->bpb_rootclus;
@@ -2215,19 +2213,15 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2215 int longarray[20]; 2213 int longarray[20];
2216 int longs=0; 2214 int longs=0;
2217 int sectoridx=0; 2215 int sectoridx=0;
2218 /* Set the cache pointer to the sector buffer we are currently using */ 2216 unsigned char* cached_buf = dir->sectorcache[0];
2219 unsigned char* cached_buf = dir->sectorcache[dir->bufindex];
2220 2217
2221 dir->entrycount = 0; 2218 dir->entrycount = 0;
2222 2219
2223 while(!done) 2220 while(!done)
2224 { 2221 {
2225 if ( !(dir->entry % (DIR_ENTRIES_PER_SECTOR*FAT_DIR_BUFSECTORS)) || 2222 if ( !(dir->entry % DIR_ENTRIES_PER_SECTOR) || !dir->sector )
2226 !dir->sector )
2227 { 2223 {
2228 /* Always read 2 sectors at a time */ 2224 rc = fat_readwrite(&dir->file, 1, cached_buf, false);
2229 rc = fat_readwrite(&dir->file, FAT_DIR_BUFSECTORS, cached_buf,
2230 false);
2231 if (rc == 0) { 2225 if (rc == 0) {
2232 /* eof */ 2226 /* eof */
2233 entry->name[0] = 0; 2227 entry->name[0] = 0;
@@ -2241,8 +2235,8 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2241 dir->sector = dir->file.lastsector; 2235 dir->sector = dir->file.lastsector;
2242 } 2236 }
2243 2237
2244 for (i = dir->entry % (DIR_ENTRIES_PER_SECTOR*FAT_DIR_BUFSECTORS); 2238 for (i = dir->entry % DIR_ENTRIES_PER_SECTOR;
2245 i < (DIR_ENTRIES_PER_SECTOR*FAT_DIR_BUFSECTORS); i++) 2239 i < DIR_ENTRIES_PER_SECTOR; i++)
2246 { 2240 {
2247 unsigned int entrypos = i * DIR_ENTRY_SIZE; 2241 unsigned int entrypos = i * DIR_ENTRY_SIZE;
2248 2242
@@ -2283,44 +2277,40 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2283 /* replace shortname with longname? */ 2277 /* replace shortname with longname? */
2284 if ( longs ) { 2278 if ( longs ) {
2285 int j; 2279 int j;
2286 /* This should be enough to hold any name segment 2280 /* This should be enough to hold any name segment utf8-encoded */
2287 utf8-encoded */
2288 unsigned char shortname[13]; /* 8+3+dot+\0 */ 2281 unsigned char shortname[13]; /* 8+3+dot+\0 */
2289 /* Add 1 for trailing \0 */ 2282 unsigned char longname_utf8segm[6*4 + 1]; /* Add 1 for trailing \0 */
2290 unsigned char longname_utf8segm[6*4 + 1];
2291 int longname_utf8len = 0; 2283 int longname_utf8len = 0;
2292 2284
2293 /* Store it temporarily */ 2285 strcpy(shortname, entry->name); /* Temporarily store it */
2294 strcpy(shortname, entry->name);
2295 entry->name[0] = 0; 2286 entry->name[0] = 0;
2296 2287
2297 /* iterate backwards through the dir entries */ 2288 /* iterate backwards through the dir entries */
2298 for (j=longs-1; j>=0; j--) { 2289 for (j=longs-1; j>=0; j--) {
2290 unsigned char* ptr = cached_buf;
2299 int index = longarray[j]; 2291 int index = longarray[j];
2300 unsigned char* ptr; 2292 /* current or cached sector? */
2301 2293 if ( sectoridx >= SECTOR_SIZE ) {
2302 /* If we have spanned over 3 sectors, the current 2294 if ( sectoridx >= SECTOR_SIZE*2 ) {
2303 buffer holds the last part and the other one 2295 if ( ( index >= SECTOR_SIZE ) &&
2304 the first part. */ 2296 ( index < SECTOR_SIZE*2 ))
2305 if(sectoridx >= FAT_DIR_BUFSIZE) { 2297 ptr = dir->sectorcache[1];
2306 if(index / FAT_DIR_BUFSIZE > 0) 2298 else
2307 ptr = dir->sectorcache[dir->bufindex]; 2299 ptr = dir->sectorcache[2];
2308 else 2300 }
2309 ptr = dir->sectorcache[1 - dir->bufindex]; 2301 else {
2310 } else { 2302 if ( index < SECTOR_SIZE )
2311 ptr = dir->sectorcache[dir->bufindex]; 2303 ptr = dir->sectorcache[1];
2304 }
2305
2306 index &= SECTOR_SIZE-1;
2312 } 2307 }
2313 2308
2314 /* Let the index point into the selected 2309 /* Try to append each segment of the long name. Check if we'd
2315 buffer */ 2310 exceed the buffer. Also check for FAT padding characters 0xFFFF. */
2316 index &= FAT_DIR_BUFSIZE-1;
2317
2318 /* Try to append each segment of the long name.
2319 Check if we'd exceed the buffer. Also check for
2320 FAT padding characters 0xFFFF. */
2321 if (fat_copy_long_name_segment(ptr + index + 1, 5, 2311 if (fat_copy_long_name_segment(ptr + index + 1, 5,
2322 longname_utf8segm) == 0) 2312 longname_utf8segm) == 0) break;
2323 break; 2313 // logf("SG: %s, EN: %s", longname_utf8segm, entry->name);
2324 longname_utf8len += strlen(longname_utf8segm); 2314 longname_utf8len += strlen(longname_utf8segm);
2325 if (longname_utf8len < FAT_FILENAME_BYTES) 2315 if (longname_utf8len < FAT_FILENAME_BYTES)
2326 strcat(entry->name, longname_utf8segm); 2316 strcat(entry->name, longname_utf8segm);
@@ -2328,8 +2318,8 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2328 break; 2318 break;
2329 2319
2330 if (fat_copy_long_name_segment(ptr + index + 14, 6, 2320 if (fat_copy_long_name_segment(ptr + index + 14, 6,
2331 longname_utf8segm) == 0) 2321 longname_utf8segm) == 0) break;
2332 break; 2322 // logf("SG: %s, EN: %s", longname_utf8segm, entry->name);
2333 longname_utf8len += strlen(longname_utf8segm); 2323 longname_utf8len += strlen(longname_utf8segm);
2334 if (longname_utf8len < FAT_FILENAME_BYTES) 2324 if (longname_utf8len < FAT_FILENAME_BYTES)
2335 strcat(entry->name, longname_utf8segm); 2325 strcat(entry->name, longname_utf8segm);
@@ -2337,8 +2327,8 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2337 break; 2327 break;
2338 2328
2339 if (fat_copy_long_name_segment(ptr + index + 28, 2, 2329 if (fat_copy_long_name_segment(ptr + index + 28, 2,
2340 longname_utf8segm) == 0) 2330 longname_utf8segm) == 0) break;
2341 break; 2331 // logf("SG: %s, EN: %s", longname_utf8segm, entry->name);
2342 longname_utf8len += strlen(longname_utf8segm); 2332 longname_utf8len += strlen(longname_utf8segm);
2343 if (longname_utf8len < FAT_FILENAME_BYTES) 2333 if (longname_utf8len < FAT_FILENAME_BYTES)
2344 strcat(entry->name, longname_utf8segm); 2334 strcat(entry->name, longname_utf8segm);
@@ -2348,18 +2338,19 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2348 2338
2349 /* Does the utf8-encoded name fit into the entry? */ 2339 /* Does the utf8-encoded name fit into the entry? */
2350 if (longname_utf8len >= FAT_FILENAME_BYTES) { 2340 if (longname_utf8len >= FAT_FILENAME_BYTES) {
2351 /* Take the short DOS name. Need to utf8-encode it 2341 /* Take the short DOS name. Need to utf8-encode it since
2352 since it may contain chars from the upper half 2342 it may contain chars from the upper half of the OEM
2353 of the OEM code page which wouldn't be a valid 2343 code page which wouldn't be a valid utf8. Beware: this
2354 utf8. Beware: this file will be shown with 2344 file will be shown with strange glyphs in file browser
2355 strange glyphs in file browser since unicode 2345 since unicode 0x80 to 0x9F are control characters. */
2356 0x80 to 0x9F are control characters. */
2357 logf("SN-DOS: %s", shortname); 2346 logf("SN-DOS: %s", shortname);
2358 unsigned char *utf8; 2347 unsigned char *utf8;
2359 utf8 = iso_decode(shortname, entry->name, -1, 2348 utf8 = iso_decode(shortname, entry->name, -1, strlen(shortname));
2360 strlen(shortname)); 2349 *utf8 = 0;
2361 *utf8 = 0;
2362 logf("SN: %s", entry->name); 2350 logf("SN: %s", entry->name);
2351 } else {
2352 // logf("LN: %s", entry->name);
2353 // logf("LNLen: %d (%c)", longname_utf8len, entry->name[0]);
2363 } 2354 }
2364 } 2355 }
2365 done = true; 2356 done = true;
@@ -2370,14 +2361,13 @@ int fat_getnext(struct fat_dir *dir, struct fat_direntry *entry)
2370 } 2361 }
2371 } 2362 }
2372 2363
2373 /* Did the name span across a buffer boundary? 2364 /* save this sector, for longname use */
2374 Then we need to fill the second buffer as well and continue. */ 2365 if ( sectoridx )
2375 if(!done) { 2366 memcpy( dir->sectorcache[2], dir->sectorcache[0], SECTOR_SIZE );
2376 sectoridx += FAT_DIR_BUFSIZE; 2367 else
2368 memcpy( dir->sectorcache[1], dir->sectorcache[0], SECTOR_SIZE );
2369 sectoridx += SECTOR_SIZE;
2377 2370
2378 dir->bufindex = 1 - dir->bufindex;
2379 cached_buf = dir->sectorcache[dir->bufindex];
2380 }
2381 } 2371 }
2382 return 0; 2372 return 0;
2383} 2373}