Added more caller ID alerting signals
If supported by the AN, different alerting signals can be configured. See command line help for details.
This commit is contained in:
parent
4027c98c53
commit
972c43d74e
|
@ -45,7 +45,8 @@
|
|||
#define DBV_TO_DBM -0.086 /* impedance 1020 Ohms */
|
||||
|
||||
#define DTAS_TX_DBV -16.0 /* relative to 1 Volt RMS */
|
||||
#define DTAS2_DURATION 0.080 /* 80 ms (DT-AS Off-Hook) */
|
||||
#define DTAS_DURATION 0.100 /* 100 ms (DT-AS On-Hook) */
|
||||
#define DTAS_CW_DURATION 0.080 /* 80 ms (DT-AS Off-Hook) */
|
||||
#define FSK_TX_DBV -15.5 /* relative to 1 Volt RMS */
|
||||
#define FSK_BAUD_RATE 1200
|
||||
#define FSK_BIT_ADJUST 0.5 /* must be 0.5 to completely sync each bit */
|
||||
|
@ -61,6 +62,7 @@
|
|||
|
||||
#define WAIT_RING_FSK 0.700 /* wait 500ms-2000ms after ring before sending FSK */
|
||||
#define WAIT_CW_DTAS 0.050 /* wait 50ms after CW before sending DT_AS */
|
||||
#define WAIT_DTAS_FSK 0.200 /* wait 200 for FSK after DT_AS */
|
||||
#define WAIT_DTAS_TEACK 0.210 /* wait 160ms + 50ms(latency) for TE-ACK after DT_AS */
|
||||
#define WAIT_TEACK_FSK 0.055 /* wait 55ms after recognition of TE-ACK before sending FSK */
|
||||
#define WAIT_RING_DTMF 0.500 /* wait after 1st ring before sending DTMF */
|
||||
|
@ -179,6 +181,8 @@ int callerid_set(callerid_t *cid, int cw, int dt_as, const char *callerid, uint8
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
cid->cw = cw;
|
||||
|
||||
if (!cid->use_dtmf) {
|
||||
uint8_t *p;
|
||||
uint8_t par = 0;
|
||||
|
@ -319,7 +323,7 @@ again:
|
|||
cid->dtas_phaseshift65536[1] = TONE_DTAS_2 / (double)cid->samplerate * 65536.0;
|
||||
cid->dtas_phase65536[0] = 0.0;
|
||||
cid->dtas_phase65536[1] = 0.0;
|
||||
cid->dt_as_count = (int)(DTAS2_DURATION * (double)cid->samplerate);
|
||||
cid->dt_as_count = (int)(((cid->cw) ? DTAS_CW_DURATION : DTAS_DURATION) * (double)cid->samplerate);
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "Now start DT_AS transmission.\n");
|
||||
break;
|
||||
case CID_STATE_WAIT_DTMF:
|
||||
|
@ -361,9 +365,17 @@ again:
|
|||
length -= i;
|
||||
count += i;
|
||||
if (cid->dt_as_count == 0) {
|
||||
/* wait for TE ACK */
|
||||
cid->state = CID_STATE_WAIT_TE_ACK;
|
||||
cid->wait = (int)(WAIT_DTAS_TEACK * (double)cid->samplerate);
|
||||
if (cid->cw) {
|
||||
/* wait for TE ACK */
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "DT-AS transmission done, waiting for TE-ACK.\n");
|
||||
cid->state = CID_STATE_WAIT_TE_ACK;
|
||||
cid->wait = (int)(WAIT_DTAS_TEACK * (double)cid->samplerate);
|
||||
} else {
|
||||
/* wait for FSK */
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "DT-AS transmission done, waiting for FSK.\n");
|
||||
cid->state = CID_STATE_WAIT_FSK;
|
||||
cid->wait = (int)(WAIT_DTAS_FSK * (double)cid->samplerate);
|
||||
}
|
||||
goto again;
|
||||
}
|
||||
break;
|
||||
|
@ -388,7 +400,10 @@ again:
|
|||
samples += ret;
|
||||
length -= ret;
|
||||
if (length) {
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "FSK transmission done, waiting to re-establish audio.\n");
|
||||
if (cid->cw)
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "FSK transmission done, waiting to re-establish audio.\n");
|
||||
else
|
||||
PDEBUG(DDSP, DEBUG_DEBUG, "FSK transmission done, waiting to send ringing.\n");
|
||||
cid->wait = (int)(WAIT_FSK_END * (double)cid->samplerate);
|
||||
cid->state = CID_STATE_WAIT_END;
|
||||
break;
|
||||
|
|
|
@ -17,6 +17,7 @@ enum cid_state {
|
|||
typedef struct callerid {
|
||||
/* settings */
|
||||
int samplerate; /* sample rate to render output */
|
||||
char cw; /* use off-hook caller ID */
|
||||
char use_dtmf; /* if set, use DTMF instead of FSK, start digit given */
|
||||
|
||||
/* play states */
|
||||
|
|
|
@ -42,7 +42,7 @@ static const char *name = "pstn";
|
|||
static const char *subscribers[SUBSCRIBER_MAX] = { "" };
|
||||
static int subscriber_num = 0;
|
||||
static int tx_delay = 0;
|
||||
static int clip = 0;
|
||||
static enum pstn_cid_method clip = CID_METHOD_NONE;
|
||||
static int cid_bell = 0;
|
||||
static int cid_dtmf = 0;
|
||||
static int clip_date = 0;
|
||||
|
@ -50,7 +50,7 @@ static int enblock = 4;
|
|||
static int recall = 0;
|
||||
static int ringing_types_incoming[SUBSCRIBER_MAX] = { 0 };
|
||||
static int ringing_type_incoming_num = 0;
|
||||
static int ringing_type_hold = 1;
|
||||
static int ringing_type_hold = 0;
|
||||
static enum tones_type tones_type = TONES_TYPE_GERMAN;
|
||||
static int rt_prio = 1;
|
||||
#define MAX_CC_ARGS 1024
|
||||
|
@ -85,8 +85,12 @@ static void print_help()
|
|||
printf(" Give a delay in milliseconds. This is required for modem/fax. Audio\n");
|
||||
printf(" toward ISDN interface is buffered with the given delay.\n");
|
||||
printf(" This feature alters dejittering strategy.\n");
|
||||
printf(" --clip [--clip-date]\n");
|
||||
printf(" --clip pulse | stop | dtas | dtas-lr [--clip-date]\n");
|
||||
printf(" Enable caller ID, optionally with date info. (disabled by default)\n");
|
||||
printf(" Use 'pulse' to send first ringing via pulse signal and CLIP afterwards.\n");
|
||||
printf(" Use 'stop' to stop after first ring, send CLIP and continue ringing.\n");
|
||||
printf(" Use 'dtas' to send CLIP with DT-AS before first ring.\n");
|
||||
printf(" Use 'dtas-lr' to send CLIP as above, but with reversed polarity.\n");
|
||||
printf(" --clip-date\n");
|
||||
printf(" Send date+time with caller ID.\n");
|
||||
printf(" --cid-bell\n");
|
||||
|
@ -157,7 +161,7 @@ static void add_options(void)
|
|||
option_add('n', "name", 1);
|
||||
option_add('I', "subscriber", 1);
|
||||
option_add(OPT_TX_DELAY, "tx-delay", 1);
|
||||
option_add(OPT_TX_CLIP, "clip", 0);
|
||||
option_add(OPT_TX_CLIP, "clip", 1);
|
||||
option_add(OPT_TX_CLIP_DATE, "clip-date", 0);
|
||||
option_add(OPT_TX_CID_BELL, "cid-bell", 0);
|
||||
option_add(OPT_TX_CID_DTMF, "cid-dtmf", 1);
|
||||
|
@ -209,7 +213,18 @@ static int handle_options(int short_option, int argi, char **argv)
|
|||
tx_delay = atoi(argv[argi]);
|
||||
break;
|
||||
case OPT_TX_CLIP:
|
||||
clip = 1;
|
||||
if (!strcasecmp(argv[argi], "pulse"))
|
||||
clip = CID_METHOD_PULSE;
|
||||
else if (!strcasecmp(argv[argi], "stop"))
|
||||
clip = CID_METHOD_STOP;
|
||||
else if (!strcasecmp(argv[argi], "dtas"))
|
||||
clip = CID_METHOD_DTAS;
|
||||
else if (!strcasecmp(argv[argi], "dtas-lr"))
|
||||
clip = CID_METHOD_DTAS_LR;
|
||||
else {
|
||||
fprintf(stderr, "Invalid clip method!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case OPT_TX_CLIP_DATE:
|
||||
clip_date = 1;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -39,9 +39,12 @@ enum pstn_v5_ie {
|
|||
};
|
||||
|
||||
enum pstn_v5_signal {
|
||||
PSTN_V5_STEADY_SIGNAL_NORMAL = 0x00,
|
||||
PSTN_V5_STEADY_SIGNAL_REVERSED = 0x01,
|
||||
PSTN_V5_STEADY_SIGNAL_OFF_HOOK = 0x04,
|
||||
PSTN_V5_STEADY_SIGNAL_ON_HOOK = 0x05,
|
||||
PSTN_V5_STEADY_SIGNAL_STOP_RING = 0x0e,
|
||||
PSTN_V5_PULSED_SIGNAL_INIT_RING = 0x79,
|
||||
PSTN_V5_PULSED_SIGNAL_ON_HOOK = 0x7c,
|
||||
};
|
||||
|
||||
|
@ -66,6 +69,14 @@ enum pstn_call_state {
|
|||
CALL_STATE_DISCONNECT_NET,
|
||||
};
|
||||
|
||||
enum pstn_cid_method {
|
||||
CID_METHOD_NONE = 0,
|
||||
CID_METHOD_PULSE,
|
||||
CID_METHOD_STOP,
|
||||
CID_METHOD_DTAS,
|
||||
CID_METHOD_DTAS_LR,
|
||||
};
|
||||
|
||||
enum pstn_cid_state {
|
||||
PSTN_CID_STATE_OFF = 0,
|
||||
PSTN_CID_STATE_WAIT1,
|
||||
|
@ -102,7 +113,7 @@ typedef struct pstn {
|
|||
int subscriber_num; /* number of subscribers and tinging types (incoming) */
|
||||
int serving_location; /* who we serve when sending causes towards interface */
|
||||
int tx_delay; /* delay to be used for fax/modem jitter buffering */
|
||||
int clip; /* send caller ID */
|
||||
enum pstn_cid_method clip; /* send caller ID */
|
||||
int clip_date; /* send date with caller ID */
|
||||
int cid_bell; /* use V.23 or Bell 202 FSK tones */
|
||||
int cid_dtmf; /* use DTMF instead of FSK caller ID */
|
||||
|
@ -117,6 +128,7 @@ typedef struct pstn {
|
|||
struct timer timer; /* timer for enblock dialing */
|
||||
enum timer_ident timer_ident; /* why is the timer running */
|
||||
char dialing[33]; /* register for en-block dialing */
|
||||
int reversed; /* if polarity is reversed */
|
||||
int dtmf_on; /* we are listening to DTMF */
|
||||
int pulse_on; /* we take pulses */
|
||||
enum pstn_cid_state callerid_state; /* transmitting callerid */
|
||||
|
@ -142,7 +154,7 @@ typedef struct pstn {
|
|||
|
||||
void pstn_destroy(pstn_t *pstn_ep);
|
||||
pstn_t *pstn_create(void);
|
||||
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);
|
||||
void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg);
|
||||
void rtp_work(pstn_t *pstn_ep);
|
||||
void pstn_work(pstn_t *pstn_ep);
|
||||
|
|
Loading…
Reference in New Issue