OSDN Git Service

Added low level I/O module directory.
[kozos-expbrd/kozos_expbrd.git] / firm / sample / simple_mp3_player / os / lowio / pff.c
1 /*----------------------------------------------------------------------------/\r
2 /  Petit FatFs - FAT file system module  R0.02a                (C)ChaN, 2010\r
3 /-----------------------------------------------------------------------------/\r
4 / Petit FatFs module is an open source software to implement FAT file system to\r
5 / small embedded systems. This is a free software and is opened for education,\r
6 / research and commercial developments under license policy of following trems.\r
7 /\r
8 /  Copyright (C) 2010, ChaN, all right reserved.\r
9 /\r
10 / * The Petit FatFs module is a free software and there is NO WARRANTY.\r
11 / * No restriction on use. You can use, modify and redistribute it for\r
12 /   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.\r
13 / * Redistributions of source code must retain the above copyright notice.\r
14 /\r
15 /-----------------------------------------------------------------------------/\r
16 / Jun 15,'09  R0.01a  First release. (Branched from FatFs R0.07b.)\r
17 /\r
18 / Dec 14,'09  R0.02   Added multiple code page support.\r
19 /                     Added write funciton.\r
20 /                     Changed stream read mode interface.\r
21 / Dec 07,'10  R0.02a  Added some configuration options.\r
22 /                     Fixed fails to open objects with DBCS character.\r
23 /----------------------------------------------------------------------------*/\r
24 \r
25 #include "pff.h"                /* Petit FatFs configurations and declarations */\r
26 #include "diskio.h"             /* Declarations of low level disk I/O functions */\r
27 \r
28 \r
29 \r
30 /*--------------------------------------------------------------------------\r
31 \r
32    Module Private Definitions\r
33 \r
34 ---------------------------------------------------------------------------*/\r
35 \r
36 \r
37 #if _FS_FAT32\r
38 #define LD_CLUST(dir)   (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))\r
39 #else\r
40 #define LD_CLUST(dir)   LD_WORD(dir+DIR_FstClusLO)\r
41 #endif\r
42 \r
43 \r
44 /*--------------------------------------------------------*/\r
45 /* DBCS code ranges and SBCS extend char conversion table */\r
46 \r
47 #if _CODE_PAGE == 932   /* Japanese Shift-JIS */\r
48 #define _DF1S   0x81    /* DBC 1st byte range 1 start */\r
49 #define _DF1E   0x9F    /* DBC 1st byte range 1 end */\r
50 #define _DF2S   0xE0    /* DBC 1st byte range 2 start */\r
51 #define _DF2E   0xFC    /* DBC 1st byte range 2 end */\r
52 #define _DS1S   0x40    /* DBC 2nd byte range 1 start */\r
53 #define _DS1E   0x7E    /* DBC 2nd byte range 1 end */\r
54 #define _DS2S   0x80    /* DBC 2nd byte range 2 start */\r
55 #define _DS2E   0xFC    /* DBC 2nd byte range 2 end */\r
56 \r
57 #elif _CODE_PAGE == 936 /* Simplified Chinese GBK */\r
58 #define _DF1S   0x81\r
59 #define _DF1E   0xFE\r
60 #define _DS1S   0x40\r
61 #define _DS1E   0x7E\r
62 #define _DS2S   0x80\r
63 #define _DS2E   0xFE\r
64 \r
65 #elif _CODE_PAGE == 949 /* Korean */\r
66 #define _DF1S   0x81\r
67 #define _DF1E   0xFE\r
68 #define _DS1S   0x41\r
69 #define _DS1E   0x5A\r
70 #define _DS2S   0x61\r
71 #define _DS2E   0x7A\r
72 #define _DS3S   0x81\r
73 #define _DS3E   0xFE\r
74 \r
75 #elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */\r
76 #define _DF1S   0x81\r
77 #define _DF1E   0xFE\r
78 #define _DS1S   0x40\r
79 #define _DS1E   0x7E\r
80 #define _DS2S   0xA1\r
81 #define _DS2E   0xFE\r
82 \r
83 #elif _CODE_PAGE == 437 /* U.S. (OEM) */\r
84 #define _DF1S   0\r
85 #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, \\r
86                                 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, \\r
87                                 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, \\r
88                                 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}\r
89 \r
90 #elif _CODE_PAGE == 720 /* Arabic (OEM) */\r
91 #define _DF1S   0\r
92 #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, \\r
93                                 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, \\r
94                                 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, \\r
95                                 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}\r
96 \r
97 #elif _CODE_PAGE == 737 /* Greek (OEM) */\r
98 #define _DF1S   0\r
99 #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, \\r
100                                 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, \\r
101                                 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, \\r
102                                 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}\r
103 \r
104 #elif _CODE_PAGE == 775 /* Baltic (OEM) */\r
105 #define _DF1S   0\r
106 #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, \\r
107                                 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, \\r
108                                 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, \\r
109                                 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}\r
110 \r
111 #elif _CODE_PAGE == 850 /* Multilingual Latin 1 (OEM) */\r
112 #define _DF1S   0\r
113 #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, \\r
114                                 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, \\r
115                                 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, \\r
116                                 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}\r
117 \r
118 #elif _CODE_PAGE == 852 /* Latin 2 (OEM) */\r
119 #define _DF1S   0\r
120 #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, \\r
121                                 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, \\r
122                                 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, \\r
123                                 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}\r
124 \r
125 #elif _CODE_PAGE == 855 /* Cyrillic (OEM) */\r
126 #define _DF1S   0\r
127 #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, \\r
128                                 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, \\r
129                                 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, \\r
130                                 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}\r
131 \r
132 #elif _CODE_PAGE == 857 /* Turkish (OEM) */\r
133 #define _DF1S   0\r
134 #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, \\r
135                                 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, \\r
136                                 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, \\r
137                                 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}\r
138 \r
139 #elif _CODE_PAGE == 858 /* Multilingual Latin 1 + Euro (OEM) */\r
140 #define _DF1S   0\r
141 #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, \\r
142                                 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, \\r
143                                 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, \\r
144                                 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}\r
145 \r
146 #elif _CODE_PAGE == 862 /* Hebrew (OEM) */\r
147 #define _DF1S   0\r
148 #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, \\r
149                                 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, \\r
150                                 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, \\r
151                                 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}\r
152 \r
153 #elif _CODE_PAGE == 866 /* Russian (OEM) */\r
154 #define _DF1S   0\r
155 #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, \\r
156                                 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, \\r
157                                 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, \\r
158                                 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}\r
159 \r
160 #elif _CODE_PAGE == 874 /* Thai (OEM, Windows) */\r
161 #define _DF1S   0\r
162 #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, \\r
163                                 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, \\r
164                                 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, \\r
165                                 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}\r
166 \r
167 #elif _CODE_PAGE == 1250 /* Central Europe (Windows) */\r
168 #define _DF1S   0\r
169 #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, \\r
170                                 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, \\r
171                                 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, \\r
172                                 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}\r
173 \r
174 #elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */\r
175 #define _DF1S   0\r
176 #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, \\r
177                                 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, \\r
178                                 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, \\r
179                                 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}\r
180 \r
181 #elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */\r
182 #define _DF1S   0\r
183 #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, \\r
184                                 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, \\r
185                                 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, \\r
186                                 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}\r
187 \r
188 #elif _CODE_PAGE == 1253 /* Greek (Windows) */\r
189 #define _DF1S   0\r
190 #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, \\r
191                                 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, \\r
192                                 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, \\r
193                                 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}\r
194 \r
195 #elif _CODE_PAGE == 1254 /* Turkish (Windows) */\r
196 #define _DF1S   0\r
197 #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, \\r
198                                 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, \\r
199                                 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, \\r
200                                 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}\r
201 \r
202 #elif _CODE_PAGE == 1255 /* Hebrew (Windows) */\r
203 #define _DF1S   0\r
204 #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, \\r
205                                 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, \\r
206                                 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, \\r
207                                 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}\r
208 \r
209 #elif _CODE_PAGE == 1256 /* Arabic (Windows) */\r
210 #define _DF1S   0\r
211 #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, \\r
212                                 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, \\r
213                                 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, \\r
214                                 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}\r
215 \r
216 #elif _CODE_PAGE == 1257 /* Baltic (Windows) */\r
217 #define _DF1S   0\r
218 #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, \\r
219                                 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, \\r
220                                 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, \\r
221                                 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}\r
222 \r
223 #elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */\r
224 #define _DF1S   0\r
225 #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, \\r
226                                 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, \\r
227                                 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, \\r
228                                 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}\r
229 \r
230 #elif _CODE_PAGE == 1   /* ASCII (for only non-LFN cfg) */\r
231 #define _DF1S   0\r
232 \r
233 #else\r
234 #error Unknown code page\r
235 \r
236 #endif\r
237 \r
238 \r
239 \r
240 /* Character code support macros */\r
241 \r
242 #define IsUpper(c)      (((c)>='A')&&((c)<='Z'))\r
243 #define IsLower(c)      (((c)>='a')&&((c)<='z'))\r
244 \r
245 #if _DF1S               /* DBCS configuration */\r
246 \r
247 #ifdef _DF2S    /* Two 1st byte areas */\r
248 #define IsDBCS1(c)      (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))\r
249 #else                   /* One 1st byte area */\r
250 #define IsDBCS1(c)      ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)\r
251 #endif\r
252 \r
253 #ifdef _DS3S    /* Three 2nd byte areas */\r
254 #define IsDBCS2(c)      (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))\r
255 #else                   /* Two 2nd byte areas */\r
256 #define IsDBCS2(c)      (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))\r
257 #endif\r
258 \r
259 #else                   /* SBCS configuration */\r
260 \r
261 #define IsDBCS1(c)      0\r
262 #define IsDBCS2(c)      0\r
263 \r
264 #endif /* _DF1S */\r
265 \r
266 \r
267 /* FatFs refers the members in the FAT structures with byte offset instead\r
268 / of structure member because there are incompatibility of the packing option\r
269 / between various compilers. */\r
270 \r
271 #define BS_jmpBoot                      0\r
272 #define BS_OEMName                      3\r
273 #define BPB_BytsPerSec          11\r
274 #define BPB_SecPerClus          13\r
275 #define BPB_RsvdSecCnt          14\r
276 #define BPB_NumFATs                     16\r
277 #define BPB_RootEntCnt          17\r
278 #define BPB_TotSec16            19\r
279 #define BPB_Media                       21\r
280 #define BPB_FATSz16                     22\r
281 #define BPB_SecPerTrk           24\r
282 #define BPB_NumHeads            26\r
283 #define BPB_HiddSec                     28\r
284 #define BPB_TotSec32            32\r
285 #define BS_55AA                         510\r
286 \r
287 #define BS_DrvNum                       36\r
288 #define BS_BootSig                      38\r
289 #define BS_VolID                        39\r
290 #define BS_VolLab                       43\r
291 #define BS_FilSysType           54\r
292 \r
293 #define BPB_FATSz32                     36\r
294 #define BPB_ExtFlags            40\r
295 #define BPB_FSVer                       42\r
296 #define BPB_RootClus            44\r
297 #define BPB_FSInfo                      48\r
298 #define BPB_BkBootSec           50\r
299 #define BS_DrvNum32                     64\r
300 #define BS_BootSig32            66\r
301 #define BS_VolID32                      67\r
302 #define BS_VolLab32                     71\r
303 #define BS_FilSysType32         82\r
304 \r
305 #define MBR_Table                       446\r
306 \r
307 #define DIR_Name                        0\r
308 #define DIR_Attr                        11\r
309 #define DIR_NTres                       12\r
310 #define DIR_CrtTime                     14\r
311 #define DIR_CrtDate                     16\r
312 #define DIR_FstClusHI           20\r
313 #define DIR_WrtTime                     22\r
314 #define DIR_WrtDate                     24\r
315 #define DIR_FstClusLO           26\r
316 #define DIR_FileSize            28\r
317 \r
318 \r
319 \r
320 /*--------------------------------------------------------------------------\r
321 \r
322    Private Functions\r
323 \r
324 ---------------------------------------------------------------------------*/\r
325 \r
326 \r
327 static\r
328 FATFS *FatFs;   /* Pointer to the file system object (logical drive) */\r
329 \r
330 \r
331 /* Fill memory */\r
332 static\r
333 void mem_set (void* dst, int val, int cnt) {\r
334         char *d = (char*)dst;\r
335         while (cnt--) *d++ = (char)val;\r
336 }\r
337 \r
338 /* Compare memory to memory */\r
339 static\r
340 int mem_cmp (const void* dst, const void* src, int cnt) {\r
341         const char *d = (const char *)dst, *s = (const char *)src;\r
342         int r = 0;\r
343         while (cnt-- && (r = *d++ - *s++) == 0) ;\r
344         return r;\r
345 }\r
346 \r
347 \r
348 \r
349 /*-----------------------------------------------------------------------*/\r
350 /* FAT access - Read value of a FAT entry                                */\r
351 /*-----------------------------------------------------------------------*/\r
352 \r
353 static\r
354 CLUST get_fat ( /* 1:IO error, Else:Cluster status */\r
355         CLUST clst      /* Cluster# to get the link information */\r
356 )\r
357 {\r
358         WORD wc, bc, ofs;\r
359         BYTE buf[4];\r
360         FATFS *fs = FatFs;\r
361 \r
362 \r
363         if (clst < 2 || clst >= fs->n_fatent)   /* Range check */\r
364                 return 1;\r
365 \r
366         switch (fs->fs_type) {\r
367 #if _FS_FAT12\r
368         case FS_FAT12 :\r
369                 bc = (WORD)clst; bc += bc / 2;\r
370                 ofs = bc % 512; bc /= 512;\r
371                 if (ofs != 511) {\r
372                         if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;\r
373                 } else {\r
374                         if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;\r
375                         if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;\r
376                 }\r
377                 wc = LD_WORD(buf);\r
378                 return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);\r
379 #endif\r
380         case FS_FAT16 :\r
381                 if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break;\r
382                 return LD_WORD(buf);\r
383 #if _FS_FAT32\r
384         case FS_FAT32 :\r
385                 if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break;\r
386                 return LD_DWORD(buf) & 0x0FFFFFFF;\r
387 #endif\r
388         }\r
389 \r
390         return 1;       /* An error occured at the disk I/O layer */\r
391 }\r
392 \r
393 \r
394 \r
395 \r
396 /*-----------------------------------------------------------------------*/\r
397 /* Get sector# from cluster#                                             */\r
398 /*-----------------------------------------------------------------------*/\r
399 \r
400 static\r
401 DWORD clust2sect (      /* !=0: Sector number, 0: Failed - invalid cluster# */\r
402         CLUST clst              /* Cluster# to be converted */\r
403 )\r
404 {\r
405         FATFS *fs = FatFs;\r
406 \r
407 \r
408         clst -= 2;\r
409         if (clst >= (fs->n_fatent - 2)) return 0;               /* Invalid cluster# */\r
410         return (DWORD)clst * fs->csize + fs->database;\r
411 }\r
412 \r
413 \r
414 \r
415 \r
416 /*-----------------------------------------------------------------------*/\r
417 /* Directory handling - Rewind directory index                           */\r
418 /*-----------------------------------------------------------------------*/\r
419 \r
420 static\r
421 FRESULT dir_rewind (\r
422         DIR *dj                 /* Pointer to directory object */\r
423 )\r
424 {\r
425         CLUST clst;\r
426         FATFS *fs = FatFs;\r
427 \r
428 \r
429         dj->index = 0;\r
430         clst = dj->sclust;\r
431         if (clst == 1 || clst >= fs->n_fatent)  /* Check start cluster range */\r
432                 return FR_DISK_ERR;\r
433         if (_FS_FAT32 && !clst && fs->fs_type == FS_FAT32)      /* Replace cluster# 0 with root cluster# if in FAT32 */\r
434                 clst = (CLUST)fs->dirbase;\r
435         dj->clust = clst;                                               /* Current cluster */\r
436         dj->sect = clst ? clust2sect(clst) : fs->dirbase;       /* Current sector */\r
437 \r
438         return FR_OK;   /* Seek succeeded */\r
439 }\r
440 \r
441 \r
442 \r
443 \r
444 /*-----------------------------------------------------------------------*/\r
445 /* Directory handling - Move directory index next                        */\r
446 /*-----------------------------------------------------------------------*/\r
447 \r
448 static\r
449 FRESULT dir_next (      /* FR_OK:Succeeded, FR_NO_FILE:End of table */\r
450         DIR *dj                 /* Pointer to directory object */\r
451 )\r
452 {\r
453         CLUST clst;\r
454         WORD i;\r
455         FATFS *fs = FatFs;\r
456 \r
457 \r
458         i = dj->index + 1;\r
459         if (!i || !dj->sect)    /* Report EOT when index has reached 65535 */\r
460                 return FR_NO_FILE;\r
461 \r
462         if (!(i % 16)) {                /* Sector changed? */\r
463                 dj->sect++;                     /* Next sector */\r
464 \r
465                 if (dj->clust == 0) {   /* Static table */\r
466                         if (i >= fs->n_rootdir) /* Report EOT when end of table */\r
467                                 return FR_NO_FILE;\r
468                 }\r
469                 else {                                  /* Dynamic table */\r
470                         if (((i / 16) & (fs->csize-1)) == 0) {  /* Cluster changed? */\r
471                                 clst = get_fat(dj->clust);              /* Get next cluster */\r
472                                 if (clst <= 1) return FR_DISK_ERR;\r
473                                 if (clst >= fs->n_fatent)               /* When it reached end of dynamic table */\r
474                                         return FR_NO_FILE;                      /* Report EOT */\r
475                                 dj->clust = clst;                               /* Initialize data for new cluster */\r
476                                 dj->sect = clust2sect(clst);\r
477                         }\r
478                 }\r
479         }\r
480 \r
481         dj->index = i;\r
482 \r
483         return FR_OK;\r
484 }\r
485 \r
486 \r
487 \r
488 \r
489 /*-----------------------------------------------------------------------*/\r
490 /* Directory handling - Find an object in the directory                  */\r
491 /*-----------------------------------------------------------------------*/\r
492 \r
493 static\r
494 FRESULT dir_find (\r
495         DIR *dj,                /* Pointer to the directory object linked to the file name */\r
496         BYTE *dir               /* 32-byte working buffer */\r
497 )\r
498 {\r
499         FRESULT res;\r
500         BYTE c;\r
501 \r
502 \r
503         res = dir_rewind(dj);                   /* Rewind directory object */\r
504         if (res != FR_OK) return res;\r
505 \r
506         do {\r
507                 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)      /* Read an entry */\r
508                         ? FR_DISK_ERR : FR_OK;\r
509                 if (res != FR_OK) break;\r
510                 c = dir[DIR_Name];      /* First character */\r
511                 if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
512                 if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */\r
513                         break;\r
514                 res = dir_next(dj);                                     /* Next entry */\r
515         } while (res == FR_OK);\r
516 \r
517         return res;\r
518 }\r
519 \r
520 \r
521 \r
522 \r
523 /*-----------------------------------------------------------------------*/\r
524 /* Read an object from the directory                                     */\r
525 /*-----------------------------------------------------------------------*/\r
526 #if _USE_DIR\r
527 static\r
528 FRESULT dir_read (\r
529         DIR *dj,                /* Pointer to the directory object to store read object name */\r
530         BYTE *dir               /* 32-byte working buffer */\r
531 )\r
532 {\r
533         FRESULT res;\r
534         BYTE a, c;\r
535 \r
536 \r
537         res = FR_NO_FILE;\r
538         while (dj->sect) {\r
539                 res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)      /* Read an entry */\r
540                         ? FR_DISK_ERR : FR_OK;\r
541                 if (res != FR_OK) break;\r
542                 c = dir[DIR_Name];\r
543                 if (c == 0) { res = FR_NO_FILE; break; }        /* Reached to end of table */\r
544                 a = dir[DIR_Attr] & AM_MASK;\r
545                 if (c != 0xE5 && c != '.' && !(a & AM_VOL))     /* Is it a valid entry? */\r
546                         break;\r
547                 res = dir_next(dj);                     /* Next entry */\r
548                 if (res != FR_OK) break;\r
549         }\r
550 \r
551         if (res != FR_OK) dj->sect = 0;\r
552 \r
553         return res;\r
554 }\r
555 #endif\r
556 \r
557 \r
558 \r
559 /*-----------------------------------------------------------------------*/\r
560 /* Pick a segment and create the object name in directory form           */\r
561 /*-----------------------------------------------------------------------*/\r
562 \r
563 #ifdef _EXCVT\r
564         static const BYTE cvt[] = _EXCVT;\r
565 #endif\r
566 \r
567 static\r
568 FRESULT create_name (\r
569         DIR *dj,                        /* Pointer to the directory object */\r
570         const char **path       /* Pointer to pointer to the segment in the path string */\r
571 )\r
572 {\r
573         BYTE c, d, ni, si, i, *sfn;\r
574         const char *p;\r
575 \r
576         /* Create file name in directory form */\r
577         sfn = dj->fn;\r
578         mem_set(sfn, ' ', 11);\r
579         si = i = 0; ni = 8;\r
580         p = *path;\r
581         for (;;) {\r
582                 c = p[si++];\r
583                 if (c <= ' ' || c == '/') break;        /* Break on end of segment */\r
584                 if (c == '.' || i >= ni) {\r
585                         if (ni != 8 || c != '.') break;\r
586                         i = 8; ni = 11;\r
587                         continue;\r
588                 }\r
589 #ifdef _EXCVT\r
590                 if (c >= 0x80)                                  /* To upper extended char (SBCS) */\r
591                         c = cvt[c - 0x80];\r
592 #endif\r
593                 if (IsDBCS1(c) && i < ni - 1) { /* DBC 1st byte? */\r
594                         d = p[si++];                            /* Get 2nd byte */\r
595                         sfn[i++] = c;\r
596                         sfn[i++] = d;\r
597                 } else {                                                /* Single byte code */\r
598                         if (IsLower(c)) c -= 0x20;      /* toupper */\r
599                         sfn[i++] = c;\r
600                 }\r
601         }\r
602         *path = &p[si];                                         /* Rerurn pointer to the next segment */\r
603 \r
604         sfn[11] = (c <= ' ') ? 1 : 0;           /* Set last segment flag if end of path */\r
605 \r
606         return FR_OK;\r
607 }\r
608 \r
609 \r
610 \r
611 \r
612 /*-----------------------------------------------------------------------*/\r
613 /* Get file information from directory entry                             */\r
614 /*-----------------------------------------------------------------------*/\r
615 #if _USE_DIR\r
616 static\r
617 void get_fileinfo (             /* No return code */\r
618         DIR *dj,                        /* Pointer to the directory object */\r
619         BYTE *dir,                      /* 32-byte working buffer */\r
620         FILINFO *fno            /* Pointer to store the file information */\r
621 )\r
622 {\r
623         BYTE i, c;\r
624         char *p;\r
625 \r
626 \r
627         p = fno->fname;\r
628         if (dj->sect) {\r
629                 for (i = 0; i < 8; i++) {       /* Copy file name body */\r
630                         c = dir[i];\r
631                         if (c == ' ') break;\r
632                         if (c == 0x05) c = 0xE5;\r
633                         *p++ = c;\r
634                 }\r
635                 if (dir[8] != ' ') {            /* Copy file name extension */\r
636                         *p++ = '.';\r
637                         for (i = 8; i < 11; i++) {\r
638                                 c = dir[i];\r
639                                 if (c == ' ') break;\r
640                                 *p++ = c;\r
641                         }\r
642                 }\r
643                 fno->fattrib = dir[DIR_Attr];                           /* Attribute */\r
644                 fno->fsize = LD_DWORD(dir+DIR_FileSize);        /* Size */\r
645                 fno->fdate = LD_WORD(dir+DIR_WrtDate);          /* Date */\r
646                 fno->ftime = LD_WORD(dir+DIR_WrtTime);          /* Time */\r
647         }\r
648         *p = 0;\r
649 }\r
650 #endif /* _USE_DIR */\r
651 \r
652 \r
653 \r
654 /*-----------------------------------------------------------------------*/\r
655 /* Follow a file path                                                    */\r
656 /*-----------------------------------------------------------------------*/\r
657 \r
658 static\r
659 FRESULT follow_path (   /* FR_OK(0): successful, !=0: error code */\r
660         DIR *dj,                        /* Directory object to return last directory and found object */\r
661         BYTE *dir,                      /* 32-byte working buffer */\r
662         const char *path        /* Full-path string to find a file or directory */\r
663 )\r
664 {\r
665         FRESULT res;\r
666 \r
667 \r
668         while (*path == ' ') path++;            /* Skip leading spaces */\r
669         if (*path == '/') path++;                       /* Strip heading separator */\r
670         dj->sclust = 0;                                         /* Set start directory (always root dir) */\r
671 \r
672         if ((BYTE)*path <= ' ') {                       /* Null path means the root directory */\r
673                 res = dir_rewind(dj);\r
674                 dir[0] = 0;\r
675 \r
676         } else {                                                        /* Follow path */\r
677                 for (;;) {\r
678                         res = create_name(dj, &path);   /* Get a segment */\r
679                         if (res != FR_OK) break;\r
680                         res = dir_find(dj, dir);                /* Find it */\r
681                         if (res != FR_OK) {                             /* Could not find the object */\r
682                                 if (res == FR_NO_FILE && !*(dj->fn+11))\r
683                                         res = FR_NO_PATH;\r
684                                 break;\r
685                         }\r
686                         if (*(dj->fn+11)) break;                /* Last segment match. Function completed. */\r
687                         if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */\r
688                                 res = FR_NO_PATH; break;\r
689                         }\r
690                         dj->sclust = LD_CLUST(dir);\r
691                 }\r
692         }\r
693 \r
694         return res;\r
695 }\r
696 \r
697 \r
698 \r
699 \r
700 /*-----------------------------------------------------------------------*/\r
701 /* Check a sector if it is an FAT boot record                            */\r
702 /*-----------------------------------------------------------------------*/\r
703 \r
704 static\r
705 BYTE check_fs ( /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */\r
706         BYTE *buf,      /* Working buffer */\r
707         DWORD sect      /* Sector# (lba) to check if it is an FAT boot record or not */\r
708 )\r
709 {\r
710         if (disk_readp(buf, sect, 510, 2))              /* Read the boot sector */\r
711                 return 3;\r
712         if (LD_WORD(buf) != 0xAA55)                             /* Check record signature */\r
713                 return 2;\r
714 \r
715         if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146) /* Check FAT12/16 */\r
716                 return 0;\r
717         if (_FS_FAT32 && !disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146)  /* Check FAT32 */\r
718                 return 0;\r
719         return 1;\r
720 }\r
721 \r
722 \r
723 \r
724 \r
725 /*--------------------------------------------------------------------------\r
726 \r
727    Public Functions\r
728 \r
729 --------------------------------------------------------------------------*/\r
730 \r
731 \r
732 \r
733 /*-----------------------------------------------------------------------*/\r
734 /* Mount/Unmount a Locical Drive                                         */\r
735 /*-----------------------------------------------------------------------*/\r
736 \r
737 FRESULT pf_mount (\r
738         FATFS *fs               /* Pointer to new file system object (NULL: Unmount) */\r
739 )\r
740 {\r
741         BYTE fmt, buf[36];\r
742         DWORD bsect, fsize, tsect, mclst;\r
743 \r
744 \r
745         FatFs = 0;\r
746         if (!fs) return FR_OK;                          /* Unregister fs object */\r
747 \r
748         if (disk_initialize() & STA_NOINIT)     /* Check if the drive is ready or not */\r
749                 return FR_NOT_READY;\r
750 \r
751         /* Search FAT partition on the drive */\r
752         bsect = 0;\r
753         fmt = check_fs(buf, bsect);                     /* Check sector 0 as an SFD format */\r
754         if (fmt == 1) {                                         /* Not an FAT boot record, it may be FDISK format */\r
755                 /* Check a partition listed in top of the partition table */\r
756                 if (disk_readp(buf, bsect, MBR_Table, 16)) {    /* 1st partition entry */\r
757                         fmt = 3;\r
758                 } else {\r
759                         if (buf[4]) {                                   /* Is the partition existing? */\r
760                                 bsect = LD_DWORD(&buf[8]);      /* Partition offset in LBA */\r
761                                 fmt = check_fs(buf, bsect);     /* Check the partition */\r
762                         }\r
763                 }\r
764         }\r
765         if (fmt == 3) return FR_DISK_ERR;\r
766         if (fmt) return FR_NO_FILESYSTEM;       /* No valid FAT patition is found */\r
767 \r
768         /* Initialize the file system object */\r
769         if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR;\r
770 \r
771         fsize = LD_WORD(buf+BPB_FATSz16-13);                            /* Number of sectors per FAT */\r
772         if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);\r
773 \r
774         fsize *= buf[BPB_NumFATs-13];                                           /* Number of sectors in FAT area */\r
775         fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */\r
776         fs->csize = buf[BPB_SecPerClus-13];                                     /* Number of sectors per cluster */\r
777         fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13);         /* Nmuber of root directory entries */\r
778         tsect = LD_WORD(buf+BPB_TotSec16-13);                           /* Number of sectors on the file system */\r
779         if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);\r
780         mclst = (tsect                                          /* Last cluster# + 1 */\r
781                 - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16\r
782                 ) / fs->csize + 2;\r
783         fs->n_fatent = (CLUST)mclst;\r
784 \r
785         fmt = FS_FAT16;                                                 /* Determine the FAT sub type */\r
786         if (mclst < 0xFF7)                                              /* Number of clusters < 0xFF5 */\r
787 #if _FS_FAT12\r
788                 fmt = FS_FAT12;\r
789 #else\r
790                 return FR_NO_FILESYSTEM;\r
791 #endif\r
792         if (mclst >= 0xFFF7)                                    /* Number of clusters >= 0xFFF5 */\r
793 #if _FS_FAT32\r
794                 fmt = FS_FAT32;\r
795 #else\r
796                 return FR_NO_FILESYSTEM;\r
797 #endif\r
798 \r
799         fs->fs_type = fmt;              /* FAT sub-type */\r
800         if (_FS_FAT32 && fmt == FS_FAT32)\r
801                 fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13));  /* Root directory start cluster */\r
802         else\r
803                 fs->dirbase = fs->fatbase + fsize;                              /* Root directory start sector (lba) */\r
804         fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;        /* Data start sector (lba) */\r
805 \r
806         fs->flag = 0;\r
807         FatFs = fs;\r
808 \r
809         return FR_OK;\r
810 }\r
811 \r
812 \r
813 \r
814 \r
815 /*-----------------------------------------------------------------------*/\r
816 /* Open or Create a File                                                 */\r
817 /*-----------------------------------------------------------------------*/\r
818 \r
819 FRESULT pf_open (\r
820         const char *path        /* Pointer to the file name */\r
821 )\r
822 {\r
823         FRESULT res;\r
824         DIR dj;\r
825         BYTE sp[12], dir[32];\r
826         FATFS *fs = FatFs;\r
827 \r
828 \r
829         if (!fs)                                                /* Check file system */\r
830                 return FR_NOT_ENABLED;\r
831 \r
832         fs->flag = 0;\r
833         dj.fn = sp;\r
834         res = follow_path(&dj, dir, path);      /* Follow the file path */\r
835         if (res != FR_OK) return res;           /* Follow failed */\r
836         if (!dir[0] || (dir[DIR_Attr] & AM_DIR))        /* It is a directory */\r
837                 return FR_NO_FILE;\r
838 \r
839         fs->org_clust = LD_CLUST(dir);                  /* File start cluster */\r
840         fs->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */\r
841         fs->fptr = 0;                                           /* File pointer */\r
842         fs->flag = FA_OPENED;\r
843 \r
844         return FR_OK;\r
845 }\r
846 \r
847 \r
848 \r
849 \r
850 /*-----------------------------------------------------------------------*/\r
851 /* Read File                                                             */\r
852 /*-----------------------------------------------------------------------*/\r
853 #if _USE_READ\r
854 \r
855 FRESULT pf_read (\r
856         void* buff,             /* Pointer to the read buffer (NULL:Forward data to the stream)*/\r
857         WORD btr,               /* Number of bytes to read */\r
858         WORD* br                /* Pointer to number of bytes read */\r
859 )\r
860 {\r
861         DRESULT dr;\r
862         CLUST clst;\r
863         DWORD sect, remain;\r
864         WORD rcnt;\r
865         BYTE cs, *rbuff = buff;\r
866         FATFS *fs = FatFs;\r
867 \r
868 \r
869         *br = 0;\r
870         if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
871         if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
872                 return FR_NOT_OPENED;\r
873 \r
874         remain = fs->fsize - fs->fptr;\r
875         if (btr > remain) btr = (WORD)remain;                   /* Truncate btr by remaining bytes */\r
876 \r
877         while (btr)     {                                                                       /* Repeat until all data transferred */\r
878                 if ((fs->fptr % 512) == 0) {                            /* On the sector boundary? */\r
879                         cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */\r
880                         if (!cs) {                                                              /* On the cluster boundary? */\r
881                                 clst = (fs->fptr == 0) ?                        /* On the top of the file? */\r
882                                         fs->org_clust : get_fat(fs->curr_clust);\r
883                                 if (clst <= 1) goto fr_abort;\r
884                                 fs->curr_clust = clst;                          /* Update current cluster */\r
885                         }\r
886                         sect = clust2sect(fs->curr_clust);              /* Get current sector */\r
887                         if (!sect) goto fr_abort;\r
888                         fs->dsect = sect + cs;\r
889                 }\r
890                 rcnt = (WORD)(512 - (fs->fptr % 512));          /* Get partial sector data from sector buffer */\r
891                 if (rcnt > btr) rcnt = btr;\r
892                 dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt);\r
893                 if (dr) goto fr_abort;\r
894                 fs->fptr += rcnt; rbuff += rcnt;                        /* Update pointers and counters */\r
895                 btr -= rcnt; *br += rcnt;\r
896         }\r
897 \r
898         return FR_OK;\r
899 \r
900 fr_abort:\r
901         fs->flag = 0;\r
902         return FR_DISK_ERR;\r
903 }\r
904 #endif\r
905 \r
906 \r
907 \r
908 /*-----------------------------------------------------------------------*/\r
909 /* Write File                                                            */\r
910 /*-----------------------------------------------------------------------*/\r
911 #if _USE_WRITE\r
912 \r
913 FRESULT pf_write (\r
914         const void* buff,       /* Pointer to the data to be written */\r
915         WORD btw,                       /* Number of bytes to write (0:Finalize the current write operation) */\r
916         WORD* bw                        /* Pointer to number of bytes written */\r
917 )\r
918 {\r
919         CLUST clst;\r
920         DWORD sect, remain;\r
921         const BYTE *p = buff;\r
922         BYTE cs;\r
923         WORD wcnt;\r
924         FATFS *fs = FatFs;\r
925 \r
926 \r
927         *bw = 0;\r
928         if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
929         if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
930                 return FR_NOT_OPENED;\r
931 \r
932         if (!btw) {             /* Finalize request */\r
933                 if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort;\r
934                 fs->flag &= ~FA__WIP;\r
935                 return FR_OK;\r
936         } else {                /* Write data request */\r
937                 if (!(fs->flag & FA__WIP))              /* Round-down fptr to the sector boundary */\r
938                         fs->fptr &= 0xFFFFFE00;\r
939         }\r
940         remain = fs->fsize - fs->fptr;\r
941         if (btw > remain) btw = (WORD)remain;                   /* Truncate btw by remaining bytes */\r
942 \r
943         while (btw)     {                                                                       /* Repeat until all data transferred */\r
944                 if (((WORD)fs->fptr % 512) == 0) {                      /* On the sector boundary? */\r
945                         cs = (BYTE)(fs->fptr / 512 & (fs->csize - 1));  /* Sector offset in the cluster */\r
946                         if (!cs) {                                                              /* On the cluster boundary? */\r
947                                 clst = (fs->fptr == 0) ?                        /* On the top of the file? */\r
948                                         fs->org_clust : get_fat(fs->curr_clust);\r
949                                 if (clst <= 1) goto fw_abort;\r
950                                 fs->curr_clust = clst;                          /* Update current cluster */\r
951                         }\r
952                         sect = clust2sect(fs->curr_clust);              /* Get current sector */\r
953                         if (!sect) goto fw_abort;\r
954                         fs->dsect = sect + cs;\r
955                         if (disk_writep(0, fs->dsect)) goto fw_abort;   /* Initiate a sector write operation */\r
956                         fs->flag |= FA__WIP;\r
957                 }\r
958                 wcnt = 512 - ((WORD)fs->fptr % 512);            /* Number of bytes to write to the sector */\r
959                 if (wcnt > btw) wcnt = btw;\r
960                 if (disk_writep(p, wcnt)) goto fw_abort;        /* Send data to the sector */\r
961                 fs->fptr += wcnt; p += wcnt;                            /* Update pointers and counters */\r
962                 btw -= wcnt; *bw += wcnt;\r
963                 if (((WORD)fs->fptr % 512) == 0) {\r
964                         if (disk_writep(0, 0)) goto fw_abort;   /* Finalize the currtent secter write operation */\r
965                         fs->flag &= ~FA__WIP;\r
966                 }\r
967         }\r
968 \r
969         return FR_OK;\r
970 \r
971 fw_abort:\r
972         fs->flag = 0;\r
973         return FR_DISK_ERR;\r
974 }\r
975 #endif\r
976 \r
977 \r
978 \r
979 /*-----------------------------------------------------------------------*/\r
980 /* Seek File R/W Pointer                                                 */\r
981 /*-----------------------------------------------------------------------*/\r
982 #if _USE_LSEEK\r
983 \r
984 FRESULT pf_lseek (\r
985         DWORD ofs               /* File pointer from top of file */\r
986 )\r
987 {\r
988         CLUST clst;\r
989         DWORD bcs, sect, ifptr;\r
990         FATFS *fs = FatFs;\r
991 \r
992 \r
993         if (!fs) return FR_NOT_ENABLED;         /* Check file system */\r
994         if (!(fs->flag & FA_OPENED))            /* Check if opened */\r
995                         return FR_NOT_OPENED;\r
996 \r
997         if (ofs > fs->fsize) ofs = fs->fsize;   /* Clip offset with the file size */\r
998         ifptr = fs->fptr;\r
999         fs->fptr = 0;\r
1000         if (ofs > 0) {\r
1001                 bcs = (DWORD)fs->csize * 512;   /* Cluster size (byte) */\r
1002                 if (ifptr > 0 &&\r
1003                         (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */\r
1004                         fs->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */\r
1005                         ofs -= fs->fptr;\r
1006                         clst = fs->curr_clust;\r
1007                 } else {                                                        /* When seek to back cluster, */\r
1008                         clst = fs->org_clust;                   /* start from the first cluster */\r
1009                         fs->curr_clust = clst;\r
1010                 }\r
1011                 while (ofs > bcs) {                             /* Cluster following loop */\r
1012                         clst = get_fat(clst);           /* Follow cluster chain */\r
1013                         if (clst <= 1 || clst >= fs->n_fatent) goto fe_abort;\r
1014                         fs->curr_clust = clst;\r
1015                         fs->fptr += bcs;\r
1016                         ofs -= bcs;\r
1017                 }\r
1018                 fs->fptr += ofs;\r
1019                 sect = clust2sect(clst);                /* Current sector */\r
1020                 if (!sect) goto fe_abort;\r
1021                 fs->dsect = sect + (fs->fptr / 512 & (fs->csize - 1));\r
1022         }\r
1023 \r
1024         return FR_OK;\r
1025 \r
1026 fe_abort:\r
1027         fs->flag = 0;\r
1028         return FR_DISK_ERR;\r
1029 }\r
1030 #endif\r
1031 \r
1032 \r
1033 \r
1034 /*-----------------------------------------------------------------------*/\r
1035 /* Create a Directroy Object                                             */\r
1036 /*-----------------------------------------------------------------------*/\r
1037 #if _USE_DIR\r
1038 \r
1039 FRESULT pf_opendir (\r
1040         DIR *dj,                        /* Pointer to directory object to create */\r
1041         const char *path        /* Pointer to the directory path */\r
1042 )\r
1043 {\r
1044         FRESULT res;\r
1045         BYTE sp[12], dir[32];\r
1046         FATFS *fs = FatFs;\r
1047 \r
1048 \r
1049         if (!fs) {                              /* Check file system */\r
1050                 res = FR_NOT_ENABLED;\r
1051         } else {\r
1052                 dj->fn = sp;\r
1053                 res = follow_path(dj, dir, path);               /* Follow the path to the directory */\r
1054                 if (res == FR_OK) {                                             /* Follow completed */\r
1055                         if (dir[0]) {                                           /* It is not the root dir */\r
1056                                 if (dir[DIR_Attr] & AM_DIR)             /* The object is a directory */\r
1057                                         dj->sclust = LD_CLUST(dir);\r
1058                                 else                                                    /* The object is not a directory */\r
1059                                         res = FR_NO_PATH;\r
1060                         }\r
1061                         if (res == FR_OK)\r
1062                                 res = dir_rewind(dj);                   /* Rewind dir */\r
1063                 }\r
1064                 if (res == FR_NO_FILE) res = FR_NO_PATH;\r
1065         }\r
1066 \r
1067         return res;\r
1068 }\r
1069 \r
1070 \r
1071 \r
1072 \r
1073 /*-----------------------------------------------------------------------*/\r
1074 /* Read Directory Entry in Sequense                                      */\r
1075 /*-----------------------------------------------------------------------*/\r
1076 \r
1077 FRESULT pf_readdir (\r
1078         DIR *dj,                        /* Pointer to the open directory object */\r
1079         FILINFO *fno            /* Pointer to file information to return */\r
1080 )\r
1081 {\r
1082         FRESULT res;\r
1083         BYTE sp[12], dir[32];\r
1084         FATFS *fs = FatFs;\r
1085 \r
1086 \r
1087         if (!fs) {                              /* Check file system */\r
1088                 res = FR_NOT_ENABLED;\r
1089         } else {\r
1090                 dj->fn = sp;\r
1091                 if (!fno) {\r
1092                         res = dir_rewind(dj);\r
1093                 } else {\r
1094                         res = dir_read(dj, dir);\r
1095                         if (res == FR_NO_FILE) {\r
1096                                 dj->sect = 0;\r
1097                                 res = FR_OK;\r
1098                         }\r
1099                         if (res == FR_OK) {                             /* A valid entry is found */\r
1100                                 get_fileinfo(dj, dir, fno);     /* Get the object information */\r
1101                                 res = dir_next(dj);                     /* Increment index for next */\r
1102                                 if (res == FR_NO_FILE) {\r
1103                                         dj->sect = 0;\r
1104                                         res = FR_OK;\r
1105                                 }\r
1106                         }\r
1107                 }\r
1108         }\r
1109 \r
1110         return res;\r
1111 }\r
1112 \r
1113 #endif /* _USE_DIR */\r
1114 \r