Index: ChangeLog
===================================================================
--- ChangeLog	(.../sd-reader_release_20070301)	(Revision 106)
+++ ChangeLog	(.../sd-reader_release_20070603)	(Revision 106)
@@ -1,4 +1,9 @@
 
+2007-06-03 sd-reader
+	* Fix reading beyond cached block (by Benjamin Meier).
+	* Implement support for reading and writing file modification dates/times.
+	  (Thanks to Torsten Seeboth for testing.)
+
 2007-03-01 sd-reader
 	* Avoid LFN directory entries for the "." and ".." directory references.
 	  This prevented Windows from deleting directories.
Index: fat16_config.h
===================================================================
--- fat16_config.h	(.../sd-reader_release_20070301)	(Revision 106)
+++ fat16_config.h	(.../sd-reader_release_20070603)	(Revision 106)
@@ -30,6 +30,35 @@
 
 /**
  * \ingroup fat16_config
+ * Controls FAT16 date and time support.
+ * 
+ * Set to 1 to enable FAT16 date and time stamping support.
+ */
+#define FAT16_DATETIME_SUPPORT 0
+
+/**
+ * \ingroup fat16_config
+ * Determines the function used for retrieving current date and time.
+ *
+ * Define this to the function call which shall be used to retrieve
+ * current date and time.
+ *
+ * \note Used only when FAT16_DATETIME_SUPPORT is 1.
+ *
+ * \param[out] year Pointer to a \c uint16_t which receives the current year.
+ * \param[out] month Pointer to a \c uint8_t which receives the current month.
+ * \param[out] day Pointer to a \c uint8_t which receives the current day.
+ * \param[out] hour Pointer to a \c uint8_t which receives the current hour.
+ * \param[out] min Pointer to a \c uint8_t which receives the current minute.
+ * \param[out] sec Pointer to a \c uint8_t which receives the current sec.
+ */
+#define fat16_get_datetime(year, month, day, hour, min, sec) \
+    get_datetime(year, month, day, hour, min, sec)
+/* forward declaration for the above */
+void get_datetime(uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec);
+
+/**
+ * \ingroup fat16_config
  * Maximum number of filesystem handles.
  */
 #define FAT16_FS_COUNT 1
Index: sd_raw.c
===================================================================
--- sd_raw.c	(.../sd-reader_release_20070301)	(Revision 106)
+++ sd_raw.c	(.../sd-reader_release_20070603)	(Revision 106)
@@ -461,6 +461,7 @@
         {
             /* use cached data */
             memcpy(buffer, raw_block + block_offset, read_length);
+            buffer += read_length;
         }
 #endif
 
Index: fat16.c
===================================================================
--- fat16.c	(.../sd-reader_release_20070301)	(Revision 106)
+++ fat16.c	(.../sd-reader_release_20070603)	(Revision 106)
@@ -194,10 +194,13 @@
 static uint8_t fat16_clear_cluster(const struct fat16_fs_struct* fs, uint16_t cluster_num);
 static uint16_t fat16_clear_cluster_callback(uint8_t* buffer, uint32_t offset, void* p);
 static uint32_t fat16_find_offset_for_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_struct* parent, const struct fat16_dir_entry_struct* dir_entry);
-static uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_entry_struct* dir_entry);
+static uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry);
 
 static uint8_t fat16_get_fs_free_callback(uint8_t* buffer, uint32_t offset, void* p);
 
+static void fat16_set_file_modification_date(struct fat16_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day);
+static void fat16_set_file_modification_time(struct fat16_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec);
+
 /**
  * \ingroup fat16_fs
  * Opens a FAT16 filesystem.
@@ -630,6 +633,13 @@
                                ((uint32_t) raw_entry[30] << 16) |
                                ((uint32_t) raw_entry[31] << 24);
 
+#if FAT16_DATETIME_SUPPORT
+        dir_entry->modification_time = ((uint16_t) raw_entry[22]) |
+                                       ((uint16_t) raw_entry[23] << 8);
+        dir_entry->modification_date = ((uint16_t) raw_entry[24]) |
+                                       ((uint16_t) raw_entry[25] << 8);
+#endif
+
         return 2;
     }
 }
@@ -1654,12 +1664,27 @@
  * \param[in] dir_entry The directory entry to write.
  * \returns 0 on failure, 1 on success.
  */
-uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, const struct fat16_dir_entry_struct* dir_entry)
+uint8_t fat16_write_dir_entry(const struct fat16_fs_struct* fs, struct fat16_dir_entry_struct* dir_entry)
 {
 #if FAT16_WRITE_SUPPORT
     if(!fs || !dir_entry)
         return 0;
     
+#if FAT16_DATETIME_SUPPORT
+    {
+        uint16_t year;
+        uint8_t month;
+        uint8_t day;
+        uint8_t hour;
+        uint8_t min;
+        uint8_t sec;
+
+        fat16_get_datetime(&year, &month, &day, &hour, &min, &sec);
+        fat16_set_file_modification_date(dir_entry, year, month, day);
+        fat16_set_file_modification_time(dir_entry, hour, min, sec);
+    }
+#endif
+
     device_write_t device_write = fs->partition->device_write;
     uint32_t offset = dir_entry->entry_offset;
     const char* name = dir_entry->long_name;
@@ -1721,6 +1746,12 @@
     /* fill directory entry buffer */
     memset(&buffer[11], 0, sizeof(buffer) - 11);
     buffer[0x0b] = dir_entry->attributes;
+#if FAT16_DATETIME_SUPPORT
+    buffer[0x16] = (dir_entry->modification_time >> 0) & 0xff;
+    buffer[0x17] = (dir_entry->modification_time >> 8) & 0xff;
+    buffer[0x18] = (dir_entry->modification_date >> 0) & 0xff;
+    buffer[0x19] = (dir_entry->modification_date >> 8) & 0xff;
+#endif
     buffer[0x1a] = (dir_entry->cluster >> 0) & 0xff;
     buffer[0x1b] = (dir_entry->cluster >> 8) & 0xff;
     buffer[0x1c] = (dir_entry->file_size >> 0) & 0xff;
@@ -1840,6 +1871,7 @@
 
     struct fat16_fs_struct* fs = parent->fs;
 
+    /* prepare directory entry with values already known */
     memset(dir_entry, 0, sizeof(*dir_entry));
     strncpy(dir_entry->long_name, file, sizeof(dir_entry->long_name) - 1);
 
@@ -2029,6 +2061,96 @@
 #endif
 
 /**
+ * \ingroup fat16_file
+ * Returns the modification date of a file.
+ *
+ * \param[in] dir_entry The directory entry of which to return the modification date.
+ * \param[out] year The year the file was last modified.
+ * \param[out] month The month the file was last modified.
+ * \param[out] day The day the file was last modified.
+ */
+void fat16_get_file_modification_date(const struct fat16_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day)
+{
+#if FAT16_DATETIME_SUPPORT
+    if(!dir_entry)
+        return;
+
+    *year = 1980 + ((dir_entry->modification_date >> 9) & 0x7f);
+    *month = (dir_entry->modification_date >> 5) & 0x0f;
+    *day = (dir_entry->modification_date >> 0) & 0x1f;
+#endif
+}
+
+/**
+ * \ingroup fat16_file
+ * Returns the modification time of a file.
+ *
+ * \param[in] dir_entry The directory entry of which to return the modification time.
+ * \param[out] hour The hour the file was last modified.
+ * \param[out] min The min the file was last modified.
+ * \param[out] sec The sec the file was last modified.
+ */
+void fat16_get_file_modification_time(const struct fat16_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec)
+{
+#if FAT16_DATETIME_SUPPORT
+    if(!dir_entry)
+        return;
+
+    *hour = (dir_entry->modification_time >> 11) & 0x1f;
+    *min = (dir_entry->modification_time >> 5) & 0x3f;
+    *sec = ((dir_entry->modification_time >> 0) & 0x1f) * 2;
+#endif
+}
+
+/**
+ * \ingroup fat16_file
+ * Sets the modification time of a date.
+ *
+ * \param[in] dir_entry The directory entry for which to set the modification date.
+ * \param[in] year The year the file was last modified.
+ * \param[in] month The month the file was last modified.
+ * \param[in] day The day the file was last modified.
+ */
+void fat16_set_file_modification_date(struct fat16_dir_entry_struct* dir_entry, uint16_t year, uint8_t month, uint8_t day)
+{
+#if FAT16_WRITE_SUPPORT
+#if FAT16_DATETIME_SUPPORT
+    if(!dir_entry)
+        return;
+
+    dir_entry->modification_date =
+        ((year - 1980) << 9) |
+        ((uint16_t) month << 5) |
+        ((uint16_t) day << 0);
+#endif
+#endif
+}
+
+/**
+ * \ingroup fat16_file
+ * Sets the modification time of a file.
+ *
+ * \param[in] dir_entry The directory entry for which to set the modification time.
+ * \param[in] hour The year the file was last modified.
+ * \param[in] min The month the file was last modified.
+ * \param[in] sec The day the file was last modified.
+ */
+void fat16_set_file_modification_time(struct fat16_dir_entry_struct* dir_entry, uint8_t hour, uint8_t min, uint8_t sec)
+{
+#if FAT16_WRITE_SUPPORT
+#if FAT16_DATETIME_SUPPORT
+    if(!dir_entry)
+        return;
+
+    dir_entry->modification_time =
+        ((uint16_t) hour << 11) |
+        ((uint16_t) min << 5) |
+        ((uint16_t) sec >> 1) ;
+#endif
+#endif
+}
+
+/**
  * \ingroup fat16_fs
  * Returns the amount of total storage capacity of the filesystem in bytes.
  *
Index: main.c
===================================================================
--- main.c	(.../sd-reader_release_20070301)	(Revision 106)
+++ main.c	(.../sd-reader_release_20070603)	(Revision 106)
@@ -583,3 +583,14 @@
     return 1;
 }
 
+void get_datetime(uint16_t* year, uint8_t* month, uint8_t* day, uint8_t* hour, uint8_t* min, uint8_t* sec)
+{
+    *year = 2007;
+    *month = 1;
+    *day = 1;
+    *hour = 0;
+    *min = 0;
+    *sec = 0;
+}
+
+
Index: fat16.h
===================================================================
--- fat16.h	(.../sd-reader_release_20070301)	(Revision 106)
+++ fat16.h	(.../sd-reader_release_20070603)	(Revision 106)
@@ -10,6 +10,8 @@
 #ifndef FAT16_H
 #define FAT16_H
 
+#include "fat16_config.h"
+
 #include <stdint.h>
 
 /**
@@ -68,6 +70,12 @@
     char long_name[32];
     /** The file's attributes. Mask of the FAT16_ATTRIB_* constants. */
     uint8_t attributes;
+#if FAT16_DATETIME_SUPPORT
+    /** Compressed representation of modification time. */
+    uint16_t modification_time;
+    /** Compressed representation of modification date. */
+    uint16_t modification_date;
+#endif
     /** The cluster in which the file's first byte resides. */
     uint16_t cluster;
     /** The file's size. */
@@ -96,6 +104,9 @@
 uint8_t fat16_create_dir(struct fat16_dir_struct* parent, const char* dir, struct fat16_dir_entry_struct* dir_entry);
 #define fat16_delete_dir fat16_delete_file
 
+void fat16_get_file_modification_date(const struct fat16_dir_entry_struct* dir_entry, uint16_t* year, uint8_t* month, uint8_t* day);
+void fat16_get_file_modification_time(const struct fat16_dir_entry_struct* dir_entry, uint8_t* hour, uint8_t* min, uint8_t* sec);
+
 uint8_t fat16_get_dir_entry_of_path(struct fat16_fs_struct* fs, const char* path, struct fat16_dir_entry_struct* dir_entry);
 
 uint32_t fat16_get_fs_size(const struct fat16_fs_struct* fs);
