1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * dummy_modems_tests.c - Tests for data_modems connected together by sockets.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2011 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*! \file */
27
28 /*! \page dummy_modems_tests_page Dummy data modems tests
29 \section dummy_modems_tests_page_sec_1 What does it do?
30 */
31
32 #if defined(HAVE_CONFIG_H)
33 #include "config.h"
34 #endif
35
36 #if defined(HAVE_FL_FL_H) && defined(HAVE_FL_FL_CARTESIAN_H) && defined(HAVE_FL_FL_AUDIO_METER_H)
37 #define ENABLE_GUI
38 #endif
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <fcntl.h>
43 #include <unistd.h>
44 #include <string.h>
45 #include <assert.h>
46 #include <termios.h>
47 #include <sndfile.h>
48
49 //#define SPANDSP_EXPOSE_INTERNAL_STRUCTURES
50
51 #include "spandsp.h"
52 #include "spandsp-sim.h"
53
54 #include "pseudo_terminals.h"
55 #include "socket_harness.h"
56
57 #if defined(ENABLE_GUI)
58 #include "media_monitor.h"
59 #endif
60
61 #define OUTPUT_WAVE_FILE_NAME "dummy_modems.wav"
62
63 #define SAMPLES_PER_CHUNK 160
64
65 SNDFILE *wave_handle = NULL;
66 int16_t wave_buffer[4096];
67
68 data_modems_state_t *data_modem_state;
69
70 int answered = false;
71 int done = false;
72
modem_call_control(data_modems_state_t * s,void * user_data,int op,const char * num)73 static int modem_call_control(data_modems_state_t *s, void *user_data, int op, const char *num)
74 {
75 printf("\nModem control - %s", at_modem_control_to_str(op));
76 switch (op)
77 {
78 case AT_MODEM_CONTROL_CALL:
79 printf(" %s", num);
80 data_modems_call_event(s, AT_CALL_EVENT_CONNECTED);
81 break;
82 case AT_MODEM_CONTROL_ANSWER:
83 answered = true;
84 data_modems_call_event(s, AT_CALL_EVENT_ANSWERED);
85 break;
86 case AT_MODEM_CONTROL_HANGUP:
87 done = true;
88 break;
89 case AT_MODEM_CONTROL_OFFHOOK:
90 break;
91 case AT_MODEM_CONTROL_DTR:
92 printf(" %d", (int) (intptr_t) num);
93 break;
94 case AT_MODEM_CONTROL_RTS:
95 printf(" %d", (int) (intptr_t) num);
96 break;
97 case AT_MODEM_CONTROL_CTS:
98 printf(" %d", (int) (intptr_t) num);
99 break;
100 case AT_MODEM_CONTROL_CAR:
101 printf(" %d", (int) (intptr_t) num);
102 break;
103 case AT_MODEM_CONTROL_RNG:
104 printf(" %d", (int) (intptr_t) num);
105 break;
106 case AT_MODEM_CONTROL_DSR:
107 printf(" %d", (int) (intptr_t) num);
108 break;
109 case AT_MODEM_CONTROL_SETID:
110 printf(" %d", (int) (intptr_t) num);
111 break;
112 case AT_MODEM_CONTROL_RESTART:
113 printf(" %d", (int) (intptr_t) num);
114 break;
115 case AT_MODEM_CONTROL_DTE_TIMEOUT:
116 printf(" %d", (int) (intptr_t) num);
117 break;
118 }
119 /*endswitch*/
120 printf("\n");
121 return 0;
122 }
123 /*- End of function --------------------------------------------------------*/
124
get_msg(void * user_data,uint8_t msg[],int len)125 static int get_msg(void *user_data, uint8_t msg[], int len)
126 {
127 return 0;
128 }
129 /*- End of function --------------------------------------------------------*/
130
put_msg(void * user_data,const uint8_t msg[],int len)131 static void put_msg(void *user_data, const uint8_t msg[], int len)
132 {
133 if (len < 0)
134 printf("Status %s\n", signal_status_to_str(len));
135 else
136 printf("Put %d '%s'\n", len, msg);
137 /*endif*/
138 }
139 /*- End of function --------------------------------------------------------*/
140
terminal_callback(void * user_data,const uint8_t msg[],int len)141 static void terminal_callback(void *user_data, const uint8_t msg[], int len)
142 {
143 data_modems_state_t *s;
144 int i;
145
146 s = (data_modems_state_t *) user_data;
147 printf("terminal callback %d\n", len);
148 for (i = 0; i < len; i++)
149 {
150 printf("0x%x ", msg[i]);
151 }
152 printf("\n");
153 at_interpreter(&s->at_state, (const char *) msg, len);
154 }
155 /*- End of function --------------------------------------------------------*/
156
termios_callback(void * user_data,struct termios * termios)157 static int termios_callback(void *user_data, struct termios *termios)
158 {
159 data_modems_state_t *s;
160
161 s = (data_modems_state_t *) user_data;
162 printf("termios callback\n");
163 return 0;
164 }
165 /*- End of function --------------------------------------------------------*/
166
hangup_callback(void * user_data,int status)167 static void hangup_callback(void *user_data, int status)
168 {
169 }
170 /*- End of function --------------------------------------------------------*/
171
terminal_free_space_callback(void * user_data)172 static int terminal_free_space_callback(void *user_data)
173 {
174 return 42;
175 }
176 /*- End of function --------------------------------------------------------*/
177
rx_callback(void * user_data,const int16_t amp[],int samples)178 static int rx_callback(void *user_data, const int16_t amp[], int samples)
179 {
180 int i;
181 int out_samples;
182
183 out_samples = data_modems_rx((data_modems_state_t *) user_data, amp, samples);
184 if (wave_handle)
185 {
186 for (i = 0; i < samples; i++)
187 wave_buffer[2*i] = amp[i];
188 /*endfor*/
189 }
190 /*endif*/
191 return out_samples;
192 }
193 /*- End of function --------------------------------------------------------*/
194
rx_fillin_callback(void * user_data,int samples)195 static int rx_fillin_callback(void *user_data, int samples)
196 {
197 return data_modems_rx_fillin((data_modems_state_t *) user_data, samples);
198 }
199 /*- End of function --------------------------------------------------------*/
200
tx_callback(void * user_data,int16_t amp[],int samples)201 static int tx_callback(void *user_data, int16_t amp[], int samples)
202 {
203 int i;
204 int out_samples;
205
206 out_samples = data_modems_tx((data_modems_state_t *) user_data, amp, samples);
207 if (wave_handle)
208 {
209 if (out_samples < samples)
210 memset(&[out_samples], 0, (samples - out_samples)*2);
211 /*endif*/
212 for (i = 0; i < samples; i++)
213 wave_buffer[2*i + 1] = amp[i];
214 /*endfor*/
215 sf_writef_short(wave_handle, wave_buffer, samples);
216 }
217 /*endif*/
218 return samples;
219 }
220 /*- End of function --------------------------------------------------------*/
221
modem_tests(int use_gui,int log_audio,bool calling_party)222 static int modem_tests(int use_gui, int log_audio, bool calling_party)
223 {
224 logging_state_t *logging;
225 socket_harness_state_t *s;
226
227 /* Now set up and run the modems */
228 if ((data_modem_state = data_modems_init(NULL,
229 calling_party,
230 terminal_write,
231 NULL,
232 modem_call_control,
233 NULL,
234 put_msg,
235 get_msg,
236 NULL)) == NULL)
237 {
238 fprintf(stderr, " Cannot start the data modem\n");
239 exit(2);
240 }
241 /*endif*/
242 logging = data_modems_get_logging_state(data_modem_state);
243 span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_DATE);
244 span_log_set_tag(logging, "Modem");
245
246 if ((s = socket_harness_init(NULL,
247 "/tmp/modemsocket",
248 "modemA",
249 calling_party,
250 terminal_callback,
251 termios_callback,
252 hangup_callback,
253 terminal_free_space_callback,
254 rx_callback,
255 rx_fillin_callback,
256 tx_callback,
257 data_modem_state)) == NULL)
258 {
259 fprintf(stderr, " Cannot start the socket harness\n");
260 exit(2);
261 }
262 /*endif*/
263
264 data_modems_set_at_tx_handler(data_modem_state, terminal_write, s);
265
266 wave_handle = NULL;
267 if (log_audio)
268 {
269 if ((wave_handle = sf_open_telephony_write(OUTPUT_WAVE_FILE_NAME, 2)) == NULL)
270 {
271 fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
272 exit(2);
273 }
274 /*endif*/
275 }
276 /*endif*/
277
278 socket_harness_run(s, calling_party);
279
280 if (log_audio)
281 {
282 if (sf_close_telephony(wave_handle))
283 {
284 fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
285 exit(2);
286 }
287 /*endif*/
288 }
289 /*endif*/
290
291 return 0;
292 }
293 /*- End of function --------------------------------------------------------*/
294
main(int argc,char * argv[])295 int main(int argc, char *argv[])
296 {
297 int log_audio;
298 int use_gui;
299 int opt;
300 bool calling_party;
301
302 log_audio = false;
303 calling_party = false;
304 use_gui = false;
305 while ((opt = getopt(argc, argv, "acgl")) != -1)
306 {
307 switch (opt)
308 {
309 case 'a':
310 calling_party = false;
311 break;
312 case 'c':
313 calling_party = true;
314 break;
315 case 'g':
316 #if defined(ENABLE_GUI)
317 use_gui = true;
318 #else
319 fprintf(stderr, "Graphical monitoring not available\n");
320 exit(2);
321 #endif
322 break;
323 case 'l':
324 log_audio = true;
325 break;
326 default:
327 //usage();
328 exit(2);
329 break;
330 }
331 /*endswitch*/
332 }
333 /*endwhile*/
334
335 if (modem_tests(use_gui, log_audio, calling_party))
336 exit(2);
337 /*endif*/
338 printf("Tests passed\n");
339 return 0;
340 }
341 /*- End of function --------------------------------------------------------*/
342 /*- End of file ------------------------------------------------------------*/
343