This is Petit FAT File System Module for mbed NXP LPC1768. The ported library from http://elm-chan.org/fsw/ff/00index_p.html made by Mr. ChaN. The connection is same as SDCard library here http://mbed.org/projects/cookbook/wiki/SDCard . If you need change a pin, You can find the definition at libpff/connect.h :)

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
shintamainjp
Date:
Tue Jun 01 12:23:29 2010 +0000
Child:
1:a24950493dec
Commit message:

Changed in this revision

libpff/connect.h Show annotated file Show diff for this revision Revisions of this file
libpff/diskio.h Show annotated file Show diff for this revision Revisions of this file
libpff/integer.h Show annotated file Show diff for this revision Revisions of this file
libpff/mmc.c Show annotated file Show diff for this revision Revisions of this file
libpff/pff.c Show annotated file Show diff for this revision Revisions of this file
libpff/pff.h Show annotated file Show diff for this revision Revisions of this file
main.c Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpff/connect.h	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,10 @@
+#ifndef _CONNECT_H_
+
+#define CONNECT_MOSI    p5
+#define CONNECT_MISO    p6
+#define CONNECT_SCK     p7
+#define CONNECT_CS      p13
+#define SPI_FREQ        2000000
+
+#define _CONNECT_H_
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpff/diskio.h	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,38 @@
+/*-----------------------------------------------------------------------
+/  PFF - Low level disk interface modlue include file    (C)ChaN, 2009
+/-----------------------------------------------------------------------*/
+
+#ifndef _DISKIO
+
+#include "integer.h"
+
+/* Status of Disk Functions */
+typedef BYTE    DSTATUS;
+
+/* Results of Disk Functions */
+typedef enum {
+    RES_OK = 0,        /* 0: Function succeeded */
+    RES_ERROR,        /* 1: Disk error */
+    RES_NOTRDY,        /* 2: Not ready */
+    RES_PARERR        /* 3: Invalid parameter */
+} DRESULT;
+
+/*---------------------------------------*/
+/* Prototypes for disk control functions */
+
+DSTATUS disk_initialize (void);
+DRESULT disk_readp (BYTE*, DWORD, WORD, WORD);
+DRESULT disk_writep (const BYTE*, DWORD);
+
+#define STA_NOINIT        0x01    /* Drive not initialized */
+#define STA_NODISK        0x02    /* No medium in the drive */
+
+/* Card type flags (CardType) */
+#define CT_MMC                0x01    /* MMC ver 3 */
+#define CT_SD1                0x02    /* SD ver 1 */
+#define CT_SD2                0x04    /* SD ver 2 */
+#define CT_SDC                (CT_SD1|CT_SD2)    /* SD */
+#define CT_BLOCK            0x08    /* Block addressing */
+
+#define _DISKIO
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpff/integer.h	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,31 @@
+/*-------------------------------------------*/
+/* Integer type definitions for FatFs module */
+/*-------------------------------------------*/
+
+#ifndef _INTEGER
+
+/* These types must be 16-bit, 32-bit or larger integer */
+typedef int                INT;
+typedef unsigned int    UINT;
+
+/* These types must be 8-bit integer */
+typedef signed char        CHAR;
+typedef unsigned char    UCHAR;
+typedef unsigned char    BYTE;
+
+/* These types must be 16-bit integer */
+typedef short            SHORT;
+typedef unsigned short    USHORT;
+typedef unsigned short    WORD;
+typedef unsigned short    WCHAR;
+
+/* These types must be 32-bit integer */
+typedef long            LONG;
+typedef unsigned long    ULONG;
+typedef unsigned long    DWORD;
+
+/* Boolean type */
+typedef enum { FALSE = 0, TRUE } BOOL;
+
+#define _INTEGER
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpff/mmc.c	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,268 @@
+/*-----------------------------------------------------------------------*/
+/* PFF - Low level disk control module for ATtiny85     (C)ChaN, 2009    */
+/*-----------------------------------------------------------------------*/
+
+#define _WRITE_FUNC    1
+
+#include "diskio.h"
+#include "mbed.h"
+#include "connect.h"
+
+/* Definitions for MMC/SDC command */
+#define CMD0    (0x40+0)    /* GO_IDLE_STATE */
+#define CMD1    (0x40+1)    /* SEND_OP_COND (MMC) */
+#define    ACMD41    (0xC0+41)    /* SEND_OP_COND (SDC) */
+#define CMD8    (0x40+8)    /* SEND_IF_COND */
+#define CMD16    (0x40+16)    /* SET_BLOCKLEN */
+#define CMD17    (0x40+17)    /* READ_SINGLE_BLOCK */
+#define CMD24    (0x40+24)    /* WRITE_BLOCK */
+#define CMD55    (0x40+55)    /* APP_CMD */
+#define CMD58    (0x40+58)    /* READ_OCR */
+
+SPI device(CONNECT_MOSI,CONNECT_MISO,CONNECT_SCK);
+DigitalOut cs(CONNECT_CS);
+
+/* Port Controls (Platform dependent) */
+#define SELECT()    cs.write(0)        /* MMC CS = L */
+#define    DESELECT()    cs.write(1)        /* MMC CS = H */
+#define    MMC_SEL        !cs.read()    /* MMC CS status (true:selected) */
+
+void xmit_spi (BYTE c) {
+    device.write(c);    /* Send a byte */
+}
+
+BYTE rcv_spi (void) {
+    return device.write(0xff);
+}
+
+/*--------------------------------------------------------------------------
+
+   Module Private Functions
+
+---------------------------------------------------------------------------*/
+
+static
+BYTE CardType;
+
+
+/*-----------------------------------------------------------------------*/
+/* Deselect the card and release SPI bus                                 */
+/*-----------------------------------------------------------------------*/
+
+static
+void release_spi (void) {
+    DESELECT();
+    rcv_spi();
+}
+
+
+/*-----------------------------------------------------------------------*/
+/* Send a command packet to MMC                                          */
+/*-----------------------------------------------------------------------*/
+
+static
+BYTE send_cmd (
+    BYTE cmd,        /* Command byte */
+    DWORD arg        /* Argument */
+) {
+    BYTE n, res;
+
+
+    if (cmd & 0x80) {    /* ACMD<n> is the command sequense of CMD55-CMD<n> */
+        cmd &= 0x7F;
+        res = send_cmd(CMD55, 0);
+        if (res > 1) return res;
+    }
+
+    /* Select the card */
+    DESELECT();
+    rcv_spi();
+    SELECT();
+    rcv_spi();
+
+    /* Send a command packet */
+    xmit_spi(cmd);                        /* Start + Command index */
+    xmit_spi((BYTE)(arg >> 24));        /* Argument[31..24] */
+    xmit_spi((BYTE)(arg >> 16));        /* Argument[23..16] */
+    xmit_spi((BYTE)(arg >> 8));            /* Argument[15..8] */
+    xmit_spi((BYTE)arg);                /* Argument[7..0] */
+    n = 0x01;                            /* Dummy CRC + Stop */
+    if (cmd == CMD0) n = 0x95;            /* Valid CRC for CMD0(0) */
+    if (cmd == CMD8) n = 0x87;            /* Valid CRC for CMD8(0x1AA) */
+    xmit_spi(n);
+
+    /* Receive a command response */
+    n = 10;                                /* Wait for a valid response in timeout of 10 attempts */
+    do {
+        res = rcv_spi();
+    } while ((res & 0x80) && --n);
+
+    return res;            /* Return with the response value */
+}
+
+
+
+/*--------------------------------------------------------------------------
+
+   Public Functions
+
+---------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* Initialize Disk Drive                                                 */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_initialize (void) {
+    BYTE n, cmd, ty, ocr[4];
+    WORD tmr;
+
+    DESELECT();
+    device.format(8);
+    device.frequency(SPI_FREQ);
+
+#if _WRITE_FUNC
+    if (MMC_SEL) disk_writep(0, 0);        /* Finalize write process if it is in progress */
+#endif
+    for (n = 100; n; n--) rcv_spi();    /* Dummy clocks */
+
+    ty = 0;
+    if (send_cmd(CMD0, 0) == 1) {            /* Enter Idle state */
+        if (send_cmd(CMD8, 0x1AA) == 1) {    /* SDv2 */
+            for (n = 0; n < 4; n++) ocr[n] = rcv_spi();        /* Get trailing return value of R7 resp */
+            if (ocr[2] == 0x01 && ocr[3] == 0xAA) {                /* The card can work at vdd range of 2.7-3.6V */
+                for (tmr = 12000; tmr && send_cmd(ACMD41, 1UL << 30); tmr--) ;    /* Wait for leaving idle state (ACMD41 with HCS bit) */
+                if (tmr && send_cmd(CMD58, 0) == 0) {        /* Check CCS bit in the OCR */
+                    for (n = 0; n < 4; n++) ocr[n] = rcv_spi();
+                    ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;    /* SDv2 (HC or SC) */
+                }
+            }
+        } else {                            /* SDv1 or MMCv3 */
+            if (send_cmd(ACMD41, 0) <= 1)     {
+                ty = CT_SD1;
+                cmd = ACMD41;    /* SDv1 */
+            } else {
+                ty = CT_MMC;
+                cmd = CMD1;    /* MMCv3 */
+            }
+            for (tmr = 25000; tmr && send_cmd(cmd, 0); tmr--) ;    /* Wait for leaving idle state */
+            if (!tmr || send_cmd(CMD16, 512) != 0)            /* Set R/W block length to 512 */
+                ty = 0;
+        }
+    }
+    CardType = ty;
+    release_spi();
+
+    return ty ? 0 : STA_NOINIT;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read partial sector                                                   */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_readp (
+    BYTE *buff,        /* Pointer to the read buffer (NULL:Read bytes are forwarded to the stream) */
+    DWORD lba,        /* Sector number (LBA) */
+    WORD ofs,        /* Byte offset to read from (0..511) */
+    WORD cnt        /* Number of bytes to read (ofs + cnt mus be <= 512) */
+) {
+    DRESULT res;
+    BYTE rc;
+    WORD bc;
+
+
+    if (!(CardType & CT_BLOCK)) lba *= 512;        /* Convert to byte address if needed */
+
+    res = RES_ERROR;
+    if (send_cmd(CMD17, lba) == 0) {        /* READ_SINGLE_BLOCK */
+
+        bc = 30000;
+        do {                            /* Wait for data packet in timeout of 100ms */
+            rc = rcv_spi();
+        } while (rc == 0xFF && --bc);
+
+        if (rc == 0xFE) {                /* A data packet arrived */
+            bc = 514 - ofs - cnt;
+
+            /* Skip leading bytes */
+            if (ofs) {
+                do {
+                    rcv_spi();
+                } while (--ofs);
+            }
+
+            /* Receive a part of the sector */
+            if (buff) {    /* Store data to the memory */
+                do {
+                    *buff++ = rcv_spi();
+                } while (--cnt);
+            } else {    /* Forward data to the outgoing stream (depends on the project) */
+                do {
+                    rcv_spi();
+                } while (--cnt);
+            }
+
+            /* Skip trailing bytes and CRC */
+            do rcv_spi();
+            while (--bc);
+
+            res = RES_OK;
+        }
+    }
+
+    release_spi();
+
+    return res;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write partial sector                                                  */
+/*-----------------------------------------------------------------------*/
+#if _WRITE_FUNC
+
+DRESULT disk_writep (
+    const BYTE *buff,    /* Pointer to the bytes to be written (NULL:Initiate/Finalize sector write) */
+    DWORD sa            /* Number of bytes to send, Sector number (LBA) or zero */
+) {
+    DRESULT res;
+    WORD bc;
+    static WORD wc;
+
+
+    res = RES_ERROR;
+
+    if (buff) {        /* Send data bytes */
+        bc = (WORD)sa;
+        while (bc && wc) {        /* Send data bytes to the card */
+            xmit_spi(*buff++);
+            wc--;
+            bc--;
+        }
+        res = RES_OK;
+    } else {
+        if (sa) {    /* Initiate sector write process */
+            if (!(CardType & CT_BLOCK)) sa *= 512;    /* Convert to byte address if needed */
+            if (send_cmd(CMD24, sa) == 0) {            /* WRITE_SINGLE_BLOCK */
+                xmit_spi(0xFF);
+                xmit_spi(0xFE);        /* Data block header */
+                wc = 512;                            /* Set byte counter */
+                res = RES_OK;
+            }
+        } else {    /* Finalize sector write process */
+            bc = wc + 2;
+            while (bc--) xmit_spi(0);    /* Fill left bytes and CRC with zeros */
+            if ((rcv_spi() & 0x1F) == 0x05) {    /* Receive data resp and wait for end of write process in timeout of 300ms */
+                for (bc = 65000; rcv_spi() != 0xFF && bc; bc--) ;    /* Wait ready */
+                if (bc) res = RES_OK;
+            }
+            release_spi();
+        }
+    }
+
+    return res;
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpff/pff.c	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,840 @@
+/*----------------------------------------------------------------------------/
+/  Petit FatFs - FAT file system module  R0.02                 (C)ChaN, 2009
+/-----------------------------------------------------------------------------/
+/ Petit FatFs module is an open source software to implement FAT file system to
+/ small embedded systems. This is a free software and is opened for education,
+/ research and commercial developments under license policy of following trems.
+/
+/  Copyright (C) 2009, ChaN, all right reserved.
+/
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/-----------------------------------------------------------------------------/
+/ Jun 15,'09  R0.01a  First release. (Branched from FatFs R0.07b.)
+/
+/ Dec 14,'09  R0.02   Added multiple code page support.
+/                     Added write funciton.
+/                     Changed stream read mode interface.
+/----------------------------------------------------------------------------*/
+
+#include "pff.h"        /* Petit FatFs configurations and declarations */
+#include "diskio.h"        /* Declarations of low level disk I/O functions */
+
+
+/*--------------------------------------------------------------------------
+
+   Private Functions
+
+---------------------------------------------------------------------------*/
+
+static
+FATFS *FatFs;    /* Pointer to the file system object (logical drive) */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* String functions                                                      */
+/*-----------------------------------------------------------------------*/
+
+/* Fill memory */
+static
+void mem_set (void* dst, int val, int cnt) {
+    char *d = (char*)dst;
+    while (cnt--) *d++ = (char)val;
+}
+
+/* Compare memory to memory */
+static
+int mem_cmp (const void* dst, const void* src, int cnt) {
+    const char *d = (const char *)dst, *s = (const char *)src;
+    int r = 0;
+    while (cnt-- && (r = *d++ - *s++) == 0) ;
+    return r;
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* FAT access - Read value of a FAT entry                                */
+/*-----------------------------------------------------------------------*/
+
+static
+CLUST get_fat (    /* 1:IO error, Else:Cluster status */
+    CLUST clst    /* Cluster# to get the link information */
+) {
+    WORD wc, bc, ofs;
+    BYTE buf[4];
+    FATFS *fs = FatFs;
+
+
+    if (clst < 2 || clst >= fs->max_clust)    /* Range check */
+        return 1;
+
+    switch (fs->fs_type) {
+        case FS_FAT12 :
+            bc = (WORD)clst;
+            bc += bc / 2;
+            ofs = bc % 512;
+            bc /= 512;
+            if (ofs != 511) {
+                if (disk_readp(buf, fs->fatbase + bc, ofs, 2)) break;
+            } else {
+                if (disk_readp(buf, fs->fatbase + bc, 511, 1)) break;
+                if (disk_readp(buf+1, fs->fatbase + bc + 1, 0, 1)) break;
+            }
+            wc = LD_WORD(buf);
+            return (clst & 1) ? (wc >> 4) : (wc & 0xFFF);
+
+        case FS_FAT16 :
+            if (disk_readp(buf, fs->fatbase + clst / 256, (WORD)(((WORD)clst % 256) * 2), 2)) break;
+            return LD_WORD(buf);
+#if _FS_FAT32
+        case FS_FAT32 :
+            if (disk_readp(buf, fs->fatbase + clst / 128, (WORD)(((WORD)clst % 128) * 4), 4)) break;
+            return LD_DWORD(buf) & 0x0FFFFFFF;
+#endif
+    }
+
+    return 1;    /* An error occured at the disk I/O layer */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get sector# from cluster#                                             */
+/*-----------------------------------------------------------------------*/
+
+static
+DWORD clust2sect (    /* !=0: Sector number, 0: Failed - invalid cluster# */
+    CLUST clst        /* Cluster# to be converted */
+) {
+    FATFS *fs = FatFs;
+
+
+    clst -= 2;
+    if (clst >= (fs->max_clust - 2)) return 0;        /* Invalid cluster# */
+    return (DWORD)clst * fs->csize + fs->database;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Rewind directory index                           */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_rewind (
+    FATDIR *dj            /* Pointer to directory object */
+) {
+    CLUST clst;
+    FATFS *fs = FatFs;
+
+
+    dj->index = 0;
+    clst = dj->sclust;
+    if (clst == 1 || clst >= fs->max_clust)    /* Check start cluster range */
+        return FR_DISK_ERR;
+#if _FS_FAT32
+    if (!clst && fs->fs_type == FS_FAT32)    /* Replace cluster# 0 with root cluster# if in FAT32 */
+        clst = fs->dirbase;
+#endif
+    dj->clust = clst;                        /* Current cluster */
+    dj->sect = clst ? clust2sect(clst) : fs->dirbase;    /* Current sector */
+
+    return FR_OK;    /* Seek succeeded */
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Move directory index next                        */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_next (    /* FR_OK:Succeeded, FR_NO_FILE:End of table */
+    FATDIR *dj            /* Pointer to directory object */
+) {
+    CLUST clst;
+    WORD i;
+    FATFS *fs = FatFs;
+
+
+    i = dj->index + 1;
+    if (!i || !dj->sect)    /* Report EOT when index has reached 65535 */
+        return FR_NO_FILE;
+
+    if (!(i & (16-1))) {    /* Sector changed? */
+        dj->sect++;            /* Next sector */
+
+        if (dj->clust == 0) {    /* Static table */
+            if (i >= fs->n_rootdir)    /* Report EOT when end of table */
+                return FR_NO_FILE;
+        } else {                   /* Dynamic table */
+            if (((i / 16) & (fs->csize-1)) == 0) {    /* Cluster changed? */
+                clst = get_fat(dj->clust);        /* Get next cluster */
+                if (clst <= 1) return FR_DISK_ERR;
+                if (clst >= fs->max_clust)        /* When it reached end of dynamic table */
+                    return FR_NO_FILE;            /* Report EOT */
+                dj->clust = clst;                /* Initialize data for new cluster */
+                dj->sect = clust2sect(clst);
+            }
+        }
+    }
+
+    dj->index = i;
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Find an object in the directory                  */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT dir_find (
+    FATDIR *dj            /* Pointer to the directory object linked to the file name */
+) {
+    FRESULT res;
+    BYTE c, *dir;
+
+
+    res = dir_rewind(dj);            /* Rewind directory object */
+    if (res != FR_OK) return res;
+
+    dir = FatFs->buf;
+    do {
+        res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)    /* Read an entry */
+              ? FR_DISK_ERR : FR_OK;
+        if (res != FR_OK) break;
+        c = dir[DIR_Name];    /* First character */
+        if (c == 0) {
+            res = FR_NO_FILE;    /* Reached to end of table */
+            break;
+        }
+        if (!(dir[DIR_Attr] & AM_VOL) && !mem_cmp(dir, dj->fn, 11)) /* Is it a valid entry? */
+            break;
+        res = dir_next(dj);                            /* Next entry */
+    } while (res == FR_OK);
+
+    return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read an object from the directory                                     */
+/*-----------------------------------------------------------------------*/
+#if _USE_DIR
+static
+FRESULT dir_read (
+    FATDIR *dj            /* Pointer to the directory object to store read object name */
+) {
+    FRESULT res;
+    BYTE a, c, *dir;
+
+
+    res = FR_NO_FILE;
+    dir = FatFs->buf;
+    while (dj->sect) {
+        res = disk_readp(dir, dj->sect, (WORD)((dj->index % 16) * 32), 32)    /* Read an entry */
+              ? FR_DISK_ERR : FR_OK;
+        if (res != FR_OK) break;
+        c = dir[DIR_Name];
+        if (c == 0) {
+            res = FR_NO_FILE;    /* Reached to end of table */
+            break;
+        }
+        a = dir[DIR_Attr] & AM_MASK;
+        if (c != 0xE5 && c != '.' && !(a & AM_VOL))    /* Is it a valid entry? */
+            break;
+        res = dir_next(dj);                /* Next entry */
+        if (res != FR_OK) break;
+    }
+
+    if (res != FR_OK) dj->sect = 0;
+
+    return res;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Pick a segment and create the object name in directory form           */
+/*-----------------------------------------------------------------------*/
+
+#ifdef _EXCVT
+static const BYTE cvt[] = _EXCVT;
+#endif
+
+static
+FRESULT create_name (
+    FATDIR *dj,            /* Pointer to the directory object */
+    const char **path    /* Pointer to pointer to the segment in the path string */
+) {
+    BYTE c, d, ni, si, i, *sfn;
+    const char *p;
+
+    /* Create file name in directory form */
+    sfn = dj->fn;
+    mem_set(sfn, ' ', 11);
+    si = i = 0;
+    ni = 8;
+    p = *path;
+    for (;;) {
+        c = p[si++];
+        if (c <= ' ' || c == '/') break;    /* Break on end of segment */
+        if (c == '.' || i >= ni) {
+            if (ni != 8 || c != '.') break;
+            i = 8;
+            ni = 11;
+            continue;
+        }
+#ifdef _EXCVT
+        if (c >= 0x80)                    /* To upper extended char (SBCS) */
+            c = cvt[c - 0x80];
+#endif
+        if (IsDBCS1(c) && i >= ni - 1) {    /* DBC 1st byte? */
+            d = p[si++];                    /* Get 2nd byte */
+            sfn[i++] = c;
+            sfn[i++] = d;
+        } else {                        /* Single byte code */
+            if (IsLower(c)) c -= 0x20;    /* toupper */
+            sfn[i++] = c;
+        }
+    }
+    *path = &p[si];                        /* Rerurn pointer to the next segment */
+
+    sfn[11] = (c <= ' ') ? 1 : 0;        /* Set last segment flag if end of path */
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get file information from directory entry                             */
+/*-----------------------------------------------------------------------*/
+#if _USE_DIR
+static
+void get_fileinfo (        /* No return code */
+    FATDIR *dj,            /* Pointer to the directory object */
+    FILINFO *fno         /* Pointer to store the file information */
+) {
+    BYTE i, c, *dir;
+    char *p;
+
+
+    p = fno->fname;
+    if (dj->sect) {
+        dir = FatFs->buf;
+        for (i = 0; i < 8; i++) {    /* Copy file name body */
+            c = dir[i];
+            if (c == ' ') break;
+            if (c == 0x05) c = 0xE5;
+            *p++ = c;
+        }
+        if (dir[8] != ' ') {        /* Copy file name extension */
+            *p++ = '.';
+            for (i = 8; i < 11; i++) {
+                c = dir[i];
+                if (c == ' ') break;
+                *p++ = c;
+            }
+        }
+        fno->fattrib = dir[DIR_Attr];                /* Attribute */
+        fno->fsize = LD_DWORD(dir+DIR_FileSize);    /* Size */
+        fno->fdate = LD_WORD(dir+DIR_WrtDate);        /* Date */
+        fno->ftime = LD_WORD(dir+DIR_WrtTime);        /* Time */
+    }
+    *p = 0;
+}
+#endif /* _USE_DIR */
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Follow a file path                                                    */
+/*-----------------------------------------------------------------------*/
+
+static
+FRESULT follow_path (    /* FR_OK(0): successful, !=0: error code */
+    FATDIR *dj,            /* Directory object to return last directory and found object */
+    const char *path    /* Full-path string to find a file or directory */
+) {
+    FRESULT res;
+    BYTE *dir;
+
+
+    while (*path == ' ') path++;        /* Skip leading spaces */
+    if (*path == '/') path++;            /* Strip heading separator */
+    dj->sclust = 0;                        /* Set start directory (always root dir) */
+
+    if ((BYTE)*path <= ' ') {            /* Null path means the root directory */
+        res = dir_rewind(dj);
+        FatFs->buf[0] = 0;
+
+    } else {                            /* Follow path */
+        for (;;) {
+            res = create_name(dj, &path);    /* Get a segment */
+            if (res != FR_OK) break;
+            res = dir_find(dj);                /* Find it */
+            if (res != FR_OK) {                /* Could not find the object */
+                if (res == FR_NO_FILE && !*(dj->fn+11))
+                    res = FR_NO_PATH;
+                break;
+            }
+            if (*(dj->fn+11)) break;        /* Last segment match. Function completed. */
+            dir = FatFs->buf;                /* There is next segment. Follow the sub directory */
+            if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */
+                res = FR_NO_PATH;
+                break;
+            }
+            dj->sclust =
+#if _FS_FAT32
+                ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
+#endif
+                LD_WORD(dir+DIR_FstClusLO);
+        }
+    }
+
+    return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Check a sector if it is an FAT boot record                            */
+/*-----------------------------------------------------------------------*/
+
+static
+BYTE check_fs (    /* 0:The FAT boot record, 1:Valid boot record but not an FAT, 2:Not a boot record, 3:Error */
+    BYTE *buf,    /* Working buffer */
+    DWORD sect    /* Sector# (lba) to check if it is an FAT boot record or not */
+) {
+    if (disk_readp(buf, sect, 510, 2))        /* Read the boot sector */
+        return 3;
+    if (LD_WORD(buf) != 0xAA55)                /* Check record signature */
+        return 2;
+
+    if (!disk_readp(buf, sect, BS_FilSysType, 2) && LD_WORD(buf) == 0x4146)    /* Check FAT12/16 */
+        return 0;
+#if _FS_FAT32
+    if (!disk_readp(buf, sect, BS_FilSysType32, 2) && LD_WORD(buf) == 0x4146)    /* Check FAT32 */
+        return 0;
+#endif
+    return 1;
+}
+
+
+
+
+/*--------------------------------------------------------------------------
+
+   Public Functions
+
+--------------------------------------------------------------------------*/
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Mount/Unmount a Locical Drive                                         */
+/*-----------------------------------------------------------------------*/
+
+FRESULT pf_mount (
+    FATFS *fs        /* Pointer to new file system object (NULL: Unmount) */
+) {
+    BYTE fmt, buf[36];
+    DWORD bsect, fsize, tsect, mclst;
+
+
+    FatFs = 0;
+    if (!fs) return FR_OK;                /* Unregister fs object */
+
+    if (disk_initialize() & STA_NOINIT)    /* Check if the drive is ready or not */
+        return FR_NOT_READY;
+
+    /* Search FAT partition on the drive */
+    bsect = 0;
+    fmt = check_fs(buf, bsect);            /* Check sector 0 as an SFD format */
+    if (fmt == 1) {                        /* Not an FAT boot record, it may be FDISK format */
+        /* Check a partition listed in top of the partition table */
+        if (disk_readp(buf, bsect, MBR_Table, 16)) {    /* 1st partition entry */
+            fmt = 3;
+        } else {
+            if (buf[4]) {                    /* Is the partition existing? */
+                bsect = LD_DWORD(&buf[8]);    /* Partition offset in LBA */
+                fmt = check_fs(buf, bsect);    /* Check the partition */
+            }
+        }
+    }
+    if (fmt == 3) return FR_DISK_ERR;
+    if (fmt) return FR_NO_FILESYSTEM;    /* No valid FAT patition is found */
+
+    /* Initialize the file system object */
+    if (disk_readp(buf, bsect, 13, sizeof(buf))) return FR_DISK_ERR;
+
+    fsize = LD_WORD(buf+BPB_FATSz16-13);                /* Number of sectors per FAT */
+    if (!fsize) fsize = LD_DWORD(buf+BPB_FATSz32-13);
+
+    fsize *= buf[BPB_NumFATs-13];                        /* Number of sectors in FAT area */
+    fs->fatbase = bsect + LD_WORD(buf+BPB_RsvdSecCnt-13); /* FAT start sector (lba) */
+    fs->csize = buf[BPB_SecPerClus-13];                    /* Number of sectors per cluster */
+    fs->n_rootdir = LD_WORD(buf+BPB_RootEntCnt-13);        /* Nmuber of root directory entries */
+    tsect = LD_WORD(buf+BPB_TotSec16-13);                /* Number of sectors on the file system */
+    if (!tsect) tsect = LD_DWORD(buf+BPB_TotSec32-13);
+    mclst = (tsect                        /* Last cluster# + 1 */
+             - LD_WORD(buf+BPB_RsvdSecCnt-13) - fsize - fs->n_rootdir / 16
+            ) / fs->csize + 2;
+    fs->max_clust = (CLUST)mclst;
+
+    fmt = FS_FAT12;                            /* Determine the FAT sub type */
+    if (mclst >= 0xFF7) fmt = FS_FAT16;        /* Number of clusters >= 0xFF5 */
+    if (mclst >= 0xFFF7)                    /* Number of clusters >= 0xFFF5 */
+#if _FS_FAT32
+        fmt = FS_FAT32;
+#else
+        return FR_NO_FILESYSTEM;
+#endif
+
+    fs->fs_type = fmt;        /* FAT sub-type */
+#if _FS_FAT32
+    if (fmt == FS_FAT32)
+        fs->dirbase = LD_DWORD(buf+(BPB_RootClus-13));    /* Root directory start cluster */
+    else
+#endif
+        fs->dirbase = fs->fatbase + fsize;                /* Root directory start sector (lba) */
+    fs->database = fs->fatbase + fsize + fs->n_rootdir / 16;    /* Data start sector (lba) */
+
+    fs->flag = 0;
+    FatFs = fs;
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Open or Create a File                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT pf_open (
+    const char *path    /* Pointer to the file name */
+) {
+    FRESULT res;
+    FATDIR dj;
+    BYTE sp[12], dir[32];
+    FATFS *fs = FatFs;
+
+
+    if (!fs)                        /* Check file system */
+        return FR_NOT_ENABLED;
+
+    fs->flag = 0;
+    fs->buf = dir;
+    dj.fn = sp;
+    res = follow_path(&dj, path);    /* Follow the file path */
+    if (res != FR_OK) return res;    /* Follow failed */
+    if (!dir[0] || (dir[DIR_Attr] & AM_DIR))    /* It is a directory */
+        return FR_NO_FILE;
+
+    fs->org_clust =                        /* File start cluster */
+#if _FS_FAT32
+        ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
+#endif
+        LD_WORD(dir+DIR_FstClusLO);
+    fs->fsize = LD_DWORD(dir+DIR_FileSize);    /* File size */
+    fs->fptr = 0;                        /* File pointer */
+    fs->flag = FA_OPENED;
+
+    return FR_OK;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read File                                                             */
+/*-----------------------------------------------------------------------*/
+#if _USE_READ
+
+FRESULT pf_read (
+    void* buff,        /* Pointer to the read buffer (NULL:Forward data to the stream)*/
+    WORD btr,        /* Number of bytes to read */
+    WORD* br        /* Pointer to number of bytes read */
+) {
+    DRESULT dr;
+    CLUST clst;
+    DWORD sect, remain;
+    BYTE *rbuff = (BYTE *)buff;
+    WORD rcnt;
+    FATFS *fs = FatFs;
+
+
+    *br = 0;
+    if (!fs) return FR_NOT_ENABLED;        /* Check file system */
+    if (!(fs->flag & FA_OPENED))        /* Check if opened */
+        return FR_NOT_OPENED;
+
+    remain = fs->fsize - fs->fptr;
+    if (btr > remain) btr = (WORD)remain;            /* Truncate btr by remaining bytes */
+
+    while (btr)    {                                    /* Repeat until all data transferred */
+        if ((fs->fptr % 512) == 0) {                /* On the sector boundary? */
+            if ((fs->fptr / 512 % fs->csize) == 0) {    /* On the cluster boundary? */
+                clst = (fs->fptr == 0) ?            /* On the top of the file? */
+                       fs->org_clust : get_fat(fs->curr_clust);
+                if (clst <= 1) goto fr_abort;
+                fs->curr_clust = clst;                /* Update current cluster */
+                fs->csect = 0;                        /* Reset sector offset in the cluster */
+            }
+            sect = clust2sect(fs->curr_clust);        /* Get current sector */
+            if (!sect) goto fr_abort;
+            fs->dsect = sect + fs->csect++;
+        }
+        rcnt = 512 - ((WORD)fs->fptr % 512);        /* Get partial sector data from sector buffer */
+        if (rcnt > btr) rcnt = btr;
+        dr = disk_readp(!buff ? 0 : rbuff, fs->dsect, (WORD)(fs->fptr % 512), rcnt);
+        if (dr) goto fr_abort;
+        fs->fptr += rcnt;
+        rbuff += rcnt;            /* Update pointers and counters */
+        btr -= rcnt;
+        *br += rcnt;
+    }
+
+    return FR_OK;
+
+fr_abort:
+    fs->flag = 0;
+    return FR_DISK_ERR;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write File                                                            */
+/*-----------------------------------------------------------------------*/
+#if _USE_WRITE
+
+FRESULT pf_write (
+    const void* buff,    /* Pointer to the data to be written */
+    WORD btw,            /* Number of bytes to write (0:Finalize the current write operation) */
+    WORD* bw            /* Pointer to number of bytes written */
+) {
+    CLUST clst;
+    DWORD sect, remain;
+    const BYTE *p = (const BYTE *)buff;
+    WORD wcnt;
+    FATFS *fs = FatFs;
+
+
+    *bw = 0;
+    if (!fs) return FR_NOT_ENABLED;        /* Check file system */
+    if (!(fs->flag & FA_OPENED))        /* Check if opened */
+        return FR_NOT_OPENED;
+
+    if (!btw) {        /* Finalize request */
+        if ((fs->flag & FA__WIP) && disk_writep(0, 0)) goto fw_abort;
+        fs->flag &= ~FA__WIP;
+        return FR_OK;
+    } else {        /* Write data request */
+        if (!(fs->flag & FA__WIP))        /* Round down fptr to the sector boundary */
+            fs->fptr &= 0xFFFFFE00;
+    }
+    remain = fs->fsize - fs->fptr;
+    if (btw > remain) btw = (WORD)remain;            /* Truncate btw by remaining bytes */
+
+    while (btw)    {                                    /* Repeat until all data transferred */
+        if (((WORD)fs->fptr % 512) == 0) {                /* On the sector boundary? */
+            if ((fs->fptr / 512 % fs->csize) == 0) {    /* On the cluster boundary? */
+                clst = (fs->fptr == 0) ?            /* On the top of the file? */
+                       fs->org_clust : get_fat(fs->curr_clust);
+                if (clst <= 1) goto fw_abort;
+                fs->curr_clust = clst;                /* Update current cluster */
+                fs->csect = 0;                        /* Reset sector offset in the cluster */
+            }
+            sect = clust2sect(fs->curr_clust);        /* Get current sector */
+            if (!sect) goto fw_abort;
+            fs->dsect = sect + fs->csect++;
+            if (disk_writep(0, fs->dsect)) goto fw_abort;    /* Initiate a sector write operation */
+            fs->flag |= FA__WIP;
+        }
+        wcnt = 512 - ((WORD)fs->fptr % 512);        /* Number of bytes to write to the sector */
+        if (wcnt > btw) wcnt = btw;
+        if (disk_writep(p, wcnt)) goto fw_abort;    /* Send data to the sector */
+        fs->fptr += wcnt;
+        p += wcnt;                /* Update pointers and counters */
+        btw -= wcnt;
+        *bw += wcnt;
+        if (((WORD)fs->fptr % 512) == 0) {
+            if (disk_writep(0, 0)) goto fw_abort;    /* Finalize the currtent secter write operation */
+            fs->flag &= ~FA__WIP;
+        }
+    }
+
+    return FR_OK;
+
+fw_abort:
+    fs->flag = 0;
+    return FR_DISK_ERR;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Seek File R/W Pointer                                                 */
+/*-----------------------------------------------------------------------*/
+#if _USE_LSEEK
+
+FRESULT pf_lseek (
+    DWORD ofs        /* File pointer from top of file */
+) {
+    CLUST clst;
+    DWORD bcs, sect, ifptr;
+    FATFS *fs = FatFs;
+
+
+    if (!fs) return FR_NOT_ENABLED;        /* Check file system */
+    if (!(fs->flag & FA_OPENED))        /* Check if opened */
+        return FR_NOT_OPENED;
+
+    if (ofs > fs->fsize) ofs = fs->fsize;    /* Clip offset with the file size */
+    ifptr = fs->fptr;
+    fs->fptr = 0;
+    if (ofs > 0) {
+        bcs = (DWORD)fs->csize * 512;    /* Cluster size (byte) */
+        if (ifptr > 0 &&
+                (ofs - 1) / bcs >= (ifptr - 1) / bcs) {    /* When seek to same or following cluster, */
+            fs->fptr = (ifptr - 1) & ~(bcs - 1);    /* start from the current cluster */
+            ofs -= fs->fptr;
+            clst = fs->curr_clust;
+        } else {                            /* When seek to back cluster, */
+            clst = fs->org_clust;            /* start from the first cluster */
+            fs->curr_clust = clst;
+        }
+        while (ofs > bcs) {                /* Cluster following loop */
+            clst = get_fat(clst);        /* Follow cluster chain */
+            if (clst <= 1 || clst >= fs->max_clust) goto fe_abort;
+            fs->curr_clust = clst;
+            fs->fptr += bcs;
+            ofs -= bcs;
+        }
+        fs->fptr += ofs;
+        sect = clust2sect(clst);        /* Current sector */
+        if (!sect) goto fe_abort;
+        fs->csect = (BYTE)(ofs / 512);    /* Sector offset in the cluster */
+        if (ofs % 512)
+            fs->dsect = sect + fs->csect++;
+    }
+
+    return FR_OK;
+
+fe_abort:
+    fs->flag = 0;
+    return FR_DISK_ERR;
+}
+#endif
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Create a Directroy Object                                             */
+/*-----------------------------------------------------------------------*/
+#if _USE_DIR
+
+FRESULT pf_opendir (
+    FATDIR *dj,            /* Pointer to directory object to create */
+    const char *path    /* Pointer to the directory path */
+) {
+    FRESULT res;
+    BYTE sp[12], dir[32];
+    FATFS *fs = FatFs;
+
+
+    if (!fs) {                /* Check file system */
+        res = FR_NOT_ENABLED;
+    } else {
+        fs->buf = dir;
+        dj->fn = sp;
+        res = follow_path(dj, path);            /* Follow the path to the directory */
+        if (res == FR_OK) {                        /* Follow completed */
+            if (dir[0]) {                        /* It is not the root dir */
+                if (dir[DIR_Attr] & AM_DIR) {    /* The object is a directory */
+                    dj->sclust =
+#if _FS_FAT32
+                        ((DWORD)LD_WORD(dir+DIR_FstClusHI) << 16) |
+#endif
+                        LD_WORD(dir+DIR_FstClusLO);
+                } else {                        /* The object is not a directory */
+                    res = FR_NO_PATH;
+                }
+            }
+            if (res == FR_OK)
+                res = dir_rewind(dj);            /* Rewind dir */
+        }
+        if (res == FR_NO_FILE) res = FR_NO_PATH;
+    }
+
+    return res;
+}
+
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Directory Entry in Sequense                                      */
+/*-----------------------------------------------------------------------*/
+
+FRESULT pf_readdir (
+    FATDIR *dj,            /* Pointer to the open directory object */
+    FILINFO *fno        /* Pointer to file information to return */
+) {
+    FRESULT res;
+    BYTE sp[12], dir[32];
+    FATFS *fs = FatFs;
+
+
+    if (!fs) {                /* Check file system */
+        res = FR_NOT_ENABLED;
+    } else {
+        fs->buf = dir;
+        dj->fn = sp;
+        if (!fno) {
+            res = dir_rewind(dj);
+        } else {
+            res = dir_read(dj);
+            if (res == FR_NO_FILE) {
+                dj->sect = 0;
+                res = FR_OK;
+            }
+            if (res == FR_OK) {                /* A valid entry is found */
+                get_fileinfo(dj, fno);        /* Get the object information */
+                res = dir_next(dj);            /* Increment index for next */
+                if (res == FR_NO_FILE) {
+                    dj->sect = 0;
+                    res = FR_OK;
+                }
+            }
+        }
+    }
+
+    return res;
+}
+
+#endif /* _USE_DIR */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libpff/pff.h	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,466 @@
+/*---------------------------------------------------------------------------/
+/  Petit FatFs - FAT file system module include file  R0.02    (C)ChaN, 2009
+/----------------------------------------------------------------------------/
+/ Petit FatFs module is an open source software to implement FAT file system to
+/ small embedded systems. This is a free software and is opened for education,
+/ research and commercial developments under license policy of following trems.
+/
+/  Copyright (C) 2009, ChaN, all right reserved.
+/
+/ * The Petit FatFs module is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/   personal, non-profit or commercial use UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/----------------------------------------------------------------------------*/
+
+#include "integer.h"
+
+/*---------------------------------------------------------------------------/
+/ Petit FatFs Configuration Options
+/
+/ CAUTION! Do not forget to make clean the project after any changes to
+/ the configuration options.
+/
+/----------------------------------------------------------------------------*/
+#ifndef _FATFS
+#define _FATFS
+
+#define    _USE_READ    1    /* pf_read(): 0:Remove ,1:Enable */
+
+#define    _USE_DIR    1    /* pf_opendir() and pf_readdir(): 0:Remove ,1:Enable */
+
+#define    _USE_LSEEK    1    /* pf_lseek(): 0:Remove ,1:Enable */
+
+#define    _USE_WRITE    1    /* pf_write(): 0:Remove ,1:Enable */
+
+#define _FS_FAT32    1    /* 0:Supports FAT12/16 only, 1:Enable FAT32 supprt */
+
+
+#define    _CODE_PAGE    1
+/* Defines which code page is used for path name. Supported code pages are:
+/  932, 936, 949, 950, 437, 720, 737, 775, 850, 852, 855, 857, 858, 862, 866,
+/  874, 1250, 1251, 1252, 1253, 1254, 1255, 1257, 1258 and 1 (ASCII only).
+/  SBCS configurations except for 1 requiers a case conversion table. This
+/  might occupy 128 bytes on the RAM on some platforms, e.g. avr-gcc. */
+
+
+#define _WORD_ACCESS    1
+/* The _WORD_ACCESS option defines which access method is used to the word
+/  data in the FAT structure.
+/
+/   0: Byte-by-byte access. Always compatible with all platforms.
+/   1: Word access. Do not choose this unless following condition is met.
+/
+/  When the byte order on the memory is big-endian or address miss-aligned
+/  word access results incorrect behavior, the _WORD_ACCESS must be set to 0.
+/  If it is not the case, the value can also be set to 1 to improve the
+/  performance and code efficiency. */
+
+
+/* End of configuration options. Do not change followings without care.     */
+/*--------------------------------------------------------------------------*/
+
+#if _FS_FAT32
+#define    CLUST    DWORD
+#else
+#define    CLUST    WORD
+#endif
+
+
+/* File system object structure */
+
+typedef struct _FATFS_ {
+    BYTE    fs_type;    /* FAT sub type */
+    BYTE    csize;        /* Number of sectors per cluster */
+    BYTE    flag;        /* File status flags */
+    BYTE    csect;        /* File sector address in the cluster */
+    WORD    n_rootdir;    /* Number of root directory entries (0 on FAT32) */
+    BYTE*    buf;        /* Pointer to the disk access buffer */
+    CLUST    max_clust;    /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */
+    DWORD    fatbase;    /* FAT start sector */
+    DWORD    dirbase;    /* Root directory start sector (Cluster# on FAT32) */
+    DWORD    database;    /* Data start sector */
+    DWORD    fptr;        /* File R/W pointer */
+    DWORD    fsize;        /* File size */
+    CLUST    org_clust;    /* File start cluster */
+    CLUST    curr_clust;    /* File current cluster */
+    DWORD    dsect;        /* File current data sector */
+} FATFS;
+
+
+
+/* Directory object structure */
+
+typedef struct _DIR_ {
+    WORD    index;        /* Current read/write index number */
+    BYTE*    fn;            /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
+    CLUST    sclust;        /* Table start cluster (0:Static table) */
+    CLUST    clust;        /* Current cluster */
+    DWORD    sect;        /* Current sector */
+} FATDIR;
+
+
+
+/* File status structure */
+
+typedef struct _FILINFO_ {
+    DWORD    fsize;        /* File size */
+    WORD    fdate;        /* Last modified date */
+    WORD    ftime;        /* Last modified time */
+    BYTE    fattrib;    /* Attribute */
+    char    fname[13];    /* File name */
+} FILINFO;
+
+
+
+/* File function return code (FRESULT) */
+
+typedef enum {
+    FR_OK = 0,            /* 0 */
+    FR_DISK_ERR,        /* 1 */
+    FR_NOT_READY,        /* 2 */
+    FR_NO_FILE,            /* 3 */
+    FR_NO_PATH,            /* 4 */
+    FR_NOT_OPENED,        /* 5 */
+    FR_NOT_ENABLED,        /* 6 */
+    FR_NO_FILESYSTEM    /* 7 */
+} FRESULT;
+
+
+
+/*--------------------------------------------------------------*/
+/* Petit FatFs module application interface                     */
+
+FRESULT pf_mount (FATFS*);                        /* Mount/Unmount a logical drive */
+FRESULT pf_open (const char*);                    /* Open a file */
+FRESULT pf_read (void*, WORD, WORD*);            /* Read data from the open file */
+FRESULT pf_write (const void*, WORD, WORD*);    /* Write data to the open file */
+FRESULT pf_lseek (DWORD);                        /* Move file pointer of the open file */
+FRESULT pf_opendir (FATDIR*, const char*);            /* Open a directory */
+FRESULT pf_readdir (FATDIR*, FILINFO*);            /* Read a directory item from the open directory */
+
+
+
+/*--------------------------------------------------------------*/
+/* Flags and offset address                                     */
+
+/* File status flag (FATFS.flag) */
+
+#define    FA_OPENED    0x01
+#define    FA_WPRT        0x02
+#define    FA__WIP        0x40
+
+
+/* FAT sub type (FATFS.fs_type) */
+
+#define FS_FAT12    1
+#define FS_FAT16    2
+#define FS_FAT32    3
+
+
+/* File attribute bits for directory entry */
+
+#define    AM_RDO    0x01    /* Read only */
+#define    AM_HID    0x02    /* Hidden */
+#define    AM_SYS    0x04    /* System */
+#define    AM_VOL    0x08    /* Volume label */
+#define AM_LFN    0x0F    /* LFN entry */
+#define AM_DIR    0x10    /* Directory */
+#define AM_ARC    0x20    /* Archive */
+#define AM_MASK    0x3F    /* Mask of defined bits */
+
+
+/* FatFs refers the members in the FAT structures with byte offset instead
+/ of structure member because there are incompatibility of the packing option
+/ between various compilers. */
+
+#define BS_jmpBoot            0
+#define BS_OEMName            3
+#define BPB_BytsPerSec        11
+#define BPB_SecPerClus        13
+#define BPB_RsvdSecCnt        14
+#define BPB_NumFATs            16
+#define BPB_RootEntCnt        17
+#define BPB_TotSec16        19
+#define BPB_Media            21
+#define BPB_FATSz16            22
+#define BPB_SecPerTrk        24
+#define BPB_NumHeads        26
+#define BPB_HiddSec            28
+#define BPB_TotSec32        32
+#define BS_55AA                510
+
+#define BS_DrvNum            36
+#define BS_BootSig            38
+#define BS_VolID            39
+#define BS_VolLab            43
+#define BS_FilSysType        54
+
+#define BPB_FATSz32            36
+#define BPB_ExtFlags        40
+#define BPB_FSVer            42
+#define BPB_RootClus        44
+#define BPB_FSInfo            48
+#define BPB_BkBootSec        50
+#define BS_DrvNum32            64
+#define BS_BootSig32        66
+#define BS_VolID32            67
+#define BS_VolLab32            71
+#define BS_FilSysType32        82
+
+#define MBR_Table            446
+
+#define    DIR_Name            0
+#define    DIR_Attr            11
+#define    DIR_NTres            12
+#define    DIR_CrtTime            14
+#define    DIR_CrtDate            16
+#define    DIR_FstClusHI        20
+#define    DIR_WrtTime            22
+#define    DIR_WrtDate            24
+#define    DIR_FstClusLO        26
+#define    DIR_FileSize        28
+
+
+
+/*--------------------------------*/
+/* Multi-byte word access macros  */
+
+#if _WORD_ACCESS == 1    /* Enable word access to the FAT structure */
+#define    LD_WORD(ptr)        (WORD)(*(WORD*)(BYTE*)(ptr))
+#define    LD_DWORD(ptr)        (DWORD)(*(DWORD*)(BYTE*)(ptr))
+#define    ST_WORD(ptr,val)    *(WORD*)(BYTE*)(ptr)=(WORD)(val)
+#define    ST_DWORD(ptr,val)    *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
+#else                    /* Use byte-by-byte access to the FAT structure */
+#define    LD_WORD(ptr)        (WORD)(((WORD)*(BYTE*)((ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
+#define    LD_DWORD(ptr)        (DWORD)(((DWORD)*(BYTE*)((ptr)+3)<<24)|((DWORD)*(BYTE*)((ptr)+2)<<16)|((WORD)*(BYTE*)((ptr)+1)<<8)|*(BYTE*)(ptr))
+#define    ST_WORD(ptr,val)    *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8)
+#define    ST_DWORD(ptr,val)    *(BYTE*)(ptr)=(BYTE)(val); *(BYTE*)((ptr)+1)=(BYTE)((WORD)(val)>>8); *(BYTE*)((ptr)+2)=(BYTE)((DWORD)(val)>>16); *(BYTE*)((ptr)+3)=(BYTE)((DWORD)(val)>>24)
+#endif
+
+
+/*--------------------------------------------------------*/
+/* DBCS code ranges and SBCS extend char conversion table */
+
+#if _CODE_PAGE == 932    /* Japanese Shift-JIS */
+#define _DF1S    0x81    /* DBC 1st byte range 1 start */
+#define _DF1E    0x9F    /* DBC 1st byte range 1 end */
+#define _DF2S    0xE0    /* DBC 1st byte range 2 start */
+#define _DF2E    0xFC    /* DBC 1st byte range 2 end */
+#define _DS1S    0x40    /* DBC 2nd byte range 1 start */
+#define _DS1E    0x7E    /* DBC 2nd byte range 1 end */
+#define _DS2S    0x80    /* DBC 2nd byte range 2 start */
+#define _DS2E    0xFC    /* DBC 2nd byte range 2 end */
+
+#elif _CODE_PAGE == 936    /* Simplified Chinese GBK */
+#define _DF1S    0x81
+#define _DF1E    0xFE
+#define _DS1S    0x40
+#define _DS1E    0x7E
+#define _DS2S    0x80
+#define _DS2E    0xFE
+
+#elif _CODE_PAGE == 949    /* Korean */
+#define _DF1S    0x81
+#define _DF1E    0xFE
+#define _DS1S    0x41
+#define _DS1E    0x5A
+#define _DS2S    0x61
+#define _DS2E    0x7A
+#define _DS3S    0x81
+#define _DS3E    0xFE
+
+#elif _CODE_PAGE == 950    /* Traditional Chinese Big5 */
+#define _DF1S    0x81
+#define _DF1E    0xFE
+#define _DS1S    0x40
+#define _DS1E    0x7E
+#define _DS2S    0xA1
+#define _DS2E    0xFE
+
+#elif _CODE_PAGE == 437    /* U.S. (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 720    /* Arabic (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 737    /* Greek (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 775    /* Baltic (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 850    /* Multilingual Latin 1 (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 852    /* Latin 2 (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 855    /* Cyrillic (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 857    /* Turkish (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 858    /* Multilingual Latin 1 + Euro (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 862    /* Hebrew (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 866    /* Russian (OEM) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 874    /* Thai (OEM, Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1250 /* Central Europe (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1251 /* Cyrillic (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1252 /* Latin 1 (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1253 /* Greek (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1254 /* Turkish (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1255 /* Hebrew (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1256 /* Arabic (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1257 /* Baltic (Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1258 /* Vietnam (OEM, Windows) */
+#define _DF1S    0
+#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, \
+                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, \
+                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, \
+                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}
+
+#elif _CODE_PAGE == 1    /* ASCII (for only non-LFN cfg) */
+#define _DF1S    0
+
+#else
+#error Unknown code page
+
+#endif
+
+
+
+/* Character code support macros */
+
+#define IsUpper(c)    (((c)>='A')&&((c)<='Z'))
+#define IsLower(c)    (((c)>='a')&&((c)<='z'))
+
+#if _DF1S        /* DBCS configuration */
+
+#ifdef _DF2S    /* Two 1st byte areas */
+#define IsDBCS1(c)    (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E))
+#else            /* One 1st byte area */
+#define IsDBCS1(c)    ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E)
+#endif
+
+#ifdef _DS3S    /* Three 2nd byte areas */
+#define IsDBCS2(c)    (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E))
+#else            /* Two 2nd byte areas */
+#define IsDBCS2(c)    (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E))
+#endif
+
+#else            /* SBCS configuration */
+
+#define IsDBCS1(c)    0
+#define IsDBCS2(c)    0
+
+#endif /* _DF1S */
+
+
+#endif /* _FATFS */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.c	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,260 @@
+/*---------------------------------------------------------------*/
+/* Petit FAT file system module test program R0.02 (C)ChaN, 2009 */
+/*---------------------------------------------------------------*/
+
+/*
+ * Ported by Shinichiro Nakamura (CuBeatSystems)
+ * http://shinta.main.jp/
+ * 2010/06/01
+ */
+
+#include <string.h>
+#include "mbed.h"
+#include "libpff/diskio.h"
+#include "libpff/pff.h"
+
+Serial pc(USBTX, USBRX);
+
+char Line[128];        /* Console input buffer */
+
+static
+void put_rc (FRESULT rc) {
+    const char *p;
+    static const char str[] =
+        "OK\0" "DISK_ERR\0" "NOT_READY\0" "NO_FILE\0" "NO_PATH\0"
+        "NOT_OPENED\0" "NOT_ENABLED\0" "NO_FILE_SYSTEM\0";
+    uint8_t i;
+
+    for (p = str, i = 0; i != (uint8_t)rc && p; i++) {
+        while (p++);
+    }
+    pc.printf("rc=%u FR_%S\n", (WORD)rc, p);
+}
+
+
+
+static
+void put_drc (BYTE res) {
+    pc.printf("rc=%d\n", res);
+}
+
+
+
+static
+void get_line (char *buff, BYTE len) {
+    BYTE c, i;
+
+    i = 0;
+    for (;;) {
+        c = pc.getc();
+        if (c == '\r') break;
+        if ((c == '\b') && i) {
+            i--;
+            pc.putc('\b');
+            pc.putc(' ');
+            pc.putc('\b');
+        }
+        if ((c >= ' ') && (i < len - 1)) {
+            buff[i++] = c;
+            pc.putc(c);
+        }
+    }
+    buff[i] = 0;
+    pc.putc('\n');
+}
+
+
+
+static
+void put_dump (const BYTE *buff, DWORD ofs, int cnt) {
+    BYTE n;
+
+    pc.printf("%08x", ofs);
+    pc.putc(' ');
+    for (n = 0; n < cnt; n++) {
+        pc.putc(' ');
+        pc.printf("%02x", buff[n]);
+    }
+    pc.printf("  ");
+    for (n = 0; n < cnt; n++) {
+        pc.putc(((buff[n] < 0x20)||(buff[n] >= 0x7F)) ? '.' : buff[n]);
+    }
+    pc.putc('\n');
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Main                                                                  */
+
+
+int main (void) {
+    char *ptr;
+    long p1, p2;
+    BYTE res;
+    WORD s1, s2, s3, ofs, cnt, w;
+    FATFS fs;            /* File system object */
+    FATDIR dir;            /* Directory object */
+    FILINFO fno;        /* File information */
+
+    pc.baud(19200);
+    pc.printf("\nPFF test monitor\n");
+
+    for (;;) {
+        pc.putc('>');
+        get_line(Line, sizeof(Line));
+        ptr = Line;
+
+        switch (*ptr++) {
+            case '?' :
+                pc.printf("di                - Initialize physical drive\n");
+                pc.printf("dd <sector> <ofs> - Dump partial secrtor 128 bytes\n");
+                pc.printf("fi                - Mount the volume\n");
+                pc.printf("fo <file>         - Open a file\n");
+                pc.printf("fd                - Read the file 128 bytes and dump it\n");
+                pc.printf("fw <len> <val>    - Write data to the file\n");
+                pc.printf("fp                - Write console input to the file\n");
+                pc.printf("fe <ofs>          - Move file pointer of the file\n");
+                pc.printf("fl [<path>]       - Directory listing\n");
+                break;
+            case 'd' :
+                switch (*ptr++) {
+                    case 'i' :    /* di - Initialize physical drive */
+                        res = disk_initialize();
+                        put_drc(res);
+                        break;
+                    case 'd' :    /* dd <sector> <ofs> - Dump partial secrtor 128 bytes */
+                        if (2 != sscanf(ptr, "%x %x", &p1, &p2)) {
+                            break;
+                        }
+                        s2 = p2;
+                        res = disk_readp((BYTE*)Line, p1, s2, 128);
+                        if (res) {
+                            put_drc(res);
+                            break;
+                        }
+                        s3 = s2 + 128;
+                        for (ptr = Line; s2 < s3; s2 += 16, ptr += 16, ofs += 16) {
+                            s1 = (s3 - s2 >= 16) ? 16 : s3 - s2;
+                            put_dump((BYTE*)ptr, s2, s1);
+                        }
+                        break;
+                }
+                break;
+            case 'f' :
+                switch (*ptr++) {
+
+                    case 'i' :    /* fi - Mount the volume */
+                        put_rc(pf_mount(&fs));
+                        break;
+
+                    case 'o' :    /* fo <file> - Open a file */
+                        while (*ptr == ' ') ptr++;
+                        put_rc(pf_open(ptr));
+                        break;
+#if _USE_READ
+                    case 'd' :    /* fd - Read the file 128 bytes and dump it */
+                        ofs = fs.fptr;
+                        res = pf_read(Line, sizeof(Line), &s1);
+                        if (res != FR_OK) {
+                            put_rc((FRESULT)res);
+                            break;
+                        }
+                        ptr = Line;
+                        while (s1) {
+                            s2 = (s1 >= 16) ? 16 : s1;
+                            s1 -= s2;
+                            put_dump((BYTE*)ptr, ofs, s2);
+                            ptr += 16;
+                            ofs += 16;
+                        }
+                        break;
+
+#endif
+#if _USE_WRITE
+                    case 'w' :    /* fw <len> <val> - Write data to the file */
+                        if (2 != sscanf(ptr, "%x %x", &p1, &p2)) {
+                            break;
+                        }
+                        for (s1 = 0; s1 < sizeof(Line); Line[s1++] = (BYTE)p2) ;
+                        p2 = 0;
+                        while (p1) {
+                            if ((UINT)p1 >= sizeof(Line)) {
+                                cnt = sizeof(Line);
+                                p1 -= sizeof(Line);
+                            } else {
+                                cnt = (WORD)p1;
+                                p1 = 0;
+                            }
+                            res = pf_write(Line, cnt, &w);    /* Write data to the file */
+                            p2 += w;
+                            if (res != FR_OK) {
+                                put_rc((FRESULT)res);
+                                break;
+                            }
+                            if (cnt != w) break;
+                        }
+                        res = pf_write(0, 0, &w);        /* Finalize the write process */
+                        put_rc((FRESULT)res);
+                        if (res == FR_OK)
+                            pc.printf("%lu bytes written.\n", p2);
+                        break;
+                    case 'p' :    /* fp - Write console input to the file */
+                        pc.printf("Type any line to write. A blank line finalize the write operation.\n");
+                        for (;;) {
+                            get_line(Line, sizeof(Line));
+                            if (!Line[0]) break;
+                            strcat(Line, "\r\n");
+                            res = pf_write(Line, strlen(Line), &w);    /* Write a line to the file */
+                            if (res) break;
+                        }
+                        res = pf_write(0, 0, &w);        /* Finalize the write process */
+                        put_rc((FRESULT)res);
+                        break;
+#endif
+#if _USE_LSEEK
+                    case 'e' :    /* fe <ofs> - Move file pointer of the file */
+                        if (1 != sscanf(ptr, "%x", &p1)) {
+                            break;
+                        }
+                        res = pf_lseek(p1);
+                        put_rc((FRESULT)res);
+                        if (res == FR_OK) {
+                            pc.printf("fptr = %lu(0x%lX)\n", fs.fptr, fs.fptr);
+                        }
+                        break;
+#endif
+#if _USE_DIR
+                    case 'l' :    /* fl [<path>] - Directory listing */
+                        while (*ptr == ' ') ptr++;
+                        res = pf_opendir(&dir, ptr);
+                        if (res) {
+                            put_rc((FRESULT)res);
+                            break;
+                        }
+                        s1 = 0;
+                        for (;;) {
+                            res = pf_readdir(&dir, &fno);
+                            if (res != FR_OK) {
+                                put_rc((FRESULT)res);
+                                break;
+                            }
+                            if (!fno.fname[0]) break;
+                            if (fno.fattrib & AM_DIR)
+                                pc.printf("   <DIR>   %s\n", fno.fname);
+                            else
+                                pc.printf("%9lu  %s\n", fno.fsize, fno.fname);
+                            s1++;
+                        }
+                        pc.printf("%u item(s)\n", s1);
+                        break;
+#endif
+                }
+                break;
+        }
+    }
+
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jun 01 12:23:29 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e6be4cd80aad