Lightweight SD card FAT file system. Originaled by chan http://elm-chan.org/fsw/ff/00index_p.html
Embed:
(wiki syntax)
Show/hide line numbers
pff.cpp
00001 /*----------------------------------------------------------------------------/ 00002 / Petit FatFs - FAT file system module R0.02a (C)ChaN, 2010 00003 /-----------------------------------------------------------------------------/ 00004 / Petit FatFs module is an open source software to implement FAT file system to 00005 / small embedded systems. This is a free software and is opened for education, 00006 / research and commercial developments under license policy of following trems. 00007 / 00008 / Copyright (C) 2010, ChaN, all right reserved. 00009 / 00010 / * The Petit FatFs module is a free software and there is NO WARRANTY. 00011 / * No restriction on use. You can use, modify and redistribute it for 00012 / personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY. 00013 / * Redistributions of source code must retain the above copyright notice. 00014 / 00015 /-----------------------------------------------------------------------------/ 00016 / Jun 15,'09 R0.01a First release. (Branched from FatFs R0.07b.) 00017 / 00018 / Dec 14,'09 R0.02 Added multiple code page support. 00019 / Added write funciton. 00020 / Changed stream read mode interface. 00021 / Dec 07,'10 R0.02a Added some configuration options. 00022 / Fixed fails to open objects with DBCS character. 00023 /----------------------------------------------------------------------------*/ 00024 00025 #include "pff.h" /* Petit FatFs configurations and declarations */ 00026 #include "diskio.h" /* Declarations of low level disk I/O functions */ 00027 00028 00029 /*-------------------------------------------------------------------------- 00030 00031 Module Private Definitions 00032 00033 ---------------------------------------------------------------------------*/ 00034 00035 00036 #if _FS_FAT32 00037 #define LD_CLUST(dir) (((DWORD)LD_WORD(dir+PFFDIR_FstClusHI)<<16) | LD_WORD(dir+PFFDIR_FstClusLO)) 00038 #else 00039 #define LD_CLUST(dir) LD_WORD(dir+PFFDIR_FstClusLO) 00040 #endif 00041 00042 00043 /*--------------------------------------------------------*/ 00044 /* DBCS code ranges and SBCS extend char conversion table */ 00045 00046 #if _CODE_PAGE == 932 /* Japanese Shift-JIS */ 00047 #define _DF1S 0x81 /* DBC 1st byte range 1 start */ 00048 #define _DF1E 0x9F /* DBC 1st byte range 1 end */ 00049 #define _DF2S 0xE0 /* DBC 1st byte range 2 start */ 00050 #define _DF2E 0xFC /* DBC 1st byte range 2 end */ 00051 #define _DS1S 0x40 /* DBC 2nd byte range 1 start */ 00052 #define _DS1E 0x7E /* DBC 2nd byte range 1 end */ 00053 #define _DS2S 0x80 /* DBC 2nd byte range 2 start */ 00054 #define _DS2E 0xFC /* DBC 2nd byte range 2 end */ 00055 00056 #elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ 00057 #define _DF1S 0x81 00058 #define _DF1E 0xFE 00059 #define _DS1S 0x40 00060 #define _DS1E 0x7E 00061 #define _DS2S 0x80 00062 #define _DS2E 0xFE 00063 00064 #elif _CODE_PAGE == 949 /* Korean */ 00065 #define _DF1S 0x81 00066 #define _DF1E 0xFE 00067 #define _DS1S 0x41 00068 #define _DS1E 0x5A 00069 #define _DS2S 0x61 00070 #define _DS2E 0x7A 00071 #define _DS3S 0x81 00072 #define _DS3E 0xFE 00073 00074 #elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ 00075 #define _DF1S 0x81 00076 #define _DF1E 0xFE 00077 #define _DS1S 0x40 00078 #define _DS1E 0x7E 00079 #define _DS2S 0xA1 00080 #define _DS2E 0xFE 00081 00082 #elif _CODE_PAGE == 437 /* U.S. (OEM) */ 00083 #define _DF1S 0 00084 #define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F,0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00085 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00086 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00087 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00088 00089 #elif _CODE_PAGE == 720 /* Arabic (OEM) */ 00090 #define _DF1S 0 00091 #define _EXCVT {0x80,0x81,0x45,0x41,0x84,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x49,0x49,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00092 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00093 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00094 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00095 00096 #elif _CODE_PAGE == 737 /* Greek (OEM) */ 00097 #define _DF1S 0 00098 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ 00099 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00100 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00101 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xE7,0xE8,0xF1,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00102 00103 #elif _CODE_PAGE == 775 /* Baltic (OEM) */ 00104 #define _DF1S 0 00105 #define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ 00106 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00107 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00108 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00109 00110 #elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */ 00111 #define _DF1S 0 00112 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ 00113 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00114 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00115 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00116 00117 #elif _CODE_PAGE == 852 /* Latin 2 (OEM) */ 00118 #define _DF1S 0 00119 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F,0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0x9F, \ 00120 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ 00121 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00122 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} 00123 00124 #elif _CODE_PAGE == 855 /* Cyrillic (OEM) */ 00125 #define _DF1S 0 00126 #define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F,0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ 00127 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ 00128 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ 00129 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} 00130 00131 #elif _CODE_PAGE == 857 /* Turkish (OEM) */ 00132 #define _DF1S 0 00133 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x98,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ 00134 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00135 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00136 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0x59,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00137 00138 #elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */ 00139 #define _DF1S 0 00140 #define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0xDE,0x8E,0x8F,0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x59,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ 00141 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00142 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD1,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00143 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE7,0xE9,0xEA,0xEB,0xED,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00144 00145 #elif _CODE_PAGE == 862 /* Hebrew (OEM) */ 00146 #define _DF1S 0 00147 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00148 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0x21,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00149 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00150 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00151 00152 #elif _CODE_PAGE == 866 /* Russian (OEM) */ 00153 #define _DF1S 0 00154 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00155 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00156 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00157 0x90,0x91,0x92,0x93,0x9d,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F,0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00158 00159 #elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */ 00160 #define _DF1S 0 00161 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00162 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00163 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00164 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00165 00166 #elif _CODE_PAGE == 1250 /* Central Europe (Windows) */ 00167 #define _DF1S 0 00168 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ 00169 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xA3,0xB4,0xB5,0xB6,0xB7,0xB8,0xA5,0xAA,0xBB,0xBC,0xBD,0xBC,0xAF, \ 00170 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00171 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} 00172 00173 #elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */ 00174 #define _DF1S 0 00175 #define _EXCVT {0x80,0x81,0x82,0x82,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x80,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x8D,0x8E,0x8F, \ 00176 0xA0,0xA2,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB2,0xA5,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xA3,0xBD,0xBD,0xAF, \ 00177 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00178 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF} 00179 00180 #elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */ 00181 #define _DF1S 0 00182 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0xAd,0x9B,0x8C,0x9D,0xAE,0x9F, \ 00183 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00184 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00185 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} 00186 00187 #elif _CODE_PAGE == 1253 /* Greek (Windows) */ 00188 #define _DF1S 0 00189 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00190 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00191 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xA2,0xB8,0xB9,0xBA, \ 00192 0xE0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xFB,0xBC,0xFD,0xBF,0xFF} 00193 00194 #elif _CODE_PAGE == 1254 /* Turkish (Windows) */ 00195 #define _DF1S 0 00196 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x8A,0x9B,0x8C,0x9D,0x9E,0x9F, \ 00197 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00198 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00199 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x9F} 00200 00201 #elif _CODE_PAGE == 1255 /* Hebrew (Windows) */ 00202 #define _DF1S 0 00203 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00204 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00205 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00206 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} 00207 00208 #elif _CODE_PAGE == 1256 /* Arabic (Windows) */ 00209 #define _DF1S 0 00210 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x8C,0x9D,0x9E,0x9F, \ 00211 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00212 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00213 0x41,0xE1,0x41,0xE3,0xE4,0xE5,0xE6,0x43,0x45,0x45,0x45,0x45,0xEC,0xED,0x49,0x49,0xF0,0xF1,0xF2,0xF3,0x4F,0xF5,0xF6,0xF7,0xF8,0x55,0xFA,0x55,0x55,0xFD,0xFE,0xFF} 00214 00215 #elif _CODE_PAGE == 1257 /* Baltic (Windows) */ 00216 #define _DF1S 0 00217 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ 00218 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xA8,0xB9,0xAA,0xBB,0xBC,0xBD,0xBE,0xAF, \ 00219 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00220 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xFF} 00221 00222 #elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */ 00223 #define _DF1S 0 00224 #define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0xAC,0x9D,0x9E,0x9F, \ 00225 0xA0,0x21,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF,0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ 00226 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ 00227 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xEC,0xCD,0xCE,0xCF,0xD0,0xD1,0xF2,0xD3,0xD4,0xD5,0xD6,0xF7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xFE,0x9F} 00228 00229 #elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ 00230 #define _DF1S 0 00231 00232 #else 00233 #error Unknown code page 00234 00235 #endif 00236 00237 00238 00239 /* Character code support macros */ 00240 00241 #define IsUpper(c) (((c)>='A')&&((c)<='Z')) 00242 #define IsLower(c) (((c)>='a')&&((c)<='z')) 00243 00244 #if _DF1S /* DBCS configuration */ 00245 00246 #ifdef _DF2S /* Two 1st byte areas */ 00247 #define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) 00248 #else /* One 1st byte area */ 00249 #define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) 00250 #endif 00251 00252 #ifdef _DS3S /* Three 2nd byte areas */ 00253 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) 00254 #else /* Two 2nd byte areas */ 00255 #define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) 00256 #endif 00257 00258 #else /* SBCS configuration */ 00259 00260 #define IsDBCS1(c) 0 00261 #define IsDBCS2(c) 0 00262 00263 #endif /* _DF1S */ 00264 00265 00266 /* FatFs refers the members in the FAT structures with byte offset instead 00267 / of structure member because there are incompatibility of the packing option 00268 / between various compilers. */ 00269 00270 #define BS_jmpBoot 0 00271 #define BS_OEMName 3 00272 #define BPB_BytsPerSec 11 00273 #define BPB_SecPerClus 13 00274 #define BPB_RsvdSecCnt 14 00275 #define BPB_NumFATs 16 00276 #define BPB_RootEntCnt 17 00277 #define BPB_TotSec16 19 00278 #define BPB_Media 21 00279 #define BPB_FATSz16 22 00280 #define BPB_SecPerTrk 24 00281 #define BPB_NumHeads 26 00282 #define BPB_HiddSec 28 00283 #define BPB_TotSec32 32 00284 #define BS_55AA 510 00285 00286 #define BS_DrvNum 36 00287 #define BS_BootSig 38 00288 #define BS_VolID 39 00289 #define BS_VolLab 43 00290 #define BS_FilSysType 54 00291 00292 #define BPB_FATSz32 36 00293 #define BPB_ExtFlags 40 00294 #define BPB_FSVer 42 00295 #define BPB_RootClus 44 00296 #define BPB_FSInfo 48 00297 #define BPB_BkBootSec 50 00298 #define BS_DrvNum32 64 00299 #define BS_BootSig32 66 00300 #define BS_VolID32 67 00301 #define BS_VolLab32 71 00302 #define BS_FilSysType32 82 00303 00304 #define MBR_Table 446 00305 00306 #define PFFDIR_Name 0 00307 #define PFFDIR_Attr 11 00308 #define PFFDIR_NTres 12 00309 #define PFFDIR_CrtTime 14 00310 #define PFFDIR_CrtDate 16 00311 #define PFFDIR_FstClusHI 20 00312 #define PFFDIR_WrtTime 22 00313 #define PFFDIR_WrtDate 24 00314 #define PFFDIR_FstClusLO 26 00315 #define PFFDIR_FileSize 28 00316 00317 00318 00319 /*-------------------------------------------------------------------------- 00320 00321 Private Functions 00322 00323 ---------------------------------------------------------------------------*/ 00324 00325 00326 static 00327 FATFS *FatFs; /* Pointer to the file system object (logical drive) */ 00328 00329 00330 /* Fill memory */ 00331 static 00332 void mem_set (void* dst, int val, int cnt) { 00333 char *d = (char*)dst; 00334 while (cnt--) *d++ = (char)val; 00335 } 00336 00337 /* Compare memory to memory */ 00338 static 00339 int mem_cmp (const void* dst, const void* src, int cnt) { 00340 const char *d = (const char *)dst, *s = (const char *)src; 00341 int r = 0; 00342 while (cnt-- && (r = *d++ - *s++) == 0) ; 00343 return r; 00344 } 00345 00346 00347 00348 /*-----------------------------------------------------------------------*/ 00349 /* FAT access - Read value of a FAT entry */ 00350 /*-----------------------------------------------------------------------*/ 00351 00352 static 00353 CLUST get_fat ( /* 1:IO error, Else:Cluster status */ 00354 CLUST clst /* Cluster# to get the link information */ 00355 ) 00356 { 00357 WORD wc, bc, ofs; 00358 BYTE buf[4]; 00359 FATFS *fs = FatFs; 00360 00361 00362 if (clst < 2 || clst >= fs->n_fatent) /* Range check */ 00363 return 1; 00364 00365 switch (fs->fs_type) { 00366 #if _FS_FAT12 00367 case FS_FAT12 : 00368 bc = (WORD)clst; bc += bc / 2; 00369 ofs = bc % 512; bc /= 512; 00370 if (ofs != 511) { 00371 if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break; 00372 } else { 00373 if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break; 00374 if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break; 00375 } 00376 wc = LD_WORD(buf); 00377 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF); 00378 #endif 00379 case FS_FAT16 : 00380 if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break; 00381 return LD_WORD(buf); 00382 #if _FS_FAT32 00383 case FS_FAT32 : 00384 if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break; 00385 return LD_DWORD(buf) & 0x0FFFFFFF; 00386 #endif 00387 } 00388 00389 return 1; /* An error occured at the disk I/O layer */ 00390 } 00391 00392 00393 00394 00395 /*-----------------------------------------------------------------------*/ 00396 /* Get sector# from cluster# */ 00397 /*-----------------------------------------------------------------------*/ 00398 00399 static 00400 DWORD clust2sect ( /* !=0: Sector number, 0: Failed - invalid cluster# */ 00401 CLUST clst /* Cluster# to be converted */ 00402 ) 00403 { 00404 FATFS *fs = FatFs; 00405 00406 00407 clst -= 2; 00408 if (clst >= (fs->n_fatent - 2)) return 0; /* Invalid cluster# */ 00409 return (DWORD)clst * fs->csize + fs->database; 00410 } 00411 00412 00413 00414 00415 /*-----------------------------------------------------------------------*/ 00416 /* Directory handling - Rewind directory index */ 00417 /*-----------------------------------------------------------------------*/ 00418 00419 static 00420 FRESULT dir_rewind ( 00421 PFFDIR *dj /* Pointer to directory object */ 00422 ) 00423 { 00424 CLUST clst; 00425 FATFS *fs = FatFs; 00426 00427 00428 dj->index = 0; 00429 clst = dj->sclust; 00430 if (clst == 1 || clst >= fs->n_fatent) /* Check start cluster range */ 00431 return FR_DISK_ERR; 00432 if (_FS_FAT32 && !clst && fs->fs_type == FS_FAT32) /* Replace cluster# 0 with root cluster# if in FAT32 */ 00433 clst = (CLUST)fs->dirbase; 00434 dj->clust = clst; /* Current cluster */ 00435 dj->sect = clst ? clust2sect(clst) : fs->dirbase; /* Current sector */ 00436 00437 return FR_OK; /* Seek succeeded */ 00438 } 00439 00440 00441 00442 00443 /*-----------------------------------------------------------------------*/ 00444 /* Directory handling - Move directory index next */ 00445 /*-----------------------------------------------------------------------*/ 00446 00447 static 00448 FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table */ 00449 PFFDIR *dj /* Pointer to directory object */ 00450 ) 00451 { 00452 CLUST clst; 00453 WORD i; 00454 FATFS *fs = FatFs; 00455 00456 00457 i = dj->index + 1; 00458 if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ 00459 return FR_NO_FILE; 00460 00461 if (!(i % 16)) { /* Sector changed? */ 00462 dj->sect++; /* Next sector */ 00463 00464 if (dj->clust == 0) { /* Static table */ 00465 if (i >= fs->n_rootdir) /* Report EOT when end of table */ 00466 return FR_NO_FILE; 00467 } 00468 else { /* Dynamic table */ 00469 if (((i / 16) & (fs->csize-1)) == 0) { /* Cluster changed? */ 00470 clst = get_fat(dj->clust); /* Get next cluster */ 00471 if (clst <= 1) return FR_DISK_ERR; 00472 if (clst >= fs->n_fatent) /* When it reached end of dynamic table */ 00473 return FR_NO_FILE; /* Report EOT */ 00474 dj->clust = clst; /* Initialize data for new cluster */ 00475 dj->sect = clust2sect(clst); 00476 } 00477 } 00478 } 00479 00480 dj->index = i; 00481 00482 return FR_OK; 00483 } 00484 00485 00486 00487 00488 /*-----------------------------------------------------------------------*/ 00489 /* Directory handling - Find an object in the directory */ 00490 /*-----------------------------------------------------------------------*/ 00491 00492 static 00493 FRESULT dir_find ( 00494 PFFDIR *dj, /* Pointer to the directory object linked to the file name */ 00495 BYTE *dir /* 32-byte working buffer */ 00496 ) 00497 { 00498 FRESULT res; 00499 BYTE c; 00500 00501 00502 res = dir_rewind(dj); /* Rewind directory object */ 00503 if (res != FR_OK) return res; 00504 00505 do { 00506 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */ 00507 ? FR_DISK_ERR : FR_OK; 00508 if (res != FR_OK) break; 00509 c = dir[PFFDIR_Name]; /* First character */ 00510 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ 00511 if (!(dir[PFFDIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */ 00512 break; 00513 res = dir_next(dj); /* Next entry */ 00514 } while (res == FR_OK); 00515 00516 return res; 00517 } 00518 00519 00520 00521 00522 /*-----------------------------------------------------------------------*/ 00523 /* Read an object from the directory */ 00524 /*-----------------------------------------------------------------------*/ 00525 #if _USE_DIR 00526 static 00527 FRESULT dir_read ( 00528 PFFDIR *dj, /* Pointer to the directory object to store read object name */ 00529 BYTE *dir /* 32-byte working buffer */ 00530 ) 00531 { 00532 FRESULT res; 00533 BYTE a, c; 00534 00535 00536 res = FR_NO_FILE; 00537 while (dj->sect) { 00538 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32) /* Read an entry */ 00539 ? FR_DISK_ERR : FR_OK; 00540 if (res != FR_OK) break; 00541 c = dir[PFFDIR_Name]; 00542 if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ 00543 a = dir[PFFDIR_Attr] & AM_MASK; 00544 if (c != 0xE5 && c != '.' && !(a & AM_VOL)) /* Is it a valid entry? */ 00545 break; 00546 res = dir_next(dj); /* Next entry */ 00547 if (res != FR_OK) break; 00548 } 00549 00550 if (res != FR_OK) dj->sect = 0; 00551 00552 return res; 00553 } 00554 #endif 00555 00556 00557 00558 /*-----------------------------------------------------------------------*/ 00559 /* Pick a segment and create the object name in directory form */ 00560 /*-----------------------------------------------------------------------*/ 00561 00562 #ifdef _EXCVT 00563 static const BYTE cvt[] = _EXCVT; 00564 #endif 00565 00566 static 00567 FRESULT create_name ( 00568 PFFDIR *dj, /* Pointer to the directory object */ 00569 const char **path /* Pointer to pointer to the segment in the path string */ 00570 ) 00571 { 00572 BYTE c, d, ni, si, i, *sfn; 00573 const char *p; 00574 00575 /* Create file name in directory form */ 00576 sfn = dj->fn; 00577 mem_set(sfn, ' ', 11); 00578 si = i = 0; ni = 8; 00579 p = *path; 00580 for (;;) { 00581 c = p[si++]; 00582 if (c <= ' ' || c == '/') break; /* Break on end of segment */ 00583 if (c == '.' || i >= ni) { 00584 if (ni != 8 || c != '.') break; 00585 i = 8; ni = 11; 00586 continue; 00587 } 00588 #ifdef _EXCVT 00589 if (c >= 0x80) /* To upper extended char (SBCS) */ 00590 c = cvt[c - 0x80]; 00591 #endif 00592 if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st byte? */ 00593 d = p[si++]; /* Get 2nd byte */ 00594 sfn[i++] = c; 00595 sfn[i++] = d; 00596 } else { /* Single byte code */ 00597 if (IsLower(c)) c -= 0x20; /* toupper */ 00598 sfn[i++] = c; 00599 } 00600 } 00601 *path = &p[si]; /* Rerurn pointer to the next segment */ 00602 00603 sfn[11] = (c <= ' ') ? 1 : 0; /* Set last segment flag if end of path */ 00604 00605 return FR_OK; 00606 } 00607 00608 00609 00610 00611 /*-----------------------------------------------------------------------*/ 00612 /* Get file information from directory entry */ 00613 /*-----------------------------------------------------------------------*/ 00614 #if _USE_DIR 00615 static 00616 void get_fileinfo ( /* No return code */ 00617 PFFDIR *dj, /* Pointer to the directory object */ 00618 BYTE *dir, /* 32-byte working buffer */ 00619 FILINFO *fno /* Pointer to store the file information */ 00620 ) 00621 { 00622 BYTE i, c; 00623 char *p; 00624 00625 00626 p = fno->fname; 00627 if (dj->sect) { 00628 for (i = 0; i < 8; i++) { /* Copy file name body */ 00629 c = dir[i]; 00630 if (c == ' ') break; 00631 if (c == 0x05) c = 0xE5; 00632 *p++ = c; 00633 } 00634 if (dir[8] != ' ') { /* Copy file name extension */ 00635 *p++ = '.'; 00636 for (i = 8; i < 11; i++) { 00637 c = dir[i]; 00638 if (c == ' ') break; 00639 *p++ = c; 00640 } 00641 } 00642 fno->fattrib = dir[PFFDIR_Attr]; /* Attribute */ 00643 fno->fsize = LD_DWORD(dir+PFFDIR_FileSize); /* Size */ 00644 fno->fdate = LD_WORD(dir+PFFDIR_WrtDate); /* Date */ 00645 fno->ftime = LD_WORD(dir+PFFDIR_WrtTime); /* Time */ 00646 } 00647 *p = 0; 00648 } 00649 #endif /* _USE_DIR */ 00650 00651 00652 00653 /*-----------------------------------------------------------------------*/ 00654 /* Follow a file path */ 00655 /*-----------------------------------------------------------------------*/ 00656 00657 static 00658 FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ 00659 PFFDIR *dj, /* Directory object to return last directory and found object */ 00660 BYTE *dir, /* 32-byte working buffer */ 00661 const char *path /* Full-path string to find a file or directory */ 00662 ) 00663 { 00664 FRESULT res; 00665 00666 00667 while (*path == ' ') path++; /* Skip leading spaces */ 00668 if (*path == '/') path++; /* Strip heading separator */ 00669 dj->sclust = 0; /* Set start directory (always root dir) */ 00670 00671 if ((BYTE)*path <= ' ') { /* Null path means the root directory */ 00672 res = dir_rewind(dj); 00673 dir[0] = 0; 00674 00675 } else { /* Follow path */ 00676 for (;;) { 00677 res = create_name(dj, &path); /* Get a segment */ 00678 if (res != FR_OK) break; 00679 res = dir_find(dj, dir); /* Find it */ 00680 if (res != FR_OK) { /* Could not find the object */ 00681 if (res == FR_NO_FILE && !*(dj->fn+11)) 00682 res = FR_NO_PATH; 00683 break; 00684 } 00685 if (*(dj->fn+11)) break; /* Last segment match. Function completed. */ 00686 if (!(dir[PFFDIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ 00687 res = FR_NO_PATH; break; 00688 } 00689 dj->sclust = LD_CLUST(dir); 00690 } 00691 } 00692 00693 return res; 00694 } 00695 00696 00697 00698 00699 /*-----------------------------------------------------------------------*/ 00700 /* Check a sector if it is an FAT boot record */ 00701 /*-----------------------------------------------------------------------*/ 00702 00703 static 00704 BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */ 00705 BYTE *buf, /* Working buffer */ 00706 DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ 00707 ) 00708 { 00709 if (disk_readp(buf, sect, 510, 2)) /* Read the boot sector */ 00710 return 3; 00711 if (LD_WORD(buf) != 0xAA55) /* Check record signature */ 00712 return 2; 00713 00714 if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */ 00715 return 0; 00716 if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146) /* Check FAT32 */ 00717 return 0; 00718 return 1; 00719 } 00720 00721 00722 00723 00724 /*-------------------------------------------------------------------------- 00725 00726 Public Functions 00727 00728 --------------------------------------------------------------------------*/ 00729 00730 00731 00732 /*-----------------------------------------------------------------------*/ 00733 /* Mount/Unmount a Locical Drive */ 00734 /*-----------------------------------------------------------------------*/ 00735 00736 FRESULT pf_mount ( 00737 FATFS *fs /* Pointer to new file system object (NULL: Unmount) */ 00738 ) 00739 { 00740 BYTE fmt, buf[36]; 00741 DWORD bsect, fsize, tsect, mclst; 00742 00743 00744 FatFs = 0; 00745 if (!fs) return FR_OK; /* Unregister fs object */ 00746 00747 if (disk_initialize() & STA_NOINIT) /* Check if the drive is ready or not */ 00748 return FR_NOT_READY; 00749 00750 /* Search FAT partition on the drive */ 00751 bsect = 0; 00752 fmt = check_fs(buf, bsect); /* Check sector 0 as an SFD format */ 00753 if (fmt == 1) { /* Not an FAT boot record, it may be FDISK format */ 00754 /* Check a partition listed in top of the partition table */ 00755 if (disk_readp(buf, bsect, MBR_Table, 16)) { /* 1st partition entry */ 00756 fmt = 3; 00757 } else { 00758 if (buf[4]) { /* Is the partition existing? */ 00759 bsect = LD_DWORD(&buf[8]); /* Partition offset in LBA */ 00760 fmt = check_fs(buf, bsect); /* Check the partition */ 00761 } 00762 } 00763 } 00764 if (fmt == 3) return FR_DISK_ERR; 00765 if (fmt) return FR_NO_FILESYSTEM; /* No valid FAT patition is found */ 00766 00767 /* Initialize the file system object */ 00768 if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR; 00769 00770 fsize = LD_WORD(buf+BPB_FATSz16-13); /* Number of sectors per FAT */ 00771 if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13); 00772 00773 fsize *= buf[BPB_NumFATs-13]; /* Number of sectors in FAT area */ 00774 fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */ 00775 fs->csize = buf[BPB_SecPerClus-13]; /* Number of sectors per cluster */ 00776 fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13); /* Nmuber of root directory entries */ 00777 tsect = LD_WORD(buf+BPB_TotSec16-13); /* Number of sectors on the file system */ 00778 if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13); 00779 mclst = (tsect /* Last cluster# + 1 */ 00780 - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16 00781 ) / fs->csize + 2; 00782 fs->n_fatent = (CLUST)mclst; 00783 00784 fmt = FS_FAT16; /* Determine the FAT sub type */ 00785 if (mclst < 0xFF7) /* Number of clusters < 0xFF5 */ 00786 #if _FS_FAT12 00787 fmt = FS_FAT12; 00788 #else 00789 return FR_NO_FILESYSTEM; 00790 #endif 00791 if (mclst >= 0xFFF7) /* Number of clusters >= 0xFFF5 */ 00792 #if _FS_FAT32 00793 fmt = FS_FAT32; 00794 #else 00795 return FR_NO_FILESYSTEM; 00796 #endif 00797 00798 fs->fs_type = fmt; /* FAT sub-type */ 00799 if (_FS_FAT32 && fmt == FS_FAT32) 00800 fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13)); /* Root directory start cluster */ 00801 else 00802 fs->dirbase = fs->fatbase + fsize; /* Root directory start sector (lba) */ 00803 fs->database = fs->fatbase + fsize + fs->n_rootdir / 16; /* Data start sector (lba) */ 00804 00805 fs->flag = 0; 00806 FatFs = fs; 00807 00808 return FR_OK; 00809 } 00810 00811 00812 00813 00814 /*-----------------------------------------------------------------------*/ 00815 /* Open or Create a File */ 00816 /*-----------------------------------------------------------------------*/ 00817 00818 FRESULT pf_open ( 00819 const char *path /* Pointer to the file name */ 00820 ) 00821 { 00822 FRESULT res; 00823 PFFDIR dj; 00824 BYTE sp[12], dir[32]; 00825 FATFS *fs = FatFs; 00826 00827 00828 if (!fs) /* Check file system */ 00829 return FR_NOT_ENABLED; 00830 00831 fs->flag = 0; 00832 dj.fn = sp; 00833 res = follow_path(&dj, dir, path); /* Follow the file path */ 00834 if (res != FR_OK) return res; /* Follow failed */ 00835 if (!dir[0] || (dir[PFFDIR_Attr] & AM_DIR)) /* It is a directory */ 00836 return FR_NO_FILE; 00837 00838 fs->org_clust = LD_CLUST(dir); /* File start cluster */ 00839 fs->fsize = LD_DWORD(dir+PFFDIR_FileSize); /* File size */ 00840 fs->fptr = 0; /* File pointer */ 00841 fs->flag = FA_OPENED; 00842 00843 return FR_OK; 00844 } 00845 00846 00847 00848 00849 /*-----------------------------------------------------------------------*/ 00850 /* Read File */ 00851 /*-----------------------------------------------------------------------*/ 00852 #if _USE_READ 00853 00854 FRESULT pf_read ( 00855 void* buff, /* Pointer to the read buffer (NULL:Forward data to the stream)*/ 00856 WORD btr, /* Number of bytes to read */ 00857 WORD* br /* Pointer to number of bytes read */ 00858 ) 00859 { 00860 DRESULT dr; 00861 CLUST clst; 00862 DWORD sect, remain; 00863 WORD rcnt; 00864 BYTE cs, *rbuff = (BYTE *)buff; 00865 FATFS *fs = FatFs; 00866 00867 00868 *br = 0; 00869 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00870 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00871 return FR_NOT_OPENED; 00872 00873 remain = fs->fsize - fs->fptr; 00874 if (btr > remain) btr = (WORD)remain; /* Truncate btr by remaining bytes */ 00875 00876 while (btr) { /* Repeat until all data transferred */ 00877 if ((fs->fptr % 512) == 0) { /* On the sector boundary? */ 00878 cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ 00879 if (!cs) { /* On the cluster boundary? */ 00880 clst = (fs->fptr == 0) ? /* On the top of the file? */ 00881 fs->org_clust : get_fat(fs->curr_clust); 00882 if (clst <= 1) goto fr_abort; 00883 fs->curr_clust = clst; /* Update current cluster */ 00884 } 00885 sect = clust2sect(fs->curr_clust); /* Get current sector */ 00886 if (!sect) goto fr_abort; 00887 fs->dsect = sect + cs; 00888 } 00889 rcnt = (WORD)(512 - (fs->fptr % 512)); /* Get partial sector data from sector buffer */ 00890 if (rcnt > btr) rcnt = btr; 00891 dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt); 00892 if (dr) goto fr_abort; 00893 fs->fptr += rcnt; rbuff += rcnt; /* Update pointers and counters */ 00894 btr -= rcnt; *br += rcnt; 00895 } 00896 00897 return FR_OK; 00898 00899 fr_abort: 00900 fs->flag = 0; 00901 return FR_DISK_ERR; 00902 } 00903 #endif 00904 00905 00906 00907 /*-----------------------------------------------------------------------*/ 00908 /* Write File */ 00909 /*-----------------------------------------------------------------------*/ 00910 #if _USE_WRITE 00911 00912 FRESULT pf_write ( 00913 const void* buff, /* Pointer to the data to be written */ 00914 WORD btw, /* Number of bytes to write (0:Finalize the current write operation) */ 00915 WORD* bw /* Pointer to number of bytes written */ 00916 ) 00917 { 00918 CLUST clst; 00919 DWORD sect, remain; 00920 const BYTE *p =(const BYTE *) buff; 00921 BYTE cs; 00922 WORD wcnt; 00923 FATFS *fs = FatFs; 00924 00925 00926 *bw = 0; 00927 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00928 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00929 return FR_NOT_OPENED; 00930 00931 if (!btw) { /* Finalize request */ 00932 if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort; 00933 fs->flag &= ~FA__WIP; 00934 return FR_OK; 00935 } else { /* Write data request */ 00936 if (!(fs->flag & FA__WIP)) /* Round-down fptr to the sector boundary */ 00937 fs->fptr &= 0xFFFFFE00; 00938 } 00939 remain = fs->fsize - fs->fptr; 00940 if (btw > remain) btw = (WORD)remain; /* Truncate btw by remaining bytes */ 00941 00942 while (btw) { /* Repeat until all data transferred */ 00943 if (((WORD)fs->fptr % 512) == 0) { /* On the sector boundary? */ 00944 cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1)); /* Sector offset in the cluster */ 00945 if (!cs) { /* On the cluster boundary? */ 00946 clst = (fs->fptr == 0) ? /* On the top of the file? */ 00947 fs->org_clust : get_fat(fs->curr_clust); 00948 if (clst <= 1) goto fw_abort; 00949 fs->curr_clust = clst; /* Update current cluster */ 00950 } 00951 sect = clust2sect(fs->curr_clust); /* Get current sector */ 00952 if (!sect) goto fw_abort; 00953 fs->dsect = sect + cs; 00954 if (disk_writep(0, fs->dsect)) goto fw_abort; /* Initiate a sector write operation */ 00955 fs->flag |= FA__WIP; 00956 } 00957 wcnt = 512 - ((WORD)fs->fptr % 512); /* Number of bytes to write to the sector */ 00958 if (wcnt > btw) wcnt = btw; 00959 if (disk_writep(p, wcnt)) goto fw_abort; /* Send data to the sector */ 00960 fs->fptr += wcnt; p += wcnt; /* Update pointers and counters */ 00961 btw -= wcnt; *bw += wcnt; 00962 if (((WORD)fs->fptr % 512) == 0) { 00963 if (disk_writep(0, 0)) goto fw_abort; /* Finalize the currtent secter write operation */ 00964 fs->flag &= ~FA__WIP; 00965 } 00966 } 00967 00968 return FR_OK; 00969 00970 fw_abort: 00971 fs->flag = 0; 00972 return FR_DISK_ERR; 00973 } 00974 #endif 00975 00976 00977 00978 /*-----------------------------------------------------------------------*/ 00979 /* Seek File R/W Pointer */ 00980 /*-----------------------------------------------------------------------*/ 00981 #if _USE_LSEEK 00982 00983 FRESULT pf_lseek ( 00984 DWORD ofs /* File pointer from top of file */ 00985 ) 00986 { 00987 CLUST clst; 00988 DWORD bcs, sect, ifptr; 00989 FATFS *fs = FatFs; 00990 00991 00992 if (!fs) return FR_NOT_ENABLED; /* Check file system */ 00993 if (!(fs->flag & FA_OPENED)) /* Check if opened */ 00994 return FR_NOT_OPENED; 00995 00996 if (ofs > fs->fsize) ofs = fs->fsize; /* Clip offset with the file size */ 00997 ifptr = fs->fptr; 00998 fs->fptr = 0; 00999 if (ofs > 0) { 01000 bcs = (DWORD)fs->csize * 512; /* Cluster size (byte) */ 01001 if (ifptr > 0 && 01002 (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ 01003 fs->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ 01004 ofs -= fs->fptr; 01005 clst = fs->curr_clust; 01006 } else { /* When seek to back cluster, */ 01007 clst = fs->org_clust; /* start from the first cluster */ 01008 fs->curr_clust = clst; 01009 } 01010 while (ofs > bcs) { /* Cluster following loop */ 01011 clst = get_fat(clst); /* Follow cluster chain */ 01012 if (clst <= 1 || clst >= fs->n_fatent) goto fe_abort; 01013 fs->curr_clust = clst; 01014 fs->fptr += bcs; 01015 ofs -= bcs; 01016 } 01017 fs->fptr += ofs; 01018 sect = clust2sect(clst); /* Current sector */ 01019 if (!sect) goto fe_abort; 01020 fs->dsect = sect + (fs->fptr / 512 & (fs->csize - 1)); 01021 } 01022 01023 return FR_OK; 01024 01025 fe_abort: 01026 fs->flag = 0; 01027 return FR_DISK_ERR; 01028 } 01029 #endif 01030 01031 01032 01033 /*-----------------------------------------------------------------------*/ 01034 /* Create a Directroy Object */ 01035 /*-----------------------------------------------------------------------*/ 01036 #if _USE_DIR 01037 01038 FRESULT pf_opendir ( 01039 PFFDIR *dj, /* Pointer to directory object to create */ 01040 const char *path /* Pointer to the directory path */ 01041 ) 01042 { 01043 FRESULT res; 01044 BYTE sp[12], dir[32]; 01045 FATFS *fs = FatFs; 01046 01047 01048 if (!fs) { /* Check file system */ 01049 res = FR_NOT_ENABLED; 01050 } else { 01051 dj->fn = sp; 01052 res = follow_path(dj, dir, path); /* Follow the path to the directory */ 01053 if (res == FR_OK) { /* Follow completed */ 01054 if (dir[0]) { /* It is not the root dir */ 01055 if (dir[PFFDIR_Attr] & AM_DIR) /* The object is a directory */ 01056 dj->sclust = LD_CLUST(dir); 01057 else /* The object is not a directory */ 01058 res = FR_NO_PATH; 01059 } 01060 if (res == FR_OK) 01061 res = dir_rewind(dj); /* Rewind dir */ 01062 } 01063 if (res == FR_NO_FILE) res = FR_NO_PATH; 01064 } 01065 01066 return res; 01067 } 01068 01069 01070 01071 01072 /*-----------------------------------------------------------------------*/ 01073 /* Read Directory Entry in Sequense */ 01074 /*-----------------------------------------------------------------------*/ 01075 01076 FRESULT pf_readdir ( 01077 PFFDIR *dj, /* Pointer to the open directory object */ 01078 FILINFO *fno /* Pointer to file information to return */ 01079 ) 01080 { 01081 FRESULT res; 01082 BYTE sp[12], dir[32]; 01083 FATFS *fs = FatFs; 01084 01085 01086 if (!fs) { /* Check file system */ 01087 res = FR_NOT_ENABLED; 01088 } else { 01089 dj->fn = sp; 01090 if (!fno) { 01091 res = dir_rewind(dj); 01092 } else { 01093 res = dir_read(dj, dir); 01094 if (res == FR_NO_FILE) { 01095 dj->sect = 0; 01096 res = FR_OK; 01097 } 01098 if (res == FR_OK) { /* A valid entry is found */ 01099 get_fileinfo(dj, dir, fno); /* Get the object information */ 01100 res = dir_next(dj); /* Increment index for next */ 01101 if (res == FR_NO_FILE) { 01102 dj->sect = 0; 01103 res = FR_OK; 01104 } 01105 } 01106 } 01107 } 01108 01109 return res; 01110 } 01111 01112 #endif /* _USE_DIR */ 01113
Generated on Wed Jul 13 2022 23:03:59 by 1.7.2