From e5345628274407219d9d7b1aa6890bb156dd3a0f Mon Sep 17 00:00:00 2001 From: MelwareDE Date: Fri, 22 Oct 2010 22:44:50 +0000 Subject: [PATCH] Use provided by Diva hardware status information for distribution of outgoing calls between CAPI controllers --- chan_capi.c | 105 ++++++++- chan_capi.h | 3 + divastatus/divastatus.c | 342 ++++++++++++++++++++++++++--- divastatus/divastatus_ifc.h | 24 +- divastatus/divastatus_parameters.h | 2 +- 5 files changed, 436 insertions(+), 40 deletions(-) diff --git a/chan_capi.c b/chan_capi.c index 0410a25..681e261 100644 --- a/chan_capi.c +++ b/chan_capi.c @@ -211,6 +211,8 @@ static char global_mohinterpret[MAX_MUSICCLASS] = "default"; #endif /* local prototypes */ +#define CC_B_INTERFACE_NOT_FREE(__x__) (((__x__)->used) || ((__x__)->channeltype != CAPI_CHANNELTYPE_B)) + static int pbx_capi_hold(struct ast_channel *c, char *param); static int pbx_capi_retrieve(struct ast_channel *c, char *param); #ifdef CC_AST_HAS_INDICATE_DATA @@ -226,6 +228,10 @@ static void pbx_capi_add_diva_protocol_independent_extension( unsigned char *facilityarray, struct ast_channel *c, const char* variable); +#ifdef DIVA_STATUS +static void pbx_capi_interface_status_changed(int controller, diva_status_interface_state_t newInterfaceState); +#endif +static int pbx_capi_check_controller_status(struct capi_pvt *currentChannel, ast_group_t capigroup); /* * B protocol settings @@ -2478,7 +2484,7 @@ pbx_capi_request(const char *type, int format, void *data, int *cause) cc_mutex_lock(&iflock); for (i = capi_iflist; i; i = i->next) { - if ((i->used) || (i->channeltype != CAPI_CHANNELTYPE_B)) { + if (CC_B_INTERFACE_NOT_FREE(i)) { /* if already in use or no real channel */ continue; } @@ -2488,17 +2494,22 @@ pbx_capi_request(const char *type, int format, void *data, int *cause) if (i->controller != controller) { /* keep on running! */ continue; + } else if (pbx_capi_check_controller_status(i, 0) != 0) { + break; } } else { /* DIAL(CAPI/gX/...) */ - if ((interface[0] == 'g') && (!(i->group & capigroup))) { - /* keep on running! */ - continue; - } + if (interface[0] == 'g') { + if ((i->group & capigroup) == 0) + continue; /* not in group, keep on running! */ + if (pbx_capi_check_controller_status(i, capigroup) != 0) + continue; /* not active or better interface found, keep on running! */ + } else if (strcmp(interface, i->name) != 0) { /* DIAL(CAPI//...) */ - if ((interface[0] != 'g') && (strcmp(interface, i->name))) { /* keep on running! */ continue; + } else if (pbx_capi_check_controller_status(i, 0) != 0) { + break; } } /* when we come here, we found a free controller match */ @@ -7556,6 +7567,9 @@ static void *capidev_loop(void *data) if (lastcall != newtime) { lastcall = newtime; capidev_run_secondly(newtime); +#ifdef DIVA_STATUS + diva_status_process_events(); +#endif } #ifdef DIVA_STREAMING divaStreamingWakeup (); @@ -8479,6 +8493,9 @@ static int cc_post_init_capi(void) cc_verbose(2, 0, VERBOSE_PREFIX_3 "enable extended voice features on contr%d\n", controller); } +#ifdef DIVA_STATUS + capi_controllers[controller]->interfaceState = diva_status_init_interface(controller, pbx_capi_interface_status_changed); +#endif /* Register MWI mailboxes and refresh MWI info */ @@ -8890,6 +8907,9 @@ int unload_module(void) for (controller = 1; controller <= CAPI_MAX_CONTROLLERS; controller++) { if (capi_controllers[controller]) { pbx_capi_cleanup_mwi(capi_controllers[controller]); +#ifdef DIVA_STATUS + diva_status_cleanup_interface(controller); +#endif ast_free(capi_controllers[controller]); } } @@ -9095,3 +9115,76 @@ struct cc_capi_controller *pbx_capi_get_controller (int controller) { return ((controller > 0 && controller <= capi_num_controllers) ? capi_controllers[controller] : 0); } +#ifdef DIVA_STATUS +/*! + \brief Notify about interface state change + + \note No locks are taken at time this function is called + \note called from the context of CAPI thread + */ +static void pbx_capi_interface_status_changed(int controller, diva_status_interface_state_t newInterfaceState) +{ + int currentInterfaceState; + + cc_mutex_lock(&iflock); + currentInterfaceState = capi_controllers[controller]->interfaceState; + capi_controllers[controller]->interfaceState = newInterfaceState; + cc_mutex_unlock(&iflock); + + printf("CAPI%d: interface state changed %s -> %s\n", + controller, + diva_status_interface_state_name((diva_status_interface_state_t)currentInterfaceState), + diva_status_interface_state_name((diva_status_interface_state_t)newInterfaceState)); + cc_verbose(1, 0, VERBOSE_PREFIX_1 "CAPI%d: interface state changed %s -> %s\n", + controller, + diva_status_interface_state_name((diva_status_interface_state_t)currentInterfaceState), + diva_status_interface_state_name((diva_status_interface_state_t)newInterfaceState)); +} +#endif + +/*! \brief Check interface is operational. If the state of the interface + is not known then check if one with known state is available. + + \note Called with iflock taken + + \note The core runs twice over the interface list, but this allows to preserve + the structure of the original code which uses this function. + */ +static int pbx_capi_check_controller_status(struct capi_pvt *currentChannel, ast_group_t capigroup) +{ +#ifdef DIVA_STATUS + int capiController = currentChannel->controller; + struct capi_pvt *newChannel; + + if (capi_controllers[capiController]->interfaceState == (int)DivaStatusInterfaceStateOK) /* known, OK */ + return 0; + + if (capi_controllers[capiController]->interfaceState == (int)DivaStatusInterfaceStateERROR) /* known, not OK */ + return -1; + + /* + The state of interface is unknown. Look if it is other interface which belongs + to requested group with known state and free capi_pvt associated with this interface + */ + if ((capigroup == 0) || (diva_status_available() != 0)) + return (0); /* Status information not available, use this interface */ + + for (newChannel = currentChannel->next; (newChannel != 0); newChannel = newChannel->next) { + if (CC_B_INTERFACE_NOT_FREE(newChannel)) { + continue; + } + if ((newChannel->controller != capiController) && + ((newChannel->group & capigroup) != 0) && + (capi_controllers[newChannel->controller]->interfaceState == (int)DivaStatusInterfaceStateOK)) { + return (-1); /* Found better interface */ + } + } + + /* + No better channel found, use this interface + */ +#endif + + return 0; +} + diff --git a/chan_capi.h b/chan_capi.h index 91055b5..6a32025 100644 --- a/chan_capi.h +++ b/chan_capi.h @@ -700,6 +700,9 @@ struct cc_capi_controller { int divaStreaming; #endif AST_LIST_HEAD_NOLOCK(, _cc_capi_mwi_mailbox) mwiSubscribtions; +#ifdef DIVA_STATUS + int interfaceState; +#endif }; /* ETSI 300 102-1 Numbering Plans */ diff --git a/divastatus/divastatus.c b/divastatus/divastatus.c index 3f0fc7b..8101551 100644 --- a/divastatus/divastatus.c +++ b/divastatus/divastatus.c @@ -28,8 +28,12 @@ * */ #include "divastreaming/platform.h" +#include "chan_capi_platform.h" +#include "chan_capi20.h" +#include "chan_capi.h" #include #include +#include #include #include #include @@ -38,7 +42,9 @@ #include "divastatus_parameters.h" #include "divastatus_ifc.h" #include "divastatus.h" +#define CC_USE_INOTIFY #ifdef CC_USE_INOTIFY +#include #include #endif @@ -46,6 +52,7 @@ typedef const char* pcchar; static pcchar DIVA_STATUS_PATH = "/usr/lib/eicon/divas/registry/ifc"; static pcchar DIVA_STATUS_FILE = "ifcstate"; +static pcchar DIVA_INFO_FILE = "info"; static pcchar DIVA_CONFIG_FILE = "info/Config"; static pcchar DIVA_SERIAL_FILE = "serial"; static pcchar DIVA_READ_ALARM_FILE = "info/Red Alarm"; @@ -55,9 +62,223 @@ static pcchar DIVA_BLUE_ALARM_FILE = "info/Blue Alarm"; /* LOCALS */ +struct _diva_status_ifc; 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); +static void diva_status_create_wd(int* wd, int controller, const char* fileName, int isDir); +static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state (diva_status_ifc_state_t* state); +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 + +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; + diva_status_changed_cb_proc_t status_changed_notify_proc; + time_t changeTime; +} diva_status_ifc_t; + +diva_status_interface_state_t diva_status_init_interface (int controller, diva_status_changed_cb_proc_t fn) +{ + 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; + controllerState->status_changed_notify_proc = fn; + 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]); + } + + 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); + + if (initialIfcState != newIfcState) { + controllerState->changeTime = time(NULL); + controllerState->status_changed_notify_proc(controllerState->capiController, newIfcState); + } +} + +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 +} /*! \brief Check divalogd is available @@ -92,18 +313,20 @@ static char* diva_status_read_file(unsigned int controller, const char* fileName length = MIN(v.st_size, 16U*1024U); - data = diva_os_malloc(0, length+1); + data = ast_malloc(length+1); if (data == 0) { close (fd); return 0; } if (read(fd, data, length) != length) { - diva_os_free(0, data); + ast_free(data); close(fd); return (0); } + close (fd); + data[length] = 0; while (((p = strchr(data, '\n')) != 0) || ((p = strchr(data, '\r')))) { @@ -119,6 +342,12 @@ static int diva_status_get_controller_state(int controller, diva_status_ifc_stat int i, pri; const char* v; + memset (state, 0x00, sizeof(*state)); + state->ifcType = DivaStatusIfcNotPri; + state->hwState = DivaStatusHwStateUnknown; + state->ifcL1State = DivaStatusIfcL2DoNotApply; + state->ifcL2State = DivaStatusIfcL2DoNotApply; + if (diva_status_active() != 0) return -1; @@ -128,6 +357,15 @@ static int diva_status_get_controller_state(int controller, diva_status_ifc_stat for (i = 0, pri = 0, p = data, v = strsep(&p, ","); v != 0 && i < DivaStateIfcConfig_Max; v = strsep(&p, ","), i++) { + 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] != '\'')); + } + switch ((diva_state_ifc_config_parameters_t)i) { case DivaStateIfcConfig_TYPE: pri += (strcmp ("PRI", v) == 0); @@ -141,20 +379,24 @@ static int diva_status_get_controller_state(int controller, diva_status_ifc_stat break; } } - diva_os_free(0, data); + ast_free(data); + + state->ifcType = (pri == 2) ? DivaStatusIfcPri : DivaStatusIfcNotPri; if ((data = diva_status_read_file(controller, DIVA_STATUS_FILE)) == 0) return (-1); - memset (state, 0x00, sizeof(*state)); - state->ifcType = (pri == 2) ? DivaStatusIfcPri : DivaStatusIfcNotPri; - state->hwState = DivaStatusHwStateUnknown; - state->ifcL1State = DivaStatusIfcL2DoNotApply; - state->ifcL2State = DivaStatusIfcL2DoNotApply; - for (i = 0, p = data, v = strsep (&p, ","); v != 0 && i < (int)DivaStateIfcState_Max; v = strsep (&p, ","), i++) { - switch ((diva_state_ifcstate_parameters_t)i) { + 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] != '\'')); + } + switch ((diva_state_ifcstate_parameters_t)i) { case DivaStateIfcState_LAYER1_STATE: if (state->ifcType == DivaStatusIfcPri) { state->ifcL1State = (strcmp ("'Activated'", v) == 0) ? DivaStatusIfcL1OK : DivaStatusIfcL1Error; @@ -168,35 +410,35 @@ static int diva_status_get_controller_state(int controller, diva_status_ifc_stat break; case DivaStateIfcState_D2_X_FRAMES: - state->ifcTxDStatistics.Frames = (unsigned int)atol(data); + state->ifcTxDStatistics.Frames = (unsigned int)atol(v); break; case DivaStateIfcState_D2_X_BYTES: - state->ifcTxDStatistics.Bytes = (unsigned int)atol(data); + state->ifcTxDStatistics.Bytes = (unsigned int)atol(v); break; case DivaStateIfcState_D2_X_ERRORS: - state->ifcTxDStatistics.Errors = (unsigned int)atol(data); + state->ifcTxDStatistics.Errors = (unsigned int)atol(v); break; case DivaStateIfcState_D2_R_FRAMES: - state->ifcRxDStatistics.Frames = (unsigned int)atol(data); + state->ifcRxDStatistics.Frames = (unsigned int)atol(v); break; case DivaStateIfcState_D2_R_BYTES: - state->ifcRxDStatistics.Bytes = (unsigned int)atol(data); + state->ifcRxDStatistics.Bytes = (unsigned int)atol(v); break; case DivaStateIfcState_D2_R_ERRORS: - state->ifcRxDStatistics.Errors = (unsigned int)atol(data); + state->ifcRxDStatistics.Errors = (unsigned int)atol(v); break; case DivaStateIfcState_MAX_TEMPERATURE: - state->maxTemperature = (unsigned int)atoi(data); + state->maxTemperature = (unsigned int)atoi(v); break; case DivaStateIfcState_TEMPERATURE: - state->currentTemperature = (unsigned int)atoi(data); + state->currentTemperature = (unsigned int)atoi(v); break; case DivaStateIfcState_HARDWARE_STATE: - if (strcmp("'Active'", data) == 0) + if (strcmp("'Active'", v) == 0) state->hwState = DivaStateHwStateActive; - else if (strcmp("'Inactive'", data) == 0) + else if (strcmp("'Inactive'", v) == 0) state->hwState = DivaStateHwStateInactive; break; @@ -204,23 +446,23 @@ static int diva_status_get_controller_state(int controller, diva_status_ifc_stat break; } } - diva_os_free (0, data); + ast_free (data); if ((data = diva_status_read_file(controller, DIVA_READ_ALARM_FILE)) != 0) { state->ifcAlarms.Red = strcmp("TRUE", data); - diva_os_free(0, data); + ast_free(data); } if ((data = diva_status_read_file(controller, DIVA_YELLOW_ALARM_FILE)) != 0) { state->ifcAlarms.Yellow = strcmp("TRUE", data); - diva_os_free(0, data); + ast_free(data); } if ((data = diva_status_read_file(controller, DIVA_BLUE_ALARM_FILE)) != 0) { state->ifcAlarms.Blue = strcmp("TRUE", data); - diva_os_free(0, data); + ast_free(data); } if ((data = diva_status_read_file(controller, DIVA_SERIAL_FILE)) != 0) { state->serialNumber = (unsigned int)(atol(data)) & 0x00ffffff; - diva_os_free(0, data); + ast_free(data); } return (0); @@ -254,3 +496,53 @@ diva_status_interface_state_t diva_status_get_interface_state(int controller) return DivaStatusInterfaceStateERROR; } +static diva_status_interface_state_t diva_status_get_interface_state_from_idi_state (diva_status_ifc_state_t* state) { + 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; +} + +/*! + \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) +{ + switch (state) { + case DivaStatusInterfaceStateOK: + return "active"; + + case DivaStatusInterfaceStateERROR: + return "inactive"; + + case DivaStatusInterfaceStateNotAvailable: + default: + return "not available"; + } +} diff --git a/divastatus/divastatus_ifc.h b/divastatus/divastatus_ifc.h index f377f52..c967658 100644 --- a/divastatus/divastatus_ifc.h +++ b/divastatus/divastatus_ifc.h @@ -27,28 +27,35 @@ #define __DIVA_STATUS_IFC_H__ typedef enum _diva_status_interface_state { - DivaStatusInterfaceStateNotAvailable = -1, - DivaStatusInterfaceStateOK = 0, - DivaStatusInterfaceStateERROR = 1, + DivaStatusInterfaceStateNotAvailable = 0, + DivaStatusInterfaceStateOK = 1, + DivaStatusInterfaceStateERROR = -1, } diva_status_interface_state_t; +/*! + \brief Check if Diva interface is available + */ +int diva_status_available(void); + +typedef void (*diva_status_changed_cb_proc_t)(int controller, diva_status_interface_state_t state); + /*! \brief activate event based status notifications */ -void diva_status_init_interface (int controller); +diva_status_interface_state_t diva_status_init_interface(int controller, diva_status_changed_cb_proc_t fn); /*! \brief deactivate event based status notifications */ -void diva_status_cleanup_interface (int controller); +void diva_status_cleanup_interface(int controller); /*! \brief retrieve file handle to be used in async I/O operations */ -int diva_status_get_waitable_object (void); +int diva_status_get_waitable_object(void); /*! \brief process status change events */ -void diva_status_process_events (void); +void diva_status_process_events(void); /*! \brief Retrieve state of interface @@ -57,8 +64,9 @@ void diva_status_process_events (void); DivaStatusInterfaceStateERROR - interface state verified and can not be used to create calls */ -diva_status_interface_state_t diva_status_get_interface_state (int controller); +diva_status_interface_state_t diva_status_get_interface_state(int controller); +const char* diva_status_interface_state_name(diva_status_interface_state_t state); diff --git a/divastatus/divastatus_parameters.h b/divastatus/divastatus_parameters.h index 3728d87..f8b9c9e 100644 --- a/divastatus/divastatus_parameters.h +++ b/divastatus/divastatus_parameters.h @@ -109,7 +109,7 @@ typedef enum _diva_state_ifcstate_parameters { } diva_state_ifcstate_parameters_t; typedef enum diva_state_ifc_config_parameters { - DivaStateIfcConfig_TYPE, + DivaStateIfcConfig_TYPE = 0, DivaStateIfcConfig_CHANNELS, DivaStateIfcConfig_PROTOCOL, DivaStateIfcConfig_NT_MODE,