FreeCalypso > hg > themwi-system-sw
diff mgw/dtmf_ctrl.c @ 127:f062c32a5116
mgw: implement DTMF
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 01 Oct 2022 20:31:15 -0800 |
parents | |
children | 529906fddcfa |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mgw/dtmf_ctrl.c Sat Oct 01 20:31:15 2022 -0800 @@ -0,0 +1,137 @@ +/* + * In this module we implement start/stop control of DTMF generation + * toward PSTN on GSM-to-PSTN gateway endpoints. + */ + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <syslog.h> +#include "../include/tmgw_ctrl.h" +#include "../include/tmgw_const.h" +#include "struct.h" +#include "int_defs.h" +#include "dtmf_defs.h" + +extern struct endpoint *find_ep_by_id(); + +extern struct timeval cur_event_time; +extern struct dtmf_desc dtmf_table[]; +extern int dtmf_timer_running; + +struct endpoint *dtmf_list_head; + +static void +add_to_dtmf_list(new_ep) + struct endpoint *new_ep; +{ + struct endpoint *ep, **epp; + + for (epp = &dtmf_list_head; *epp; epp = &ep->dtmf_next) + ; + *epp = new_ep; + new_ep->dtmf_pp = epp; +} + +void +dtmf_stop_immediate(ep) + struct endpoint *ep; +{ + if (ep->dtmf_frames_sent) + ep->dtmf_aftermath = 1; + *ep->dtmf_pp = ep->dtmf_next; + if (ep->dtmf_next) + ep->dtmf_next->dtmf_pp = ep->dtmf_pp; + ep->dtmf_pp = 0; + ep->dtmf_next = 0; + if (!dtmf_list_head) + dtmf_timer_running = 0; +} + +void +process_dtmf_start(conn, req, resp) + struct ctrl_conn *conn; + struct tmgw_ctrl_req *req; + struct tmgw_ctrl_resp *resp; +{ + struct endpoint *ep; + struct dtmf_desc *desc; + struct timeval tv_diff; + unsigned delta_frames; + + ep = find_ep_by_id(conn, req->ep_id); + if (!ep) { +protocol_err: resp->res = TMGW_RESP_ERR_PROT; + return; + } + if (ep->ep_type != TMGW_EP_TYPE_GATEWAY) + goto protocol_err; + if (!(ep->fwd_mode & TMGW_FWD_ENABLE_GSM2PSTN)) + goto protocol_err; + for (desc = dtmf_table; desc->digit; desc++) + if (desc->digit == req->fwd_mode) + break; + if (!desc->digit) { + resp->res = TMGW_RESP_ERR_PARAM; + return; + } + if (ep->dtmf_pp) { + resp->res = TMGW_RESP_ERR_BUSY; + return; + } + if (!ep->g2p_state) { + resp->res = TMGW_RESP_ERR_NOTRDY; + return; + } + /* figure out starting timestamp */ + if (!ep->dtmf_aftermath) + ep->dtmf_last_ts = ep->g2p_last_ts; + ep->dtmf_m_bit = 0; + if (timercmp(&cur_event_time, &ep->g2p_local_time, >)) { + timersub(&cur_event_time, &ep->g2p_local_time, &tv_diff); + delta_frames = tv_diff.tv_sec * 50 + tv_diff.tv_usec / 20000; + if (delta_frames) { + ep->dtmf_last_ts += delta_frames * SAMPLES_PER_FRAME; + ep->dtmf_m_bit = 1; + } + } + /* initialize other state vars */ + ep->dtmf_frames_sent = 0; + ep->dtmf_sample_ptr = desc->samples; + ep->dtmf_stop_req = 0; + /* link it and start it */ + add_to_dtmf_list(ep); + start_dtmf_timer(); + /* return success */ + resp->res = TMGW_RESP_OK; +} + +void +process_dtmf_stop(conn, req, resp) + struct ctrl_conn *conn; + struct tmgw_ctrl_req *req; + struct tmgw_ctrl_resp *resp; +{ + struct endpoint *ep; + + ep = find_ep_by_id(conn, req->ep_id); + if (!ep) { +protocol_err: resp->res = TMGW_RESP_ERR_PROT; + return; + } + if (ep->ep_type != TMGW_EP_TYPE_GATEWAY) + goto protocol_err; + /* return OK whether we stop a tone or if there was none running */ + resp->res = TMGW_RESP_OK; + if (ep->dtmf_pp) { + ep->dtmf_stop_req = 1; + if (ep->dtmf_frames_sent >= DTMF_MIN_FRAMES) + dtmf_stop_immediate(ep); + } +}