wanpipe/api/libsangoma/.svn/tmp/tempfile.13.tmp

2376 lines
62 KiB
Plaintext

/*******************************************************************************//**
* \file libsangoma.c
* \brief Wanpipe API Code Library for Sangoma AFT T1/E1/Analog/BRI/Serial hardware
*
* Author(s): Nenad Corbic <ncorbic@sangoma.com>
* David Rokhvarg <davidr@sangoma.com>
* Michael Jerris <mike@jerris.com>
* Anthony Minessale II <anthmct@yahoo.com>
*
* Copyright: (c) 2005-2008 Nenad Corbic <ncorbic@sangoma.com>
*
* * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the Sangoma Technologies nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Sangoma Technologies ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Sangoma Technologies BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*******************************************************************************
*/
#include "libsangoma-pvt.h"
static void libsng_dbg(const char * fmt, ...)
{
va_list args;
char buf[1024];
va_start(args, fmt);
_vsnprintf(buf, sizeof(buf), fmt, args);
#if defined(__WINDOWS__)
OutputDebugString(buf);
#else
printf(buf);
#endif
va_end(args);
}
/*********************************************************************//**
* WINDOWS Only Section
*************************************************************************/
#define DBG_POLL if(0)libsng_dbg
#define DBG_EVNT if(0)libsng_dbg
#define DBG_ERR if(0)libsng_dbg("Error: %s() line: %d : ", __FUNCTION__, __LINE__);if(0)libsng_dbg
#define DBG_INIT if(0)libsng_dbg
#if defined(__WINDOWS__)
/*
\fn static void DecodeLastError(LPSTR lpszFunction)
\brief Decodes the Error in radable format.
\param lpszFunction error string
Private Windows Only Function
*/
static void DecodeLastError(LPSTR lpszFunction)
{
LPVOID lpMsgBuf;
DWORD dwLastErr = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dwLastErr,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
// Display the string.
DBG_POLL("Last Error in %s(): %s (%d)\n", lpszFunction, lpMsgBuf, dwLastErr);
// Free the buffer.
LocalFree( lpMsgBuf );
}
/*
\fn static int handle_device_ioctl_result(int bResult)
\brief Checks result code of ioctl
\param bResult result of ioctl call
Private Windows Only Function
*/
static u16 handle_device_ioctl_result(int bResult, char *caller_name)
{
if(bResult == 0){
//error
DecodeLastError(caller_name);
return 1;
}else{
return 0;
}
}
/*
\fn static int DoManagementCommand(HANDLE fd, wan_udp_hdr_t* wan_udp)
\brief Executes Driver Management Command
\param fd device file descriptor
\param wan_udp managemet cmd structure
Private Windows Function
*/
static int DoManagementCommand(HANDLE fd, wan_udp_hdr_t* wan_udp)
{
DWORD ln, bIoResult;
unsigned char id = 0;
wan_udp->wan_udphdr_request_reply = 0x01;
wan_udp->wan_udphdr_id = id;
wan_udp->wan_udphdr_return_code = WAN_UDP_TIMEOUT_CMD;
bIoResult = DeviceIoControl(
fd,
IoctlManagementCommand,
(LPVOID)wan_udp,
sizeof(wan_udp_hdr_t),
(LPVOID)wan_udp,
sizeof(wan_udp_hdr_t),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
);
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
}
/*
\fn static int DoTdmvApiCommand(HANDLE fd, wanpipe_tdm_api_cmd_t *api_cmd)
\brief Executes Driver TDM API Command
\param fd device file descriptor
\param api_cmd tdm_api managemet cmd structure
Private Windows Function
*/
static int DoTdmvApiCommand(HANDLE fd, wanpipe_tdm_api_cmd_t *api_cmd)
{
DWORD ln, bIoResult;
bIoResult = DeviceIoControl(
fd,
IoctlTdmApiCommand,
(LPVOID)api_cmd,
sizeof(wanpipe_tdm_api_cmd_t),
(LPVOID)api_cmd,
sizeof(wanpipe_tdm_api_cmd_t),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
);
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
}
/*
\fn static int tdmv_api_ioctl(HANDLE fd, wanpipe_tdm_api_cmd_t *api_cmd)
\brief Executes Driver TDM API Command Wrapper Function
\param fd device file descriptor
\param api_cmd tdm_api managemet cmd structure
Private Windows Function
*/
static int tdmv_api_ioctl(HANDLE fd, wanpipe_tdm_api_cmd_t *api_cmd)
{
if(DoTdmvApiCommand(fd, api_cmd)){
return SANG_STATUS_GENERAL_ERROR;
}
return api_cmd->result;
}
/*
\fn static USHORT DoReadCommand(HANDLE drv, RX_DATA_STRUCT * pRx)
\brief API READ Function
\param drv device file descriptor
\param pRx receive data structure
Private Windows Function
This function will NOT block because using IoctlReadCommandNonBlocking.
*/
static USHORT DoReadCommand(HANDLE drv, RX_DATA_STRUCT * pRx)
{
DWORD ln, bIoResult;
bIoResult = DeviceIoControl(
drv,
IoctlReadCommandNonBlocking,
(LPVOID)NULL,//NO input buffer!
0,
(LPVOID)pRx,
sizeof(RX_DATA_STRUCT),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL);
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
}
/*
\fn static UCHAR DoWriteCommand(HANDLE drv, TX_DATA_STRUCT * pTx)
\brief API Write Function
\param drv device file descriptor
\param pRx receive data structure
Private Windows Function
In Legacy API mode this fuction will Block if data is busy.
In API mode no function is allowed to Block
*/
static UCHAR DoWriteCommand(HANDLE drv,
void *input_data_buffer, u32 size_of_input_data_buffer,
void *output_data_buffer, u32 size_of_output_data_buffer
)
{
DWORD BytesReturned, bIoResult;
bIoResult = DeviceIoControl(
drv,
IoctlWriteCommand,
(LPVOID)input_data_buffer,
size_of_input_data_buffer,
(LPVOID)output_data_buffer,
size_of_output_data_buffer,
(LPDWORD)(&BytesReturned),
(LPOVERLAPPED)NULL);
return (UCHAR)handle_device_ioctl_result(bIoResult, __FUNCTION__);
}
/*
\fn static USHORT sangoma_poll_fd(HANDLE drv, API_POLL_STRUCT *api_poll_ptr)
\brief Non Blocking API Poll function used to find out if Rx Data, Events or
Free Tx buffer available
\param drv device file descriptor
\param api_poll_ptr poll device that stores polling information read/write/event
\param overlapped pointer to system overlapped io structure.
Private Windows Function
*/
static USHORT sangoma_poll_fd(sng_fd_t fd, API_POLL_STRUCT *api_poll_ptr)
{
DWORD ln, bIoResult;
bIoResult = DeviceIoControl(
fd,
IoctlApiPoll,
(LPVOID)NULL,
0L,
(LPVOID)api_poll_ptr,
sizeof(API_POLL_STRUCT),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL);
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
}
static USHORT DoSetSharedEventCommand(HANDLE drv, PREGISTER_EVENT event)
{
DWORD ln, bIoResult;
bIoResult = DeviceIoControl(
drv,
IoctlSetSharedEvent,
(LPVOID)event,
sizeof(REGISTER_EVENT),
(LPVOID)event,
sizeof(REGISTER_EVENT),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL);
return handle_device_ioctl_result(bIoResult, __FUNCTION__);
}
static int init_sangoma_event_object(sangoma_wait_obj_t *sng_wait_obj, int flags_in)
{
int event_index = -1;
if(flags_in & POLLIN){
event_index = LIBSNG_EVENT_INDEX_POLLIN;
}
if(flags_in & POLLOUT){
event_index = LIBSNG_EVENT_INDEX_POLLOUT;
}
if(flags_in & POLLPRI){
event_index = LIBSNG_EVENT_INDEX_POLLPRI;
}
if(event_index == -1){
/* invalid 'flags_in', this should be an assert */
return SANG_STATUS_GENERAL_ERROR;
}
sng_wait_obj->sng_event_objects[event_index].hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
if(!sng_wait_obj->sng_event_objects[event_index].hEvent){
//error
return SANG_STATUS_GENERAL_ERROR;
}
sng_wait_obj->sng_event_objects[event_index].user_flags_bitmap = flags_in;
if(DoSetSharedEventCommand(sng_wait_obj->fd, &sng_wait_obj->sng_event_objects[event_index])){
//error
return SANG_STATUS_GENERAL_ERROR;
}
return sng_wait_obj->sng_event_objects[event_index].operation_status;
}
static void sangoma_reset_wait_obj(sangoma_wait_obj_t *sng_wait_obj, int flags_in)
{
if(flags_in & POLLIN){
if(sng_wait_obj->sng_event_objects[LIBSNG_EVENT_INDEX_POLLIN].hEvent){
ResetEvent(sng_wait_obj->sng_event_objects[LIBSNG_EVENT_INDEX_POLLIN].hEvent);
}
}
if(flags_in & POLLOUT){
if(sng_wait_obj->sng_event_objects[LIBSNG_EVENT_INDEX_POLLOUT].hEvent){
ResetEvent(sng_wait_obj->sng_event_objects[LIBSNG_EVENT_INDEX_POLLOUT].hEvent);
}
}
if(flags_in & POLLPRI){
if(sng_wait_obj->sng_event_objects[LIBSNG_EVENT_INDEX_POLLPRI].hEvent){
ResetEvent(sng_wait_obj->sng_event_objects[LIBSNG_EVENT_INDEX_POLLPRI].hEvent);
}
}
}
static sangoma_status_t _SAPI_CALL sangoma_wait_obj_poll(sangoma_wait_obj_t *sangoma_wait_object, int flags_in, int *flags_out)
{
int err;
sangoma_wait_obj_t *sng_wait_obj = sangoma_wait_object;
/*! api structure used by windows IoctlApiPoll call */
API_POLL_STRUCT api_poll;
*flags_out = 0;
memset(&api_poll, 0x00, sizeof(API_POLL_STRUCT));
api_poll.user_flags_bitmap = flags_in;
/* This call is non-blocking - it will return immediatly. */
if(sangoma_poll_fd(sng_wait_obj->fd, &api_poll)){
/* error - ioctl failed */
return SANG_STATUS_IO_ERROR;
}
if(api_poll.operation_status == SANG_STATUS_SUCCESS){
*flags_out = api_poll.poll_events_bitmap;
err = 0;
}else{
/* error - command failed */
err = api_poll.operation_status;
}
if(*flags_out == 0){
DBG_POLL("======%s(): *flags_out: 0x%X, flags_in: 0x%X\n", __FUNCTION__, *flags_out, flags_in);
}
return err;
}
static int check_number_of_wait_objects(uint32_t number_of_objects, const char *caller_function, int lineno)
{
if(number_of_objects >= MAXIMUM_WAIT_OBJECTS){
DBG_ERR("Caller: %s(): Line: %d: 'number_of_objects': %d is greater than the Maximum of: %d\n",
caller_function, lineno, number_of_objects, MAXIMUM_WAIT_OBJECTS);
return 1;
}
return 0;
}
static sangoma_status_t get_out_flags(IN sangoma_wait_obj_t *sng_wait_objects[],
IN uint32_t in_flags[], OUT uint32_t out_flags[],
IN uint32_t number_of_sangoma_wait_objects,
IN BOOL reset_events_if_out_flags_set,
OUT BOOL *at_least_one_poll_set_flags_out)
{
uint32_t i, j;
if(at_least_one_poll_set_flags_out){
*at_least_one_poll_set_flags_out = FALSE;
}
for(i = 0; i < number_of_sangoma_wait_objects; i++) {
sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i];
if (!SANGOMA_OBJ_HAS_DEVICE(sangoma_wait_object)) {
continue;
}
for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){
if(!sangoma_wait_object->sng_event_objects[j].hEvent) {
continue;
}
if(sangoma_wait_obj_poll(sangoma_wait_object, in_flags[i], &out_flags[i])){
return SANG_STATUS_GENERAL_ERROR;
}
if( out_flags[i] & in_flags[i] ){
if(TRUE == reset_events_if_out_flags_set){
sangoma_reset_wait_obj(sangoma_wait_object, out_flags[i]);/* since we are NOT going to wait on this event, reset it 'manually' */
}
if(at_least_one_poll_set_flags_out){
*at_least_one_poll_set_flags_out = TRUE;
}
}
}
}
return SANG_STATUS_SUCCESS;
}
#endif /* __WINDOWS__ */
/*********************************************************************//**
* Common Linux & Windows Code
*************************************************************************/
/************************************************************//**
* Device POLL Functions
***************************************************************/
/*!
\fn sangoma_status_t sangoma_wait_obj_create(sangoma_wait_obj_t **sangoma_wait_object, sng_fd_t fd, sangoma_wait_obj_type_t object_type)
\brief Create a wait object that will be used with sangoma_waitfor_many() API
\param sangoma_wait_object pointer a single device object
\param fd device file descriptor
\param object_type type of the wait object. see sangoma_wait_obj_type_t for types
\see sangoma_wait_obj_type_t
\return SANG_STATUS_SUCCESS: success, or error status
*/
sangoma_status_t _SAPI_CALL sangoma_wait_obj_create(sangoma_wait_obj_t **sangoma_wait_object, sng_fd_t fd, sangoma_wait_obj_type_t object_type)
{
int err = 0;
sangoma_wait_obj_t *sng_wait_obj;
if (!sangoma_wait_object) {
return SANG_STATUS_INVALID_DEVICE;
}
*sangoma_wait_object = NULL;
sng_wait_obj = malloc(sizeof(**sangoma_wait_object));
if (!sng_wait_obj) {
return SANG_STATUS_FAILED_ALLOCATE_MEMORY;
}
memset(sng_wait_obj, 0x00, sizeof(*sng_wait_obj));
/* it is a first initialization of the object */
sng_wait_obj->init_flag = LIBSNG_MAGIC_NO;
sng_wait_obj->fd = fd;
sng_wait_obj->object_type = object_type;
#if defined(__WINDOWS__)
DBG_INIT("%s(): sng_wait_obj ptr: 0x%p\n", __FUNCTION__, sng_wait_obj);
DBG_INIT("%s(): fd: 0x%X, object_type: %s\n", __FUNCTION__, fd, DECODE_SANGOMA_WAIT_OBJECT_TYPE(object_type));
DBG_INIT("%s(): sizeof(**sangoma_wait_object): %d\n", __FUNCTION__, sizeof(**sangoma_wait_object));
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
sng_wait_obj->generic_event_object.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL);
if(!sng_wait_obj->generic_event_object.hEvent){
return SANG_STATUS_GENERAL_ERROR;
}
}
if(SANGOMA_GENERIC_WAIT_OBJ == object_type){
/* everything is done for the generic wait object */
*sangoma_wait_object = sng_wait_obj;
return SANG_STATUS_SUCCESS;
}
err = init_sangoma_event_object(sng_wait_obj, POLLIN /* must be a SINGLE bit because there is a signaling object for each bit */);
if(SANG_STATUS_SUCCESS != err){
return err;
}
err = init_sangoma_event_object(sng_wait_obj, POLLOUT /* must be a SINGLE bit because there is a signaling object for each bit */);
if(SANG_STATUS_SUCCESS != err){
return err;
}
err = init_sangoma_event_object(sng_wait_obj, POLLPRI /* must be a SINGLE bit because there is a signaling object for each bit */);
if(SANG_STATUS_SUCCESS != err) {
return err;
}
DBG_INIT("%s(): returning: %d", __FUNCTION__, err);
#else
int filedes[2];
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
sng_wait_obj->signal_read_fd = INVALID_HANDLE_VALUE;
sng_wait_obj->signal_write_fd = INVALID_HANDLE_VALUE;
/* if we want cross-process event notification we can use a named pipe with mkfifo() */
if (pipe(filedes)) {
return -1;
}
sng_wait_obj->signal_read_fd = filedes[0];
sng_wait_obj->signal_write_fd = filedes[1];
}
#endif
*sangoma_wait_object = sng_wait_obj;
return err;
}
/*!
\fn sangoma_status_t sangoma_wait_obj_delete(sangoma_wait_obj_t **sangoma_wait_object)
\brief De-allocate all resources in a wait object
\param sangoma_wait_object pointer to a pointer to a single device object
\return SANG_STATUS_SUCCESS on success or some sangoma status error
*/
sangoma_status_t _SAPI_CALL sangoma_wait_obj_delete(sangoma_wait_obj_t **sangoma_wait_object)
{
sangoma_wait_obj_t *sng_wait_obj = *sangoma_wait_object;
#if defined(__WINDOWS__)
int index = 0;
#endif
if(sng_wait_obj->init_flag != LIBSNG_MAGIC_NO){
/* error. object was not initialized by sangoma_wait_obj_init() */
return SANG_STATUS_INVALID_DEVICE;
}
#if defined(__WINDOWS__)
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
sangoma_close(&sng_wait_obj->generic_event_object.hEvent);
}
if (SANGOMA_OBJ_HAS_DEVICE(sng_wait_obj)) {
for(index = 0; index < LIBSNG_NUMBER_OF_EVENT_OBJECTS; index++){
sangoma_close(&sng_wait_obj->sng_event_objects[index].hEvent);
}
}
#else
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
sangoma_close(&sng_wait_obj->signal_read_fd);
sangoma_close(&sng_wait_obj->signal_write_fd);
}
#endif
sng_wait_obj->init_flag = 0;
sng_wait_obj->object_type = UNKNOWN_WAIT_OBJ;
*sangoma_wait_object = NULL;
return SANG_STATUS_SUCCESS;
}
/*!
\fn void sangoma_wait_obj_signal(void *sangoma_wait_object)
\brief Set wait object to a signaled state
\param sangoma_wait_object pointer a single device object
\return 0 on success, non-zero on error
*/
int _SAPI_CALL sangoma_wait_obj_signal(sangoma_wait_obj_t *sng_wait_obj)
{
if (!SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_obj)) {
/* even when Windows objects are always signalable for the sake of providing
* a consistent interface to the user we downgrade the capabilities of Windows
* objects unless the sangoma wait object is explicitly initialized as signalable
* */
return SANG_STATUS_INVALID_DEVICE;
}
#if defined(__WINDOWS__)
if(sng_wait_obj->generic_event_object.hEvent){
if (!SetEvent(sng_wait_obj->generic_event_object.hEvent)) {
return SANG_STATUS_GENERAL_ERROR;
}
}
#else
/* at this point we know is a signalable object and has a signal_write_fd */
if (write(sng_wait_obj->signal_write_fd, "s", 1) < 1) {
return SANG_STATUS_GENERAL_ERROR;
}
#endif
return SANG_STATUS_SUCCESS;
}
/*!
\fn sng_fd_t sangoma_wait_obj_get_fd(void *sangoma_wait_object)
\brief Retrieve fd device file descriptor which was the 'fd' parameter for sangoma_wait_obj_init()
\param sangoma_wait_object pointer a single device object
\return fd - device file descriptor
*/
sng_fd_t _SAPI_CALL sangoma_wait_obj_get_fd(sangoma_wait_obj_t *sng_wait_obj)
{
return sng_wait_obj->fd;
}
/*!
\fn void sangoma_wait_obj_set_context(sangoma_wait_obj_t *sangoma_wait_object)
\brief Store the given context into provided sangoma wait object.
\brief This function is useful to associate a context with a sangoma wait object.
\param sangoma_wait_object pointer a single device object
\param context void pointer to user context
\return void
*/
void _SAPI_CALL sangoma_wait_obj_set_context(sangoma_wait_obj_t *sng_wait_obj, void *context)
{
sng_wait_obj->context = context;
}
/*!
\fn void *sangoma_wait_obj_get_context(sangoma_wait_obj_t *sangoma_wait_object)
\brief Retrieve the user context (if any) that was set via sangoma_wait_obj_set_context.
\param sangoma_wait_object pointer a single device object
\return void*
*/
void* _SAPI_CALL sangoma_wait_obj_get_context(sangoma_wait_obj_t *sng_wait_obj)
{
return sng_wait_obj->context;
}
/*!
\fn sangoma_status_t _SAPI_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sangoma_wait_objects[], int32_t in_flags[], int32_t out_flags[] uint32_t number_of_sangoma_wait_objects, int32_t system_wait_timeout);
\brief Wait for multiple sangoma waitable objects
\param sangoma_wait_objects pointer to array of wait objects previously created with sangoma_wait_obj_create
\param in_flags array of flags corresponding to the flags the user is interested on for each waitable object
\param out_flags array of flags corresponding to the flags that are ready in the waitable objects
\param number_of_sangoma_wait_objects size of the array of waitable objects and flags
\param system_wait_timeout timeout in miliseconds in case of no event
\return negative: SANG_STATUS_APIPOLL_TIMEOUT: timeout, SANG_STATUS_SUCCESS: event occured check in sangoma_wait_objects, any other return code is some error
*/
sangoma_status_t _SAPI_CALL sangoma_waitfor_many(sangoma_wait_obj_t *sng_wait_objects[], uint32_t in_flags[], uint32_t out_flags[],
uint32_t number_of_sangoma_wait_objects, int32_t system_wait_timeout)
{
#if defined(__WINDOWS__)
HANDLE hEvents[MAXIMUM_WAIT_OBJECTS];
int at_least_one_poll_set_flags_out, number_of_internal_signaling_objects, err;
#endif
uint32_t i = 0, j = 0;
memset(out_flags, 0x00, number_of_sangoma_wait_objects * sizeof(out_flags[0]));
#if defined(__WINDOWS__)
/* This loop will calculate 'number_of_internal_signaling_objects' and will initialize 'hEvents'
* based on 'number_of_sangoma_wait_objects' and 'in_flags'. */
number_of_internal_signaling_objects = 0;
for(i = 0; i < number_of_sangoma_wait_objects; i++){
sangoma_wait_obj_t *sangoma_wait_object = sng_wait_objects[i];
/* if SANGOMA_OBJ_IS_SIGNALABLE add the generic_event_object.hEvent to the hEvents */
if(sangoma_wait_object->generic_event_object.hEvent){
if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){
return SANG_STATUS_NO_FREE_BUFFERS;
}
hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->generic_event_object.hEvent;
number_of_internal_signaling_objects++;
}
for(j = 0; j < LIBSNG_NUMBER_OF_EVENT_OBJECTS; j++){
if(sangoma_wait_object->sng_event_objects[j].hEvent){
if( ((j == LIBSNG_EVENT_INDEX_POLLIN) && (in_flags[i] & POLLIN)) ||
((j == LIBSNG_EVENT_INDEX_POLLOUT) && (in_flags[i] & POLLOUT)) ||
((j == LIBSNG_EVENT_INDEX_POLLPRI) && (in_flags[i] & POLLPRI)) ){
if(check_number_of_wait_objects(number_of_internal_signaling_objects, __FUNCTION__, __LINE__)){
return SANG_STATUS_NO_FREE_BUFFERS;
}
hEvents[number_of_internal_signaling_objects] = sangoma_wait_object->sng_event_objects[j].hEvent;
number_of_internal_signaling_objects++;
}
}/* if () */
}/* for() */
}/* for() */
if(number_of_internal_signaling_objects < 1){
DBG_ERR("'number_of_internal_signaling_objects': %d is less than the Minimum of: 1!\n",
number_of_internal_signaling_objects);
/* error - most likely the user did not initialize sng_wait_objects[] */
return SANG_STATUS_INVALID_PARAMETER;
}
at_least_one_poll_set_flags_out = FALSE;
/* It is important to get 'out flags' BEFORE the WaitForMultipleObjects()
* because it allows to keep API driver's transmit queue full. */
err = get_out_flags(sng_wait_objects, in_flags, out_flags, number_of_sangoma_wait_objects, TRUE, &at_least_one_poll_set_flags_out);
if(SANG_ERROR(err)){
return err;
}
if(TRUE == at_least_one_poll_set_flags_out){
return SANG_STATUS_SUCCESS;
}
/* wait untill at least one of the events is signaled OR a 'system_wait_timeout' occured */
if (WAIT_TIMEOUT == WaitForMultipleObjects(number_of_internal_signaling_objects, &hEvents[0], FALSE, system_wait_timeout)){
return SANG_STATUS_APIPOLL_TIMEOUT;
}
/* WaitForMultipleObjects() was waken by a Sangoma or by a non-Sangoma wait object. */
err = get_out_flags(sng_wait_objects, in_flags, out_flags, number_of_sangoma_wait_objects, TRUE, NULL);
if(SANG_ERROR(err)){
return err;
}
return SANG_STATUS_SUCCESS;
#else
struct pollfd pfds[number_of_sangoma_wait_objects*2]; /* we need twice as many polls because of the sangoma signalable objects */
char dummy_buf[1];
int res;
j = 0;
memset(pfds, 0, sizeof(pfds));
for(i = 0; i < number_of_sangoma_wait_objects; i++){
if (SANGOMA_OBJ_HAS_DEVICE(sng_wait_objects[i])) {
pfds[i].fd = sng_wait_objects[i]->fd;
pfds[i].events = in_flags[i];
}
if (SANGOMA_OBJ_IS_SIGNALABLE(sng_wait_objects[i])) {
pfds[number_of_sangoma_wait_objects+j].fd = sng_wait_objects[i]->signal_read_fd;
pfds[number_of_sangoma_wait_objects+j].events = POLLIN;
j++;
}
}
poll_try_again:
res = poll(pfds, (number_of_sangoma_wait_objects + j), system_wait_timeout);
if (res > 0) {
for(i = 0; i < number_of_sangoma_wait_objects; i++){
out_flags[i] = pfds[i].revents;
}
for(i = 0; i < j; i++){
/* TODO: we must do something extra for signalled objects like setting a flag.
* current user of the SANGOMA_OBJ_IS_SIGNALABLE feature is Netborder and they dont
* need to know which object was signaled. If we want to know which object was signaled
* we need a new libsangoma API sangoma_wait_obj_is_signaled() where in Windows we can
* use WaitForSingleObject to test the signaled state and in Linux we can set a flag in
* sng_wait_obj
* */
if (pfds[number_of_sangoma_wait_objects+i].revents & POLLIN) {
/* read and discard the signal byte */
read(pfds[number_of_sangoma_wait_objects+i].fd, &dummy_buf, 1);
}
}
} else if (res < 0 && errno == EINTR) {
/* TODO: decrement system_wait_timeout */
goto poll_try_again;
}
if (res < 0) {
return SANG_STATUS_GENERAL_ERROR;
}
if (res == 0) {
return SANG_STATUS_APIPOLL_TIMEOUT;
}
return SANG_STATUS_SUCCESS;
#endif
}
/*!
\fn sangoma_status_t _SAPI_CALL sangoma_waitfor(sangoma_wait_obj_t *sangoma_wait_obj, int32_t inflags, int32_t *outflags, int32_t timeout)
\brief Wait for a single waitable object
\param sangoma_wait_obj pointer to array of file descriptors to wait for
\param timeout timeout in miliseconds in case of no event
\return SANG_STATUS_APIPOLL_TIMEOUT: timeout, SANG_STATUS_SUCCESS: event occured use sangoma_wait_obj_get_out_flags to check or error status
*/
sangoma_status_t _SAPI_CALL sangoma_waitfor(sangoma_wait_obj_t *sangoma_wait_obj, uint32_t inflags, uint32_t *outflags, int32_t timeout)
{
return sangoma_waitfor_many(&sangoma_wait_obj, &inflags, outflags, 1, timeout);
}
/************************************************************//**
* Device OPEN / CLOSE Functions
***************************************************************/
int _SAPI_CALL sangoma_span_chan_toif(int span, int chan, char *interface_name)
{
#if defined(__WINDOWS__)
/* FIXME: Not implemented */
return -1;
#else
sprintf(interface_name,"s%ic%i",span,chan);
#endif
return 0;
}
int _SAPI_CALL sangoma_interface_toi(char *interface_name, int *span, int *chan)
{
char *p=NULL, *sp = NULL, *ch = NULL;
int ret = 0;
char data[FNAME_LEN];
strncpy(data, interface_name, FNAME_LEN);
if ((data[0])) {
for (p = data; *p; p++) {
if (sp && *p == 'g') {
*p = '\0';
ch = (p + 1);
break;
} else if (*p == 'w') {
sp = (p + 1);
}
}
if(ch && sp) {
*span = atoi(sp);
*chan = atoi(ch);
ret = 1;
} else {
*span = -1;
*chan = -1;
}
}
return ret;
}
int _SAPI_CALL sangoma_interface_wait_up(int span, int chan, int sectimeout)
{
#if defined(__WINDOWS__)
/* Windows does not need to wait for interfaces to come up */
return 0;
#else
char interface_name[FNAME_LEN];
struct stat statbuf;
struct timeval endtime = {0,0};
struct timeval curtime = {0,0};
int counter;
int rc;
if (sectimeout >= 0 && gettimeofday(&endtime, NULL)) {
return -1;
}
snprintf(interface_name, sizeof(interface_name), "/dev/" WP_INTERFACE_NAME_FORM, span, chan);
endtime.tv_sec += sectimeout;
do {
counter = 0;
while ((rc = stat(interface_name, &statbuf)) && errno == ENOENT && counter != 10) {
poll(0, 0, 100); // test in 100ms increments
counter++;
}
if (!rc || errno != ENOENT) break;
if (gettimeofday(&curtime, NULL)) {
return -1;
}
} while (sectimeout < 0 || timercmp(&endtime, &curtime,>));
return rc;
#endif
}
int _SAPI_CALL sangoma_span_chan_fromif(char *interface_name, int *span, int *chan)
{
char *p = NULL, *sp = NULL, *ch = NULL;
int ret = 0;
char data[FNAME_LEN];
strncpy(data, interface_name, FNAME_LEN);
if ((data[0])) {
for (p = data; *p; p++) {
if (sp && *p == 'c') {
*p = '\0';
ch = (p + 1);
break;
} else if (*p == 's') {
sp = (p + 1);
}
}
if(ch && sp) {
*span = atoi(sp);
*chan = atoi(ch);
ret = 1;
} else {
*span = -1;
*chan = -1;
}
}
return ret;
}
sng_fd_t _SAPI_CALL sangoma_open_api_span_chan(int span, int chan)
{
sng_fd_t fd = INVALID_HANDLE_VALUE;
wanpipe_api_t tdm_api;
int err;
fd = __sangoma_open_api_span_chan(span, chan);
#if defined(__WINDOWS__)
if(fd == INVALID_HANDLE_VALUE){
return fd;
}
#else
if (fd < 0) {
return fd;
}
#endif
memset(&tdm_api,0,sizeof(tdm_api));
tdm_api.wp_cmd.cmd = WP_API_CMD_OPEN_CNT;
err=sangoma_cmd_exec(fd,&tdm_api);
if (err){
sangoma_close(&fd);
return fd;
}
if (tdm_api.wp_cmd.open_cnt > 1) {
/* this is NOT the first open request for this span/chan */
sangoma_close(&fd);
fd = INVALID_HANDLE_VALUE;/* fd is NOT valid anymore */
}
return fd;
}
/* no checks done for multiple open */
sng_fd_t _SAPI_CALL __sangoma_open_api_span_chan(int span, int chan)
{
char fname[FNAME_LEN], tmp_fname[FNAME_LEN];
/* Form the Interface Name from span and chan number (i.e. wanpipe1_if1). */
_snprintf(tmp_fname, DEV_NAME_LEN, WP_INTERFACE_NAME_FORM, span, chan);
#if defined(__WINDOWS__)
_snprintf(fname , FNAME_LEN, "\\\\.\\%s", tmp_fname);
return CreateFile( fname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
(HANDLE)NULL
);
#else
sprintf(fname,"/dev/%s", tmp_fname);
return open(fname, O_RDWR);
#endif
}
sng_fd_t _SAPI_CALL sangoma_open_api_ctrl(void)
{
char fname[FNAME_LEN], tmp_fname[FNAME_LEN];
/* Form the Ctrl Device Name. */
_snprintf(tmp_fname, DEV_NAME_LEN, WP_CTRL_DEV_NAME);
#if defined(__WINDOWS__)
_snprintf(fname , FNAME_LEN, "\\\\.\\%s", tmp_fname);
return CreateFile( fname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
(HANDLE)NULL
);
#else
sprintf(fname,"/dev/%s", tmp_fname);
return open(fname, O_RDWR);
#endif
}
int _SAPI_CALL sangoma_get_open_cnt(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_OPEN_CNT;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return -1;
}
return tdm_api->wp_cmd.open_cnt;
}
sng_fd_t _SAPI_CALL sangoma_create_socket_by_name(char *device, char *card)
{
int span,chan;
sangoma_interface_toi(device,&span,&chan);
return sangoma_open_api_span_chan(span,chan);
}
sng_fd_t _SAPI_CALL sangoma_open_api_span(int span)
{
int i=0;
sng_fd_t fd = INVALID_HANDLE_VALUE;
for(i = 1; i < 32; i++){
fd = sangoma_open_api_span_chan(span, i);
#if defined(__WINDOWS__)
if(fd != INVALID_HANDLE_VALUE){
#else
if (fd >= 0) {
#endif
//found free chan
break;
}
}//for()
return fd;
}
/*!
\fn void sangoma_close(sng_fd_t *fd)
\brief Close device file descriptor
\param fd device file descriptor
\return void
*/
void _SAPI_CALL sangoma_close(sng_fd_t *fd)
{
#if defined(__WINDOWS__)
if( *fd != INVALID_HANDLE_VALUE){
CloseHandle(*fd);
*fd = INVALID_HANDLE_VALUE;
}
#else
if (*fd >= 0) {
close(*fd);
*fd = -1;
}
#endif
}
/************************************************************//**
* Device READ / WRITE Functions
***************************************************************/
int _SAPI_CALL sangoma_readmsg(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, int datalen, int flag)
{
int rx_len=0;
#if defined(__WINDOWS__)
wp_api_hdr_t *rx_hdr = (wp_api_hdr_t*)hdrbuf;
wp_api_element_t wp_api_element;
if(hdrlen != sizeof(wp_api_hdr_t)){
//error
DBG_ERR("hdrlen (%i) != sizeof(wp_api_hdr_t) (%i)\n", hdrlen, sizeof(wp_api_hdr_t));
return -1;
}
if(DoReadCommand(fd, &wp_api_element)){
//error
DBG_ERR("DoReadCommand() failed! Check messages log.\n");
return -4;
}
memcpy(rx_hdr, &wp_api_element.hdr, sizeof(wp_api_hdr_t));
switch(rx_hdr->operation_status)
{
case SANG_STATUS_RX_DATA_AVAILABLE:
/* ok */
if(rx_hdr->data_length <= datalen){
memcpy(databuf, wp_api_element.data, rx_hdr->data_length);
}else{
rx_hdr->operation_status = SANG_STATUS_BUFFER_TOO_SMALL;
}
break;
default:
/* note that SANG_STATUS_NO_DATA_AVAILABLE is NOT an error! */
if(0)DBG_ERR("Operation Status: %s(%d)\n",
SDLA_DECODE_SANG_STATUS(rx_hdr->operation_status), rx_hdr->operation_status);
return -5;
}
rx_len = rx_hdr->data_length;
#else
struct msghdr msg;
struct iovec iov[2];
memset(&msg,0,sizeof(struct msghdr));
iov[0].iov_len=hdrlen;
iov[0].iov_base=hdrbuf;
iov[1].iov_len=datalen;
iov[1].iov_base=databuf;
msg.msg_iovlen=2;
msg.msg_iov=iov;
rx_len = read(fd,&msg,sizeof(msg));
if (rx_len <= sizeof(wp_api_hdr_t)){
return -EINVAL;
}
rx_len-=sizeof(wp_api_hdr_t);
#endif
return rx_len;
}
int _SAPI_CALL sangoma_writemsg(sng_fd_t fd, void *hdrbuf, int hdrlen, void *databuf, unsigned short datalen, int flag)
{
int bsent=-1;
wp_api_hdr_t *wp_api_hdr = hdrbuf;
if (hdrlen != sizeof(wp_api_hdr_t)) {
/* error. Possible cause is a mismatch between versions of API header files. */
DBG_ERR("hdrlen (%i) != sizeof(wp_api_hdr_t) (%i)\n", hdrlen, sizeof(wp_api_hdr_t));
return -1;
}
#if defined(__WINDOWS__)
//queue data for transmission
if(DoWriteCommand(fd, databuf, datalen, hdrbuf, hdrlen)){
//error
DBG_ERR("DoWriteCommand() failed!! Check messages log.\n");
return -1;
}
bsent=0;
//check that frame was transmitted
switch(wp_api_hdr->operation_status)
{
case SANG_STATUS_SUCCESS:
bsent = datalen;
break;
default:
DBG_ERR("Operation Status: %s(%d)\n",
SDLA_DECODE_SANG_STATUS(wp_api_hdr->operation_status), wp_api_hdr->operation_status);
break;
}//switch()
#else
struct msghdr msg;
struct iovec iov[2];
memset(&msg,0,sizeof(struct msghdr));
iov[0].iov_len=hdrlen;
iov[0].iov_base=hdrbuf;
iov[1].iov_len=datalen;
iov[1].iov_base=databuf;
msg.msg_iovlen=2;
msg.msg_iov=iov;
bsent = write(fd,&msg,datalen+hdrlen);
if (bsent == (datalen+hdrlen)){
wp_api_hdr->wp_api_hdr_operation_status=SANG_STATUS_SUCCESS;
bsent-=sizeof(wp_api_hdr_t);
} else if (errno == EBUSY){
wp_api_hdr->wp_api_hdr_operation_status=SANG_STATUS_DEVICE_BUSY;
} else {
wp_api_hdr->wp_api_hdr_operation_status=SANG_STATUS_IO_ERROR;
}
wp_api_hdr->wp_api_hdr_data_length=bsent;
//FIXME - THIS SHOULD BE DONE IN KERNEL
wp_api_hdr->wp_api_tx_hdr_max_queue_length=16;
wp_api_hdr->wp_api_tx_hdr_number_of_frames_in_queue=0;
#endif
return bsent;
}
#ifdef WANPIPE_TDM_API
/************************************************************//**
* Device API COMMAND Functions
***************************************************************/
/*========================================================
* Execute TDM command
*
*/
int _SAPI_CALL sangoma_cmd_exec(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
#if defined(__WINDOWS__)
err = tdmv_api_ioctl(fd, &tdm_api->wp_cmd);
#else
err = ioctl(fd,WANPIPE_IOCTL_API_CMD,&tdm_api->wp_cmd);
if (err < 0){
char tmp[50];
sprintf(tmp,"TDM API: CMD: %i\n",tdm_api->wp_cmd.cmd);
perror(tmp);
return -1;
}
#endif
return err;
}
/*========================================================
* Get Full TDM API configuration per channel
*
*/
int _SAPI_CALL sangoma_get_full_cfg(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FULL_CFG;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
#if 0
printf("TDM API CFG:\n");
printf("\thw_tdm_coding:\t%d\n",tdm_api->wp_cmd.hw_tdm_coding);
printf("\thw_mtu_mru:\t%d\n",tdm_api->wp_cmd.hw_mtu_mru);
printf("\tusr_period:\t%d\n",tdm_api->wp_cmd.usr_period);
printf("\ttdm_codec:\t%d\n",tdm_api->wp_cmd.tdm_codec);
printf("\tpower_level:\t%d\n",tdm_api->wp_cmd.power_level);
printf("\trx_disable:\t%d\n",tdm_api->wp_cmd.rx_disable);
printf("\ttx_disable:\t%d\n",tdm_api->wp_cmd.tx_disable);
printf("\tusr_mtu_mru:\t%d\n",tdm_api->wp_cmd.usr_mtu_mru);
printf("\tidle flag:\t0x%02X\n",tdm_api->wp_cmd.idle_flag);
#ifdef WP_API_FEATURE_FE_ALARM
printf("\tfe alarms:\t0x%02X\n",tdm_api->wp_cmd.fe_alarms);
#endif
printf("\trx pkt\t%d\ttx pkt\t%d\n",tdm_api->wp_cmd.stats.rx_packets,
tdm_api->wp_cmd.stats.tx_packets);
printf("\trx err\t%d\ttx err\t%d\n",
tdm_api->wp_cmd.stats.rx_errors,
tdm_api->wp_cmd.stats.tx_errors);
#ifndef __WINDOWS__
printf("\trx ovr\t%d\ttx idl\t%d\n",
tdm_api->wp_cmd.stats.rx_fifo_errors,
tdm_api->wp_cmd.stats.tx_carrier_errors);
#endif
#endif
return 0;
}
/*========================================================
* SET Codec on a particular Channel.
*
* Available codecs are defined in
* /usr/src/linux/include/linux/wanpipe_cfg.h
*
* enum wan_codec_format {
* WP_NONE,
* WP_SLINEAR
* }
*
*/
int _SAPI_CALL sangoma_tdm_set_codec(sng_fd_t fd, wanpipe_api_t *tdm_api, int codec)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_CODEC;
tdm_api->wp_cmd.tdm_codec = codec;
err=sangoma_cmd_exec(fd,tdm_api);
return err;
}
/*========================================================
* GET Codec from a particular Channel.
*
* Available codecs are defined in
* /usr/src/linux/include/linux/wanpipe_cfg.h
*
* enum wan_codec_format {
* WP_NONE,
* WP_SLINEAR
* }
*
*/
int _SAPI_CALL sangoma_tdm_get_codec(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_CODEC;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.tdm_codec;
}
/*========================================================
* SET Rx/Tx Hardware Period in milliseconds.
*
* Available options are:
* 10,20,30,40,50 ms
*
*/
int _SAPI_CALL sangoma_tdm_set_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api, int period)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_USR_PERIOD;
tdm_api->wp_cmd.usr_period = period;
err=sangoma_cmd_exec(fd,tdm_api);
return err;
}
/*========================================================
* GET Rx/Tx Hardware Period in milliseconds.
*
* Available options are:
* 10,20,30,40,50 ms
*
*/
int _SAPI_CALL sangoma_tdm_get_usr_period(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_PERIOD;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.usr_period;
}
/*========================================================
* GET Current User Hardware Coding Format
*
* Coding Format will be ULAW/ALAW based on T1/E1
*/
int _SAPI_CALL sangoma_get_hw_coding(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_CODING;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.hw_tdm_coding;
}
#ifdef WP_API_FEATURE_DTMF_EVENTS
/*========================================================
* GET Current User Hardware DTMF Enabled/Disabled
*
* Will return true if HW DTMF is enabled on Octasic
*/
int _SAPI_CALL sangoma_tdm_get_hw_dtmf(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_DTMF;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.hw_dtmf;
}
/*========================================================
* GET Current User Hardware EC Enabled/Disabled
*
* Will return true if HW EC is enabled
*/
int _SAPI_CALL sangoma_tdm_get_hw_ec(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_HW_EC;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.hw_ec;
}
#endif
/*========================================================
* GET Current User MTU/MRU values in bytes.
*
* The USER MTU/MRU values will change each time a PERIOD
* or CODEC is adjusted.
*/
int _SAPI_CALL sangoma_tdm_get_usr_mtu_mru(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_USR_MTU_MRU;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.usr_mtu_mru;
}
/*========================================================
* SET TDM Power Level
*
* This option is not implemented yet
*
*/
int _SAPI_CALL sangoma_tdm_set_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api, int power)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_POWER_LEVEL;
tdm_api->wp_cmd.power_level = power;
err=sangoma_cmd_exec(fd,tdm_api);
return err;
}
/*========================================================
* GET TDM Power Level
*
* This option is not implemented yet
*
*/
int _SAPI_CALL sangoma_tdm_get_power_level(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_POWER_LEVEL;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.power_level;
}
int _SAPI_CALL sangoma_flush_bufs(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_FLUSH_BUFFERS;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api, int poll_in_sec) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_RBS_EVENTS;
tdm_api->wp_cmd.rbs_poll=poll_in_sec;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_disable_rbs_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_RBS_EVENTS;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_write_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel, unsigned char rbs)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_WRITE_RBS_BITS;
tdm_api->wp_cmd.chan = (unsigned char)channel;
tdm_api->wp_cmd.rbs_tx_bits=rbs;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_read_rbs(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel, unsigned char *rbs)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_READ_RBS_BITS;
tdm_api->wp_cmd.chan = (unsigned char)channel;
tdm_api->wp_cmd.rbs_tx_bits=0;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
*rbs=(unsigned char)tdm_api->wp_cmd.rbs_rx_bits;
return 0;
}
int _SAPI_CALL sangoma_read_event(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
#ifdef WP_API_FEATURE_EVENTS
wp_api_event_t *rx_event;
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_READ_EVENT;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
rx_event = &tdm_api->wp_cmd.event;
/*
The use of callbacks here is purely optional and is left
here for backward compatibility purposes. By default user
should handle events outside this funciton. This function
should only be used to read the event
*/
switch (rx_event->wp_api_event_type){
case WP_API_EVENT_RBS:
if (tdm_api->wp_callback.wp_rbs_event) {
tdm_api->wp_callback.wp_rbs_event(fd,rx_event->wp_api_event_rbs_bits);
}
break;
#ifdef WP_API_FEATURE_DTMF_EVENTS
case WP_API_EVENT_DTMF:
if (tdm_api->wp_callback.wp_dtmf_event) {
tdm_api->wp_callback.wp_dtmf_event(fd,
rx_event->wp_api_event_dtmf_digit,
rx_event->wp_api_event_dtmf_type,
rx_event->wp_api_event_dtmf_port);
}
break;
#endif
case WP_API_EVENT_RXHOOK:
if (tdm_api->wp_callback.wp_rxhook_event) {
tdm_api->wp_callback.wp_rxhook_event(fd,
rx_event->wp_api_event_hook_state);
}
break;
case WP_API_EVENT_RING_DETECT:
if (tdm_api->wp_callback.wp_ring_detect_event) {
tdm_api->wp_callback.wp_ring_detect_event(fd,
rx_event->wp_api_event_ring_state);
}
break;
case WP_API_EVENT_RING_TRIP_DETECT:
if (tdm_api->wp_callback.wp_ring_trip_detect_event) {
tdm_api->wp_callback.wp_ring_trip_detect_event(fd,
rx_event->wp_api_event_ring_state);
}
break;
#ifdef WP_API_FEATURE_FE_ALARM
case WP_API_EVENT_ALARM:
if (tdm_api->wp_callback.wp_fe_alarm_event) {
tdm_api->wp_callback.wp_fe_alarm_event(fd,
rx_event->wp_api_event_alarm);
}
break;
#endif
#ifdef WP_API_FEATURE_LINK_STATUS
/* Link Status */
case WP_API_EVENT_LINK_STATUS:
if(tdm_api->wp_callback.wp_link_status_event){
tdm_api->wp_callback.wp_link_status_event(fd,
rx_event->wp_api_event_link_status);
}
break;
#endif
#ifdef WP_API_FEATURE_POL_REV
case WP_API_EVENT_POLARITY_REVERSE:
break;
#endif
default:
#ifdef __WINDOWS__
printf("libsangoma: %s fd=0x%p: Unknown TDM event!", __FUNCTION__,fd);
#else
printf("libsangoma: %s fd=%d: Unknown TDM event!", __FUNCTION__, fd);
#endif
break;
}
return 0;
#else
printf("Error: Read Event not supported!\n");
return -1;
#endif
}
#ifdef WP_API_FEATURE_DTMF_EVENTS
int _SAPI_CALL sangoma_tdm_enable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_disable_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_DTMF;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_disable_rm_dtmf_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RM_DTMF;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_disable_rxhook_events(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RXHOOK;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_disable_ring_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return err;
}
int _SAPI_CALL sangoma_tdm_disable_ring_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_TRIP_DETECT;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.rbs_poll;
}
int _SAPI_CALL sangoma_tdm_disable_ring_trip_detect_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_RING_DETECT;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_txsig_kewl(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_KEWL;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_txsig_start(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_START;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_txsig_onhook(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_ONHOOK;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_txsig_offhook(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TXSIG_OFFHOOK;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_enable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api, uint16_t tone_id) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
tdm_api->wp_cmd.event.wp_api_event_tone_type = tone_id;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.rbs_poll;
}
int _SAPI_CALL sangoma_tdm_disable_tone_events(sng_fd_t fd, wanpipe_api_t *tdm_api) {
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_TONE;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
tdm_api->wp_cmd.event.wp_api_event_tone_type = 0x00;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return tdm_api->wp_cmd.rbs_poll;
}
#endif
int _SAPI_CALL sangoma_tdm_enable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_ENABLE_HWEC;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
int _SAPI_CALL sangoma_tdm_disable_hwec(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_DISABLE_HWEC;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
return 0;
}
/*========================================================
* GET Front End Alarms
*
*/
#ifdef WP_API_FEATURE_FE_ALARM
int _SAPI_CALL sangoma_tdm_get_fe_alarms(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned int *alarms)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_ALARMS;
err=sangoma_cmd_exec(fd,tdm_api);
if (err){
return err;
}
*alarms=tdm_api->wp_cmd.fe_alarms;
return 0;
}
/* get current Line Connection state - Connected/Disconnected */
int _SAPI_CALL sangoma_get_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char *current_status)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS;
err = sangoma_cmd_exec(fd, tdm_api);
*current_status = tdm_api->wp_cmd.fe_status;
return err;
}
#endif
/* get current Line Connection state - Connected/Disconnected */
#ifdef WP_API_FEATURE_LINK_STATUS
int _SAPI_CALL sangoma_get_link_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char *current_status)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_FE_STATUS;
err = sangoma_cmd_exec(fd, tdm_api);
*current_status = tdm_api->wp_cmd.fe_status;
return err;
}
/* set current Line Connection state - Connected/Disconnected. valid only for ISDN BRI */
int _SAPI_CALL sangoma_set_fe_status(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char new_status)
{
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_FE_STATUS;
tdm_api->wp_cmd.fe_status = new_status;
return sangoma_cmd_exec(fd, tdm_api);
}
#endif
int _SAPI_CALL sangoma_disable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
{
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.channel = (unsigned char)channel;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_DISABLE;
return sangoma_cmd_exec(fd, tdm_api);
}
int _SAPI_CALL sangoma_enable_bri_bchan_loopback(sng_fd_t fd, wanpipe_api_t *tdm_api, int channel)
{
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_EVENT;
tdm_api->wp_cmd.event.channel = (unsigned char)channel;
tdm_api->wp_cmd.event.wp_api_event_type = WP_API_EVENT_BRI_CHAN_LOOPBACK;
tdm_api->wp_cmd.event.wp_api_event_mode = WP_API_EVENT_ENABLE;
return sangoma_cmd_exec(fd, tdm_api);
}
int _SAPI_CALL sangoma_get_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_TX_Q_SIZE;
tdm_api->wp_cmd.tx_queue_sz = 0;
err=sangoma_cmd_exec(fd, tdm_api);
if (err < 0) {
return err;
}
return tdm_api->wp_cmd.tx_queue_sz;
}
int _SAPI_CALL sangoma_set_tx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, int size)
{
if (size < 0) {
return -1;
}
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_TX_Q_SIZE;
tdm_api->wp_cmd.tx_queue_sz = size;
return sangoma_cmd_exec(fd, tdm_api);
}
int _SAPI_CALL sangoma_get_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_RX_Q_SIZE;
tdm_api->wp_cmd.rx_queue_sz = 0;
err=sangoma_cmd_exec(fd, tdm_api);
if (err < 0) {
return err;
}
return tdm_api->wp_cmd.rx_queue_sz;
}
int _SAPI_CALL sangoma_set_rx_queue_sz(sng_fd_t fd, wanpipe_api_t *tdm_api, int size)
{
if (size < 0) {
return -1;
}
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RX_Q_SIZE;
tdm_api->wp_cmd.rx_queue_sz = size;
return sangoma_cmd_exec(fd, tdm_api);
}
int _SAPI_CALL sangoma_get_driver_version(sng_fd_t fd, wanpipe_api_t *tdm_api, wan_driver_version_t *drv_ver)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_DRIVER_VERSION;
err = sangoma_cmd_exec(fd, tdm_api);
if (err == 0) {
if (tdm_api->wp_cmd.data_len == sizeof(wan_driver_version_t)) {
if (drv_ver) {
memcpy(drv_ver,&tdm_api->wp_cmd.version,sizeof(wan_driver_version_t));
}
} else {
return -1;
}
}
return err;
}
int _SAPI_CALL sangoma_get_firmware_version(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char *ver)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_FIRMWARE_VERSION;
err = sangoma_cmd_exec(fd, tdm_api);
if (err == 0) {
if (tdm_api->wp_cmd.data_len == sizeof(unsigned char)) {
*ver = tdm_api->wp_cmd.data[0];
} else {
return -1;
}
}
return err;
}
int _SAPI_CALL sangoma_get_cpld_version(sng_fd_t fd, wanpipe_api_t *tdm_api, unsigned char *ver)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_CPLD_VERSION;
err = sangoma_cmd_exec(fd, tdm_api);
if (err == 0) {
if (tdm_api->wp_cmd.data_len == sizeof(unsigned char)) {
*ver = tdm_api->wp_cmd.data[0];
} else {
return -1;
}
}
return err;
}
int _SAPI_CALL sangoma_get_stats(sng_fd_t fd, wanpipe_api_t *tdm_api, wanpipe_chan_stats_t *stats)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_GET_STATS;
err = sangoma_cmd_exec(fd, tdm_api);
if (err == 0) {
if (stats) {
memcpy(stats,&tdm_api->wp_cmd.stats,sizeof(wanpipe_chan_stats_t));
}
}
return err;
}
int _SAPI_CALL sangoma_flush_stats(sng_fd_t fd, wanpipe_api_t *tdm_api)
{
tdm_api->wp_cmd.cmd = WP_API_CMD_RESET_STATS;
return sangoma_cmd_exec(fd, tdm_api);
}
int _SAPI_CALL sangoma_set_rm_rxflashtime(sng_fd_t fd, wanpipe_api_t *tdm_api, int rxflashtime)
{
int err;
tdm_api->wp_cmd.cmd = WP_API_CMD_SET_RM_RXFLASHTIME;
tdm_api->wp_cmd.rxflashtime=rxflashtime;
err = sangoma_cmd_exec(fd, tdm_api);
return err;
}
#ifndef LIBSANGOMA_LIGHT
/************************************************************//**
* Device PORT Control Functions
***************************************************************/
static int sangoma_port_mgmnt_ioctl(sng_fd_t fd, port_management_struct_t *port_management)
{
#if defined(__WINDOWS__)
DWORD ln;
if(DeviceIoControl(
fd,
IoctlPortManagementCommand,
(LPVOID)port_management,
sizeof(port_management_struct_t),
(LPVOID)port_management,
sizeof(port_management_struct_t),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
) == FALSE){
//check messages log
printf("%s():Error: IoctlPortManagementCommand failed!!\n", __FUNCTION__);
return -1;
}else {
return 0;
}
#else
int err;
err=ioctl(fd,WANPIPE_IOCTL_PORT_MGMT,port_management);
if (err) {
return -1;
} else {
return 0;
}
#endif
}
static int sangoma_port_cfg_ioctl(sng_fd_t fd, port_cfg_t *port_cfg)
{
#if defined(__WINDOWS__)
DWORD ln;
if(DeviceIoControl(
fd,
IoctlPortConfigurationCommand,
(LPVOID)port_cfg,
sizeof(port_cfg_t),
(LPVOID)port_cfg,
sizeof(port_cfg_t),
(LPDWORD)(&ln),
(LPOVERLAPPED)NULL
) == FALSE){
//check messages log
printf("%s():Error: IoctlSetDriverConfiguration failed!!\n", __FUNCTION__);
return 1;
}else{
return 0;
}
#else
int err;
err=ioctl(fd,WANPIPE_IOCTL_PORT_CONFIG,port_cfg);
if (err) {
return -1;
} else {
return 0;
}
#endif
}
/* open wanpipe configuration device */
sng_fd_t _SAPI_CALL sangoma_open_driver_ctrl(int port_no)
{
char fname[FNAME_LEN], tmp_fname[FNAME_LEN];
#if defined(__WINDOWS__)
/* Form the Config Device Name (i.e. wanpipe1, wanpipe2,...). */
_snprintf(tmp_fname, DEV_NAME_LEN, WP_PORT_NAME_FORM, port_no);
_snprintf(fname, FNAME_LEN, "\\\\.\\%s", tmp_fname);
return CreateFile( fname,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
(HANDLE)NULL
);
#else
/* Form the Config Device Name. ("/dev/wanpipe") */
_snprintf(tmp_fname, DEV_NAME_LEN, WP_CONFIG_DEV_NAME);
sprintf(fname,"/dev/%s", tmp_fname);
return open(fname, O_RDWR);
#endif
}
int _SAPI_CALL sangoma_mgmt_cmd(sng_fd_t fd, wan_udp_hdr_t* wan_udp)
{
#if defined(__WINDOWS__)
if(DoManagementCommand(fd, wan_udp)){
return 1;
}
#else
unsigned char id = 0;
int err=0;
wan_udp->wan_udphdr_request_reply = 0x01;
wan_udp->wan_udphdr_id = id;
wan_udp->wan_udphdr_return_code = WAN_UDP_TIMEOUT_CMD;
err=ioctl(fd,WANPIPE_IOCTL_PIPEMON,wan_udp);
if (err < 0) {
return 1;
}
#endif
if(wan_udp->wan_udphdr_return_code != WAN_CMD_OK){
return 2;
}
return 0;
}
int _SAPI_CALL sangoma_driver_port_start(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
{
int err;
port_mgmnt->command_code = START_PORT_VOLATILE_CONFIG;
port_mgmnt->port_no = port_no;
err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt);
if (err) {
return err;
}
if (port_mgmnt->operation_status != SANG_STATUS_SUCCESS ) {
err=port_mgmnt->operation_status;
}
return err;
}
int _SAPI_CALL sangoma_driver_port_stop(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
{
int err;
port_mgmnt->command_code = STOP_PORT;
port_mgmnt->port_no = port_no;
err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt);
if (err) {
return err;
}
if (port_mgmnt->operation_status != SANG_STATUS_SUCCESS){
if(port_mgmnt->operation_status == SANG_STATUS_CAN_NOT_STOP_DEVICE_WHEN_ALREADY_STOPPED) {
err = 0;
}else{
err = port_mgmnt->operation_status;
}
}
return err;
}
int _SAPI_CALL sangoma_driver_get_hw_info(sng_fd_t fd, port_management_struct_t *port_mgmnt, unsigned short port_no)
{
int err;
port_mgmnt->command_code = GET_HARDWARE_INFO;
port_mgmnt->port_no = port_no;
err = sangoma_port_mgmnt_ioctl(fd, port_mgmnt);
if (err) {
port_mgmnt->operation_status = SANG_STATUS_INVALID_DEVICE;
return err;
}
if (port_mgmnt->operation_status != SANG_STATUS_SUCCESS ) {
err=port_mgmnt->operation_status;
}
return err;
}
int _SAPI_CALL sangoma_driver_port_set_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no)
{
port_cfg->command_code = SET_PORT_VOLATILE_CONFIG;
port_cfg->port_no = port_no;
return sangoma_port_cfg_ioctl(fd, port_cfg);
}
int _SAPI_CALL sangoma_driver_port_get_config(sng_fd_t fd, port_cfg_t *port_cfg, unsigned short port_no)
{
port_cfg->command_code = GET_PORT_VOLATILE_CONFIG;
port_cfg->port_no = port_no;
return sangoma_port_cfg_ioctl(fd, port_cfg);
}
#endif
#endif /* WANPIPE_TDM_API */