2010-10-19 13:44:06 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
Copyright (c) Dialogic(R), 2010
|
|
|
|
|
|
|
|
*
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
|
|
any later version.
|
|
|
|
*
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
|
|
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*! \file
|
|
|
|
* \brief Implements to access Diva management file system
|
|
|
|
*
|
|
|
|
* \par Access to Diva hardware state
|
|
|
|
* divalogd captures information from Diva management and exports
|
|
|
|
* it CVS file format.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
#include "divastreaming/platform.h"
|
2010-10-22 22:44:50 +00:00
|
|
|
#include "chan_capi_platform.h"
|
|
|
|
#include "chan_capi20.h"
|
|
|
|
#include "chan_capi.h"
|
2010-10-19 13:44:06 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2010-10-22 22:44:50 +00:00
|
|
|
#include <time.h>
|
2010-10-19 13:44:06 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "dlist.h"
|
|
|
|
#include "divastatus_parameters.h"
|
|
|
|
#include "divastatus_ifc.h"
|
|
|
|
#include "divastatus.h"
|
|
|
|
#ifdef CC_USE_INOTIFY
|
2010-10-22 22:44:50 +00:00
|
|
|
#include <fcntl.h>
|
2010-10-19 13:44:06 +00:00
|
|
|
#include <sys/inotify.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
typedef const char* pcchar;
|
|
|
|
|
|
|
|
static pcchar DIVA_STATUS_PATH = "/usr/lib/eicon/divas/registry/ifc";
|
|
|
|
static pcchar DIVA_STATUS_FILE = "ifcstate";
|
2010-10-22 22:44:50 +00:00
|
|
|
static pcchar DIVA_INFO_FILE = "info";
|
2010-10-19 13:44:06 +00:00
|
|
|
static pcchar DIVA_CONFIG_FILE = "info/Config";
|
|
|
|
static pcchar DIVA_SERIAL_FILE = "serial";
|
|
|
|
static pcchar DIVA_READ_ALARM_FILE = "info/Red Alarm";
|
|
|
|
static pcchar DIVA_YELLOW_ALARM_FILE = "info/Yellow Alarm";
|
|
|
|
static pcchar DIVA_BLUE_ALARM_FILE = "info/Blue Alarm";
|
|
|
|
|
|
|
|
/*
|
|
|
|
LOCALS
|
|
|
|
*/
|
2010-10-22 22:44:50 +00:00
|
|
|
struct _diva_status_ifc;
|
2010-10-19 13:44:06 +00:00
|
|
|
static int diva_status_active(void);
|
|
|
|
static int diva_status_get_controller_state(int controller, diva_status_ifc_state_t *state);
|
|
|
|
static char* diva_status_read_file(unsigned int controller, const char* fileName);
|
2010-10-22 22:44:50 +00:00
|
|
|
static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir);
|
2010-10-25 21:21:31 +00:00
|
|
|
static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state (const diva_status_ifc_state_t* state);
|
|
|
|
static diva_status_hardware_state_t diva_status_get_hw_state_from_idi_state (const diva_status_ifc_state_t* state);
|
2010-10-22 22:44:50 +00:00
|
|
|
static int diva_status_map_CAPI2XDI(int capiController);
|
|
|
|
static void diva_status_process_event(struct _diva_status_ifc *controllerState, int initialStateIndex, int newStateIndex);
|
|
|
|
#ifdef CC_USE_INOTIFY
|
|
|
|
static pcchar DIVA_DIVA_FS_PATH = "/usr/lib/eicon/divas/registry/ifc";
|
|
|
|
static void diva_status_cleanup_wd(int wd);
|
|
|
|
static int divaFsWd = -1; /*! \brief Diva fs state */
|
|
|
|
#endif
|
|
|
|
|
2010-10-26 09:53:16 +00:00
|
|
|
#ifdef CC_AST_HAS_VERSION_1_6
|
|
|
|
static
|
|
|
|
#endif
|
|
|
|
char diva_status_ifc_state_usage[] =
|
|
|
|
"Usage: " CC_MESSAGE_NAME " ifcstate\n"
|
|
|
|
" Show info about interfaces.\n";
|
|
|
|
|
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
static int inotifyFd = -1; /*! \brief inotify descriptor */
|
|
|
|
static diva_entity_queue_t controller_q; /*! \brief Active controllers. \note List changed only while CAPI thread is not running */
|
|
|
|
|
|
|
|
typedef struct _diva_status_ifc {
|
|
|
|
diva_entity_link_t link;
|
|
|
|
int capiController;
|
|
|
|
int idiController;
|
|
|
|
diva_status_ifc_state_t state[2];
|
|
|
|
int currentState;
|
|
|
|
int ifstateWd;
|
|
|
|
int infoWd;
|
2010-10-25 21:21:31 +00:00
|
|
|
diva_status_changed_cb_proc_t status_changed_notify_proc; /*! \brief Notify about interface state change */
|
|
|
|
diva_hwstatus_changed_cb_proc_t hw_status_changed_notify_proc; /*! \brief Notify about hardware state change */
|
|
|
|
time_t changeTime; /*! \brief Time interface state changed */
|
|
|
|
time_t unavailableChangeTime; /*! \brief Time interface state changed to unavailable */
|
|
|
|
time_t hwChangeTime; /*! \brief Time hardware state changed */
|
|
|
|
time_t unavailableHwChangeTime; /*! \brief Time hardware state changed to unavailable */
|
2010-10-22 22:44:50 +00:00
|
|
|
} diva_status_ifc_t;
|
|
|
|
|
2010-10-25 21:21:31 +00:00
|
|
|
diva_status_interface_state_t diva_status_init_interface(int controller,
|
|
|
|
diva_status_hardware_state_t* hwState,
|
|
|
|
diva_status_changed_cb_proc_t fn,
|
|
|
|
diva_hwstatus_changed_cb_proc_t hwfn)
|
2010-10-22 22:44:50 +00:00
|
|
|
{
|
|
|
|
int idiController = diva_status_map_CAPI2XDI(controller);
|
|
|
|
diva_status_ifc_t* controllerState = idiController > 0 ? (ast_malloc(sizeof(*controllerState))) : 0;
|
|
|
|
diva_status_interface_state_t ret = DivaStatusInterfaceStateNotAvailable;
|
|
|
|
|
|
|
|
if (controllerState != 0) {
|
|
|
|
controllerState->capiController = controller;
|
|
|
|
controllerState->idiController = idiController;
|
2010-10-25 21:21:31 +00:00
|
|
|
controllerState->status_changed_notify_proc = fn;
|
|
|
|
controllerState->hw_status_changed_notify_proc = hwfn;
|
2010-10-22 22:44:50 +00:00
|
|
|
controllerState->ifstateWd = -1;
|
|
|
|
controllerState->infoWd = -1;
|
|
|
|
diva_status_create_wd(&controllerState->ifstateWd, idiController, DIVA_STATUS_FILE, 0);
|
|
|
|
diva_status_create_wd(&controllerState->infoWd, idiController, DIVA_INFO_FILE, 1);
|
|
|
|
controllerState->currentState = 0;
|
|
|
|
controllerState->changeTime = time(NULL);
|
|
|
|
diva_status_get_controller_state(idiController, &controllerState->state[controllerState->currentState]);
|
|
|
|
diva_q_add_tail(&controller_q, &controllerState->link);
|
|
|
|
ret = diva_status_get_interface_state_from_idi_state(&controllerState->state[controllerState->currentState]);
|
2010-10-25 21:21:31 +00:00
|
|
|
*hwState = diva_status_get_hw_state_from_idi_state(&controllerState->state[controllerState->currentState]);
|
2010-10-22 22:44:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
void diva_status_cleanup_interface (int controller)
|
|
|
|
{
|
|
|
|
diva_entity_link_t* link;
|
|
|
|
|
|
|
|
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
|
|
|
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
|
|
|
|
|
|
|
if (controllerState->capiController == controller) {
|
|
|
|
diva_q_remove(&controller_q, link);
|
|
|
|
#ifdef CC_USE_INOTIFY
|
|
|
|
if (controllerState->ifstateWd >= 0)
|
|
|
|
inotify_rm_watch(inotifyFd, controllerState->ifstateWd);
|
|
|
|
if (controllerState->infoWd >= 0)
|
|
|
|
inotify_rm_watch(inotifyFd, controllerState->infoWd);
|
|
|
|
#endif
|
|
|
|
ast_free (controllerState);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CC_USE_INOTIFY
|
|
|
|
if (diva_q_get_head(&controller_q) == 0) {
|
|
|
|
if (divaFsWd >= 0) {
|
|
|
|
inotify_rm_watch(inotifyFd, divaFsWd);
|
|
|
|
divaFsWd = -1;
|
|
|
|
}
|
|
|
|
if (inotifyFd >= 0) {
|
|
|
|
close(inotifyFd);
|
|
|
|
inotifyFd = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int diva_status_get_waitable_object(void)
|
|
|
|
{
|
|
|
|
return inotifyFd;
|
|
|
|
}
|
|
|
|
|
|
|
|
void diva_status_process_events(void)
|
|
|
|
{
|
|
|
|
diva_entity_link_t* link;
|
|
|
|
|
|
|
|
/*
|
|
|
|
Polling
|
|
|
|
*/
|
|
|
|
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
|
|
|
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
|
|
|
if ((controllerState->ifstateWd < 0) || (controllerState->infoWd < 0)) {
|
|
|
|
int currentState = controllerState->currentState;
|
|
|
|
diva_status_create_wd(&controllerState->ifstateWd, controllerState->idiController, DIVA_STATUS_FILE, 0);
|
|
|
|
diva_status_create_wd(&controllerState->infoWd, controllerState->idiController, DIVA_INFO_FILE, 1);
|
|
|
|
controllerState->currentState = (controllerState->currentState + 1) % 2;
|
|
|
|
diva_status_get_controller_state(controllerState->idiController, &controllerState->state[controllerState->currentState]);
|
|
|
|
diva_status_process_event(controllerState, currentState, controllerState->currentState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Events
|
|
|
|
*/
|
|
|
|
#ifdef CC_USE_INOTIFY
|
|
|
|
if (inotifyFd >= 0 && divaFsWd >= 0) {
|
|
|
|
unsigned char buffer[1024];
|
|
|
|
int length;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
while ((length = read(inotifyFd, buffer, sizeof(buffer))) > 0) {
|
|
|
|
i = 0;
|
|
|
|
while (i < length) {
|
|
|
|
struct inotify_event *event = (struct inotify_event*)&buffer[i];
|
|
|
|
|
|
|
|
if ((event->mask & (IN_IGNORED|IN_DELETE_SELF|IN_UNMOUNT|IN_Q_OVERFLOW)) != 0) {
|
|
|
|
diva_status_cleanup_wd((event->mask & IN_IGNORED) == 0 ? event->wd : -1);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (event->wd != divaFsWd) {
|
|
|
|
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
|
|
|
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
|
|
|
if ((controllerState->ifstateWd == event->wd) || (controllerState->infoWd == event->wd)) {
|
|
|
|
int currentState = controllerState->currentState;
|
|
|
|
controllerState->currentState = (controllerState->currentState + 1) % 2;
|
|
|
|
diva_status_get_controller_state(controllerState->idiController, &controllerState->state[controllerState->currentState]);
|
|
|
|
diva_status_process_event(controllerState, currentState, controllerState->currentState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
i += sizeof(*event) + event->len;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CC_USE_INOTIFY
|
|
|
|
static void diva_status_cleanup_wd(int wd)
|
|
|
|
{
|
|
|
|
diva_entity_link_t* link;
|
|
|
|
|
|
|
|
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
|
|
|
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
|
|
|
|
|
|
|
if ((controllerState->ifstateWd >= 0) && (wd != controllerState->ifstateWd)) {
|
|
|
|
inotify_rm_watch(inotifyFd, controllerState->ifstateWd);
|
|
|
|
}
|
|
|
|
controllerState->ifstateWd = -1;
|
|
|
|
if ((controllerState->infoWd >= 0) && (wd != controllerState->infoWd)) {
|
|
|
|
inotify_rm_watch(inotifyFd, controllerState->infoWd);
|
|
|
|
}
|
|
|
|
controllerState->infoWd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((divaFsWd >= 0) && (wd != divaFsWd)) {
|
|
|
|
inotify_rm_watch(inotifyFd, divaFsWd);
|
|
|
|
}
|
|
|
|
divaFsWd = -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void diva_status_process_event(diva_status_ifc_t *controllerState, int initialStateIndex, int newStateIndex)
|
|
|
|
{
|
|
|
|
diva_status_ifc_state_t* initialState = &controllerState->state[initialStateIndex];
|
|
|
|
diva_status_ifc_state_t* newState = &controllerState->state[newStateIndex];
|
|
|
|
diva_status_interface_state_t initialIfcState = diva_status_get_interface_state_from_idi_state (initialState);
|
|
|
|
diva_status_interface_state_t newIfcState = diva_status_get_interface_state_from_idi_state (newState);
|
2010-10-25 21:21:31 +00:00
|
|
|
diva_status_hardware_state_t initalHwState = diva_status_get_hw_state_from_idi_state(initialState);
|
|
|
|
diva_status_hardware_state_t newHwState = diva_status_get_hw_state_from_idi_state(newState);
|
|
|
|
time_t t = time(NULL);
|
2010-10-22 22:44:50 +00:00
|
|
|
|
|
|
|
if (initialIfcState != newIfcState) {
|
2010-10-25 21:21:31 +00:00
|
|
|
controllerState->changeTime = t;
|
|
|
|
|
|
|
|
if (newIfcState == DivaStatusInterfaceStateERROR)
|
|
|
|
controllerState->unavailableChangeTime = t;
|
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
controllerState->status_changed_notify_proc(controllerState->capiController, newIfcState);
|
|
|
|
}
|
2010-10-25 21:21:31 +00:00
|
|
|
|
|
|
|
if (initalHwState != newHwState) {
|
|
|
|
controllerState->hwChangeTime = t;
|
|
|
|
|
|
|
|
if (newHwState == DivaStatusHardwareStateERROR)
|
|
|
|
controllerState->unavailableHwChangeTime = t;
|
|
|
|
|
|
|
|
controllerState->hw_status_changed_notify_proc(controllerState->capiController, newHwState);
|
|
|
|
}
|
2010-10-22 22:44:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir)
|
|
|
|
{
|
|
|
|
#ifdef CC_USE_INOTIFY
|
|
|
|
if (inotifyFd < 0) {
|
|
|
|
inotifyFd = inotify_init();
|
|
|
|
if (inotifyFd >= 0)
|
|
|
|
fcntl(inotifyFd, F_SETFL, O_NONBLOCK);
|
|
|
|
}
|
|
|
|
if (inotifyFd >= 0 && divaFsWd < 0) {
|
|
|
|
divaFsWd = inotify_add_watch (inotifyFd, DIVA_DIVA_FS_PATH, IN_DELETE_SELF | IN_UNMOUNT | IN_IGNORED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*wd >= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (inotifyFd >= 0 && divaFsWd >= 0) {
|
|
|
|
int name_len = strlen(DIVA_STATUS_PATH) + strlen(fileName) + 32;
|
|
|
|
char name[name_len];
|
|
|
|
|
|
|
|
snprintf(name, name_len, "%s/adapter%u/%s", DIVA_STATUS_PATH, controller, fileName);
|
|
|
|
name[name_len-1] = 0;
|
|
|
|
|
|
|
|
*wd = inotify_add_watch (inotifyFd, name,
|
|
|
|
IN_CLOSE_WRITE | IN_DELETE_SELF | IN_IGNORED | ((isDir != 0) ? IN_DELETE : 0));
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
*wd = -1;
|
|
|
|
#endif
|
|
|
|
}
|
2010-10-19 13:44:06 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
\brief Check divalogd is available
|
|
|
|
*/
|
|
|
|
static int diva_status_active(void)
|
|
|
|
{
|
|
|
|
struct stat v;
|
|
|
|
|
|
|
|
return ((stat(DIVA_STATUS_PATH, &v) == 0 && S_ISDIR(v.st_mode) != 0) ? 0 : -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char* diva_status_read_file(unsigned int controller, const char* fileName)
|
|
|
|
{
|
|
|
|
int name_len = strlen(DIVA_STATUS_PATH) + strlen(fileName) + 32;
|
|
|
|
char name[name_len];
|
|
|
|
struct stat v;
|
|
|
|
int fd;
|
|
|
|
int length;
|
|
|
|
char *data, *p;
|
|
|
|
|
|
|
|
snprintf(name, name_len, "%s/adapter%u/%s", DIVA_STATUS_PATH, controller, fileName);
|
|
|
|
name[name_len-1] = 0;
|
|
|
|
|
|
|
|
fd = open(name, O_RDONLY);
|
|
|
|
if (fd < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (fstat(fd, &v) != 0 || v.st_size == 0) {
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
length = MIN(v.st_size, 16U*1024U);
|
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
data = ast_malloc(length+1);
|
2010-10-19 13:44:06 +00:00
|
|
|
if (data == 0) {
|
|
|
|
close (fd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (read(fd, data, length) != length) {
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free(data);
|
2010-10-19 13:44:06 +00:00
|
|
|
close(fd);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
close (fd);
|
|
|
|
|
2010-10-19 13:44:06 +00:00
|
|
|
data[length] = 0;
|
|
|
|
|
|
|
|
while (((p = strchr(data, '\n')) != 0) || ((p = strchr(data, '\r')))) {
|
|
|
|
*p = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int diva_status_get_controller_state(int controller, diva_status_ifc_state_t *state)
|
|
|
|
{
|
|
|
|
char *data, *p;
|
|
|
|
int i, pri;
|
|
|
|
const char* v;
|
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
memset (state, 0x00, sizeof(*state));
|
|
|
|
state->ifcType = DivaStatusIfcNotPri;
|
|
|
|
state->hwState = DivaStatusHwStateUnknown;
|
|
|
|
state->ifcL1State = DivaStatusIfcL2DoNotApply;
|
|
|
|
state->ifcL2State = DivaStatusIfcL2DoNotApply;
|
|
|
|
|
2010-10-19 13:44:06 +00:00
|
|
|
if (diva_status_active() != 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((data = diva_status_read_file(controller, DIVA_CONFIG_FILE)) == 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
for (i = 0, pri = 0, p = data, v = strsep(&p, ",");
|
|
|
|
v != 0 && i < DivaStateIfcConfig_Max;
|
|
|
|
v = strsep(&p, ","), i++) {
|
2010-10-22 22:44:50 +00:00
|
|
|
if (v[0] == '\'' && v[strlen(v)-1] != '\'') {
|
|
|
|
const char *tmp;
|
|
|
|
do {
|
|
|
|
if ((p != 0) && (*p != 0))
|
|
|
|
p[-1] = ',';
|
|
|
|
tmp = strsep (&p, ",");
|
|
|
|
} while ((tmp != 0) && (tmp[strlen(tmp)-1] != '\''));
|
|
|
|
}
|
|
|
|
|
2010-10-19 13:44:06 +00:00
|
|
|
switch ((diva_state_ifc_config_parameters_t)i) {
|
|
|
|
case DivaStateIfcConfig_TYPE:
|
|
|
|
pri += (strcmp ("PRI", v) == 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DivaStateIfcConfig_PRI:
|
|
|
|
pri += (strcmp ("'YES'", v) == 0);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free(data);
|
|
|
|
|
|
|
|
state->ifcType = (pri == 2) ? DivaStatusIfcPri : DivaStatusIfcNotPri;
|
2010-10-19 13:44:06 +00:00
|
|
|
|
|
|
|
if ((data = diva_status_read_file(controller, DIVA_STATUS_FILE)) == 0)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
for (i = 0, p = data, v = strsep (&p, ","); v != 0 && i < (int)DivaStateIfcState_Max; v = strsep (&p, ","), i++) {
|
2010-10-22 22:44:50 +00:00
|
|
|
if (v[0] == '\'' && v[strlen(v)-1] != '\'') {
|
|
|
|
const char *tmp;
|
|
|
|
do {
|
|
|
|
if ((p != 0) && (*p != 0))
|
|
|
|
p[-1] = ',';
|
|
|
|
tmp = strsep (&p, ",");
|
|
|
|
} while ((tmp != 0) && (tmp[strlen(tmp)-1] != '\''));
|
|
|
|
}
|
2010-10-19 13:44:06 +00:00
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
switch ((diva_state_ifcstate_parameters_t)i) {
|
2010-10-19 13:44:06 +00:00
|
|
|
case DivaStateIfcState_LAYER1_STATE:
|
|
|
|
if (state->ifcType == DivaStatusIfcPri) {
|
|
|
|
state->ifcL1State = (strcmp ("'Activated'", v) == 0) ? DivaStatusIfcL1OK : DivaStatusIfcL1Error;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DivaStateIfcState_LAYER2_STATE:
|
|
|
|
if (state->ifcType == DivaStatusIfcPri) {
|
2010-10-26 09:53:16 +00:00
|
|
|
state->ifcL2State = (strcmp ("'Layer2 UP'", v) == 0) ? DivaStatusIfcL2OK : DivaStatusIfcL2Error;
|
2010-10-19 13:44:06 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2010-10-26 09:53:16 +00:00
|
|
|
case DivaStateIfcState_D1_X_FRAMES:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->ifcTxDStatistics.Frames = (unsigned int)atol(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
2010-10-26 09:53:16 +00:00
|
|
|
case DivaStateIfcState_D1_X_BYTES:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->ifcTxDStatistics.Bytes = (unsigned int)atol(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
2010-10-26 09:53:16 +00:00
|
|
|
case DivaStateIfcState_D1_X_ERRORS:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->ifcTxDStatistics.Errors = (unsigned int)atol(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
2010-10-26 09:53:16 +00:00
|
|
|
case DivaStateIfcState_D1_R_FRAMES:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->ifcRxDStatistics.Frames = (unsigned int)atol(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
2010-10-26 09:53:16 +00:00
|
|
|
case DivaStateIfcState_D1_R_BYTES:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->ifcRxDStatistics.Bytes = (unsigned int)atol(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
2010-10-26 09:53:16 +00:00
|
|
|
case DivaStateIfcState_D1_R_ERRORS:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->ifcRxDStatistics.Errors = (unsigned int)atol(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DivaStateIfcState_MAX_TEMPERATURE:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->maxTemperature = (unsigned int)atoi(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
|
|
|
case DivaStateIfcState_TEMPERATURE:
|
2010-10-22 22:44:50 +00:00
|
|
|
state->currentTemperature = (unsigned int)atoi(v);
|
2010-10-19 13:44:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DivaStateIfcState_HARDWARE_STATE:
|
2010-10-22 22:44:50 +00:00
|
|
|
if (strcmp("'Active'", v) == 0)
|
2010-10-19 13:44:06 +00:00
|
|
|
state->hwState = DivaStateHwStateActive;
|
2010-10-22 22:44:50 +00:00
|
|
|
else if (strcmp("'Inactive'", v) == 0)
|
2010-10-19 13:44:06 +00:00
|
|
|
state->hwState = DivaStateHwStateInactive;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free (data);
|
2010-10-19 13:44:06 +00:00
|
|
|
|
|
|
|
if ((data = diva_status_read_file(controller, DIVA_READ_ALARM_FILE)) != 0) {
|
2010-10-26 09:53:16 +00:00
|
|
|
state->ifcAlarms.Red = strcmp("TRUE", data) == 0;
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free(data);
|
2010-10-19 13:44:06 +00:00
|
|
|
}
|
|
|
|
if ((data = diva_status_read_file(controller, DIVA_YELLOW_ALARM_FILE)) != 0) {
|
2010-10-26 09:53:16 +00:00
|
|
|
state->ifcAlarms.Yellow = strcmp("TRUE", data) == 0;
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free(data);
|
2010-10-19 13:44:06 +00:00
|
|
|
}
|
|
|
|
if ((data = diva_status_read_file(controller, DIVA_BLUE_ALARM_FILE)) != 0) {
|
2010-10-26 09:53:16 +00:00
|
|
|
state->ifcAlarms.Blue = strcmp("TRUE", data) == 0;
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free(data);
|
2010-10-19 13:44:06 +00:00
|
|
|
}
|
|
|
|
if ((data = diva_status_read_file(controller, DIVA_SERIAL_FILE)) != 0) {
|
|
|
|
state->serialNumber = (unsigned int)(atol(data)) & 0x00ffffff;
|
2010-10-22 22:44:50 +00:00
|
|
|
ast_free(data);
|
2010-10-19 13:44:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
chan_capi interface
|
|
|
|
*/
|
|
|
|
diva_status_interface_state_t diva_status_get_interface_state(int controller)
|
|
|
|
{
|
|
|
|
diva_status_ifc_state_t state;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = diva_status_get_controller_state(controller, &state);
|
|
|
|
|
|
|
|
if ((ret != 0) ||
|
|
|
|
(state.ifcType != DivaStatusIfcPri) ||
|
|
|
|
(state.ifcL1State == DivaStatusIfcL2DoNotApply) ||
|
|
|
|
(state.hwState == DivaStatusHwStateUnknown)) {
|
|
|
|
return (DivaStatusInterfaceStateNotAvailable);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((state.ifcAlarms.Red == 0) &&
|
|
|
|
(state.ifcAlarms.Yellow == 0) &&
|
|
|
|
(state.ifcAlarms.Blue == 0) &&
|
|
|
|
(state.hwState == DivaStateHwStateActive) &&
|
|
|
|
(state.ifcL1State == DivaStatusIfcL1OK)) {
|
|
|
|
return DivaStatusInterfaceStateOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DivaStatusInterfaceStateERROR;
|
|
|
|
}
|
|
|
|
|
2010-10-25 21:21:31 +00:00
|
|
|
static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state(const diva_status_ifc_state_t* state)
|
|
|
|
{
|
2010-10-22 22:44:50 +00:00
|
|
|
if ((state->ifcType != DivaStatusIfcPri) ||
|
|
|
|
(state->ifcL1State == DivaStatusIfcL2DoNotApply) ||
|
|
|
|
(state->hwState == DivaStatusHwStateUnknown)) {
|
|
|
|
return (DivaStatusInterfaceStateNotAvailable);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((state->ifcAlarms.Red == 0) &&
|
|
|
|
(state->ifcAlarms.Yellow == 0) &&
|
|
|
|
(state->ifcAlarms.Blue == 0) &&
|
|
|
|
(state->hwState == DivaStateHwStateActive) &&
|
|
|
|
(state->ifcL1State == DivaStatusIfcL1OK)) {
|
|
|
|
return DivaStatusInterfaceStateOK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DivaStatusInterfaceStateERROR;
|
|
|
|
}
|
|
|
|
|
2010-10-25 21:21:31 +00:00
|
|
|
static diva_status_hardware_state_t diva_status_get_hw_state_from_idi_state(const diva_status_ifc_state_t* state)
|
|
|
|
{
|
|
|
|
switch(state->hwState) {
|
|
|
|
case DivaStateHwStateActive:
|
|
|
|
return (DivaStatusHardwareStateOK);
|
|
|
|
|
|
|
|
case DivaStateHwStateInactive:
|
|
|
|
return (DivaStatusHardwareStateERROR);
|
|
|
|
|
|
|
|
case DivaStatusHwStateUnknown:
|
|
|
|
default:
|
|
|
|
return (DivaStatusHardwareStateUnknown);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-10-22 22:44:50 +00:00
|
|
|
/*!
|
|
|
|
\brief Map CAPI controller to Diva hardware
|
|
|
|
|
|
|
|
\note In most cases chan_capi uses 1:1 mappimg
|
|
|
|
between CAPI controller and Diva hardware
|
|
|
|
|
|
|
|
\todo Read CAPI2DIva mapping table from CAPI
|
|
|
|
*/
|
|
|
|
static int diva_status_map_CAPI2XDI(int capiController)
|
|
|
|
{
|
|
|
|
return ((capiController > 0) ? capiController : -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int diva_status_available(void)
|
|
|
|
{
|
|
|
|
return (diva_status_active());
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* diva_status_interface_state_name(diva_status_interface_state_t state)
|
|
|
|
{
|
2010-10-25 21:21:31 +00:00
|
|
|
switch(state) {
|
2010-10-22 22:44:50 +00:00
|
|
|
case DivaStatusInterfaceStateOK:
|
|
|
|
return "active";
|
|
|
|
|
|
|
|
case DivaStatusInterfaceStateERROR:
|
|
|
|
return "inactive";
|
|
|
|
|
|
|
|
case DivaStatusInterfaceStateNotAvailable:
|
|
|
|
default:
|
2010-10-26 09:53:16 +00:00
|
|
|
return "unknown";
|
2010-10-22 22:44:50 +00:00
|
|
|
}
|
|
|
|
}
|
2010-10-25 21:21:31 +00:00
|
|
|
|
|
|
|
const char* diva_status_hw_state_name(diva_status_hardware_state_t hwState)
|
|
|
|
{
|
|
|
|
switch(hwState) {
|
|
|
|
case DivaStatusHardwareStateOK:
|
|
|
|
return "active";
|
|
|
|
|
|
|
|
case DivaStatusHardwareStateERROR:
|
|
|
|
return "not running";
|
|
|
|
|
|
|
|
case DivaStatusHardwareStateUnknown:
|
|
|
|
default:
|
|
|
|
return "unknown";
|
|
|
|
}
|
|
|
|
}
|
2010-10-26 09:53:16 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifdef CC_AST_HAS_VERSION_1_6
|
|
|
|
char *pbxcli_capi_ifc_status(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
|
|
|
|
#else
|
|
|
|
int pbxcli_capi_ifc_status(int fd, int argc, char *argv[])
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
diva_entity_link_t* link;
|
|
|
|
#ifdef CC_AST_HAS_VERSION_1_6
|
|
|
|
int fd = a->fd;
|
|
|
|
|
|
|
|
if (cmd == CLI_INIT) {
|
|
|
|
e->command = CC_MESSAGE_NAME " ifcstate";
|
|
|
|
e->usage = diva_status_ifc_state_usage;
|
|
|
|
return NULL;
|
|
|
|
} else if (cmd == CLI_GENERATE)
|
|
|
|
return NULL;
|
|
|
|
if (a->argc != e->args)
|
|
|
|
return CLI_SHOWUSAGE;
|
|
|
|
#else
|
|
|
|
|
|
|
|
if (argc != 2)
|
|
|
|
return RESULT_SHOWUSAGE;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( diva_q_get_head(&controller_q) == NULL) {
|
|
|
|
ast_cli(fd, "There are no interraces in " CC_MESSAGE_NAME " instance.\n");
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
ast_cli(fd, CC_MESSAGE_NAME " interfaces\n");
|
|
|
|
ast_cli(fd, "%s %-9s%-4s%-4s%-4s%-7s%-5s%8s%12s%12s%12s%12s\n",
|
2010-10-29 18:54:15 +00:00
|
|
|
"INTERFACE", "State", "L1", "L2", "RED", "YELLOW", "BLUE", "D-Rx-Frames", "D-Rx-Bytes","D-Tx-Frames", "D-Tx-Bytes", "D-Errors");
|
2010-10-26 09:53:16 +00:00
|
|
|
|
|
|
|
for (link = diva_q_get_head(&controller_q); link != 0; link = diva_q_get_next(link)) {
|
|
|
|
diva_status_ifc_t *controllerState = DIVAS_CONTAINING_RECORD(link, diva_status_ifc_t, link);
|
|
|
|
diva_status_ifc_state_t* state = &controllerState->state[controllerState->currentState];
|
2010-10-29 18:54:15 +00:00
|
|
|
ast_cli(fd, "ISDN%-3d%-2s %-9s%-4s%-4s%-4s%-7s%-3s %12d %11d %11d %11d %11d\n",
|
2010-10-26 09:53:16 +00:00
|
|
|
controllerState->capiController, "",
|
|
|
|
diva_status_interface_state_name(diva_status_get_interface_state_from_idi_state (state)),
|
|
|
|
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
|
|
|
(state->ifcL1State == DivaStatusIfcL1OK ? "On" : "Off") : "-",
|
|
|
|
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
|
|
|
(state->ifcL2State == DivaStatusIfcL2OK ? "On" : "Off") : "-",
|
|
|
|
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
|
|
|
(state->ifcAlarms.Red != 0 ? "On" : "Off") : "-",
|
|
|
|
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
|
|
|
(state->ifcAlarms.Yellow != 0 ? "On" : "Off") : "-",
|
|
|
|
((state->ifcType == DivaStatusIfcPri) && (state->hwState == DivaStatusHardwareStateOK)) ?
|
|
|
|
(state->ifcAlarms.Blue != 0 ? "On" : "Off") : "-",
|
|
|
|
state->ifcRxDStatistics.Frames, state->ifcRxDStatistics.Bytes,
|
|
|
|
state->ifcTxDStatistics.Frames, state->ifcTxDStatistics.Bytes,
|
|
|
|
state->ifcRxDStatistics.Errors + state->ifcTxDStatistics.Errors
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CC_AST_HAS_VERSION_1_6
|
|
|
|
return CLI_SUCCESS;
|
|
|
|
#else
|
|
|
|
return RESULT_SUCCESS;
|
|
|
|
#endif
|
|
|
|
}
|