Show ensbox_sb.c syntax highlighted
/*
*
* Copyright (c) 2006 The Regents of the University of California. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Neither the name of the University nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <libdev/packet_client.h>
#include <libdev/status_dev.h>
#include <emrun/emrun.h>
#define TOSH_DATA_LENGTH 255
#include "../../../tos-contrib/include/AM_emstar.h"
#include "../../../tos-contrib/ENSBox/apps/ENSBox/ENSBoxDefs.h"
//// Defines //// (@TCC -- move these to a shared header probably)
#define ENSBOX_SB_STATUS_DEV sim_path("/dev/loc/sb")
//// Usage ////
void usage(char *name){
misc_print_usage
(name,
"",
""
);
exit(1);
}
//// Variables that need to be declared upfront ////
pd_client_context_t *pd_client = NULL;
//// simple internal utility functions ////
// send one byte (plus the TOSNIC_ENSBOX_PACKET flag) to the pd_client
void pd_client_send_1(uint8_t data_val){
uint8_t s[2];
s[0] = TOSNIC_ENSBOX_PACKET;
s[1] = data_val;
pd_client_send(pd_client, s, sizeof(s));
}
//// Status client stuff ////
// status client struct
typedef struct ensbox_sb_state {
status_context_t * status_ref; // ref to status device
g_event_t * timer_ref; // timer to trigger events
// actual state vars
float temperature; //
uint8_t temperature_flags; //
} ensbox_sb_state_t;
ensbox_sb_state_t state = {};
// state change timer
int ensbox_sb_state_timer_fired(void *data, int interval, g_event_t *event){
ensbox_sb_state_t * sb_state = (ensbox_sb_state_t *) data;
// update the state //
// update temperature reading
unsigned char s[2];
s[0] = TOSNIC_ENSBOX_PACKET;
s[1] = ENSBOX_MSG_SB_TEMP;
pd_client_send(pd_client, s, sizeof(s));
// trigger the status device to be readable
g_status_dev_notify(sb_state->status_ref);
// keep firing the timer! (to stop it return TIMER_DONE)
return TIMER_RENEW;
}
// Macine readable output (@TCC -- to fill in more rationally)
int ensbox_sb_status_bin(status_context_t *info, buf_t *buf){
//ensbox_sb_state_t *sb_state = (ensbox_sb_state_t *) sd_data(info);
// now, copy over the latest state
//bufcpy(buf, &(sb_state->state), sizeof(sb_state->whatever));
// means this message is complete and the notification of
// the client can be cleared
return STATUS_MSG_COMPLETE;
}
// Human readable output
int ensbox_sb_status_print(status_context_t *info, buf_t *buf){
ensbox_sb_state_t *sb_state = (ensbox_sb_state_t *) sd_data(info);
bufprintf(buf, "Temperature (at sensor board): %0.2f (Flags 0x%X)\n",
sb_state->temperature, sb_state->temperature_flags);
bufprintf(buf, "\nCommands supported:\n");
bufprintf(buf, "\tpwr_gumstix_{on|off|status}\n");
bufprintf(buf, "\tpwr_GPS_{on|off|status}\n");
bufprintf(buf, "\tpwr_audio_in_{on|off|status}\n");
bufprintf(buf, "\tpwr_audio_out_{on|off|status}\n");
return STATUS_MSG_COMPLETE;
}
// Parse commands echoed into the device
static int ensbox_sb_status_write(status_context_t *info, char *command,
size_t buf_size){
int retval = EVENT_RENEW;
//ensbox_sb_state_t *sb_state = (ensbox_sb_state_t *) sd_data(info);
parser_state_t *ps = misc_parse_init(command, MISC_PARSE_COLON_SCHEME);
elog(LOG_WARNING, "Got command \"%s\"", command);
while( misc_parse_next_kvp(ps) >= 0 ){
// power commands & querries
if( strcmp(ps->key, "pwr_gumstix_off") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_GUMSTIX_OFF);
}
else if( strcmp(ps->key, "pwr_gumstix_on") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_GUMSTIX_ON);
}
else if( strcmp(ps->key, "pwr_gumstix_status") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_GUMSTIX_STATUS);
}
if( strcmp(ps->key, "pwr_GPS_off") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_GPS_OFF);
}
else if( strcmp(ps->key, "pwr_GPS_on") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_GPS_ON);
}
else if( strcmp(ps->key, "pwr_GPS_status") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_GPS_STATUS);
}
if( strcmp(ps->key, "pwr_audio_in_off") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_AUDIO_IN_OFF);
}
else if( strcmp(ps->key, "pwr_audio_in_on") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_AUDIO_IN_ON);
}
else if( strcmp(ps->key, "pwr_audio_in_status") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_AUDIO_IN_STATUS);
}
if( strcmp(ps->key, "pwr_audio_out_off") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_AUDIO_OUT_OFF);
}
else if( strcmp(ps->key, "pwr_audio_out_on") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_AUDIO_OUT_ON);
}
else if( strcmp(ps->key, "pwr_audio_out_status") == 0 ){
pd_client_send_1(ENSBOX_MSG_SB_PWR_AUDIO_OUT_STATUS);
}
}
return retval;
}
//// Packet client stuff ////
int sb_msg_recv(void *pkt, ssize_t len,
pd_client_context_t *pd_client){
elog(LOG_WARNING, "got message");
elog_raw(LOG_WARNING, pkt, len);
switch(((uint8_t*)pkt)[1]){
case ENSBOX_MSG_SB_TEMP :
// update temperature state
state.temperature = ((int8_t*)pkt)[2] + 0.0 +
(((((uint8_t*)pkt)[3])&0x80)?.5:0) +
(((((uint8_t*)pkt)[3])&0x40)?.25:0);
state.temperature_flags = (((uint8_t*)pkt)[3])&0x3F;
elog(LOG_WARNING, "Temperature %.2f (0x%X)", state.temperature,
state.temperature_flags);
break;
// power status (component on/off) querries (1=on)
case ENSBOX_MSG_SB_PWR_GUMSTIX_STATUS :
elog(LOG_WARNING, "Pwr status for Gumstix = %d", ((uint8_t*)pkt)[2]);
break;
case ENSBOX_MSG_SB_PWR_GPS_STATUS :
elog(LOG_WARNING, "Pwr status for GPS = %d", ((uint8_t*)pkt)[2]);
break;
case ENSBOX_MSG_SB_PWR_AUDIO_IN_STATUS :
elog(LOG_WARNING, "Pwr status for Audio Input amps = %d",
((uint8_t*)pkt)[2]);
break;
case ENSBOX_MSG_SB_PWR_AUDIO_OUT_STATUS :
elog(LOG_WARNING, "Pwr status for Audio Out amp = %d",
((uint8_t*)pkt)[2]);
break;
default:
elog(LOG_WARNING, "Unknown message type");
}
return EVENT_RENEW;
}
//// Other ////
// Callback when we are asked (by emrun) to shut down
static void sb_shutdown(void *data){
elog(LOG_NOTICE, "Shutting down ENSBox Sensor Board Driver");
exit(0);
}
//// Main ////
int main(int argc, char *argv[]){
// ensbox_sb_state_t state = {};
// generic init
misc_init(&argc, argv, CVSTAG);
if (misc_args_remain(&argc, argv)) {
usage(argv[0]);
}
/// register with emrun ///
emrun_opts_t emrun_opts = {
shutdown: sb_shutdown,
data: &state
};
emrun_init(&emrun_opts); /* this should be the last initialization */
// register pd_client
pd_client_opts_t pd_opts = {
devname: sim_path("/dev/link/mote0/mote/raw"),
receive: sb_msg_recv,
};
pd_client_open(&pd_opts, &pd_client);
// register status_dev
status_dev_opts_t s_opts = {
device: {
devname: ENSBOX_SB_STATUS_DEV,
device_info: &state
},
printable: ensbox_sb_status_print,
binary: ensbox_sb_status_bin,
write: ensbox_sb_status_write
};
if( g_status_dev(&s_opts, &(state.status_ref)) < 0 ){
elog(LOG_CRIT, "Unable to create status device \"%s\": %m",
s_opts.device.devname);
exit(1);
}
// register timers which update status dev
g_timer_add(10000, ensbox_sb_state_timer_fired, &state,
NULL, &(state.timer_ref));
// done: register with emrun //
g_main(); // start the emrun event loop
elog(LOG_CRIT, "event loop exited unexpectedly!"); // should never get here
return 1;
}
See more files for this project here