summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dpmcgee@gmail.com>2011-11-21 00:10:16 -0600
committerDan McGee <dpmcgee@gmail.com>2011-11-21 00:10:16 -0600
commit7c2808a72206fa5efff26d82e2bbd0457f3bfbbd (patch)
treecbf943167782efc06dbe2f61e3c7e1c0aa6d1262
parent1de53f23da464e3bef10206d0bcbbfdd156b8e31 (diff)
downloadonkyocontrol-7c2808a72206fa5efff26d82e2bbd0457f3bfbbd.tar.gz
onkyocontrol-7c2808a72206fa5efff26d82e2bbd0457f3bfbbd.zip
Fix some faulty timeval related math and comparisons
Add a timeval_positive helper function that doesn't get confused when tv_usec is set to 0 (regardless of the value of tv_sec). Use it wherever possible, and also attempt to reason through our other time value comparison points to ensure all values are being handled correctly, especially those that result in a zero in a field or a zero difference. Signed-off-by: Dan McGee <dpmcgee@gmail.com>
-rw-r--r--onkyo.c32
-rw-r--r--onkyo.h2
-rw-r--r--util.c10
3 files changed, 30 insertions, 14 deletions
diff --git a/onkyo.c b/onkyo.c
index a768d06..ac24f36 100644
--- a/onkyo.c
+++ b/onkyo.c
@@ -587,7 +587,7 @@ static int open_socket_listener(const char *path)
* 1 is returned and timeoutval is left undefined. If we cannot send, then 0
* is returned and the timeoutval is set accordingly.
* @param last the last time we sent a command to the receiver
- * @param last time value to use as 'now'
+ * @param now time value to use as 'now'
* @param timeoutval location to store timeout before next permitted send
* @return 1 if we can send a command, 0 if we cannot (and timeoutval is set)
*/
@@ -602,9 +602,10 @@ static int can_send_command(struct timeval * restrict last,
wait.tv_usec = 1000 * COMMAND_WAIT;
wait.tv_sec = wait.tv_usec / 1000000;
wait.tv_usec -= wait.tv_sec * 1000000;
+
/* check if both of our difference values are > wait values */
if(diff.tv_sec > wait.tv_sec ||
- (diff.tv_sec == wait.tv_sec && diff.tv_usec > wait.tv_usec)) {
+ (diff.tv_sec == wait.tv_sec && diff.tv_usec >= wait.tv_usec)) {
/* it has been long enough, note that timeoutval is untouched */
return 1;
}
@@ -912,7 +913,7 @@ int main(int argc, char *argv[])
/* do we need to queue a power off command for sleep? */
if(r->zone2_sleep.tv_sec) {
timeval_diff(&r->zone2_sleep, &now, &diff);
- if(diff.tv_sec >= 0 && diff.tv_usec > 0) {
+ if(timeval_positive(&diff)) {
timeoutval = timeval_min(&timeoutval, &diff);
} else {
process_command(r, "zone2power off");
@@ -921,7 +922,7 @@ int main(int argc, char *argv[])
}
if(r->zone3_sleep.tv_sec) {
timeval_diff(&r->zone3_sleep, &now, &diff);
- if(diff.tv_sec >= 0 && diff.tv_usec > 0) {
+ if(timeval_positive(&diff)) {
timeoutval = timeval_min(&timeoutval, &diff);
} else {
process_command(r, "zone3power off");
@@ -938,7 +939,7 @@ int main(int argc, char *argv[])
r->next_sleep_update.tv_sec += 60;
}
timeval_diff(&r->next_sleep_update, &now, &diff);
- if(diff.tv_sec >= 0 && diff.tv_usec > 0) {
+ if(timeval_positive(&diff)) {
timeoutval = timeval_min(&timeoutval, &diff);
}
} else {
@@ -1013,18 +1014,23 @@ int main(int argc, char *argv[])
}
/* do we need to send a sleep status update? */
if(r->next_sleep_update.tv_sec) {
- struct timeval diff;
+ struct timeval diff, *next;
gettimeofday(&now, NULL);
- timeval_diff(&now, &r->next_sleep_update, &diff);
- if(diff.tv_sec >= 0 && diff.tv_usec > 0) {
- if(r->zone2_sleep.tv_sec > 0)
+ next = &r->next_sleep_update;
+
+ timeval_diff(&now, next, &diff);
+ if(timeval_positive(&diff)) {
+ if(r->zone2_sleep.tv_sec)
write_fakesleep_status(r, now, '2');
- if(r->zone3_sleep.tv_sec > 0)
+ if(r->zone3_sleep.tv_sec)
write_fakesleep_status(r, now, '3');
/* now that we've notified, schedule it again not 60
- * seconds from now, but 60 seconds absolute from when we
- * should have notified */
- r->next_sleep_update.tv_sec += 60;
+ * seconds from now, but at 60 second intervals from when
+ * we should have notified */
+ do {
+ next->tv_sec += 60;
+ diff.tv_sec -= 60;
+ } while(timeval_positive(&diff));
}
}
r = r->next;
diff --git a/onkyo.h b/onkyo.h
index a74dba4..1769dbf 100644
--- a/onkyo.h
+++ b/onkyo.h
@@ -76,7 +76,6 @@ int write_to_connections(const char *msg);
void init_statuses(void);
int rcvr_send_command(struct receiver *rcvr);
int process_incoming_message(struct receiver *rcvr, int logfd);
-enum power initial_power_status(void);
/* command.c - user command processing */
void init_commands(void);
@@ -96,6 +95,7 @@ void timeval_diff(struct timeval * restrict a,
struct timeval * restrict b, struct timeval * restrict result);
struct timeval timeval_min(struct timeval *restrict a,
struct timeval * restrict b);
+int timeval_positive(struct timeval *tv);
#define timeval_clear(tv) do { (tv).tv_sec = 0; (tv).tv_usec = 0; } while(0)
#endif /* ONKYO_H */
diff --git a/util.c b/util.c
index b571d32..0e16b5f 100644
--- a/util.c
+++ b/util.c
@@ -116,4 +116,14 @@ struct timeval timeval_min(struct timeval *restrict a,
return a->tv_usec < b->tv_usec ? *a : *b;
}
+int timeval_positive(struct timeval *tv)
+{
+ if(tv->tv_sec > 0)
+ return 1;
+ if(tv->tv_sec == 0 && tv->tv_usec > 0)
+ return 1;
+
+ return 0;
+}
+
/* vim: set ts=4 sw=4 noet: */