diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/fat.c | 108 |
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 | } |