blob: e2664002aae3a964b2c486894189dd003bd151e7 [file] [log] [blame]
/*******************************************************************************
Copyright (C) Marvell International Ltd. and its affiliates
This software file (the "File") is owned and distributed by Marvell
International Ltd. and/or its affiliates ("Marvell") under the following
alternative licensing terms. Once you have made an election to distribute the
File under one of the following license alternatives, please (i) delete this
introductory statement regarding license alternatives, (ii) delete the two
license alternatives that you have not elected to use and (iii) preserve the
Marvell copyright notice above.
********************************************************************************
Marvell Commercial License Option
If you received this File from Marvell and you have entered into a commercial
license agreement (a "Commercial License") with Marvell, the File is licensed
to you under the terms of the applicable Commercial License.
********************************************************************************
Marvell GPL License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File in accordance with the terms and conditions of the General
Public License Version 2, June 1991 (the "GPL License"), a copy of which is
available along with the File in the license.txt file or by writing to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
DISCLAIMED. The GPL License provides additional details about this warranty
disclaimer.
********************************************************************************
Marvell BSD License Option
If you received this File from Marvell, you may opt to use, redistribute and/or
modify this File under the following licensing terms.
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 Marvell nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>
#include <sched.h>
#include "sys_service.h"
#include "tdm/test/tdm_dev.h"
#include "vp_api_common.h"
#if defined(ZARLINK_SLIC_VE880)
#include "vp880_api.h"
#include "profile_88266.h"
#elif defined(ZARLINK_SLIC_VE792)
#include "vp792_api.h"
#include "profile_79238.h"
#endif
/* Defines */
#define GET_DEV_STATUS(deviceId) vpapi_dev_status[deviceId]
#define GET_LINE_STATUS(lineId) vpapi_line_status[lineId]
#define REGISTER_DEVICE(deviceId) \
vpapi_dev_status[deviceId] = 1;
#define REGISTER_LINE(lineId) \
vpapi_line_status[lineId] = 1;
#define MAX_PROFILE_SIZE 128
#define GET_DEVICE(lineId) (lineId/MAX_LINES_PER_DEVICE)
#define GET_LINE(lineId) (lineId % MAX_LINES_PER_DEVICE)
#define MAX_EVENT_QUEUE_SIZE 256
#define VPAPI_TICK_TIMER_PERIOD 1
#define VPAPI_MOD_NAME "vpapi"
#define TOOL_PREFIX ">> "
#define TIMEOUT 11000 /* usec */
/* Line calibration increases init time significantly */
#define LINE_CALIBRATION_SUPPORT
/* Defines */
#define N_A 0
#define ON_HOOK 0
#define OFF_HOOK 1
#define CH_BUFF_SIZE (80 * pcm_bytes)
#define BUFF_ADDR(buff, line) ((unsigned char*)buff + (line*80*pcm_bytes))
#define TIMER_THREAD_PRIORITY 99
/* VE880 */
#if defined(ZARLINK_SLIC_VE880)
#define MAX_DEVICES 2
#define MAX_LINES 4
#define MAX_LINES_PER_DEVICE 2
#define MAX_DEVICE_LINES 2
#define VP_DEV_SERIES VP_DEV_880_SERIES
#define DEV_PROFILE ABS_VBL_FLYBACK
#define DC_COEFF DC_22MA_CC
#define AC_COEFF AC_FXS_RF14_DEF
#define WB_AC_COEFF AC_FXS_RF14_WB_US
#define RING_PROFILE RING_DEF
VpDevCtxType pDevCtx[MAX_DEVICES];
VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
Vp880DeviceObjectType pDevObj[MAX_DEVICES];
Vp880LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
/* VE792 */
#elif defined(ZARLINK_SLIC_VE792)
#define TBD 0
#define MAX_DEVICES 4
#define MAX_LINES 32
#define MAX_LINES_PER_DEVICE 8
#define MAX_DEVICE_LINES 8
#define VP_DEV_SERIES VP_DEV_792_SERIES
#define DEV_PROFILE VE792_DEV_PROFILE
#define DC_COEFF VE792_DC_COEFF
#define AC_COEFF VE792_AC_COEFF_600
#define WB_AC_COEFF TBD /* TBD: AC profile for WideBand support */
#define RING_PROFILE RING_20HZ_SINE
/* Power-supply related parameters */
#define VBH -50
#define VBL -25
#define VBP 50
VpDevCtxType pDevCtx[MAX_DEVICES];
VpLineCtxType pLineCtx[MAX_DEVICES][MAX_LINES_PER_DEVICE];
Vp792DeviceObjectType pDevObj[MAX_DEVICES];
Vp792LineObjectType pLineObj[MAX_DEVICES][MAX_LINES_PER_DEVICE];
extern int BattOn(int vbhSetting, int vblSetting, int vbpSetting);
extern int BattOff(void);
#endif
/* Extern */
extern int dev_profile_size;
extern int dc_profile_size;
extern int ac_profile_size;
extern int ring_profile_size;
extern pthread_mutex_t vp_lock;
/* GLobals */
unsigned char time_slot_table[MAX_LINES];
unsigned char vpapi_dev_status[MAX_DEVICES];
unsigned char vpapi_line_status[MAX_LINES];
VpOptionCodecType codec = VP_OPTION_ALAW;
/* Static */
static unsigned short total_lines = 0;
static unsigned short total_devs = 0;
static unsigned char pcm_bytes = 0;
static unsigned char cal_devs = 0;
#ifdef LINE_CALIBRATION_SUPPORT
static unsigned short cal_lines = 0;
#endif
static unsigned char hook_state[MAX_LINES];
static char dev_name[] = "/dev/tdm";
static int buff_size = 0;
static unsigned char aud_buf[2][320 * MAX_LINES];
static unsigned short f1Mem = 0;
static unsigned short f2Mem = 0;
static int offhook_count = 0;
static unsigned int event_count = 0;
static int tdm_fd = 0;
static unsigned char data_buff[MAX_SLIC_RDWR_BUFF_SIZE];
static int slic_init = 0;
/* sin table, 256 points */
static short sinTbl[] = {0,402,804,1205,1606,2005,2404,2801,3196,3590,3981,4370,4756,
5139,5519,5896,6270,6639,7005,7366,7723,8075,8423,8765,9102,9433,9759,10079,10393,
10701,11002,11297,11585,11865,12139,12405,12664,12915,13159,13394,13622,13841,14052,
14255,14449,14634,14810,14977,15136,15285,15425,15556,15678,15790,15892,15985,16068,
16142,16206,16260,16304,16339,16363,16378,16383,16378,16363,16339,16304,16260,16206,
16142,16068,15985,15892,15790,15678,15556,15425,15285,15136,14977,14810,14634,14449,
14255,14052,13841,13622,13394,13159,12915,12664,12405,12139,11865,11585,11297,11002,
10701,10393,10079,9759,9433,9102,8765,8423,8075,7723,7366,7005,6639,6270,5896,5519,
5139,4756,4370,3981,3590,3196,2801,2404,2005,1606,1205,804,402,0,-402,-804,-1205,-1606,
-2005,-2404,-2801,-3196,-3590,-3981,-4370,-4756,-5139,-5519,-5896,-6270,-6639,-7005,
-7366,-7723,-8075,-8423,-8765,-9102,-9433,-9759,-10079,-10393,-10701,-11002,-11297,
-11585,-11865,-12139,-12405,-12664,-12915,-13159,-13394,-13622,-13841,-14052,-14255,
-14449,-14634,-14810,-14977,-15136,-15285,-15425,-15556,-15678,-15790,-15892,-15985,
-16068,-16142,-16206,-16260,-16304,-16339,-16363,-16378,-16383,-16378,-16363,-16339,
-16304,-16260,-16206,-16142,-16068,-15985,-15892,-15790,-15678,-15556,-15425,-15285,
-15136,-14977,-14810,-14634,-14449,-14255,-14052,-13841,-13622,-13394,-13159,-12915,
-12664,-12405,-12139,-11865,-11585,-11297,-11002,-10701,-10393,-10079,-9759,-9433,-9102,
-8765,-8423,-8075,-7723,-7366,-7005,-6639,-6270,-5896,-5519,-5139,-4756,-4370,-3981,
-3590,-3196,-2801,-2404,-2005,-1606,-1205,-804,-402,0};
/* Static APIs */
static void vpapi_dev_init(VpDeviceIdType dev_id);
static inline void wait_for_vpapi_event(void);
static int vpapi_init(void);
static void vpapi_init_done(void);
static void vpapi_release(void);
static void release(int signum);
static void sw_tone_test(int tdm_fd, unsigned char line_id);
static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1);
static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line);
static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff);
static void sw_loopback(int tdm_fd, unsigned char line_id);
static void slic_digital_loopback(int tdm_fd, unsigned long int iterations);
static void channel_balancing_test(int tdm_fd, unsigned long int iterations);
static inline int slic_dl_data_compare(int offset);
static VpStatusType vpapi_init_device(VpDeviceIdType dev_id, VpProfilePtrType dev_profile_ptr,
VpProfilePtrType ac_profile_ptr, VpProfilePtrType dc_profile_ptr,
VpProfilePtrType ring_profile_ptr, VpProfilePtrType fxo_ac_profile_ptr,
VpProfilePtrType fxo_cfg_profile_ptr, vpapi_init_device_params_t *params_ptr);
void *sys_service_timer_function(void *arg);
#if defined(MV_TDM_USE_DCO)
static void set_tdm_clk_config(void);
static int get_tdm_clk_correction(void);
static void set_tdm_clk_correction(int correction);
#endif
int main(void)
{
pthread_t timer_thread;
pthread_attr_t attr;
struct sched_param parm;
sigset_t alarm_sig;
int ret = 0, cmd = 0, val = 0, tdm_init = 0;
int proc_fd, fdflags, cmd_len, i;
char str[32];
unsigned char ec_val[] = {0x1, 0x2};
unsigned char line0_id, line1_id;
tdm_dev_params_t tdm_params;
unsigned long int iterations;
timer_t TimerID;
event_count = 0;
slic_init = 0;
total_devs = 0;
total_lines = 0;
sys_service_init();
memset(vpapi_dev_status, 0, MAX_DEVICES);
memset(vpapi_line_status, 0, MAX_LINES);
/* Reset event counter */
event_count = 0;
/* open tdm device */
tdm_fd = open(dev_name, O_RDWR);
if (tdm_fd <= 0) {
printf("%s Cannot open %s device\n", TOOL_PREFIX, dev_name);
return 1;
}
/* set some flags */
fdflags = fcntl(tdm_fd, F_GETFL, 0);
fdflags |= O_NONBLOCK;
fcntl(tdm_fd, F_SETFL, fdflags);
printf("\n%s Please enter total lines number: ", TOOL_PREFIX);
gets(str);
total_lines = atoi(str);
printf("%s Please enter PCM sample size(1/2/4): ",TOOL_PREFIX);
gets(str);
pcm_bytes = atoi(str);
/* Calculate total lines buffer size */
buff_size = (80 * pcm_bytes * total_lines);
/* Fill TDM info */
tdm_params.pcm_format = pcm_bytes;
tdm_params.total_lines = total_lines;
total_devs = (total_lines/MAX_DEVICE_LINES);
if((total_lines % MAX_DEVICE_LINES))
total_devs++;
/* Init timer thread */
pthread_attr_init(&attr);
parm.sched_priority=TIMER_THREAD_PRIORITY;
pthread_attr_setschedpolicy(&attr,SCHED_FIFO);
pthread_attr_setschedparam(&attr,&parm);
pthread_create (&timer_thread, &attr, sys_service_timer_function, NULL);
/* Handle termination gracefully */
if (signal (SIGINT, release) == SIG_IGN)
signal (SIGINT, SIG_IGN);
/* Issue main menu */
while(1) {
printf("\n Marvell Voice Tool:\n");
printf(" 0. Read from SLIC register(VE880 only)\n");
printf(" 1. Write to SLIC register(VE880 only)\n");
printf(" 2. Start ring\n");
printf(" 3. Stop ring\n");
printf(" 4. Start SW tone\n");
printf(" 5. Self echo on local phone\n");
printf(" 6. Loopback two local phones\n");
printf(" 7. Multiple local phone pairs loopback\n");
printf(" 8. Digital Loopback(incremental pattern)\n");
printf(" 9. Channel balancing\n");
printf(" a. Start Phone devices\n");
printf(" b. Stop Phone devices\n");
#if defined(MV_TDM_USE_DCO)
printf(" c. Config TDM PCLK\n");
printf(" d. Get current TDM PCLK frequency correction (DCO)\n");
printf(" e. Set TDM PCLK frequency correction (DCO)\n");
#endif
printf(" q. Quit\n");
printf("\n%s Please select option: ", TOOL_PREFIX);
/* Clear write buffer */
memset(aud_buf[1], 0, buff_size);
gets(str);
switch(str[0])
{
case '0':
#if defined(ZARLINK_SLIC_VE880)
printf("%s Enter line id: ",TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
printf("%s Enter SLIC register command(decimal): ",TOOL_PREFIX);
gets(str);
cmd = atoi(str);
printf("%s Enter SLIC register command size: ",TOOL_PREFIX);
gets(str);
cmd_len = atoi(str);
VpMpiCmd(GET_DEVICE(line0_id), ec_val[GET_LINE(line0_id)], (cmd | 1), cmd_len, data_buff);
printf("\n%s Sent command 0x%x to line(%d)\n", TOOL_PREFIX, cmd, line0_id);
printf("%s Return value: ",TOOL_PREFIX);
for(i = 0; i < cmd_len; i++)
printf("0x%x ", data_buff[i]);
printf("\n");
#else
printf("%s operation not supported\n",TOOL_PREFIX);
#endif
break;
case '1':
#if defined(ZARLINK_SLIC_VE880)
printf("%s Enter line id: ",TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
printf("%s Enter SLIC register command(decimal): ",TOOL_PREFIX);
gets(str);
cmd = atoi(str);
printf("%s Enter SLIC register command size: ",TOOL_PREFIX);
gets(str);
cmd_len = atoi(str);
printf("%s Enter data(press Enter after each byte): ",TOOL_PREFIX);
for(i = 0; i < cmd_len; i++) {
gets(str);
data_buff[i] = atoi(str);
}
VpMpiCmd(GET_DEVICE(line0_id), ec_val[GET_LINE(line0_id)], cmd, cmd_len, data_buff);
printf("\n%s Sent command 0x%x to line(%d)\n", TOOL_PREFIX, cmd, line0_id);
#else
printf("%s operation not supported\n",TOOL_PREFIX);
#endif
break;
case '2':
printf("%s Enter line id: ", TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
printf("Start ringing on line %d\n", line0_id);
VpSetLineState(&pLineCtx[GET_DEVICE(line0_id)][line0_id], VP_LINE_RINGING);
break;
case '3':
printf("%s Enter line id: ", TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
printf("Stop ringing on line %d\n", line0_id);
VpSetLineState(&pLineCtx[GET_DEVICE(line0_id)][line0_id], VP_LINE_STANDBY);
break;
case '4':
if(pcm_bytes < 2) {
printf("Test is supported for linear mode only - try again\n");
break;
}
printf("%s Enter line id: ", TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
sw_tone_test(tdm_fd, line0_id);
break;
case '5':
printf("%s Enter line id: ", TOOL_PREFIX);
gets(str);
printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
line0_id = atoi(str);
sw_loopback(tdm_fd, line0_id);
break;
case '6':
printf("%s Enter line #0: ", TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
printf("%s Enter line #1: ", TOOL_PREFIX);
gets(str);
printf("Waiting for off-hook...\n");
line1_id = atoi(str);
if(line0_id >= MAX_LINES || line1_id >= MAX_LINES) {
printf("%s Error, line must be in the range of 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
break;
}
sw_loopback_two_phones_test(tdm_fd, line0_id, line1_id);
break;
case '7':
printf("%s Enter starting line range: ", TOOL_PREFIX);
gets(str);
line0_id = atoi(str);
printf("%s Enter ending line range: ", TOOL_PREFIX);
gets(str);
printf("Waiting for off-hook...\n");
line1_id = atoi(str);
if((line0_id >= MAX_LINES) ||
(line1_id >= MAX_LINES) ||
((line1_id-line0_id) % 2 == 0)) {
printf("%s Error, lines range must be even and \
between 0-%d\n", TOOL_PREFIX, (MAX_LINES-1));
break;
}
sw_loopback_multi_phones_test(tdm_fd, line0_id, line1_id);
break;
case '8':
printf("%s Enter number of iterations(must be greater than 3): ", TOOL_PREFIX);
gets(str);
iterations = (unsigned long int)atoi(str);
if(iterations < 4) {
printf("Requires at least 4 iterations - try again\n");
break;
}
slic_digital_loopback(tdm_fd, iterations);
break;
case '9':
printf("%s Enter number of iterations('0' - for infinite loop): ", TOOL_PREFIX);
gets(str);
iterations = (unsigned long int)atoi(str);
channel_balancing_test(tdm_fd, iterations);
break;
case 'a':
/* Start Telephony */
if(ioctl(tdm_fd, TDM_DEV_TDM_START, &tdm_params)) {
printf("%s Error, unable to init TDM\n", TOOL_PREFIX);
return 1;
}
if(vpapi_init()) {
printf("%s Error, init failed\n", TOOL_PREFIX);
ret = 1;
goto voice_out;
}
slic_init = 1;
/* Wait to device/s and line/s calibration to finish */
#ifdef LINE_CALIBRATION_SUPPORT
while((cal_devs < total_devs) || (cal_lines < total_lines)) {
#else
while(cal_devs < total_devs) {
#endif
wait_for_vpapi_event();
}
break;
case 'b':
/* Stop Telephony */
release(0);
break;
#if defined(MV_TDM_USE_DCO)
case 'c':
set_tdm_clk_config();
break;
case 'd':
printf("%s Current PPM correction is (+/-1000): %d", TOOL_PREFIX, get_tdm_clk_correction());
break;
case 'e':
printf("%s Enter number of PPM for correction (+/-1000, 0 to disable correction): ", TOOL_PREFIX);
gets(str);
set_tdm_clk_correction((int)atoi(str));
break;
#endif
case 'q':
goto voice_out;
default:
printf("Option is not supported - try again\n");
break;
}
}
voice_out:
release(1);
pthread_kill(timer_thread, SIGKILL);
return ret;
}
void release(int signum)
{
if (signum) {
printf("\n%s Stopping Phone devices and exit\n", TOOL_PREFIX);
sleep(1);
} else {
printf("\n%s Stopping Phone devices\n", TOOL_PREFIX);
}
/* Stop SLIC/s */
if(slic_init)
vpapi_release();
/* Stop TDM */
if(ioctl(tdm_fd, TDM_DEV_TDM_STOP, 0)) {
printf("Error, unable to stop TDM\n");
return;
}
if (signum)
close(tdm_fd);
if (signum)
exit(signum);
}
static void channel_balancing_test(int tdm_fd, unsigned long int iterations)
{
fd_set rd_fds, wr_fds;
struct timeval timeout = {0, TIMEOUT};
int msg_len, cmp_status = 0, ch, cb_loop = 0, i;
unsigned long int loops = 0, index;
VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
if (tdm_fd <= 0) {
printf("Device %s is not accessible\n", dev_name);
return;
}
/* Fill Tx buffer with incremental pattern */
for(ch = 0; ch < total_lines; ch++) {
for(index = 0; index < (80 * pcm_bytes); index+=2)
*((unsigned short*)&aud_buf[1][(80 * pcm_bytes * ch) + index]) = (((index+3) << 8)+ (index+1));
}
/* Put SLIC/s in loopback mode */
for(ch = 0; ch < total_lines; ch++)
VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
/* Wait a bit */
sleep(1);
/* Put SLIC/s in TALK mode */
for(ch = 0; ch < total_lines; ch++)
VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_TALK);
/* Wait a bit */
sleep(1);
if (iterations == 0)
iterations = (unsigned long int)(-1); /* Assume infinite */
while (loops < iterations) {
cb_loop = 0;
i = 0;
if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
printf("Error, unable to start pcm bus\n");
return;
}
while (cb_loop == 0) {
FD_ZERO(&rd_fds);
FD_ZERO(&wr_fds);
FD_SET(tdm_fd, &rd_fds);
FD_SET(tdm_fd, &wr_fds);
/* Wait for event */
if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
goto cb_out;
}
/* Write */
if (FD_ISSET(tdm_fd, &wr_fds))
{
msg_len = write(tdm_fd, aud_buf[1], buff_size);
if (msg_len < buff_size) {
printf("write() failed\n");
goto cb_out;
}
}
/* Read */
if (FD_ISSET(tdm_fd, &rd_fds))
{
memset(aud_buf[0], 0, buff_size);
msg_len = read(tdm_fd, aud_buf[0], buff_size);
if (msg_len < buff_size) {
printf("read() failed\n");
goto cb_out;
}
if(i > 3) {
for(ch = 1; ch < total_lines; ch++) {
if(memcmp(aud_buf[0], &aud_buf[0][(ch * pcm_bytes * 80)], (pcm_bytes * 80))) {
printf("\nERROR - data miscompare(ch=%d) !!!\n", ch);
cmp_status = 1;
goto cb_out;
}
}
cb_loop = 1;
}
i++;
}
/* Reload timeout */
timeout.tv_usec = TIMEOUT;
}
loops++;
if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
printf("Error, unable to stop pcm bus\n");
return;
}
printf("loop #%u\n", loops);
sleep(1);
}
cb_out:
if(cmp_status == 0) {
printf("\nChannel balancing test PASSED !!!\n");
}
else {
printf("Dump Rx buffer:\n");
for(ch = 0; ch < total_lines; ch++) {
printf("Buffer #%d: ", ch);
for(i = 0; i < (pcm_bytes * 80); i++) {
printf("0x%x ", aud_buf[0][(ch * pcm_bytes * 80) + i]);
}
printf("\n\n");
sleep(1);
}
}
if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
printf("Error, unable to stop pcm bus\n");
return;
}
lp = VP_OPTION_LB_OFF;
/* Disable loopback mode */
for(ch = 0; ch < total_lines; ch++)
VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
/* Put SLIC/s in STANDBY mode */
for(ch = 0; ch < total_lines; ch++)
VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_STANDBY);
}
static void slic_digital_loopback(int tdm_fd, unsigned long int iterations)
{
fd_set rd_fds, wr_fds;
struct timeval timeout = {0, TIMEOUT};
int msg_len, cmp_status = 0, ch;
unsigned long int loops = 0, index;
VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
if (tdm_fd <= 0) {
printf("Device %s is not accessible\n", dev_name);
return;
}
/* Put SLIC/s in loopback mode */
for(ch = 0; ch < total_lines; ch++)
VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
/* Wait a bit */
sleep(1);
/* Put SLIC/s in TALK mode */
for(ch = 0; ch < total_lines; ch++)
VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_TALK);
/* Fill Tx buffer with incremental pattern */
for(ch = 0; ch < total_lines; ch++) {
for(index = 0; index < (80 * pcm_bytes); index++)
aud_buf[1][index + (80 * pcm_bytes * ch)] = (index+ch+2);
}
if (ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
printf("Error, unable to start pcm bus\n");
return;
}
while (loops < iterations) {
FD_ZERO(&rd_fds);
FD_ZERO(&wr_fds);
FD_SET(tdm_fd, &rd_fds);
FD_SET(tdm_fd, &wr_fds);
/* Wait for event */
if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
goto slic_dl_out;
}
/* Write */
if (FD_ISSET(tdm_fd, &wr_fds))
{
msg_len = write(tdm_fd, aud_buf[1], buff_size);
if (msg_len < buff_size) {
printf("write() failed\n");
goto slic_dl_out;
}
}
/* Read */
if (FD_ISSET(tdm_fd, &rd_fds))
{
memset(aud_buf[0], 0, buff_size);
msg_len = read(tdm_fd, aud_buf[0], buff_size);
if (msg_len < buff_size) {
printf("read() failed\n");
goto slic_dl_out;
}
if(loops++ > 3) {
for(ch = 0; ch < total_lines; ch++) {
if(slic_dl_data_compare(ch)) {
printf("\nERROR - data miscompare(loops=%d) !!!\n",loops);
cmp_status = 1;
goto slic_dl_out;
}
}
}
}
/* Reload timeout */
timeout.tv_usec = TIMEOUT;
}
slic_dl_out:
if(cmp_status == 0)
printf("\nDigital loopback test(%d lines) - PASS !!!\n",total_lines);
if (ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
printf("Error, unable to stop pcm bus\n");
return;
}
lp = VP_OPTION_LB_OFF;
/* Disable loopback mode */
for(ch = 0; ch < total_lines; ch++)
VpSetOption(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_NULL, VP_OPTION_ID_LOOPBACK, &lp);
/* Put SLIC/s in STANDBY mode */
for(ch = 0; ch < total_lines; ch++)
VpSetLineState(&pLineCtx[GET_DEVICE(ch)][GET_LINE(ch)], VP_LINE_STANDBY);
}
static inline int slic_dl_data_compare(int ch)
{
int i = 0, offset = (ch * pcm_bytes * 80);
/* Align Tx & Rx data start */
while((aud_buf[1][offset] != aud_buf[0][offset+i]) && (i < (pcm_bytes * 80)))
i++;
if(i >= (offset + (pcm_bytes * 80))) {
printf("\nError, first Tx byte not found inside Rx buffer\n");
return -1;
}
if(memcmp(&aud_buf[0][offset+i], &aud_buf[1][offset], ((pcm_bytes * 80) - i))) {
printf("\nDump buffers:\n");
for(i = offset; i < (offset +(pcm_bytes * 80)); i++)
printf("write[%d] = 0x%x, read[%d] = 0x%x\n", i, aud_buf[1][i], i, aud_buf[0][i]);
return -1;
}
else
return 0;
}
static void sw_loopback(int tdm_fd, unsigned char line_id)
{
fd_set rd_fds, wr_fds;
struct timeval timeout = {0, TIMEOUT};
int msg_len;
if (tdm_fd <= 0) {
printf("Device %s is not accessible\n", dev_name);
return;
}
/* Wait until line goes off-hook */
while(hook_state[line_id] == 0) {
wait_for_vpapi_event();
}
if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
printf("Error, unable to start pcm bus\n");
return;
}
while(hook_state[line_id] == 1) {
FD_ZERO(&rd_fds);
FD_ZERO(&wr_fds);
FD_SET(tdm_fd, &rd_fds);
FD_SET(tdm_fd, &wr_fds);
/* Wait for event */
if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
return;
}
/* Read */
if (FD_ISSET(tdm_fd, &rd_fds))
{
printf("Rd\n");
msg_len = read(tdm_fd, aud_buf[0], buff_size);
if (msg_len <= 0) {
printf("read() failed\n");
return;
}
memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
}
/* Write */
if (FD_ISSET(tdm_fd, &wr_fds))
{
printf("Wr\n");
msg_len = write(tdm_fd, aud_buf[1], buff_size);
if (msg_len <= 0) {
printf("write() failed\n");
return;
}
}
/* Check hook state */
wait_for_vpapi_event();
/* Reload timeout */
timeout.tv_usec = TIMEOUT;
}
if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
printf("Error, unable to stop pcm bus\n");
return;
}
}
static void gen_tone(unsigned short freq, unsigned char line_id, unsigned char* tx_buff)
{
short i;
short buf[80];
short sample;
for(i = 0; i < 80; i++) {
sample = (sinTbl[f1Mem >> 8] + sinTbl[f2Mem >> 8]) >> 2;
#ifndef CONFIG_CPU_BIG_ENDIAN
buf[i] = sample;
#else
buf[i] = ((sample & 0xff) << 8)+ (sample >> 8);
#endif
f1Mem += freq;
f2Mem += freq;
}
memcpy(BUFF_ADDR(tx_buff, line_id), (void *)buf, 160);
}
static void sw_tone_test(int tdm_fd, unsigned char line_id)
{
fd_set wr_fds;
struct timeval timeout = {0, TIMEOUT};
int msg_len, x;
char str[4];
if (tdm_fd <= 0) {
printf("%s Device %s is not accessible\n", TOOL_PREFIX, dev_name);
return;
}
while(1) {
printf("%s Choose frequency: (1) 300HZ (2) 630HZ (3) 1000HZ (4) Back to main menu: ", TOOL_PREFIX);
gets(str);
printf("%s Waiting for off-hook...\n", TOOL_PREFIX);
if(str[0] == '1') {
x = 2457;
//printf("%s Generating 300HZ tone\n", TOOL_PREFIX);
}
else if (str[0] == '2') {
x = 5161;
//printf("%s Generating 630HZ tone\n", TOOL_PREFIX);
}
else if (str[0] == '3') {
x = 8192;
//printf("%s Generating 1000HZ tone\n", TOOL_PREFIX);
}
else if (str[0] == '4') {
return;
}
else {
printf("%s Input error - try again\n", TOOL_PREFIX);
continue;
}
/* Wait until both lines go off-hook */
while(hook_state[line_id] == 0) {
wait_for_vpapi_event();
}
if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
printf("Error, unable to start pcm bus\n");
return;
}
printf("%s Waiting for on-hook to return to menu.\n", TOOL_PREFIX);
while(hook_state[line_id] == 1) {
FD_ZERO(&wr_fds);
FD_SET(tdm_fd, &wr_fds);
/* Wait for event */
if (select(tdm_fd+1, NULL, &wr_fds, NULL, &timeout) == 0) {
printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
return;
}
/* Write */
if (FD_ISSET(tdm_fd, &wr_fds))
{
gen_tone(x, line_id, aud_buf[1]);
if (pcm_bytes == 4)
gen_tone(x, line_id, (aud_buf[1]+160));
msg_len = write(tdm_fd, aud_buf[1], buff_size);
if (msg_len <= 0) {
printf("write() failed\n");
return;
}
}
/* Check hook state */
wait_for_vpapi_event();
/* Reload timeout */
timeout.tv_usec = TIMEOUT;
}
}
}
static void sw_loopback_multi_phones_test(int tdm_fd, unsigned char start_line, unsigned char end_line)
{
fd_set rd_fds, wr_fds;
struct timeval timeout = {0, TIMEOUT};
int msg_len;
unsigned char line_id;
if (tdm_fd <= 0) {
printf("Device %s is not accessible\n", dev_name);
return;
}
/* Wait until at least one line goes off-hook */
while(offhook_count == 0) {
wait_for_vpapi_event();
}
if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
printf("Error, unable to start pcm bus\n");
return;
}
while(offhook_count) {
FD_ZERO(&rd_fds);
FD_ZERO(&wr_fds);
FD_SET(tdm_fd, &rd_fds);
FD_SET(tdm_fd, &wr_fds);
/* Wait for event */
if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
return;
}
/* Read */
if (FD_ISSET(tdm_fd, &rd_fds))
{
msg_len = read(tdm_fd, aud_buf[0], buff_size); if (msg_len <= 0) {
printf("read() failed\n");
return;
}
for(line_id = start_line; line_id < end_line; line_id+=2) {
memcpy(BUFF_ADDR(aud_buf[1], line_id), BUFF_ADDR(aud_buf[0], (line_id+1)), CH_BUFF_SIZE);
memcpy(BUFF_ADDR(aud_buf[1], (line_id+1)), BUFF_ADDR(aud_buf[0], line_id), CH_BUFF_SIZE);
}
}
/* Write */
if (FD_ISSET(tdm_fd, &wr_fds))
{
msg_len = write(tdm_fd, aud_buf[1], buff_size);
if (msg_len <= 0) {
printf("write() failed\n");
return;
}
}
/* Check hook state */
wait_for_vpapi_event();
/* Reload timeout */
timeout.tv_usec = TIMEOUT;
}
if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
printf("Error, unable to stop pcm bus\n");
return;
}
}
static void sw_loopback_two_phones_test(int tdm_fd, unsigned char line0, unsigned char line1)
{
fd_set rd_fds, wr_fds;
struct timeval timeout = {0, TIMEOUT};
int msg_len;
if (tdm_fd <= 0) {
printf("Device %s is not accessible\n", dev_name);
return;
}
if(ioctl(tdm_fd, TDM_DEV_PCM_START, 0)) {
printf("Error, unable to start pcm bus\n");
return;
}
/* Wait until both lines go off-hook */
while((hook_state[line0] == 0) || (hook_state[line1] == 0)) {
wait_for_vpapi_event();
}
while((hook_state[line0] == 1) && (hook_state[line1] == 1)) {
FD_ZERO(&rd_fds);
FD_ZERO(&wr_fds);
FD_SET(tdm_fd, &rd_fds);
FD_SET(tdm_fd, &wr_fds);
/* Wait for event */
if (select(tdm_fd+1, &rd_fds, &wr_fds, NULL, &timeout) == 0) {
printf("Error, timeout while polling(%dusec)\n", TIMEOUT);
return;
}
/* Read */
if (FD_ISSET(tdm_fd, &rd_fds))
{
msg_len = read(tdm_fd, aud_buf[0], buff_size); if (msg_len <= 0) {
printf("read() failed\n");
return;
}
memcpy(BUFF_ADDR(aud_buf[1], line0), BUFF_ADDR(aud_buf[0], line1), CH_BUFF_SIZE);
memcpy(BUFF_ADDR(aud_buf[1], line1), BUFF_ADDR(aud_buf[0], line0), CH_BUFF_SIZE);
}
/* Write */
if (FD_ISSET(tdm_fd, &wr_fds))
{
msg_len = write(tdm_fd, aud_buf[1], buff_size);
if (msg_len <= 0) {
printf("write() failed\n");
return;
}
}
/* Check hook state */
wait_for_vpapi_event();
/* Reload timeout */
timeout.tv_usec = TIMEOUT;
}
if(ioctl(tdm_fd, TDM_DEV_PCM_STOP, 0)) {
printf("Error, unable to stop pcm bus\n");
return;
}
}
static int vpapi_init(void)
{
int i = 0;
VpDeviceIdType dev_id = 0;
VpLineIdType line_id = 0;
VpLineIdType line_dev_num;
VpStatusType status;
vpapi_init_device_params_t params;
/* Check params */
if(total_lines > MAX_LINES) {
printf("## Error, total number of lines(%d) exceeded maximum(%d) ##\n", total_lines, MAX_LINES);
return -1;
}
/* Set lines status to on-hook */
memset(hook_state, 0, MAX_LINES);
cal_devs = 0;
#ifdef LINE_CALIBRATION_SUPPORT
cal_lines = 0;
#endif
/* Fill time slot table */
memset(time_slot_table, 0, MAX_LINES);
for(i = 0; i < total_lines; i++)
time_slot_table[i] = ((i+1) * pcm_bytes); /* skip slot #0 */
/* Extract PCM format */
switch(pcm_bytes)
{
case 1:
codec = VP_OPTION_ALAW;
break;
case 2:
codec = VP_OPTION_LINEAR;
break;
case 4:
codec = VP_OPTION_WIDEBAND;
break;
default:
codec = VP_OPTION_ALAW;
printf("## Warning, wrong PCM size - set to default(ALAW) ##\n");
break;
}
#if defined(ZARLINK_SLIC_VE792)
/* Bring up the power supply */
if(BattOn(VBH, VBL, VBP)) {
printf("## Error, VE792 power supply could not initialized properly ##\n");
return -1;
}
#endif
/* Create max device objects */
for(dev_id = 0; dev_id < total_devs; dev_id++) {
status = VpMakeDeviceObject(VP_DEV_SERIES, dev_id, &pDevCtx[dev_id], &pDevObj[dev_id]);
if (status != VP_STATUS_SUCCESS) {
printf("## Error, device %d could not initialized properly(status=%d) ##\n", dev_id, status);
return -1;
}
#if defined(ZARLINK_SLIC_VE792)
status = VpMapSlacId(&pDevCtx[dev_id], 0);
if (status != VP_STATUS_SUCCESS) {
printf("## Error, SLAC %d could not be mapped(status=%d) ##\n", dev_id, status);
return -1;
}
#endif
/* Create requested channels for each device */
while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
/*printf("dev_id = %d, line_id = %d, total_lines = %d, total_dev = %d\n", dev_id, line_id, total_lines, total_devs);*/
status = VpMakeLineObject(VP_TERM_FXS_GENERIC, GET_LINE(line_id), &pLineCtx[dev_id][GET_LINE(line_id)],
&pLineObj[dev_id][GET_LINE(line_id)], &pDevCtx[dev_id]);
if (status != VP_STATUS_SUCCESS) {
printf("## Error, line %d of device %d could not initialized \
properly(status=%d) ##\n", line_id, dev_id, status);
return -1;
}
/* Map unique LineId to LineCtx */
status = VpMapLineId(&pLineCtx[dev_id][GET_LINE(line_id)], line_id);
if (status != VP_STATUS_SUCCESS) {
printf("## Error, line %d for device %d could not \
mapped(status=%d) ##\n", line_id, dev_id, status);
return -1;
}
line_id++;
}
params.dev_size = dev_profile_size;
params.ac_size = ac_profile_size;
params.dc_size = dc_profile_size;
params.ring_size = ring_profile_size;
params.fxo_ac_size = 0;
params.fxo_cfg_size = 0;
/*printf("pcm_bytes = %d, total_dev = %d\n", pcm_bytes, total_devs);*/
if (pcm_bytes < 4)
status = vpapi_init_device(dev_id, DEV_PROFILE, AC_COEFF, DC_COEFF, RING_PROFILE, NULL, NULL, &params);
else
status = vpapi_init_device(dev_id, DEV_PROFILE, WB_AC_COEFF, DC_COEFF, RING_PROFILE, NULL, NULL, &params);
if (status != VP_STATUS_SUCCESS) {
printf("## Error, device(%d) init failed(status=%d)\n", dev_id, status);
return -1;
}
}
return 0;
}
static inline void wait_for_vpapi_event(void)
{
bool status;
VpEventType event;
VpDeviceIdType dev_id;
for(dev_id = 0; dev_id < total_devs ; dev_id++) {
while(sys_service_get_event(dev_id, &event) == TRUE) {
switch(event.eventCategory) {
case VP_EVCAT_SIGNALING:
switch(event.eventId) {
case VP_LINE_EVID_HOOK_OFF:
if(cal_devs == total_devs) {
printf("off-hook(%d)\n", event.lineId);
hook_state[event.lineId] = 1;
offhook_count++;
VpSetLineState(&pLineCtx[GET_DEVICE(event.lineId)][GET_LINE(event.lineId)], VP_LINE_TALK);
}
break;
case VP_LINE_EVID_HOOK_ON:
if(cal_devs == total_devs) {
printf("on-hook(%d)\n", event.lineId);
hook_state[event.lineId] = 0;
offhook_count--;
VpSetLineState(&pLineCtx[GET_DEVICE(event.lineId)][GET_LINE(event.lineId)], VP_LINE_STANDBY);
}
break;
default:
/*printf("Unknown SIGNALING event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);*/
break;
}
break;
case VP_EVCAT_RESPONSE:
switch(event.eventId) {
case VP_DEV_EVID_DEV_INIT_CMP:
printf("Zarlink telephony device(%d) initialized successfully\n", event.deviceId);
vpapi_dev_init(event.deviceId);
cal_devs++;
break;
case VP_EVID_CAL_CMP:
#ifdef LINE_CALIBRATION_SUPPORT
cal_lines++;
if(cal_lines == (total_lines-1)) {
/*VpOptionLoopbackType lp = VP_OPTION_LB_TIMESLOT;
vpapi_set_option(1, 0, 0, VP_OPTION_ID_LOOPBACK, &lp); */
printf("Zarlink telephony lines(%d) calibrated successfully\n", total_lines);
vpapi_init_done();
}
#endif
break;
default:
/*printf("Unknown RESPONSE event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);*/
break;
}
break;
case VP_EVCAT_FAULT:
printf("Got FAULT event[id-0x%x][lineId-%d]\n",event.eventId, event.lineId);
break;
default:
printf("Got event[category-0x%x][id-%d]\n",event.eventCategory,event.eventId);
break;
}
}
}
}
static void vpapi_init_done(void)
{
VpStatusType status;
VpDeviceIdType dev_id;
VpLineIdType line_id, base_line_id;
for (dev_id = 0; dev_id < total_devs; dev_id++)
{
line_id = (dev_id * MAX_DEVICE_LINES);
while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
/* Set CODEC options */
status = VpSetOption(&pLineCtx[dev_id][GET_LINE(line_id)], VP_NULL, VP_OPTION_ID_CODEC, &codec);
if(status != VP_STATUS_SUCCESS)
{
printf("## Error setting VP_OPTION_ID_CODEC (%d) ##\n", status);
return;
}
line_id++;
}
}
return;
}
static void vpapi_dev_init(VpDeviceIdType dev_id)
{
VpOptionEventMaskType event_mask;
VpStatusType status;
VpOptionTimeslotType time_slot;
VpLineIdType line_id;
/* Clear all events */
memset(&event_mask, 0xff, sizeof(VpOptionEventMaskType));
event_mask.faults = (unsigned short)VP_EVCAT_FAULT_UNMASK_ALL;
event_mask.signaling = (unsigned short)(~(VP_LINE_EVID_HOOK_OFF | VP_LINE_EVID_HOOK_ON));
#ifdef LINE_CALIBRATION_SUPPORT
event_mask.response = (unsigned short)(~VP_EVID_CAL_CMP);
#endif
status = VpSetOption(VP_NULL, &pDevCtx[dev_id], VP_OPTION_ID_EVENT_MASK, &event_mask);
if(status != VP_STATUS_SUCCESS)
{
printf("## Error while setting VP_OPTION_ID_EVENT_MASK (%d) ##\n", status);
return;
}
line_id = (dev_id * MAX_DEVICE_LINES);
while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
VpSetLineState(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)], VP_LINE_STANDBY);
/* Configure PCM timeslots */
time_slot.tx = time_slot.rx = time_slot_table[line_id];
/*printf("## INFO: line(%d): rx-slot(%d) , tx-slot(%d) ##\n", line_id, time_slot.rx, time_slot.tx);*/
status = VpSetOption(&pLineCtx[dev_id][GET_LINE(line_id)], VP_NULL, VP_OPTION_ID_TIMESLOT, &time_slot);
if(status != VP_STATUS_SUCCESS)
{
printf("## Error setting VP_OPTION_ID_TIMESLOT (%d) ##\n", status);
return;
}
#if 0
/* Set CODEC options */
status = vpapi_set_option(1, line_id, dev_id, VP_OPTION_ID_CODEC, &codec);
if(status != VP_STATUS_SUCCESS)
{
printf("## Error setting VP_OPTION_ID_CODEC (%d) ##\n", status);
return;
}
#endif
#ifdef LINE_CALIBRATION_SUPPORT
/* Start line calibration */
status = VpCalLine(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)]);
if(status == VP_STATUS_SUCCESS) {
REGISTER_LINE(line_id);
}
#endif
line_id++;
}
}
static void vpapi_release(void)
{
VpDeviceIdType dev_id = 0;
VpLineIdType line_id = 0;
VpOptionEventMaskType event_mask;
VpStatusType status;
/* Clear all events */
memset(&event_mask, 0xff, sizeof(VpOptionEventMaskType));
for(dev_id = 0; dev_id < total_devs; dev_id++) {
/* Mask all interrupts */
status = VpSetOption(VP_NULL, &pDevCtx[dev_id], VP_OPTION_ID_EVENT_MASK, &event_mask);
if(status != VP_STATUS_SUCCESS) {
printf("Error while setting VP_OPTION_ID_EVENT_MASK (%d)\n", status);
continue;
}
while((line_id < ((dev_id+1)*MAX_DEVICE_LINES)) && (line_id < total_lines)) {
/* Place each line in DISCONNECT state */
VpSetLineState(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)], VP_LINE_DISCONNECT);
/* Free line context */
status = VpFreeLineCtx(&pLineCtx[GET_DEVICE(line_id)][GET_LINE(line_id)]);
if(status == VP_STATUS_SUCCESS) {
vpapi_line_status[line_id] = 0;
total_lines--;
#if defined(SLIC_TIMER_EVENT_SUPPORT)
if(total_lines == 0) {
atomic_set(&vpapi_init, 0);
del_timer(&vpapi_timer);
}
#endif
} else {
printf("Error while free line %d context\n", line_id);
continue;
}
line_id++;
}
}
#if defined(ZARLINK_SLIC_VE792)
/* Shut down the power supply */
if(BattOff()) {
printf("## Error while shutting down VE792 power supply ##\n");
sleep(1);
}
#endif
}
VpStatusType vpapi_init_device(VpDeviceIdType dev_id, VpProfilePtrType dev_profile_ptr,
VpProfilePtrType ac_profile_ptr, VpProfilePtrType dc_profile_ptr,
VpProfilePtrType ring_profile_ptr, VpProfilePtrType fxo_ac_profile_ptr,
VpProfilePtrType fxo_cfg_profile_ptr, vpapi_init_device_params_t *params_ptr)
{
VpStatusType status;
int rc;
status = VpInitDevice(&pDevCtx[dev_id], dev_profile_ptr, ac_profile_ptr, dc_profile_ptr, ring_profile_ptr,
fxo_ac_profile_ptr, fxo_cfg_profile_ptr);
if(status == VP_STATUS_SUCCESS) {
REGISTER_DEVICE(dev_id);
}
return 0;
}
#if defined(MV_TDM_USE_DCO)
static void set_tdm_clk_config(void)
{
tdm_dev_clk_t tdm_dev_clk;
/* Config TDM clock */
if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_CONFIG, &tdm_dev_clk)) {
printf("%s Error, unable to config TDM clock.\n", TOOL_PREFIX);
}
}
static int get_tdm_clk_correction(void)
{
tdm_dev_clk_t tdm_dev_clk;
/* Get TDM clock */
if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_GET, &tdm_dev_clk)) {
printf("%s Error, unable to get TDM clock.\n", TOOL_PREFIX);
return 0;
}
return tdm_dev_clk.correction;
}
static void set_tdm_clk_correction(int correction)
{
tdm_dev_clk_t tdm_dev_clk;
tdm_dev_clk.correction=correction;
/* Set TDM clock */
if(ioctl(tdm_fd, TDM_DEV_TDM_CLK_SET, &tdm_dev_clk)) {
printf("%s Error, unable to set TDM clock.\n", TOOL_PREFIX);
}
}
#endif