Sansa Connect: Discard invalid monotime reads

Read monotime twice in a row and only accept the value if it matches or
the two reads are 1 second apart.

Change-Id: Ibd289103a20404dd1b2bbd131fdfa8905852c788
This commit is contained in:
Tomasz Moń 2021-06-27 13:14:11 +02:00
parent a4ab636423
commit 1b81bd8a61
No known key found for this signature in database
GPG key ID: 92BA8820D4D517C8

View file

@ -120,9 +120,10 @@ static bool input_interrupt_pending;
#define MONOTIME_OFFSET_FILE ROCKBOX_DIR "/monotime_offset.dat" #define MONOTIME_OFFSET_FILE ROCKBOX_DIR "/monotime_offset.dat"
static uint32_t monotime_offset; static uint32_t monotime_offset;
/* Buffer last read monotime value. Reading monotime takes /* Buffer last read monotime value. Reading monotime takes
* atleast 700 us so the tick counter is used together with * atleast 1400 us so the tick counter is used together with
* last read monotime value to return current time. * last read monotime value to return current time.
*/ */
static bool monotime_available;
static uint32_t monotime_value; static uint32_t monotime_value;
static unsigned long monotime_value_tick; static unsigned long monotime_value_tick;
@ -521,16 +522,6 @@ bool charging_state(void)
return (avr_battery_status & BATTERY_STATUS_CHARGING) != 0; return (avr_battery_status & BATTERY_STATUS_CHARGING) != 0;
} }
static uint32_t avr_hid_get_monotime(void)
{
uint8_t tmp[4];
if (avr_execute_command(CMD_MONOTIME, tmp, sizeof(tmp)))
{
return (tmp[0]) | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24);
}
return 0;
}
static void avr_hid_enable_wheel(void) static void avr_hid_enable_wheel(void)
{ {
uint8_t enable = 0x01; uint8_t enable = 0x01;
@ -651,22 +642,48 @@ static bool write_monotime_offset(void)
static void read_monotime(void) static void read_monotime(void)
{ {
uint32_t value = avr_hid_get_monotime(); uint8_t tmp[4];
uint32_t t1, t2;
if (!avr_execute_command(CMD_MONOTIME, tmp, sizeof(tmp)))
{
return;
}
t1 = (tmp[0]) | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24);
if (!avr_execute_command(CMD_MONOTIME, tmp, sizeof(tmp)))
{
return;
}
t2 = (tmp[0]) | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24);
if ((t1 == t2) || (t1 + 1 == t2))
{
int flags = disable_irq_save(); int flags = disable_irq_save();
monotime_value = value; monotime_value = t1;
monotime_value_tick = current_tick; monotime_value_tick = current_tick;
restore_irq(flags); restore_irq(flags);
monotime_available = true;
}
} }
static time_t get_timestamp(void) static time_t get_timestamp(void)
{ {
time_t timestamp; time_t timestamp;
if (!monotime_available)
{
read_monotime();
}
if (monotime_available)
{
int flags = disable_irq_save(); int flags = disable_irq_save();
timestamp = monotime_value; timestamp = monotime_value;
timestamp += monotime_offset; timestamp += monotime_offset;
timestamp += ((current_tick - monotime_value_tick) / HZ); timestamp += ((current_tick - monotime_value_tick) / HZ);
restore_irq(flags); restore_irq(flags);
return timestamp; return timestamp;
}
return 0;
} }
void rtc_init(void) void rtc_init(void)