diff --git a/connection.h b/connection.h deleted file mode 100644 index c74e31aa1618425bf3ee4a8381da39e9725ba621..0000000000000000000000000000000000000000 --- a/connection.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef ENDPTMNGR_CONNECTION_H -#define ENDPTMNGR_CONNECTION_H - - -//------------------------------------------------------------- -extern struct connection_t *connection; - -//------------------------------------------------------------- -int find_connection_from_asterisk_id(int line, int conId); - -#endif diff --git a/libvoice/broadcom/brcm-connection.c b/libvoice/broadcom/brcm-connection.c index 922dfce41bd2983b75eb9262766c6f4e3d323049..90f83e7a3e428a56a32db7fb460ea228b71f4053 100644 --- a/libvoice/broadcom/brcm-connection.c +++ b/libvoice/broadcom/brcm-connection.c @@ -1,4 +1,3 @@ - // Management of call connections #include <stdio.h> @@ -8,23 +7,17 @@ #include <stdlib.h> #include <string.h> #include <sys/types.h> -#include <sched.h> // sched_yield() +#include <sched.h> // sched_yield() #include <bosTypes.h> -#include <hapi_rtp.h> // for vrgEndptPrivate.h to work -#include <vrgEndptCfg.h> // for vrgEndptPrivate.h to work -#include <bosSemLinuxUser.h> // for vrgEndptPrivate.h to work -#include <vrgEndptPrivate.h> // struct VRG_ENDPT -#include <hdspCmd.h> // hdspSendCmd -#include <hapi_hec.h> // HAPI_HEC_SETREG1_CMD - -#include "connection.h" -#include "main.h" -#include "line.h" -#include "line-dect.h" -#include "log.h" +#include <hapi_rtp.h> // for vrgEndptPrivate.h to work +#include <vrgEndptCfg.h> // for vrgEndptPrivate.h to work +#include <bosSemLinuxUser.h> // for vrgEndptPrivate.h to work +#include <vrgEndptPrivate.h> // struct VRG_ENDPT +#include <hdspCmd.h> // hdspSendCmd +#include <hapi_hec.h> // HAPI_HEC_SETREG1_CMD -struct connection_t *connection; +#include "libvoice.h" //------------------------------------------------------------- // Create an endpoint connection and assign the unique @@ -33,69 +26,72 @@ struct connection_t *connection; int voice_connection_create(int line, int conId) { VRG_ENDPT *epIntern; EPSTATUS status; + EPZCNXPARAM *epCnx; int conIdx, i; // Check that the new connection is unique - if(find_connection_from_asterisk_id(line, conId) != -1) { + if(voice_connection_find(line, conId) != -1) { ENDPT_DBG("Error; duplicated connection %d %d\n", line, conId); return -1; } // Find a free slot for this new connection - for(conIdx = 0; conIdx < epInfo.numEndpoints * MAX_NUM_CNX && - connection[conIdx].line != -1 && - connection[conIdx].conId != -1; conIdx++); - if(conIdx == epInfo.numEndpoints * MAX_NUM_CNX) { - ENDPT_DBG("Error; out of connetion memory %d %d\n", line, conId); + for(conIdx = 0; + conIdx < max_num_connections && connections[conIdx].line != -1 && connections[conIdx].conId != -1; + conIdx++); + if(conIdx >= max_num_connections) { + ENDPT_DBG("Error; out of connection memory %d %d\n", line, conId); return -1; } // Find lines[line].epHandle for this connection for(i = 0; i < epInfo.numEndpoints && lines[i].epHandle.lineId != line; i++); - if(i == epInfo.numEndpoints) { + if(i >= epInfo.numEndpoints) { ENDPT_DBG("Error; can't find endpoint %d %d\n", line, conId); return -1; } - connection[conIdx].line = i; - connection[conIdx].conId = conId; + connections[conIdx].line = i; + connections[conIdx].conId = conId; /* Arguments for which codec to use etc. This maps endpoint * capabilites and UCI config to per connection config. */ - memset(&connection[conIdx].epCnx, 0, sizeof(EPZCNXPARAM)); - connection[conIdx].epCnx.mode = EPCNXMODE_SNDRX; - connection[conIdx].epCnx.cnxParmList.send.codecs[0].type = CODEC_PCMA; - connection[conIdx].epCnx.cnxParmList.recv.codecs[0].type = CODEC_PCMA; - connection[conIdx].epCnx.cnxParmList.send.codecs[0].rtpPayloadType = + epCnx = (EPZCNXPARAM *)connections[conIdx].priv; + memset(epCnx, 0, sizeof(EPZCNXPARAM)); + epCnx->mode = EPCNXMODE_SNDRX; + epCnx->cnxParmList.send.codecs[0].type = CODEC_PCMA; + epCnx->cnxParmList.recv.codecs[0].type = CODEC_PCMA; + epCnx->cnxParmList.send.codecs[0].rtpPayloadType = RTP_PAYLOAD_PCMA; - connection[conIdx].epCnx.cnxParmList.recv.codecs[0].rtpPayloadType = + epCnx->cnxParmList.recv.codecs[0].rtpPayloadType = RTP_PAYLOAD_PCMA; - connection[conIdx].epCnx.cnxParmList.send.numCodecs = 1; - connection[conIdx].epCnx.cnxParmList.recv.numCodecs = 1; - connection[conIdx].epCnx.cnxParmList.send.numPeriods = 1; - connection[conIdx].epCnx.cnxParmList.recv.numPeriods = 1; - connection[conIdx].epCnx.cnxParmList.send.period[0] = CODEC_PTIME_20; - connection[conIdx].epCnx.cnxParmList.recv.period[0] = CODEC_PTIME_20; - connection[conIdx].epCnx.namedPhoneEvts = lines[line].epCap.nteCap; - connection[conIdx].epCnx.echocancel = + epCnx->cnxParmList.send.numCodecs = 1; + epCnx->cnxParmList.recv.numCodecs = 1; + epCnx->cnxParmList.send.numPeriods = 1; + epCnx->cnxParmList.recv.numPeriods = 1; + epCnx->cnxParmList.send.period[0] = CODEC_PTIME_20; + epCnx->cnxParmList.recv.period[0] = CODEC_PTIME_20; + epCnx->namedPhoneEvts = lines[line].epCap.nteCap; + epCnx->echocancel = (lines[line].epCap.eCap && lines[line].uciConf.echocancel ? 1 : 0); - connection[conIdx].epCnx.silence = + epCnx->silence = (lines[line].epCap.sCap && lines[line].uciConf.silence ? 1 : 0); - connection[conIdx].epCnx.comfortNoise = (lines[line].uciConf.comfortNoise ? 1 : 0); - connection[conIdx].epCnx.preserveFaxMode = 0; - connection[conIdx].epCnx.secHdrSize = 0; - connection[conIdx].epCnx.dataMode = EPDATAMODE_NONE; - connection[conIdx].epCnx.autoEncoder = EPAUTOENC_OFF; - connection[conIdx].epCnx.vbdparam.vbdMode = EPVBDMODE_NONE; - connection[conIdx].epCnx.digitRelayType = EPDTMFRFC2833_DISABLED; - connection[conIdx].epCnx.rtcpXRConfig = HAPI_RTP_RTCP_XR_GENERATE_VOIP_REPORT; - connection[conIdx].epCnx.txVolume = lines[line].uciConf.txgain; - connection[conIdx].epCnx.rxVolume = lines[line].uciConf.rxgain; + epCnx->comfortNoise = (lines[line].uciConf.comfortNoise ? 1 : 0); + epCnx->preserveFaxMode = 0; + epCnx->secHdrSize = 0; + epCnx->dataMode = EPDATAMODE_NONE; + epCnx->autoEncoder = EPAUTOENC_OFF; + epCnx->vbdparam.vbdMode = EPVBDMODE_NONE; + epCnx->digitRelayType = EPDTMFRFC2833_DISABLED; + epCnx->rtcpXRConfig = HAPI_RTP_RTCP_XR_GENERATE_VOIP_REPORT; + epCnx->txVolume = lines[line].uciConf.txgain; + epCnx->rxVolume = lines[line].uciConf.rxgain; // Is the endpoint in onhook state? For dect we simulate offhook. - if(perhapsSimulateHook(line, EPEVT_OFFHOOK)) goto err; + if(perhapsSimulateHook(line, EPEVT_OFFHOOK)) + goto err; - status = vrgEndptCreateConnection(&lines[connection[conIdx].line].epHandle, - conId, &connection[conIdx].epCnx); + status = vrgEndptCreateConnection(&lines[connections[conIdx].line].epHandle, + conId, &connections[conIdx].epCnx); if (status != EPSTATUS_SUCCESS) { ENDPT_DBG("Error creating connection %d: %s\n", conId, strerror_endp(status)); @@ -105,7 +101,7 @@ int voice_connection_create(int line, int conId) { /* Disable DSP-lib non-linear processing due to it causes audio * clipping. An alternative is to disable echo cancelation. This * method is however less intrusive we hope... */ - if(connection[conIdx].epCnx.echocancel) { + if(epCnx->echocancel) { epIntern = GetEndptState(line); if(!epIntern) goto err; @@ -119,8 +115,8 @@ int voice_connection_create(int line, int conId) { return 0; err: - connection[conIdx].line = -1; - connection[conIdx].conId = -1; + connections[conIdx].line = -1; + connections[conIdx].conId = -1; return -1; } @@ -133,16 +129,17 @@ int voice_connection_close(int line, int conId) { res = 0; epIntern = GetEndptState(line); - if(!epIntern || epIntern->cnxCnt == 0) return 0; // Line was already closed + if(!epIntern || epIntern->cnxCnt == 0) return 0; // Line was already closed - conIdx = find_connection_from_asterisk_id(line, conId); - if(conIdx == -1) return -1; + conIdx = voice_connection_find(line, conId); + if (conIdx == -1) + return -1; // Does the the endpoint use simulated hook events? Then do onhook now. res = perhapsSimulateHook(line, EPEVT_ONHOOK); status = vrgEndptDeleteConnection( - &lines[connection[conIdx].line].epHandle, conId); + &lines[connections[conIdx].line].epHandle, conId); if (status != EPSTATUS_SUCCESS) { ENDPT_DBG("Error closeing connection %d\n", conId); ENDPT_DBG("Error closeing connection BRCM/%d/%d\n", line, conId); @@ -150,8 +147,8 @@ int voice_connection_close(int line, int conId) { } if(res == 0) ENDPT_DBG("Closed connection BRCM/%d/%d\n", line, conId); - connection[conIdx].line = -1; // Mark connection slot free - connection[conIdx].conId = -1; + connections[conIdx].line = -1; // Mark connection slot free + connections[conIdx].conId = -1; return res; } @@ -163,10 +160,10 @@ int voice_connection_close_all(void) { res = 0; - for(conIdx = 0; conIdx < epInfo.numEndpoints * MAX_NUM_CNX; conIdx++) { - if(connection[conIdx].line != -1 && connection[conIdx].conId != -1 && - lines[connection[conIdx].line].epHandle.lineId != -1 && - voice_connection_close(connection[conIdx].line, connection[conIdx].line)) { + for(conIdx = 0; conIdx < max_num_connections; conIdx++) { + if(connections[conIdx].line != -1 && connections[conIdx].conId != -1 && + lines[connections[conIdx].line].epHandle.lineId != -1 && + voice_connection_close(connections[conIdx].line, connections[conIdx].line)) { res = -1; } } @@ -178,14 +175,17 @@ int voice_connection_close_all(void) { // Set an existing connection into conferece call mode int voice_connection_conference_start(int line, int conId) { EPSTATUS status; + EPZCNXPARAM *epCnx; int conIdx; - conIdx = find_connection_from_asterisk_id(line, conId); - if(conIdx == -1) return -1; + conIdx = voice_connection_find(line, conId); + if(conIdx == -1) + return -1; - connection[conIdx].epCnx.mode = EPCNXMODE_CONF; - status = vrgEndptModifyConnection(&lines[connection[conIdx].line].epHandle, - conId, &connection[conIdx].epCnx); + epCnx = (EPZCNXPARAM *)connections[conIdx].priv; + epCnx->mode = EPCNXMODE_CONF; + status = vrgEndptModifyConnection(&lines[connections[conIdx].line].epHandle, + conId, epCnx); if (status == EPSTATUS_SUCCESS) { ENDPT_DBG("Enabled conference for connection %d/%d\n", line, conId); } @@ -201,14 +201,17 @@ int voice_connection_conference_start(int line, int conId) { // Set an existing conference call into "normal" mode int voice_connection_conference_stop(int line, int conId) { EPSTATUS status; + EPZCNXPARAM *epCnx; int conIdx; - conIdx = find_connection_from_asterisk_id(line, conId); - if(conIdx == -1) return -1; + conIdx = voice_connection_find(line, conId); + if(conIdx == -1) + return -1; - connection[conIdx].epCnx.mode = EPCNXMODE_SNDRX; - status = vrgEndptModifyConnection(&lines[connection[conIdx].line].epHandle, - conId, &connection[conIdx].epCnx); + epCnx = (EPZCNXPARAM *)connections[conIdx].priv; + epCnx->mode = EPCNXMODE_SNDRX; + status = vrgEndptModifyConnection(&lines[connections[conIdx].line].epHandle, + conId, epCnx); if (status == EPSTATUS_SUCCESS) { ENDPT_DBG("Disabled conference for connection %d/%d\n", line, conId); } @@ -221,19 +224,23 @@ int voice_connection_conference_stop(int line, int conId) { } //------------------------------------------------------------- -int voice_connection_init(void) { +int voice_connection_init(int num_terminals) { int i; - // Initialize list of active connections and mark all as free - connection = malloc(sizeof(struct connection_t) * - epInfo.numEndpoints * MAX_NUM_CNX); - if(!connection) { - err_exit("Error init connection mem\n"); + max_num_connections = num_terminals * VRG_ENDPT_CFG_MAX_CNX_PER_ENDPT; + + connections = malloc(sizeof(struct connection_t) * max_num_connections); + if(!connections) { + err_exit("Error out of memory\n"); } - for(i = 0; i < epInfo.numEndpoints * MAX_NUM_CNX; i++) { - connection[i].line = -1; - connection[i].conId = -1; + for(i = 0; i < max_num_connections; i++) { + connections[i].line = -1; + connections[i].conId = -1; + connections[i].priv = (EPZCNXPARAM *)malloc(sizeof(EPZCNXPARAM)); + if(!connections[i].priv) { + err_exit("Error out of memory\n"); + } } return 0; @@ -241,11 +248,15 @@ int voice_connection_init(void) { //------------------------------------------------------------- int voice_connection_deinit(void) { - // Terminate all calls - if(connection) { + int i; + + if(connections) { voice_connection_close_all(); - free(connection); - connection = NULL; + for(i = 0; i < max_num_connections; i++) { + free(connections[i].priv); + } + free(connections); + connections = NULL; } return 0; diff --git a/libvoice/broadcom/brcm-dect.c b/libvoice/broadcom/brcm-dect.c index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..594bdd3963022fd47c0736eeed766295b750d7e7 100644 --- a/libvoice/broadcom/brcm-dect.c +++ b/libvoice/broadcom/brcm-dect.c @@ -0,0 +1,162 @@ +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <assert.h> + +#include <bosTypes.h> +#include <vrgEndptCfg.h> // for vrgEndptPrivate.h to work +#include <hapi_rtp.h> // for vrgEndptPrivate.h to work +#include <bosSemLinuxUser.h> // for vrgEndptPrivate.h to work +#include <vrgEndptPrivate.h> // struct VRG_ENDPT + +//------------------------------------------------------------- +// Simulate phone line onhook for external Dect handset. +static int setDectOnhook(int line) { + VRG_ENDPT *epIntern; + int res = 0; + + ENDPT_DBG("%s: line=%d\n", __func__, line); + + epIntern = GetEndptState(line); + if(!epIntern) { + ENDPT_DBG("%s: GetEndptState() failed\n", __func__); + return -1; + } + + if(epIntern->cnxCnt > 1) { + ENDPT_DBG("%s: epIntern->cnxCnt(%d) > 1\n", __func__, epIntern->cnxCnt); + return 0; + } + + if(!lines[line].simulatedHook) { + ENDPT_DBG("%s:lines[%d].simulatedHook=0\n", __func__, line); + return 0; + } + + // Consider future hook states again. + if(casCtlIgnoreHookState(epIntern->casCtlHandle, + CAS_IGNOREHOOKSTATE_OFF) != CAS_CTL_SUCCESS) { + res = -1; + } + + // Go "early onhook" and then "fully onhook". + if(simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_ONHOOK) || + simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_ONHOOK)) { + res = -1; + } + + // Restore libvoip force onhook timeout. + if(vrgEndptProvSet(line, EPPROV_MinDisconnect, &lines[line].defMinDisconnect, + sizeof(uint32_t)) != EPSTATUS_SUCCESS) { + res = -1; + } + lines[line].simulatedHook = 0; + lines[line].signalizedCw = 0; + + return res; +} + +//------------------------------------------------------------- +// Simulate phone line offhook for Dect handset. +static int setDectOffhook(int line) { + uint32_t onhookTimeout = CAS_IGNOREHOOKSTATE_ON; // 16-bit variable in libvoip + VRG_ENDPT *epIntern; + EPSTATUS status; + + epIntern = GetEndptState(line); + if(!epIntern) + return -1; + if(epIntern->cnxCnt > 1) + return 0; + if(isLineOffhook(line)) + return 0;// No need for offhook + ENDPT_DBG("%s() BRCM/%d\n", __func__, line); + + // Extend the time until libvoip force onhooks. + status = vrgEndptProvSet(line, EPPROV_MinDisconnect, + &onhookTimeout, sizeof(uint32_t)); + if(status != EPSTATUS_SUCCESS) { + ENDPT_DBG("Error setting force onhook time %d: %s\n", + line, strerror_endp(status)); + goto err; + } + + // Go "early offhook" and then "fully offhook". + if(simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_OFFHOOK) || + simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_OFFHOOK)) { + goto err; + } + + // Ignore future hook state. + if(casCtlIgnoreHookState(epIntern->casCtlHandle, + CAS_IGNOREHOOKSTATE_ON) == CAS_CTL_SUCCESS) { + ENDPT_DBG("Simulated offhook for BRCM/%d/%c\n", line, '*'); + lines[line].simulatedHook = 1; + } + else { + goto err; + } + + return 0; +err: + setDectOnhook(line); + return -1; +} + +//------------------------------------------------------------- +// Simulate Dect hook flash (the R-key). +static int doDectHookFlash(int line) { + VRG_ENDPT *epIntern; + + epIntern = GetEndptState(line); + if(!epIntern) return -1; + if(epIntern->cnxCnt == 0) return 0; // No need for hook flash + if(!lines[line].simulatedHook) return 0; + if(!isLineOffhook(line)) return 0; + ENDPT_DBG("%s() BRCM/%d\n", __func__, line); + + // Go "early onhook", "early offhook" and then "flash". + if(simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_ONHOOK) || + simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_OFFHOOK) || + simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_FLASH)) { + goto err; + } + + // Ignore future hook state. + if(casCtlIgnoreHookState(epIntern->casCtlHandle, + CAS_IGNOREHOOKSTATE_ON) == CAS_CTL_SUCCESS) { + ENDPT_DBG("Simulated hook flash (R-key) for BRCM/%d\n", line); + } + else { + goto err; + } + + return 0; +err: + setDectOnhook(line); + return -1; +} + +//------------------------------------------------------------- +// If necessary, simulate an phone line event. +int perhapsSimulateHook(int line, EPEVT event) { + if(lines[line].epHandle.endptType != EPTYPE_DECT) return 0; + + switch(event) { + case EPEVT_ONHOOK: + return setDectOnhook(line); + + case EPEVT_OFFHOOK: + return setDectOffhook(line); + + case EPEVT_FLASH: + return doDectHookFlash(line); + + default: + return -1; + } + + return 0; +} diff --git a/libvoice/broadcom/brcm-line.c b/libvoice/broadcom/brcm-line.c index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..392f2bdbab09422ecc09451aaf796829745cac8b 100644 --- a/libvoice/broadcom/brcm-line.c +++ b/libvoice/broadcom/brcm-line.c @@ -0,0 +1,24 @@ +#include <endpoint_api.h> +#include <vrgEndptCfg.h> // VRG_ENDPT_CFG_MAX_CNX_PER_ENDPT +#include <casCtl.h> // CAS_CTL_DETECT_EVENT +#include <hapi_hec.h> // HAPI_HEC_VOLUME_MAX + +int voice_get_min_tx_gain(void) +{ + return HAPI_HEC_GAIN_MIN; +} + +int voice_get_max_tx_gain(void) +{ + return HAPI_HEC_GAIN_MAX; +} + +int voice_get_min_rx_gain(void) +{ + return HAPI_HEC_VOLUME_MIN; +} + +int voice_get_max_rx_gain(void) +{ + return HAPI_HEC_VOLUME_MAX; +} diff --git a/libvoice/common.c b/libvoice/common.c new file mode 100644 index 0000000000000000000000000000000000000000..da34c35c845b7bb0f4c58a017e4242b322f7bf6c --- /dev/null +++ b/libvoice/common.c @@ -0,0 +1,19 @@ +#include <stdio.h> + +#include <libvoice.h> + +struct connection_t *connections = NULL; +int max_num_connections = 0; + +int voice_connection_find(int line, int conId) +{ + int conIdx; + + for(conIdx = 0; conIdx < max_num_connections; conIdx++) { + if(connections[conIdx].line == line && connections[conIdx].conId == conId) { + return conIdx; + } + } + + return -1; +} diff --git a/libvoice/libvoice.h b/libvoice/libvoice.h index 7e98cf3b940441d53f079843d54be4a7ec5267aa..8a1d82fb8c6180407853911f52c3ff07f41045ce 100644 --- a/libvoice/libvoice.h +++ b/libvoice/libvoice.h @@ -1,18 +1,59 @@ #ifndef __LIBVOICE_H #define __LIBVOICE_H -struct connection_t { // Per connection parameters (one line can have many connections) - int line; // Logical line VOICE_DAUGHTER_BOARD_PARMS.BP_CHAN_PCM[i] - int conId; // Arbitrary number from Asterisk - EPZCNXPARAM epCnx; +#include <stdint.h> + +struct connection_t { // Per connection parameters (one line can have many connections) + int line; // Logical line VOICE_DAUGHTER_BOARD_PARMS.BP_CHAN_PCM[i] + int conId; // Arbitrary number from Asterisk + void *priv; // Platform dependent data +}; + +struct rtp_stats_t { + uint16_t local_burst_density; + uint16_t remote_burst_density; + uint16_t local_burst_duration; + uint16_t remote_burst_duration; + uint16_t local_gap_density; + uint16_t remote_gap_density; + uint16_t local_gap_duration; + uint16_t remote_gap_duration; + uint16_t local_jb_rate; + uint16_t remote_jb_rate; + uint16_t local_jb_max; + uint16_t remote_jb_max; + uint16_t local_jb_nominal; + uint16_t remote_jb_nominal; + uint16_t local_jb_abs_max; + uint16_t remote_jb_abs_max; + uint32_t discarded; + uint32_t lost; + uint32_t rxpkts; + uint32_t txpkts; + uint16_t jb_avg; + uint32_t jitter; + uint16_t loss_rate; + uint32_t max_jitter; + uint32_t avg_round_trip_delay; }; +extern struct connection_t *connections; +extern int max_num_connections; + +// Connection API +int voice_connection_init(int num_terminals); +int voice_connection_deinit(void); int voice_connection_create(int line, int conId); int voice_connection_close(int line, int conId); int voice_connection_close_all(void); int voice_connection_conference_start(int line, int conId); int voice_connection_conference_stop(int line, int conId); -int voice_connection_init(void); -int voice_connection_deinit(void); +int voice_connection_find(int line, int conId); + +// Misc +int voice_get_min_tx_gain(void); +int voice_get_max_tx_gain(void); +int voice_get_min_rx_gain(void); +int voice_get_max_rx_gain(void); #endif diff --git a/line-dect.c b/line-dect.c index b8fa69626ab91423daddb4bfe4eb2f43eddaea5f..b2cda9080a8862c1025b3c93ceec0e98b319bbe9 100644 --- a/line-dect.c +++ b/line-dect.c @@ -10,16 +10,9 @@ #include <sys/types.h> #include <assert.h> -#include <bosTypes.h> -#include <vrgEndptCfg.h> // for vrgEndptPrivate.h to work -#include <hapi_rtp.h> // for vrgEndptPrivate.h to work -#include <bosSemLinuxUser.h> // for vrgEndptPrivate.h to work -#include <vrgEndptPrivate.h> // struct VRG_ENDPT - #include "line-dect.h" #include "line.h" #include "ubus.h" -#include "connection.h" #include "log.h" //------------------------------------------------------------- @@ -86,156 +79,6 @@ int ubus_process_queued_reqs_to_dectmngr(void) { return 0; } -//------------------------------------------------------------- -// Simulate phone line onhook for external Dect handset. -static int setDectOnhook(int line) { - VRG_ENDPT *epIntern; - int res = 0; - - ENDPT_DBG("%s: line=%d\n", __func__, line); - - epIntern = GetEndptState(line); - if(!epIntern) { - ENDPT_DBG("%s: GetEndptState() failed\n", __func__); - return -1; - } - - if(epIntern->cnxCnt > 1) { - ENDPT_DBG("%s: epIntern->cnxCnt(%d) > 1\n", __func__, epIntern->cnxCnt); - return 0; - } - - if(!lines[line].simulatedHook) { - ENDPT_DBG("%s:lines[%d].simulatedHook=0\n", __func__, line); - return 0; - } - - // Consider future hook states again. - if(casCtlIgnoreHookState(epIntern->casCtlHandle, - CAS_IGNOREHOOKSTATE_OFF) != CAS_CTL_SUCCESS) { - res = -1; - } - - // Go "early onhook" and then "fully onhook". - if(simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_ONHOOK) || - simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_ONHOOK)) { - res = -1; - } - - // Restore libvoip force onhook timeout. - if(vrgEndptProvSet(line, EPPROV_MinDisconnect, &lines[line].defMinDisconnect, - sizeof(uint32_t)) != EPSTATUS_SUCCESS) { - res = -1; - } - lines[line].simulatedHook = 0; - lines[line].signalizedCw = 0; - - return res; -} - -//------------------------------------------------------------- -// Simulate phone line offhook for Dect handset. -static int setDectOffhook(int line) { - uint32_t onhookTimeout = CAS_IGNOREHOOKSTATE_ON; // 16-bit variable in libvoip - VRG_ENDPT *epIntern; - EPSTATUS status; - - epIntern = GetEndptState(line); - if(!epIntern) - return -1; - if(epIntern->cnxCnt > 1) - return 0; - if(isLineOffhook(line)) - return 0;// No need for offhook - ENDPT_DBG("%s() BRCM/%d\n", __func__, line); - - // Extend the time until libvoip force onhooks. - status = vrgEndptProvSet(line, EPPROV_MinDisconnect, - &onhookTimeout, sizeof(uint32_t)); - if(status != EPSTATUS_SUCCESS) { - ENDPT_DBG("Error setting force onhook time %d: %s\n", - line, strerror_endp(status)); - goto err; - } - - // Go "early offhook" and then "fully offhook". - if(simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_OFFHOOK) || - simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_OFFHOOK)) { - goto err; - } - - // Ignore future hook state. - if(casCtlIgnoreHookState(epIntern->casCtlHandle, - CAS_IGNOREHOOKSTATE_ON) == CAS_CTL_SUCCESS) { - ENDPT_DBG("Simulated offhook for BRCM/%d/%c\n", line, '*'); - lines[line].simulatedHook = 1; - } - else { - goto err; - } - - return 0; -err: - setDectOnhook(line); - return -1; -} - -//------------------------------------------------------------- -// Simulate Dect hook flash (the R-key). -static int doDectHookFlash(int line) { - VRG_ENDPT *epIntern; - - epIntern = GetEndptState(line); - if(!epIntern) return -1; - if(epIntern->cnxCnt == 0) return 0; // No need for hook flash - if(!lines[line].simulatedHook) return 0; - if(!isLineOffhook(line)) return 0; - ENDPT_DBG("%s() BRCM/%d\n", __func__, line); - - // Go "early onhook", "early offhook" and then "flash". - if(simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_ONHOOK) || - simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_EARLY_OFFHOOK) || - simulate_hook_event(&lines[line].epHandle, CAS_CTL_EVENT_FLASH)) { - goto err; - } - - // Ignore future hook state. - if(casCtlIgnoreHookState(epIntern->casCtlHandle, - CAS_IGNOREHOOKSTATE_ON) == CAS_CTL_SUCCESS) { - ENDPT_DBG("Simulated hook flash (R-key) for BRCM/%d\n", line); - } - else { - goto err; - } - - return 0; -err: - setDectOnhook(line); - return -1; -} - -//------------------------------------------------------------- -// If necessary, simulate an phone line event. -int perhapsSimulateHook(int line, EPEVT event) { - if(lines[line].epHandle.endptType != EPTYPE_DECT) return 0; - - switch(event) { - case EPEVT_ONHOOK: - return setDectOnhook(line); - - case EPEVT_OFFHOOK: - return setDectOffhook(line); - - case EPEVT_FLASH: - return doDectHookFlash(line); - - default: - return -1; - } - - return 0; -} - //------------------------------------------------------------- // If appropriate, simulate keypad digit presses. Returns // true if something was sent and false if not. diff --git a/line.c b/line.c index 65effb343ffc1a63223516e2dd278c52eb8a151c..bf2651e45d30d76fa523b1a8e69465a91cfdbf00 100644 --- a/line.c +++ b/line.c @@ -441,15 +441,15 @@ void lineAudioTx(pe_packet_t *p) { } ep_packet.packetp = ap->rtp; - conIdx = find_connection_from_asterisk_id(ap->line, ap->cnx_id); + conIdx = voice_connection_find(ap->line, ap->cnx_id); if (conIdx == -1 || (ap->rtp[0] != 0x80 && ap->rtp[0] != 0x81) || !ap->rtp_size || - lines[connection[conIdx].line].epHandle.lineId == -1) { + lines[connections[conIdx].line].epHandle.lineId == -1) { ENDPT_DBG("bad audio packet\n"); return; } - ret = vrgEndptPacket(&lines[connection[conIdx].line].epHandle, + ret = vrgEndptPacket(&lines[connections[conIdx].line].epHandle, ap->cnx_id, &ep_packet, ap->rtp_size, 0); if (ret != EPSTATUS_SUCCESS) { ENDPT_DBG("Error vrgEndptPacket: %s\n", strerror_endp(ret)); @@ -1363,18 +1363,3 @@ int voice_get_rtp_stats(int line, int connection, int reset, struct rtp_stats_t return 0; } - -//------------------------------------------------------------- -// Map the phone line and connection ID Asterisk use -// to our internal list of connections. -int find_connection_from_asterisk_id(int line, int conId) { - int conIdx; - - for(conIdx = 0; conIdx < epInfo.numEndpoints * MAX_NUM_CNX; conIdx++) { - if(connection[conIdx].line == line && connection[conIdx].conId == conId) { - return conIdx; - } - } - - return -1; -} diff --git a/line.h b/line.h index 498e3516ed62610de67a8ba9c149b9cafc1630d2..7fd220b9f1c2e118b97f6fd0ed9e37587ebf01ca 100644 --- a/line.h +++ b/line.h @@ -3,33 +3,9 @@ #include <stdint.h> -#if defined(PLATFORM_BROADCOM) -#include <endpoint_api.h> -#include <vrgEndptCfg.h> // VRG_ENDPT_CFG_MAX_CNX_PER_ENDPT -#include <casCtl.h> // CAS_CTL_DETECT_EVENT -#include <hapi_hec.h> // HAPI_HEC_VOLUME_MAX -#elif defined(PLATFORM_QUALCOMM) -// TODO: include Qualcomm specific headers -#endif #include <libpicoevent.h> - #include "ubus.h" -//------------------------------------------------------------- -#if defined(PLATFORM_BROADCOM) -#define MAX_NUM_CNX (VRG_ENDPT_CFG_MAX_CNX_PER_ENDPT) // Max number of connections per phone line -#define TX_GAIN_MIN HAPI_HEC_GAIN_MIN -#define TX_GAIN_MAX HAPI_HEC_GAIN_MAX -#define RX_GAIN_MIN HAPI_HEC_VOLUME_MIN -#define RX_GAIN_MAX HAPI_HEC_VOLUME_MAX -#elif defined(PLATFORM_QUALCOMM) -// TODO: Qualcomm specific values -#define MAX_NUM_CNX -#define TX_GAIN_MIN -#define TX_GAIN_MAX -#define RX_GAIN_MIN -#define RX_GAIN_MAX -#endif #define MAX_CALLID_LEN 120 // Max length of caller id string we accept. #define MAX_KEYPAD_DIGITS 100 // Max number of simulated keypad presses we accept. @@ -129,35 +105,6 @@ struct lineReq_t { struct ubusReq_t ubus; }; -struct rtp_stats_t { - uint16_t local_burst_density; - uint16_t remote_burst_density; - uint16_t local_burst_duration; - uint16_t remote_burst_duration; - uint16_t local_gap_density; - uint16_t remote_gap_density; - uint16_t local_gap_duration; - uint16_t remote_gap_duration; - uint16_t local_jb_rate; - uint16_t remote_jb_rate; - uint16_t local_jb_max; - uint16_t remote_jb_max; - uint16_t local_jb_nominal; - uint16_t remote_jb_nominal; - uint16_t local_jb_abs_max; - uint16_t remote_jb_abs_max; - uint32_t discarded; - uint32_t lost; - uint32_t rxpkts; - uint32_t txpkts; - uint16_t jb_avg; - uint32_t jitter; - uint16_t loss_rate; - uint32_t max_jitter; - uint32_t avg_round_trip_delay; -}; - - //------------------------------------------------------------- extern struct ep_info_t epInfo; // Misc info about the endpoint from low level driver extern struct line_t *lines; // Array of phone lines (endpoints) indexed by logical number diff --git a/main.c b/main.c index e300b1e94d99401e44abf190c0efecdb7825b03d..207a34f6869023562e62e45474a0bcbd02cf86ca 100644 --- a/main.c +++ b/main.c @@ -212,7 +212,7 @@ int main(void) { if(config_init(context, package)) goto err; package = NULL; // the package has been unloaded by config_init() if(lineInit()) goto err; - if(voice_connection_init()) goto err; + if(voice_connection_init(epInfo.numEndpoints)) goto err; if(perhaps_erase_unuseds_lines(context)) goto err; if(ubus_enable_receive()) goto err; diff --git a/ubus.c b/ubus.c index d0c493eb33dfcb6bccb7decf34719a7cca7e9e8e..37807424aaad5f6be40072c2bcabea595f265036 100644 --- a/ubus.c +++ b/ubus.c @@ -10,6 +10,7 @@ #include <assert.h> #include <libpicoevent.h> +#include <libvoice.h> #include "ubus.h" #include "line.h" #include "line-dect.h" @@ -386,7 +387,7 @@ static void uci_query_lineX(struct uci_context *context, struct uci_section *sec free(error); } else { intVal = strtol(strVal, NULL, 10); - if(intVal >= TX_GAIN_MIN && intVal <= TX_GAIN_MAX) { + if(intVal >= voice_get_min_tx_gain() && intVal <= voice_get_max_tx_gain()) { lines[phoneLine].uciConf.txgain = intVal; ENDPT_DBG(" %s=%d\n", option, intVal); } else { @@ -402,7 +403,7 @@ static void uci_query_lineX(struct uci_context *context, struct uci_section *sec free(error); } else { intVal = strtol(strVal, NULL, 10); - if(intVal >= RX_GAIN_MIN && intVal <= RX_GAIN_MAX) { + if(intVal >= voice_get_min_rx_gain() && intVal <= voice_get_max_rx_gain()) { lines[phoneLine].uciConf.rxgain = intVal; ENDPT_DBG(" %s=%d\n", option, intVal); } else { @@ -723,9 +724,9 @@ static int ubus_request_rtp_stats(struct ubus_context *uctx, struct ubus_object reset = blobmsg_get_bool(keys[RTP_STATS_RESET]); // Make sure this line has an active connection - for(conIdx = 0; conIdx < (epInfo.numEndpoints * MAX_NUM_CNX) && connection[conIdx].line != line; conIdx++) + for(conIdx = 0; conIdx < max_num_connections && connections[conIdx].line != line; conIdx++) continue; - if (conIdx >= epInfo.numEndpoints * MAX_NUM_CNX) { + if (conIdx >= max_num_connections) { ENDPT_DBG("Error: out of connection memory %d\n", line); return UBUS_STATUS_UNKNOWN_ERROR; } @@ -734,7 +735,7 @@ static int ubus_request_rtp_stats(struct ubus_context *uctx, struct ubus_object if(blob_buf_init(&blob, 0)) return UBUS_STATUS_UNKNOWN_ERROR; - if (voice_get_rtp_stats(line, connection[conIdx].conId, reset, &rtp_stats) != 0) + if (voice_get_rtp_stats(line, connections[conIdx].conId, reset, &rtp_stats) != 0) return UBUS_STATUS_UNKNOWN_ERROR; blobmsg_add_u16(&blob, "lineId", line);