FreeCalypso > hg > themwi-system-sw
comparison 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 |
comparison
equal
deleted
inserted
replaced
126:815e4c59162e | 127:f062c32a5116 |
---|---|
1 /* | |
2 * In this module we implement start/stop control of DTMF generation | |
3 * toward PSTN on GSM-to-PSTN gateway endpoints. | |
4 */ | |
5 | |
6 #include <sys/types.h> | |
7 #include <sys/socket.h> | |
8 #include <sys/time.h> | |
9 #include <netinet/in.h> | |
10 #include <stdio.h> | |
11 #include <stdint.h> | |
12 #include <stdlib.h> | |
13 #include <string.h> | |
14 #include <strings.h> | |
15 #include <syslog.h> | |
16 #include "../include/tmgw_ctrl.h" | |
17 #include "../include/tmgw_const.h" | |
18 #include "struct.h" | |
19 #include "int_defs.h" | |
20 #include "dtmf_defs.h" | |
21 | |
22 extern struct endpoint *find_ep_by_id(); | |
23 | |
24 extern struct timeval cur_event_time; | |
25 extern struct dtmf_desc dtmf_table[]; | |
26 extern int dtmf_timer_running; | |
27 | |
28 struct endpoint *dtmf_list_head; | |
29 | |
30 static void | |
31 add_to_dtmf_list(new_ep) | |
32 struct endpoint *new_ep; | |
33 { | |
34 struct endpoint *ep, **epp; | |
35 | |
36 for (epp = &dtmf_list_head; *epp; epp = &ep->dtmf_next) | |
37 ; | |
38 *epp = new_ep; | |
39 new_ep->dtmf_pp = epp; | |
40 } | |
41 | |
42 void | |
43 dtmf_stop_immediate(ep) | |
44 struct endpoint *ep; | |
45 { | |
46 if (ep->dtmf_frames_sent) | |
47 ep->dtmf_aftermath = 1; | |
48 *ep->dtmf_pp = ep->dtmf_next; | |
49 if (ep->dtmf_next) | |
50 ep->dtmf_next->dtmf_pp = ep->dtmf_pp; | |
51 ep->dtmf_pp = 0; | |
52 ep->dtmf_next = 0; | |
53 if (!dtmf_list_head) | |
54 dtmf_timer_running = 0; | |
55 } | |
56 | |
57 void | |
58 process_dtmf_start(conn, req, resp) | |
59 struct ctrl_conn *conn; | |
60 struct tmgw_ctrl_req *req; | |
61 struct tmgw_ctrl_resp *resp; | |
62 { | |
63 struct endpoint *ep; | |
64 struct dtmf_desc *desc; | |
65 struct timeval tv_diff; | |
66 unsigned delta_frames; | |
67 | |
68 ep = find_ep_by_id(conn, req->ep_id); | |
69 if (!ep) { | |
70 protocol_err: resp->res = TMGW_RESP_ERR_PROT; | |
71 return; | |
72 } | |
73 if (ep->ep_type != TMGW_EP_TYPE_GATEWAY) | |
74 goto protocol_err; | |
75 if (!(ep->fwd_mode & TMGW_FWD_ENABLE_GSM2PSTN)) | |
76 goto protocol_err; | |
77 for (desc = dtmf_table; desc->digit; desc++) | |
78 if (desc->digit == req->fwd_mode) | |
79 break; | |
80 if (!desc->digit) { | |
81 resp->res = TMGW_RESP_ERR_PARAM; | |
82 return; | |
83 } | |
84 if (ep->dtmf_pp) { | |
85 resp->res = TMGW_RESP_ERR_BUSY; | |
86 return; | |
87 } | |
88 if (!ep->g2p_state) { | |
89 resp->res = TMGW_RESP_ERR_NOTRDY; | |
90 return; | |
91 } | |
92 /* figure out starting timestamp */ | |
93 if (!ep->dtmf_aftermath) | |
94 ep->dtmf_last_ts = ep->g2p_last_ts; | |
95 ep->dtmf_m_bit = 0; | |
96 if (timercmp(&cur_event_time, &ep->g2p_local_time, >)) { | |
97 timersub(&cur_event_time, &ep->g2p_local_time, &tv_diff); | |
98 delta_frames = tv_diff.tv_sec * 50 + tv_diff.tv_usec / 20000; | |
99 if (delta_frames) { | |
100 ep->dtmf_last_ts += delta_frames * SAMPLES_PER_FRAME; | |
101 ep->dtmf_m_bit = 1; | |
102 } | |
103 } | |
104 /* initialize other state vars */ | |
105 ep->dtmf_frames_sent = 0; | |
106 ep->dtmf_sample_ptr = desc->samples; | |
107 ep->dtmf_stop_req = 0; | |
108 /* link it and start it */ | |
109 add_to_dtmf_list(ep); | |
110 start_dtmf_timer(); | |
111 /* return success */ | |
112 resp->res = TMGW_RESP_OK; | |
113 } | |
114 | |
115 void | |
116 process_dtmf_stop(conn, req, resp) | |
117 struct ctrl_conn *conn; | |
118 struct tmgw_ctrl_req *req; | |
119 struct tmgw_ctrl_resp *resp; | |
120 { | |
121 struct endpoint *ep; | |
122 | |
123 ep = find_ep_by_id(conn, req->ep_id); | |
124 if (!ep) { | |
125 protocol_err: resp->res = TMGW_RESP_ERR_PROT; | |
126 return; | |
127 } | |
128 if (ep->ep_type != TMGW_EP_TYPE_GATEWAY) | |
129 goto protocol_err; | |
130 /* return OK whether we stop a tone or if there was none running */ | |
131 resp->res = TMGW_RESP_OK; | |
132 if (ep->dtmf_pp) { | |
133 ep->dtmf_stop_req = 1; | |
134 if (ep->dtmf_frames_sent >= DTMF_MIN_FRAMES) | |
135 dtmf_stop_immediate(ep); | |
136 } | |
137 } |