SNMP agent attached to SPI slave

Dependencies:   mbed

lwip/core/snmp/private_mib.c

Committer:
lorcansmith
Date:
2012-08-13
Revision:
0:2a53a4c3238c
Child:
2:25e12a7fe0aa

File content as of revision 0:2a53a4c3238c:

/*****************************************************************************
*                   Copyright Field Electronics Ltd
* File:             private_mib.c
* Reference:        3000-A3600-SRC-private_mib
* Content:          Header file for private MIB tree structures
* Version:          1.6
* System:           mbed gnu compiler
* Target Hardware:  mbed LPC1768                                  
* Amendment Record:    
* Author:      L. Smith for all versions unless otherwise specified
* Initial release
* 0.1         23/11/11: L. Smith
  Derived from snmp_structs.h by Christiaan Simons <christiaan.simons@axon.tv>
* 0.2         28/11/11: L. Smith
  Add f3k_cpu_version & f3k_mbed_version to scalar values 
* 0.3         01/12/11: L. Smith
  Replace lwIP SNMP_ENTERPRISE_ID by Field PEN - see http://www.iana.org/assignments/enterprise-numbers
* 0.4         13/12/11: L. Smith
  Increase function calls for number of I/O nodes to 32 
* 0.5         21/12/11: L. Smith
  Increase f3k_system nodes from 3 to 5
* 0.6         22/12/11: L. Smith
  Add f3k_comms_set_value() and f3k_comms_set_test() to enable UID change
* 0.7         27/12/11: L. Smith
  Add f3k_sys_set_value() and f3k_sys_set_test() to enable UID change
* 0.8         29/12/11: L. Smith
  Update f3k_sys_set_value() and f3k_sys_set_test() to enable net address change
* 0.9         30/12/11: L. Smith
  Read least sig. (alternate) bytes from I/O channels in snmp_get_f3k_IO_value()
* 1.0         11/01/12: L. Smith
  Add breaks in case statement to fix f3k_speed reporting error
* 1.1         30/01/12: L. Smith
  Add f3k_SPI_count as f3k_sys_object 5 before f3k_run_scan
* 1.2         02/05/12: L. Smith
  Change pointers for RTU unit ID from s32_t to u16_t
* 1.3         19/06/12: L. Smith
  Add f3k_IO_mask as R/W f3k_sys_object 7 - hex formatted string
* 1.4         20/06/12: L. Smith
  Add snmp_trh_addrs[4] as R/W f3k_comms 8 - trap host SNMP_ASN1_IPADDR
* 1.5         25/07/12: L. Smith
  Add snmp_publiccommunity as 9th f3k_comms variable with R/W ability
* 1.6         08/08/12: L. Smith
  Add f3k_IO_alarm & f3k_al_mask nodes for I/O alarm strings
*******************************************************************************/

#include "lwip/opt.h"

#if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */

#include <stdlib.h>
#include <string.h>

#include "lwip/snmp.h"
#include "lwip/udp.h"
#include "lwip/snmp_asn1.h"
#include "lwip/snmp_structs.h"
#include "lwip/snmp_msg.h"
#include "IO_file.h"
#include "private_mib.h"

/* mib_f3k integers derived from 3000 CPU */
static u16_t f3k_error = 0,
             f3k_num_cards = 0,
             f3k_SPI_count = 0,
             f3k_run_scan = 0,
             f3k_uid = 0,
             f3k_protocol = 0;
static u32_t f3k_speed  = 0;
static char f3k_fw_version[ 4 ] = {0,0,0,0};
/* v1.3: I/O mask is read/written in SNMP protocol as 8 byte hex string */
static char f3k_IO_mask[ 8 ] = {0,0,0,0,0,0,0,0};

/* lengths of ethernet address strings */
static u16_t snmp_ip_len = 0,
             snmp_net_len = 0,
             snmp_gwy_len = 0,
             snmp_trh_len = 0,
             snmp_dns_len = 0;
/* ethernet address strings */
static char snmp_ip_addrs[ 16 ] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static char snmp_net_mask[ 16 ] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static char snmp_gwy_addrs[ 16 ] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static char snmp_dns_addrs[ 16 ] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
static char snmp_trh_addrs[ 16 ] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
//static char snmp_trh_addrs[ 4 ] = {0,0,0,0};    // v1.4: Trap host address


static void f3k_amask_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
static void f3k_amask_get_value(struct obj_def *od, u16_t len, void *value);
static u8_t f3k_amask_set_test(struct obj_def *od, u16_t len, void *value);
static void f3k_amask_set_value(struct obj_def *od, u16_t len, void *value);
static void f3k_alarm_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
static void f3k_alarm_get_value(struct obj_def *od, u16_t len, void *value);
static u8_t f3k_alarm_set_test(struct obj_def *od, u16_t len, void *value);
static void f3k_alarm_set_value(struct obj_def *od, u16_t len, void *value);
static void f3k_IO_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
static void f3k_IO_get_value(struct obj_def *od, u16_t len, void *value);
static void f3k_comms_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
static void f3k_comms_get_value(struct obj_def *od, u16_t len, void *value);
static u8_t f3k_comms_set_test(struct obj_def *od, u16_t len, void *value);
static void f3k_comms_set_value(struct obj_def *od, u16_t len, void *value);
static void f3k_sys_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
static void f3k_sys_get_value(struct obj_def *od, u16_t len, void *value);
static u8_t f3k_sys_set_test(struct obj_def *od, u16_t len, void *value);
static void f3k_sys_set_value(struct obj_def *od, u16_t len, void *value);
void snmp_get_f3k_data( void );
u32_t snmp_get_f3k_IO_value( u8_t index );
void snmp_update_net_addrs( void );
int update_addrs_from_string( char * adrs_str, unsigned char * num_array );

/* the following routines are not used as no tables are used for F3000  
static void f3kentry_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od);
static void f3kentry_get_value(struct obj_def *od, u16_t len, void *value);

// mib_f3k .1.3.6.1.4.1.SNMP_ENTERPRISE_ID 
// index root node for f3kTable
struct mib_list_rootnode f3k_root = {
  &f3kentry_get_object_def,
  &f3kentry_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_LR,
  0,
  NULL,
  NULL,
  0
};

const s32_t f3kentry_ids[2] = { 1, 2 };
struct mib_node* const f3kentry_nodes[2] = {
  (struct mib_node*)&f3k_root, (struct mib_node*)&f3k_root,
};
const struct mib_array_node f3kentry = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  2,
  f3kentry_ids,
  f3kentry_nodes
};

s32_t f3ktable_id = 1;
struct mib_node* f3ktable_node = (struct mib_node*)&f3kentry;
struct mib_ram_array_node f3ktable = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_RA,
  0,
  &f3ktable_id,
  &f3ktable_node
};
*/

/* f3k_al_mask nodes */
const mib_scalar_node f3k_amask_scalar = {
  &f3k_amask_get_object_def,
  &f3k_amask_get_value,
  &f3k_amask_set_test,
  &f3k_amask_set_value,
  MIB_NODE_SC,
  0
};

const s32_t f3k_amask_ids[MAX_ALARM_ID] = { 1, 2, 3, 4, 5, 6, 7, MAX_ALARM_ID };
struct mib_node* const f3k_amask_nodes[MAX_ALARM_ID] = {
  (struct mib_node*)&f3k_amask_scalar, (struct mib_node*)&f3k_amask_scalar,
  (struct mib_node*)&f3k_amask_scalar, (struct mib_node*)&f3k_amask_scalar,
  (struct mib_node*)&f3k_amask_scalar, (struct mib_node*)&f3k_amask_scalar,
  (struct mib_node*)&f3k_amask_scalar, (struct mib_node*)&f3k_amask_scalar
};

/* v1.6: f3k_al_mask .1.3.6.1.4.1.SNMP_ENTERPRISE_ID.mib_f3k */
const struct mib_array_node f3k_al_mask = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  MAX_ALARM_ID,
  f3k_amask_ids,
  f3k_amask_nodes
};


/* f3k_IO_alarm nodes */
const mib_scalar_node f3k_alarm_scalar = {
  &f3k_alarm_get_object_def,
  &f3k_alarm_get_value,
  &f3k_alarm_set_test,
  &f3k_alarm_set_value,
  MIB_NODE_SC,
  0
};

const s32_t f3k_alarm_ids[MAX_ALARM_ID] = { 1, 2, 3, 4, 5, 6, 7, MAX_ALARM_ID };
struct mib_node* const f3k_alarm_nodes[MAX_ALARM_ID] = {
  (struct mib_node*)&f3k_alarm_scalar, (struct mib_node*)&f3k_alarm_scalar,
  (struct mib_node*)&f3k_alarm_scalar, (struct mib_node*)&f3k_alarm_scalar,
  (struct mib_node*)&f3k_alarm_scalar, (struct mib_node*)&f3k_alarm_scalar,
  (struct mib_node*)&f3k_alarm_scalar, (struct mib_node*)&f3k_alarm_scalar
};

/* v1.6: f3k_IO_alarm .1.3.6.1.4.1.SNMP_ENTERPRISE_ID.mib_f3k */
const struct mib_array_node f3k_IO_alarm = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  MAX_ALARM_ID,
  f3k_alarm_ids,
  f3k_alarm_nodes
};


/* f3k_IO nodes */
const mib_scalar_node f3k_IO_scalar = {
  &f3k_IO_get_object_def,
  &f3k_IO_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_SC,
  0
};

const s32_t f3k_IO_ids[32] = { 1, 2, 3, 4, 5, 6, 7, 8, 
                               9, 10, 11, 12, 13, 14, 15, 16, 
                               17, 18, 19, 20, 21, 22, 23, 24,
                               25, 26, 27, 28, 29, 30, 31, 32 };
struct mib_node* const f3k_IO_nodes[32] = {
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar, 
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar,
  (struct mib_node*)&f3k_IO_scalar, (struct mib_node*)&f3k_IO_scalar
};
/* v0.3: f3k_IO .1.3.6.1.4.1.SNMP_ENTERPRISE_ID.mib_f3k */
const struct mib_array_node f3k_IO = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  32,
  f3k_IO_ids,
  f3k_IO_nodes
};


/* f3k_comms nodes */
const mib_scalar_node f3k_comms_scalar = {
  &f3k_comms_get_object_def,
  &f3k_comms_get_value,
  &f3k_comms_set_test,
  &f3k_comms_set_value,
  MIB_NODE_SC,
  0
};

const s32_t f3k_comms_ids[MAX_COMMS_ID] = { 1, 2, 3, 4, 5, 6, 7, 8, MAX_COMMS_ID };
struct mib_node* const f3k_comms_nodes[MAX_COMMS_ID] = {
  (struct mib_node*)&f3k_comms_scalar, (struct mib_node*)&f3k_comms_scalar,
  (struct mib_node*)&f3k_comms_scalar, (struct mib_node*)&f3k_comms_scalar,
  (struct mib_node*)&f3k_comms_scalar, (struct mib_node*)&f3k_comms_scalar,
  (struct mib_node*)&f3k_comms_scalar, (struct mib_node*)&f3k_comms_scalar,
  (struct mib_node*)&f3k_comms_scalar
};
/* v0.3: f3k_comms .1.3.6.1.4.1.SNMP_ENTERPRISE_ID.mib_f3k */
const struct mib_array_node f3k_comms = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  MAX_COMMS_ID,
  f3k_comms_ids,
  f3k_comms_nodes
};


/* f3k_system nodes */
const mib_scalar_node f3k_sys_scalar = {
  &f3k_sys_get_object_def,
  &f3k_sys_get_value,
  &f3k_sys_set_test,
  &f3k_sys_set_value,
  MIB_NODE_SC,
  0
};

const s32_t f3k_sys_ids[7] = { 1, 2, 3, 4, 5, 6, 7 };
struct mib_node* const f3k_sys_nodes[7] = {
  (struct mib_node*)&f3k_sys_scalar, (struct mib_node*)&f3k_sys_scalar,
  (struct mib_node*)&f3k_sys_scalar, (struct mib_node*)&f3k_sys_scalar,
  (struct mib_node*)&f3k_sys_scalar, (struct mib_node*)&f3k_sys_scalar,
  (struct mib_node*)&f3k_sys_scalar 
  /*, (struct mib_node*)&f3ktable */
};
/* v0.3: f3k_system .1.3.6.1.4.1.SNMP_ENTERPRISE_ID.mib_f3k */
const struct mib_array_node f3k_system = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  7,
  f3k_sys_ids,
  f3k_sys_nodes
};

/* 1.6  Add f3k_IO_alarm & f3k_al_mask nodes for I/O alarm strings */
const s32_t f3k_ids[5] = { 1, 2, 3, 4, 5 };
struct mib_node* const f3k_nodes[5] = {
  (struct mib_node*)&f3k_system,
  (struct mib_node*)&f3k_comms,
  (struct mib_node*)&f3k_IO,
  (struct mib_node*)&f3k_IO_alarm,
  (struct mib_node*)&f3k_al_mask
};
/* v0.3: mib_f3k .1.3.6.1.4.1.SNMP_ENTERPRISE_ID */
/* f3k private node called from mib_array_node mib_link */
const struct mib_array_node mib_f3k = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  5,
  f3k_ids,
  f3k_nodes
};


/* link from enterprises node to SNMP system calls via mib_private */
/* v0.2: SNMP_ENTERPRISE_ID .1.3.6.1.4.1 
const s32_t private_ids[1] = { SNMP_ENTERPRISE_ID };
struct mib_node* const private_nodes[1] = { (struct mib_node*)&mib_f3k };
const struct mib_array_node mib_enterprise = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  1,
  private_ids,
  private_nodes
};
*/

/* internet .1.3.6.1 */
/* When using a private MIB, you have to create a file 'private_mib.h' that contains
 * a 'struct mib_array_node mib_private' which contains your MIB. 
s32_t internet_ids[2] = { 2, 4 };
struct mib_node* const internet_nodes[2] = { (struct mib_node*)&mgmt, (struct mib_node*)&mib_private };
const struct mib_array_node internet = {
  &noleafs_get_object_def,
  &noleafs_get_value,
  &noleafs_set_test,
  &noleafs_set_value,
  MIB_NODE_AR,
  2,
  internet_ids,
  internet_nodes
};
*/


/****************************************************************************/ 
/*              snmp_get_f3k_data: 
* Description:  Updates SNMP data from data array written by F3000 SPI
*               Called by f3k_sys_get_value()
* Parameters:   NONE
* Returns:      NONE
*/
/****************************************************************************/ 
void snmp_get_f3k_data(void)
{
u8_t comm_cfg;
u8_t f3k_version;

  f3k_error = fsvr.get_error();
  f3k_num_cards = (u16_t)fsvr.get_byte( NUM_CARD_IDX );
  f3k_SPI_count = fsvr.get_SPI_count();
  f3k_run_scan = (u16_t)fsvr.get_byte( RUN_SCAN_IDX );
  strncpy( f3k_IO_mask, get_hex_mask( mask4_IO_registers ), 8 );  // v1.3: copy mask4_IO_registers as hex
  f3k_uid  = (u16_t)fsvr.get_byte( UNIT_ID_IDX );
  comm_cfg  = (u8_t)fsvr.get_byte( COMMS_IDX );
  f3k_protocol  = (u16_t)(comm_cfg / 16);
  switch (comm_cfg & 0x0f)
  {
      case    2    :  
          f3k_speed  = 600;
          break;
      case    3    : 
          f3k_speed  = 1200;
          break;
      case    4    : 
          f3k_speed  = 2400;
          break;
      case    5    : 
          f3k_speed  = 4800;
          break;
      case    6    : 
          f3k_speed  = 9600;
          break;
      case    7    : 
          f3k_speed  = 19200;
          break;
      case    8    : 
          f3k_speed  = 38400;
          break;
      case    9    : 
          f3k_speed  = 76800;
          break;
      default    : 
          f3k_speed  = 9600;
          break;
  }
  f3k_version = (u8_t)fsvr.get_byte( VERSION_IDX );
  f3k_fw_version[0] = (f3k_version / 16) + '0'; 
  f3k_fw_version[1] = '.';
  if ( (f3k_version & 0xf) < 0xa )
  {
    f3k_fw_version[2] = (f3k_version & 0xf) + '0';
  }
  else 
  {
    f3k_fw_version[2] = (f3k_version & 0xf) - 0xa + 'A';
  }
}

/****************************************************************************/ 
/*              snmp_get_f3k_IO_value: 
* Description:  Updates SNMP data from I/O data in array written by F3000 SPI
*               Called by f3kentry_get_value()
* Parameters:   IN: u8_t 1-based index into 0-based Field SPI server array
* Returns:      u32_t io_value from Field SPI server array
*/
/****************************************************************************/ 
u32_t snmp_get_f3k_IO_value( u8_t index )
{
unsigned short io_value;

  index = index > 0 ?  2 * (index - 1) : index; // index range is 1 to 32
  io_value = 256 * fsvr.get_byte( index );  // v0.9: read ms byte from I/O
  io_value += fsvr.get_byte( index + 1 );   // v0.9: add ls byte from I/O
  return (u32_t)io_value; 
}

/****************************************************************************/ 
/*              snmp_update_net_addrs: 
* Description:  Updates SNMP address strings from ethernet addresses
*               v1.4: Add trap host address conversion
*               Called by f3k_comms_get_object_def()
* Parameters:   NONE
* Returns:      NONE
*/
/****************************************************************************/ 
void snmp_update_net_addrs( void )
{
char i;

  for ( i = 0; i < 16; i++ )
  {                                 // ensure string terminated by 0
    snmp_ip_addrs[ i ] = 0;
    snmp_net_mask[ i ] = 0;
    snmp_gwy_addrs[ i ] = 0;
    snmp_dns_addrs[ i ] = 0;
    snmp_trh_addrs[ i ] = 0;
  }
  sprintf( snmp_ip_addrs, "%d.%d.%d.%d", ip_ad[0], ip_ad[1], ip_ad[2], ip_ad[3] );
  snmp_ip_len = strlen( snmp_ip_addrs );
  sprintf( snmp_net_mask, "%d.%d.%d.%d", msk_ad[0], msk_ad[1], msk_ad[2], msk_ad[3] );
  snmp_net_len = strlen( snmp_net_mask );
  sprintf( snmp_gwy_addrs, "%d.%d.%d.%d", gwy_ad[0], gwy_ad[1], gwy_ad[2], gwy_ad[3] );
  snmp_gwy_len = strlen( snmp_gwy_addrs );
  sprintf( snmp_dns_addrs, "%d.%d.%d.%d", dns_ad[0], dns_ad[1], dns_ad[2], dns_ad[3] );
  snmp_dns_len = strlen( snmp_dns_addrs );
  sprintf( snmp_trh_addrs, "%d.%d.%d.%d", th_ad[0], th_ad[1], th_ad[2], th_ad[3] );
  snmp_trh_len = strlen( snmp_trh_addrs );  
/*  for ( i = 0; i < 4; i++ )
  {                                 // copy IP addresses to string
    snmp_trh_addrs[ i ] = th_ad[ i ];
  } */
}

/****************************************************************************/ 
/*              update_addrs_from_string: 
* Description:  Reads data from adrs_str into num_array
* Globals used: NONE 
* Parameters:   IN: char * adrs_str
*               OUT: unsigned char * num_array
* Returns:      Returns set_ok = 1 if able to set value, 0 otherwise
*/
/****************************************************************************/ 
int update_addrs_from_string( char * adrs_str, unsigned char * num_array )
{
unsigned char c, i, j, digit_found, number_completed;
int set_ok, new_num;

  set_ok = 1;                       // default is good value
  new_num = 0;
  i = j = 0;
  number_completed = digit_found = false;
  while ( ((c = adrs_str[ i ]) != 0) && (i++ < 16) )
  {
      num_array[ j ] = 0;
      if ( c < '0' || c > '9' )
      {                             // not a numeric character
        if ( digit_found )
        {
          number_completed = true;
        }
      }
      else                          // numeric character
      {
        digit_found = true;
        if ( number_completed )
        {                           // test for valid data
          if ( (new_num <= 255) && (j < 4) )
          {                         // save number into array
            num_array[ j++ ] = new_num;
          }
          else
          {
            set_ok = 0;
            break;
          }
          new_num = 0;
        }
        new_num = 10*new_num + c - '0';
        number_completed = false;
      } // else numeric character
  } // end while
  if ( number_completed || (c == 0) )
  {                                 // test for valid data
      if ( (new_num <= 255) && (j < 4) && (i <= 16) )
      {                             // save last number into array
        num_array[ j ] = new_num;
      }
      else
      {
        set_ok = 0;
      }
  }
  return set_ok;  
}


/****************************************************************************/ 
/*              f3k_sys_get_object_def: 
* Description:  get definition for F3000 scalar objects
*               Called via mib_scalar_node f3k_sys_scalar
* Parameters:   IN: u8_t ident_len - length of ID in...
*               IN: s32_t *ident - array holding ID
*               OUT: struct obj_def *od - object definition found
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_sys_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
u8_t id;

  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 7));
  if ((ident_len == 2) &&
      (ident[0] > 0) && (ident[0] <= MAX_PRIVATE_ID))
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;

    id = (u8_t)ident[0];
//    printf("\r\nf3k_sys_get_object_def: ident_len %d, id %d\r\n", ident_len, id);
    switch (id)
    {
      case 1: /* f3k_fw_version */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = 3; 
        break;
      case 2: /* snmp_fw_version */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = 4; 
        break;
      case 3: /* f3k_error */
      case 4: /* f3k_num_cards */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
        od->v_len = sizeof(u32_t);
        break;
      case 5: /* f3k_SPI_count */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE);
        od->v_len = sizeof(u32_t);
        break;
      case 6: /* f3k_run_scan */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
        od->v_len = sizeof(u32_t);
        break;
      case 7: /* v1.3: f3k_IO_mask */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = 8; 
        break;
    } // end switch
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("f3k_sys_get_object_def: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}

/****************************************************************************/ 
/*              f3k_sys_get_value: 
* Description:  Returns f3k scalar object value
*               @param ident points to objectname.0 (object id trailer)
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes)
*               OUT: void *value - points to (varbind) space to copy value into
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_sys_get_value(struct obj_def *od, u16_t len, void *value)
{
  u32_t *uint_ptr = (u32_t*)value;
  u8_t *uchr_ptr = (u8_t*)value;
  u8_t id;
  u8_t i = 0;               // character pointer for copying unterminated strings

  LWIP_UNUSED_ARG(len);
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_PRIVATE_ID));
  snmp_get_f3k_data();                  // read the data from the SPI array
  id = (u8_t)od->id_inst_ptr[0];
  switch ( id )
  {
    case 1: /* f3k_fw_version */
      while (i < len) {
        *(uchr_ptr++) = f3k_fw_version[ i++ ];
      }
      break;
    case 2: /* snmp_fw_version */
      while (i < len) {
        *(uchr_ptr++) = snmp_fw_version[ i++ ];
      }
      break;
    case 3: /* f3k_error */
      *uint_ptr = f3k_error;
      break;
    case 4: /* f3k_num_cards */
      *uint_ptr = f3k_num_cards;
      break;
    case 5: /* f3k_SPI_count */
      *uint_ptr = f3k_SPI_count;
      break;
    case 6: /* f3k_run_scan */
      *uint_ptr = f3k_run_scan;
      break;
    case 7: /* v1.3: f3k_IO_mask */
      while (i < len) {
        *(uchr_ptr++) = f3k_IO_mask[ i++ ];
      }
      break;
  }
}

/****************************************************************************/ 
/*              f3k_sys_set_test: 
* Description:  Test f3k_ object value before setting
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      Returns set_ok = 1 if able to set value, 0 otherwise
*/
/****************************************************************************/ 
static u8_t
f3k_sys_set_test(struct obj_def *od, u16_t len, void *value)
{
  u8_t id, set_ok;
  u8_t i = 0;               
  u8_t * uc_ptr  = (u8_t*)value;        // char pointer to first byte in value
  
  LWIP_UNUSED_ARG(len);
  set_ok = 0;
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 7));
  id = (u8_t)od->id_inst_ptr[0];
//  printf("\r\nf3k_sys_set_test:  id %d\r\n", id);
  if ( id == 6 )
  {                                 /* f3k_run_scan */
    s32_t *sint_ptr = (s32_t*)value;

    if ( (*sint_ptr == 0) || (*sint_ptr == 1) )
    {
        set_ok = 1;
    }
  }
  else if ( id == 7 )
  {                                 /* v1.3: f3k_IO_mask */
    if ( len <= 8 )
    {                               // ensure all digits are hexadecimal
        set_ok = 1;
        for ( i = 0; i < len; i++ )
        {
          if ( !isxdigit( *(uc_ptr++) ) )
          {
            set_ok = 0;             // invalid hexadecimal digit
            break;                  // so quit
          }
        } 
    }
  }
  return set_ok;
}

/****************************************************************************/ 
/*              f3k_sys_set_value: 
* Description:  Returns f3k scalar object value
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_sys_set_value(struct obj_def *od, u16_t len, void *value)
{
  u8_t id;
  u8_t * uc_ptr  = (u8_t*)value;        // char pointer to first byte in value

//  LWIP_UNUSED_ARG(len);
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 7));
  id = (u8_t)od->id_inst_ptr[0];
  if ( id == 6 )
  {                                     /* f3k_run_scan */
    cmd_buf[ RUN_SCAN_CMD ] = *uc_ptr;
    cmd_buf[ 0 ] = cmd_buf[ RUN_SCAN_CMD ];  // tell the 3000 cpu  data available
    new_cmd_idx = RUN_SCAN_CMD;
    fsvr.put_byte( RUN_SCAN_IDX, cmd_buf[ RUN_SCAN_CMD ] );
  }
  else if ( id == 7 )
  {                                     /* v1.3: f3k_IO_mask */
    mask4_IO_registers = convert2decimal( uc_ptr, len );
    net_addrs_set = true;               // save mask to file system
  }
}


/****************************************************************************/ 
/*              f3k_comms_get_object_def: 
* Description:  get definition for F3000 scalar objects
*               Called via mib_scalar_node f3k_comms_scalar
* Parameters:   IN: u8_t ident_len - length of ID in...
*               IN: s32_t *ident - array holding ID
*               OUT: struct obj_def *od - object definition found
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_comms_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
u8_t id;
  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
  if ((ident_len == 2) &&
      (ident[0] > 0) && (ident[0] <= MAX_COMMS_ID)) // v1.5: change from MAX_PRIVATE_ID
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;
    id = (u8_t)ident[0];
//    printf("\r\nf3k_comms_get_object_def: ident_len %d, id %d\r\n", ident_len, id);
    snmp_update_net_addrs();
    switch (id)
    {
      case 1: /* RTU unit ID */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
        od->v_len = sizeof(u16_t);      // v1.2: changed from u32_t
        break;
      case 2: /* RTU baud rate */
      case 3: /* RTU protocol */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_ONLY;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG);
        od->v_len = sizeof(u16_t);      // v1.2: changed from u32_t
        break;
      case 4: /* IP address */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = snmp_ip_len; 
        break;
      case 5: /* net mask */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = snmp_net_len; 
        break;
      case 6: /* Gateway address */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = snmp_gwy_len; 
        break;
      case 7: /* DNS address */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = snmp_dns_len; 
        break;
      case 8: /* v1.4: Trap host address */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = snmp_trh_len; 
        break;
       case 9: /* v1.5: community string */
        od->instance = MIB_OBJECT_SCALAR;
        od->access = MIB_OBJECT_READ_WRITE;
        od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
        od->v_len = strlen(snmp_publiccommunity); 
        break;
   }  // end switch
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("f3k_comms_get_object_def: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}

/****************************************************************************/ 
/*              f3k_comms_get_value: 
* Description:  Returns f3k scalar object value
*               @param ident points to objectname.0 (object id trailer)
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes)
*               OUT: void *value - points to (varbind) space to copy value into
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_comms_get_value(struct obj_def *od, u16_t len, void *value)
{
  u32_t *uint_ptr = (u32_t*)value;
  u8_t * uchr_ptr = (u8_t*)value;
  u8_t id;
  u8_t i = 0;

  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_COMMS_ID));
  snmp_get_f3k_data();                  // read the data from the SPI array
  id = (u8_t)od->id_inst_ptr[0];
  switch (id)
  {
    case 1: /* RTU unit ID */
      *uint_ptr = f3k_uid;
      break;
    case 2: /* RTU baud rate */
      *uint_ptr = f3k_speed;
      break;
    case 3: /* RTU protocol */
      *uint_ptr = f3k_protocol;
      break;
    case 4: /* IP address */
      while (i < len) {
        *(uchr_ptr++) = snmp_ip_addrs[ i++ ];
      }
      break;
    case 5: /* net mask */
      while (i < len) {
        *(uchr_ptr++) = snmp_net_mask[ i++ ];
      }
      break;
    case 6: /* Gateway address */
      while (i < len) {
        *(uchr_ptr++) = snmp_gwy_addrs[ i++ ];
      }
      break;
    case 7: /* DNS address */
      while (i < len) {
        *(uchr_ptr++) = snmp_dns_addrs[ i++ ];
      }
      break;
    case 8: /* v1.4: Trap host address */
      while (i < len) {
        *(uchr_ptr++) = snmp_trh_addrs[ i++ ];
      }
    case 9: /* v1.5: community string */
      while (i < len) {
        *(uchr_ptr++) = snmp_publiccommunity[ i++ ];
      }
      break;
  }
}

/****************************************************************************/ 
/*              f3k_comms_set_test: 
* Description:  Test f3k_comms object value before setting
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      Returns set_ok = 1 if able to set value, 0 otherwise
*/
/****************************************************************************/ 
static u8_t
f3k_comms_set_test(struct obj_def *od, u16_t len, void *value)
{
u8_t id, set_ok, i;
u8_t * uc_ptr;
u16_t *uint_ptr = (u16_t*)value;  // v1.2: changed from s32_t
char test_addrs[16];
unsigned char test_ad[4];

  set_ok = i = 0;
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_COMMS_ID));
  uc_ptr  = (u8_t*)value;               // char pointer to first byte in value
  id = (u8_t)od->id_inst_ptr[0];
//  printf("\r\nf3k_comms_set_test: id %d, len %d\r\n", id, len);
  switch ( id ) 
  {
    case 1: /* RTU unit ID */
      if ( *uint_ptr < 255 )
      {
        set_ok = 1;
      }
      break;
    case 4: /* IP address */
    case 5: /* net mask */
    case 6: /* Gateway address */
    case 7: /* DNS address */
    case 8: /* v1.4: Trap host address */
      if ( len <= 16 )
      {
        while ( i < 16 ) 
        {
          test_addrs[ i++ ] =  i < len ? *(uc_ptr++) : 0;
        }
        set_ok = update_addrs_from_string( test_addrs, test_ad );
      }
      break;
    case 9: /* v1.5: community string */
      if ( (len >= MIN_COMMUNITY) && (len < MAX_COMMUNITY) )
      {
        set_ok = 1;
        while ( i++ < MAX_COMMUNITY ) 
        {
          if ( *(uc_ptr++) == ' ' )
          {
            set_ok = 0;             // no spaces allowed in community string
          }
        }
      }
      break;
  }  // end switch
  return set_ok;
}

/****************************************************************************/ 
/*              f3k_comms_set_value: 
* Description:  Returns f3k scalar object value
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_comms_set_value(struct obj_def *od, u16_t len, void *value)
{
  u8_t id, i;
  u8_t * uc_ptr;

  i = 0;
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_COMMS_ID));
  uc_ptr  = (u8_t*)value;               // char pointer to first byte in value
  id = (u8_t)od->id_inst_ptr[0];
  switch (id)
  {
    case 1: /* RTU unit ID */
      cmd_buf[ UNIT_ID_CMD ] = *uc_ptr;
      cmd_buf[ 0 ] = cmd_buf[ UNIT_ID_CMD ]; // tell the 3000 cpu data available
      new_cmd_idx = UNIT_ID_CMD;
      fsvr.put_byte( UNIT_ID_IDX, cmd_buf[ UNIT_ID_CMD ] );
      break;
    case 4: /* IP address */
      while ( i < 16 ) {
        snmp_ip_addrs[ i++ ] = ( i < len ) ? *(uc_ptr++) : 0;
      }
      update_addrs_from_string( snmp_ip_addrs, ip_ad );
      net_addrs_set = true;
      break;
    case 5: /* net mask */
      while ( i < 16 ) {
        snmp_net_mask[ i++ ] = ( i < len ) ? *(uc_ptr++) : 0;
      }
      update_addrs_from_string( snmp_net_mask, msk_ad );
      net_addrs_set = true;
      break;
    case 6: /* Gateway address */
      while ( i < 16 ) {
        snmp_gwy_addrs[ i++ ] = ( i < len ) ? *(uc_ptr++) : 0;
      }
      update_addrs_from_string( snmp_gwy_addrs, gwy_ad );
      net_addrs_set = true;
      break;
    case 7: /* DNS address */
      while ( i < 16 ) {
        snmp_dns_addrs[ i++ ] = ( i < len ) ? *(uc_ptr++) : 0;
      }
      update_addrs_from_string( snmp_dns_addrs, dns_ad );
      net_addrs_set = true;
      break;
    case 8: /* v1.4: Trap host address */
      while ( i < 16 ) {
        snmp_trh_addrs[ i++ ] = ( i < len ) ? *(uc_ptr++) : 0;
      }
      update_addrs_from_string( snmp_trh_addrs, th_ad );
      net_addrs_set = true;
      break;
    case 9: /* v1.5: community string */
      while ( i < MAX_COMMUNITY ) {
        snmp_publiccommunity[ i++ ] = ( i < len ) ? *(uc_ptr++) : 0;
      }
      net_addrs_set = true;
      break;
  }
}


/****************************************************************************/ 
/*              f3k_IO_get_object_def: 
* Description:  get definition for F3000 scalar objects
*               Called via mib_scalar_node f3k_IO_scalar
* Parameters:   IN: u8_t ident_len - length of ID in...
*               IN: s32_t *ident - array holding ID
*               OUT: struct obj_def *od - object definition found
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_IO_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
u8_t id;

  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
  if ((ident_len == 2) &&
      (ident[0] > 0) && (ident[0] <= MAX_IO_TABLE))
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;

    id = (u8_t)ident[0];
    printf("\r\nf3k_IO_get_object_def: ident_len %d, id %d\r\n", ident_len, id);

    od->instance = MIB_OBJECT_SCALAR;
    od->access = MIB_OBJECT_READ_ONLY;
    od->asn_type = (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE);
    od->v_len = sizeof(u32_t);
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("f3k_IO_get_object_def: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}

/****************************************************************************/ 
/*              f3k_IO_get_value: 
* Description:  Returns f3k scalar object value
*               @param ident points to objectname.0 (object id trailer)
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes)
*               OUT: void *value - points to (varbind) space to copy value into
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_IO_get_value(struct obj_def *od, u16_t len, void *value)
{
  u32_t *uint_ptr = (u32_t*)value;
  u8_t id;

  LWIP_UNUSED_ARG(len);
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= 0xff));
  id = (u8_t)od->id_inst_ptr[0];
  *uint_ptr = snmp_get_f3k_IO_value( id );
}

/****************************************************************************/ 
/*              f3k_alarm_get_object_def: 
* Description:  get definition for F3000 scalar objects
*               Called via mib_scalar_node f3k_alarm_scalar
* Parameters:   IN: u8_t ident_len - length of ID in...
*               IN: s32_t *ident - array holding ID
*               OUT: struct obj_def *od - object definition found
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_alarm_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
u8_t id;

  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= 0xff));
  if ((ident_len == 2) &&
      (ident[0] > 0) && (ident[0] <= MAX_ALARM_ID)) 
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;
    id = (u8_t)ident[0];
    printf("\r\nf3k_alarm_get_object_def: ident_len %d, id %d\r\n", ident_len, id);
    /* alarm strings */
    od->instance = MIB_OBJECT_SCALAR;
    od->access = MIB_OBJECT_READ_WRITE;
    od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
    od->v_len = strlen( (const char *)alarm_msg[ id-1 ] ); 
//    printf("f3k_alarm_get_object_def: od->v_len = strlen( get_alarm_string(id-1) ) %d\r\n", od->v_len);
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("f3k_alarm_get_object_def: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}

/****************************************************************************/ 
/*              f3k_alarm_get_value: 
* Description:  Returns f3k scalar object value
*               @param ident points to objectname.0 (object id trailer)
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes)
*               OUT: void *value - points to (varbind) space to copy value into
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_alarm_get_value(struct obj_def *od, u16_t len, void *value)
{
  u8_t * uchr_ptr = (u8_t*)value;
  u8_t id;
  u8_t i = 0;

  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_ALARM_ID));
  id = (u8_t)od->id_inst_ptr[0];
//  printf("\r\nf3k_alarm_get_value: id %d, len %d", id, len );
  while ( i < len ) {
    *(uchr_ptr++) = (u8_t)alarm_msg[ id-1 ][ i++ ];
  }
}

/****************************************************************************/ 
/*              f3k_alarm_set_test: 
* Description:  Test f3k_alarm object value before setting
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      Returns set_ok = 1 if able to set value, 0 otherwise
*/
/****************************************************************************/ 
static u8_t
f3k_alarm_set_test(struct obj_def *od, u16_t len, void *value)
{
u8_t id, set_ok;

  LWIP_UNUSED_ARG(value);
  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_ALARM_ID));
  id = (u8_t)od->id_inst_ptr[0];
  set_ok = (len > 0) && (len < MSG_LNGTH) ? 1 : 0;
  printf("\r\f3k_alarm_set_test: id %d, len %d set_ok %d\r\n", id, len, set_ok);
  return set_ok;
}

/****************************************************************************/ 
/*              f3k_alarm_set_value: 
* Description:  Sets f3k_alarm_scalar object value
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_alarm_set_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id, i;
u8_t * uc_ptr;

  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_ALARM_ID));
  id = (u8_t)od->id_inst_ptr[0];
  uc_ptr  = (u8_t*)value;               // char pointer to first byte in value
  i = 0;
//  printf("\r\f3k_alarm_set_value: id %d, len %d uc_ptr %c\r\n", id, len, *uc_ptr);
  while ( i < MSG_LNGTH ) {
    alarm_msg[id-1][i] = ( i < len ) ? *(uc_ptr++) : 0;
    i++;
  }
  alarm_str_set = id;
}

/****************************************************************************/ 
/*              f3k_amask_get_object_def: 
* Description:  get definition for F3000 scalar objects
*               Called via mib_scalar_node f3k_sys_scalar
* Parameters:   IN: u8_t ident_len - length of ID in...
*               IN: s32_t *ident - array holding ID
*               OUT: struct obj_def *od - object definition found
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_amask_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od)
{
u8_t id;

  /* return to object name, adding index depth (1) */
  ident_len += 1;
  ident -= 1;
  LWIP_ASSERT("invalid id", (ident[0] >= 0) && (ident[0] <= MAX_ALARM_ID));
  if ((ident_len == 2) &&
      (ident[0] > 0) && (ident[0] <= MAX_ALARM_ID))
  {
    od->id_inst_len = ident_len;
    od->id_inst_ptr = ident;

    id = (u8_t)ident[0];
    printf("\r\nf3k_amask_get_object_def: ident_len %d, id %d\r\n", ident_len, id);
    od->instance = MIB_OBJECT_SCALAR;
    od->access = MIB_OBJECT_READ_WRITE;
    od->asn_type = (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR);
    od->v_len = 8;                      // 8 hex chars mask IO channels 1-32
  }
  else
  {
    LWIP_DEBUGF(SNMP_MIB_DEBUG,("\nf3k_amask_get_object_def: no scalar\n"));
    od->instance = MIB_OBJECT_NONE;
  }
}

/****************************************************************************/ 
/*              f3k_amask_get_value: 
* Description:  Returns f3k_amask scalar object value
*               @param ident points to objectname.0 (object id trailer)
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes)
*               OUT: void *value - points to (varbind) space to copy value into
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_amask_get_value(struct obj_def *od, u16_t len, void *value)
{
  u8_t * uchr_ptr = (u8_t*)value;
  u8_t id;
  u8_t i = 0;

  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_ALARM_ID));
  id = (u8_t)od->id_inst_ptr[0];
  strncpy( f3k_IO_mask, get_hex_mask( io_mask[id-1] ), 8 );  // v1.3: copy numeric io_mask[]
  while ( i < len ) {
    *(uchr_ptr++) = f3k_IO_mask[ i++ ];
  }
}

/****************************************************************************/ 
/*              f3k_amask_set_test: 
* Description:  Test f3k_amask object value before setting
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      Returns set_ok = 1 if able to set value, 0 otherwise
*/
/****************************************************************************/ 
static u8_t
f3k_amask_set_test(struct obj_def *od, u16_t len, void *value)
{
u8_t i, id, set_ok;
u8_t * uc_ptr  = (u8_t*)value;        // char pointer to first byte in value

  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_ALARM_ID));
  id = (u8_t)od->id_inst_ptr[0];
  printf("\r\f3k_amask_set_test: id %d, len %d\r\n", id, len);
  if ( (len > 0) && (len <= 8) )
  {                                 // ensure all digits are hexadecimal
    set_ok = 1;
    for ( i = 0; i < len; i++ )
    {
      if ( !isxdigit( *(uc_ptr++) ) )
      {
        set_ok = 0;                 // invalid hexadecimal digit
        break;                      // so quit
      }
    } 
  }
  return set_ok;
}

/****************************************************************************/ 
/*              f3k_amask_set_value: 
* Description:  Sets f3k_alarm_scalar object value
* Parameters:   IN: struct obj_def *od - object definition found
*               IN: u16_t len - return value space (in bytes) - NOT USED
*               OUT: void *value - points to (varbind) space to copy value from
* Returns:      NONE
*/
/****************************************************************************/ 
static void
f3k_amask_set_value(struct obj_def *od, u16_t len, void *value)
{
u8_t id;
u8_t * uc_ptr  = (u8_t*)value;        // char pointer to first byte in value

  LWIP_ASSERT("invalid id", (od->id_inst_ptr[0] >= 0) && (od->id_inst_ptr[0] <= MAX_ALARM_ID));
  id = (u8_t)od->id_inst_ptr[0];

  io_mask[ id-1 ] = convert2decimal( uc_ptr, len );
  alarm_str_set = id;
}

#endif /* LWIP_SNMP */