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(&amp[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