|
|
|
@ -311,7 +311,7 @@ static void pstn_new_state(pstn_t *pstn, enum pstn_state state)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* initialization and configuration of interface instance */
|
|
|
|
|
int pstn_init(pstn_t *pstn, const char *name, const char *socketname, const char **subscribers, int subscriber_num, uint8_t serving_location, int tx_delay, int clip, int cid_bell, int cid_dtmf, int clip_date, int enblock, int recall, int *ringing_types_incoming, int ringing_type_hold, enum tones_type tones_type, char law)
|
|
|
|
|
int pstn_init(pstn_t *pstn, const char *name, const char *socketname, const char **subscribers, int subscriber_num, uint8_t serving_location, int tx_delay, enum pstn_cid_method clip, int cid_bell, int cid_dtmf, int clip_date, int enblock, int recall, int *ringing_types_incoming, int ringing_type_hold, enum tones_type tones_type, char law)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
int rc;
|
|
|
|
@ -436,6 +436,8 @@ static void timer_off(pstn_t *pstn)
|
|
|
|
|
|
|
|
|
|
static void callerid_on(pstn_t *pstn, int cw, const char *callerid, uint8_t caller_type)
|
|
|
|
|
{
|
|
|
|
|
int dtas = 0;
|
|
|
|
|
|
|
|
|
|
/* DTMF on CW not supported */
|
|
|
|
|
if (cw && pstn->cid_dtmf) {
|
|
|
|
|
PDEBUG(DTEL, DEBUG_INFO, "DTMF CID is not allowed for waiting call, don't sending CID.\n");
|
|
|
|
@ -444,21 +446,30 @@ static void callerid_on(pstn_t *pstn, int cw, const char *callerid, uint8_t call
|
|
|
|
|
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Schedule caller ID transmission. (cw=%d, callerid=%s)\n", cw, callerid);
|
|
|
|
|
|
|
|
|
|
/* add DT_AS on waitng call */
|
|
|
|
|
callerid_set(&pstn->callerid, cw, (cw) ? 1 : 0, callerid, caller_type, pstn->clip_date);
|
|
|
|
|
|
|
|
|
|
if (cw) {
|
|
|
|
|
dtas = 1;
|
|
|
|
|
pstn->callerid_state = PSTN_CID_STATE_WAIT1;
|
|
|
|
|
/* add delay when cw */
|
|
|
|
|
pstn->callerid_wait1 = 8000;
|
|
|
|
|
pstn->callerid_wait2 = 0;
|
|
|
|
|
} else {
|
|
|
|
|
pstn->callerid_state = PSTN_CID_STATE_WAIT1;
|
|
|
|
|
/* add delay when ringing */
|
|
|
|
|
pstn->callerid_wait1 = 8000;
|
|
|
|
|
pstn->callerid_wait2 = 16000;
|
|
|
|
|
if (pstn->clip == CID_METHOD_DTAS || pstn->clip == CID_METHOD_DTAS_LR) {
|
|
|
|
|
dtas = 1;
|
|
|
|
|
pstn->callerid_state = PSTN_CID_STATE_WAIT1;
|
|
|
|
|
/* wait for channel and do not wait to ring afterwards */
|
|
|
|
|
pstn->callerid_wait1 = 4000;
|
|
|
|
|
pstn->callerid_wait2 = 0;
|
|
|
|
|
} else {
|
|
|
|
|
pstn->callerid_state = PSTN_CID_STATE_WAIT1;
|
|
|
|
|
/* wait to stop ringing and wait to continue ringing */
|
|
|
|
|
pstn->callerid_wait1 = 8000;
|
|
|
|
|
pstn->callerid_wait2 = 16000;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* add DT_AS on waitng call */
|
|
|
|
|
callerid_set(&pstn->callerid, cw, dtas, callerid, caller_type, pstn->clip_date);
|
|
|
|
|
|
|
|
|
|
/* turn DTMF on, to detect TE-ACK */
|
|
|
|
|
if (cw) {
|
|
|
|
|
/* start DTMF */
|
|
|
|
@ -630,7 +641,7 @@ static void bchannel_rx_tx(pstn_t *pstn, uint8_t *data, int len)
|
|
|
|
|
/* wait before sending callerid */
|
|
|
|
|
pstn->callerid_wait1 -= len;
|
|
|
|
|
if (pstn->callerid_wait1 <= 0) {
|
|
|
|
|
if (pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ALERTING_SUB) {
|
|
|
|
|
if (pstn->clip == CID_METHOD_STOP && pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ALERTING_SUB) {
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Stop ringing.\n");
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_STEADY_SIGNAL, 1, 0x80 | 0x0e};
|
|
|
|
|
v5_sig_req(pstn, ie, sizeof(ie));
|
|
|
|
@ -671,7 +682,13 @@ static void bchannel_rx_tx(pstn_t *pstn, uint8_t *data, int len)
|
|
|
|
|
if (pstn->callerid_wait2 <= 0) {
|
|
|
|
|
pstn->callerid_state = PSTN_CID_STATE_OFF;
|
|
|
|
|
if (pstn->call[PSTN_CALL_ACTIVE]->state == CALL_STATE_ALERTING_SUB) {
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Continue with ringing.\n");
|
|
|
|
|
if (pstn->clip == CID_METHOD_DTAS_LR) {
|
|
|
|
|
pstn->reversed = 0;
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Set normal polarity.\n");
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_STEADY_SIGNAL, 1, 0x80 | PSTN_V5_STEADY_SIGNAL_NORMAL};
|
|
|
|
|
v5_sig_req(pstn, ie, sizeof(ie));
|
|
|
|
|
}
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Start ringing.\n");
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_CADENCED_RINGING, 1, 0x80 | pstn->ringing_types_incoming[pstn->call[PSTN_CALL_ACTIVE]->subscriber_index] };
|
|
|
|
|
v5_sig_req(pstn, ie, sizeof(ie));
|
|
|
|
|
}
|
|
|
|
@ -892,8 +909,36 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg)
|
|
|
|
|
osmo_cc_ll_msg(&pstn->cc_ep, pstn_call->cc_callref, new_msg);
|
|
|
|
|
if (pstn->state == PSTN_STATE_NULL) {
|
|
|
|
|
/* send message to V5 */
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_CADENCED_RINGING, 1, 0x80 | pstn->ringing_types_incoming[pstn_call->subscriber_index] };
|
|
|
|
|
v5_est_req(pstn, ie, sizeof(ie));
|
|
|
|
|
switch (pstn->clip) {
|
|
|
|
|
case CID_METHOD_DTAS:
|
|
|
|
|
{
|
|
|
|
|
v5_est_req(pstn, NULL, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CID_METHOD_DTAS_LR:
|
|
|
|
|
{
|
|
|
|
|
pstn->reversed = 1;
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Reversed polarity.\n");
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_STEADY_SIGNAL, 1, 0x80 | PSTN_V5_STEADY_SIGNAL_REVERSED};
|
|
|
|
|
v5_est_req(pstn, ie, sizeof(ie));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CID_METHOD_PULSE:
|
|
|
|
|
{
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Start one ring pulse.\n");
|
|
|
|
|
uint8_t ie[5] = { PSTN_V5_IE_PULSED_SIGNAL, 3, 0x80 | PSTN_V5_PULSED_SIGNAL_INIT_RING, 0x60, 0x80 | 0x40 | 0x01};
|
|
|
|
|
v5_est_req(pstn, ie, sizeof(ie));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case CID_METHOD_STOP:
|
|
|
|
|
case CID_METHOD_NONE:
|
|
|
|
|
{
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Start ringing.\n");
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_CADENCED_RINGING, 1, 0x80 | pstn->ringing_types_incoming[pstn_call->subscriber_index] };
|
|
|
|
|
v5_est_req(pstn, ie, sizeof(ie));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pstn->clip) {
|
|
|
|
|
/* send callerid */
|
|
|
|
|
callerid_on(pstn, 0, callerid, caller_type);
|
|
|
|
@ -1543,7 +1588,7 @@ static void v5_receive(pstn_t *pstn, uint8_t *data, int len)
|
|
|
|
|
case PSTN_EVENT_EST_IND:
|
|
|
|
|
/* in case of collision, just treat as ACK and proceed outgoing call */
|
|
|
|
|
if (pstn->state == PSTN_STATE_EST_LE) {
|
|
|
|
|
PDEBUG(DTEL, DEBUG_INFO, " -> Handle establish collision, send ACK.\n");
|
|
|
|
|
PDEBUG(DTEL, DEBUG_NOTICE, "Handle establish collision, send ACK. A possible ACK from AN will be ignored.\n");
|
|
|
|
|
/* send ack message to V5 */
|
|
|
|
|
v5_est_ack_req(pstn);
|
|
|
|
|
/* treat as establish acknowledgement from PSTN interface */
|
|
|
|
@ -1668,7 +1713,13 @@ static void v5_disc_req_and_cleanup(pstn_t *pstn)
|
|
|
|
|
/* change state */
|
|
|
|
|
pstn_new_state(pstn, PSTN_STATE_NULL);
|
|
|
|
|
|
|
|
|
|
v5_send(pstn, PSTN_EVENT_DISC_REQ, NULL, 0);
|
|
|
|
|
if (pstn->reversed) {
|
|
|
|
|
pstn->reversed = 0;
|
|
|
|
|
PDEBUG(DTEL, DEBUG_DEBUG, "Normal polarity.\n");
|
|
|
|
|
uint8_t ie[3] = { PSTN_V5_IE_STEADY_SIGNAL, 1, 0x80 | PSTN_V5_STEADY_SIGNAL_NORMAL};
|
|
|
|
|
v5_send(pstn, PSTN_EVENT_DISC_REQ, ie, sizeof(ie));
|
|
|
|
|
} else
|
|
|
|
|
v5_send(pstn, PSTN_EVENT_DISC_REQ, NULL, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|