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);