I figured out where DST info is stored on my SD800.
get_parameter_data(20, buf, 8)
returns a structure containing at least 5 useful bytes. I modified the parameter browser to look at these in hex rather than as a string (on my camera there are three 8 byte values, none of which look like strings. I think it would be useful to add this diff:
svn di core/gui.c
Index: core/gui.c
===================================================================
--- core/gui.c (revision 795)
+++ core/gui.c (working copy)
@@ -2620,6 +2620,14 @@
get_parameter_data(p, &r, len);
sprintf(sbuf, "%3d: %30d :%2d ", p, r,len);
}
+ else if (len==8){
+ get_parameter_data(p, s, len);
+ sprintf(sbuf,
+ "%3d: "
+ " %02x %02x %02x %02x %02x %02x %02x %02x"
+ " :%2d ",
+ p,s[0],s[1],s[2],s[3],s[4],s[5],s[6],s[7],len);
+ }
else {
if (len>=sizeof(s)) count=sizeof(s)-1; else count=len;
get_parameter_data(p, &s, count);
Anyway, parameter 20 holds:
- Home Timezone
- (0x1) -- I don't know what this represents and I've never seen it change
- Travel Timezone
- (0x1) -- Another "one" byte, which I've also never seen change
- Is Travel Time -- A byte saying whether to use the home time (0x0) or travel time (0x1)
- Is Home DST
- Is Travel DST
- (0x0) -- I don't know if this one is used either
I hacked the localtime() wrapper to use DST/Travel-compensated time rather than returning the _localtime() value directly.
My DST/Travel compensation code relies on parameter 20 holding this 8-byte structure. I'd be surprised if it's the same parameter ID on all cameras, and I don't know how to figure out which ID might be used on other cameras, or even which cameras don't include the DST/Travel feature, so it's not very robust.
I'll leave it to somebody who's more familiar with the CHDK codebase to figure out how to incorporate this code, but here's how I handled it:
/*
** tz_offset table
**
** NOTE: this data must be stored in the firmware somewhere, but I don't know where.
**
** The following table matches the time zone list and time offsets used by
** my SD800 camera. This list is, of course, subject to change. For example,
** one of the cities listed is "Caracas", whose time zone at the time the camera
** was designed was -4:00 offset from UTC. Since then, Venezuela switched its
** time zone offset to -4:30, so a newer camera might instead list "San Juan, PR"
** as -4:00 and "Caracas" as -4:30. This would extend the table to 33 entries.
*/
static const int tz_offset[32] =
{
0, // 00 => +0:00 London
1*HOURS, // 01 => +1:00 Paris
2*HOURS, // 02 => +2:00 Cairo
3*HOURS, // 03 => +3:00 Moscow
3*HOURS+30*MINUTES, // 04 => +3:30 Teheran
4*HOURS, // 05 => +4:00 Dubai
4*HOURS+30*MINUTES, // 06 => +4:30 Kabul
5*HOURS, // 07 => +5:00 Karachi
5*HOURS+30*MINUTES, // 08 => +5:30 Delhi
5*HOURS+45*MINUTES, // 09 => +5:45 Kathmandu
6*HOURS, // 0A => +6:00 Dacca
6*HOURS+30*MINUTES, // 0B => +6:30 Yangon
7*HOURS, // 0C => +7:00 Bangkok
8*HOURS, // 0D => +8:00 Hong Kong
9*HOURS, // 0E => +9:00 Tokyo
9*HOURS+30*MINUTES, // 0F => +9:30 Adelaide
10*HOURS, // 10 => +10:00 Sydney
11*HOURS, // 11 => +11:00 Solomon Islands
12*HOURS, // 12 => +12:00 Wellington
12*HOURS+45*MINUTES, // 13 => +12:45 Chatham Islands
-11*HOURS, // 14 => -11:00 Samoa
-10*HOURS, // 15 => -10:00 Honolulu
-9*HOURS, // 16 => -9:00 Anchorage
-8*HOURS, // 17 => -8:00 Los Angeles
-7*HOURS, // 18 => -7:00 Denver
-6*HOURS, // 19 => -6:00 Chicago
-5*HOURS, // 1A => -5:00 New York
-4*HOURS, // 1B => -4:00 Caracas
-3*HOURS-30*MINUTES, // 1C => -3:30 Newfoundland
-3*HOURS, // 1D => -3:00 Rio De Janeiro
-2*HOURS, // 1E => -2:00 Fernando de Noronha
-1*HOURS, // 1F => -1:00 Azores
};
/*
** struct timezone_info
**
** Canon stores information about home and travel timezones and daylight savings
** time settings in a structure that looks something like this.
*/
struct timezone_info {
unsigned char home_tz; // Home time index into tz_offset table
unsigned char one1; // Unknown meaning, always 1 on SD800
unsigned char travel_tz; // Travel time index into tz_offset table
unsigned char one2; // Unknown meaning, always 1 on SD800
unsigned char is_travel; // Flag for Is Travel Time enabled
unsigned char home_dst; // Flag for Is Home DST enabled
unsigned char travel_dst; // Flag for Is Travel DST enabled
unsigned char unused;
};
/*
** tz_compensate(tod)
**
** Some Canon cameras have settings for daylight savings time and for a second
** time zone to use when traveling. The _localtime() function on these cameras
** doesn't know about these settings, and only compensates for the local time
** zone.
**
** This function reads the parameter data that describes the time offsets and
** applies them to a time value before the time value is passed to _localtime().
*/
const unsigned long *tz_compensate(const unsigned long *tod) {
static unsigned long biased_tod; // static so it's OK to return pointer
struct timezone_info tz_prop;
get_parameter_data(PARAM_TIMEZONE_INFO, &tz_prop, sizeof(tz_prop));
if (tz_prop.is_travel)
biased_tod = *tod +
((tz_offset[tz_prop.travel_tz] - tz_offset[tz_prop.home_tz]) +
(tz_prop.travel_dst ? 1*HOURS : 0));
else
biased_tod = *tod + (tz_prop.home_dst ? 1*HOURS : 0);
return &biased_tod;
}
void *localtime(const unsigned long *_tod)
{
#if !CAM_DRYOS
return _localtime(tz_compensate(_tod));
#else
// for DRYOS cameras do something with this! - sizeof(x[]) must be >= sizeof(struct tm) : 'static int x[9];'
static int x[9];
return _LocalTime(tz_compensate(_tod), &x);
#endif
}