Code Search for Developers
 
 
  

hostmote_conf.c from EmStar at Krugle


Show hostmote_conf.c syntax highlighted

/* ex: set tabstop=8 expandtab shiftwidth=2 softtabstop=2: */

/*
 *
 * 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.
 *
 */
 

/*
 * basic configuration messages for host-mote protocol: reset, etc.
 *
 * $Id: hostmote_conf.c,v 1.40 2005/04/15 21:15:19 thanos Exp $
 */

char *hostmote_conf_id = "$Id: hostmote_conf.c,v 1.40 2005/04/15 21:15:19 thanos Exp $";

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include "hostmote_i.h"

#define MOTE_STATUS_TIMEOUT  5000


/****************************************************************/

static void convert_mac_int_to_string(uint8_t type, char *name);
static void convert_status_to_report(mote_conf_hdr_t *status, 
        mote_report *report);

/* Callback when the timeout expires from when we send a stat request
 * and when we expect to receive a response. */
static int stat_timeout_handler(void *data, int interval, g_event_t *ev)
{
  mote_state_t *m = (mote_state_t *) data;

  if (++m->not_responding > m->next_complaint) {
    elog(LOG_WARNING, "%s: Mote not responding, still trying...", MOTE(m));
    m->next_complaint += 1 + i_min(m->next_complaint, 100);
  }

    mote_configure(m, 1);

  return TIMER_DONE;
}


/*
 * Send a message to the mote asking it to send us status
 */
void mote_request_status(mote_state_t *m)
{
  hostmote_header hdr={0};

  elog(LOG_DEBUG(0), "%s: ***** Requesting mote status", MOTE(m));

  m->last_status_request = time(0);

  HOSTMOTE_SET_OP(HOSTMOTE_CONF, CONF_STAT, &hdr);
  if (mote_serial_send(m, &hdr, 0) < 0) {
    elog(LOG_WARNING, "%s: couldn't send status request to mote: %m", MOTE(m));
  } 
  
  /* set timeout in case we don't hear back */
  g_event_destroy(m->stat_timeout);
  g_timer_add(MOTE_STATUS_TIMEOUT, stat_timeout_handler, m, NULL, &m->stat_timeout);
}


/*
 * Send a message to the mote asking it to send us status
 */

#define COPY_AND_CHECK(field, flag) \
  do { if (m->request_set_##field) { \
    if (request.field != m->requested_conf.field) { \
      request.field = m->requested_conf.field; \
      request.set_flags |= flag; \
    } } } while(0)

void mote_configure(mote_state_t *m, int from_user)
{
  hostmote_header hdr={0};

  /* construct the status request */
//  mote_conf_hdr_t request = m->status;
  mote_conf_request_t request;
  request.set_flags = 0;

  request.saddr = m->report.saddr;
  request.pot = m->report.pot;
  request.lpl_tx = m->report.lpl_tx;
  request.lpl_rx = m->report.lpl_rx;
  
  /* copy over */
  COPY_AND_CHECK(saddr, CONF_SET_SADDR);
  COPY_AND_CHECK(pot, CONF_SET_POT);
  // this can be used with smac as well. smac will return the value
  // without doing anything
  COPY_AND_CHECK(lpl_tx, CONF_SET_LPL_TX_MODE);
  COPY_AND_CHECK(lpl_rx, CONF_SET_LPL_RX_MODE);

  if (request.set_flags || from_user) {
    buf_t *buf = buf_new();

    if (!from_user) {
      elog(LOG_WARNING, "Mote [%d] reported inconsistent info..."
          " reconfiguring!", m->index);
    }

    elog(LOG_DEBUG(0), "%s: ***** Sending mote configuration", MOTE(m));
    
    HOSTMOTE_SET_OP(HOSTMOTE_CONF, CONF_CONF, &hdr);
    
    /* construct the mote message: first the header, then conf struct */
    bufcpy(buf, &hdr, sizeof(hdr));
    bufcpy(buf, &request, sizeof(request));
    
    if (mote_serial_send(m, (hostmote_header *) buf->buf, 
                sizeof(request)) < 0) {
      elog(LOG_WARNING, "%s: couldn't send new configuration to mote: %m", 
          MOTE(m));
    } 
    
    buf_free(buf);

    /* set timeout in case we don't hear back */
    g_event_destroy(m->stat_timeout);
    g_timer_add(MOTE_STATUS_TIMEOUT, stat_timeout_handler, m, NULL, &m->stat_timeout);
  }

  else {
    elog(LOG_DEBUG(0), "%s: ***** Skipping mote configuration", MOTE(m));
  }
}



/*
 * Send a reset message to the mote
 */
void mote_reset(mote_state_t *m, uint8_t type)
{
  hostmote_header hdr={0};

  /* be sure we are awake */
  //sync_start(1);


  if (type!=SOFT_RESET && type!=HARD_RESET) {
      elog(LOG_ERR, "Unknown RESET type %d", type);
      return;
  }

  elog(LOG_DEBUG(0), "%s: ***** RESETTING MOTE (type=%d)", MOTE(m), type);

  HOSTMOTE_SET_OP(HOSTMOTE_RST, 0, &hdr);
  hdr.subop=type;

  if (mote_serial_send(m, &hdr, 0) < 0) {
    elog(LOG_ERR, "%s: can't reset mote: %m", MOTE(m));
  }

  m->report.pcCrcErrors=0;

  /* request status information from the mote */
  mote_request_status(m);

}


/*
 * Send a sleep message to the mote
 */
void mote_sleep(mote_state_t *m)
{
  m->asleep = 1;
  elog(LOG_WARNING, "%s: not *really* sleeping the mote", MOTE(m));

#if 0
  hostmote_header hdr;

  elog(LOG_DEBUG(0), "%s: ***** SLEEPING MOTE", MOTE(m));

  HOSTMOTE_SET_OP(HOSTMOTE_SLEEP, 0, &hdr);
  if (mote_serial_send(m, &hdr, 0) < 0) {
    elog(LOG_WARNING, "%s: couldn't sleep mote: %m", MOTE(m));
  } else {
    m->asleep = 1;
  }

#endif
}


/*
 * This function is called when a CONF message arrives from the mote.
 */
void mote_conf_input_handler(mote_state_t *m, hostmote_header *hdr, int datalen)
{
  mote_conf_hdr_t *mc = (mote_conf_hdr_t *)(hdr->data);

  if (m->status==NULL) {
    elog(LOG_ERR, "NULL status pointer!");
    // perhaps we should exit here
    return;
  }

  if (hdr->opnum != HOSTMOTE_CONF) {
    elog(LOG_ERR, "Got a non-CONF message (%d) but conf handler got to run?!",
        hdr->opnum);
    return;
  }

  if (HOSTMOTE_DATALEN(hdr)==0) {
    elog(LOG_ERR, "Got a 0-length conf packet!");
    return;
  }



  // first let's make sure our pointer has the type set
  if (m->status->type == 0) {
      // type hasn't been initialized yet. we set it now
      m->status->type = mc->type;

      switch (mc->type) {

        case BMAC_CONF:
          elog(LOG_NOTICE, "Mote [%d] says it's using BMAC", m->index);
          break;

        case SMAC_CONF:
          elog(LOG_NOTICE, "Mote [%d] says it's using SMAC", m->index);
          break;

        default:
          elog(LOG_ERR, "Mote [%d] sent invalid conf type %d", m->index,
              mc->type);
          return;
          break;
      }
  }

  // now let's make sure the type hasn't changed since the time we set it
  // this could happen if someone swapped motes...

  if (m->status->type != mc->type) {
      elog(LOG_WARNING, "Warning: mote conf type has changed!"
             " (got %d, had %d)", mc->type, m->status->type);
      // not sure what else we're supposed to do here
      m->status->type = mc->type;
  }

  if (datalen > m->alloc_conf_length) {
      elog(LOG_WARNING, "Warning: datalen is greater than conf"
             " allocated length (%d > %d)", datalen, m->alloc_conf_length);

      m->alloc_conf_length+=datalen;  //increase by datalen
      // realloc
      m->status = realloc(m->status, m->alloc_conf_length);
  }


  switch (HOSTMOTE_SUBOP(hdr)) {
  case CONF_SYNC:
    elog(LOG_WARNING, "%s: got unsupported CONF_SYNC message", MOTE(m));
    // mote_handle_sync_message(m, conf);
    /* fall through */
    // why fall through? it should break!
    break;
    

  case CONF_STAT:
    elog(LOG_DEBUG(0), "%s: **** Got STAT message", MOTE(m));
    memcpy(m->status, mc, datalen);
    // convert status to report here
    // we're using the values of report for other things so this is critical
    convert_status_to_report(m->status, &m->report);
    mote_configure(m, 0);
    g_status_dev_notify(m->status_ev);
    g_event_destroy(m->stat_timeout);
    if (m->not_responding) {
      m->not_responding = 0;
      m->next_complaint = 0;
      elog(LOG_WARNING, "%s: Mote OK", MOTE(m));
    }
    break;
  }

}


/*
 * when someone tries to open the status device, initiate a mote
 * status request.  Return 0, meaning don't allow the read to complete
 * until the status comes back.
 */
static int mote_status_open(status_context_t *info)
{
  mote_state_t *m = (mote_state_t *) sd_data(info);
  mote_request_status(m);
  return 0;
}


/*
 * Generate human-readable mote status when someone tries to cat
 * /dev/mote/status
 */


static int mote_status_printable(status_context_t *info, buf_t *buf)
{
  char name[128]={0};
  
  mote_state_t *m = (mote_state_t *) sd_data(info);


  convert_status_to_report(m->status, &m->report);
  convert_mac_int_to_string(m->status->type, name);

  switch (m->status->type) {

    case BMAC_CONF:

      bufprintf(buf,
	    "Current Mote Status:\n"
            "  MAC type=            %s\n"
            "  Version number=      [mote:%03d, pc:%03d]\n"
	    "  if id=               %04x [%6d] (%d.%d)\n"
            "  MTU=                 %03d\n"
	    "  pot=                 %u\n"
            "  LPL TX mode=         %u\n"
            "  LPL RX mode=         %u\n"
            "  Bytes sent=          %u\n"
            "  Packets sent=        %u\n"
            "  Bytes rcvd=          %u\n"
            "  Packets rcvd=        %u\n"
            "  Packet CRC errors=   %u\n"
            "  Packet Drops=        %u\n"
            "  Packet TX errors=    %u\n"
            "  Packets queued=      %d\n"
            "  Max queue size=      %d\n"
            "  PC->Mote CRC errors= %u\n"
            "  Mote->PC CRC errors= %u\n",

            name,

            m->report.version,
            HOSTMOTE_CURRENT_VERSION,

	    m->report.saddr,
	    m->report.saddr,
	    (m->report.saddr & 0xff00) >> 8,
	    (m->report.saddr & 0xff),

            m->report.mtu,

	    m->report.pot,
            m->report.lpl_tx,
            m->report.lpl_rx,
            m->report.txBytes,
            m->report.txPkts,
            m->report.rxBytes,
            m->report.rxPkts,
            m->report.pktCrcErrors,
            m->report.rxDrops,
            m->report.txErrors,
            m->report.pkts_queued,
            m->report.max_queue_size,
            m->report.serialCrcErrors,
            m->report.pcCrcErrors);

            break;

    case SMAC_CONF:

      bufprintf(buf,
        "Current Mote Status:\n"
        "  MAC type=            %s\n"
        "  Version number =     [mote:%03d, pc:%03d]\n"
        "  if id=               %04x [%6d] (%d.%d)\n"
        "  MTU=                 %03d\n"
        "  fault count=         %02x\n"
        "  pot=                 %u\n"
        "  TX packets=          %ud\n"
        "  TX errors=           %ud\n"
	"  RX packets=          %ud\n" /* arg 15 */
        "  RX drops=            %ud\n"
        "  MAC TX errors=       %ud\n"
        "  Sleep RX errors=     %ud\n"
        "  Length errors=       %ud\n"
	"  Pkt CRC errors=      %ud\n" /* arg 20 */
        "  Pkts queued=         %d\n"
        "  Max queue size=      %d\n"
        "  PC->Mote CRC errors= %ud\n"
        "  Mote->PC CRC errors= %ud\n"
	"  reTX packets=        %ud\n" /* arg 25 */
        "  Ctrl packets=        %ud\n"
        "  Neighbors=           %d\n"
        "  Schedules=           %d\n"
        "  MAC state=           %d\n"
	"  Radio state=         %d\n",  /* arg 30 */

        name,

        m->report.version,
        HOSTMOTE_CURRENT_VERSION,

        m->report.saddr,
	m->report.saddr,
        (m->report.saddr & 0xff00) >> 8,
        (m->report.saddr & 0xff),

        m->report.mtu,

        m->report.reset_count,
        m->report.pot,
        m->report.txPkts,
        m->report.txErrors,
        m->report.rxPkts,
        m->report.rxDrops,

        m->report.macTxErrors,
        m->report.sleepErrors,

        m->report.lenErrors,
        m->report.pktCrcErrors,
        m->report.pkts_queued,
        m->report.max_queue_size,
        m->report.serialCrcErrors,
        m->report.pcCrcErrors,
        m->report.retx,
	m->report.ctrlPkts,
	m->report.numNeighb,
	m->report.numSched,
	m->report.macState,
	m->report.radioState);

        break;

    default:
        elog(LOG_ERR, "Unknown conf type %d", m->status->type);
        break;
  }


  if (m->asleep)
    bufprintf(buf, "  Currently asleep\n");

  return STATUS_MSG_COMPLETE;
}


/*
 * Return the most recent mote status struct when someone tries to do
 * a binary read of it
 */
static int mote_status_binary(status_context_t *info, buf_t *buf)
{
  mote_state_t *m = (mote_state_t *) sd_data(info);

  convert_status_to_report(m->status, &m->report);

  bufcpy(buf, &m->report, sizeof(m->report));
  return STATUS_MSG_COMPLETE;
}


/******* Command Interface ********/



/*
 *  command interface
 */

char *mote_command_usage(void *data)
{
  return
    "Mote command interface:\n"
    "  address=0xXXXX:    Set address to specified hex value\n"
    "  address=DDDDD:     Set address to specified decimal value\n"
    "  pot=DDD:           Set mote power\n"
    "  pwr=0xXX:          Set radio power for chipcon radio (mica2+)\n"
    "  lpl_tx=D:          Set LPL TX mode\n"
    "  lpl_rx=D:          Set LPL RX mode\n"
    "  lpl=D:             Set LPL TX and RX mode\n"
    "  soft_reset:        Resets mote state but doesn't reboot mote\n"
    "  hard_reset:        Reboots mote\n"
    "\n";
}



/*
 *  argument processing macros
 */

#define CASE(str) \
  if ((strncmp(command, (str), strlen(str)) == 0) && \
      (args = command + strlen(str)))

#define NUMERIC_ARG(field, str, flag) \
do { \
  uint tmp; \
  if (strncmp(args, "0x", 2) == 0) { \
    if (1 != sscanf(args+2, "%x", &tmp)) { \
      fprintf(stderr, "Invalid %s %s\n", str, args); \
      break; \
    } \
  } \
  else { \
    if (1 != sscanf(args, "%u", &tmp)) { \
      fprintf(stderr, "Invalid %s %s\n", str, args); \
      break; \
    } \
  } \
  m->requested_conf.field = tmp; \
  m->request_set_##field = 1; \
} while (0)



static int mote_command_handler(char *command, size_t size, void *data)
{
  mote_state_t *m = (mote_state_t *) data;
  char *args = NULL;
  int reset = -1;
  int sleep = 0;
  int wake = 0;


  // parse command
  while (command && *command) {
    args = NULL;

    CASE("address=") {
      NUMERIC_ARG(saddr, "address", CONF_SET_SADDR);
    }

    CASE("pot=") {
      NUMERIC_ARG(pot, "pot", CONF_SET_POT);
    }

    CASE("pwr=") {
      NUMERIC_ARG(pot, "pwr", CONF_SET_PWR);
    }

    CASE("lpl_tx=") {
      NUMERIC_ARG(lpl_tx, "lpl_tx", CONF_SET_LPL_TX_MODE);
    }
    CASE("lpl_rx=") {
      NUMERIC_ARG(lpl_rx, "lpl_rx", CONF_SET_LPL_RX_MODE);
    }

    CASE("lpl=") {
      NUMERIC_ARG(lpl_tx, "lpl", CONF_SET_LPL_TX_MODE);
      NUMERIC_ARG(lpl_rx, "lpl", CONF_SET_LPL_RX_MODE);
    }

    CASE("soft_reset") {
      reset=SOFT_RESET;
    }

    CASE("hard_reset") {
        reset=HARD_RESET;
    }


    command = strpbrk(command, ":");
    if (command) command++;
  }


  if (wake) {
    //sync_start(1);
  }

  
  if (reset>-1) {
    mote_reset(m, reset);
  } else {
    mote_configure(m, 1);
  }

  if (sleep) {
    mote_sleep(m);
  }


  
  return EVENT_RENEW;
}




/*
 * Initialize the configuration-related pieces of hostmoted
 */
void mote_conf_init(mote_state_t *m)
{
  /* Options for the mote status device */
  status_dev_opts_t s_opts = {
    device: {
      device_info: m,
      devname: mote_name(m->index, MOTE_STATUS_DEV)
    },
    open:      mote_status_open,
    printable: mote_status_printable,
    binary:    mote_status_binary,
    no_read_on_open: 1
  };

  /* Options for the mote command device */
  cmd_dev_opts_t c_opts = {
    device: {
      device_info: m,
      devname: mote_name(m->index, MOTE_COMMAND_DEV)
    },
    command: mote_command_handler,
    usage:   mote_command_usage
  };

  /* Create the status device */
  if (g_status_dev(&s_opts, &m->status_ev) < 0) {
    elog(LOG_CRIT, "can't create status dev %s: %m", s_opts.device.devname);
    exit(1);
  }

  /* Create the command device */
  if (g_command_dev(&c_opts, &m->command_ev) < 0) {
    elog(LOG_CRIT, "can't create command dev %s: %m", c_opts.device.devname);
    exit(1);
  }
}


static void convert_status_to_report(mote_conf_hdr_t *status, 
        mote_report *report)
{
    // declare both pointers, we have stack space
    mote_bmac_conf_t *bmac_conf;
    mote_smac_conf_t *smac_conf;


    if (status==NULL || report==NULL) {
        elog(LOG_ERR, "NULL pointer!\n");
        return;
    }


    switch (status->type) {

        case BMAC_CONF:
            bmac_conf = (mote_bmac_conf_t *)status->data;

            report->conf_type = status->type;
            report->mtu=bmac_conf->mtu;
            report->version=bmac_conf->version;
            report->saddr=bmac_conf->saddr;
            report->pot=bmac_conf->pot;
            report->lpl_tx=bmac_conf->lpl_tx;
            report->lpl_rx=bmac_conf->lpl_rx;
            report->serialCrcErrors=bmac_conf->serialCrcErrors;
            report->txPkts=bmac_conf->txPkts;
            report->rxPkts=bmac_conf->rxPkts;
            report->txErrors=bmac_conf->txErrors;

            report->pktCrcErrors=bmac_conf->pktCrcErrors;
            report->txBytes=bmac_conf->txBytes;
            report->rxBytes=bmac_conf->rxBytes;
            report->rxDrops=bmac_conf->rxDrops;
            report->pkts_queued=bmac_conf->pkts_queued;
            report->max_queue_size=bmac_conf->max_queue_size;
            break;


        case SMAC_CONF:
            smac_conf = (mote_smac_conf_t *)status->data;

            report->conf_type = status->type;
            report->mtu=smac_conf->mtu;
            report->version=smac_conf->version;
            report->saddr=smac_conf->saddr;
            report->pot=smac_conf->pot;
            report->lpl_tx=smac_conf->lpl_tx;
            report->lpl_rx=smac_conf->lpl_rx;
            report->serialCrcErrors=smac_conf->serialCrcErrors;
            report->txPkts=smac_conf->txPkts;
            report->rxPkts=smac_conf->rxPkts;
            report->txErrors=smac_conf->txErrors;



            report->reset_count=smac_conf->fault;
            report->rxDrops=smac_conf->rxDrops;
            report->lenErrors=smac_conf->lenErrors;
            report->pktCrcErrors=smac_conf->crcErrors;
            report->retx=smac_conf->retx;
            report->ctrlPkts=smac_conf->ctrlPkts;
            report->numNeighb=smac_conf->numNeighb;
            report->numSched=smac_conf->numSched;
            report->macState=smac_conf->macState;
            report->radioState=smac_conf->radioState;
            report->sleepErrors=smac_conf->sleepErrors;
            report->macTxErrors=smac_conf->macTxErrors;
            report->pkts_queued=smac_conf->pkts_queued;
            report->max_queue_size=smac_conf->max_queue_size;

            break;


        default:
            elog(LOG_ERR, "Unkwown conf type %d", status->type);
            break;
    }
    


}



static void convert_mac_int_to_string(uint8_t type, char *name)
{
  if (name==NULL) {
    elog(LOG_ERR, "NULL name pointer");
    return;
  }

  switch (type) {

    case BMAC_CONF:
      sprintf(name, "B-MAC");
      break;

    case SMAC_CONF:
      sprintf(name, "S-MAC");
      break;

    default:
      elog(LOG_ERR, "Invalid type %d", type);
      sprintf(name, "INVALID");
      break;
  }

}





See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  hostmote_ceiling.c
  hostmote_conf.c
  hostmote_i.h
  hostmote_main.c
  hostmote_reprog.c
  hostmote_serial.c
  hostmote_sync.c
  hostmote_upper.c