diff options
author | Jens Arnold <amiconn@rockbox.org> | 2009-08-16 17:18:45 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2009-08-16 17:18:45 +0000 |
commit | bf9facc49c0ef0a8fabdda3d1e765c2edd2e390f (patch) | |
tree | aa409d730f4c6c6def253f5ed5a5085e58c1e67c /firmware/drivers | |
parent | 042bbad6d67def88923cd7f583c19a767f9fff56 (diff) | |
download | rockbox-bf9facc49c0ef0a8fabdda3d1e765c2edd2e390f.tar.gz rockbox-bf9facc49c0ef0a8fabdda3d1e765c2edd2e390f.zip |
FAT timestamp handling improvements for non-RTC targets:
- When writing to a file that is older than the build, file date is set to the build date.
- Time is advanced so that the minutes are a multiple of 11, excluding '00', and seconds =
minutes. This is done as a hint that the time isn't 100% correct.
- Date increment uses actual month lengths (but without leap year handling)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22348 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/fat.c | 99 |
1 files changed, 54 insertions, 45 deletions
diff --git a/firmware/drivers/fat.c b/firmware/drivers/fat.c index e319669e97..578397cbe6 100644 --- a/firmware/drivers/fat.c +++ b/firmware/drivers/fat.c | |||
@@ -1001,70 +1001,79 @@ static void fat_time(unsigned short* date, | |||
1001 | #else | 1001 | #else |
1002 | /* non-RTC version returns an increment from the supplied time, or a | 1002 | /* non-RTC version returns an increment from the supplied time, or a |
1003 | * fixed standard time/date if no time given as input */ | 1003 | * fixed standard time/date if no time given as input */ |
1004 | |||
1005 | /* Macros to convert a 2-digit string to a decimal constant. | ||
1006 | (YEAR), MONTH and DAY are set by the date command, which outputs | ||
1007 | DAY as 00..31 and MONTH as 01..12. The leading zero would lead to | ||
1008 | misinterpretation as an octal constant. */ | ||
1009 | #define S100(x) 1 ## x | ||
1010 | #define C2DIG2DEC(x) (S100(x)-100) | ||
1011 | /* The actual build date, as FAT date constant */ | ||
1012 | #define BUILD_DATE_FAT (((YEAR - 1980) << 9) \ | ||
1013 | | (C2DIG2DEC(MONTH) << 5) \ | ||
1014 | | C2DIG2DEC(DAY)) | ||
1015 | |||
1016 | bool date_forced = false; | ||
1004 | bool next_day = false; | 1017 | bool next_day = false; |
1018 | unsigned time2 = 0; /* double time, for CRTTIME with 1s precision */ | ||
1005 | 1019 | ||
1020 | if (date && *date < BUILD_DATE_FAT) | ||
1021 | { | ||
1022 | *date = BUILD_DATE_FAT; | ||
1023 | date_forced = true; | ||
1024 | } | ||
1025 | |||
1006 | if (time) | 1026 | if (time) |
1007 | { | 1027 | { |
1008 | if (0 == *time) | 1028 | time2 = *time << 1; |
1029 | if (time2 == 0 || date_forced) | ||
1009 | { | 1030 | { |
1010 | /* set to 00:15:00 */ | 1031 | time2 = (11 < 6) | 11; /* set to 00:11:11 */ |
1011 | *time = (15 << 5); | ||
1012 | } | 1032 | } |
1013 | else | 1033 | else |
1014 | { | 1034 | { |
1015 | unsigned short mins = (*time >> 5) & 0x003F; | 1035 | unsigned mins = (time2 >> 6) & 0x3f; |
1016 | unsigned short hours = (*time >> 11) & 0x001F; | 1036 | unsigned hours = (time2 >> 12) & 0x1f; |
1017 | if ((mins += 10) >= 60) | 1037 | |
1018 | { | 1038 | mins = 11 * ((mins/11) + 1); /* advance to next multiple of 11 */ |
1019 | mins = 0; | 1039 | if (mins > 59) |
1020 | hours++; | ||
1021 | } | ||
1022 | if ((++hours) >= 24) | ||
1023 | { | 1040 | { |
1024 | hours = hours - 24; | 1041 | mins = 11; /* 00 would be a bad marker */ |
1025 | next_day = true; | 1042 | if (++hours > 23) |
1043 | { | ||
1044 | hours = 0; | ||
1045 | next_day = true; | ||
1046 | } | ||
1026 | } | 1047 | } |
1027 | *time = (hours << 11) | (mins << 5); | 1048 | time2 = (hours << 12) | (mins << 6) | mins; /* secs = mins */ |
1028 | } | 1049 | } |
1050 | *time = time2 >> 1; | ||
1029 | } | 1051 | } |
1052 | |||
1053 | if (tenth) | ||
1054 | *tenth = (time2 & 1) * 100; | ||
1030 | 1055 | ||
1031 | if (date) | 1056 | if (date && next_day) |
1032 | { | 1057 | { |
1033 | if (0 == *date) | 1058 | static const unsigned char daysinmonth[] = |
1034 | { | 1059 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
1035 | /* Macros to convert a 2-digit string to a decimal constant. | 1060 | unsigned day = *date & 0x1f; |
1036 | (YEAR), MONTH and DAY are set by the date command, which outputs | 1061 | unsigned month = (*date >> 5) & 0x0f; |
1037 | DAY as 00..31 and MONTH as 01..12. The leading zero would lead to | 1062 | unsigned year = (*date >> 9) & 0x7f; |
1038 | misinterpretation as an octal constant. */ | 1063 | |
1039 | #define S100(x) 1 ## x | 1064 | /* simplification: ignore leap years */ |
1040 | #define C2DIG2DEC(x) (S100(x)-100) | 1065 | if (++day > daysinmonth[month-1]) |
1041 | /* set to build date */ | ||
1042 | *date = ((YEAR - 1980) << 9) | (C2DIG2DEC(MONTH) << 5) | ||
1043 | | C2DIG2DEC(DAY); | ||
1044 | } | ||
1045 | else | ||
1046 | { | 1066 | { |
1047 | unsigned short day = *date & 0x001F; | 1067 | day = 1; |
1048 | unsigned short month = (*date >> 5) & 0x000F; | 1068 | if (++month > 12) |
1049 | unsigned short year = (*date >> 9) & 0x007F; | ||
1050 | if (next_day) | ||
1051 | { | 1069 | { |
1052 | /* do a very simple day increment - never go above 28 days */ | 1070 | month = 1; |
1053 | if (++day > 28) | 1071 | year++; |
1054 | { | ||
1055 | day = 1; | ||
1056 | if (++month > 12) | ||
1057 | { | ||
1058 | month = 1; | ||
1059 | year++; | ||
1060 | } | ||
1061 | } | ||
1062 | *date = (year << 9) | (month << 5) | day; | ||
1063 | } | 1072 | } |
1064 | } | 1073 | } |
1074 | *date = (year << 9) | (month << 5) | day; | ||
1065 | } | 1075 | } |
1066 | if (tenth) | 1076 | |
1067 | *tenth = 0; | ||
1068 | #endif /* CONFIG_RTC */ | 1077 | #endif /* CONFIG_RTC */ |
1069 | } | 1078 | } |
1070 | 1079 | ||