00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "config.h"
00019
00020 #include "partition.h"
00021 #include "fat16.h"
00022 #include "fat16_config.h"
00023
00024 #include <string.h>
00025
00026 #if USE_DYNAMIC_MEMORY
00027 #include <stdlib.h>
00028 #endif
00029
00077 #define FAT16_CLUSTER_FREE 0x0000
00078 #define FAT16_CLUSTER_RESERVED_MIN 0xfff0
00079 #define FAT16_CLUSTER_RESERVED_MAX 0xfff6
00080 #define FAT16_CLUSTER_BAD 0xfff7
00081 #define FAT16_CLUSTER_LAST_MIN 0xfff8
00082 #define FAT16_CLUSTER_LAST_MAX 0xffff
00083
00084 #define FAT16_DIRENTRY_DELETED 0xe5
00085 #define FAT16_DIRENTRY_LFNLAST (1 << 6)
00086 #define FAT16_DIRENTRY_LFNSEQMASK ((1 << 6) - 1)
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 struct fat16_header_struct
00138 {
00139 uint32_t size;
00140
00141 uint32_t fat_offset;
00142 uint32_t fat_size;
00143
00144 uint16_t sector_size;
00145 uint16_t cluster_size;
00146
00147 uint32_t root_dir_offset;
00148
00149 uint32_t cluster_zero_offset;
00150 };
00151
00152 struct fat16_fs_struct
00153 {
00154 struct partition_struct* partition;
00155 struct fat16_header_struct header;
00156 };
00157
00158 struct fat16_file_struct
00159 {
00160 struct fat16_fs_struct* fs;
00161 struct fat16_dir_entry_struct dir_entry;
00162 uint32_t pos;
00163 uint16_t pos_cluster;
00164 };
00165
00166 struct fat16_dir_struct
00167 {
00168 struct fat16_fs_struct* fs;
00169 struct fat16_dir_entry_struct dir_entry;
00170 uint16_t entry_cluster;
00171 uint16_t entry_offset;
00172 };
00173
00174 struct fat16_read_dir_callback_arg
00175 {
00176 struct fat16_dir_entry_struct* dir_entry;
00177 uint16_t bytes_read;
00178 uint8_t finished;
00179 };
00180
00181 struct fat16_usage_count_callback_arg
00182 {
00183 uint16_t cluster_count;
00184 uint8_t buffer_size;
00185 };
00186
00187 #if !USE_DYNAMIC_MEMORY
00188 static struct fat16_fs_struct fat16_fs_handles[FAT16_FS_COUNT];
00189 static struct fat16_file_struct fat16_file_handles[FAT16_FILE_COUNT];
00190 static struct fat16_dir_struct fat16_dir_handles[FAT16_DIR_COUNT];
00191 #endif
00192
00193 static uint8_t fat16_read_header(struct fat16_fs_struct* fs);
00194 static uint16_t fat16_get_next_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num);
00195 static uint16_t fat16_append_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num, uint16_t count);
00196 static uint8_t fat16_free_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num);
00197 static uint8_t fat16_terminate_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num);
00198 static uint8_t fat16_clear_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num);
00199 static uint16_t fat16_clear_cluster_callback(uint8_t* buffer, uint32_t offset, void* p);
00200 static uint32_t fat16_cluster_offset(const struct fat16_fs_struct* fs, uint16_t cluster_num);
00201 static uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p);
00202 static uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry);
00203 static uint32_t fat16_find_offset_for_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_struct* parent, const struct fat16_dir_entry_struct* dir_entry);
00204 static uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry);
00205
00206 static uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p);
00207
00208 static void fat16_set_file_modification_date(struct fat16_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day);
00209 static void fat16_set_file_modification_time(struct fat16_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec);
00210
00219 struct fat16_fs_struct* fat16_open(struct partition_struct* partition)
00220 {
00221 if(!partition ||
00222 #if FAT16_WRITE_SUPPORT
00223 !partition->device_write ||
00224 !partition->device_write_interval
00225 #else
00226 0
00227 #endif
00228 )
00229 return 0;
00230
00231 #if USE_DYNAMIC_MEMORY
00232 struct fat16_fs_struct* fs = malloc(sizeof(*fs));
00233 if(!fs)
00234 return 0;
00235 #else
00236 struct fat16_fs_struct* fs = fat16_fs_handles;
00237 uint8_t i;
00238 for(i = 0; i < FAT16_FS_COUNT; ++i)
00239 {
00240 if(!fs->partition)
00241 break;
00242
00243 ++fs;
00244 }
00245 if(i >= FAT16_FS_COUNT)
00246 return 0;
00247 #endif
00248
00249 memset(fs, 0, sizeof(*fs));
00250
00251 fs->partition = partition;
00252 if(!fat16_read_header(fs))
00253 {
00254 #if USE_DYNAMIC_MEMORY
00255 free(fs);
00256 #else
00257 fs->partition = 0;
00258 #endif
00259 return 0;
00260 }
00261
00262 return fs;
00263 }
00264
00275 void fat16_close(struct fat16_fs_struct* fs)
00276 {
00277 if(!fs)
00278 return;
00279
00280 #if USE_DYNAMIC_MEMORY
00281 free(fs);
00282 #else
00283 fs->partition = 0;
00284 #endif
00285 }
00286
00294 uint8_t fat16_read_header(struct fat16_fs_struct* fs)
00295 {
00296 if(!fs)
00297 return 0;
00298
00299 struct partition_struct* partition = fs->partition;
00300 if(!partition)
00301 return 0;
00302
00303
00304 uint8_t buffer[25];
00305 uint32_t partition_offset = partition->offset * 512;
00306 if(!partition->device_read(partition_offset + 0x0b, buffer, sizeof(buffer)))
00307 return 0;
00308
00309 uint16_t bytes_per_sector = ((uint16_t) buffer[0x00]) |
00310 ((uint16_t) buffer[0x01] << 8);
00311 uint8_t sectors_per_cluster = buffer[0x02];
00312 uint16_t reserved_sectors = ((uint16_t) buffer[0x03]) |
00313 ((uint16_t) buffer[0x04] << 8);
00314 uint8_t fat_copies = buffer[0x05];
00315 uint16_t max_root_entries = ((uint16_t) buffer[0x06]) |
00316 ((uint16_t) buffer[0x07] << 8);
00317 uint16_t sector_count_16 = ((uint16_t) buffer[0x08]) |
00318 ((uint16_t) buffer[0x09] << 8);
00319 uint16_t sectors_per_fat = ((uint16_t) buffer[0x0b]) |
00320 ((uint16_t) buffer[0x0c] << 8);
00321 uint32_t sector_count = ((uint32_t) buffer[0x15]) |
00322 ((uint32_t) buffer[0x16] << 8) |
00323 ((uint32_t) buffer[0x17] << 16) |
00324 ((uint32_t) buffer[0x18] << 24);
00325
00326 if(sectors_per_fat == 0)
00327
00328 return 0;
00329
00330 if(sector_count == 0)
00331 {
00332 if(sector_count_16 == 0)
00333
00334 return 0;
00335 else
00336 sector_count = sector_count_16;
00337 }
00338
00339
00340 uint32_t data_sector_count = sector_count
00341 - reserved_sectors
00342 - (uint32_t) sectors_per_fat * fat_copies
00343 - ((max_root_entries * 32 + bytes_per_sector - 1) / bytes_per_sector);
00344 uint32_t data_cluster_count = data_sector_count / sectors_per_cluster;
00345 if(data_cluster_count < 4085 || data_cluster_count >= 65525)
00346
00347 return 0;
00348
00349 partition->type = PARTITION_TYPE_FAT16;
00350
00351
00352 struct fat16_header_struct* header = &fs->header;
00353 memset(header, 0, sizeof(*header));
00354
00355 header->size = sector_count * bytes_per_sector;
00356
00357 header->fat_offset =
00358 partition_offset +
00359
00360 (uint32_t) reserved_sectors * bytes_per_sector;
00361 header->fat_size = (data_cluster_count + 2) * 2;
00362
00363 header->sector_size = bytes_per_sector;
00364 header->cluster_size = (uint32_t) bytes_per_sector * sectors_per_cluster;
00365
00366 header->root_dir_offset =
00367 header->fat_offset +
00368
00369 (uint32_t) fat_copies * sectors_per_fat * bytes_per_sector;
00370
00371 header->cluster_zero_offset =
00372 header->root_dir_offset +
00373
00374 (uint32_t) max_root_entries * 32;
00375
00376 return 1;
00377 }
00378
00391 uint8_t fat16_get_dir_entry_of_path(struct fat16_fs_struct* fs, const char* path, struct fat16_dir_entry_struct* dir_entry)
00392 {
00393 if(!fs || !path || path[0] == '\0' || !dir_entry)
00394 return 0;
00395
00396 if(path[0] == '/')
00397 ++path;
00398
00399
00400 memset(dir_entry, 0, sizeof(*dir_entry));
00401 dir_entry->attributes = FAT16_ATTRIB_DIR;
00402
00403 while(1)
00404 {
00405 if(path[0] == '\0')
00406 return 1;
00407
00408 struct fat16_dir_struct* dd = fat16_open_dir(fs, dir_entry);
00409 if(!dd)
00410 break;
00411
00412
00413 const char* sub_path = strchr(path, '/');
00414 uint8_t length_to_sep;
00415 if(sub_path)
00416 {
00417 length_to_sep = sub_path - path;
00418 ++sub_path;
00419 }
00420 else
00421 {
00422 length_to_sep = strlen(path);
00423 sub_path = path + length_to_sep;
00424 }
00425
00426
00427 while(fat16_read_dir(dd, dir_entry))
00428 {
00429
00430 if((strlen(dir_entry->long_name) != length_to_sep ||
00431 strncmp(path, dir_entry->long_name, length_to_sep) != 0))
00432 continue;
00433
00434 fat16_close_dir(dd);
00435 dd = 0;
00436
00437 if(path[length_to_sep] == '\0')
00438
00439 return 1;
00440
00441 if(dir_entry->attributes & FAT16_ATTRIB_DIR)
00442 {
00443
00444 path = sub_path;
00445 break;
00446 }
00447
00448
00449 return 0;
00450 }
00451
00452 fat16_close_dir(dd);
00453 }
00454
00455 return 0;
00456 }
00457
00470 uint16_t fat16_get_next_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num)
00471 {
00472 if(!fs || cluster_num < 2)
00473 return 0;
00474
00475
00476 uint8_t fat_entry[2];
00477 if(!fs->partition->device_read(fs->header.fat_offset + 2 * cluster_num, fat_entry, 2))
00478 return 0;
00479
00480
00481 cluster_num = ((uint16_t) fat_entry[0]) |
00482 ((uint16_t) fat_entry[1] << 8);
00483
00484 if(cluster_num == FAT16_CLUSTER_FREE ||
00485 cluster_num == FAT16_CLUSTER_BAD ||
00486 (cluster_num >= FAT16_CLUSTER_RESERVED_MIN && cluster_num <= FAT16_CLUSTER_RESERVED_MAX) ||
00487 (cluster_num >= FAT16_CLUSTER_LAST_MIN && cluster_num <= FAT16_CLUSTER_LAST_MAX))
00488 return 0;
00489
00490 return cluster_num;
00491 }
00492
00504 uint16_t fat16_append_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num, uint16_t count)
00505 {
00506 #if FAT16_WRITE_SUPPORT
00507 if(!fs)
00508 return 0;
00509
00510 device_read_t device_read = fs->partition->device_read;
00511 device_write_t device_write = fs->partition->device_write;
00512 uint32_t fat_offset = fs->header.fat_offset;
00513 uint16_t cluster_max = fs->header.fat_size / 2;
00514 uint16_t cluster_next = 0;
00515 uint16_t count_left = count;
00516 uint8_t buffer[2];
00517
00518 for(uint16_t cluster_new = 0; cluster_new < cluster_max; ++cluster_new)
00519 {
00520 if(!device_read(fat_offset + 2 * cluster_new, buffer, sizeof(buffer)))
00521 return 0;
00522
00523
00524 if(buffer[0] == (FAT16_CLUSTER_FREE & 0xff) &&
00525 buffer[1] == ((FAT16_CLUSTER_FREE >> 8) & 0xff))
00526 {
00527
00528 if(count_left == count)
00529 {
00530 buffer[0] = FAT16_CLUSTER_LAST_MAX & 0xff;
00531 buffer[1] = (FAT16_CLUSTER_LAST_MAX >> 8) & 0xff;
00532 }
00533 else
00534 {
00535 buffer[0] = cluster_next & 0xff;
00536 buffer[1] = (cluster_next >> 8) & 0xff;
00537 }
00538
00539 if(!device_write(fat_offset + 2 * cluster_new, buffer, sizeof(buffer)))
00540 break;
00541
00542 cluster_next = cluster_new;
00543 if(--count_left == 0)
00544 break;
00545 }
00546 }
00547
00548 do
00549 {
00550 if(count_left > 0)
00551 break;
00552
00553
00554
00555
00556 if(cluster_num >= 2)
00557 {
00558 buffer[0] = cluster_next & 0xff;
00559 buffer[1] = (cluster_next >> 8) & 0xff;
00560 if(!device_write(fat_offset + 2 * cluster_num, buffer, sizeof(buffer)))
00561 break;
00562 }
00563
00564 return cluster_next;
00565
00566 } while(0);
00567
00568
00569
00570
00571 fat16_free_clusters(fs, cluster_next);
00572
00573 return 0;
00574 #else
00575 return 0;
00576 #endif
00577 }
00578
00596 uint8_t fat16_free_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num)
00597 {
00598 #if FAT16_WRITE_SUPPORT
00599 if(!fs || cluster_num < 2)
00600 return 0;
00601
00602 uint32_t fat_offset = fs->header.fat_offset;
00603 uint8_t buffer[2];
00604 while(cluster_num)
00605 {
00606 if(!fs->partition->device_read(fat_offset + 2 * cluster_num, buffer, 2))
00607 return 0;
00608
00609
00610 uint16_t cluster_num_next = ((uint16_t) buffer[0]) |
00611 ((uint16_t) buffer[1] << 8);
00612
00613 if(cluster_num_next == FAT16_CLUSTER_FREE)
00614 return 1;
00615 if(cluster_num_next == FAT16_CLUSTER_BAD ||
00616 (cluster_num_next >= FAT16_CLUSTER_RESERVED_MIN &&
00617 cluster_num_next <= FAT16_CLUSTER_RESERVED_MAX
00618 )
00619 )
00620 return 0;
00621 if(cluster_num_next >= FAT16_CLUSTER_LAST_MIN && cluster_num_next <= FAT16_CLUSTER_LAST_MAX)
00622 cluster_num_next = 0;
00623
00624
00625 buffer[0] = FAT16_CLUSTER_FREE & 0xff;
00626 buffer[1] = (FAT16_CLUSTER_FREE >> 8) & 0xff;
00627 fs->partition->device_write(fat_offset + 2 * cluster_num, buffer, 2);
00628
00629
00630
00631
00632
00633 cluster_num = cluster_num_next;
00634 }
00635
00636 return 1;
00637 #else
00638 return 0;
00639 #endif
00640 }
00641
00654 uint8_t fat16_terminate_clusters(const struct fat16_fs_struct* fs, uint16_t cluster_num)
00655 {
00656 #if FAT16_WRITE_SUPPORT
00657 if(!fs || cluster_num < 2)
00658 return 0;
00659
00660
00661 uint16_t cluster_num_next = fat16_get_next_cluster(fs, cluster_num);
00662
00663
00664 uint8_t buffer[2];
00665 buffer[0] = FAT16_CLUSTER_LAST_MAX & 0xff;
00666 buffer[1] = (FAT16_CLUSTER_LAST_MAX >> 8) & 0xff;
00667 if(!fs->partition->device_write(fs->header.fat_offset + 2 * cluster_num, buffer, 2))
00668 return 0;
00669
00670
00671 if(cluster_num_next)
00672 return fat16_free_clusters(fs, cluster_num_next);
00673 else
00674 return 1;
00675 #else
00676 return 0;
00677 #endif
00678 }
00679
00690 uint8_t fat16_clear_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num)
00691 {
00692 #if FAT16_WRITE_SUPPORT
00693 if(cluster_num < 2)
00694 return 0;
00695
00696 uint32_t cluster_offset = fat16_cluster_offset(fs, cluster_num);
00697 uint8_t zero[16];
00698 return fs->partition->device_write_interval(cluster_offset,
00699 zero,
00700 fs->header.cluster_size,
00701 fat16_clear_cluster_callback,
00702 0
00703 );
00704 #else
00705 return 0;
00706 #endif
00707 }
00708
00713 uint16_t fat16_clear_cluster_callback(uint8_t* buffer, uint32_t offset, void* p)
00714 {
00715 #if FAT16_WRITE_SUPPORT
00716 memset(buffer, 0, 16);
00717 return 16;
00718 #else
00719 return 0;
00720 #endif
00721 }
00722
00731 uint32_t fat16_cluster_offset(const struct fat16_fs_struct* fs, uint16_t cluster_num)
00732 {
00733 if(!fs || cluster_num < 2)
00734 return 0;
00735
00736 return fs->header.cluster_zero_offset + (uint32_t) (cluster_num - 2) * fs->header.cluster_size;
00737 }
00738
00748 struct fat16_file_struct* fat16_open_file(struct fat16_fs_struct* fs, const struct fat16_dir_entry_struct* dir_entry)
00749 {
00750 if(!fs || !dir_entry || (dir_entry->attributes & FAT16_ATTRIB_DIR))
00751 return 0;
00752
00753 #if USE_DYNAMIC_MEMORY
00754 struct fat16_file_struct* fd = malloc(sizeof(*fd));
00755 if(!fd)
00756 return 0;
00757 #else
00758 struct fat16_file_struct* fd = fat16_file_handles;
00759 uint8_t i;
00760 for(i = 0; i < FAT16_FILE_COUNT; ++i)
00761 {
00762 if(!fd->fs)
00763 break;
00764
00765 ++fd;
00766 }
00767 if(i >= FAT16_FILE_COUNT)
00768 return 0;
00769 #endif
00770
00771 memcpy(&fd->dir_entry, dir_entry, sizeof(*dir_entry));
00772 fd->fs = fs;
00773 fd->pos = 0;
00774 fd->pos_cluster = dir_entry->cluster;
00775
00776 return fd;
00777 }
00778
00786 void fat16_close_file(struct fat16_file_struct* fd)
00787 {
00788 if(fd)
00789 #if USE_DYNAMIC_MEMORY
00790 free(fd);
00791 #else
00792 fd->fs = 0;
00793 #endif
00794 }
00795
00808 int16_t fat16_read_file(struct fat16_file_struct* fd, uint8_t* buffer, uint16_t buffer_len)
00809 {
00810
00811 if(!fd || !buffer || buffer_len < 1)
00812 return -1;
00813
00814
00815 if(fd->pos + buffer_len > fd->dir_entry.file_size)
00816 buffer_len = fd->dir_entry.file_size - fd->pos;
00817 if(buffer_len == 0)
00818 return 0;
00819
00820 uint16_t cluster_size = fd->fs->header.cluster_size;
00821 uint16_t cluster_num = fd->pos_cluster;
00822 uint16_t buffer_left = buffer_len;
00823 uint16_t first_cluster_offset = fd->pos % cluster_size;
00824
00825
00826 if(!cluster_num)
00827 {
00828 cluster_num = fd->dir_entry.cluster;
00829
00830 if(!cluster_num)
00831 {
00832 if(!fd->pos)
00833 return 0;
00834 else
00835 return -1;
00836 }
00837
00838 if(fd->pos)
00839 {
00840 uint32_t pos = fd->pos;
00841 while(pos >= cluster_size)
00842 {
00843 pos -= cluster_size;
00844 cluster_num = fat16_get_next_cluster(fd->fs, cluster_num);
00845 if(!cluster_num)
00846 return -1;
00847 }
00848 }
00849 }
00850
00851
00852 do
00853 {
00854
00855 uint32_t cluster_offset = fat16_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
00856 uint16_t copy_length = cluster_size - first_cluster_offset;
00857 if(copy_length > buffer_left)
00858 copy_length = buffer_left;
00859
00860
00861 if(!fd->fs->partition->device_read(cluster_offset, buffer, copy_length))
00862 return buffer_len - buffer_left;
00863
00864
00865 buffer += copy_length;
00866 buffer_left -= copy_length;
00867 fd->pos += copy_length;
00868
00869 if(first_cluster_offset + copy_length >= cluster_size)
00870 {
00871
00872 if((cluster_num = fat16_get_next_cluster(fd->fs, cluster_num)))
00873 {
00874 first_cluster_offset = 0;
00875 }
00876 else
00877 {
00878 fd->pos_cluster = 0;
00879 return buffer_len - buffer_left;
00880 }
00881 }
00882
00883 fd->pos_cluster = cluster_num;
00884
00885 } while(buffer_left > 0);
00886
00887 return buffer_len;
00888 }
00889
00902 int16_t fat16_write_file(struct fat16_file_struct* fd, const uint8_t* buffer, uint16_t buffer_len)
00903 {
00904 #if FAT16_WRITE_SUPPORT
00905
00906 if(!fd || !buffer || buffer_len < 1)
00907 return -1;
00908 if(fd->pos > fd->dir_entry.file_size)
00909 return -1;
00910
00911 uint16_t cluster_size = fd->fs->header.cluster_size;
00912 uint16_t cluster_num = fd->pos_cluster;
00913 uint16_t buffer_left = buffer_len;
00914 uint16_t first_cluster_offset = fd->pos % cluster_size;
00915
00916
00917 if(!cluster_num)
00918 {
00919 cluster_num = fd->dir_entry.cluster;
00920
00921 if(!cluster_num)
00922 {
00923 if(!fd->pos)
00924 {
00925
00926 fd->dir_entry.cluster = cluster_num = fat16_append_clusters(fd->fs, 0, 1);
00927 if(!cluster_num)
00928 return -1;
00929 }
00930 else
00931 {
00932 return -1;
00933 }
00934 }
00935
00936 if(fd->pos)
00937 {
00938 uint32_t pos = fd->pos;
00939 uint16_t cluster_num_next;
00940 while(pos >= cluster_size)
00941 {
00942 pos -= cluster_size;
00943 cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
00944 if(!cluster_num_next && pos == 0)
00945
00946 cluster_num_next = fat16_append_clusters(fd->fs, cluster_num, 1);
00947 if(!cluster_num_next)
00948 return -1;
00949
00950 cluster_num = cluster_num_next;
00951 }
00952 }
00953 }
00954
00955
00956 do
00957 {
00958
00959 uint32_t cluster_offset = fat16_cluster_offset(fd->fs, cluster_num) + first_cluster_offset;
00960 uint16_t write_length = cluster_size - first_cluster_offset;
00961 if(write_length > buffer_left)
00962 write_length = buffer_left;
00963
00964
00965 if(!fd->fs->partition->device_write(cluster_offset, buffer, write_length))
00966 break;
00967
00968
00969 buffer += write_length;
00970 buffer_left -= write_length;
00971 fd->pos += write_length;
00972
00973 if(first_cluster_offset + write_length >= cluster_size)
00974 {
00975
00976 uint16_t cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
00977 if(!cluster_num_next && buffer_left > 0)
00978
00979 cluster_num_next = fat16_append_clusters(fd->fs, cluster_num, 1);
00980 if(!cluster_num_next)
00981 {
00982 fd->pos_cluster = 0;
00983 break;
00984 }
00985
00986 cluster_num = cluster_num_next;
00987 first_cluster_offset = 0;
00988 }
00989
00990 fd->pos_cluster = cluster_num;
00991
00992 } while(buffer_left > 0);
00993
00994
00995 if(fd->pos > fd->dir_entry.file_size)
00996 {
00997 uint32_t size_old = fd->dir_entry.file_size;
00998
00999
01000 fd->dir_entry.file_size = fd->pos;
01001
01002 if(!fat16_write_dir_entry(fd->fs, &fd->dir_entry))
01003 {
01004
01005
01006
01007
01008 buffer_left = fd->pos - size_old;
01009 fd->pos = size_old;
01010 }
01011 }
01012
01013 return buffer_len - buffer_left;
01014
01015 #else
01016 return -1;
01017 #endif
01018 }
01019
01046 uint8_t fat16_seek_file(struct fat16_file_struct* fd, int32_t* offset, uint8_t whence)
01047 {
01048 if(!fd || !offset)
01049 return 0;
01050
01051 uint32_t new_pos = fd->pos;
01052 switch(whence)
01053 {
01054 case FAT16_SEEK_SET:
01055 new_pos = *offset;
01056 break;
01057 case FAT16_SEEK_CUR:
01058 new_pos += *offset;
01059 break;
01060 case FAT16_SEEK_END:
01061 new_pos = fd->dir_entry.file_size + *offset;
01062 break;
01063 default:
01064 return 0;
01065 }
01066
01067 if(new_pos > fd->dir_entry.file_size && !fat16_resize_file(fd, new_pos))
01068 return 0;
01069
01070 fd->pos = new_pos;
01071 fd->pos_cluster = 0;
01072
01073 *offset = new_pos;
01074 return 1;
01075 }
01076
01096 uint8_t fat16_resize_file(struct fat16_file_struct* fd, uint32_t size)
01097 {
01098 #if FAT16_WRITE_SUPPORT
01099 if(!fd)
01100 return 0;
01101
01102 uint16_t cluster_num = fd->dir_entry.cluster;
01103 uint16_t cluster_size = fd->fs->header.cluster_size;
01104 uint32_t size_new = size;
01105
01106 do
01107 {
01108 if(cluster_num == 0 && size_new == 0)
01109
01110 break;
01111
01112
01113 while(size_new > cluster_size)
01114 {
01115
01116 uint16_t cluster_num_next = fat16_get_next_cluster(fd->fs, cluster_num);
01117 if(cluster_num_next)
01118 {
01119 cluster_num = cluster_num_next;
01120 size_new -= cluster_size;
01121 }
01122 else
01123 {
01124 break;
01125 }
01126 }
01127
01128 if(size_new > cluster_size || cluster_num == 0)
01129 {
01130
01131
01132
01133 uint16_t cluster_count = size_new / cluster_size;
01134 if((uint32_t) cluster_count * cluster_size < size_new)
01135 ++cluster_count;
01136 uint16_t cluster_new_chain = fat16_append_clusters(fd->fs, cluster_num, cluster_count);
01137 if(!cluster_new_chain)
01138 return 0;
01139
01140 if(!cluster_num)
01141 {
01142 cluster_num = cluster_new_chain;
01143 fd->dir_entry.cluster = cluster_num;
01144 }
01145 }
01146
01147
01148 fd->dir_entry.file_size = size;
01149 if(size == 0)
01150 fd->dir_entry.cluster = 0;
01151 if(!fat16_write_dir_entry(fd->fs, &fd->dir_entry))
01152 return 0;
01153
01154 if(size == 0)
01155 {
01156
01157 fat16_free_clusters(fd->fs, cluster_num);
01158 }
01159 else if(size_new <= cluster_size)
01160 {
01161
01162 fat16_terminate_clusters(fd->fs, cluster_num);
01163 }
01164
01165 } while(0);
01166
01167
01168 if(size < fd->pos)
01169 {
01170 fd->pos = size;
01171 fd->pos_cluster = 0;
01172 }
01173
01174 return 1;
01175 #else
01176 return 0;
01177 #endif
01178 }
01179
01189 struct fat16_dir_struct* fat16_open_dir(struct fat16_fs_struct* fs, const struct fat16_dir_entry_struct* dir_entry)
01190 {
01191 if(!fs || !dir_entry || !(dir_entry->attributes & FAT16_ATTRIB_DIR))
01192 return 0;
01193
01194 #if USE_DYNAMIC_MEMORY
01195 struct fat16_dir_struct* dd = malloc(sizeof(*dd));
01196 if(!dd)
01197 return 0;
01198 #else
01199 struct fat16_dir_struct* dd = fat16_dir_handles;
01200 uint8_t i;
01201 for(i = 0; i < FAT16_DIR_COUNT; ++i)
01202 {
01203 if(!dd->fs)
01204 break;
01205
01206 ++dd;
01207 }
01208 if(i >= FAT16_DIR_COUNT)
01209 return 0;
01210 #endif
01211
01212 memcpy(&dd->dir_entry, dir_entry, sizeof(*dir_entry));
01213 dd->fs = fs;
01214 dd->entry_cluster = dir_entry->cluster;
01215 dd->entry_offset = 0;
01216
01217 return dd;
01218 }
01219
01231 void fat16_close_dir(struct fat16_dir_struct* dd)
01232 {
01233 if(dd)
01234 #if USE_DYNAMIC_MEMORY
01235 free(dd);
01236 #else
01237 dd->fs = 0;
01238 #endif
01239 }
01240
01250 uint8_t fat16_read_dir(struct fat16_dir_struct* dd, struct fat16_dir_entry_struct* dir_entry)
01251 {
01252 if(!dd || !dir_entry)
01253 return 0;
01254
01255
01256 const struct fat16_header_struct* header = &dd->fs->header;
01257 uint16_t cluster_size = header->cluster_size;
01258 uint16_t cluster_num = dd->entry_cluster;
01259 uint16_t cluster_offset = dd->entry_offset;
01260 struct fat16_read_dir_callback_arg arg;
01261
01262
01263 memset(dir_entry, 0, sizeof(*dir_entry));
01264
01265
01266 memset(&arg, 0, sizeof(arg));
01267 arg.dir_entry = dir_entry;
01268
01269
01270 if(cluster_num == 0)
01271 cluster_size = header->cluster_zero_offset - header->root_dir_offset;
01272
01273
01274 uint8_t buffer[32];
01275 while(!arg.finished)
01276 {
01277
01278 uint16_t cluster_left = cluster_size - cluster_offset;
01279 uint32_t pos = cluster_offset;
01280 if(cluster_num == 0)
01281 pos += header->root_dir_offset;
01282 else
01283 pos += fat16_cluster_offset(dd->fs, cluster_num);
01284
01285 arg.bytes_read = 0;
01286 if(!dd->fs->partition->device_read_interval(pos,
01287 buffer,
01288 sizeof(buffer),
01289 cluster_left,
01290 fat16_dir_entry_read_callback,
01291 &arg)
01292 )
01293 return 0;
01294
01295 cluster_offset += arg.bytes_read;
01296
01297 if(cluster_offset >= cluster_size)
01298 {
01299
01300 cluster_offset = 0;
01301
01302
01303 if(!(cluster_num = fat16_get_next_cluster(dd->fs, cluster_num)))
01304 {
01305
01306 cluster_num = dd->dir_entry.cluster;
01307 break;
01308 }
01309 }
01310 }
01311
01312 dd->entry_cluster = cluster_num;
01313 dd->entry_offset = cluster_offset;
01314
01315 return dir_entry->long_name[0] != '\0' ? 1 : 0;
01316 }
01317
01329 uint8_t fat16_reset_dir(struct fat16_dir_struct* dd)
01330 {
01331 if(!dd)
01332 return 0;
01333
01334 dd->entry_cluster = dd->dir_entry.cluster;
01335 dd->entry_offset = 0;
01336 return 1;
01337 }
01338
01343 uint8_t fat16_dir_entry_read_callback(uint8_t* buffer, uint32_t offset, void* p)
01344 {
01345 struct fat16_read_dir_callback_arg* arg = p;
01346 struct fat16_dir_entry_struct* dir_entry = arg->dir_entry;
01347
01348 arg->bytes_read += 32;
01349
01350
01351 if(buffer[0] == FAT16_DIRENTRY_DELETED || !buffer[0])
01352 return 1;
01353
01354 if(!dir_entry->entry_offset)
01355 dir_entry->entry_offset = offset;
01356
01357 switch(fat16_interpret_dir_entry(dir_entry, buffer))
01358 {
01359 case 0:
01360 {
01361 return 0;
01362 }
01363 case 1:
01364 {
01365 return 1;
01366 }
01367 case 2:
01368 {
01369 arg->finished = 1;
01370 return 0;
01371 }
01372 }
01373
01374 return 0;
01375 }
01376
01393 uint8_t fat16_interpret_dir_entry(struct fat16_dir_entry_struct* dir_entry, const uint8_t* raw_entry)
01394 {
01395 if(!dir_entry || !raw_entry || !raw_entry[0])
01396 return 0;
01397
01398 char* long_name = dir_entry->long_name;
01399 if(raw_entry[11] == 0x0f)
01400 {
01401
01402
01403
01404
01405 uint16_t char_offset = ((raw_entry[0] & 0x3f) - 1) * 13;
01406 const uint8_t char_mapping[] = { 1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30 };
01407 for(uint8_t i = 0; i <= 12 && char_offset + i < sizeof(dir_entry->long_name) - 1; ++i)
01408 long_name[char_offset + i] = raw_entry[char_mapping[i]];
01409
01410 return 1;
01411 }
01412 else
01413 {
01414
01415 if(long_name[0] == '\0')
01416 {
01417 uint8_t i;
01418 for(i = 0; i < 8; ++i)
01419 {
01420 if(raw_entry[i] == ' ')
01421 break;
01422 long_name[i] = raw_entry[i];
01423 }
01424 if(long_name[0] == 0x05)
01425 long_name[0] = (char) FAT16_DIRENTRY_DELETED;
01426
01427 if(raw_entry[8] != ' ')
01428 {
01429 long_name[i++] = '.';
01430
01431 uint8_t j = 8;
01432 for(; j < 11; ++j)
01433 {
01434 if(raw_entry[j] != ' ')
01435 {
01436 long_name[i++] = raw_entry[j];
01437 }
01438 else
01439 {
01440 break;
01441 }
01442 }
01443 }
01444
01445 long_name[i] = '\0';
01446 }
01447
01448
01449 dir_entry->attributes = raw_entry[11];
01450 dir_entry->cluster = ((uint16_t) raw_entry[26]) |
01451 ((uint16_t) raw_entry[27] << 8);
01452 dir_entry->file_size = ((uint32_t) raw_entry[28]) |
01453 ((uint32_t) raw_entry[29] << 8) |
01454 ((uint32_t) raw_entry[30] << 16) |
01455 ((uint32_t) raw_entry[31] << 24);
01456
01457 #if FAT16_DATETIME_SUPPORT
01458 dir_entry->modification_time = ((uint16_t) raw_entry[22]) |
01459 ((uint16_t) raw_entry[23] << 8);
01460 dir_entry->modification_date = ((uint16_t) raw_entry[24]) |
01461 ((uint16_t) raw_entry[25] << 8);
01462 #endif
01463
01464 return 2;
01465 }
01466 }
01467
01477 uint32_t fat16_find_offset_for_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_struct* parent, const struct fat16_dir_entry_struct* dir_entry)
01478 {
01479 #if FAT16_WRITE_SUPPORT
01480 if(!fs || !dir_entry)
01481 return 0;
01482
01483
01484 uint8_t free_dir_entries_needed = (strlen(dir_entry->long_name) + 12) / 13 + 1;
01485 uint8_t free_dir_entries_found = 0;
01486 uint16_t cluster_num = parent->dir_entry.cluster;
01487 uint32_t dir_entry_offset = 0;
01488 uint32_t offset = 0;
01489 uint32_t offset_to = 0;
01490
01491 if(cluster_num == 0)
01492 {
01493
01494 offset = fs->header.root_dir_offset;
01495 offset_to = fs->header.cluster_zero_offset;
01496 dir_entry_offset = offset;
01497 }
01498
01499 while(1)
01500 {
01501 if(offset == offset_to)
01502 {
01503 if(cluster_num == 0)
01504
01505
01506
01507 return 0;
01508
01509 if(offset)
01510 {
01511
01512
01513
01514
01515 uint16_t cluster_next = fat16_get_next_cluster(fs, cluster_num);
01516 if(!cluster_next)
01517 {
01518 cluster_next = fat16_append_clusters(fs, cluster_num, 1);
01519 if(!cluster_next)
01520 return 0;
01521
01522
01523 dir_entry_offset = fs->header.cluster_zero_offset +
01524 (uint32_t) (cluster_next - 2) * fs->header.cluster_size;
01525
01526
01527 fat16_clear_cluster(fs, cluster_next);
01528
01529 break;
01530 }
01531 cluster_num = cluster_next;
01532 }
01533
01534 offset = fat16_cluster_offset(fs, cluster_num);
01535 offset_to = offset + fs->header.cluster_size;
01536 dir_entry_offset = offset;
01537 free_dir_entries_found = 0;
01538 }
01539
01540
01541 uint8_t first_char;
01542 if(!fs->partition->device_read(offset, &first_char, sizeof(first_char)))
01543 return 0;
01544
01545
01546 if(first_char == FAT16_DIRENTRY_DELETED || !first_char)
01547 {
01548
01549 ++free_dir_entries_found;
01550 if(free_dir_entries_found >= free_dir_entries_needed)
01551 break;
01552
01553 offset += 32;
01554 }
01555 else
01556 {
01557 offset += 32;
01558 dir_entry_offset = offset;
01559 free_dir_entries_found = 0;
01560 }
01561 }
01562
01563 return dir_entry_offset;
01564
01565 #else
01566 return 0;
01567 #endif
01568 }
01569
01589 uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry)
01590 {
01591 #if FAT16_WRITE_SUPPORT
01592 if(!fs || !dir_entry)
01593 return 0;
01594
01595 #if FAT16_DATETIME_SUPPORT
01596 {
01597 uint16_t year;
01598 uint8_t month;
01599 uint8_t day;
01600 uint8_t hour;
01601 uint8_t min;
01602 uint8_t sec;
01603
01604 fat16_get_datetime(&year, &month, &day, &hour, &min, &sec);
01605 fat16_set_file_modification_date(dir_entry, year, month, day);
01606 fat16_set_file_modification_time(dir_entry, hour, min, sec);
01607 }
01608 #endif
01609
01610 device_write_t device_write = fs->partition->device_write;
01611 uint32_t offset = dir_entry->entry_offset;
01612 const char* name = dir_entry->long_name;
01613 uint8_t name_len = strlen(name);
01614 uint8_t lfn_entry_count = (name_len + 12) / 13;
01615 uint8_t buffer[32];
01616
01617
01618
01619
01620 memset(&buffer[0], ' ', 11);
01621 char* name_ext = strrchr(name, '.');
01622 if(name_ext && *++name_ext)
01623 {
01624 uint8_t name_ext_len = strlen(name_ext);
01625 name_len -= name_ext_len + 1;
01626
01627 if(name_ext_len > 3)
01628 name_ext_len = 3;
01629
01630 memcpy(&buffer[8], name_ext, name_ext_len);
01631 }
01632
01633 if(name_len <= 8)
01634 {
01635 memcpy(buffer, name, name_len);
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646 if(name[0] == '.' &&
01647 ((name[1] == '.' && name[2] == '\0') ||
01648 name[1] == '\0')
01649 )
01650 lfn_entry_count = 0;
01651 }
01652 else
01653 {
01654 memcpy(buffer, name, 8);
01655
01656
01657
01658
01659 uint8_t num = dir_entry->cluster & 0xff;
01660
01661 buffer[6] = (num < 0xa0) ? ('0' + (num >> 4)) : ('a' + (num >> 4));
01662 num &= 0x0f;
01663 buffer[7] = (num < 0x0a) ? ('0' + num) : ('a' + num);
01664 }
01665 if(buffer[0] == FAT16_DIRENTRY_DELETED)
01666 buffer[0] = 0x05;
01667
01668
01669 memset(&buffer[11], 0, sizeof(buffer) - 11);
01670 buffer[0x0b] = dir_entry->attributes;
01671 #if FAT16_DATETIME_SUPPORT
01672 buffer[0x16] = (dir_entry->modification_time >> 0) & 0xff;
01673 buffer[0x17] = (dir_entry->modification_time >> 8) & 0xff;
01674 buffer[0x18] = (dir_entry->modification_date >> 0) & 0xff;
01675 buffer[0x19] = (dir_entry->modification_date >> 8) & 0xff;
01676 #endif
01677 buffer[0x1a] = (dir_entry->cluster >> 0) & 0xff;
01678 buffer[0x1b] = (dir_entry->cluster >> 8) & 0xff;
01679 buffer[0x1c] = (dir_entry->file_size >> 0) & 0xff;
01680 buffer[0x1d] = (dir_entry->file_size >> 8) & 0xff;
01681 buffer[0x1e] = (dir_entry->file_size >> 16) & 0xff;
01682 buffer[0x1f] = (dir_entry->file_size >> 24) & 0xff;
01683
01684
01685 if(!device_write(offset + (uint32_t) lfn_entry_count * 32, buffer, sizeof(buffer)))
01686 return 0;
01687
01688
01689 uint8_t checksum = buffer[0];
01690 for(uint8_t i = 1; i < 11; ++i)
01691 checksum = ((checksum >> 1) | (checksum << 7)) + buffer[i];
01692
01693
01694 for(uint8_t lfn_entry = lfn_entry_count; lfn_entry > 0; --lfn_entry)
01695 {
01696 memset(buffer, 0xff, sizeof(buffer));
01697
01698
01699 const char* long_name_curr = name + (lfn_entry - 1) * 13;
01700 uint8_t i = 1;
01701 while(i < 0x1f)
01702 {
01703 buffer[i++] = *long_name_curr;
01704 buffer[i++] = 0;
01705
01706 switch(i)
01707 {
01708 case 0x0b:
01709 i = 0x0e;
01710 break;
01711 case 0x1a:
01712 i = 0x1c;
01713 break;
01714 }
01715
01716 if(!*long_name_curr++)
01717 break;
01718 }
01719
01720
01721 buffer[0x00] = lfn_entry;
01722 if(lfn_entry == lfn_entry_count)
01723 buffer[0x00] |= FAT16_DIRENTRY_LFNLAST;
01724
01725
01726 buffer[0x0b] = 0x0f;
01727
01728
01729 buffer[0x0d] = checksum;
01730
01731
01732 buffer[0x0c] = 0;
01733 buffer[0x1a] = 0;
01734 buffer[0x1b] = 0;
01735
01736
01737 device_write(offset, buffer, sizeof(buffer));
01738
01739 offset += sizeof(buffer);
01740 }
01741
01742 return 1;
01743
01744 #else
01745 return 0;
01746 #endif
01747 }
01748
01775 uint8_t fat16_create_file(struct fat16_dir_struct* parent, const char* file, struct fat16_dir_entry_struct* dir_entry)
01776 {
01777 #if FAT16_WRITE_SUPPORT
01778 if(!parent || !file || !file[0] || !dir_entry)
01779 return 0;
01780
01781
01782 while(1)
01783 {
01784 if(!fat16_read_dir(parent, dir_entry))
01785 break;
01786
01787 if(strcmp(file, dir_entry->long_name) == 0)
01788 {
01789 fat16_reset_dir(parent);
01790 return 0;
01791 }
01792 }
01793
01794 struct fat16_fs_struct* fs = parent->fs;
01795
01796
01797 memset(dir_entry, 0, sizeof(*dir_entry));
01798 strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1);
01799
01800
01801 if(!(dir_entry->entry_offset = fat16_find_offset_for_dir_entry(fs, parent, dir_entry)))
01802 return 0;
01803
01804
01805 if(!fat16_write_dir_entry(fs, dir_entry))
01806 return 0;
01807
01808 return 1;
01809
01810 #else
01811 return 0;
01812 #endif
01813 }
01814
01829 uint8_t fat16_delete_file(struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry)
01830 {
01831 #if FAT16_WRITE_SUPPORT
01832 if(!fs || !dir_entry)
01833 return 0;
01834
01835
01836 uint32_t dir_entry_offset = dir_entry->entry_offset;
01837 if(!dir_entry_offset)
01838 return 0;
01839
01840 uint8_t buffer[12];
01841 while(1)
01842 {
01843
01844 if(!fs->partition->device_read(dir_entry_offset, buffer, sizeof(buffer)))
01845 return 0;
01846
01847
01848 buffer[0] = FAT16_DIRENTRY_DELETED;
01849
01850
01851 if(!fs->partition->device_write(dir_entry_offset, buffer, sizeof(buffer)))
01852 return 0;
01853
01854
01855 if(buffer[11] != 0x0f)
01856 break;
01857
01858 dir_entry_offset += 32;
01859 }
01860
01861
01862
01863
01864 return (dir_entry->cluster == 0 || fat16_free_clusters(fs, dir_entry->cluster));
01865 #else
01866 return 0;
01867 #endif
01868 }
01869
01888 uint8_t fat16_create_dir(struct fat16_dir_struct* parent, const char* dir, struct fat16_dir_entry_struct* dir_entry)
01889 {
01890 #if FAT16_WRITE_SUPPORT
01891 if(!parent || !dir || !dir[0] || !dir_entry)
01892 return 0;
01893
01894
01895 while(1)
01896 {
01897 if(!fat16_read_dir(parent, dir_entry))
01898 break;
01899
01900 if(strcmp(dir, dir_entry->long_name) == 0)
01901 {
01902 fat16_reset_dir(parent);
01903 return 0;
01904 }
01905 }
01906
01907 struct fat16_fs_struct* fs = parent->fs;
01908
01909
01910 uint16_t dir_cluster = fat16_append_clusters(fs, 0, 1);
01911 if(!dir_cluster)
01912 return 0;
01913
01914
01915 fat16_clear_cluster(fs, dir_cluster);
01916
01917 memset(dir_entry, 0, sizeof(*dir_entry));
01918 dir_entry->attributes = FAT16_ATTRIB_DIR;
01919
01920
01921 dir_entry->entry_offset = fs->header.cluster_zero_offset +
01922 (uint32_t) (dir_cluster - 2) * fs->header.cluster_size;
01923 dir_entry->long_name[0] = '.';
01924 dir_entry->cluster = dir_cluster;
01925 if(!fat16_write_dir_entry(fs, dir_entry))
01926 {
01927 fat16_free_clusters(fs, dir_cluster);
01928 return 0;
01929 }
01930
01931
01932 dir_entry->entry_offset += 32;
01933 dir_entry->long_name[1] = '.';
01934 dir_entry->cluster = parent->dir_entry.cluster;
01935 if(!fat16_write_dir_entry(fs, dir_entry))
01936 {
01937 fat16_free_clusters(fs, dir_cluster);
01938 return 0;
01939 }
01940
01941
01942 strncpy(dir_entry->long_name, dir, sizeof(dir_entry->long_name) - 1);
01943 dir_entry->cluster = dir_cluster;
01944
01945
01946 if(!(dir_entry->entry_offset = fat16_find_offset_for_dir_entry(fs, parent, dir_entry)))
01947 {
01948 fat16_free_clusters(fs, dir_cluster);
01949 return 0;
01950 }
01951
01952
01953 if(!fat16_write_dir_entry(fs, dir_entry))
01954 {
01955 fat16_free_clusters(fs, dir_cluster);
01956 return 0;
01957 }
01958
01959 return 1;
01960
01961 #else
01962 return 0;
01963 #endif
01964 }
01965
01981 #ifdef DOXYGEN
01982 uint8_t fat16_delete_dir(struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry);
01983 #endif
01984
01994 void fat16_get_file_modification_date(const struct fat16_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day)
01995 {
01996 #if FAT16_DATETIME_SUPPORT
01997 if(!dir_entry)
01998 return;
01999
02000 *year = 1980 + ((dir_entry->modification_date >> 9) & 0x7f);
02001 *month = (dir_entry->modification_date >> 5) & 0x0f;
02002 *day = (dir_entry->modification_date >> 0) & 0x1f;
02003 #endif
02004 }
02005
02015 void fat16_get_file_modification_time(const struct fat16_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec)
02016 {
02017 #if FAT16_DATETIME_SUPPORT
02018 if(!dir_entry)
02019 return;
02020
02021 *hour = (dir_entry->modification_time >> 11) & 0x1f;
02022 *min = (dir_entry->modification_time >> 5) & 0x3f;
02023 *sec = ((dir_entry->modification_time >> 0) & 0x1f) * 2;
02024 #endif
02025 }
02026
02036 void fat16_set_file_modification_date(struct fat16_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day)
02037 {
02038 #if FAT16_WRITE_SUPPORT
02039 #if FAT16_DATETIME_SUPPORT
02040 if(!dir_entry)
02041 return;
02042
02043 dir_entry->modification_date =
02044 ((year - 1980) << 9) |
02045 ((uint16_t) month << 5) |
02046 ((uint16_t) day << 0);
02047 #endif
02048 #endif
02049 }
02050
02060 void fat16_set_file_modification_time(struct fat16_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec)
02061 {
02062 #if FAT16_WRITE_SUPPORT
02063 #if FAT16_DATETIME_SUPPORT
02064 if(!dir_entry)
02065 return;
02066
02067 dir_entry->modification_time =
02068 ((uint16_t) hour << 11) |
02069 ((uint16_t) min << 5) |
02070 ((uint16_t) sec >> 1) ;
02071 #endif
02072 #endif
02073 }
02074
02082 uint32_t fat16_get_fs_size(const struct fat16_fs_struct* fs)
02083 {
02084 if(!fs)
02085 return 0;
02086
02087 return (fs->header.fat_size / 2 - 2) * fs->header.cluster_size;
02088 }
02089
02100 uint32_t fat16_get_fs_free(const struct fat16_fs_struct* fs)
02101 {
02102 if(!fs)
02103 return 0;
02104
02105 uint8_t fat[32];
02106 struct fat16_usage_count_callback_arg count_arg;
02107 count_arg.cluster_count = 0;
02108 count_arg.buffer_size = sizeof(fat);
02109
02110 uint32_t fat_offset = fs->header.fat_offset;
02111 uint32_t fat_size = fs->header.fat_size;
02112 while(fat_size > 0)
02113 {
02114 uint16_t length = UINT16_MAX - 1;
02115 if(fat_size < length)
02116 length = fat_size;
02117
02118 if(!fs->partition->device_read_interval(fat_offset,
02119 fat,
02120 sizeof(fat),
02121 length,
02122 fat16_get_fs_free_callback,
02123 &count_arg
02124 )
02125 )
02126 return 0;
02127
02128 fat_offset += length;
02129 fat_size -= length;
02130 }
02131
02132 return (uint32_t) count_arg.cluster_count * fs->header.cluster_size;
02133 }
02134
02139 uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p)
02140 {
02141 struct fat16_usage_count_callback_arg* count_arg = (struct fat16_usage_count_callback_arg*) p;
02142 uint8_t buffer_size = count_arg->buffer_size;
02143
02144 for(uint8_t i = 0; i < buffer_size; i += 2)
02145 {
02146 if((((uint16_t) buffer[1] << 8) | ((uint16_t) buffer[0] << 0)) == FAT16_CLUSTER_FREE)
02147 ++(count_arg->cluster_count);
02148
02149 buffer += 2;
02150 }
02151
02152 return 1;
02153 }
02154