Show radio.c syntax highlighted
/*
*
* Copyright (c) 2003 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.
*
*/
/*
* radio.c
*
* This is an emview module that displays radio state
*
* Author: girod
*
* $Id: radio.c,v 1.24 2004/04/02 07:09:46 girod Exp $
*/
char radio_c_id[] = "$Id: radio.c,v 1.24 2004/04/02 07:09:46 girod Exp $";
#include <mod/mod_radio.h>
#include <emview/emview.h>
#include <libmisc/misc.h>
#include <link/link.h>
struct radio_state {
GQuark comp_name;
};
typedef struct link_status_ext {
link_status_t stat;
struct timeval rcv_time;
} link_status_ext_t;
/* the global module variable */
static emview_module_t *mod = NULL;
/*
* functions that generate a radio name strings
*/
char *radio_box_name(int index)
{ return emview_generic_item_name(mod, index, NULL); }
GQuark radio_box_name_q(int index)
{
emview_module_inst_t *inst = emview_mod_inst_index(mod, index);
if (inst)
return ((struct radio_state *)(inst->data))->comp_name;
elog(LOG_ERR, "Can't find radio index %d!", index);
return 0;
}
void radio_register_component(node_id_t node, int index)
{
emview_component_register(radio_box_name_q(index), node, EMVIEW_COMP_TYPE_BOX);
}
int radio_lookup(char *device)
{
emview_module_inst_t *inst = emview_mod_inst_lookup(mod, device);
if (inst) return inst->index;
return -1;
}
link_status_t *radio_get_status(node_id_t node, int index)
{
emview_module_inst_t *inst = emview_mod_inst_index(mod, index);
if (inst) {
emview_dev_node_t *dn = emview_dev_node_lookup(inst->dev, node);
if (dn)
return &(((link_status_ext_t *)dn->data)->stat);
}
return NULL;
}
char *radio_status_device_name(int index)
{
return link_name_s(emview_mod_inst_index(mod, index)->name,
LINK_STATUS_SUBDEV);
}
char *radio_data_source_name(int index, char *source)
{ return emview_generic_item_name(mod, index, source); }
char *radio_option_name(int index, char *option)
{ return radio_data_source_name(index, option); }
/*
* radio interface lookup function
*/
int radio_lookup_if(node_id_t id, if_id_t target_if, int prefer_index)
{
int i,k;
for (k=-1; k < emview_mod_inst_count(mod); k++) {
/* preference */
if (k<0) i = prefer_index;
else i = k;
{
emview_module_inst_t *inst = emview_mod_inst_index(mod, i);
emview_dev_node_t *dn = emview_dev_node_lookup(inst->dev, id);
if (dn && dn->data) {
link_status_ext_t *stat = (link_status_ext_t *)dn->data;
if (stat->stat.if_id == target_if)
return i;
}
}
}
return -1;
}
int radio_lookup_if_fixup(node_id_t *id, if_id_t target_if, int prefer_index)
{
int i,k;
emview_dev_node_t *dn;
if (*id != LINK_BROADCAST)
return radio_lookup_if(*id, target_if, prefer_index);
for (k=-1; k < emview_mod_inst_count(mod); k++) {
/* preference */
if (k<0) i = prefer_index;
else i = k;
{
emview_module_inst_t *inst = emview_mod_inst_index(mod, i);
for (dn=emview_dn_top(inst->dev); dn;
dn=emview_dn_next(dn)) {
if (dn && dn->data) {
link_status_ext_t *stat = (link_status_ext_t *)dn->data;
if (stat->stat.if_id == target_if) {
*id = emview_dn_get_node_id(dn);
return i;
}
}
}
}
}
return -1;
}
/*
* handle new status
*/
int radio_handle_data(emview_device_t *dev, emproxy_reply_hdr_t *reply,
emview_dev_node_t *node)
{
emview_module_inst_t *inst = (emview_module_inst_t *)emview_get_device_opts(dev)->private_data;
elog(LOG_DEBUG(10), "Got radio status data for node %d", emview_dn_get_node_id(node));
if (reply->data_length >= sizeof(link_status_t)) {
link_status_ext_t last_xstat;
link_status_ext_t *xstat;
link_status_t *stat;
int time_diff;
/* create status buffer if not present */
if (node->data == NULL)
node->data = g_new0(link_status_ext_t, 1);
/* cast pointer to it */
xstat = (link_status_ext_t *)node->data;
stat = &(xstat->stat);
/* copy */
memmove(&last_xstat, xstat, sizeof(link_status_ext_t));
memmove(stat, reply->data, sizeof(link_status_t));
xstat->rcv_time = reply->report_time;
/* push data to sources */
emview_update_source_int(radio_data_source_name(inst->index, RADIO_SOURCE_SLEEP),
reply->node_id, !stat->active);
emview_update_source_int(radio_data_source_name(inst->index, RADIO_SOURCE_IF_ID),
reply->node_id, stat->if_id);
/* compute the BPS */
if (last_xstat.rcv_time.tv_sec) {
time_diff = misc_tv_offset_neg(&(xstat->rcv_time), &(last_xstat.rcv_time));
if (time_diff > (MILLION_I / 2)) {
float bps[2];
char label[2][20];
char c[2] = {'R','T'};
int i;
bps[0] = (xstat->stat.bytes_rx - last_xstat.stat.bytes_rx) / (time_diff/MILLION_F);
bps[1] = (xstat->stat.bytes_tx - last_xstat.stat.bytes_tx) / (time_diff/MILLION_F);
for (i=0; i<2; i++) {
if (bps[i] < 1000)
sprintf(label[i], "%.1f%c", bps[i], c[i]);
if (bps[i] >= 1000.0)
sprintf(label[i], "%.1fK%c", bps[i] / 1000.0, c[i]);
else if (bps[i] > MILLION_F)
sprintf(label[i], "%.1fM%c", bps[i] / MILLION_F, c[i]);
}
emview_update_source(radio_data_source_name(inst->index, RADIO_SOURCE_BPS_RX),
reply->node_id, label[0]);
emview_update_source(radio_data_source_name(inst->index, RADIO_SOURCE_BPS_TX),
reply->node_id, label[1]);
}
}
}
return 0;
}
int radio_timeout(emview_device_t *dev, emview_dev_node_t *node)
{
elog(LOG_DEBUG(10), "Node %d timed out!", emview_dn_get_node_id(node));
return 0;
}
/*
* config
*/
static
int radio_config_device(emview_module_t *mod, emview_module_inst_t *instance,
char *device, node_id_t node)
{
int i = instance->index;
struct radio_state *radio = (struct radio_state *)instance->data;
emview_device_t *dev;
/*
* Register the device
*/
char buf[255];
emview_device_opts_t opts = {
name: radio_status_device_name(i),
private_data: instance,
proxy_string: buf,
data_handler: radio_handle_data,
node_timeout: radio_timeout,
parent: mod
};
radio->comp_name = g_quark_from_string(radio_box_name(i));
/* construct proxy string. Use device if supplied... */
sprintf(buf, "dev=%s:reread=1000",
device ? device : radio_status_device_name(i));
/* register device */
dev = emview_register_device(&opts);
instance->dev = dev;
/*
* Register data sources
*/
/* register sources for this device */
emview_register_source
(dev, radio_data_source_name(i, RADIO_SOURCE_CHANNEL), NULL);
emview_register_source
(dev, radio_data_source_name(i, RADIO_SOURCE_SLEEP), NULL);
emview_register_source
(dev, radio_data_source_name(i, RADIO_SOURCE_BPS_RX), NULL);
emview_register_source
(dev, radio_data_source_name(i, RADIO_SOURCE_BPS_TX), NULL);
emview_register_source
(dev, radio_data_source_name(i, RADIO_SOURCE_IF_ID), NULL);
return 0;
}
static
int radio_config_assign(emview_module_t *mod, emview_module_inst_t *inst,
node_id_t node, parser_state_t *ps)
{
int i = inst->index;
/*
* Register a GUI component
*/
/* Install a new radio component for this node, if needed */
emview_component_register(radio_box_name_q(i), node, EMVIEW_COMP_TYPE_BOX);
/*
* Register all our option classes.
*/
/* core option set */
emview_assign_source(node, radio_box_name(i), EMVIEW_BOX_COLOR,
radio_data_source_name(i, RADIO_SOURCE_CHANNEL),
radio_option_name(i, RADIO_CORE_OPTION), EMVIEW_ENABLE);
emview_assign_source(node, radio_box_name(i), EMVIEW_BOX_FLAG3,
radio_data_source_name(i, RADIO_SOURCE_SLEEP),
radio_option_name(i, RADIO_CORE_OPTION), EMVIEW_ENABLE);
emview_document_option_class
(mod, radio_option_name(i, RADIO_CORE_OPTION), "core",
"Indicates channel and sleep mode", NULL);
/* numeric traffic meter */
emview_assign_source(node, radio_box_name(i), EMVIEW_BOX_ABOVE,
radio_data_source_name(i, RADIO_SOURCE_BPS_RX),
radio_option_name(i, RADIO_NUM_TRAFFIC_OPTION), EMVIEW_ENABLE);
emview_assign_source(node, radio_box_name(i), EMVIEW_BOX_ABOVE,
radio_data_source_name(i, RADIO_SOURCE_BPS_TX),
radio_option_name(i, RADIO_NUM_TRAFFIC_OPTION), EMVIEW_ENABLE);
emview_document_option_class
(mod, radio_option_name(i, RADIO_NUM_TRAFFIC_OPTION), "numeric",
"Numerically Indicates the current traffic rate above node", NULL);
/* leds traffic meter */
emview_assign_source(node, radio_box_name(i), EMVIEW_BOX_FLAG1,
radio_data_source_name(i, RADIO_SOURCE_BPS_TX),
radio_option_name(i, RADIO_LEDS_TRAFFIC_OPTION), EMVIEW_ENABLE);
emview_assign_source(node, radio_box_name(i), EMVIEW_BOX_FLAG3,
radio_data_source_name(i, RADIO_SOURCE_BPS_RX),
radio_option_name(i, RADIO_LEDS_TRAFFIC_OPTION), EMVIEW_ENABLE);
emview_document_option_class
(mod, radio_option_name(i, RADIO_LEDS_TRAFFIC_OPTION), "leds",
"Indicates if there was radio activity in the last second", NULL);
return 0;
}
static
int radio_config_options(emview_module_t *mod, emview_module_inst_t *inst,
node_id_t node, parser_state_t *ps)
{
int i = inst->index;
/*
* parse enables and other config..
*/
while (misc_parse_next_kvp(ps) >= 0) {
if (strcmp(ps->key, "leds") == 0) {
emview_option_class_set_enable
(node, radio_option_name(i, RADIO_LEDS_TRAFFIC_OPTION), 1);
continue;
}
if (strcmp(ps->key, "numeric") == 0) {
emview_option_class_set_enable
(node, radio_option_name(i, RADIO_NUM_TRAFFIC_OPTION), 1);
continue;
}
if (strcmp(ps->key, "core") == 0) {
emview_option_class_set_enable
(node, radio_option_name(i, RADIO_CORE_OPTION), 1);
continue;
}
elog(LOG_WARNING, "Unexpected key: %s", ps->key);
}
return 0;
}
/*
* Main
*/
int radio_main(int *argc, char **argv)
{
emview_module_opts_t mod_opts = {
name: RADIO_MODULE_NAME,
description: "Displays a link device's status",
usage: "leds:numeric:core",
instance_data_length: sizeof(struct radio_state),
config_new_instance: radio_config_device,
config_assign: radio_config_assign,
config_opts: radio_config_options,
};
/* register with emview and get context structure */
mod = emview_register(&mod_opts);
return 0;
}
See more files for this project here