summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan McGee <dpmcgee@gmail.com>2010-10-23 02:26:23 -0500
committerDan McGee <dpmcgee@gmail.com>2011-01-21 16:16:23 -0600
commit1badcfb435d2aaff2ddc0e3d36b36eee2e37f9d6 (patch)
tree86f419d38a7c56df781bafd45bee30f8216ea546
parent56aa1adfd9c1ac715b76dab51a02ae09895b866f (diff)
downloadonkyocontrol-1badcfb435d2aaff2ddc0e3d36b36eee2e37f9d6.tar.gz
onkyocontrol-1badcfb435d2aaff2ddc0e3d36b36eee2e37f9d6.zip
Move most receiver sending logic into rcvr_send_command()
Before, we were doing concatination of prefix and suffix in the queuing portion, and deciding whether to actually send the command in the main loop. Move as much of this logic as possible into one method to make it easier to accommodate alternate message formats. Signed-off-by: Dan McGee <dpmcgee@gmail.com>
-rw-r--r--command.c68
-rw-r--r--onkyo.c43
-rw-r--r--onkyo.h2
-rw-r--r--receiver.c79
4 files changed, 89 insertions, 103 deletions
diff --git a/command.c b/command.c
index 41767f2..daaedcd 100644
--- a/command.c
+++ b/command.c
@@ -56,20 +56,35 @@ static char *strtoupper(char *str)
}
/**
- * Queue a receiver command to be sent when the serial device file descriptor
+ * Queue a receiver command to be sent when the device file descriptor
* is available for writing. Queueing and sending asynchronously allows
* the program to backlog many commands at once without blocking on the
- * relatively slow serial device. When queueing, we check if this command
+ * potentially slow receiver device. When queueing, we check if this command
* is already in the queue- if so, we do not queue it again.
- * @param rcvr the receiver to queue the command for
- * @param cmd command to queue, will be freed once it is actually ran
- * @return 0 on queueing success, 1 on queueing skip
+ * @param rcvr the receiver the command should be queued for
+ * @param cmd the command struct for the first part of the receiver command
+ * string, usually containing a prefix aka "PWR"
+ * @param arg the second part of the receiver command string, aka "QSTN"
+ * @return 0 on success, -1 on missing args
*/
-static int queue_rcvr_command(struct receiver *rcvr, char *cmd)
+static int cmd_attempt(struct receiver *rcvr,
+ const struct command *cmd, const char *arg)
{
- struct cmdqueue *q = malloc(sizeof(struct cmdqueue));
- q->hash = hash_sdbm(cmd);
- q->cmd = cmd;
+ char *fullcmd;
+ struct cmdqueue *q;
+
+ if(!cmd || !arg)
+ return(-1);
+
+ if(!cmd->fake && !cmd->prefix)
+ return(-1);
+
+ fullcmd = malloc(strlen(cmd->prefix) + strlen(arg) + 1);
+ sprintf(fullcmd, "%s%s", cmd->prefix, arg);
+
+ q = malloc(sizeof(struct cmdqueue));
+ q->hash = hash_sdbm(fullcmd);
+ q->cmd = fullcmd;
q->next = NULL;
if(rcvr->queue == NULL) {
@@ -80,8 +95,8 @@ static int queue_rcvr_command(struct receiver *rcvr, char *cmd)
if(ptr->hash == q->hash) {
/* command already in our queue, skip second copy */
free(q);
- free(cmd);
- return(1);
+ free(fullcmd);
+ return(0);
}
if(!ptr->next)
break;
@@ -92,37 +107,6 @@ static int queue_rcvr_command(struct receiver *rcvr, char *cmd)
return(0);
}
-/**
- * Attempt to write a receiver command out to the control channel.
- * This will take a in a simple receiver string minus any preamble or ending
- * characters, turn it into a valid command, and queue it to send to the
- * receiver.
- * @param rcvr the receiver the command should be queued for
- * @param cmd the command struct for the first part of the receiver command
- * string, usually containing a prefix aka "PWR"
- * @param arg the second part of the receiver command string, aka "QSTN"
- * @return 0 on success, -1 on missing args
- */
-static int cmd_attempt(struct receiver *rcvr,
- const struct command *cmd, const char *arg)
-{
- char *fullcmd;
-
- if(!cmd || !arg)
- return(-1);
-
- if(!cmd->fake && !cmd->prefix)
- return(-1);
-
- fullcmd = malloc(strlen(START_SEND) + strlen(cmd->prefix) + strlen(arg)
- + strlen(END_SEND) + 1);
- sprintf(fullcmd, START_SEND "%s%s" END_SEND, cmd->prefix, arg);
-
- /* send the command to the receiver */
- queue_rcvr_command(rcvr, fullcmd);
- return(0);
-}
-
static int cmd_attempt_raw(struct receiver *rcvr,
const char *fake, const char *arg)
{
diff --git a/onkyo.c b/onkyo.c
index 14116d9..c99cbee 100644
--- a/onkyo.c
+++ b/onkyo.c
@@ -185,8 +185,8 @@ static void cleanup(int ret)
if(rcvr->fd > -1) {
xclose(rcvr->fd);
}
- free(rcvr);
receivers = receivers->next;
+ free(rcvr);
}
/* close the log file descriptor */
@@ -714,37 +714,6 @@ static struct timeval min_timeval(struct timeval *tv1, struct timeval *tv2)
return(tv1->tv_usec < tv2->tv_usec ? *tv1 : *tv2);
}
-/**
- * Get the next receiver command that should be sent. This implementation has
- * logic to discard non-power commands if the receiver is not powered up.
- * @param rcvr the receiver to pull a command out of the queue for
- * @return the command to send (must be freed), NULL if none available
- */
-static char *next_rcvr_command(struct receiver *rcvr)
-{
- /* Determine whether we should send the command. This depends on two
- * factors:
- * 1. If the power is on, always send the command.
- * 2. If the power is off, send only power commands through.
- */
- while(rcvr->queue) {
- /* dequeue the next cmd queue item */
- struct cmdqueue *ptr = rcvr->queue;
- rcvr->queue = rcvr->queue->next;
-
- if(rcvr->power || is_power_command(ptr->cmd)) {
- char *cmd = ptr->cmd;
- free(ptr);
- return cmd;
- } else {
- printf("skipping command as receiver power appears to be off\n");
- free(ptr->cmd);
- free(ptr);
- }
- }
- return NULL;
-}
-
static const struct option opts[] = {
{"bind", optional_argument, 0, 'b'},
{"daemon", no_argument, 0, 'd'},
@@ -1000,15 +969,7 @@ int main(int argc, char *argv[])
}
/* check if we have outgoing messages to send to receiver */
if(r->fd > -1 && r->queue != NULL && FD_ISSET(r->fd, &writefds)) {
- char *cmd = next_rcvr_command(r);
- if(cmd) {
- int ret = rcvr_send_command(r->fd, cmd);
- if(ret != 0) {
- printf("%s", rcvr_err);
- }
- /* set our last sent time */
- gettimeofday(&(r->last_cmd), NULL);
- }
+ rcvr_send_command(r);
}
r = r->next;
}
diff --git a/onkyo.h b/onkyo.h
index 410318b..a97a884 100644
--- a/onkyo.h
+++ b/onkyo.h
@@ -66,7 +66,7 @@ struct receiver {
/* receiver.c - receiver interaction functions, status processing */
void init_statuses(void);
void free_statuses(void);
-int rcvr_send_command(int serialfd, const char *cmd);
+int rcvr_send_command(struct receiver *rcvr);
char *process_incoming_message(int serialfd, int logfd);
enum power initial_power_status(void);
enum power update_power_status(enum power pwr, const char *msg);
diff --git a/receiver.c b/receiver.c
index 6903499..e77674b 100644
--- a/receiver.c
+++ b/receiver.c
@@ -36,32 +36,73 @@ struct status {
const char *value;
};
+/**
+ * Get the next receiver command that should be sent. This implementation has
+ * logic to discard non-power commands if the receiver is not powered up.
+ * @param rcvr the receiver to pull a command out of the queue for
+ * @return the command to send (must be freed), NULL if none available
+ */
+static char *next_rcvr_command(struct receiver *rcvr)
+{
+ /* Determine whether we should send the command. This depends on two
+ * factors:
+ * 1. If the power is on, always send the command.
+ * 2. If the power is off, send only power commands through.
+ */
+ while(rcvr->queue) {
+ /* dequeue the next cmd queue item */
+ struct cmdqueue *ptr = rcvr->queue;
+ rcvr->queue = rcvr->queue->next;
+
+ if(rcvr->power || is_power_command(ptr->cmd)) {
+ char *cmd = ptr->cmd;
+ free(ptr);
+ return cmd;
+ } else {
+ printf("skipping command as receiver power appears to be off\n");
+ free(ptr->cmd);
+ free(ptr);
+ }
+ }
+ return NULL;
+}
+
/**
* Send a command to the receiver. This should be used when a write() to the
* given file descriptor is known to be non-blocking; e.g. after a select()
* call on the descriptor.
- * @param serialfd the file descriptor the receiver is accessible on
- * @param cmd the command to send to the receiver
- * @return 0 on success, -1 on failure
+ * @param rcvr the receiver to send a command to from the attached queue
+ * @return 0 on success or no action taken, -1 on failure
*/
-int rcvr_send_command(int serialfd, const char *cmd)
+int rcvr_send_command(struct receiver *rcvr)
{
- size_t cmdsize;
- ssize_t retval;
-
- if(!cmd)
- return(-1);
- cmdsize = strlen(cmd);
-
- /* write the command */
- retval = xwrite(serialfd, cmd, cmdsize);
- if(retval < 0 || ((size_t)retval) != cmdsize) {
- fprintf(stderr, "send_command, write returned %zd\n", retval);
- return(-1);
+ if(!rcvr->queue)
+ return -1;
+
+ char *cmd = next_rcvr_command(rcvr);
+ if(cmd) {
+ ssize_t retval;
+ size_t cmdsize = strlen(START_SEND) + strlen(cmd)
+ + strlen(END_SEND);
+ char *fullcmd = malloc(cmdsize + 1);
+ sprintf(fullcmd, START_SEND "%s" END_SEND, cmd);
+
+ /* write the command */
+ retval = xwrite(rcvr->fd, fullcmd, cmdsize);
+ /* print command to console; newline is already in command */
+ printf("command: %s", fullcmd);
+ free(fullcmd);
+ free(cmd);
+
+ if(retval < 0 || ((size_t)retval) != cmdsize) {
+ fprintf(stderr, "send_command, write returned %zd\n", retval);
+ printf("%s", rcvr_err);
+ return(-1);
+ }
+ /* set our last sent time */
+ gettimeofday(&(rcvr->last_cmd), NULL);
}
- /* print command to console; newline is already in command */
- printf("command: %s", cmd);
- return(0);
+ return 0;
}
/**