1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005/2012, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * This module (mod_gsmopen) has been contributed by:
25  *
26  * Giovanni Maruzzelli (gmaruzz@gmail.com)
27  *
28  *
29  * Further Contributors:
30  *
31  *
32  *
33  * mod_gsmopen.c -- GSM compatible Endpoint Module
34  *
35  */
36 
37 #include "gsmopen.h"
38 
39 #if 0
40 #ifdef WIN32
41 /***************/
42 // from http://www.openasthra.com/c-tidbits/gettimeofday-function-for-windows/
43 
44 #include <time.h>
45 
46 #if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
47 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000Ui64
48 #else /*  */
49 #define DELTA_EPOCH_IN_MICROSECS  11644473600000000ULL
50 #endif /*  */
51 struct sk_timezone {
52 	int tz_minuteswest;			/* minutes W of Greenwich */
53 	int tz_dsttime;				/* type of dst correction */
54 };
55 int gettimeofday(struct timeval *tv, struct sk_timezone *tz)
56 {
57 	FILETIME ft;
58 	unsigned __int64 tmpres = 0;
59 	static int tzflag;
60 	if (NULL != tv) {
61 		GetSystemTimeAsFileTime(&ft);
62 		tmpres |= ft.dwHighDateTime;
63 		tmpres <<= 32;
64 		tmpres |= ft.dwLowDateTime;
65 
66 		/*converting file time to unix epoch */
67 		tmpres /= 10;			/*convert into microseconds */
68 		tmpres -= DELTA_EPOCH_IN_MICROSECS;
69 		tv->tv_sec = (long) (tmpres / 1000000UL);
70 		tv->tv_usec = (long) (tmpres % 1000000UL);
71 	}
72 	if (NULL != tz) {
73 		if (!tzflag) {
74 			_tzset();
75 			tzflag++;
76 		}
77 		tz->tz_minuteswest = _timezone / 60;
78 		tz->tz_dsttime = _daylight;
79 	}
80 	return 0;
81 }
82 
83 /***************/
84 #endif /* WIN32 */
85 #endif //0
86 SWITCH_BEGIN_EXTERN_C
87 SWITCH_MODULE_LOAD_FUNCTION(mod_gsmopen_load);
88 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_gsmopen_shutdown);
89 SWITCH_MODULE_DEFINITION(mod_gsmopen, mod_gsmopen_load, mod_gsmopen_shutdown, NULL);
90 SWITCH_END_EXTERN_C
91 #define GSMOPEN_CHAT_PROTO "sms"
92 #if 1
93 SWITCH_STANDARD_API(gsm_function);
94 /* BEGIN: Changes here */
95 #define GSM_SYNTAX "list [full] || console || AT_command || remove < interface_name | interface_id > || reload"
96 /* END: Changes heres */
97 SWITCH_STANDARD_API(gsmopen_function);
98 #define GSMOPEN_SYNTAX "interface_name AT_command"
99 #endif //0
100 
101 SWITCH_STANDARD_API(gsmopen_boost_audio_function);
102 #define GSMOPEN_BOOST_AUDIO_SYNTAX "interface_name [<play|capt> <in decibels: -40 ... 0 ... +40>]"
103 SWITCH_STANDARD_API(sendsms_function);
104 #define SENDSMS_SYNTAX "gsmopen_sendsms interface_name destination_number SMS_text"
105 SWITCH_STANDARD_API(gsmopen_dump_function);
106 #define GSMOPEN_DUMP_SYNTAX "gsmopen_dump <interface_name|list>"
107 /* BEGIN: Changes here */
108 #define FULL_RELOAD 0
109 #define SOFT_RELOAD 1
110 /* END: Changes heres */
111 
112 const char *interface_status[] = {	/* should match GSMOPEN_STATE_xxx in gsmopen.h */
113 	"IDLE",
114 	"DOWN",
115 	"RING",
116 	"DIALING",
117 	"BUSY",
118 	"UP",
119 	"RINGING",
120 	"PRERING",
121 	"DOUBLE",
122 	"SELECTD",
123 	"HANG_RQ",
124 	"PREANSW"
125 };
126 const char *phone_callflow[] = {	/* should match CALLFLOW_XXX in gsmopen.h */
127 	"CALL_IDLE",
128 	"CALL_DOWN",
129 	"INCOMING_RNG",
130 	"CALL_DIALING",
131 	"CALL_LINEBUSY",
132 	"CALL_ACTIVE",
133 	"INCOMING_HNG",
134 	"CALL_RLEASD",
135 	"CALL_NOCARR",
136 	"CALL_INFLUX",
137 	"CALL_INCOMING",
138 	"CALL_FAILED",
139 	"CALL_NOSRVC",
140 	"CALL_OUTRESTR",
141 	"CALL_SECFAIL",
142 	"CALL_NOANSWER",
143 	"STATUS_FNSHED",
144 	"STATUS_CANCLED",
145 	"STATUS_FAILED",
146 	"STATUS_REFUSED",
147 	"STATUS_RINGING",
148 	"STATUS_INPROGRS",
149 	"STATUS_UNPLACD",
150 	"STATUS_ROUTING",
151 	"STATUS_EARLYMD",
152 	"INCOMING_CLID",
153 	"STATUS_RMTEHOLD"
154 };
155 
156 
157 static struct {
158 	int debug;
159 	char *ip;
160 	int port;
161 	char *dialplan;
162 	char *destination;
163 	char *context;
164 	char *codec_string;
165 	char *codec_order[SWITCH_MAX_CODECS];
166 	int codec_order_last;
167 	char *codec_rates_string;
168 	char *codec_rates[SWITCH_MAX_CODECS];
169 	int codec_rates_last;
170 	unsigned int flags;
171 	int fd;
172 	int calls;
173 	int real_interfaces;
174 	int next_interface;
175 	char hold_music[256];
176 	private_t GSMOPEN_INTERFACES[GSMOPEN_MAX_INTERFACES];
177 	switch_mutex_t *mutex;
178 	private_t *gsm_console;
179 } globals;
180 
181 switch_endpoint_interface_t *gsmopen_endpoint_interface;
182 switch_memory_pool_t *gsmopen_module_pool = NULL;
183 int running = 0;
184 
185 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan);
186 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context);
187 SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination);
188 //SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_string, globals.codec_string);
189 //SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_codec_rates_string, globals.codec_rates_string);
190 
191 /* BEGIN: Changes here */
192 static switch_status_t interface_exists(char *the_interface);
193 #if 1
194 static switch_status_t remove_interface(char *the_interface);
195 #endif //0
196 /* END: Changes here */
197 
198 static switch_status_t channel_on_init(switch_core_session_t *session);
199 static switch_status_t channel_on_hangup(switch_core_session_t *session);
200 static switch_status_t channel_on_destroy(switch_core_session_t *session);
201 static switch_status_t channel_on_routing(switch_core_session_t *session);
202 static switch_status_t channel_on_exchange_media(switch_core_session_t *session);
203 static switch_status_t channel_on_consume_media(switch_core_session_t *session);
204 static switch_status_t channel_on_soft_execute(switch_core_session_t *session);
205 static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
206 													switch_event_t *var_event,
207 													switch_caller_profile_t *outbound_profile,
208 													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
209 													switch_call_cause_t *cancel_cause);
210 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id);
211 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id);
212 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig);
213 static switch_status_t gsmopen_tech_init(private_t * tech_pvt, switch_core_session_t *session);
214 
gsmopen_codec(private_t * tech_pvt,int sample_rate,int codec_ms)215 static switch_status_t gsmopen_codec(private_t * tech_pvt, int sample_rate, int codec_ms)
216 {
217 	switch_core_session_t *session = NULL;
218 
219 	if (switch_core_codec_init
220 		(&tech_pvt->read_codec, "L16", NULL, NULL, sample_rate, codec_ms, 1,
221 		 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
222 		ERRORA("Can't load codec?\n", GSMOPEN_P_LOG);
223 		return SWITCH_STATUS_FALSE;
224 	}
225 
226 	if (switch_core_codec_init
227 		(&tech_pvt->write_codec, "L16", NULL, NULL, sample_rate, codec_ms, 1,
228 		 SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) {
229 		ERRORA("Can't load codec?\n", GSMOPEN_P_LOG);
230 		switch_core_codec_destroy(&tech_pvt->read_codec);
231 		return SWITCH_STATUS_FALSE;
232 	}
233 
234 	tech_pvt->read_frame.rate = sample_rate;
235 	tech_pvt->read_frame.codec = &tech_pvt->read_codec;
236 
237 	session = switch_core_session_locate(tech_pvt->session_uuid_str);
238 
239 	if (session) {
240 		switch_core_session_set_read_codec(session, &tech_pvt->read_codec);
241 		switch_core_session_set_write_codec(session, &tech_pvt->write_codec);
242 		switch_core_session_rwunlock(session);
243 	} else {
244 		ERRORA("no session\n", GSMOPEN_P_LOG);
245 		return SWITCH_STATUS_FALSE;
246 	}
247 
248 	return SWITCH_STATUS_SUCCESS;
249 
250 }
251 
gsmopen_tech_init(private_t * tech_pvt,switch_core_session_t * session)252 switch_status_t gsmopen_tech_init(private_t * tech_pvt, switch_core_session_t *session)
253 {
254 
255 #ifdef WANT_SPEEX
256 	int ciapa;
257 	long level;
258 	int tmp;
259 #endif// WANT_SPEEX
260 	switch_assert(tech_pvt != NULL);
261 	switch_assert(session != NULL);
262 	tech_pvt->read_frame.data = tech_pvt->databuf;
263 	tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf);
264 	switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
265 	switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session));
266 	switch_core_session_set_private(session, tech_pvt);
267 	switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str));
268 	if (!strlen(tech_pvt->session_uuid_str)) {
269 		ERRORA("no tech_pvt->session_uuid_str\n", GSMOPEN_P_LOG);
270 		return SWITCH_STATUS_FALSE;
271 	}
272 	if (gsmopen_codec(tech_pvt, SAMPLERATE_GSMOPEN, 20) != SWITCH_STATUS_SUCCESS) {
273 		ERRORA("gsmopen_codec FAILED\n", GSMOPEN_P_LOG);
274 		return SWITCH_STATUS_FALSE;
275 	}
276 	//teletone_dtmf_detect_init(&tech_pvt->dtmf_detect, tech_pvt->read_codec.implementation->actual_samples_per_second);
277 	//teletone_dtmf_detect_init(&tech_pvt->dtmf_detect, 8000);
278     dtmf_rx_init(&tech_pvt->dtmf_state, NULL, NULL);
279     dtmf_rx_parms(&tech_pvt->dtmf_state, 0, 10, 10, -99);
280 
281 #ifdef GSMOPEN_ALSA
282 	if(tech_pvt->no_sound==0){
283 		if (alsa_init(tech_pvt)) {
284 			ERRORA("alsa_init failed\n", GSMOPEN_P_LOG);
285 			return SWITCH_STATUS_FALSE;
286 
287 		}
288 	}
289 #endif// GSMOPEN_ALSA
290 #ifdef GSMOPEN_PORTAUDIO
291 	if(tech_pvt->no_sound==0){
292 		if (gsmopen_portaudio_init(tech_pvt)) {
293 			ERRORA("gsmopen_portaudio_init failed\n", GSMOPEN_P_LOG);
294 			return SWITCH_STATUS_FALSE;
295 
296 		}
297 	}
298 #endif// GSMOPEN_PORTAUDIO
299 
300 	if (switch_core_timer_init(&tech_pvt->timer_read, "soft", 20, tech_pvt->read_codec.implementation->samples_per_packet, gsmopen_module_pool) !=
301 		SWITCH_STATUS_SUCCESS) {
302 		ERRORA("setup timer failed\n", GSMOPEN_P_LOG);
303 		return SWITCH_STATUS_FALSE;
304 	}
305 
306 	switch_core_timer_sync(&tech_pvt->timer_read);
307 
308 	if (switch_core_timer_init(&tech_pvt->timer_write, "soft", 20, tech_pvt->write_codec.implementation->samples_per_packet, gsmopen_module_pool) !=
309 		SWITCH_STATUS_SUCCESS) {
310 		ERRORA("setup timer failed\n", GSMOPEN_P_LOG);
311 		return SWITCH_STATUS_FALSE;
312 	}
313 
314 	switch_core_timer_sync(&tech_pvt->timer_write);
315 
316 #ifdef WANT_SPEEX
317   /* Echo canceller with 100 ms tail length */
318 #ifndef GIOVA48
319   tech_pvt->echo_state = speex_echo_state_init(160, 1024);
320   ciapa = 8000;
321 #else// GIOVA48
322   tech_pvt->echo_state = speex_echo_state_init(960, 4800);
323   ciapa = 48000;
324 #endif // GIOVA48
325   speex_echo_ctl(tech_pvt->echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &ciapa);
326 
327 #if 1 //NO MORE
328   /* Setup preprocessor and associate with echo canceller for residual echo suppression */
329 #ifndef GIOVA48
330   tech_pvt->preprocess = speex_preprocess_state_init(160, 8000);
331 #else// GIOVA48
332   tech_pvt->preprocess = speex_preprocess_state_init(960, 48000);
333 #endif // GIOVA48
334   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE,
335                        tech_pvt->echo_state);
336 
337 #if 0
338   /* Setup preprocessor various other goodies */
339   tmp = 0;
340   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_AGC, &tmp);
341   //level=8000.1;
342   //speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_AGC_LEVEL, &level);
343 
344   // Let's turn off all of the 'denoisers' (eg denoise and dereverb, and vad too) because they start automatic gain on mic input on cm108 usb, also if it (the agc on usb) disbled through mixer
345   tmp = 0;
346   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_DENOISE, &tmp);
347   tmp = 0;
348   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_DEREVERB, &tmp);
349   tmp = 0;
350   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_VAD, &tmp);
351 #endif
352 
353   tmp = 0;
354   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_SET_DENOISE, &tmp);
355   tmp = 1;
356   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_AGC, &tmp);
357   fprintf(stderr, "AGC is: %d\n", tmp);
358   level = 1.0;
359   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_AGC_LEVEL, &level);
360   fprintf(stderr, "AGC_LEVEL is: %f\n", level);
361   //tmp=1;
362   //speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_AGC_TARGET, &tmp);
363   //fprintf( stderr, "AGC_TARGET is: %d\n", tmp );
364   tmp = 1;
365   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_DENOISE, &tmp);
366   fprintf(stderr, "DENOISE is: %d\n", tmp);
367   tmp = 1;
368   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_DEREVERB, &tmp);
369   fprintf(stderr, "DEREVERB is: %d\n", tmp);
370   tmp = 1;
371   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_VAD, &tmp);
372   fprintf(stderr, "VAD is: %d\n", tmp);
373 
374 #if 0
375   tmp = 1;
376   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_NOISE_SUPPRESS, &tmp);
377   fprintf(stderr, "SPEEX_PREPROCESS_GET_NOISE_SUPPRESS is: %d\n", tmp);
378   tmp = 1;
379   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS, &tmp);
380   fprintf(stderr, "SPEEX_PREPROCESS_GET_ECHO_SUPPRESS is: %d\n", tmp);
381   tmp = 1;
382   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE,
383                        &tmp);
384   fprintf(stderr, "SPEEX_PREPROCESS_GET_ECHO_SUPPRESS_ACTIVE is: %d\n", tmp);
385   tmp = 1;
386   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_AGC_MAX_GAIN, &tmp);
387   fprintf(stderr, "SPEEX_PREPROCESS_GET_AGC_MAX_GAIN is: %d\n", tmp);
388   tmp = 1;
389   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_AGC_INCREMENT, &tmp);
390   fprintf(stderr, "SPEEX_PREPROCESS_GET_AGC_INCREMENT is: %d\n", tmp);
391   tmp = 1;
392   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_AGC_DECREMENT, &tmp);
393   fprintf(stderr, "SPEEX_PREPROCESS_GET_AGC_DECREMENT is: %d\n", tmp);
394   tmp = 1;
395   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_PROB_START, &tmp);
396   fprintf(stderr, "SPEEX_PREPROCESS_GET_PROB_START is: %d\n", tmp);
397   tmp = 1;
398   speex_preprocess_ctl(tech_pvt->preprocess, SPEEX_PREPROCESS_GET_PROB_CONTINUE, &tmp);
399   fprintf(stderr, "SPEEX_PREPROCESS_GET_PROB_CONTINUE is: %d\n", tmp);
400 #endif //0
401 #endif// 0 //NO MORE
402 
403 #endif // WANT_SPEEX
404 
405 
406 
407 	switch_clear_flag(tech_pvt, TFLAG_HANGUP);
408 	DEBUGA_GSMOPEN("gsmopen_codec SUCCESS\n", GSMOPEN_P_LOG);
409 	return SWITCH_STATUS_SUCCESS;
410 }
411 
412 /* BEGIN: Changes here */
interface_exists(char * the_interface)413 static switch_status_t interface_exists(char *the_interface)
414 {
415 	int i;
416 	int interface_id;
417 
418 	if (*the_interface == '#') {	/* look by interface id or interface name */
419 		the_interface++;
420 		switch_assert(the_interface);
421 		interface_id = atoi(the_interface);
422 
423 		/* take a number as interface id */
424 		if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
425 			if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) {
426 				return SWITCH_STATUS_SUCCESS;
427 			}
428 		} else {
429 			/* interface name */
430 			for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) {
431 				if (strcmp(globals.GSMOPEN_INTERFACES[interface_id].name, the_interface) == 0) {
432 					return SWITCH_STATUS_SUCCESS;
433 					break;
434 				}
435 			}
436 		}
437 	} else {					/* look by gsmopen_user */
438 
439 
440 		for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) {
441 			if (strlen(globals.GSMOPEN_INTERFACES[i].gsmopen_user)) {
442 				if (strcmp(globals.GSMOPEN_INTERFACES[i].gsmopen_user, the_interface) == 0) {
443 					return SWITCH_STATUS_SUCCESS;
444 				}
445 			}
446 		}
447 	}
448 	return SWITCH_STATUS_FALSE;
449 }
450 
451 #if 1
remove_interface(char * the_interface)452 static switch_status_t remove_interface(char *the_interface)
453 {
454 	int x = 10;
455 	unsigned int howmany = 8;
456 	int interface_id = -1;
457 	private_t *tech_pvt = NULL;
458 	switch_status_t status;
459 
460 	//running = 0;
461 
462 
463 	//XXX if (*the_interface == '#') {	/* remove by interface id or interface name */
464 		//XXX the_interface++;
465 		switch_assert(the_interface);
466 		interface_id = atoi(the_interface);
467 
468 		if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) {
469 			/* take a number as interface id */
470 			tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id];
471 		} else {
472 
473 			for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) {
474 				if (strcmp(globals.GSMOPEN_INTERFACES[interface_id].name, the_interface) == 0) {
475 					tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id];
476 					break;
477 				}
478 			}
479 		}
480 	//XXX } //else {					/* remove by gsmopen_user */
481 		//for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) {
482 			//if (strcmp(globals.GSMOPEN_INTERFACES[interface_id].gsmopen_user, the_interface) == 0) {
483 				//tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id];
484 				//break;
485 			//}
486 		//}
487 	//}
488 
489 	if (!tech_pvt) {
490 		DEBUGA_GSMOPEN("interface '%s' does not exist\n", GSMOPEN_P_LOG, the_interface);
491 		goto end;
492 	}
493 
494 	if (strlen(globals.GSMOPEN_INTERFACES[interface_id].session_uuid_str)) {
495 		DEBUGA_GSMOPEN("interface '%s' is busy\n", GSMOPEN_P_LOG, the_interface);
496 		goto end;
497 	}
498 
499 	globals.GSMOPEN_INTERFACES[interface_id].running = 0;
500 
501 	if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) {
502 #if 1
503 #ifdef WIN32
504 		switch_file_write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", &howmany);	// let's the controldev_thread die
505 #else /* WIN32 */
506 		howmany = write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", howmany);
507 #endif /* WIN32 */
508 #endif //0
509 		DEBUGA_GSMOPEN("HERE will shutdown gsmopen_signaling_thread of '%s'\n", GSMOPEN_P_LOG, the_interface);
510 	}
511 
512 	if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread) {
513 #if 0
514 #ifdef WIN32
515 		if (SendMessage(tech_pvt->GSMopenHandles.win32_hInit_MainWindowHandle, WM_DESTROY, 0, 0) == FALSE) {	// let's the gsmopen_api_thread_func die
516 			DEBUGA_GSMOPEN("got FALSE here, thread probably was already dead. GetLastError returned: %d\n", GSMOPEN_P_LOG, GetLastError());
517 			globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread = NULL;
518 		}
519 #else
520 		XEvent e;
521 		Atom atom1 = XInternAtom(tech_pvt->GSMopenHandles.disp, "GSMOPENCONTROLAPI_MESSAGE_BEGIN", False);
522 		memset(&e, 0, sizeof(e));
523 		e.xclient.type = ClientMessage;
524 		e.xclient.message_type = atom1;	/*  leading message */
525 		e.xclient.display = tech_pvt->GSMopenHandles.disp;
526 		e.xclient.window = tech_pvt->GSMopenHandles.gsmopen_win;
527 		e.xclient.format = 8;
528 
529 		XSendEvent(tech_pvt->GSMopenHandles.disp, tech_pvt->GSMopenHandles.win, False, 0, &e);
530 		XSync(tech_pvt->GSMopenHandles.disp, False);
531 #endif //WIN32
532 #endif //0
533 
534 		DEBUGA_GSMOPEN("HERE will shutdown gsmopen_api_thread of '%s'\n", GSMOPEN_P_LOG, the_interface);
535 	}
536 
537 	while (x) {
538 		x--;
539 		switch_yield(50000);
540 	}
541 
542 	if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) {
543 		switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread);
544 	}
545 
546 	if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread) {
547 		switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread);
548 	}
549 
550 	switch_mutex_lock(globals.mutex);
551 	if (globals.gsm_console == &globals.GSMOPEN_INTERFACES[interface_id]) {
552 		DEBUGA_GSMOPEN("interface '%s' no more console\n", GSMOPEN_P_LOG, the_interface);
553 		globals.gsm_console = NULL;
554 	} else {
555 		DEBUGA_GSMOPEN("interface '%s' STILL console\n", GSMOPEN_P_LOG, the_interface);
556 	}
557 	memset(&globals.GSMOPEN_INTERFACES[interface_id], '\0', sizeof(private_t));
558 	globals.real_interfaces--;
559 	switch_mutex_unlock(globals.mutex);
560 
561 	DEBUGA_GSMOPEN("interface '%s' deleted successfully\n", GSMOPEN_P_LOG, the_interface);
562 	globals.GSMOPEN_INTERFACES[interface_id].running = 1;
563   end:
564 	//running = 1;
565 	return SWITCH_STATUS_SUCCESS;
566 }
567 #endif //0
568 
569 /* END: Changes here */
570 
571 /*
572    State methods they get called when the state changes to the specific state
573    returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next
574    so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it.
575 */
channel_on_init(switch_core_session_t * session)576 static switch_status_t channel_on_init(switch_core_session_t *session)
577 {
578 	switch_channel_t *channel;
579 	private_t *tech_pvt = NULL;
580 
581 	tech_pvt = (private_t *) switch_core_session_get_private(session);
582 	switch_assert(tech_pvt != NULL);
583 
584 	channel = switch_core_session_get_channel(session);
585 	switch_assert(channel != NULL);
586 	//ERRORA("%s CHANNEL INIT\n", GSMOPEN_P_LOG, tech_pvt->name);
587 	switch_set_flag(tech_pvt, TFLAG_IO);
588 
589 	switch_mutex_lock(globals.mutex);
590 	globals.calls++;
591 
592 	switch_mutex_unlock(globals.mutex);
593 	DEBUGA_GSMOPEN("%s CHANNEL INIT %s\n", GSMOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
594 
595 	return SWITCH_STATUS_SUCCESS;
596 }
597 
channel_on_destroy(switch_core_session_t * session)598 static switch_status_t channel_on_destroy(switch_core_session_t *session)
599 {
600 	private_t *tech_pvt = NULL;
601 
602 	tech_pvt = (private_t *) switch_core_session_get_private(session);
603 
604 
605 	if (tech_pvt) {
606 		DEBUGA_GSMOPEN("%s CHANNEL DESTROY %s\n", GSMOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
607 
608 		if (switch_core_codec_ready(&tech_pvt->read_codec)) {
609 			switch_core_codec_destroy(&tech_pvt->read_codec);
610 		}
611 
612 		if (switch_core_codec_ready(&tech_pvt->write_codec)) {
613 			switch_core_codec_destroy(&tech_pvt->write_codec);
614 		}
615 
616 		switch_core_timer_destroy(&tech_pvt->timer_read);
617 		switch_core_timer_destroy(&tech_pvt->timer_write);
618 
619 #ifdef GSMOPEN_ALSA
620 	if(tech_pvt->no_sound==0){
621 		alsa_shutdown(tech_pvt);
622 	}
623 #endif// GSMOPEN_ALSA
624 #ifdef GSMOPEN_PORTAUDIO
625 	if(tech_pvt->no_sound==0){
626 		if (gsmopen_portaudio_shutdown(tech_pvt)) {
627 			ERRORA("gsmopen_portaudio_shutdown failed\n", GSMOPEN_P_LOG);
628 
629 		}
630 	}
631 #endif// GSMOPEN_PORTAUDIO
632 
633 
634 		*tech_pvt->session_uuid_str = '\0';
635 		tech_pvt->interface_state = GSMOPEN_STATE_IDLE;
636 		if (tech_pvt->phone_callflow == CALLFLOW_STATUS_FINISHED) {
637 			tech_pvt->phone_callflow = CALLFLOW_CALL_IDLE;
638 		}
639 		switch_core_session_set_private(session, NULL);
640 	} else {
641 		DEBUGA_GSMOPEN("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(session));
642 	}
643 
644 	return SWITCH_STATUS_SUCCESS;
645 }
646 
channel_on_hangup(switch_core_session_t * session)647 static switch_status_t channel_on_hangup(switch_core_session_t *session)
648 {
649 	switch_channel_t *channel = NULL;
650 	private_t *tech_pvt = NULL;
651 
652 
653 	channel = switch_core_session_get_channel(session);
654 	switch_assert(channel != NULL);
655 
656 	tech_pvt = (private_t *) switch_core_session_get_private(session);
657 	switch_assert(tech_pvt != NULL);
658 
659 	tech_pvt->phone_callflow = CALLFLOW_CALL_HANGUP_REQUESTED;
660 
661 	if (!switch_channel_test_flag(channel, CF_ANSWERED)) {
662 		if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
663 			tech_pvt->ob_failed_calls++;
664 		} else {
665 			tech_pvt->ib_failed_calls++;
666 		}
667 	}
668 
669 
670 	DEBUGA_GSMOPEN("%s CHANNEL HANGUP\n", GSMOPEN_P_LOG, tech_pvt->name);
671 	switch_clear_flag(tech_pvt, TFLAG_IO);
672 	switch_clear_flag(tech_pvt, TFLAG_VOICE);
673 	switch_set_flag(tech_pvt, TFLAG_HANGUP);
674 
675 	gsmopen_hangup(tech_pvt);
676 
677 	//memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str));
678 	//*tech_pvt->session_uuid_str = '\0';
679 	DEBUGA_GSMOPEN("%s CHANNEL HANGUP\n", GSMOPEN_P_LOG, tech_pvt->name);
680 	switch_mutex_lock(globals.mutex);
681 	globals.calls--;
682 	if (globals.calls < 0) {
683 		globals.calls = 0;
684 	}
685 
686 	tech_pvt->interface_state = GSMOPEN_STATE_IDLE;
687 	//FIXME if (tech_pvt->phone_callflow == CALLFLOW_STATUS_FINISHED) {
688 	tech_pvt->phone_callflow = CALLFLOW_CALL_IDLE;
689 	//FIXME }
690 	switch_mutex_unlock(globals.mutex);
691 
692 	return SWITCH_STATUS_SUCCESS;
693 }
694 
channel_on_routing(switch_core_session_t * session)695 static switch_status_t channel_on_routing(switch_core_session_t *session)
696 {
697 	switch_channel_t *channel = NULL;
698 	private_t *tech_pvt = NULL;
699 
700 	channel = switch_core_session_get_channel(session);
701 	switch_assert(channel != NULL);
702 
703 	tech_pvt = (private_t *) switch_core_session_get_private(session);
704 	switch_assert(tech_pvt != NULL);
705 
706 	DEBUGA_GSMOPEN("%s CHANNEL ROUTING\n", GSMOPEN_P_LOG, tech_pvt->name);
707 
708 	return SWITCH_STATUS_SUCCESS;
709 }
710 
channel_on_execute(switch_core_session_t * session)711 static switch_status_t channel_on_execute(switch_core_session_t *session)
712 {
713 
714 	switch_channel_t *channel = NULL;
715 	private_t *tech_pvt = NULL;
716 
717 	channel = switch_core_session_get_channel(session);
718 	switch_assert(channel != NULL);
719 
720 	tech_pvt = (private_t *) switch_core_session_get_private(session);
721 	switch_assert(tech_pvt != NULL);
722 
723 	DEBUGA_GSMOPEN("%s CHANNEL EXECUTE\n", GSMOPEN_P_LOG, tech_pvt->name);
724 
725 	return SWITCH_STATUS_SUCCESS;
726 }
727 
channel_kill_channel(switch_core_session_t * session,int sig)728 static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig)
729 {
730 	switch_channel_t *channel = NULL;
731 	private_t *tech_pvt = NULL;
732 
733 	channel = switch_core_session_get_channel(session);
734 	switch_assert(channel != NULL);
735 
736 	tech_pvt = (private_t *) switch_core_session_get_private(session);
737 	switch_assert(tech_pvt != NULL);
738 
739 	DEBUGA_GSMOPEN("%s CHANNEL KILL_CHANNEL\n", GSMOPEN_P_LOG, tech_pvt->name);
740 	switch (sig) {
741 	case SWITCH_SIG_KILL:
742 		DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_SIG_KILL\n", GSMOPEN_P_LOG, switch_channel_get_name(channel));
743 		//switch_mutex_lock(tech_pvt->flag_mutex);
744 		switch_clear_flag(tech_pvt, TFLAG_IO);
745 		switch_clear_flag(tech_pvt, TFLAG_VOICE);
746 		switch_set_flag(tech_pvt, TFLAG_HANGUP);
747 		//switch_mutex_unlock(tech_pvt->flag_mutex);
748 		break;
749 	case SWITCH_SIG_BREAK:
750 		DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_SIG_BREAK\n", GSMOPEN_P_LOG, switch_channel_get_name(channel));
751 		//switch_set_flag(tech_pvt, TFLAG_BREAK);
752 		//switch_mutex_lock(tech_pvt->flag_mutex);
753 		switch_set_flag(tech_pvt, TFLAG_BREAK);
754 		//switch_mutex_unlock(tech_pvt->flag_mutex);
755 		break;
756 	default:
757 		break;
758 	}
759 
760 	return SWITCH_STATUS_SUCCESS;
761 }
channel_on_consume_media(switch_core_session_t * session)762 static switch_status_t channel_on_consume_media(switch_core_session_t *session)
763 {
764 	private_t *tech_pvt = NULL;
765 
766 	tech_pvt = (private_t *) switch_core_session_get_private(session);
767 
768 	DEBUGA_GSMOPEN("%s CHANNEL CONSUME_MEDIA\n", GSMOPEN_P_LOG, tech_pvt->name);
769 	return SWITCH_STATUS_SUCCESS;
770 }
771 
772 
channel_on_exchange_media(switch_core_session_t * session)773 static switch_status_t channel_on_exchange_media(switch_core_session_t *session)
774 {
775 	private_t *tech_pvt = NULL;
776 	tech_pvt = (private_t *) switch_core_session_get_private(session);
777 	DEBUGA_GSMOPEN("%s CHANNEL EXCHANGE_MEDIA\n", GSMOPEN_P_LOG, tech_pvt->name);
778 	return SWITCH_STATUS_SUCCESS;
779 }
780 
channel_on_soft_execute(switch_core_session_t * session)781 static switch_status_t channel_on_soft_execute(switch_core_session_t *session)
782 {
783 	private_t *tech_pvt = NULL;
784 	tech_pvt = (private_t *) switch_core_session_get_private(session);
785 	DEBUGA_GSMOPEN("%s CHANNEL SOFT_EXECUTE\n", GSMOPEN_P_LOG, tech_pvt->name);
786 	return SWITCH_STATUS_SUCCESS;
787 }
788 
channel_send_dtmf(switch_core_session_t * session,const switch_dtmf_t * dtmf)789 static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf)
790 {
791 	private_t *tech_pvt = (private_t *) switch_core_session_get_private(session);
792 	switch_assert(tech_pvt != NULL);
793 
794 	DEBUGA_GSMOPEN("%s CHANNEL SEND_DTMF\n", GSMOPEN_P_LOG, tech_pvt->name);
795 	DEBUGA_GSMOPEN("DTMF: %c\n", GSMOPEN_P_LOG, dtmf->digit);
796 
797 	gsmopen_senddigit(tech_pvt, dtmf->digit);
798 
799 	return SWITCH_STATUS_SUCCESS;
800 }
801 
channel_read_frame(switch_core_session_t * session,switch_frame_t ** frame,switch_io_flag_t flags,int stream_id)802 static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id)
803 {
804 	switch_channel_t *channel = NULL;
805 	private_t *tech_pvt = NULL;
806 	switch_byte_t *data;
807 #if defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
808 	int samples;
809 	char digit_str[256];
810 #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
811 #ifdef GSMOPEN_PORTAUDIO
812 #ifdef WANT_SPEEX
813   spx_int16_t *speexptr;
814   spx_int16_t pcm2[160];
815   int i;
816 #endif// GSMOPEN_ALSA
817 #endif// WANT_SPEEX
818 
819 
820 	channel = switch_core_session_get_channel(session);
821 	switch_assert(channel != NULL);
822 
823 	tech_pvt = (private_t *) switch_core_session_get_private(session);
824 	switch_assert(tech_pvt != NULL);
825 
826 	if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
827 		ERRORA("channel not ready \n", GSMOPEN_P_LOG);
828 		//TODO: kill the bastard
829 		return SWITCH_STATUS_FALSE;
830 	}
831 
832 
833 	tech_pvt->read_frame.flags = SFF_NONE;
834 	*frame = NULL;
835 
836 	if (switch_test_flag(tech_pvt, TFLAG_HANGUP)) {
837 		return SWITCH_STATUS_FALSE;
838 	}
839 
840 #ifndef GSMOPEN_PORTAUDIO
841 	switch_core_timer_next(&tech_pvt->timer_read);
842 #endif// GSMOPEN_PORTAUDIO
843 
844 		if(tech_pvt->no_sound==1){
845 		goto cng;
846 		}
847 #if defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
848 #ifdef GSMOPEN_ALSA
849 	//if ((samples = snd_pcm_readi(tech_pvt->alsac, tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_packet)) > 0)
850 	if ((samples = alsa_read(tech_pvt, (short *) tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_packet)) > 0)
851 #endif// GSMOPEN_ALSA
852 #ifdef GSMOPEN_PORTAUDIO
853 	if ((samples = gsmopen_portaudio_read(tech_pvt, (short *) tech_pvt->read_frame.data, tech_pvt->read_codec.implementation->samples_per_packet)) > 0)
854 #endif// GSMOPEN_PORTAUDIO
855 	{
856 
857 #ifdef GSMOPEN_PORTAUDIO
858 #ifdef WANT_SPEEX
859 
860   if (tech_pvt->speexecho) {
861   speexptr = ((spx_int16_t *) tech_pvt->read_frame.data);
862     /* Perform echo cancellation */
863     speex_echo_capture(tech_pvt->echo_state, speexptr, pcm2);
864 #ifndef GIOVA48
865     for (i = 0; i < 160; i++)
866 #else //GIOVA48
867     for (i = 0; i < 960; i++)
868 #endif //GIOVA48
869       speexptr[i] = pcm2[i];
870   }
871   /* Apply noise/echo residual suppression */
872   if (tech_pvt->speexpreprocess) {
873     speex_preprocess_run(tech_pvt->preprocess, speexptr);
874   }
875 
876 		DEBUGA_GSMOPEN("read\n", GSMOPEN_P_LOG);
877 #endif //WANT_SPEEX
878 #endif // GSMOPEN_PORTAUDIO
879 
880 
881 
882 
883 
884 		tech_pvt->read_frame.datalen = samples * 2;
885 		tech_pvt->read_frame.samples = samples;
886 
887 #ifndef GSMOPEN_PORTAUDIO
888 		tech_pvt->read_frame.timestamp = tech_pvt->timer_read.samplecount;
889 #endif// GSMOPEN_PORTAUDIO
890 
891 		*frame = &tech_pvt->read_frame;
892 
893 		//status = SWITCH_STATUS_SUCCESS;
894 		switch_set_flag(tech_pvt, TFLAG_VOICE);
895 	}
896 
897 		//WARNINGA("samples=%d\n", GSMOPEN_P_LOG, samples);
898 	if (samples != 160) {
899 		ERRORA("samples=%d\n", GSMOPEN_P_LOG, samples);
900 		goto cng;
901 	}
902 //DEBUGA_GSMOPEN("samples=%d tech_pvt->read_frame.timestamp=%d\n", GSMOPEN_P_LOG, samples, tech_pvt->read_frame.timestamp);
903 
904 //usleep(17000);
905 //usleep(17000);
906 
907 
908 
909 
910 
911 	memset(digit_str, 0, sizeof(digit_str));
912 	//teletone_dtmf_detect(&tech_pvt->dtmf_detect, (int16_t *) tech_pvt->read_frame.data, tech_pvt->read_frame.samples);
913 	//teletone_dtmf_get(&tech_pvt->dtmf_detect, digit_str, sizeof(digit_str));
914     dtmf_rx(&tech_pvt->dtmf_state, (int16_t *) tech_pvt->read_frame.data, tech_pvt->read_frame.samples);
915     dtmf_rx_get(&tech_pvt->dtmf_state, digit_str, sizeof(digit_str));
916 
917 		gsmopen_sound_boost(tech_pvt->read_frame.data, tech_pvt->read_frame.samples, tech_pvt->capture_boost);
918 
919 	if (digit_str[0]) {
920 		switch_time_t new_dtmf_timestamp = switch_time_now();
921 		if ((new_dtmf_timestamp - tech_pvt->old_dtmf_timestamp) > 350000) {	//FIXME: make it configurable
922 			char *p = digit_str;
923 			switch_channel_t *channel = switch_core_session_get_channel(session);
924 
925 			while (p && *p) {
926 				switch_dtmf_t dtmf = {0};
927 				dtmf.digit = *p;
928 				dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION;
929 				switch_channel_queue_dtmf(channel, &dtmf);
930 				p++;
931 			}
932 			NOTICA("DTMF DETECTED: [%s] new_dtmf_timestamp: %u, delta_t: %u\n", GSMOPEN_P_LOG, digit_str, (unsigned int) new_dtmf_timestamp,
933 				   (unsigned int) (new_dtmf_timestamp - tech_pvt->old_dtmf_timestamp));
934 			tech_pvt->old_dtmf_timestamp = new_dtmf_timestamp;
935 		}
936 	}
937 	while (switch_test_flag(tech_pvt, TFLAG_IO)) {
938 		if (switch_test_flag(tech_pvt, TFLAG_BREAK)) {
939 			switch_clear_flag(tech_pvt, TFLAG_BREAK);
940 			DEBUGA_GSMOPEN("CHANNEL READ FRAME goto CNG\n", GSMOPEN_P_LOG);
941 			goto cng;
942 		}
943 
944 		if (!switch_test_flag(tech_pvt, TFLAG_IO)) {
945 			DEBUGA_GSMOPEN("CHANNEL READ FRAME not IO\n", GSMOPEN_P_LOG);
946 			return SWITCH_STATUS_FALSE;
947 		}
948 
949 		if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) {
950 			switch_clear_flag(tech_pvt, TFLAG_VOICE);
951 			if (!tech_pvt->read_frame.datalen) {
952 				DEBUGA_GSMOPEN("CHANNEL READ CONTINUE\n", GSMOPEN_P_LOG);
953 				continue;
954 			}
955 			*frame = &tech_pvt->read_frame;
956 #ifdef BIGENDIAN
957 			if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
958 				switch_swap_linear((*frame)->data, (int) (*frame)->datalen / 2);
959 			}
960 #endif
961 			//WARNINGA("HERE\n", GSMOPEN_P_LOG);
962 			return SWITCH_STATUS_SUCCESS;
963 		}
964 
965 		WARNINGA("HERE\n", GSMOPEN_P_LOG);
966 		DEBUGA_GSMOPEN("CHANNEL READ no TFLAG_VOICE\n", GSMOPEN_P_LOG);
967 		return SWITCH_STATUS_FALSE;
968 
969 	}
970 
971 	DEBUGA_GSMOPEN("CHANNEL READ FALSE\n", GSMOPEN_P_LOG);
972 	return SWITCH_STATUS_FALSE;
973 #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
974   cng:
975 	data = (switch_byte_t *) tech_pvt->read_frame.data;
976 	data[0] = 65;
977 	data[1] = 0;
978 	tech_pvt->read_frame.datalen = 2;
979 	tech_pvt->read_frame.flags = SFF_CNG;
980 	*frame = &tech_pvt->read_frame;
981 #ifdef GSMOPEN_PORTAUDIO
982 		//speex_echo_state_reset(tech_pvt->stream->echo_state);
983 #endif // GSMOPEN_PORTAUDIO
984 	return SWITCH_STATUS_SUCCESS;
985 
986 }
987 
channel_write_frame(switch_core_session_t * session,switch_frame_t * frame,switch_io_flag_t flags,int stream_id)988 static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id)
989 {
990 	switch_channel_t *channel = NULL;
991 	private_t *tech_pvt = NULL;
992 #if defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
993 	unsigned int sent;
994 #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
995 #ifdef GSMOPEN_PORTAUDIO
996 #ifdef WANT_SPEEX
997   spx_int16_t *speexptr;
998 #endif// GSMOPEN_ALSA
999 #endif// WANT_SPEEX
1000 
1001 	channel = switch_core_session_get_channel(session);
1002 	switch_assert(channel != NULL);
1003 
1004 	tech_pvt = (private_t *) switch_core_session_get_private(session);
1005 	switch_assert(tech_pvt != NULL);
1006 
1007 	if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) {
1008 		ERRORA("channel not ready \n", GSMOPEN_P_LOG);
1009 		//TODO: kill the bastard
1010 		return SWITCH_STATUS_FALSE;
1011 	}
1012 #ifdef BIGENDIAN
1013 	if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) {
1014 #ifdef WIN32
1015 		switch_swap_linear((int16_t *)frame->data, (int) frame->datalen / 2);
1016 #else
1017 		switch_swap_linear(frame->data, (int) frame->datalen / 2);
1018 #endif //WIN32
1019 	}
1020 #endif
1021 
1022 	//switch_core_timer_next(&tech_pvt->timer_write);
1023 	//sent = frame->datalen;
1024 
1025 	//ERRORA("PLAY \n", GSMOPEN_P_LOG);
1026 	//snd_pcm_writei(tech_pvt->alsap, (short *) frame->data, (int) (frame->datalen / 2));
1027 
1028 	gsmopen_sound_boost(frame->data, frame->samples, tech_pvt->playback_boost);
1029 #ifdef GSMOPEN_ALSA
1030 
1031 	switch_core_timer_next(&tech_pvt->timer_write);
1032 	sent = alsa_write(tech_pvt, (short *) frame->data, (int) (frame->datalen));
1033 //DEBUGA_GSMOPEN("sent=%d \n", GSMOPEN_P_LOG, sent);
1034 
1035 	if (sent && sent != frame->datalen / 2 && sent != -1) {
1036 		DEBUGA_GSMOPEN("sent %d\n", GSMOPEN_P_LOG, sent);
1037 	}
1038 #endif// GSMOPEN_ALSA
1039 #ifdef GSMOPEN_PORTAUDIO
1040 	sent = gsmopen_portaudio_write(tech_pvt, (short *) frame->data, (int) (frame->datalen));
1041 //DEBUGA_GSMOPEN("sent=%d \n", GSMOPEN_P_LOG, sent);
1042 
1043 	if (sent && sent != frame->datalen / 2 && sent != -1) {
1044 		DEBUGA_GSMOPEN("sent %d\n", GSMOPEN_P_LOG, sent);
1045 	}
1046 
1047 #ifdef WANT_SPEEX
1048   if (tech_pvt->speexecho) {
1049   speexptr = (spx_int16_t *) frame->data;
1050     /* Put frame into playback buffer */
1051     speex_echo_playback(tech_pvt->echo_state, speexptr);
1052 		DEBUGA_GSMOPEN("write\n", GSMOPEN_P_LOG);
1053   }
1054 #endif //WANT_SPEEX
1055 #endif // GSMOPEN_PORTAUDIO
1056 	//NOTICA("sent=%d\n", GSMOPEN_P_LOG, sent);
1057 	return SWITCH_STATUS_SUCCESS;
1058 }
1059 
channel_answer_channel(switch_core_session_t * session)1060 static switch_status_t channel_answer_channel(switch_core_session_t *session)
1061 {
1062 	private_t *tech_pvt;
1063 	switch_channel_t *channel = NULL;
1064 
1065 	channel = switch_core_session_get_channel(session);
1066 	switch_assert(channel != NULL);
1067 
1068 	tech_pvt = (private_t *) switch_core_session_get_private(session);
1069 	switch_assert(tech_pvt != NULL);
1070 
1071 	//ERRORA("%s CHANNEL INIT\n", GSMOPEN_P_LOG, tech_pvt->name);
1072 	switch_set_flag(tech_pvt, TFLAG_IO);
1073 	gsmopen_serial_answer(tech_pvt);
1074 
1075 	/* Move channel's state machine to ROUTING. This means the call is trying
1076 	   to get from the initial start where the call because, to the point
1077 	   where a destination has been identified. If the channel is simply
1078 	   left in the initial state, nothing will happen. */
1079 	switch_channel_set_state(channel, CS_ROUTING);
1080 	switch_mutex_lock(globals.mutex);
1081 	globals.calls++;
1082 
1083 	switch_mutex_unlock(globals.mutex);
1084 	DEBUGA_GSMOPEN("%s CHANNEL ANSWER %s\n", GSMOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session));
1085 
1086 
1087 
1088 
1089 
1090 
1091 
1092 
1093 
1094 
1095 
1096 
1097 
1098 
1099 
1100 
1101 	DEBUGA_GSMOPEN("ANSWERED! \n", GSMOPEN_P_LOG);
1102 
1103 	return SWITCH_STATUS_SUCCESS;
1104 }
1105 
channel_receive_message(switch_core_session_t * session,switch_core_session_message_t * msg)1106 static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg)
1107 {
1108 	switch_channel_t *channel;
1109 	private_t *tech_pvt;
1110 #if defined(GSMOPEN_ALSA)
1111 	int samples;
1112 	short tmp_buffer[1280];
1113 #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
1114 
1115 	channel = switch_core_session_get_channel(session);
1116 	switch_assert(channel != NULL);
1117 
1118 	tech_pvt = (private_t *) switch_core_session_get_private(session);
1119 	switch_assert(tech_pvt != NULL);
1120 
1121 	switch (msg->message_id) {
1122 	case SWITCH_MESSAGE_INDICATE_ANSWER:
1123 		{
1124 			DEBUGA_GSMOPEN("MSG_ID=%d, TO BE ANSWERED!\n", GSMOPEN_P_LOG, msg->message_id);
1125 			channel_answer_channel(session);
1126 		}
1127 		break;
1128 	case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC:
1129 
1130 		DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_AUDIO_SYNC\n", GSMOPEN_P_LOG, switch_channel_get_name(channel));
1131 		switch_core_timer_sync(&tech_pvt->timer_read);
1132 		switch_core_timer_sync(&tech_pvt->timer_write);
1133 
1134 #ifdef GSMOPEN_ALSA
1135 		while ((samples = alsa_read(tech_pvt, tmp_buffer, tech_pvt->read_codec.implementation->samples_per_packet * 4)) > 160) {
1136 			//WARNINGA("read %d samples\n", GSMOPEN_P_LOG, samples);
1137 		}
1138 #endif// GSMOPEN_ALSA
1139 #ifdef GSMOPEN_PORTAUDIO
1140 		//while ((samples = gsmopen_portaudio_read(tech_pvt, tmp_buffer, tech_pvt->read_codec.implementation->samples_per_packet * 2)) > 160) {
1141 			//WARNINGA("read %d samples\n", GSMOPEN_P_LOG, samples);
1142 		//}
1143 #ifdef WANT_SPEEX
1144 		speex_echo_state_reset(tech_pvt->echo_state);
1145 #endif// WANT_SPEEX
1146 #endif// GSMOPEN_PORTAUDIO
1147 		break;
1148 
1149 
1150 	default:
1151 		{
1152 			DEBUGA_GSMOPEN("MSG_ID=%d\n", GSMOPEN_P_LOG, msg->message_id);
1153 		}
1154 		break;
1155 	}
1156 
1157 	return SWITCH_STATUS_SUCCESS;
1158 }
1159 
channel_receive_event(switch_core_session_t * session,switch_event_t * event)1160 static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event)
1161 {
1162 	struct private_object *tech_pvt = (struct private_object *) switch_core_session_get_private(session);
1163 	char *body = switch_event_get_body(event);
1164 	switch_assert(tech_pvt != NULL);
1165 
1166 	if (!body) {
1167 		body = (char *) "";
1168 	}
1169 
1170 	WARNINGA("event: |||%s|||\n", GSMOPEN_P_LOG, body);
1171 
1172 	return SWITCH_STATUS_SUCCESS;
1173 }
1174 
1175 switch_state_handler_table_t gsmopen_state_handlers = {
1176 	/*.on_init */ channel_on_init,
1177 	/*.on_routing */ channel_on_routing,
1178 	/*.on_execute */ channel_on_execute,
1179 	/*.on_hangup */ channel_on_hangup,
1180 	/*.on_exchange_media */ channel_on_exchange_media,
1181 	/*.on_soft_execute */ channel_on_soft_execute,
1182 	/*.on_consume_media */ channel_on_consume_media,
1183 	/*.on_hibernate */ NULL,
1184 	/*.on_reset */ NULL,
1185 	/*.on_park */ NULL,
1186 	/*.on_reporting */ NULL,
1187 	/*.on_destroy */ channel_on_destroy
1188 };
1189 
1190 switch_io_routines_t gsmopen_io_routines = {
1191 	/*.outgoing_channel */ channel_outgoing_channel,
1192 	/*.read_frame */ channel_read_frame,
1193 	/*.write_frame */ channel_write_frame,
1194 	/*.kill_channel */ channel_kill_channel,
1195 	/*.send_dtmf */ channel_send_dtmf,
1196 	/*.receive_message */ channel_receive_message,
1197 	/*.receive_event */ channel_receive_event
1198 };
1199 
channel_outgoing_channel(switch_core_session_t * session,switch_event_t * var_event,switch_caller_profile_t * outbound_profile,switch_core_session_t ** new_session,switch_memory_pool_t ** pool,switch_originate_flag_t flags,switch_call_cause_t * cancel_cause)1200 static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *session,
1201 													switch_event_t *var_event,
1202 													switch_caller_profile_t *outbound_profile,
1203 													switch_core_session_t **new_session, switch_memory_pool_t **pool, switch_originate_flag_t flags,
1204 													switch_call_cause_t *cancel_cause)
1205 {
1206 	private_t *tech_pvt = NULL;
1207 	if ((*new_session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
1208 		switch_channel_t *channel = NULL;
1209 		switch_caller_profile_t *caller_profile;
1210 		char *rdest;
1211 		int found = 0;
1212 		char interface_name[256];
1213 
1214 		DEBUGA_GSMOPEN("1 SESSION_REQUEST %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(*new_session));
1215 		switch_core_session_add_stream(*new_session, NULL);
1216 
1217 
1218 		if (!zstr(outbound_profile->destination_number)) {
1219 			int i;
1220 			char *slash;
1221 
1222 			switch_copy_string(interface_name, outbound_profile->destination_number, 255);
1223 			slash = strrchr(interface_name, '/');
1224 			*slash = '\0';
1225 
1226 			switch_mutex_lock(globals.mutex);
1227 			if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) {
1228 				/* we've been asked for the "ANY" interface, let's find the first idle interface */
1229 				//DEBUGA_GSMOPEN("Finding one available gsmopen interface\n", GSMOPEN_P_LOG);
1230 				//tech_pvt = find_available_gsmopen_interface(NULL);
1231 				//if (tech_pvt)
1232 				//found = 1;
1233 				//} else if (strncmp("RR", interface_name, strlen(interface_name)) == 0) {
1234 				/* Find the first idle interface using Round Robin */
1235 				DEBUGA_GSMOPEN("Finding one available gsmopen interface RR\n", GSMOPEN_P_LOG);
1236 				tech_pvt = find_available_gsmopen_interface_rr(NULL);
1237 				if (tech_pvt) {
1238 					found = 1;
1239 					DEBUGA_GSMOPEN("FOUND one available gsmopen interface RR\n", GSMOPEN_P_LOG);
1240 				}
1241 			}
1242 
1243 			for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
1244 				/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
1245 				if (strlen(globals.GSMOPEN_INTERFACES[i].name)
1246 					&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) {
1247 					if (strlen(globals.GSMOPEN_INTERFACES[i].session_uuid_str)) {
1248 						DEBUGA_GSMOPEN
1249 							("globals.GSMOPEN_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n",
1250 							 GSMOPEN_P_LOG, i, globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].session_uuid_str);
1251 						DEBUGA_GSMOPEN("1 SESSION_DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(*new_session));
1252 						switch_core_session_destroy(new_session);
1253 						switch_mutex_unlock(globals.mutex);
1254 						return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1255 					}
1256 
1257 					DEBUGA_GSMOPEN("globals.GSMOPEN_INTERFACES[%d].name=|||%s|||?\n", GSMOPEN_P_LOG, i, globals.GSMOPEN_INTERFACES[i].name);
1258 					tech_pvt = &globals.GSMOPEN_INTERFACES[i];
1259 					found = 1;
1260 					break;
1261 				}
1262 
1263 			}
1264 
1265 		} else {
1266 			ERRORA("Doh! no destination number?\n", GSMOPEN_P_LOG);
1267 			switch_core_session_destroy(new_session);
1268 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1269 		}
1270 
1271 		if (!found) {
1272 			DEBUGA_GSMOPEN("Doh! no available interface for |||%s|||?\n", GSMOPEN_P_LOG, interface_name);
1273 			DEBUGA_GSMOPEN("2 SESSION_DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(*new_session));
1274 			switch_core_session_destroy(new_session);
1275 			switch_mutex_unlock(globals.mutex);
1276 			//return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1277 			return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION;
1278 		}
1279 
1280 		channel = switch_core_session_get_channel(*new_session);
1281 		if (!channel) {
1282 			ERRORA("Doh! no channel?\n", GSMOPEN_P_LOG);
1283 			switch_core_session_destroy(new_session);
1284 			switch_mutex_unlock(globals.mutex);
1285 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1286 		}
1287 		if (gsmopen_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
1288 			ERRORA("Doh! no tech_init?\n", GSMOPEN_P_LOG);
1289 			switch_core_session_destroy(new_session);
1290 			switch_mutex_unlock(globals.mutex);
1291 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1292 		}
1293 
1294 
1295 		if (outbound_profile) {
1296 			char name[128];
1297 
1298 			snprintf(name, sizeof(name), "gsmopen/%s", outbound_profile->destination_number);
1299 			//snprintf(name, sizeof(name), "gsmopen/%s", tech_pvt->name);
1300 			switch_channel_set_name(channel, name);
1301 			caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
1302 			switch_channel_set_caller_profile(channel, caller_profile);
1303 			tech_pvt->caller_profile = caller_profile;
1304 		} else {
1305 			ERRORA("Doh! no caller profile\n", GSMOPEN_P_LOG);
1306 			switch_core_session_destroy(new_session);
1307 			switch_mutex_unlock(globals.mutex);
1308 			return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1309 		}
1310 
1311 		tech_pvt->ob_calls++;
1312 
1313 		rdest = strchr(caller_profile->destination_number, '/');
1314 		*rdest++ = '\0';
1315 
1316 		//gsmopen_call(tech_pvt, rdest, 30);
1317 
1318 		switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str));
1319 		caller_profile = tech_pvt->caller_profile;
1320 		caller_profile->destination_number = rdest;
1321 
1322 		switch_set_flag(tech_pvt, TFLAG_OUTBOUND);
1323 		switch_channel_set_state(channel, CS_INIT);
1324 		gsmopen_call(tech_pvt, rdest, 30);
1325 		switch_mutex_unlock(globals.mutex);
1326 		return SWITCH_CAUSE_SUCCESS;
1327 	}
1328 
1329 	ERRORA("Doh! no new_session\n", GSMOPEN_P_LOG);
1330 	return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;
1331 }
1332 
1333 /*!
1334  * \brief This thread runs during a call, and monitor the interface for signaling, like hangup, caller id, etc most of signaling is handled inside the gsmopen_signaling_read function
1335  *
1336  */
1337 
load_config(int reload_type)1338 static switch_status_t load_config(int reload_type)
1339 {
1340 	const char *cf = "gsmopen.conf";
1341 	switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface;
1342 	private_t *tech_pvt = NULL;
1343 
1344 	switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, gsmopen_module_pool);
1345 	if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) {
1346 		ERRORA("open of %s failed\n", GSMOPEN_P_LOG, cf);
1347 		running = 0;
1348 		switch_xml_free(xml);
1349 		return SWITCH_STATUS_TERM;
1350 	}
1351 
1352 	switch_mutex_lock(globals.mutex);
1353 	if ((global_settings = switch_xml_child(cfg, "global_settings"))) {
1354 		for (param = switch_xml_child(global_settings, "param"); param; param = param->next) {
1355 			char *var = (char *) switch_xml_attr_soft(param, "name");
1356 			char *val = (char *) switch_xml_attr_soft(param, "value");
1357 
1358 			if (!strcasecmp(var, "debug")) {
1359 				DEBUGA_GSMOPEN("globals.debug=%d\n", GSMOPEN_P_LOG, globals.debug);
1360 				globals.debug = atoi(val);
1361 				DEBUGA_GSMOPEN("globals.debug=%d\n", GSMOPEN_P_LOG, globals.debug);
1362 			} else if (!strcasecmp(var, "hold-music")) {
1363 				switch_set_string(globals.hold_music, val);
1364 				DEBUGA_GSMOPEN("globals.hold_music=%s\n", GSMOPEN_P_LOG, globals.hold_music);
1365 			} else if (!strcmp(var, "dialplan")) {
1366 				set_global_dialplan(val);
1367 				DEBUGA_GSMOPEN("globals.dialplan=%s\n", GSMOPEN_P_LOG, globals.dialplan);
1368 			} else if (!strcmp(var, "destination")) {
1369 				set_global_destination(val);
1370 				DEBUGA_GSMOPEN("globals.destination=%s\n", GSMOPEN_P_LOG, globals.destination);
1371 			} else if (!strcmp(var, "context")) {
1372 				set_global_context(val);
1373 				DEBUGA_GSMOPEN("globals.context=%s\n", GSMOPEN_P_LOG, globals.context);
1374 
1375 			}
1376 
1377 		}
1378 	}
1379 
1380 	if ((interfaces = switch_xml_child(cfg, "per_interface_settings"))) {
1381 		int i = 0;
1382 
1383 		for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) {
1384 			char *id = (char *) switch_xml_attr(myinterface, "id");
1385 			char *name = (char *) switch_xml_attr(myinterface, "name");
1386 			const char *context = "default";
1387 			const char *dialplan = "XML";
1388 			const char *destination = "5000";
1389 			const char *controldevice_name = "/dev/ttyACM0";
1390 			//char *digit_timeout;
1391 			//char *max_digits;
1392 			//char *hotline;
1393 			char *dial_regex = NULL;
1394 			char *hold_music = NULL;
1395 			char *fail_dial_regex = NULL;
1396 			//const char *enable_callerid ;
1397 
1398 
1399 			const char *at_dial_pre_number = "ATD";
1400 			const char *at_dial_post_number = ";";
1401 			const char *at_dial_expect = "OK";
1402 			const char *at_hangup = "ATH";
1403 			const char *at_hangup_expect = "OK";
1404 			const char *at_answer = "ATA";
1405 			const char *at_answer_expect = "OK";
1406 			const char *at_send_dtmf = "AT+VTS";
1407 			const char *at_preinit_1 = "";
1408 			const char *at_preinit_1_expect = "";
1409 			const char *at_preinit_2 = "";
1410 			const char *at_preinit_2_expect = "";
1411 			const char *at_preinit_3 = "";
1412 			const char *at_preinit_3_expect = "";
1413 			const char *at_preinit_4 = "";
1414 			const char *at_preinit_4_expect = "";
1415 			const char *at_preinit_5 = "";
1416 			const char *at_preinit_5_expect = "";
1417 			const char *at_postinit_1 = "at+cmic=0,9";
1418 			const char *at_postinit_1_expect = "OK";
1419 			const char *at_postinit_2 = "AT+CKPD=\"EEE\"";
1420 			const char *at_postinit_2_expect = "OK";
1421 			const char *at_postinit_3 = "AT+CSSN=1,0";
1422 			const char *at_postinit_3_expect = "OK";
1423 			const char *at_postinit_4 = "at+sidet=0";
1424 			const char *at_postinit_4_expect = "OK";
1425 			const char *at_postinit_5 = "at+clvl=99";
1426 			const char *at_postinit_5_expect = "OK";
1427 			const char *at_query_battchg = "AT+CBC";
1428 			const char *at_query_battchg_expect = "OK";
1429 			const char *at_query_signal = "AT+CSQ";
1430 			const char *at_query_signal_expect = "OK";
1431 			const char *at_call_idle = "+MCST: 1";
1432 			const char *at_call_incoming = "+MCST: 2";
1433 			const char *at_call_active = "+CSSI: 7";
1434 			const char *at_call_failed = "+MCST: 65";
1435 			const char *at_call_calling = "+CSSI: 1";
1436 			const char *at_indicator_noservice_string = "CIEV: 2;0";
1437 			const char *at_indicator_nosignal_string = "CIEV: 5;0";
1438 			const char *at_indicator_lowsignal_string = "CIEV: 5;1";
1439 			const char *at_indicator_lowbattchg_string = "CIEV: 0;1";
1440 			const char *at_indicator_nobattchg_string = "CIEV: 0;0";
1441 			const char *at_indicator_callactive_string = "CIEV: 3;1";
1442 			const char *at_indicator_nocallactive_string = "CIEV: 3;0";
1443 			const char *at_indicator_nocallsetup_string = "CIEV: 6;0";
1444 			const char *at_indicator_callsetupincoming_string = "CIEV: 6;1";
1445 			const char *at_indicator_callsetupoutgoing_string = "CIEV: 6;2";
1446 			const char *at_indicator_callsetupremoteringing_string = "CIEV: 6;3";
1447 			//const char *sms_receiving_program = "/usr/local/bin/ciapalo";
1448 			const char *alsacname = "plughw:1";
1449 			const char *alsapname = "plughw:1";
1450 			const char *at_early_audio = "0";
1451 			const char *at_after_preinit_pause = "500000";
1452 			const char *at_initial_pause = "500000";
1453 			const char *at_has_clcc = "0";
1454 			const char *at_has_ecam = "0";
1455 			const char *alsa_period_size = "160";
1456 			const char *alsa_periods_in_buffer = "4";
1457 			const char *gsmopen_sound_rate = "8000";
1458 			const char *alsa_play_is_mono = "1";
1459 			const char *alsa_capture_is_mono = "1";
1460 			const char *capture_boost = "5";
1461 			const char *playback_boost = "10";
1462 #if defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
1463 			const char *no_sound = "0";
1464 #else
1465 			const char *no_sound = "1";
1466 #endif // defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
1467 #ifdef GSMOPEN_PORTAUDIO
1468 			const char *portaudiocindex;
1469 			const char *portaudiopindex;
1470 			const char *speexecho;
1471 			const char *speexpreprocess;
1472 #endif// GSMOPEN_PORTAUDIO
1473 
1474 			uint32_t interface_id = 0;
1475 #ifdef WIN32
1476 			int controldevice_speed = 115200;	//FIXME TODO
1477 #else
1478 			uint32_t controldevice_speed = B115200;	//FIXME TODO
1479 #endif //WIN32
1480 			uint32_t controldevprotocol = PROTOCOL_AT;	//FIXME TODO
1481 			uint32_t running = 1;	//FIXME TODO
1482 			const char *gsmopen_serial_sync_period = "300";	//FIXME TODO
1483 
1484 
1485 
1486 			tech_pvt = NULL;
1487 
1488 			for (param = switch_xml_child(myinterface, "param"); param; param = param->next) {
1489 				char *var = (char *) switch_xml_attr_soft(param, "name");
1490 				char *val = (char *) switch_xml_attr_soft(param, "value");
1491 
1492 				if (!strcasecmp(var, "id")) {
1493 					id = val;
1494 				} else if (!strcasecmp(var, "name")) {
1495 					name = val;
1496 				} else if (!strcasecmp(var, "context")) {
1497 					context = val;
1498 				} else if (!strcasecmp(var, "dialplan")) {
1499 					dialplan = val;
1500 				} else if (!strcasecmp(var, "destination")) {
1501 					destination = val;
1502 				} else if (!strcasecmp(var, "controldevice_name")) {
1503 					controldevice_name = val;
1504 				//} else if (!strcasecmp(var, "digit_timeout")) {
1505 					//digit_timeout = val;
1506 				//} else if (!strcasecmp(var, "max_digits")) {
1507 					//max_digits = val;
1508 				//} else if (!strcasecmp(var, "hotline")) {
1509 					//hotline = val;
1510 				} else if (!strcasecmp(var, "dial_regex")) {
1511 					dial_regex = val;
1512 				} else if (!strcasecmp(var, SWITCH_HOLD_MUSIC_VARIABLE)) {
1513 					hold_music = val;
1514 				} else if (!strcasecmp(var, "fail_dial_regex")) {
1515 					fail_dial_regex = val;
1516 				//} else if (!strcasecmp(var, "enable_callerid")) {
1517 					//enable_callerid = val;
1518 				} else if (!strcasecmp(var, "at_dial_pre_number")) {
1519 					at_dial_pre_number = val;
1520 				} else if (!strcasecmp(var, "at_dial_post_number")) {
1521 					at_dial_post_number = val;
1522 				} else if (!strcasecmp(var, "at_dial_expect")) {
1523 					at_dial_expect = val;
1524 				} else if (!strcasecmp(var, "at_hangup")) {
1525 					at_hangup = val;
1526 				} else if (!strcasecmp(var, "at_hangup_expect")) {
1527 					at_hangup_expect = val;
1528 				} else if (!strcasecmp(var, "at_answer")) {
1529 					at_answer = val;
1530 				} else if (!strcasecmp(var, "at_answer_expect")) {
1531 					at_answer_expect = val;
1532 				} else if (!strcasecmp(var, "at_send_dtmf")) {
1533 					at_send_dtmf = val;
1534 				} else if (!strcasecmp(var, "at_preinit_1")) {
1535 					at_preinit_1 = val;
1536 				} else if (!strcasecmp(var, "at_preinit_1_expect")) {
1537 					at_preinit_1_expect = val;
1538 				} else if (!strcasecmp(var, "at_preinit_2")) {
1539 					at_preinit_2 = val;
1540 				} else if (!strcasecmp(var, "at_preinit_2_expect")) {
1541 					at_preinit_2_expect = val;
1542 				} else if (!strcasecmp(var, "at_preinit_3")) {
1543 					at_preinit_3 = val;
1544 				} else if (!strcasecmp(var, "at_preinit_3_expect")) {
1545 					at_preinit_3_expect = val;
1546 				} else if (!strcasecmp(var, "at_preinit_4")) {
1547 					at_preinit_4 = val;
1548 				} else if (!strcasecmp(var, "at_preinit_4_expect")) {
1549 					at_preinit_4_expect = val;
1550 				} else if (!strcasecmp(var, "at_preinit_5")) {
1551 					at_preinit_5 = val;
1552 				} else if (!strcasecmp(var, "at_preinit_5_expect")) {
1553 					at_preinit_5_expect = val;
1554 				} else if (!strcasecmp(var, "at_postinit_1")) {
1555 					at_postinit_1 = val;
1556 				} else if (!strcasecmp(var, "at_postinit_1_expect")) {
1557 					at_postinit_1_expect = val;
1558 				} else if (!strcasecmp(var, "at_postinit_2")) {
1559 					at_postinit_2 = val;
1560 				} else if (!strcasecmp(var, "at_postinit_2_expect")) {
1561 					at_postinit_2_expect = val;
1562 				} else if (!strcasecmp(var, "at_postinit_3")) {
1563 					at_postinit_3 = val;
1564 				} else if (!strcasecmp(var, "at_postinit_3_expect")) {
1565 					at_postinit_3_expect = val;
1566 				} else if (!strcasecmp(var, "at_postinit_4")) {
1567 					at_postinit_4 = val;
1568 				} else if (!strcasecmp(var, "at_postinit_4_expect")) {
1569 					at_postinit_4_expect = val;
1570 				} else if (!strcasecmp(var, "at_postinit_5")) {
1571 					at_postinit_5 = val;
1572 				} else if (!strcasecmp(var, "at_postinit_5_expect")) {
1573 					at_postinit_5_expect = val;
1574 				} else if (!strcasecmp(var, "at_query_battchg")) {
1575 					at_query_battchg = val;
1576 				} else if (!strcasecmp(var, "at_query_battchg_expect")) {
1577 					at_query_battchg_expect = val;
1578 				} else if (!strcasecmp(var, "at_query_signal")) {
1579 					at_query_signal = val;
1580 				} else if (!strcasecmp(var, "at_query_signal_expect")) {
1581 					at_query_signal_expect = val;
1582 				} else if (!strcasecmp(var, "at_call_idle")) {
1583 					at_call_idle = val;
1584 				} else if (!strcasecmp(var, "at_call_incoming")) {
1585 					at_call_incoming = val;
1586 				} else if (!strcasecmp(var, "at_call_active")) {
1587 					at_call_active = val;
1588 				} else if (!strcasecmp(var, "at_call_failed")) {
1589 					at_call_failed = val;
1590 				} else if (!strcasecmp(var, "at_call_calling")) {
1591 					at_call_calling = val;
1592 				} else if (!strcasecmp(var, "at_indicator_noservice_string")) {
1593 					at_indicator_noservice_string = val;
1594 				} else if (!strcasecmp(var, "at_indicator_nosignal_string")) {
1595 					at_indicator_nosignal_string = val;
1596 				} else if (!strcasecmp(var, "at_indicator_lowsignal_string")) {
1597 					at_indicator_lowsignal_string = val;
1598 				} else if (!strcasecmp(var, "at_indicator_lowbattchg_string")) {
1599 					at_indicator_lowbattchg_string = val;
1600 				} else if (!strcasecmp(var, "at_indicator_nobattchg_string")) {
1601 					at_indicator_nobattchg_string = val;
1602 				} else if (!strcasecmp(var, "at_indicator_callactive_string")) {
1603 					at_indicator_callactive_string = val;
1604 				} else if (!strcasecmp(var, "at_indicator_nocallactive_string")) {
1605 					at_indicator_nocallactive_string = val;
1606 				} else if (!strcasecmp(var, "at_indicator_nocallsetup_string")) {
1607 					at_indicator_nocallsetup_string = val;
1608 				} else if (!strcasecmp(var, "at_indicator_callsetupincoming_string")) {
1609 					at_indicator_callsetupincoming_string = val;
1610 				} else if (!strcasecmp(var, "at_indicator_callsetupoutgoing_string")) {
1611 					at_indicator_callsetupoutgoing_string = val;
1612 				} else if (!strcasecmp(var, "at_indicator_callsetupremoteringing_string")) {
1613 					at_indicator_callsetupremoteringing_string = val;
1614 					//} else if (!strcasecmp(var, "sms_receiving_program")) {
1615 					//sms_receiving_program = val;
1616 				} else if (!strcasecmp(var, "alsacname")) {
1617 					alsacname = val;
1618 				} else if (!strcasecmp(var, "alsapname")) {
1619 					alsapname = val;
1620 #ifdef GSMOPEN_PORTAUDIO
1621 				} else if (!strcasecmp(var, "portaudiocindex")) {
1622 					portaudiocindex = val;
1623 				} else if (!strcasecmp(var, "portaudiopindex")) {
1624 					portaudiopindex = val;
1625 				} else if (!strcasecmp(var, "speexecho")) {
1626 					speexecho = val;
1627 				} else if (!strcasecmp(var, "speexpreprocess")) {
1628 					speexpreprocess = val;
1629 #endif// GSMOPEN_PORTAUDIO
1630 				} else if (!strcasecmp(var, "at_early_audio")) {
1631 					at_early_audio = val;
1632 				} else if (!strcasecmp(var, "at_after_preinit_pause")) {
1633 					at_after_preinit_pause = val;
1634 				} else if (!strcasecmp(var, "at_initial_pause")) {
1635 					at_initial_pause = val;
1636 				} else if (!strcasecmp(var, "at_has_clcc")) {
1637 					at_has_clcc = val;
1638 				} else if (!strcasecmp(var, "at_has_ecam")) {
1639 					at_has_ecam = val;
1640 				} else if (!strcasecmp(var, "alsa_period_size")) {
1641 					alsa_period_size = val;
1642 				} else if (!strcasecmp(var, "alsa_periods_in_buffer")) {
1643 					alsa_periods_in_buffer = val;
1644 				} else if (!strcasecmp(var, "gsmopen_sound_rate")) {
1645 					gsmopen_sound_rate = val;
1646 				} else if (!strcasecmp(var, "alsa_play_is_mono")) {
1647 					alsa_play_is_mono = val;
1648 				} else if (!strcasecmp(var, "alsa_capture_is_mono")) {
1649 					alsa_capture_is_mono = val;
1650 				} else if (!strcasecmp(var, "capture_boost")) {
1651 					capture_boost = val;
1652 				} else if (!strcasecmp(var, "playback_boost")) {
1653 					playback_boost = val;
1654 				} else if (!strcasecmp(var, "no_sound")) {
1655 					no_sound = val;
1656 				} else if (!strcasecmp(var, "gsmopen_serial_sync_period")) {
1657 					gsmopen_serial_sync_period = val;
1658 				}
1659 
1660 
1661 			}
1662 
1663 			/* BEGIN: Changes here */
1664 			if (reload_type == SOFT_RELOAD) {
1665 				char the_interface[256];
1666 				sprintf(the_interface, "#%s", name);
1667 
1668 				if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) {
1669 					continue;
1670 				}
1671 			}
1672 			/* END: Changes here */
1673 
1674 			if (!id) {
1675 				ERRORA("interface missing REQUIRED param 'id'\n", GSMOPEN_P_LOG);
1676 				continue;
1677 			}
1678 
1679 			if (switch_is_number(id)) {
1680 				interface_id = atoi(id);
1681 			} else {
1682 				ERRORA("interface param 'id' MUST be a number, now id='%s'\n", GSMOPEN_P_LOG, id);
1683 				continue;
1684 			}
1685 
1686 			if (!switch_is_number(at_early_audio)) {
1687 				ERRORA("interface param 'at_early_audio' MUST be a number, now at_early_audio='%s'\n", GSMOPEN_P_LOG, at_early_audio);
1688 				continue;
1689 			}
1690 			if (!switch_is_number(at_after_preinit_pause)) {
1691 				ERRORA("interface param 'at_after_preinit_pause' MUST be a number, now at_after_preinit_pause='%s'\n", GSMOPEN_P_LOG,
1692 					   at_after_preinit_pause);
1693 				continue;
1694 			}
1695 			if (!switch_is_number(at_initial_pause)) {
1696 				ERRORA("interface param 'at_initial_pause' MUST be a number, now at_initial_pause='%s'\n", GSMOPEN_P_LOG, at_initial_pause);
1697 				continue;
1698 			}
1699 			if (!switch_is_number(at_has_clcc)) {
1700 				ERRORA("interface param 'at_has_clcc' MUST be a number, now at_has_clcc='%s'\n", GSMOPEN_P_LOG, at_has_clcc);
1701 				continue;
1702 			}
1703 			if (!switch_is_number(at_has_ecam)) {
1704 				ERRORA("interface param 'at_has_ecam' MUST be a number, now at_has_ecam='%s'\n", GSMOPEN_P_LOG, at_has_ecam);
1705 				continue;
1706 			}
1707 			if (!switch_is_number(alsa_period_size)) {
1708 				ERRORA("interface param 'alsa_period_size' MUST be a number, now alsa_period_size='%s'\n", GSMOPEN_P_LOG, alsa_period_size);
1709 				continue;
1710 			}
1711 			if (!switch_is_number(alsa_periods_in_buffer)) {
1712 				ERRORA("interface param 'alsa_periods_in_buffer' MUST be a number, now alsa_periods_in_buffer='%s'\n", GSMOPEN_P_LOG,
1713 					   alsa_periods_in_buffer);
1714 				continue;
1715 			}
1716 			if (!switch_is_number(gsmopen_sound_rate)) {
1717 				ERRORA("interface param 'gsmopen_sound_rate' MUST be a number, now gsmopen_sound_rate='%s'\n", GSMOPEN_P_LOG, gsmopen_sound_rate);
1718 				continue;
1719 			}
1720 			if (!switch_is_number(alsa_play_is_mono)) {
1721 				ERRORA("interface param 'alsa_play_is_mono' MUST be a number, now alsa_play_is_mono='%s'\n", GSMOPEN_P_LOG, alsa_play_is_mono);
1722 				continue;
1723 			}
1724 			if (!switch_is_number(alsa_capture_is_mono)) {
1725 				ERRORA("interface param 'alsa_capture_is_mono' MUST be a number, now alsa_capture_is_mono='%s'\n", GSMOPEN_P_LOG, alsa_capture_is_mono);
1726 				continue;
1727 			}
1728 			if (!switch_is_number(capture_boost)) {
1729 				ERRORA("interface param 'capture_boost' MUST be a number, now capture_boost='%s'\n", GSMOPEN_P_LOG, capture_boost);
1730 				continue;
1731 			}
1732 			if (!switch_is_number(playback_boost)) {
1733 				ERRORA("interface param 'playback_boost' MUST be a number, now playback_boost='%s'\n", GSMOPEN_P_LOG, playback_boost);
1734 				continue;
1735 			}
1736 			if (!switch_is_number(no_sound)) {
1737 				ERRORA("interface param 'no_sound' MUST be a number, now no_sound='%s'\n", GSMOPEN_P_LOG, no_sound);
1738 				continue;
1739 			}
1740 			if (!switch_is_number(gsmopen_serial_sync_period)) {
1741 				ERRORA("interface param 'gsmopen_serial_sync_period' MUST be a number, now gsmopen_serial_sync_period='%s'\n", GSMOPEN_P_LOG, gsmopen_serial_sync_period);
1742 				continue;
1743 			}
1744 
1745 
1746 			if (interface_id && interface_id < GSMOPEN_MAX_INTERFACES) {
1747 				private_t newconf;
1748 				switch_threadattr_t *gsmopen_api_thread_attr = NULL;
1749 				int res = 0;
1750 
1751 				memset(&newconf, '\0', sizeof(newconf));
1752 				globals.GSMOPEN_INTERFACES[interface_id] = newconf;
1753 
1754 
1755 				tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id];
1756 
1757 				switch_mutex_init(&globals.GSMOPEN_INTERFACES[interface_id].controldev_lock, SWITCH_MUTEX_NESTED, gsmopen_module_pool);
1758 
1759 
1760 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].id, id);
1761 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].name, name);
1762 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].context, context);
1763 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].dialplan, dialplan);
1764 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].destination, destination);
1765 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].controldevice_name, controldevice_name);
1766 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].dial_regex, dial_regex);
1767 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].hold_music, hold_music);
1768 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].fail_dial_regex, fail_dial_regex);
1769 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_dial_pre_number, at_dial_pre_number);
1770 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_dial_post_number, at_dial_post_number);
1771 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_dial_expect, at_dial_expect);
1772 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_hangup, at_hangup);
1773 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_hangup_expect, at_hangup_expect);
1774 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_answer, at_answer);
1775 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_answer_expect, at_answer_expect);
1776 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_send_dtmf, at_send_dtmf);
1777 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_1, at_preinit_1);
1778 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_1_expect, at_preinit_1_expect);
1779 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_2, at_preinit_2);
1780 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_2_expect, at_preinit_2_expect);
1781 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_3, at_preinit_3);
1782 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_3_expect, at_preinit_3_expect);
1783 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_4, at_preinit_4);
1784 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_4_expect, at_preinit_4_expect);
1785 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_5, at_preinit_5);
1786 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_5_expect, at_preinit_5_expect);
1787 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_1, at_postinit_1);
1788 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_1_expect, at_postinit_1_expect);
1789 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_2, at_postinit_2);
1790 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_2_expect, at_postinit_2_expect);
1791 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_3, at_postinit_3);
1792 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_3_expect, at_postinit_3_expect);
1793 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_4, at_postinit_4);
1794 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_4_expect, at_postinit_4_expect);
1795 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_5, at_postinit_5);
1796 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_5_expect, at_postinit_5_expect);
1797 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_battchg, at_query_battchg);
1798 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_battchg_expect, at_query_battchg_expect);
1799 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_signal, at_query_signal);
1800 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_signal_expect, at_query_signal_expect);
1801 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_idle, at_call_idle);
1802 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_incoming, at_call_incoming);
1803 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_active, at_call_active);
1804 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_failed, at_call_failed);
1805 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_calling, at_call_calling);
1806 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_noservice_string, at_indicator_noservice_string);
1807 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nosignal_string, at_indicator_nosignal_string);
1808 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_lowsignal_string, at_indicator_lowsignal_string);
1809 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_lowbattchg_string, at_indicator_lowbattchg_string);
1810 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nobattchg_string, at_indicator_nobattchg_string);
1811 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callactive_string, at_indicator_callactive_string);
1812 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nocallactive_string, at_indicator_nocallactive_string);
1813 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nocallsetup_string, at_indicator_nocallsetup_string);
1814 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callsetupincoming_string, at_indicator_callsetupincoming_string);
1815 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callsetupoutgoing_string, at_indicator_callsetupoutgoing_string);
1816 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callsetupremoteringing_string,
1817 								  at_indicator_callsetupremoteringing_string);
1818 				//switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].sms_receiving_program, sms_receiving_program);
1819 #ifdef GSMOPEN_ALSA
1820 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].alsacname, alsacname);
1821 				switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].alsapname, alsapname);
1822 #endif// GSMOPEN_ALSA
1823 
1824 #ifdef GSMOPEN_PORTAUDIO
1825 				globals.GSMOPEN_INTERFACES[interface_id].portaudiocindex = atoi(portaudiocindex);
1826 				globals.GSMOPEN_INTERFACES[interface_id].portaudiopindex = atoi(portaudiopindex);
1827 				globals.GSMOPEN_INTERFACES[interface_id].speexecho = atoi(speexecho);
1828 				globals.GSMOPEN_INTERFACES[interface_id].speexpreprocess = atoi(speexpreprocess);
1829 #endif// GSMOPEN_PORTAUDIO
1830 				globals.GSMOPEN_INTERFACES[interface_id].at_early_audio = atoi(at_early_audio);
1831 				globals.GSMOPEN_INTERFACES[interface_id].at_after_preinit_pause = atoi(at_after_preinit_pause);
1832 				globals.GSMOPEN_INTERFACES[interface_id].at_initial_pause = atoi(at_initial_pause);
1833 				globals.GSMOPEN_INTERFACES[interface_id].at_has_clcc = atoi(at_has_clcc);
1834 				globals.GSMOPEN_INTERFACES[interface_id].at_has_ecam = atoi(at_has_ecam);
1835 #ifdef GSMOPEN_ALSA
1836 				globals.GSMOPEN_INTERFACES[interface_id].alsa_period_size = atoi(alsa_period_size);
1837 				globals.GSMOPEN_INTERFACES[interface_id].alsa_periods_in_buffer = atoi(alsa_periods_in_buffer);
1838 				globals.GSMOPEN_INTERFACES[interface_id].gsmopen_sound_rate = atoi(gsmopen_sound_rate);
1839 				globals.GSMOPEN_INTERFACES[interface_id].alsa_play_is_mono = atoi(alsa_play_is_mono);
1840 				globals.GSMOPEN_INTERFACES[interface_id].alsa_capture_is_mono = atoi(alsa_capture_is_mono);
1841 #endif// GSMOPEN_ALSA
1842 				globals.GSMOPEN_INTERFACES[interface_id].capture_boost = atoi(capture_boost);
1843 				globals.GSMOPEN_INTERFACES[interface_id].playback_boost = atoi(playback_boost);
1844 #if defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
1845 				globals.GSMOPEN_INTERFACES[interface_id].no_sound = atoi(no_sound);
1846 #else
1847 				globals.GSMOPEN_INTERFACES[interface_id].no_sound = 1;
1848 #endif //  defined(GSMOPEN_ALSA) || defined(GSMOPEN_PORTAUDIO)
1849 				globals.GSMOPEN_INTERFACES[interface_id].gsmopen_serial_sync_period = atoi(gsmopen_serial_sync_period);
1850 
1851 
1852 
1853 				globals.GSMOPEN_INTERFACES[interface_id].controldevice_speed = controldevice_speed;	//FIXME
1854 				globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol = controldevprotocol;	//FIXME
1855 				globals.GSMOPEN_INTERFACES[interface_id].running = running;	//FIXME
1856 
1857 
1858 
1859 				WARNINGA("STARTING interface_id=%d\n", GSMOPEN_P_LOG, interface_id);
1860 				DEBUGA_GSMOPEN("id=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].id);
1861 				DEBUGA_GSMOPEN("name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].name);
1862 				DEBUGA_GSMOPEN("hold-music=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].hold_music);
1863 				DEBUGA_GSMOPEN("context=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].context);
1864 				DEBUGA_GSMOPEN("dialplan=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].dialplan);
1865 				DEBUGA_GSMOPEN("destination=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].destination);
1866 				DEBUGA_GSMOPEN("controldevice_name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].controldevice_name);
1867 #ifdef GSMOPEN_ALSA
1868 				DEBUGA_GSMOPEN("alsacname=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].alsacname);
1869 				DEBUGA_GSMOPEN("alsapname=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].alsapname);
1870 #endif// GSMOPEN_ALSA
1871 
1872 
1873 #ifdef GSMOPEN_PORTAUDIO
1874 				//FIXME
1875 				//globals.GSMOPEN_INTERFACES[interface_id].portaudiocindex = 1;
1876 				//globals.GSMOPEN_INTERFACES[interface_id].portaudiopindex = 1;
1877 				//globals.GSMOPEN_INTERFACES[interface_id].speexecho = 1;
1878 				//globals.GSMOPEN_INTERFACES[interface_id].speexpreprocess = 1;
1879 				DEBUGA_GSMOPEN("portaudiocindex=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].portaudiocindex);
1880 				DEBUGA_GSMOPEN("portaudiocindex=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].portaudiocindex);
1881 				DEBUGA_GSMOPEN("speexecho=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].speexecho);
1882 				DEBUGA_GSMOPEN("speexpreprocess=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].speexpreprocess);
1883 #endif// GSMOPEN_PORTAUDIO
1884 				DEBUGA_GSMOPEN("gsmopen_serial_sync_period=%d\n", GSMOPEN_P_LOG, (int)globals.GSMOPEN_INTERFACES[interface_id].gsmopen_serial_sync_period);
1885 				/* init the serial port */
1886 				if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) {
1887 					globals.GSMOPEN_INTERFACES[interface_id].controldevfd =
1888 						gsmopen_serial_init(&globals.GSMOPEN_INTERFACES[interface_id], globals.GSMOPEN_INTERFACES[interface_id].controldevice_speed);
1889 					if (globals.GSMOPEN_INTERFACES[interface_id].controldevfd == -1) {
1890 						ERRORA("gsmopen_serial_init failed\n", GSMOPEN_P_LOG);
1891 						ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
1892 						//return SWITCH_STATUS_FALSE;
1893 						globals.GSMOPEN_INTERFACES[interface_id].running=0;
1894 						alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_init failed");
1895 						globals.GSMOPEN_INTERFACES[interface_id].active=0;
1896 						globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
1897 						continue;
1898 					}
1899 				}
1900 
1901 				/* config the phone/modem on the serial port */
1902 				if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) {
1903 					res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]);
1904 					if (res) {
1905 						int count = 0;
1906 						ERRORA("gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG);
1907 						while(res && count < 5){
1908 							switch_sleep(100000); //0.1 seconds
1909 							res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]);
1910 							count++;
1911 							if (res) {
1912 								ERRORA("%d: gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG, count);
1913 							}
1914 						}
1915 						if (res) {
1916 							ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
1917 							//return SWITCH_STATUS_FALSE;
1918 							globals.GSMOPEN_INTERFACES[interface_id].running=0;
1919 							alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed");
1920 							globals.GSMOPEN_INTERFACES[interface_id].active=0;
1921 							globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
1922 							continue;
1923 						}
1924 					}
1925 				}
1926 
1927 				if(globals.GSMOPEN_INTERFACES[interface_id].no_sound==0){
1928 #ifdef GSMOPEN_ALSA
1929 					if (alsa_init(&globals.GSMOPEN_INTERFACES[interface_id])) {
1930 						ERRORA("alsa_init failed\n", GSMOPEN_P_LOG);
1931 						ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
1932 						//return SWITCH_STATUS_FALSE;
1933 						globals.GSMOPEN_INTERFACES[interface_id].running=0;
1934 						alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "alsa_init failed");
1935 						globals.GSMOPEN_INTERFACES[interface_id].active=0;
1936 						globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
1937 						continue;
1938 
1939 					}
1940 
1941 					if (alsa_shutdown(&globals.GSMOPEN_INTERFACES[interface_id])) {
1942 						ERRORA("alsa_shutdown failed\n", GSMOPEN_P_LOG);
1943 						ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
1944 						//return SWITCH_STATUS_FALSE;
1945 						globals.GSMOPEN_INTERFACES[interface_id].running=0;
1946 						alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "alsa_shutdown failed");
1947 						globals.GSMOPEN_INTERFACES[interface_id].active=0;
1948 						globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
1949 						continue;
1950 
1951 					}
1952 #endif// GSMOPEN_ALSA
1953 #ifdef GSMOPEN_PORTAUDIO
1954 					if (gsmopen_portaudio_init(&globals.GSMOPEN_INTERFACES[interface_id])) {
1955 						ERRORA("gsmopen_portaudio_init failed\n", GSMOPEN_P_LOG);
1956 						ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
1957 						//return SWITCH_STATUS_FALSE;
1958 						globals.GSMOPEN_INTERFACES[interface_id].running=0;
1959 						alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_portaudio_init failed");
1960 						globals.GSMOPEN_INTERFACES[interface_id].active=0;
1961 						globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
1962 						continue;
1963 
1964 					}
1965 
1966 					if (gsmopen_portaudio_shutdown(&globals.GSMOPEN_INTERFACES[interface_id])) {
1967 						ERRORA("gsmopen_portaudio_shutdown failed\n", GSMOPEN_P_LOG);
1968 						ERRORA("STARTING interface_id=%d FAILED\n", GSMOPEN_P_LOG, interface_id);
1969 						//return SWITCH_STATUS_FALSE;
1970 						globals.GSMOPEN_INTERFACES[interface_id].running=0;
1971 						alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_portaudio_shutdown failed");
1972 						globals.GSMOPEN_INTERFACES[interface_id].active=0;
1973 						globals.GSMOPEN_INTERFACES[interface_id].name[0]='\0';
1974 						continue;
1975 
1976 					}
1977 #endif// GSMOPEN_PORTAUDIO
1978 				}
1979 
1980 				globals.GSMOPEN_INTERFACES[interface_id].active=1;
1981 
1982 				//gsmopen_store_boost((char *)"5", &globals.GSMOPEN_INTERFACES[interface_id].capture_boost);    //FIXME
1983 				//gsmopen_store_boost((char *)"10", &globals.GSMOPEN_INTERFACES[interface_id].playback_boost);  //FIXME
1984 				gsmopen_store_boost((char *) capture_boost, &globals.GSMOPEN_INTERFACES[interface_id].capture_boost);	//FIXME
1985 				gsmopen_store_boost((char *) playback_boost, &globals.GSMOPEN_INTERFACES[interface_id].playback_boost);	//FIXME
1986 
1987 				switch_sleep(100000);
1988 				switch_threadattr_create(&gsmopen_api_thread_attr, gsmopen_module_pool);
1989 				switch_threadattr_stacksize_set(gsmopen_api_thread_attr, SWITCH_THREAD_STACKSIZE);
1990 				switch_thread_create(&globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread, gsmopen_api_thread_attr, gsmopen_do_gsmopenapi_thread,
1991 									 &globals.GSMOPEN_INTERFACES[interface_id], gsmopen_module_pool);
1992 
1993 				switch_sleep(100000);
1994 				WARNINGA("STARTED interface_id=%d\n", GSMOPEN_P_LOG, interface_id);
1995 
1996 			} else {
1997 				ERRORA("interface id %d is higher than GSMOPEN_MAX_INTERFACES (%d)\n", GSMOPEN_P_LOG, interface_id, GSMOPEN_MAX_INTERFACES);
1998 				alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "interface id is higher than GSMOPEN_MAX_INTERFACES");
1999 				continue;
2000 			}
2001 
2002 		}
2003 
2004 		for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) {
2005 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)) {
2006 				/* How many real intterfaces */
2007 				globals.real_interfaces = i + 1;
2008 
2009 				tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2010 
2011 				DEBUGA_GSMOPEN("id=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].id);
2012 				DEBUGA_GSMOPEN("name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].name);
2013 				DEBUGA_GSMOPEN("context=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].context);
2014 				DEBUGA_GSMOPEN("hold-music=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].hold_music);
2015 				DEBUGA_GSMOPEN("dialplan=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].dialplan);
2016 				DEBUGA_GSMOPEN("destination=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].destination);
2017 				DEBUGA_GSMOPEN("controldevice_name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].controldevice_name);
2018 #ifdef GSMOPEN_ALSA
2019 				DEBUGA_GSMOPEN("alsacname=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].alsacname);
2020 				DEBUGA_GSMOPEN("alsapname=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].alsapname);
2021 #endif// GSMOPEN_ALSA
2022 #ifdef GSMOPEN_PORTAUDIO
2023 				DEBUGA_GSMOPEN("portaudiocindex=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].portaudiocindex);
2024 				DEBUGA_GSMOPEN("portaudiopindex=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].portaudiopindex);
2025 				DEBUGA_GSMOPEN("speexecho=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].speexecho);
2026 				DEBUGA_GSMOPEN("speexpreprocess=%d\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].speexpreprocess);
2027 #endif// GSMOPEN_PORTAUDIO
2028 				DEBUGA_GSMOPEN("gsmopen_serial_sync_period=%d\n", GSMOPEN_P_LOG, (int)globals.GSMOPEN_INTERFACES[i].gsmopen_serial_sync_period);
2029 
2030 			}
2031 		}
2032 	}
2033 
2034 	switch_mutex_unlock(globals.mutex);
2035 	switch_xml_free(xml);
2036 
2037 	return SWITCH_STATUS_SUCCESS;
2038 }
2039 
2040 //static switch_status_t chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint)
chat_send(switch_event_t * message_event)2041 static switch_status_t chat_send(switch_event_t *message_event)
2042 {
2043 	char *user, *host, *f_user = NULL, *f_host = NULL, *f_resource = NULL;
2044 	private_t *tech_pvt = NULL;
2045 	int i = 0, found = 0;
2046 
2047         const char *proto;
2048         const char *from;
2049         const char *to;
2050         const char *subject;
2051         const char *body;
2052         //const char *type;
2053 	const char *hint;
2054 
2055 	proto = switch_event_get_header(message_event, "proto");
2056 	from = switch_event_get_header(message_event, "from");
2057 	to = switch_event_get_header(message_event, "to");
2058 	subject = switch_event_get_header(message_event, "subject");
2059 	body = switch_event_get_body(message_event);
2060 	//type = switch_event_get_header(message_event, "type");
2061 	hint = switch_event_get_header(message_event, "hint");
2062 
2063 	switch_assert(proto != NULL);
2064 
2065 	DEBUGA_GSMOPEN("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, hint=%s)\n", GSMOPEN_P_LOG, proto, from, to, subject, body,
2066 				   hint ? hint : "NULL");
2067 
2068 	if (!to || !strlen(to)) {
2069 		ERRORA("Missing To: header.\n", GSMOPEN_P_LOG);
2070 		return SWITCH_STATUS_SUCCESS;
2071 	}
2072 
2073 	if ((!from && !hint) || (!strlen(from) && !strlen(hint))) {
2074 		ERRORA("Missing From: AND Hint: headers.\n", GSMOPEN_P_LOG);
2075 		return SWITCH_STATUS_SUCCESS;
2076 	}
2077 
2078 	if (from && (f_user = strdup(from))) {
2079 		if ((f_host = strchr(f_user, '@'))) {
2080 			*f_host++ = '\0';
2081 			if ((f_resource = strchr(f_host, '/'))) {
2082 				*f_resource++ = '\0';
2083 			}
2084 		}
2085 	}
2086 
2087 	if (!strlen(hint)) {		//FIXME FIXME FIXME
2088 		hint = from;
2089 	}
2090 	if (to && (user = strdup(to))) {
2091 		if ((host = strchr(user, '@'))) {
2092 			*host++ = '\0';
2093 		}
2094 
2095 		DEBUGA_GSMOPEN("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, hint=%s)\n", GSMOPEN_P_LOG, proto, from, to, subject, body,
2096 					   hint ? hint : "NULL");
2097 		if (hint && strlen(hint)) {
2098 			//in hint we receive the interface name to use
2099 			for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2100 				if (strlen(globals.GSMOPEN_INTERFACES[i].name)
2101 					&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, hint, strlen(hint)) == 0)) {
2102 					tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2103 					DEBUGA_GSMOPEN("Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", GSMOPEN_P_LOG, i,
2104 								   globals.GSMOPEN_INTERFACES[i].name);
2105 					found = 1;
2106 					break;
2107 				}
2108 			}
2109 		}						/* FIXME add a tech_pvt member for the SIM telephone number //else {
2110 								   //we have no a predefined interface name to use (hint is NULL), so let's choose an interface from the username (from)
2111 								   for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2112 								   if (strlen(globals.GSMOPEN_INTERFACES[i].name)
2113 								   && (strncmp(globals.GSMOPEN_INTERFACES[i].skype_user, from, strlen(from)) == 0)) {
2114 								   tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2115 								   DEBUGA_GSMOPEN("Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", GSMOPEN_P_LOG, i, globals.GSMOPEN_INTERFACES[i].name);
2116 								   found = 1;
2117 								   break;
2118 								   }
2119 								   }
2120 								   }
2121 								 */
2122 		if (!found) {
2123 			ERRORA("ERROR: A GSMopen interface with name='%s' or one with SIM_number='%s' was not found\n", GSMOPEN_P_LOG, hint ? hint : "NULL",
2124 				   from ? from : "NULL");
2125 			goto end;
2126 		} else {
2127 			gsmopen_sendsms(tech_pvt, (char *) to, (char *) body);
2128 		}
2129 	}
2130   end:
2131 	switch_safe_free(user);
2132 	switch_safe_free(f_user);
2133 	return SWITCH_STATUS_SUCCESS;
2134 }
2135 
compat_chat_send(const char * proto,const char * from,const char * to,const char * subject,const char * body,const char * type,const char * hint)2136 static switch_status_t compat_chat_send(const char *proto, const char *from, const char *to,
2137                                                                                 const char *subject, const char *body, const char *type, const char *hint)
2138 {
2139         switch_event_t *message_event;
2140         switch_status_t status;
2141 
2142         if (switch_event_create(&message_event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
2143                 switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto);
2144                 switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from);
2145                 switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to);
2146                 switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject);
2147                 switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type);
2148                 switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint);
2149 
2150                 if (body) {
2151                         switch_event_add_body(message_event, "%s", body);
2152                 }
2153         } else {
2154                 abort();
2155         }
2156 
2157         status = chat_send(message_event);
2158         switch_event_destroy(&message_event);
2159 
2160         return status;
2161 
2162 }
2163 
SWITCH_MODULE_LOAD_FUNCTION(mod_gsmopen_load)2164 SWITCH_MODULE_LOAD_FUNCTION(mod_gsmopen_load)
2165 {
2166 	switch_api_interface_t *commands_api_interface;
2167 	switch_chat_interface_t *chat_interface;
2168 
2169 	gsmopen_module_pool = pool;
2170 	memset(&globals, '\0', sizeof(globals));
2171 
2172 	running = 1;
2173 
2174 	if (load_config(FULL_RELOAD) != SWITCH_STATUS_SUCCESS) {
2175 		running = 0;
2176 		return SWITCH_STATUS_FALSE;
2177 	}
2178 
2179 	if (switch_event_reserve_subclass(MY_EVENT_INCOMING_SMS) != SWITCH_STATUS_SUCCESS) {
2180 		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n");
2181 		return SWITCH_STATUS_GENERR;
2182 	}
2183 
2184 	*module_interface = switch_loadable_module_create_module_interface(pool, modname);
2185 	gsmopen_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE);
2186 	gsmopen_endpoint_interface->interface_name = "gsmopen";
2187 	gsmopen_endpoint_interface->io_routines = &gsmopen_io_routines;
2188 	gsmopen_endpoint_interface->state_handler = &gsmopen_state_handlers;
2189 
2190 	if (running) {
2191 
2192 #if 1
2193 		SWITCH_ADD_API(commands_api_interface, "gsm", "gsm console AT_command", gsm_function, GSM_SYNTAX);
2194 		SWITCH_ADD_API(commands_api_interface, "gsmopen", "gsmopen interface AT_command", gsmopen_function, GSMOPEN_SYNTAX);
2195 #endif //0
2196 		SWITCH_ADD_API(commands_api_interface, "gsmopen_boost_audio", "gsmopen_boost_audio interface AT_command", gsmopen_boost_audio_function, GSMOPEN_BOOST_AUDIO_SYNTAX);
2197 		SWITCH_ADD_API(commands_api_interface, "gsmopen_dump", "gsmopen_dump interface", gsmopen_dump_function, GSMOPEN_DUMP_SYNTAX);
2198 		SWITCH_ADD_API(commands_api_interface, "gsmopen_sendsms", "gsmopen_sendsms interface destination_number SMS_text", sendsms_function,
2199 					   SENDSMS_SYNTAX);
2200 		SWITCH_ADD_CHAT(chat_interface, GSMOPEN_CHAT_PROTO, chat_send);
2201 
2202 		/* indicate that the module should continue to be loaded */
2203 		return SWITCH_STATUS_SUCCESS;
2204 	} else
2205 		return SWITCH_STATUS_FALSE;
2206 }
2207 
SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_gsmopen_shutdown)2208 SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_gsmopen_shutdown)
2209 {
2210 	int x;
2211 	private_t *tech_pvt = NULL;
2212 	switch_status_t status;
2213 	unsigned int howmany = 8;
2214 	int interface_id;
2215 	int fd;
2216 
2217 	running = 0;
2218 
2219 	for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) {
2220 		tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id];
2221 
2222 		if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) {
2223 			WARNINGA("SHUTDOWN interface_id=%d\n", GSMOPEN_P_LOG, interface_id);
2224 			globals.GSMOPEN_INTERFACES[interface_id].running = 0;
2225 			if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) {
2226 #ifdef WIN32
2227 				switch_file_write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", &howmany);	// let's the controldev_thread die
2228 #else /* WIN32 */
2229 				howmany = write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", howmany);
2230 #endif /* WIN32 */
2231 			}
2232 			x = 10;
2233 			while (x) {			//FIXME 0.5 seconds?
2234 				x--;
2235 				switch_yield(50000);
2236 			}
2237 			if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) {
2238 				switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread);
2239 			}
2240 			if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread) {
2241 				switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread);
2242 			}
2243 
2244 			x = 10;
2245 			while (x) {			//FIXME 0.5 seconds?
2246 				x--;
2247 				switch_yield(50000);
2248 			}
2249 			fd = tech_pvt->controldevfd;
2250 			//DEBUGA_GSMOPEN("SHUTDOWN tech_pvt->controldevfd=%d\n", GSMOPEN_P_LOG, tech_pvt->controldevfd);
2251 			if (fd) {
2252 				//close(fd);
2253 				//tech_pvt->controldevfd = -1;
2254 				DEBUGA_GSMOPEN("SHUTDOWN tech_pvt->controldevfd=%d\n", GSMOPEN_P_LOG, tech_pvt->controldevfd);
2255 			}
2256 #ifndef WIN32
2257 			shutdown(tech_pvt->audiogsmopenpipe[0], 2);
2258 			close(tech_pvt->audiogsmopenpipe[0]);
2259 			shutdown(tech_pvt->audiogsmopenpipe[1], 2);
2260 			close(tech_pvt->audiogsmopenpipe[1]);
2261 			shutdown(tech_pvt->audiopipe[0], 2);
2262 			close(tech_pvt->audiopipe[0]);
2263 			shutdown(tech_pvt->audiopipe[1], 2);
2264 			close(tech_pvt->audiopipe[1]);
2265 			shutdown(tech_pvt->GSMopenHandles.fdesc[0], 2);
2266 			close(tech_pvt->GSMopenHandles.fdesc[0]);
2267 			shutdown(tech_pvt->GSMopenHandles.fdesc[1], 2);
2268 			close(tech_pvt->GSMopenHandles.fdesc[1]);
2269 #endif /* WIN32 */
2270 		}
2271 
2272 	}
2273 
2274 	switch_event_free_subclass(MY_EVENT_INCOMING_SMS);
2275 
2276 	switch_safe_free(globals.dialplan);
2277 	switch_safe_free(globals.context);
2278 	switch_safe_free(globals.destination);
2279 	switch_safe_free(globals.codec_string);
2280 	switch_safe_free(globals.codec_rates_string);
2281 
2282 	return SWITCH_STATUS_SUCCESS;
2283 }
2284 
2285 
gsmopen_do_gsmopenapi_thread(switch_thread_t * thread,void * obj)2286 void *SWITCH_THREAD_FUNC gsmopen_do_gsmopenapi_thread(switch_thread_t * thread, void *obj)
2287 {
2288 	return gsmopen_do_gsmopenapi_thread_func(obj);
2289 }
2290 
dtmf_received(private_t * tech_pvt,char * value)2291 int dtmf_received(private_t * tech_pvt, char *value)
2292 {
2293 	switch_core_session_t *session = NULL;
2294 	switch_channel_t *channel = NULL;
2295 
2296 	session = switch_core_session_locate(tech_pvt->session_uuid_str);
2297 	channel = switch_core_session_get_channel(session);
2298 
2299 	if (channel) {
2300 
2301 		if (!switch_channel_test_flag(channel, CF_BRIDGED)) {
2302 
2303 			switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) };
2304 			DEBUGA_GSMOPEN("received DTMF %c on channel %s\n", GSMOPEN_P_LOG, dtmf.digit, switch_channel_get_name(channel));
2305 			switch_mutex_lock(tech_pvt->flag_mutex);
2306 			//FIXME: why sometimes DTMFs from here do not seems to be get by FS?
2307 			switch_channel_queue_dtmf(channel, &dtmf);
2308 			switch_set_flag(tech_pvt, TFLAG_DTMF);
2309 			switch_mutex_unlock(tech_pvt->flag_mutex);
2310 		} else {
2311 			DEBUGA_GSMOPEN
2312 				("received a DTMF on channel %s, but we're BRIDGED, so let's NOT relay it out of band\n", GSMOPEN_P_LOG, switch_channel_get_name(channel));
2313 		}
2314 	} else {
2315 		WARNINGA("received %c DTMF, but no channel?\n", GSMOPEN_P_LOG, value[0]);
2316 	}
2317 	switch_core_session_rwunlock(session);
2318 
2319 	return 0;
2320 }
2321 
new_inbound_channel(private_t * tech_pvt)2322 int new_inbound_channel(private_t * tech_pvt)
2323 {
2324 	switch_core_session_t *session = NULL;
2325 	switch_channel_t *channel = NULL;
2326 
2327 	switch_assert(tech_pvt != NULL);
2328 	tech_pvt->ib_calls++;
2329 	if ((session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL)) != 0) {
2330 		DEBUGA_GSMOPEN("2 SESSION_REQUEST %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(session));
2331 		switch_core_session_add_stream(session, NULL);
2332 		channel = switch_core_session_get_channel(session);
2333 		if (!channel) {
2334 			ERRORA("Doh! no channel?\n", GSMOPEN_P_LOG);
2335 			switch_core_session_destroy(&session);
2336 			return 0;
2337 		}
2338 		if (gsmopen_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) {
2339 			ERRORA("Doh! no tech_init?\n", GSMOPEN_P_LOG);
2340 			switch_core_session_destroy(&session);
2341 			return 0;
2342 		}
2343 
2344 		if ((tech_pvt->caller_profile =
2345 			 switch_caller_profile_new(switch_core_session_get_pool(session), "gsmopen",
2346 									   tech_pvt->dialplan, tech_pvt->callid_name,
2347 									   tech_pvt->callid_number, NULL, NULL, NULL, NULL, "mod_gsmopen", tech_pvt->context, tech_pvt->destination)) != 0) {
2348 			char name[128];
2349 			//switch_snprintf(name, sizeof(name), "gsmopen/%s/%s", tech_pvt->name, tech_pvt->caller_profile->destination_number);
2350 			switch_snprintf(name, sizeof(name), "gsmopen/%s", tech_pvt->name);
2351 			switch_channel_set_name(channel, name);
2352 			switch_channel_set_caller_profile(channel, tech_pvt->caller_profile);
2353 		}
2354 		switch_channel_set_state(channel, CS_INIT);
2355 		if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) {
2356 			ERRORA("Error spawning thread\n", GSMOPEN_P_LOG);
2357 			switch_core_session_destroy(&session);
2358 			return 0;
2359 		}
2360 	}
2361 	if (channel) {
2362 		//switch_channel_mark_answered(channel);
2363 	}
2364 
2365 	DEBUGA_GSMOPEN("new_inbound_channel\n", GSMOPEN_P_LOG);
2366 
2367 	return 0;
2368 }
2369 
remote_party_is_ringing(private_t * tech_pvt)2370 int remote_party_is_ringing(private_t * tech_pvt)
2371 {
2372 	switch_core_session_t *session = NULL;
2373 	switch_channel_t *channel = NULL;
2374 
2375 	if (!zstr(tech_pvt->session_uuid_str)) {
2376 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2377 	} else {
2378 		ERRORA("No session???\n", GSMOPEN_P_LOG);
2379 		goto done;
2380 	}
2381 	if (session) {
2382 		channel = switch_core_session_get_channel(session);
2383 	} else {
2384 		ERRORA("No session???\n", GSMOPEN_P_LOG);
2385 		goto done;
2386 	}
2387 	if (channel) {
2388 		switch_channel_mark_ring_ready(channel);
2389 		DEBUGA_GSMOPEN("gsmopen_call: REMOTE PARTY RINGING\n", GSMOPEN_P_LOG);
2390 	} else {
2391 		ERRORA("No channel???\n", GSMOPEN_P_LOG);
2392 	}
2393 
2394 	switch_core_session_rwunlock(session);
2395 
2396   done:
2397 	return 0;
2398 }
2399 
remote_party_is_early_media(private_t * tech_pvt)2400 int remote_party_is_early_media(private_t * tech_pvt)
2401 {
2402 	switch_core_session_t *session = NULL;
2403 	switch_channel_t *channel = NULL;
2404 
2405 	if (!zstr(tech_pvt->session_uuid_str)) {
2406 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2407 	} else {
2408 		ERRORA("No session???\n\n\n", GSMOPEN_P_LOG);
2409 		//TODO: kill the bastard
2410 		goto done;
2411 	}
2412 	if (session) {
2413 		channel = switch_core_session_get_channel(session);
2414 		switch_core_session_add_stream(session, NULL);
2415 	} else {
2416 		ERRORA("No session???\n", GSMOPEN_P_LOG);
2417 		//TODO: kill the bastard
2418 		goto done;
2419 	}
2420 	if (channel) {
2421 		switch_channel_mark_pre_answered(channel);
2422 		DEBUGA_GSMOPEN("gsmopen_call: REMOTE PARTY EARLY MEDIA\n", GSMOPEN_P_LOG);
2423 	} else {
2424 		ERRORA("No channel???\n", GSMOPEN_P_LOG);
2425 		//TODO: kill the bastard
2426 	}
2427 
2428 	switch_core_session_rwunlock(session);
2429 
2430   done:
2431 	return 0;
2432 }
2433 
outbound_channel_answered(private_t * tech_pvt)2434 int outbound_channel_answered(private_t * tech_pvt)
2435 {
2436 	switch_core_session_t *session = NULL;
2437 	switch_channel_t *channel = NULL;
2438 
2439 	if (!zstr(tech_pvt->session_uuid_str)) {
2440 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
2441 	} else {
2442 		ERRORA("No session???\n", GSMOPEN_P_LOG);
2443 		goto done;
2444 	}
2445 	if (session) {
2446 		channel = switch_core_session_get_channel(session);
2447 	} else {
2448 		ERRORA("No channel???\n", GSMOPEN_P_LOG);
2449 		goto done;
2450 	}
2451 	if (channel) {
2452 		switch_channel_mark_answered(channel);
2453 		tech_pvt->phone_callflow = GSMOPEN_STATE_UP;
2454 		tech_pvt->interface_state = GSMOPEN_STATE_UP;
2455 		//DEBUGA_GSMOPEN("gsmopen_call: %s, answered\n", GSMOPEN_P_LOG, id);
2456 	} else {
2457 		ERRORA("No channel???\n", GSMOPEN_P_LOG);
2458 	}
2459 
2460 	switch_core_session_rwunlock(session);
2461 
2462   done:
2463 	DEBUGA_GSMOPEN("outbound_channel_answered!\n", GSMOPEN_P_LOG);
2464 
2465 	return 0;
2466 }
2467 
find_available_gsmopen_interface_rr(private_t * tech_pvt_calling)2468 private_t *find_available_gsmopen_interface_rr(private_t * tech_pvt_calling)
2469 {
2470 	private_t *tech_pvt = NULL;
2471 	int i;
2472 	//int num_interfaces = GSMOPEN_MAX_INTERFACES;
2473 	//int num_interfaces = globals.real_interfaces;
2474 
2475 	switch_mutex_lock(globals.mutex);
2476 
2477 	/* Fact is the real interface start from 1 */
2478 	//XXX no, is just a convention, but you can have it start from 0. I do not, for aestetic reasons :-)
2479 	//if (globals.next_interface == 0) globals.next_interface = 1;
2480 
2481 	for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) {
2482 		int interface_id;
2483 
2484 		interface_id = globals.next_interface;
2485 		//interface_id = interface_id < GSMOPEN_MAX_INTERFACES ? interface_id : interface_id - GSMOPEN_MAX_INTERFACES + 1;
2486 		globals.next_interface = interface_id + 1 < GSMOPEN_MAX_INTERFACES ? interface_id + 1 : 0;
2487 
2488 		if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) {
2489 			int gsmopen_state = 0;
2490 
2491 			tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id];
2492 			gsmopen_state = tech_pvt->interface_state;
2493 			DEBUGA_GSMOPEN("gsmopen interface: %d, name: %s, state: %d\n", GSMOPEN_P_LOG, interface_id, globals.GSMOPEN_INTERFACES[interface_id].name,
2494 						   gsmopen_state);
2495 			if ((tech_pvt_calling ? strcmp(tech_pvt->gsmopen_user, tech_pvt_calling->gsmopen_user) : 1)
2496 				&& (GSMOPEN_STATE_DOWN == gsmopen_state || 0 == gsmopen_state) && (tech_pvt->phone_callflow == CALLFLOW_STATUS_FINISHED
2497 																				   || 0 == tech_pvt->phone_callflow)) {
2498 				DEBUGA_GSMOPEN("returning as available gsmopen interface name: %s, state: %d callflow: %d\n", GSMOPEN_P_LOG, tech_pvt->name, gsmopen_state,
2499 							   tech_pvt->phone_callflow);
2500 				/*set to Dialing state to avoid other thread fint it, don't know if it is safe */
2501 				//XXX no, it's not safe
2502 				if (tech_pvt_calling == NULL) {
2503 					tech_pvt->interface_state = GSMOPEN_STATE_SELECTED;
2504 				}
2505 
2506 				switch_mutex_unlock(globals.mutex);
2507 				return tech_pvt;
2508 			}
2509 		}						// else {
2510 		//DEBUGA_GSMOPEN("GSM interface: %d blank!! A hole here means we cannot hunt the last interface.\n", GSMOPEN_P_LOG, interface_id);
2511 		//}
2512 	}
2513 
2514 	switch_mutex_unlock(globals.mutex);
2515 	return NULL;
2516 }
2517 
2518 #if 1
SWITCH_STANDARD_API(gsm_function)2519 SWITCH_STANDARD_API(gsm_function)
2520 {
2521 	char *mycmd = NULL, *argv[10] = { 0 };
2522 	int argc = 0;
2523 
2524 	if (globals.gsm_console)
2525 		stream->write_function(stream, "gsm console is: |||%s|||\n", globals.gsm_console->name);
2526 	else
2527 		stream->write_function(stream, "gsm console is NOT yet assigned\n");
2528 
2529 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
2530 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2531 	}
2532 
2533 	if (!argc || !argv[0]) {
2534 		stream->write_function(stream, "%s", GSM_SYNTAX);
2535 		goto end;
2536 	}
2537 
2538 	if (!strcasecmp(argv[0], "list")) {
2539 		int i;
2540 		char next_flag_char = ' ';
2541 
2542 		stream->write_function(stream, "F ID\t    Name    \tIB (F/T)    OB (F/T)\tState\tCallFlw\t\tUUID\n");
2543 		stream->write_function(stream, "= ====\t  ========  \t=======     =======\t======\t============\t======\n");
2544 
2545 		for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) {
2546 			next_flag_char = i == globals.next_interface ? '*' : ' ';
2547 
2548 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)) {
2549 				stream->write_function(stream,
2550 									   "%c %d\t[%s]\t%3ld/%ld\t%6ld/%ld\t%s\t%s\t%s\n",
2551 									   next_flag_char,
2552 									   i, globals.GSMOPEN_INTERFACES[i].name,
2553 									   globals.GSMOPEN_INTERFACES[i].ib_failed_calls,
2554 									   globals.GSMOPEN_INTERFACES[i].ib_calls,
2555 									   globals.GSMOPEN_INTERFACES[i].ob_failed_calls,
2556 									   globals.GSMOPEN_INTERFACES[i].ob_calls,
2557 									   interface_status[globals.GSMOPEN_INTERFACES[i].interface_state],
2558 									   phone_callflow[globals.GSMOPEN_INTERFACES[i].phone_callflow], globals.GSMOPEN_INTERFACES[i].session_uuid_str);
2559 			} else if (argc > 1 && !strcasecmp(argv[1], "full")) {
2560 				stream->write_function(stream, "%c\t%d\n", next_flag_char, i);
2561 			}
2562 
2563 		}
2564 		stream->write_function(stream, "\nTotal: %d\n", globals.real_interfaces - 1);
2565 
2566 	} else if (!strcasecmp(argv[0], "console")) {
2567 		int i;
2568 		int found = 0;
2569 
2570 		if (argc == 2) {
2571 			for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2572 				/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
2573 				if (strlen(globals.GSMOPEN_INTERFACES[i].name)
2574 					&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) {
2575 					globals.gsm_console = &globals.GSMOPEN_INTERFACES[i];
2576 					stream->write_function(stream, "gsm console is now: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i,
2577 										   globals.GSMOPEN_INTERFACES[i].name);
2578 					stream->write_function(stream, "gsm console is: |||%s|||\n", globals.gsm_console->name);
2579 					found = 1;
2580 					break;
2581 				}
2582 
2583 			}
2584 			if (!found)
2585 				stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[1]);
2586 		} else {
2587 
2588 			stream->write_function(stream, "-ERR Usage: gsm console interface_name\n");
2589 			goto end;
2590 		}
2591 
2592 	} else if (!strcasecmp(argv[0], "ciapalino")) {
2593 
2594 /* BEGIN: Changes heres */
2595 	} else if (!strcasecmp(argv[0], "reload")) {
2596 		if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) {
2597 			stream->write_function(stream, "gsm reload failed\n");
2598 		} else {
2599 			stream->write_function(stream, "gsm reload success\n");
2600 		}
2601 	} else if (!strcasecmp(argv[0], "remove")) {
2602 		if (argc == 2) {
2603 			if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) {
2604 				if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) {
2605 					stream->write_function(stream, "gsm remove '%s' failed\n", argv[1]);
2606 				} else {
2607 					stream->write_function(stream, "gsm remove '%s' success\n", argv[1]);
2608 				}
2609 			}
2610 		} else {
2611 			stream->write_function(stream, "-ERR Usage: gsm remove interface_name\n");
2612 			goto end;
2613 		}
2614 /* END: Changes heres */
2615 
2616 	} else {
2617 		if (globals.gsm_console)
2618 			gsmopen_serial_write_AT_noack(globals.gsm_console, (char *) cmd);
2619 		else
2620 			stream->write_function(stream, "gsm console is NOT yet assigned\n");
2621 	}
2622   end:
2623 	switch_safe_free(mycmd);
2624 
2625 	return SWITCH_STATUS_SUCCESS;
2626 }
2627 
SWITCH_STANDARD_API(gsmopen_function)2628 SWITCH_STANDARD_API(gsmopen_function)
2629 {
2630 	char *mycmd = NULL, *argv[10] = { 0 };
2631 	int argc = 0;
2632 	private_t *tech_pvt = NULL;
2633 
2634 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
2635 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2636 	}
2637 
2638 	if (!argc) {
2639 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_SYNTAX);
2640 		goto end;
2641 	}
2642 
2643 	if (argc < 2) {
2644 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_SYNTAX);
2645 		goto end;
2646 	}
2647 
2648 	if (argv[0]) {
2649 		int i;
2650 		int found = 0;
2651 
2652 		for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2653 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
2654 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)
2655 				&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
2656 				tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2657 				stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name);
2658 				found = 1;
2659 				break;
2660 			}
2661 
2662 		}
2663 		if (!found) {
2664 			stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]);
2665 			switch_safe_free(mycmd);
2666 
2667 			return SWITCH_STATUS_SUCCESS;
2668 		} else {
2669 			gsmopen_serial_write_AT_noack(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]);
2670 		}
2671 	} else {
2672 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_SYNTAX);
2673 	}
2674   end:
2675 	switch_safe_free(mycmd);
2676 
2677 	return SWITCH_STATUS_SUCCESS;
2678 }
2679 #endif //0
SWITCH_STANDARD_API(gsmopen_dump_function)2680 SWITCH_STANDARD_API(gsmopen_dump_function)
2681 {
2682 	char *mycmd = NULL, *argv[10] = { 0 };
2683 	int argc = 0;
2684 	private_t *tech_pvt = NULL;
2685 	char value[512];
2686 
2687 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
2688 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2689 	}
2690 
2691 	if (!argc) {
2692 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_DUMP_SYNTAX);
2693 		goto end;
2694 	}
2695 	if (argc == 1) {
2696 		int i;
2697 		int found = 0;
2698 
2699 		for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2700 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
2701 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)
2702 					&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
2703 				tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2704 				//stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name);
2705 				found = 1;
2706 				break;
2707 			}
2708 
2709 		}
2710 		if (!found && (strcmp("list", argv[0]) == 0)) {
2711 			int i;
2712 			stream->write_function(stream, "gsmopen_dump LIST\n\n");
2713 			for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) {
2714 				if (strlen(globals.GSMOPEN_INTERFACES[i].name)) {
2715 					stream->write_function(stream, "dumping interface '%s'\n\n", globals.GSMOPEN_INTERFACES[i].name);
2716 					tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2717 
2718 
2719 					stream->write_function(stream, "interface_name = %s\n", tech_pvt->name);
2720 					stream->write_function(stream, "interface_id = %s\n", tech_pvt->id);
2721 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->active);
2722 					stream->write_function(stream, "active = %s\n", value);
2723 					if(!tech_pvt->network_creg_not_supported){
2724 						snprintf(value, sizeof(value)-1, "%d", tech_pvt->not_registered);
2725 						stream->write_function(stream, "not_registered = %s\n", value);
2726 						snprintf(value, sizeof(value)-1, "%d", tech_pvt->home_network_registered);
2727 						stream->write_function(stream, "home_network_registered = %s\n", value);
2728 						snprintf(value, sizeof(value)-1, "%d", tech_pvt->roaming_registered);
2729 						stream->write_function(stream, "roaming_registered = %s\n", value);
2730 					}else{
2731 						stream->write_function(stream, "not_registered = %s\n", "N/A");
2732 						stream->write_function(stream, "home_network_registered = %s\n", "N/A");
2733 						stream->write_function(stream, "roaming_registered = %s\n", "N/A");
2734 					}
2735 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->got_signal);
2736 					stream->write_function(stream, "got_signal = %s\n", value);
2737 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->running);
2738 					stream->write_function(stream, "running = %s\n", value);
2739 					stream->write_function(stream, "imei = %s\n", tech_pvt->imei);
2740 					stream->write_function(stream, "imsi = %s\n", tech_pvt->imsi);
2741 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->controldev_dead);
2742 					stream->write_function(stream, "controldev_dead = %s\n", value);
2743 					stream->write_function(stream, "controldevice_name = %s\n", tech_pvt->controldevice_name);
2744 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->no_sound);
2745 					stream->write_function(stream, "no_sound = %s\n", value);
2746 #ifdef GSMOPEN_ALSA
2747 					stream->write_function(stream, "alsacname = %s\n", tech_pvt->alsacname);
2748 					stream->write_function(stream, "alsapname = %s\n", tech_pvt->alsapname);
2749 #endif// GSMOPEN_ALSA
2750 #ifdef GSMOPEN_PORTAUDIO
2751 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->portaudiocindex);
2752 					stream->write_function(stream, "portaudiocindex = %s\n", value);
2753 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->portaudiopindex);
2754 					stream->write_function(stream, "portaudiopindex = %s\n", value);
2755 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->speexecho);
2756 					stream->write_function(stream, "speexecho = %s\n", value);
2757 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->speexpreprocess);
2758 					stream->write_function(stream, "speexpreprocess = %s\n", value);
2759 #endif// GSMOPEN_PORTAUDIO
2760 					snprintf(value, sizeof(value)-1, "%f", tech_pvt->playback_boost);
2761 					stream->write_function(stream, "playback_boost = %s\n", value);
2762 					snprintf(value, sizeof(value)-1, "%f", tech_pvt->capture_boost);
2763 					stream->write_function(stream, "capture_boost = %s\n", value);
2764 					stream->write_function(stream, "dialplan = %s\n", tech_pvt->dialplan);
2765 					stream->write_function(stream, "context = %s\n", tech_pvt->context);
2766 					stream->write_function(stream, "destination = %s\n", tech_pvt->destination);
2767 					snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ib_calls);
2768 					stream->write_function(stream, "ib_calls = %s\n", value);
2769 					snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ob_calls);
2770 					stream->write_function(stream, "ob_calls = %s\n", value);
2771 					snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ib_failed_calls);
2772 					stream->write_function(stream, "ib_failed_calls = %s\n", value);
2773 					snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ob_failed_calls);
2774 					stream->write_function(stream, "ob_failed_calls = %s\n", value);
2775 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->interface_state);
2776 					stream->write_function(stream, "interface_state = %s\n", value);
2777 					snprintf(value, sizeof(value)-1, "%d", tech_pvt->phone_callflow);
2778 					stream->write_function(stream, "phone_callflow = %s\n", value);
2779 					stream->write_function(stream, "session_uuid_str = %s\n", tech_pvt->session_uuid_str);
2780 					stream->write_function(stream, "\n");
2781 
2782 					dump_event(tech_pvt);
2783 				}
2784 
2785 			}
2786 
2787 		} else if(found){
2788 			stream->write_function(stream, "dumping interface '%s'\n\n", argv[0]);
2789 			tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2790 
2791 
2792 			stream->write_function(stream, "interface_name = %s\n", tech_pvt->name);
2793 			stream->write_function(stream, "interface_id = %s\n", tech_pvt->id);
2794 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->active);
2795 			stream->write_function(stream, "active = %s\n", value);
2796 			if(!tech_pvt->network_creg_not_supported){
2797 				snprintf(value, sizeof(value)-1, "%d", tech_pvt->not_registered);
2798 				stream->write_function(stream, "not_registered = %s\n", value);
2799 				snprintf(value, sizeof(value)-1, "%d", tech_pvt->home_network_registered);
2800 				stream->write_function(stream, "home_network_registered = %s\n", value);
2801 				snprintf(value, sizeof(value)-1, "%d", tech_pvt->roaming_registered);
2802 				stream->write_function(stream, "roaming_registered = %s\n", value);
2803 			}else{
2804 				stream->write_function(stream, "not_registered = %s\n", "N/A");
2805 				stream->write_function(stream, "home_network_registered = %s\n", "N/A");
2806 				stream->write_function(stream, "roaming_registered = %s\n", "N/A");
2807 			}
2808 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->got_signal);
2809 			stream->write_function(stream, "got_signal = %s\n", value);
2810 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->running);
2811 			stream->write_function(stream, "running = %s\n", value);
2812 			stream->write_function(stream, "imei = %s\n", tech_pvt->imei);
2813 			stream->write_function(stream, "imsi = %s\n", tech_pvt->imsi);
2814 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->controldev_dead);
2815 			stream->write_function(stream, "controldev_dead = %s\n", value);
2816 			stream->write_function(stream, "controldevice_name = %s\n", tech_pvt->controldevice_name);
2817 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->no_sound);
2818 			stream->write_function(stream, "no_sound = %s\n", value);
2819 #ifdef GSMOPEN_ALSA
2820 			stream->write_function(stream, "alsacname = %s\n", tech_pvt->alsacname);
2821 			stream->write_function(stream, "alsapname = %s\n", tech_pvt->alsapname);
2822 #endif// GSMOPEN_ALSA
2823 #ifdef GSMOPEN_PORTAUDIO
2824 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->portaudiocindex);
2825 			stream->write_function(stream, "portaudiocindex = %s\n", value);
2826 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->portaudiopindex);
2827 			stream->write_function(stream, "portaudiopindex = %s\n", value);
2828 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->speexecho);
2829 			stream->write_function(stream, "speexecho = %s\n", value);
2830 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->speexpreprocess);
2831 			stream->write_function(stream, "speexpreprocess = %s\n", value);
2832 #endif// GSMOPEN_PORTAUDIO
2833 			snprintf(value, sizeof(value)-1, "%f", tech_pvt->playback_boost);
2834 			stream->write_function(stream, "playback_boost = %s\n", value);
2835 			snprintf(value, sizeof(value)-1, "%f", tech_pvt->capture_boost);
2836 			stream->write_function(stream, "capture_boost = %s\n", value);
2837 			stream->write_function(stream, "dialplan = %s\n", tech_pvt->dialplan);
2838 			stream->write_function(stream, "context = %s\n", tech_pvt->context);
2839 			stream->write_function(stream, "destination = %s\n", tech_pvt->destination);
2840 			snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ib_calls);
2841 			stream->write_function(stream, "ib_calls = %s\n", value);
2842 			snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ob_calls);
2843 			stream->write_function(stream, "ob_calls = %s\n", value);
2844 			snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ib_failed_calls);
2845 			stream->write_function(stream, "ib_failed_calls = %s\n", value);
2846 			snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ob_failed_calls);
2847 			stream->write_function(stream, "ob_failed_calls = %s\n", value);
2848 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->interface_state);
2849 			stream->write_function(stream, "interface_state = %s\n", value);
2850 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->phone_callflow);
2851 			stream->write_function(stream, "phone_callflow = %s\n", value);
2852 			stream->write_function(stream, "session_uuid_str = %s\n", tech_pvt->session_uuid_str);
2853 			stream->write_function(stream, "\n");
2854 
2855 			dump_event(tech_pvt);
2856 		} else{
2857 			stream->write_function(stream, "interface '%s' was not found\n", argv[0]);
2858 		}
2859 	} else {
2860 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_DUMP_SYNTAX);
2861 	}
2862 end:
2863 	switch_safe_free(mycmd);
2864 
2865 	return SWITCH_STATUS_SUCCESS;
2866 }
SWITCH_STANDARD_API(gsmopen_boost_audio_function)2867 SWITCH_STANDARD_API(gsmopen_boost_audio_function)
2868 {
2869 	char *mycmd = NULL, *argv[10] = { 0 };
2870 	int argc = 0;
2871 	//private_t *tech_pvt;
2872 
2873 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
2874 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
2875 	}
2876 
2877 	if (argc == 1 || argc==3) {
2878 		int i;
2879 		int found = 0;
2880 
2881 		for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2882 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
2883 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)
2884 					&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
2885 				//tech_pvt = &globals.GSMOPEN_INTERFACES[i];
2886 				stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name);
2887 				found = 1;
2888 				break;
2889 			}
2890 
2891 		}
2892 		if (!found) {
2893 			stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]);
2894 
2895 		} else {
2896 			if (argc == 1) {
2897 				stream->write_function(stream,"[%s] capture boost is %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].capture_boost);
2898 				stream->write_function(stream,"[%s] playback boost is %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].playback_boost);
2899 				stream->write_function(stream, "%s usage: %s", argv[0], GSMOPEN_BOOST_AUDIO_SYNTAX);
2900 				goto end;
2901 			} else if ((strncmp("play", argv[1], strlen(argv[1])) == 0)) {
2902 				if (switch_is_number(argv[2])) {
2903 					stream->write_function(stream,"[%s] playback boost was %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].playback_boost);
2904 					gsmopen_store_boost(argv[2], &globals.GSMOPEN_INTERFACES[i].playback_boost);	//FIXME
2905 					stream->write_function(stream,"[%s] playback boost is now %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].playback_boost);
2906 				}
2907 			}else if ((strncmp("capt", argv[1], strlen(argv[1])) == 0)) {
2908 				if (switch_is_number(argv[2])) {
2909 					stream->write_function(stream,"[%s] capture boost was %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].capture_boost);
2910 					gsmopen_store_boost(argv[2], &globals.GSMOPEN_INTERFACES[i].capture_boost);	//FIXME
2911 					stream->write_function(stream,"[%s] capture boost is now %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].capture_boost);
2912 				}
2913 			} else {
2914 				stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_BOOST_AUDIO_SYNTAX);
2915 			}
2916 		}
2917 	} else {
2918 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_BOOST_AUDIO_SYNTAX);
2919 	}
2920   end:
2921 	switch_safe_free(mycmd);
2922 
2923 	return SWITCH_STATUS_SUCCESS;
2924 }
2925 
2926 
2927 #if 0
2928 int gsmopen_transfer(private_t * tech_pvt, char *id, char *value)
2929 {
2930 	char msg_to_gsmopen[1024];
2931 	int i;
2932 	int found = 0;
2933 	private_t *giovatech;
2934 	struct timeval timenow;
2935 
2936 	switch_mutex_lock(globals.mutex);
2937 
2938 	gettimeofday(&timenow, NULL);
2939 	for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2940 		if (strlen(globals.GSMOPEN_INTERFACES[i].name)) {
2941 
2942 			giovatech = &globals.GSMOPEN_INTERFACES[i];
2943 			//NOTICA("gsmopen interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->gsmopen_user=%s\n", GSMOPEN_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->gsmopen_user);
2944 			//FIXME check a timestamp here
2945 			if (strlen(giovatech->gsmopen_call_id) && (giovatech->interface_state != GSMOPEN_STATE_DOWN) && (!strcmp(giovatech->gsmopen_user, tech_pvt->gsmopen_user)) && (!strcmp(giovatech->callid_number, value)) && ((((timenow.tv_sec - giovatech->answer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->answer_time.tv_usec)) < 500000)) {	//0.5sec
2946 				found = 1;
2947 				DEBUGA_GSMOPEN
2948 					("FOUND  (name=%s, giovatech->interface_state=%d != GSMOPEN_STATE_DOWN) && (giovatech->gsmopen_user=%s == tech_pvt->gsmopen_user=%s) && (giovatech->callid_number=%s == value=%s)\n",
2949 					 GSMOPEN_P_LOG, giovatech->name, giovatech->interface_state, giovatech->gsmopen_user, tech_pvt->gsmopen_user, giovatech->callid_number,
2950 					 value)
2951 					break;
2952 			}
2953 		}
2954 	}
2955 
2956 	if (found) {
2957 		//tech_pvt->callid_number[0]='\0';
2958 		//sprintf(msg_to_gsmopen, "ALTER CALL %s END HANGUP", id);
2959 		//gsmopen_signaling_write(tech_pvt, msg_to_gsmopen);
2960 		switch_mutex_unlock(globals.mutex);
2961 		return 0;
2962 	}
2963 	DEBUGA_GSMOPEN("NOT FOUND\n", GSMOPEN_P_LOG);
2964 
2965 	if (!tech_pvt || !tech_pvt->gsmopen_call_id || !strlen(tech_pvt->gsmopen_call_id)) {
2966 		/* we are not inside an active call */
2967 		DEBUGA_GSMOPEN("We're NO MORE in a call now %s\n", GSMOPEN_P_LOG, (tech_pvt && tech_pvt->gsmopen_call_id) ? tech_pvt->gsmopen_call_id : "");
2968 		switch_mutex_unlock(globals.mutex);
2969 
2970 	} else {
2971 
2972 		/* we're owned, we're in a call, let's try to transfer */
2973 		/************************** TODO
2974 		  Checking here if it is possible to transfer this call to Test2
2975 		  -> GET CALL 288 CAN_TRANSFER Test2
2976 		  <- CALL 288 CAN_TRANSFER test2 TRUE
2977 		 **********************************/
2978 
2979 		private_t *available_gsmopen_interface = NULL;
2980 
2981 		gettimeofday(&timenow, NULL);
2982 		for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
2983 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)) {
2984 
2985 				giovatech = &globals.GSMOPEN_INTERFACES[i];
2986 				//NOTICA("gsmopen interface: %d, name: %s, state: %d, value=%s, giovatech->callid_number=%s, giovatech->gsmopen_user=%s\n", GSMOPEN_P_LOG, i, giovatech->name, giovatech->interface_state, value, giovatech->callid_number, giovatech->gsmopen_user);
2987 				//FIXME check a timestamp here
2988 				if (strlen(giovatech->gsmopen_transfer_call_id) && (giovatech->interface_state != GSMOPEN_STATE_DOWN) && (!strcmp(giovatech->gsmopen_user, tech_pvt->gsmopen_user)) && (!strcmp(giovatech->transfer_callid_number, value)) && ((((timenow.tv_sec - giovatech->transfer_time.tv_sec) * 1000000) + (timenow.tv_usec - giovatech->transfer_time.tv_usec)) < 1000000)) {	//1.0 sec
2989 					found = 1;
2990 					DEBUGA_GSMOPEN
2991 						("FOUND  (name=%s, giovatech->interface_state=%d != GSMOPEN_STATE_DOWN) && (giovatech->gsmopen_user=%s == tech_pvt->gsmopen_user=%s) && (giovatech->transfer_callid_number=%s == value=%s)\n",
2992 						 GSMOPEN_P_LOG, giovatech->name, giovatech->interface_state,
2993 						 giovatech->gsmopen_user, tech_pvt->gsmopen_user, giovatech->transfer_callid_number, value)
2994 						break;
2995 				}
2996 			}
2997 		}
2998 
2999 		if (found) {
3000 			//tech_pvt->callid_number[0]='\0';
3001 			//sprintf(msg_to_gsmopen, "ALTER CALL %s END HANGUP", id);
3002 			//gsmopen_signaling_write(tech_pvt, msg_to_gsmopen);
3003 			switch_mutex_unlock(globals.mutex);
3004 			return 0;
3005 		}
3006 		DEBUGA_GSMOPEN("NOT FOUND\n", GSMOPEN_P_LOG);
3007 
3008 		available_gsmopen_interface = find_available_gsmopen_interface_rr(tech_pvt);
3009 		if (available_gsmopen_interface) {
3010 			/* there is a gsmopen interface idle, let's transfer the call to it */
3011 
3012 			//FIXME write a timestamp here
3013 			gettimeofday(&tech_pvt->transfer_time, NULL);
3014 			switch_copy_string(tech_pvt->gsmopen_transfer_call_id, id, sizeof(tech_pvt->gsmopen_transfer_call_id) - 1);
3015 
3016 			switch_copy_string(tech_pvt->transfer_callid_number, value, sizeof(tech_pvt->transfer_callid_number) - 1);
3017 
3018 			DEBUGA_GSMOPEN
3019 				("Let's transfer the gsmopen_call %s to %s interface (with gsmopen_user: %s), because we are already in a gsmopen call(%s)\n",
3020 				 GSMOPEN_P_LOG, tech_pvt->gsmopen_call_id, available_gsmopen_interface->name, available_gsmopen_interface->gsmopen_user, id);
3021 
3022 			//FIXME why this? the inbound call will come, eventually, on that other interface
3023 			//available_gsmopen_interface->ib_calls++;
3024 
3025 			sprintf(msg_to_gsmopen, "ALTER CALL %s TRANSFER %s", id, available_gsmopen_interface->gsmopen_user);
3026 			//gsmopen_signaling_write(tech_pvt, msg_to_gsmopen);
3027 			if (tech_pvt->interface_state == GSMOPEN_STATE_SELECTED) {
3028 				tech_pvt->interface_state = GSMOPEN_STATE_IDLE;	//we marked it GSMOPEN_STATE_SELECTED just in case it has to make an outbound call
3029 			}
3030 		} else {
3031 			/* no gsmopen interfaces idle, do nothing */
3032 			DEBUGA_GSMOPEN
3033 				("Not answering the gsmopen_call %s, because we are already in a gsmopen call(%s) and not transferring, because no other gsmopen interfaces are available\n",
3034 				 GSMOPEN_P_LOG, id, tech_pvt->gsmopen_call_id);
3035 			sprintf(msg_to_gsmopen, "ALTER CALL %s END HANGUP", id);
3036 			//gsmopen_signaling_write(tech_pvt, msg_to_gsmopen);
3037 		}
3038 		switch_sleep(10000);
3039 		DEBUGA_GSMOPEN
3040 			("We have NOT answered a GSM RING from gsmopen_call %s, because we are already in a gsmopen call (%s)\n",
3041 			 GSMOPEN_P_LOG, id, tech_pvt->gsmopen_call_id);
3042 
3043 		switch_mutex_unlock(globals.mutex);
3044 	}
3045 	return 0;
3046 }
3047 #endif //0
3048 
gsmopen_do_gsmopenapi_thread_func(void * obj)3049 void *gsmopen_do_gsmopenapi_thread_func(void *obj)
3050 {
3051 
3052 	private_t *tech_pvt = (private_t *) obj;
3053 	time_t now_timestamp;
3054 
3055 	//if (gsmopen_present(GSMopenHandles))
3056 		while (running && tech_pvt->running) {
3057 			int res;
3058 			//gsmopen_sleep(1000000); //1 sec
3059 			//DEBUGA_GSMOPEN("ciao!\n", GSMOPEN_P_LOG);
3060 			res = gsmopen_serial_read(tech_pvt);
3061 			if (res == -1) {	//manage the graceful interface shutdown
3062 				tech_pvt->controldev_dead = 1;
3063 				close(tech_pvt->controldevfd);
3064 				ERRORA("gsmopen_serial_monitor failed, declaring %s dead\n", GSMOPEN_P_LOG, tech_pvt->controldevice_name);
3065 				tech_pvt->running=0;
3066 				alarm_event(tech_pvt, ALARM_FAILED_INTERFACE, "gsmopen_serial_monitor failed, declaring interface dead");
3067 				tech_pvt->active=0;
3068 				tech_pvt->name[0]='\0';
3069 				switch_sleep(1000000);
3070 			} else if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL && tech_pvt->interface_state == GSMOPEN_STATE_RING
3071 					   && tech_pvt->phone_callflow != CALLFLOW_CALL_HANGUP_REQUESTED) {
3072 				//WARNINGA("INCOMING RING\n", GSMOPEN_P_LOG);
3073 
3074 				gsmopen_ring(tech_pvt);
3075 
3076 				//FIXME gsmopen_answer(tech_pvt);
3077 				//new_inbound_channel(tech_pvt);
3078 				//FIXME if (!gsmopen_new(p, AST_STATE_RING, tech_pvt->context)) {
3079 				//FIXME ERRORA("gsmopen_new failed! BAD BAD BAD\n", GSMOPEN_P_LOG);
3080 				//FIXME }
3081 
3082 
3083 			} else if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL && tech_pvt->interface_state == GSMOPEN_STATE_DIALING) {
3084 				WARNINGA("WE'RE DIALING, let's take the earlymedia\n", GSMOPEN_P_LOG);
3085 				tech_pvt->interface_state = CALLFLOW_STATUS_EARLYMEDIA;
3086 				remote_party_is_early_media(tech_pvt);
3087 				//new_inbound_channel(tech_pvt);
3088 				//FIXME if (!gsmopen_new(p, AST_STATE_RING, tech_pvt->context)) {
3089 				//FIXME ERRORA("gsmopen_new failed! BAD BAD BAD\n", GSMOPEN_P_LOG);
3090 				//FIXME }
3091 
3092 
3093 
3094 
3095 			} else if (tech_pvt->interface_state == CALLFLOW_CALL_REMOTEANSWER) {
3096 				WARNINGA("REMOTE PARTY ANSWERED\n", GSMOPEN_P_LOG);
3097 				outbound_channel_answered(tech_pvt);
3098 				//new_inbound_channel(tech_pvt);
3099 				//FIXME if (!gsmopen_new(p, AST_STATE_RING, tech_pvt->context)) {
3100 				//FIXME ERRORA("gsmopen_new failed! BAD BAD BAD\n", GSMOPEN_P_LOG);
3101 				//FIXME }
3102 			}
3103 			switch_sleep(100);		//give other threads a chance
3104 			time(&now_timestamp);
3105 
3106 			if ((now_timestamp - tech_pvt->gsmopen_serial_synced_timestamp) > tech_pvt->gsmopen_serial_sync_period) {	//TODO find a sensible period. 5min? in config?
3107 				gsmopen_serial_sync(tech_pvt);
3108 				gsmopen_serial_getstatus_AT(tech_pvt);
3109 			}
3110 		}
3111 	DEBUGA_GSMOPEN("EXIT\n", GSMOPEN_P_LOG);
3112 	//running = 0;
3113 	return NULL;
3114 
3115 }
3116 
3117 
SWITCH_STANDARD_API(sendsms_function)3118 SWITCH_STANDARD_API(sendsms_function)
3119 {
3120 	char *mycmd = NULL, *argv[3] = { 0 };
3121 	int argc = 0;
3122 	private_t *tech_pvt = NULL;
3123 
3124 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
3125 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3126 	}
3127 
3128 	if (!argc) {
3129 		stream->write_function(stream, "ERROR, usage: %s", SENDSMS_SYNTAX);
3130 		goto end;
3131 	}
3132 
3133 	if (argc < 3) {
3134 		stream->write_function(stream, "ERROR, usage: %s", SENDSMS_SYNTAX);
3135 		goto end;
3136 	}
3137 
3138 	if (argv[0]) {
3139 		int i;
3140 		int found = 0;
3141 
3142 		for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
3143 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
3144 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)
3145 				&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
3146 				tech_pvt = &globals.GSMOPEN_INTERFACES[i];
3147 				stream->write_function(stream, "Trying to send your SMS: interface=%s, dest=%s, text=%s\n", argv[0], argv[1], argv[2]);
3148 				found = 1;
3149 				break;
3150 			}
3151 
3152 		}
3153 		if (!found) {
3154 			stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]);
3155 			switch_safe_free(mycmd);
3156 
3157 			return SWITCH_STATUS_SUCCESS;
3158 		} else {
3159 			//gsmopen_sendsms(tech_pvt, (char *) argv[1], (char *) argv[2]);
3160 			NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=NULL, hint=%s)\n", GSMOPEN_P_LOG, GSMOPEN_CHAT_PROTO, tech_pvt->name,
3161 				   argv[1], "SIMPLE MESSAGE", switch_str_nil(argv[2]), tech_pvt->name);
3162 
3163 			compat_chat_send(GSMOPEN_CHAT_PROTO, tech_pvt->name, argv[1], "SIMPLE MESSAGE", switch_str_nil(argv[2]), NULL, tech_pvt->name);
3164 		}
3165 	} else {
3166 		stream->write_function(stream, "ERROR, usage: %s", SENDSMS_SYNTAX);
3167 	}
3168   end:
3169 	switch_safe_free(mycmd);
3170 
3171 	return SWITCH_STATUS_SUCCESS;
3172 }
3173 
dump_event_full(private_t * tech_pvt,int is_alarm,int alarm_code,const char * alarm_message)3174 int dump_event_full(private_t * tech_pvt, int is_alarm, int alarm_code, const char *alarm_message)
3175 {
3176 	switch_event_t *event;
3177 	char value[512];
3178 	switch_core_session_t *session = NULL;
3179 	switch_channel_t *channel = NULL;
3180 	switch_status_t status;
3181 
3182 	session = switch_core_session_locate(tech_pvt->session_uuid_str);
3183 	if(session){
3184 		channel = switch_core_session_get_channel(session);
3185 	}
3186 
3187 	if (is_alarm){
3188 		ERRORA("ALARM on interface %s: \n", GSMOPEN_P_LOG, tech_pvt->name );
3189 		status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ALARM);
3190 	}else{
3191 		DEBUGA_GSMOPEN("DUMP on interface %s: \n", GSMOPEN_P_LOG, tech_pvt->name );
3192 		status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_DUMP);
3193 	}
3194 	if (status == SWITCH_STATUS_SUCCESS) {
3195 		if (is_alarm){
3196 			snprintf(value, sizeof(value)-1, "%d", alarm_code);
3197 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm_code", value);
3198 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm_message", alarm_message);
3199 		}
3200 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "interface_name", tech_pvt->name);
3201 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "interface_id", tech_pvt->id);
3202 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->active);
3203 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "active", value);
3204 		if(!tech_pvt->network_creg_not_supported){
3205 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->not_registered);
3206 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "not_registered", value);
3207 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->home_network_registered);
3208 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "home_network_registered", value);
3209 			snprintf(value, sizeof(value)-1, "%d", tech_pvt->roaming_registered);
3210 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "roaming_registered", value);
3211 		}else{
3212 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "not_registered", "N/A");
3213 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "home_network_registered", "N/A");
3214 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "roaming_registered", "N/A");
3215 		}
3216 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->got_signal);
3217 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "got_signal", value);
3218 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->running);
3219 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "running", value);
3220 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "imei", tech_pvt->imei);
3221 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "imsi", tech_pvt->imsi);
3222 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->controldev_dead);
3223 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "controldev_dead", value);
3224 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "controldevice_name", tech_pvt->controldevice_name);
3225 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->no_sound);
3226 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "no_sound", value);
3227 #ifdef GSMOPEN_ALSA
3228 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alsacname", tech_pvt->alsacname);
3229 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alsapname", tech_pvt->alsapname);
3230 #endif// GSMOPEN_ALSA
3231 #ifdef GSMOPEN_PORTAUDIO
3232 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->portaudiocindex);
3233 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "portaudiocindex", value);
3234 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->portaudiopindex);
3235 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "portaudiopindex", value);
3236 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->speexecho);
3237 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "speexecho", value);
3238 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->speexpreprocess);
3239 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "speexpreprocess", value);
3240 #endif// GSMOPEN_PORTAUDIO
3241 		snprintf(value, sizeof(value)-1, "%f", tech_pvt->playback_boost);
3242 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "playback_boost", value);
3243 		snprintf(value, sizeof(value)-1, "%f", tech_pvt->capture_boost);
3244 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "capture_boost", value);
3245 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialplan", tech_pvt->dialplan);
3246 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "context", tech_pvt->context);
3247 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "destination", tech_pvt->destination);
3248 		snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ib_calls);
3249 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ib_calls", value);
3250 		snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ob_calls);
3251 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ob_calls", value);
3252 		snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ib_failed_calls);
3253 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ib_failed_calls", value);
3254 		snprintf(value, sizeof(value)-1, "%lu", tech_pvt->ob_failed_calls);
3255 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ob_failed_calls", value);
3256 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->interface_state);
3257 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "interface_state", value);
3258 		snprintf(value, sizeof(value)-1, "%d", tech_pvt->phone_callflow);
3259 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "phone_callflow", value);
3260 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "session_uuid_str", tech_pvt->session_uuid_str);
3261 		if (strlen(tech_pvt->session_uuid_str)) {
3262 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
3263 		} else {				//no session
3264 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
3265 		}
3266 		if (channel) {
3267 			switch_channel_event_set_data(channel, event);
3268 		}
3269 		switch_event_fire(&event);
3270 	} else {
3271 		ERRORA("cannot create event on interface %s. WHY?????\n", GSMOPEN_P_LOG, tech_pvt->name);
3272 	}
3273 
3274 	if (session) {
3275 		switch_core_session_rwunlock(session);
3276 	}
3277 	return 0;
3278 }
3279 
dump_event(private_t * tech_pvt)3280 int dump_event(private_t * tech_pvt)
3281 {
3282 	return dump_event_full(tech_pvt, 0, 0, NULL);
3283 }
3284 
3285 
alarm_event(private_t * tech_pvt,int alarm_code,const char * alarm_message)3286 int alarm_event(private_t * tech_pvt, int alarm_code, const char *alarm_message)
3287 {
3288 	return dump_event_full(tech_pvt, 1, alarm_code, alarm_message);
3289 }
3290 
sms_incoming(private_t * tech_pvt)3291 int sms_incoming(private_t * tech_pvt)
3292 {
3293 	switch_event_t *event;
3294 	switch_core_session_t *session = NULL;
3295 	int event_sent_to_esl = 0;
3296 
3297 	//DEBUGA_GSMOPEN("received SMS on interface %s: %s\n", GSMOPEN_P_LOG, tech_pvt->name, tech_pvt->sms_message);
3298 	DEBUGA_GSMOPEN("received SMS on interface %s: DATE=%s, SENDER=%s, BODY=%s|\n", GSMOPEN_P_LOG, tech_pvt->name, tech_pvt->sms_date, tech_pvt->sms_sender,
3299 				   tech_pvt->sms_body);
3300 
3301 	if (!zstr(tech_pvt->session_uuid_str)) {
3302 		session = switch_core_session_locate(tech_pvt->session_uuid_str);
3303 	}
3304 	if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
3305 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", GSMOPEN_CHAT_PROTO);
3306 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
3307 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
3308 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->sms_sender);
3309 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "date", tech_pvt->sms_date);
3310 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "userdataheader", tech_pvt->sms_userdataheader);
3311 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "datacodingscheme", tech_pvt->sms_datacodingscheme);
3312 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "servicecentreaddress", tech_pvt->sms_servicecentreaddress);
3313 		switch_event_add_header(event, SWITCH_STACK_BOTTOM, "messagetype", "%d", tech_pvt->sms_messagetype);
3314 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
3315 		//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
3316 		switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
3317 		switch_event_add_body(event, "%s\n", tech_pvt->sms_body);
3318 		if (session) {
3319 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
3320 			if (switch_core_session_queue_event(session, &event) != SWITCH_STATUS_SUCCESS) {
3321 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "delivery-failure", "true");
3322 				switch_event_fire(&event);
3323 			}
3324 		} else {				//no session
3325 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
3326 			switch_event_fire(&event);
3327 			event_sent_to_esl = 1;
3328 		}
3329 
3330 	} else {
3331 		ERRORA("cannot create event on interface %s. WHY?????\n", GSMOPEN_P_LOG, tech_pvt->name);
3332 	}
3333 
3334 	if (!event_sent_to_esl) {
3335 
3336 		if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) {
3337 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", GSMOPEN_CHAT_PROTO);
3338 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name);
3339 			//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->chatmessages[which].from_dispname);
3340 			//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->chatmessages[which].from_handle);
3341 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->sms_sender);
3342 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "date", tech_pvt->sms_date);
3343 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "datacodingscheme", tech_pvt->sms_datacodingscheme);
3344 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "servicecentreaddress", tech_pvt->sms_servicecentreaddress);
3345 			switch_event_add_header(event, SWITCH_STACK_BOTTOM, "messagetype", "%d", tech_pvt->sms_messagetype);
3346 			switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE");
3347 			//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "chatname", tech_pvt->chatmessages[which].chatname);
3348 			//switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "id", tech_pvt->chatmessages[which].id);
3349 			switch_event_add_body(event, "%s\n", tech_pvt->sms_body);
3350 			if (session) {
3351 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true");
3352 			} else {			//no session
3353 				switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false");
3354 			}
3355 			switch_event_fire(&event);
3356 		} else {
3357 			ERRORA("cannot create event on interface %s. WHY?????\n", GSMOPEN_P_LOG, tech_pvt->name);
3358 		}
3359 	}
3360 
3361 	if (session) {
3362 		switch_core_session_rwunlock(session);
3363 	}
3364 	//memset(&tech_pvt->chatmessages[which], '\0', sizeof(&tech_pvt->chatmessages[which]) );
3365 	//memset(tech_pvt->sms_message, '\0', sizeof(tech_pvt->sms_message));
3366 	return 0;
3367 }
3368 
3369 
3370 #ifdef NOTDEF
SWITCH_STANDARD_API(gsmopen_chat_function)3371 SWITCH_STANDARD_API(gsmopen_chat_function)
3372 {
3373 	char *mycmd = NULL, *argv[10] = { 0 };
3374 	int argc = 0;
3375 	private_t *tech_pvt = NULL;
3376 	//int tried =0;
3377 	int i;
3378 	int found = 0;
3379 	//char skype_msg[1024];
3380 
3381 	if (!zstr(cmd) && (mycmd = strdup(cmd))) {
3382 		argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0])));
3383 	}
3384 
3385 	if (!argc) {
3386 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_CHAT_SYNTAX);
3387 		goto end;
3388 	}
3389 
3390 	if (argc < 3) {
3391 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_CHAT_SYNTAX);
3392 		goto end;
3393 	}
3394 
3395 	if (argv[0]) {
3396 		for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) {
3397 			/* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */
3398 			if (strlen(globals.GSMOPEN_INTERFACES[i].name)
3399 				&& (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) {
3400 				tech_pvt = &globals.GSMOPEN_INTERFACES[i];
3401 				stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name);
3402 				found = 1;
3403 				break;
3404 			}
3405 
3406 		}
3407 		if (!found) {
3408 			stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]);
3409 			goto end;
3410 		} else {
3411 
3412 			//chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint);
3413 			//chat_send(p*roto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint);
3414 			//chat_send(GSMOPEN_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE", switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, hint);
3415 
3416 			NOTICA("chat_send(proto=%s, from=%s, to=%s, subject=%s, body=%s, type=NULL, hint=%s)\n", GSMOPEN_P_LOG, GSMOPEN_CHAT_PROTO, tech_pvt->skype_user,
3417 				   argv[1], "SIMPLE MESSAGE", switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), tech_pvt->name);
3418 
3419 			chat_send(GSMOPEN_CHAT_PROTO, tech_pvt->skype_user, argv[1], "SIMPLE MESSAGE",
3420 					  switch_str_nil((char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]), NULL, tech_pvt->name);
3421 
3422 			//NOTICA("TEXT is: %s\n", GSMOPEN_P_LOG, (char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1] );
3423 			//snprintf(skype_msg, sizeof(skype_msg), "CHAT CREATE %s", argv[1]);
3424 			//gsmopen_signaling_write(tech_pvt, skype_msg);
3425 			//switch_sleep(100);
3426 		}
3427 	} else {
3428 		stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_CHAT_SYNTAX);
3429 		goto end;
3430 	}
3431 
3432 #ifdef NOTDEF
3433 
3434 	found = 0;
3435 
3436 	while (!found) {
3437 		for (i = 0; i < MAX_CHATS; i++) {
3438 			if (!strcmp(tech_pvt->chats[i].dialog_partner, argv[1])) {
3439 				snprintf(skype_msg, sizeof(skype_msg), "CHATMESSAGE %s %s", tech_pvt->chats[i].chatname,
3440 						 (char *) &cmd[strlen(argv[0]) + 1 + strlen(argv[1]) + 1]);
3441 				gsmopen_signaling_write(tech_pvt, skype_msg);
3442 				found = 1;
3443 				break;
3444 			}
3445 		}
3446 		if (found) {
3447 			break;
3448 		}
3449 		if (tried > 1000) {
3450 			stream->write_function(stream, "ERROR: no chat with dialog_partner='%s' was found\n", argv[1]);
3451 			break;
3452 		}
3453 		switch_sleep(1000);
3454 	}
3455 #endif //NOTDEF
3456 
3457   end:
3458 	switch_safe_free(mycmd);
3459 
3460 	return SWITCH_STATUS_SUCCESS;
3461 }
3462 #endif // NOTDEF
3463 
3464 
3465 /* For Emacs:
3466  * Local Variables:
3467  * mode:c
3468  * indent-tabs-mode:t
3469  * tab-width:4
3470  * c-basic-offset:4
3471  * End:
3472  * For VIM:
3473  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet expandtab:
3474  */
3475