/* * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * Copyright (C) 2005-2011, Anthony Minessale II * * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application * * The Initial Developer of the Original Code is * Anthony Minessale II * Portions created by the Initial Developer are Copyright (C) * the Initial Developer. All Rights Reserved. * * This module (mod_gsmopen) has been contributed by: * * Giovanni Maruzzelli * * Maintainer: Giovanni Maruzzelli * * mod_gsmopen.cpp -- GSM Modem compatible Endpoint Module * */ #include "gsmopen.h" SWITCH_BEGIN_EXTERN_C SWITCH_MODULE_LOAD_FUNCTION(mod_gsmopen_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_gsmopen_shutdown); SWITCH_MODULE_DEFINITION(mod_gsmopen, mod_gsmopen_load, mod_gsmopen_shutdown, NULL); SWITCH_END_EXTERN_C #define GSMOPEN_CHAT_PROTO "sms" SWITCH_STANDARD_API(gsm_function); #define GSM_SYNTAX "list [full] || console || AT_command || remove < interface_name | interface_id > || reload" SWITCH_STANDARD_API(gsmopen_function); #define GSMOPEN_SYNTAX "interface_name AT_command" SWITCH_STANDARD_API(gsmopen_boost_audio_function); #define GSMOPEN_BOOST_AUDIO_SYNTAX "interface_name [ ]" SWITCH_STANDARD_API(sendsms_function); #define SENDSMS_SYNTAX "gsmopen_sendsms interface_name destination_number SMS_text" SWITCH_STANDARD_API(gsmopen_dump_function); #define GSMOPEN_DUMP_SYNTAX "gsmopen_dump " SWITCH_STANDARD_API(gsmopen_ussd_function); #define USSD_SYNTAX "gsmopen_ussd [nowait]" #define FULL_RELOAD 0 #define SOFT_RELOAD 1 const char *interface_status[] = { /* should match GSMOPEN_STATE_xxx in gsmopen.h */ "IDLE", "DOWN", "RING", "DIALING", "BUSY", "UP", "RINGING", "PRERING", "DOUBLE", "SELECTD", "HANG_RQ", "PREANSW" }; const char *phone_callflow[] = { /* should match CALLFLOW_XXX in gsmopen.h */ "CALL_IDLE", "CALL_DOWN", "INCOMING_RNG", "CALL_DIALING", "CALL_LINEBUSY", "CALL_ACTIVE", "INCOMING_HNG", "CALL_RLEASD", "CALL_NOCARR", "CALL_INFLUX", "CALL_INCOMING", "CALL_FAILED", "CALL_NOSRVC", "CALL_OUTRESTR", "CALL_SECFAIL", "CALL_NOANSWER", "STATUS_FNSHED", "STATUS_CANCLED", "STATUS_FAILED", "STATUS_REFUSED", "STATUS_RINGING", "STATUS_INPROGRS", "STATUS_UNPLACD", "STATUS_ROUTING", "STATUS_EARLYMD", "INCOMING_CLID", "STATUS_RMTEHOLD" }; static struct { int debug; char *ip; int port; char *dialplan; char *destination; char *context; char *codec_string; char *codec_order[SWITCH_MAX_CODECS]; int codec_order_last; char *codec_rates_string; char *codec_rates[SWITCH_MAX_CODECS]; int codec_rates_last; unsigned int flags; int fd; int calls; int real_interfaces; int next_interface; char hold_music[256]; private_t GSMOPEN_INTERFACES[GSMOPEN_MAX_INTERFACES]; switch_mutex_t *mutex; private_t *gsm_console; } globals; switch_endpoint_interface_t *gsmopen_endpoint_interface; switch_memory_pool_t *gsmopen_module_pool = NULL; int running = 0; SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_dialplan, globals.dialplan); SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_context, globals.context); SWITCH_DECLARE_GLOBAL_STRING_FUNC(set_global_destination, globals.destination); static switch_status_t interface_exists(char *the_interface); static switch_status_t remove_interface(char *the_interface); static switch_status_t channel_on_init(switch_core_session_t *session); static switch_status_t channel_on_hangup(switch_core_session_t *session); static switch_status_t channel_on_destroy(switch_core_session_t *session); static switch_status_t channel_on_routing(switch_core_session_t *session); static switch_status_t channel_on_exchange_media(switch_core_session_t *session); static switch_status_t channel_on_consume_media(switch_core_session_t *session); static switch_status_t channel_on_soft_execute(switch_core_session_t *session); static switch_call_cause_t 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); static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id); static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig); static switch_status_t gsmopen_tech_init(private_t *tech_pvt, switch_core_session_t *session); static switch_status_t gsmopen_codec(private_t *tech_pvt, int sample_rate, int codec_ms) { switch_core_session_t *session = NULL; if (switch_core_codec_init (&tech_pvt->read_codec, "L16", NULL, NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) { ERRORA("Can't load codec?\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } if (switch_core_codec_init (&tech_pvt->write_codec, "L16", NULL, NULL, sample_rate, codec_ms, 1, SWITCH_CODEC_FLAG_ENCODE | SWITCH_CODEC_FLAG_DECODE, NULL, NULL) != SWITCH_STATUS_SUCCESS) { ERRORA("Can't load codec?\n", GSMOPEN_P_LOG); switch_core_codec_destroy(&tech_pvt->read_codec); return SWITCH_STATUS_FALSE; } tech_pvt->read_frame.rate = sample_rate; tech_pvt->read_frame.codec = &tech_pvt->read_codec; session = switch_core_session_locate(tech_pvt->session_uuid_str); if (session) { switch_core_session_set_read_codec(session, &tech_pvt->read_codec); switch_core_session_set_write_codec(session, &tech_pvt->write_codec); switch_core_session_rwunlock(session); } else { ERRORA("no session\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } return SWITCH_STATUS_SUCCESS; } switch_status_t gsmopen_tech_init(private_t *tech_pvt, switch_core_session_t *session) { switch_assert(tech_pvt != NULL); switch_assert(session != NULL); tech_pvt->read_frame.data = tech_pvt->databuf; tech_pvt->read_frame.buflen = sizeof(tech_pvt->databuf); switch_mutex_init(&tech_pvt->mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_mutex_init(&tech_pvt->flag_mutex, SWITCH_MUTEX_NESTED, switch_core_session_get_pool(session)); switch_core_session_set_private(session, tech_pvt); switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(session), sizeof(tech_pvt->session_uuid_str)); if (!strlen(tech_pvt->session_uuid_str)) { ERRORA("no tech_pvt->session_uuid_str\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } if (gsmopen_codec(tech_pvt, SAMPLERATE_GSMOPEN, 20) != SWITCH_STATUS_SUCCESS) { ERRORA("gsmopen_codec FAILED\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } dtmf_rx_init(&tech_pvt->dtmf_state, NULL, NULL); dtmf_rx_parms(&tech_pvt->dtmf_state, 0, 10, 10, -99); /* if (tech_pvt->no_sound == 0) { if (serial_audio_init(tech_pvt)) { ERRORA("serial_audio_init failed\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } } */ if (switch_core_timer_init(&tech_pvt->timer_read, "soft", 20, tech_pvt->read_codec.implementation->samples_per_packet, gsmopen_module_pool) != SWITCH_STATUS_SUCCESS) { ERRORA("setup timer failed\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } switch_core_timer_sync(&tech_pvt->timer_read); if (switch_core_timer_init(&tech_pvt->timer_write, "soft", 20, tech_pvt->write_codec.implementation->samples_per_packet, gsmopen_module_pool) != SWITCH_STATUS_SUCCESS) { ERRORA("setup timer failed\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } switch_core_timer_sync(&tech_pvt->timer_write); switch_mutex_lock(tech_pvt->flag_mutex); switch_clear_flag(tech_pvt, TFLAG_HANGUP); switch_mutex_unlock(tech_pvt->flag_mutex); DEBUGA_GSMOPEN("gsmopen_codec SUCCESS\n", GSMOPEN_P_LOG); return SWITCH_STATUS_SUCCESS; } static switch_status_t list_interfaces(const char *line, const char *cursor, switch_console_callback_match_t **matches) { int interface_id; switch_console_callback_match_t *my_matches = NULL; switch_status_t status = SWITCH_STATUS_FALSE; for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) { if (globals.GSMOPEN_INTERFACES[interface_id].running) { switch_console_push_match(&my_matches, (const char *) globals.GSMOPEN_INTERFACES[interface_id].name); } } if (my_matches) { *matches = my_matches; status = SWITCH_STATUS_SUCCESS; } return status; } static switch_status_t interface_exists(char *the_interface) { int i; int interface_id; if (*the_interface == '#') { /* look by interface id or interface name */ the_interface++; switch_assert(the_interface); interface_id = atoi(the_interface); /* take a number as interface id */ if (interface_id > 0 || (interface_id == 0 && strcmp(the_interface, "0") == 0)) { if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) { return SWITCH_STATUS_SUCCESS; } } else { /* interface name */ for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) { if (strcmp(globals.GSMOPEN_INTERFACES[interface_id].name, the_interface) == 0) { return SWITCH_STATUS_SUCCESS; break; } } } } else { /* look by gsmopen_user */ for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { if (strlen(globals.GSMOPEN_INTERFACES[i].gsmopen_user)) { if (strcmp(globals.GSMOPEN_INTERFACES[i].gsmopen_user, the_interface) == 0) { return SWITCH_STATUS_SUCCESS; } } } } return SWITCH_STATUS_FALSE; } static switch_status_t remove_interface(char *the_interface) { int x = 10; int fd; #ifdef WIN32 switch_size_t howmany = 8; #else unsigned int howmany = 8; #endif int interface_id = -1; private_t *tech_pvt = NULL; switch_status_t status; switch_assert(the_interface); interface_id = atoi(the_interface); if ((interface_id > 0 && interface_id < GSMOPEN_MAX_INTERFACES) || (interface_id == 0 && strcmp(the_interface, "0") == 0)) { if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) { /* take a number as interface id */ tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id]; } } else { for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) { if (strcmp(globals.GSMOPEN_INTERFACES[interface_id].name, the_interface) == 0) { tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id]; break; } } } if (!tech_pvt) { DEBUGA_GSMOPEN("interface '%s' does not exist\n", GSMOPEN_P_LOG, the_interface); goto end; } if (strlen(globals.GSMOPEN_INTERFACES[interface_id].session_uuid_str)) { DEBUGA_GSMOPEN("interface '%s' is busy\n", GSMOPEN_P_LOG, the_interface); goto end; } LOKKA(tech_pvt->controldev_lock); globals.GSMOPEN_INTERFACES[interface_id].running = 0; if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) { #ifdef WIN32 switch_file_write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", &howmany); // let's the controldev_thread die #else /* WIN32 */ howmany = write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", howmany); #endif /* WIN32 */ DEBUGA_GSMOPEN("HERE will shutdown gsmopen_signaling_thread of '%s'\n", GSMOPEN_P_LOG, the_interface); } if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread) { DEBUGA_GSMOPEN("HERE will shutdown gsmopen_api_thread of '%s'\n", GSMOPEN_P_LOG, the_interface); } while (x) { x--; switch_yield(50000); } if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) { switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread); } if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread) { switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread); } fd = tech_pvt->controldevfd; if (fd) { tech_pvt->controldevfd = -1; DEBUGA_GSMOPEN("SHUTDOWN tech_pvt->controldevfd=%d\n", GSMOPEN_P_LOG, tech_pvt->controldevfd); } serial_audio_shutdown(tech_pvt); int res; res = tech_pvt->serialPort_serial_control->Close(); DEBUGA_GSMOPEN("serial_shutdown res=%d (controldevfd is %d)\n", GSMOPEN_P_LOG, res, tech_pvt->controldevfd); #ifndef WIN32 shutdown(tech_pvt->audiogsmopenpipe[0], 2); close(tech_pvt->audiogsmopenpipe[0]); shutdown(tech_pvt->audiogsmopenpipe[1], 2); close(tech_pvt->audiogsmopenpipe[1]); shutdown(tech_pvt->audiopipe[0], 2); close(tech_pvt->audiopipe[0]); shutdown(tech_pvt->audiopipe[1], 2); close(tech_pvt->audiopipe[1]); shutdown(tech_pvt->GSMopenHandles.fdesc[0], 2); close(tech_pvt->GSMopenHandles.fdesc[0]); shutdown(tech_pvt->GSMopenHandles.fdesc[1], 2); close(tech_pvt->GSMopenHandles.fdesc[1]); #endif /* WIN32 */ UNLOCKA(tech_pvt->controldev_lock); switch_mutex_lock(globals.mutex); if (globals.gsm_console == &globals.GSMOPEN_INTERFACES[interface_id]) { DEBUGA_GSMOPEN("interface '%s' no more console\n", GSMOPEN_P_LOG, the_interface); globals.gsm_console = NULL; } else { DEBUGA_GSMOPEN("interface '%s' STILL console\n", GSMOPEN_P_LOG, the_interface); } memset(&globals.GSMOPEN_INTERFACES[interface_id], '\0', sizeof(private_t)); globals.real_interfaces--; switch_mutex_unlock(globals.mutex); DEBUGA_GSMOPEN("interface '%s' deleted successfully\n", GSMOPEN_P_LOG, the_interface); end: return SWITCH_STATUS_SUCCESS; } /* State methods that get called when the state changes to the specific state returning SWITCH_STATUS_SUCCESS tells the core to execute the standard state method next so if you fully implement the state you can return SWITCH_STATUS_FALSE to skip it. */ static switch_status_t channel_on_init(switch_core_session_t *session) { switch_channel_t *channel; private_t *tech_pvt = NULL; tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_IO); switch_mutex_unlock(tech_pvt->flag_mutex); switch_mutex_lock(globals.mutex); globals.calls++; switch_mutex_unlock(globals.mutex); DEBUGA_GSMOPEN("%s CHANNEL INIT %s\n", GSMOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session)); return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_destroy(switch_core_session_t *session) { private_t *tech_pvt = NULL; tech_pvt = (private_t *) switch_core_session_get_private(session); if (tech_pvt) { DEBUGA_GSMOPEN("%s CHANNEL DESTROY %s\n", GSMOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session)); if (switch_core_codec_ready(&tech_pvt->read_codec)) { switch_core_codec_destroy(&tech_pvt->read_codec); } if (switch_core_codec_ready(&tech_pvt->write_codec)) { switch_core_codec_destroy(&tech_pvt->write_codec); } switch_core_timer_destroy(&tech_pvt->timer_read); switch_core_timer_destroy(&tech_pvt->timer_write); if (tech_pvt->no_sound == 0) { serial_audio_shutdown(tech_pvt); } *tech_pvt->session_uuid_str = '\0'; tech_pvt->interface_state = GSMOPEN_STATE_IDLE; if (tech_pvt->phone_callflow == CALLFLOW_STATUS_FINISHED) { tech_pvt->phone_callflow = CALLFLOW_CALL_IDLE; } memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); switch_core_session_set_private(session, NULL); } else { DEBUGA_GSMOPEN("!!!!!!NO tech_pvt!!!! CHANNEL DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(session)); } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_hangup(switch_core_session_t *session) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); tech_pvt->phone_callflow = CALLFLOW_CALL_HANGUP_REQUESTED; if (!switch_channel_test_flag(channel, CF_ANSWERED)) { if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) { tech_pvt->ob_failed_calls++; } else { tech_pvt->ib_failed_calls++; } } DEBUGA_GSMOPEN("%s CHANNEL HANGUP\n", GSMOPEN_P_LOG, tech_pvt->name); switch_mutex_lock(tech_pvt->flag_mutex); switch_clear_flag(tech_pvt, TFLAG_IO); switch_clear_flag(tech_pvt, TFLAG_VOICE); switch_set_flag(tech_pvt, TFLAG_HANGUP); switch_mutex_unlock(tech_pvt->flag_mutex); gsmopen_hangup(tech_pvt); //memset(tech_pvt->session_uuid_str, '\0', sizeof(tech_pvt->session_uuid_str)); //*tech_pvt->session_uuid_str = '\0'; DEBUGA_GSMOPEN("%s CHANNEL HANGUP\n", GSMOPEN_P_LOG, tech_pvt->name); switch_mutex_lock(globals.mutex); globals.calls--; if (globals.calls < 0) { globals.calls = 0; } tech_pvt->interface_state = GSMOPEN_STATE_IDLE; tech_pvt->phone_callflow = CALLFLOW_CALL_IDLE; switch_mutex_unlock(globals.mutex); return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_routing(switch_core_session_t *session) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); DEBUGA_GSMOPEN("%s CHANNEL ROUTING\n", GSMOPEN_P_LOG, tech_pvt->name); return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_execute(switch_core_session_t *session) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); DEBUGA_GSMOPEN("%s CHANNEL EXECUTE\n", GSMOPEN_P_LOG, tech_pvt->name); return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_kill_channel(switch_core_session_t *session, int sig) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); DEBUGA_GSMOPEN("%s CHANNEL KILL_CHANNEL\n", GSMOPEN_P_LOG, tech_pvt->name); switch (sig) { case SWITCH_SIG_KILL: DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_SIG_KILL\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); switch_mutex_lock(tech_pvt->flag_mutex); switch_clear_flag(tech_pvt, TFLAG_IO); switch_clear_flag(tech_pvt, TFLAG_VOICE); switch_set_flag(tech_pvt, TFLAG_HANGUP); switch_mutex_unlock(tech_pvt->flag_mutex); break; case SWITCH_SIG_BREAK: DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_SIG_BREAK\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_BREAK); switch_mutex_unlock(tech_pvt->flag_mutex); break; default: break; } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_consume_media(switch_core_session_t *session) { private_t *tech_pvt = NULL; tech_pvt = (private_t *) switch_core_session_get_private(session); if (tech_pvt) { DEBUGA_GSMOPEN("%s CHANNEL CONSUME_MEDIA\n", GSMOPEN_P_LOG, tech_pvt->name); } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_exchange_media(switch_core_session_t *session) { private_t *tech_pvt = NULL; tech_pvt = (private_t *) switch_core_session_get_private(session); if (tech_pvt) { DEBUGA_GSMOPEN("%s CHANNEL EXCHANGE_MEDIA\n", GSMOPEN_P_LOG, tech_pvt->name); } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_on_soft_execute(switch_core_session_t *session) { private_t *tech_pvt = NULL; tech_pvt = (private_t *) switch_core_session_get_private(session); if (tech_pvt) { DEBUGA_GSMOPEN("%s CHANNEL SOFT_EXECUTE\n", GSMOPEN_P_LOG, tech_pvt->name); } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_send_dtmf(switch_core_session_t *session, const switch_dtmf_t *dtmf) { private_t *tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); DEBUGA_GSMOPEN("%s CHANNEL SEND_DTMF\n", GSMOPEN_P_LOG, tech_pvt->name); DEBUGA_GSMOPEN("DTMF: %c\n", GSMOPEN_P_LOG, dtmf->digit); gsmopen_senddigit(tech_pvt, dtmf->digit); return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_read_frame(switch_core_session_t *session, switch_frame_t **frame, switch_io_flag_t flags, int stream_id) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; switch_byte_t *data; int samples; char digit_str[256]; char buffer2[640]; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) { ERRORA("channel not ready \n", GSMOPEN_P_LOG); //TODO: kill the bastard return SWITCH_STATUS_FALSE; } tech_pvt->read_frame.flags = SFF_NONE; *frame = NULL; if (switch_test_flag(tech_pvt, TFLAG_HANGUP)) { return SWITCH_STATUS_FALSE; } switch_core_timer_next(&tech_pvt->timer_read); if (tech_pvt->no_sound) { goto cng; } memset(buffer2, 0, sizeof(buffer2)); samples = tech_pvt->serialPort_serial_audio->Read(buffer2, 640); if (samples >= 320) { tech_pvt->buffer2_full = 0; if (samples >= 640) { DEBUGA_GSMOPEN("read more than 320, samples=%d\n", GSMOPEN_P_LOG, samples); memcpy(tech_pvt->buffer2, buffer2 + 320, 320); tech_pvt->buffer2_full = 1; } samples = 320; memcpy(tech_pvt->read_frame.data, buffer2, 320); } else { if (samples != 0) { DEBUGA_GSMOPEN("read less than 320, samples=%d\n", GSMOPEN_P_LOG, samples); } if (tech_pvt->buffer2_full) { memcpy(tech_pvt->read_frame.data, tech_pvt->buffer2, 320); tech_pvt->buffer2_full = 0; samples = 320; DEBUGA_GSMOPEN("samples=%d FROM BUFFER\n", GSMOPEN_P_LOG, samples); memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); } } tech_pvt->read_frame.datalen = samples; tech_pvt->read_frame.samples = samples / 2; tech_pvt->read_frame.timestamp = tech_pvt->timer_read.samplecount; *frame = &tech_pvt->read_frame; switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_VOICE); switch_mutex_unlock(tech_pvt->flag_mutex); if (samples != 320) { memset(tech_pvt->buffer2, 0, sizeof(tech_pvt->buffer2)); if (samples != 0) { DEBUGA_GSMOPEN("samples=%d, goto cng\n", GSMOPEN_P_LOG, samples); } goto cng; } memset(digit_str, 0, sizeof(digit_str)); dtmf_rx(&tech_pvt->dtmf_state, (int16_t *) tech_pvt->read_frame.data, tech_pvt->read_frame.samples); dtmf_rx_get(&tech_pvt->dtmf_state, digit_str, sizeof(digit_str)); gsmopen_sound_boost(tech_pvt->read_frame.data, tech_pvt->read_frame.samples, tech_pvt->capture_boost); if (digit_str[0]) { switch_time_t new_dtmf_timestamp = switch_time_now(); if ((new_dtmf_timestamp - tech_pvt->old_dtmf_timestamp) > 350000) { //FIXME: make it configurable char *p = digit_str; while (p && *p) { switch_dtmf_t dtmf = { 0 }; dtmf.digit = *p; dtmf.duration = SWITCH_DEFAULT_DTMF_DURATION; switch_channel_queue_dtmf(channel, &dtmf); p++; } DEBUGA_GSMOPEN("DTMF DETECTED: [%s] new_dtmf_timestamp: %u, delta_t: %u\n", GSMOPEN_P_LOG, digit_str, (unsigned int) new_dtmf_timestamp, (unsigned int) (new_dtmf_timestamp - tech_pvt->old_dtmf_timestamp)); tech_pvt->old_dtmf_timestamp = new_dtmf_timestamp; } } while (switch_test_flag(tech_pvt, TFLAG_IO)) { if (switch_test_flag(tech_pvt, TFLAG_BREAK)) { switch_mutex_lock(tech_pvt->flag_mutex); switch_clear_flag(tech_pvt, TFLAG_BREAK); switch_mutex_unlock(tech_pvt->flag_mutex); DEBUGA_GSMOPEN("BREAK: CHANNEL READ FRAME goto CNG\n", GSMOPEN_P_LOG); goto cng; } if (!switch_test_flag(tech_pvt, TFLAG_IO)) { DEBUGA_GSMOPEN("CHANNEL READ FRAME not IO\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } if (switch_test_flag(tech_pvt, TFLAG_IO) && switch_test_flag(tech_pvt, TFLAG_VOICE)) { switch_mutex_lock(tech_pvt->flag_mutex); switch_clear_flag(tech_pvt, TFLAG_VOICE); switch_mutex_unlock(tech_pvt->flag_mutex); if (!tech_pvt->read_frame.datalen) { DEBUGA_GSMOPEN("CHANNEL READ CONTINUE\n", GSMOPEN_P_LOG); continue; } *frame = &tech_pvt->read_frame; #ifdef BIGENDIAN if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { switch_swap_linear((int16_t *) (*frame)->data, (int) (*frame)->datalen / 2); } #endif return SWITCH_STATUS_SUCCESS; } DEBUGA_GSMOPEN("CHANNEL READ no TFLAG_VOICE\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; } DEBUGA_GSMOPEN("CHANNEL READ FALSE\n", GSMOPEN_P_LOG); return SWITCH_STATUS_FALSE; cng: data = (switch_byte_t *) tech_pvt->read_frame.data; data[0] = 65; data[1] = 0; tech_pvt->read_frame.datalen = 2; tech_pvt->read_frame.flags = SFF_CNG; *frame = &tech_pvt->read_frame; return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_write_frame(switch_core_session_t *session, switch_frame_t *frame, switch_io_flag_t flags, int stream_id) { switch_channel_t *channel = NULL; private_t *tech_pvt = NULL; unsigned int sent; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); if (!switch_channel_ready(channel) || !switch_test_flag(tech_pvt, TFLAG_IO)) { ERRORA("channel not ready \n", GSMOPEN_P_LOG); //TODO: kill the bastard return SWITCH_STATUS_FALSE; } #ifdef BIGENDIAN if (switch_test_flag(tech_pvt, TFLAG_LINEAR)) { #ifdef WIN32 switch_swap_linear((int16_t *) frame->data, (int) frame->datalen / 2); #else switch_swap_linear(frame->data, (int) frame->datalen / 2); #endif //WIN32 } #endif gsmopen_sound_boost(frame->data, frame->samples, tech_pvt->playback_boost); if (!tech_pvt->no_sound) { if (!tech_pvt->serialPort_serial_audio_opened) { serial_audio_init(tech_pvt); } sent = tech_pvt->serialPort_serial_audio->Write((char *) frame->data, (int) (frame->datalen)); if (sent && sent != frame->datalen && sent != -1) { DEBUGA_GSMOPEN("sent %u\n", GSMOPEN_P_LOG, sent); } } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_answer_channel(switch_core_session_t *session) { private_t *tech_pvt; switch_channel_t *channel = NULL; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_IO); switch_mutex_unlock(tech_pvt->flag_mutex); gsmopen_serial_answer(tech_pvt); switch_mutex_lock(globals.mutex); globals.calls++; switch_mutex_unlock(globals.mutex); DEBUGA_GSMOPEN("%s CHANNEL ANSWER %s\n", GSMOPEN_P_LOG, tech_pvt->name, switch_core_session_get_uuid(session)); if (channel) { switch_channel_mark_answered(channel); } DEBUGA_GSMOPEN("ANSWERED! \n", GSMOPEN_P_LOG); return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_receive_message(switch_core_session_t *session, switch_core_session_message_t *msg) { switch_channel_t *channel; private_t *tech_pvt; channel = switch_core_session_get_channel(session); switch_assert(channel != NULL); tech_pvt = (private_t *) switch_core_session_get_private(session); switch_assert(tech_pvt != NULL); switch (msg->message_id) { case SWITCH_MESSAGE_INDICATE_ANSWER: { DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_ANSWER\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); if (tech_pvt->interface_state != GSMOPEN_STATE_UP && tech_pvt->phone_callflow != CALLFLOW_CALL_ACTIVE) { DEBUGA_GSMOPEN("MSG_ID=%d, TO BE ANSWERED!\n", GSMOPEN_P_LOG, msg->message_id); channel_answer_channel(session); } } break; case SWITCH_MESSAGE_INDICATE_PROGRESS: { DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_PROGRESS\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); if (tech_pvt->interface_state != GSMOPEN_STATE_UP && tech_pvt->phone_callflow != CALLFLOW_CALL_ACTIVE) { DEBUGA_GSMOPEN("MSG_ID=%d, TO BE ANSWERED!\n", GSMOPEN_P_LOG, msg->message_id); channel_answer_channel(session); } } break; case SWITCH_MESSAGE_INDICATE_AUDIO_SYNC: DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_AUDIO_SYNC\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); switch_core_timer_sync(&tech_pvt->timer_read); switch_core_timer_sync(&tech_pvt->timer_write); break; case SWITCH_MESSAGE_INDICATE_TRANSFER: DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_TRANSFER\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); break; case SWITCH_MESSAGE_INDICATE_BRIDGE: DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_BRIDGE\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); break; case SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY: DEBUGA_GSMOPEN("%s CHANNEL got SWITCH_MESSAGE_INDICATE_TRANSCODING_NECESSARY\n", GSMOPEN_P_LOG, switch_channel_get_name(channel)); break; default: { if (msg->message_id != SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC && msg->message_id != SWITCH_MESSAGE_INDICATE_APPLICATION_EXEC_COMPLETE) { DEBUGA_GSMOPEN("MSG_ID=%d\n", GSMOPEN_P_LOG, msg->message_id); } } break; } return SWITCH_STATUS_SUCCESS; } static switch_status_t channel_receive_event(switch_core_session_t *session, switch_event_t *event) { struct private_object *tech_pvt = (struct private_object *) switch_core_session_get_private(session); char *body = switch_event_get_body(event); switch_assert(tech_pvt != NULL); if (!body) { body = (char *) ""; } WARNINGA("event: |||%s|||\n", GSMOPEN_P_LOG, body); return SWITCH_STATUS_SUCCESS; } switch_state_handler_table_t gsmopen_state_handlers = { /*.on_init */ channel_on_init, /*.on_routing */ channel_on_routing, /*.on_execute */ channel_on_execute, /*.on_hangup */ channel_on_hangup, /*.on_exchange_media */ channel_on_exchange_media, /*.on_soft_execute */ channel_on_soft_execute, /*.on_consume_media */ channel_on_consume_media, /*.on_hibernate */ NULL, /*.on_reset */ NULL, /*.on_park */ NULL, /*.on_reporting */ NULL, /*.on_destroy */ channel_on_destroy }; switch_io_routines_t gsmopen_io_routines = { /*.outgoing_channel */ channel_outgoing_channel, /*.read_frame */ channel_read_frame, /*.write_frame */ channel_write_frame, /*.kill_channel */ channel_kill_channel, /*.send_dtmf */ channel_send_dtmf, /*.receive_message */ channel_receive_message, /*.receive_event */ channel_receive_event }; static switch_call_cause_t 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) { private_t *tech_pvt = NULL; int result; if ((*new_session = switch_core_session_request_uuid(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool, switch_event_get_header(var_event, "origination_uuid"))) != 0) { switch_channel_t *channel = NULL; switch_caller_profile_t *caller_profile; char *rdest; int found = 0; char interface_name[256]; DEBUGA_GSMOPEN("1 SESSION_REQUEST %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(*new_session)); switch_core_session_add_stream(*new_session, NULL); if (!zstr(outbound_profile->destination_number)) { int i; char *slash; switch_copy_string(interface_name, outbound_profile->destination_number, 255); slash = strrchr(interface_name, '/'); *slash = '\0'; switch_mutex_lock(globals.mutex); if (strncmp("ANY", interface_name, strlen(interface_name)) == 0 || strncmp("RR", interface_name, strlen(interface_name)) == 0) { /* we've been asked for the "ANY" interface, let's find the first idle interface */ /* Find the first idle interface using Round Robin */ DEBUGA_GSMOPEN("Finding one available gsmopen interface RR\n", GSMOPEN_P_LOG); tech_pvt = find_available_gsmopen_interface_rr(NULL); if (tech_pvt) { found = 1; DEBUGA_GSMOPEN("FOUND one available gsmopen interface RR\n", GSMOPEN_P_LOG); } } for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, interface_name, strlen(interface_name)) == 0)) { if (strlen(globals.GSMOPEN_INTERFACES[i].session_uuid_str)) { DEBUGA_GSMOPEN ("globals.GSMOPEN_INTERFACES[%d].name=|||%s||| session_uuid_str=|||%s||| is BUSY\n", GSMOPEN_P_LOG, i, globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].session_uuid_str); DEBUGA_GSMOPEN("1 SESSION_DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(*new_session)); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION; } DEBUGA_GSMOPEN("globals.GSMOPEN_INTERFACES[%d].name=|||%s|||?\n", GSMOPEN_P_LOG, i, globals.GSMOPEN_INTERFACES[i].name); tech_pvt = &globals.GSMOPEN_INTERFACES[i]; found = 1; break; } } } else { ERRORA("Doh! no destination number?\n", GSMOPEN_P_LOG); switch_core_session_destroy(new_session); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } if (!found) { DEBUGA_GSMOPEN("Doh! no available interface for |||%s|||?\n", GSMOPEN_P_LOG, interface_name); DEBUGA_GSMOPEN("2 SESSION_DESTROY %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(*new_session)); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_NORMAL_CIRCUIT_CONGESTION; } channel = switch_core_session_get_channel(*new_session); if (!channel) { ERRORA("Doh! no channel?\n", GSMOPEN_P_LOG); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } if (gsmopen_tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) { ERRORA("Doh! no tech_init?\n", GSMOPEN_P_LOG); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } if (outbound_profile) { char name[128]; snprintf(name, sizeof(name), "gsmopen/%s", outbound_profile->destination_number); switch_channel_set_name(channel, name); caller_profile = switch_caller_profile_clone(*new_session, outbound_profile); switch_channel_set_caller_profile(channel, caller_profile); tech_pvt->caller_profile = caller_profile; } else { ERRORA("Doh! no caller profile\n", GSMOPEN_P_LOG); switch_core_session_destroy(new_session); switch_mutex_unlock(globals.mutex); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } tech_pvt->ob_calls++; rdest = strchr(caller_profile->destination_number, '/'); *rdest++ = '\0'; switch_copy_string(tech_pvt->session_uuid_str, switch_core_session_get_uuid(*new_session), sizeof(tech_pvt->session_uuid_str)); caller_profile = tech_pvt->caller_profile; caller_profile->destination_number = rdest; switch_mutex_lock(tech_pvt->flag_mutex); switch_set_flag(tech_pvt, TFLAG_OUTBOUND); switch_mutex_unlock(tech_pvt->flag_mutex); switch_channel_set_state(channel, CS_INIT); result=gsmopen_call(tech_pvt, rdest, 30); switch_mutex_unlock(globals.mutex); if(result != 0){ return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } return SWITCH_CAUSE_SUCCESS; } ERRORA("Doh! no new_session\n", GSMOPEN_P_LOG); return SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; } /*! * \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 * */ static switch_status_t load_config(int reload_type) { const char *cf = "gsmopen.conf"; switch_xml_t cfg, xml, global_settings, param, interfaces, myinterface; private_t *tech_pvt = NULL; #ifdef WIN32 DEBUGA_GSMOPEN("Windows CODEPAGE Input =%u\n", GSMOPEN_P_LOG, GetConsoleCP()); SetConsoleCP(65001); DEBUGA_GSMOPEN("Windows CODEPAGE Input =%u\n", GSMOPEN_P_LOG, GetConsoleCP()); DEBUGA_GSMOPEN("Windows CODEPAGE Output =%u\n", GSMOPEN_P_LOG, GetConsoleOutputCP()); SetConsoleOutputCP(65001); DEBUGA_GSMOPEN("Windows CODEPAGE Output =%u\n", GSMOPEN_P_LOG, GetConsoleOutputCP()); //let's hope to have unicode in console now. You need to use Lucida Console or, much better, Courier New font for the command prompt to show unicode #endif // WIN32 NOTICA("GSMOPEN Charset Output Test 0 %s\n", GSMOPEN_P_LOG, "èéòàù"); NOTICA("GSMOPEN Charset Output Test 1 %s\n", GSMOPEN_P_LOG, "ç°§^£"); NOTICA("GSMOPEN Charset Output Test 2 %s\n", GSMOPEN_P_LOG, "новости"); NOTICA("GSMOPEN Charset Output Test 3 %s\n", GSMOPEN_P_LOG, "ﺎﻠﺠﻤﻋﺓ"); NOTICA("GSMOPEN Charset Output Test 4 %s\n", GSMOPEN_P_LOG, "ראת"); NOTICA("GSMOPEN Charset Output Test 5 %s\n", GSMOPEN_P_LOG, "לק"); NOTICA("GSMOPEN Charset Output Test 6 %s\n", GSMOPEN_P_LOG, "人大"); switch_mutex_init(&globals.mutex, SWITCH_MUTEX_NESTED, gsmopen_module_pool); if (!(xml = switch_xml_open_cfg(cf, &cfg, NULL))) { ERRORA("open of %s failed\n", GSMOPEN_P_LOG, cf); running = 0; switch_xml_free(xml); return SWITCH_STATUS_TERM; } switch_mutex_lock(globals.mutex); set_global_dialplan("XML"); DEBUGA_GSMOPEN("Default globals.dialplan=%s\n", GSMOPEN_P_LOG, globals.dialplan); set_global_destination("5000"); DEBUGA_GSMOPEN("Default globals.destination=%s\n", GSMOPEN_P_LOG, globals.destination); set_global_context("default"); DEBUGA_GSMOPEN("Default globals.context=%s\n", GSMOPEN_P_LOG, globals.context); if ((global_settings = switch_xml_child(cfg, "global_settings"))) { for (param = switch_xml_child(global_settings, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "debug")) { DEBUGA_GSMOPEN("globals.debug=%d\n", GSMOPEN_P_LOG, globals.debug); globals.debug = atoi(val); DEBUGA_GSMOPEN("globals.debug=%d\n", GSMOPEN_P_LOG, globals.debug); } else if (!strcasecmp(var, "hold-music")) { switch_set_string(globals.hold_music, val); DEBUGA_GSMOPEN("globals.hold_music=%s\n", GSMOPEN_P_LOG, globals.hold_music); } else if (!strcmp(var, "dialplan")) { set_global_dialplan(val); DEBUGA_GSMOPEN("globals.dialplan=%s\n", GSMOPEN_P_LOG, globals.dialplan); } else if (!strcmp(var, "destination")) { set_global_destination(val); DEBUGA_GSMOPEN("globals.destination=%s\n", GSMOPEN_P_LOG, globals.destination); } else if (!strcmp(var, "context")) { set_global_context(val); DEBUGA_GSMOPEN("globals.context=%s\n", GSMOPEN_P_LOG, globals.context); } } } if ((interfaces = switch_xml_child(cfg, "per_interface_settings"))) { int i = 0; for (myinterface = switch_xml_child(interfaces, "interface"); myinterface; myinterface = myinterface->next) { char *id = (char *) switch_xml_attr(myinterface, "id"); char *name = (char *) switch_xml_attr(myinterface, "name"); const char *context = globals.context; const char *dialplan = globals.dialplan; const char *destination = globals.destination; const char *controldevice_name = "/dev/ttyUSB3"; const char *controldevice_audio_name = "/dev/ttyUSB2"; char *digit_timeout = NULL; char *max_digits = NULL; char *hotline = NULL; char *dial_regex = NULL; char *hold_music = globals.hold_music; char *fail_dial_regex = NULL; const char *enable_callerid = "true"; const char *at_dial_pre_number = "ATD"; const char *at_dial_post_number = ";"; const char *at_dial_expect = "OK"; const char *at_hangup = "ATH"; const char *at_hangup_expect = "OK"; const char *at_answer = "ATA"; const char *at_answer_expect = "OK"; const char *at_send_dtmf = "AT^DTMF"; const char *at_preinit_1 = ""; const char *at_preinit_1_expect = ""; const char *at_preinit_2 = ""; const char *at_preinit_2_expect = ""; const char *at_preinit_3 = ""; const char *at_preinit_3_expect = ""; const char *at_preinit_4 = ""; const char *at_preinit_4_expect = ""; const char *at_preinit_5 = ""; const char *at_preinit_5_expect = ""; const char *at_postinit_1 = "at+cmic=0,9"; const char *at_postinit_1_expect = "OK"; const char *at_postinit_2 = "AT+CKPD=\"EEE\""; const char *at_postinit_2_expect = "OK"; const char *at_postinit_3 = "AT+CSSN=1,0"; const char *at_postinit_3_expect = "OK"; const char *at_postinit_4 = "at+sidet=0"; const char *at_postinit_4_expect = "OK"; const char *at_postinit_5 = "at+clvl=3"; const char *at_postinit_5_expect = "OK"; const char *at_query_battchg = "AT+CBC"; const char *at_query_battchg_expect = "OK"; const char *at_query_signal = "AT+CSQ"; const char *at_query_signal_expect = "OK"; const char *at_call_idle = "+MCST: 1"; const char *at_call_incoming = "RING"; const char *at_call_active = "^CONN:1,0"; const char *at_call_failed = "+MCST: 65"; const char *at_call_calling = "^ORIG:1,0"; const char *at_indicator_noservice_string = "CIEV: 2;0"; const char *at_indicator_nosignal_string = "CIEV: 5;0"; const char *at_indicator_lowsignal_string = "CIEV: 5;1"; const char *at_indicator_lowbattchg_string = "CIEV: 0;1"; const char *at_indicator_nobattchg_string = "CIEV: 0;0"; const char *at_indicator_callactive_string = "CIEV: 3;1"; const char *at_indicator_nocallactive_string = "CIEV: 3;0"; const char *at_indicator_nocallsetup_string = "CIEV: 6;0"; const char *at_indicator_callsetupincoming_string = "CIEV: 6;1"; const char *at_indicator_callsetupoutgoing_string = "CIEV: 6;2"; const char *at_indicator_callsetupremoteringing_string = "CIEV: 6;3"; const char *at_early_audio = "0"; const char *at_after_preinit_pause = "500000"; const char *at_initial_pause = "500000"; const char *at_has_clcc = "0"; const char *at_has_ecam = "0"; const char *gsmopen_sound_rate = "8000"; const char *capture_boost = "0"; const char *playback_boost = "0"; const char *no_sound = "0"; const char *portaudiocindex = "1"; const char *portaudiopindex = "1"; const char *speexecho = "1"; const char *speexpreprocess = "1"; const char *ussd_request_encoding = "auto"; const char *ussd_response_encoding = "auto"; uint32_t interface_id = 0; int controldevice_speed = 115200; //FIXME TODO //int controldevice_audio_speed = 115200; //FIXME TODO uint32_t controldevprotocol = PROTOCOL_AT; //FIXME TODO const char *gsmopen_serial_sync_period = "300"; //FIXME TODO const char *imei = ""; const char *imsi = ""; tech_pvt = NULL; for (param = switch_xml_child(myinterface, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); char *val = (char *) switch_xml_attr_soft(param, "value"); if (!strcasecmp(var, "id")) { id = val; } else if (!strcasecmp(var, "name")) { name = val; } else if (!strcasecmp(var, "context")) { context = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; } else if (!strcasecmp(var, "destination")) { destination = val; } else if (!strcasecmp(var, "controldevice_name")) { controldevice_name = val; } else if (!strcasecmp(var, "controldevice_audio_name")) { controldevice_audio_name = val; } else if (!strcasecmp(var, "digit_timeout")) { digit_timeout = val; } else if (!strcasecmp(var, "max_digits")) { max_digits = val; } else if (!strcasecmp(var, "hotline")) { hotline = val; } else if (!strcasecmp(var, "dial_regex")) { dial_regex = val; } else if (!strcasecmp(var, SWITCH_HOLD_MUSIC_VARIABLE)) { hold_music = val; } else if (!strcasecmp(var, "fail_dial_regex")) { fail_dial_regex = val; } else if (!strcasecmp(var, "enable_callerid")) { enable_callerid = val; } else if (!strcasecmp(var, "at_dial_pre_number")) { at_dial_pre_number = val; } else if (!strcasecmp(var, "at_dial_post_number")) { at_dial_post_number = val; } else if (!strcasecmp(var, "at_dial_expect")) { at_dial_expect = val; } else if (!strcasecmp(var, "at_hangup")) { at_hangup = val; } else if (!strcasecmp(var, "at_hangup_expect")) { at_hangup_expect = val; } else if (!strcasecmp(var, "at_answer")) { at_answer = val; } else if (!strcasecmp(var, "at_answer_expect")) { at_answer_expect = val; } else if (!strcasecmp(var, "at_send_dtmf")) { at_send_dtmf = val; } else if (!strcasecmp(var, "at_preinit_1")) { at_preinit_1 = val; } else if (!strcasecmp(var, "at_preinit_1_expect")) { at_preinit_1_expect = val; } else if (!strcasecmp(var, "at_preinit_2")) { at_preinit_2 = val; } else if (!strcasecmp(var, "at_preinit_2_expect")) { at_preinit_2_expect = val; } else if (!strcasecmp(var, "at_preinit_3")) { at_preinit_3 = val; } else if (!strcasecmp(var, "at_preinit_3_expect")) { at_preinit_3_expect = val; } else if (!strcasecmp(var, "at_preinit_4")) { at_preinit_4 = val; } else if (!strcasecmp(var, "at_preinit_4_expect")) { at_preinit_4_expect = val; } else if (!strcasecmp(var, "at_preinit_5")) { at_preinit_5 = val; } else if (!strcasecmp(var, "at_preinit_5_expect")) { at_preinit_5_expect = val; } else if (!strcasecmp(var, "at_postinit_1")) { at_postinit_1 = val; } else if (!strcasecmp(var, "at_postinit_1_expect")) { at_postinit_1_expect = val; } else if (!strcasecmp(var, "at_postinit_2")) { at_postinit_2 = val; } else if (!strcasecmp(var, "at_postinit_2_expect")) { at_postinit_2_expect = val; } else if (!strcasecmp(var, "at_postinit_3")) { at_postinit_3 = val; } else if (!strcasecmp(var, "at_postinit_3_expect")) { at_postinit_3_expect = val; } else if (!strcasecmp(var, "at_postinit_4")) { at_postinit_4 = val; } else if (!strcasecmp(var, "at_postinit_4_expect")) { at_postinit_4_expect = val; } else if (!strcasecmp(var, "at_postinit_5")) { at_postinit_5 = val; } else if (!strcasecmp(var, "at_postinit_5_expect")) { at_postinit_5_expect = val; } else if (!strcasecmp(var, "at_query_battchg")) { at_query_battchg = val; } else if (!strcasecmp(var, "at_query_battchg_expect")) { at_query_battchg_expect = val; } else if (!strcasecmp(var, "at_query_signal")) { at_query_signal = val; } else if (!strcasecmp(var, "at_query_signal_expect")) { at_query_signal_expect = val; } else if (!strcasecmp(var, "at_call_idle")) { at_call_idle = val; } else if (!strcasecmp(var, "at_call_incoming")) { at_call_incoming = val; } else if (!strcasecmp(var, "at_call_active")) { at_call_active = val; } else if (!strcasecmp(var, "at_call_failed")) { at_call_failed = val; } else if (!strcasecmp(var, "at_call_calling")) { at_call_calling = val; } else if (!strcasecmp(var, "at_indicator_noservice_string")) { at_indicator_noservice_string = val; } else if (!strcasecmp(var, "at_indicator_nosignal_string")) { at_indicator_nosignal_string = val; } else if (!strcasecmp(var, "at_indicator_lowsignal_string")) { at_indicator_lowsignal_string = val; } else if (!strcasecmp(var, "at_indicator_lowbattchg_string")) { at_indicator_lowbattchg_string = val; } else if (!strcasecmp(var, "at_indicator_nobattchg_string")) { at_indicator_nobattchg_string = val; } else if (!strcasecmp(var, "at_indicator_callactive_string")) { at_indicator_callactive_string = val; } else if (!strcasecmp(var, "at_indicator_nocallactive_string")) { at_indicator_nocallactive_string = val; } else if (!strcasecmp(var, "at_indicator_nocallsetup_string")) { at_indicator_nocallsetup_string = val; } else if (!strcasecmp(var, "at_indicator_callsetupincoming_string")) { at_indicator_callsetupincoming_string = val; } else if (!strcasecmp(var, "at_indicator_callsetupoutgoing_string")) { at_indicator_callsetupoutgoing_string = val; } else if (!strcasecmp(var, "at_indicator_callsetupremoteringing_string")) { at_indicator_callsetupremoteringing_string = val; } else if (!strcasecmp(var, "portaudiocindex")) { portaudiocindex = val; } else if (!strcasecmp(var, "portaudiopindex")) { portaudiopindex = val; } else if (!strcasecmp(var, "speexecho")) { speexecho = val; } else if (!strcasecmp(var, "speexpreprocess")) { speexpreprocess = val; } else if (!strcasecmp(var, "at_early_audio")) { at_early_audio = val; } else if (!strcasecmp(var, "at_after_preinit_pause")) { at_after_preinit_pause = val; } else if (!strcasecmp(var, "at_initial_pause")) { at_initial_pause = val; } else if (!strcasecmp(var, "at_has_clcc")) { at_has_clcc = val; } else if (!strcasecmp(var, "at_has_ecam")) { at_has_ecam = val; } else if (!strcasecmp(var, "gsmopen_sound_rate")) { gsmopen_sound_rate = val; } else if (!strcasecmp(var, "capture_boost")) { capture_boost = val; } else if (!strcasecmp(var, "playback_boost")) { playback_boost = val; } else if (!strcasecmp(var, "no_sound")) { no_sound = val; } else if (!strcasecmp(var, "imsi")) { imsi = val; } else if (!strcasecmp(var, "imei")) { imei = val; } else if (!strcasecmp(var, "gsmopen_serial_sync_period")) { gsmopen_serial_sync_period = val; } else if (!strcasecmp(var, "ussd_request_encoding")) { ussd_request_encoding = val; } else if (!strcasecmp(var, "ussd_response_encoding")) { ussd_response_encoding = val; } } if (reload_type == SOFT_RELOAD) { char the_interface[256]; sprintf(the_interface, "#%s", name); if (interface_exists(the_interface) == SWITCH_STATUS_SUCCESS) { continue; } } if (!id) { ERRORA("interface missing REQUIRED param 'id'\n", GSMOPEN_P_LOG); continue; } if (switch_is_number(id)) { interface_id = atoi(id); } else { ERRORA("interface param 'id' MUST be a number, now id='%s'\n", GSMOPEN_P_LOG, id); continue; } if (!switch_is_number(at_early_audio)) { ERRORA("interface param 'at_early_audio' MUST be a number, now at_early_audio='%s'\n", GSMOPEN_P_LOG, at_early_audio); continue; } if (!switch_is_number(at_after_preinit_pause)) { ERRORA("interface param 'at_after_preinit_pause' MUST be a number, now at_after_preinit_pause='%s'\n", GSMOPEN_P_LOG, at_after_preinit_pause); continue; } if (!switch_is_number(at_initial_pause)) { ERRORA("interface param 'at_initial_pause' MUST be a number, now at_initial_pause='%s'\n", GSMOPEN_P_LOG, at_initial_pause); continue; } if (!switch_is_number(at_has_clcc)) { ERRORA("interface param 'at_has_clcc' MUST be a number, now at_has_clcc='%s'\n", GSMOPEN_P_LOG, at_has_clcc); continue; } if (!switch_is_number(at_has_ecam)) { ERRORA("interface param 'at_has_ecam' MUST be a number, now at_has_ecam='%s'\n", GSMOPEN_P_LOG, at_has_ecam); continue; } if (!switch_is_number(gsmopen_sound_rate)) { ERRORA("interface param 'gsmopen_sound_rate' MUST be a number, now gsmopen_sound_rate='%s'\n", GSMOPEN_P_LOG, gsmopen_sound_rate); continue; } if (!switch_is_number(capture_boost)) { ERRORA("interface param 'capture_boost' MUST be a number, now capture_boost='%s'\n", GSMOPEN_P_LOG, capture_boost); continue; } if (!switch_is_number(playback_boost)) { ERRORA("interface param 'playback_boost' MUST be a number, now playback_boost='%s'\n", GSMOPEN_P_LOG, playback_boost); continue; } if (!switch_is_number(no_sound)) { ERRORA("interface param 'no_sound' MUST be a number, now no_sound='%s'\n", GSMOPEN_P_LOG, no_sound); continue; } if (!switch_is_number(gsmopen_serial_sync_period)) { 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); continue; } if (interface_id && interface_id < GSMOPEN_MAX_INTERFACES) { private_t newconf; //int res = 0; memset(&newconf, '\0', sizeof(newconf)); globals.GSMOPEN_INTERFACES[interface_id] = newconf; switch_mutex_init(&globals.GSMOPEN_INTERFACES[interface_id].controldev_lock, SWITCH_MUTEX_NESTED, gsmopen_module_pool); switch_mutex_init(&globals.GSMOPEN_INTERFACES[interface_id].controldev_audio_lock, SWITCH_MUTEX_NESTED, gsmopen_module_pool); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].id, id); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].name, name); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].context, context); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].dialplan, dialplan); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].destination, destination); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].controldevice_name, controldevice_name); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].controldevice_audio_name, controldevice_audio_name); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].dial_regex, dial_regex); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].hold_music, hold_music); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].fail_dial_regex, fail_dial_regex); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_dial_pre_number, at_dial_pre_number); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_dial_post_number, at_dial_post_number); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_dial_expect, at_dial_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_hangup, at_hangup); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_hangup_expect, at_hangup_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_answer, at_answer); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_answer_expect, at_answer_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_send_dtmf, at_send_dtmf); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_1, at_preinit_1); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_1_expect, at_preinit_1_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_2, at_preinit_2); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_2_expect, at_preinit_2_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_3, at_preinit_3); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_3_expect, at_preinit_3_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_4, at_preinit_4); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_4_expect, at_preinit_4_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_5, at_preinit_5); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_preinit_5_expect, at_preinit_5_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_1, at_postinit_1); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_1_expect, at_postinit_1_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_2, at_postinit_2); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_2_expect, at_postinit_2_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_3, at_postinit_3); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_3_expect, at_postinit_3_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_4, at_postinit_4); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_4_expect, at_postinit_4_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_5, at_postinit_5); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_postinit_5_expect, at_postinit_5_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_battchg, at_query_battchg); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_battchg_expect, at_query_battchg_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_signal, at_query_signal); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_query_signal_expect, at_query_signal_expect); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_idle, at_call_idle); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_incoming, at_call_incoming); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_active, at_call_active); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_failed, at_call_failed); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_call_calling, at_call_calling); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_noservice_string, at_indicator_noservice_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nosignal_string, at_indicator_nosignal_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_lowsignal_string, at_indicator_lowsignal_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_lowbattchg_string, at_indicator_lowbattchg_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nobattchg_string, at_indicator_nobattchg_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callactive_string, at_indicator_callactive_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nocallactive_string, at_indicator_nocallactive_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_nocallsetup_string, at_indicator_nocallsetup_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callsetupincoming_string, at_indicator_callsetupincoming_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callsetupoutgoing_string, at_indicator_callsetupoutgoing_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].at_indicator_callsetupremoteringing_string, at_indicator_callsetupremoteringing_string); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].imsi, imsi); switch_set_string(globals.GSMOPEN_INTERFACES[interface_id].imei, imei); globals.GSMOPEN_INTERFACES[interface_id].at_early_audio = atoi(at_early_audio); globals.GSMOPEN_INTERFACES[interface_id].at_after_preinit_pause = atoi(at_after_preinit_pause); globals.GSMOPEN_INTERFACES[interface_id].at_initial_pause = atoi(at_initial_pause); globals.GSMOPEN_INTERFACES[interface_id].at_has_clcc = atoi(at_has_clcc); globals.GSMOPEN_INTERFACES[interface_id].at_has_ecam = atoi(at_has_ecam); globals.GSMOPEN_INTERFACES[interface_id].capture_boost = atoi(capture_boost); globals.GSMOPEN_INTERFACES[interface_id].playback_boost = atoi(playback_boost); globals.GSMOPEN_INTERFACES[interface_id].no_sound = atoi(no_sound); globals.GSMOPEN_INTERFACES[interface_id].gsmopen_serial_sync_period = atoi(gsmopen_serial_sync_period); globals.GSMOPEN_INTERFACES[interface_id].ussd_request_encoding = strcasecmp(ussd_request_encoding, "plain") == 0 ? USSD_ENCODING_PLAIN : strcasecmp(ussd_request_encoding, "hex7") == 0 ? USSD_ENCODING_HEX_7BIT : strcasecmp(ussd_request_encoding, "hex8") == 0 ? USSD_ENCODING_HEX_8BIT : strcasecmp(ussd_request_encoding, "ucs2") == 0 ? USSD_ENCODING_UCS2 : USSD_ENCODING_AUTO; globals.GSMOPEN_INTERFACES[interface_id].ussd_response_encoding = strcasecmp(ussd_response_encoding, "plain") == 0 ? USSD_ENCODING_PLAIN : strcasecmp(ussd_response_encoding, "hex7") == 0 ? USSD_ENCODING_HEX_7BIT : strcasecmp(ussd_response_encoding, "hex8") == 0 ? USSD_ENCODING_HEX_8BIT : strcasecmp(ussd_response_encoding, "ucs2") == 0 ? USSD_ENCODING_UCS2 : USSD_ENCODING_AUTO; globals.GSMOPEN_INTERFACES[interface_id].controldevice_speed = controldevice_speed; //FIXME globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol = controldevprotocol; //FIXME globals.GSMOPEN_INTERFACES[interface_id].running = 1; //FIXME gsmopen_store_boost((char *) capture_boost, &globals.GSMOPEN_INTERFACES[interface_id].capture_boost); //FIXME gsmopen_store_boost((char *) playback_boost, &globals.GSMOPEN_INTERFACES[interface_id].playback_boost); //FIXME } else { ERRORA("interface id %u is higher than GSMOPEN_MAX_INTERFACES (%d)\n", GSMOPEN_P_LOG, interface_id, GSMOPEN_MAX_INTERFACES); alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "interface id is higher than GSMOPEN_MAX_INTERFACES"); continue; } } #ifndef WIN32 find_ttyusb_devices(NULL, "/sys/devices"); #endif// WIN32 for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { switch_threadattr_t *gsmopen_api_thread_attr = NULL; int res = 0; int interface_id = i; tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id]; if (strlen(globals.GSMOPEN_INTERFACES[i].name) && !globals.GSMOPEN_INTERFACES[i].active) { WARNINGA("STARTING interface_id=%u\n", GSMOPEN_P_LOG, interface_id); DEBUGA_GSMOPEN("id=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].id); DEBUGA_GSMOPEN("name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].name); DEBUGA_GSMOPEN("hold-music=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].hold_music); DEBUGA_GSMOPEN("context=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].context); DEBUGA_GSMOPEN("dialplan=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].dialplan); DEBUGA_GSMOPEN("destination=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].destination); DEBUGA_GSMOPEN("imei=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].imei); DEBUGA_GSMOPEN("imsi=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].imsi); DEBUGA_GSMOPEN("controldevice_name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].controldevice_name); DEBUGA_GSMOPEN("controldevice_audio_name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[interface_id].controldevice_audio_name); DEBUGA_GSMOPEN("gsmopen_serial_sync_period=%d\n", GSMOPEN_P_LOG, (int) globals.GSMOPEN_INTERFACES[interface_id].gsmopen_serial_sync_period); /* init the serial port */ if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) { globals.GSMOPEN_INTERFACES[interface_id].controldevfd = gsmopen_serial_init(&globals.GSMOPEN_INTERFACES[interface_id], globals.GSMOPEN_INTERFACES[interface_id].controldevice_speed); if (globals.GSMOPEN_INTERFACES[interface_id].controldevfd == -1) { ERRORA("STARTING interface_id=%u FAILED: gsmopen_serial_init failed\n", GSMOPEN_P_LOG, interface_id); globals.GSMOPEN_INTERFACES[interface_id].running = 0; alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_init failed"); globals.GSMOPEN_INTERFACES[interface_id].active = 0; globals.GSMOPEN_INTERFACES[interface_id].name[0] = '\0'; continue; } } /* config the phone/modem on the serial port */ if (globals.GSMOPEN_INTERFACES[interface_id].controldevprotocol != PROTOCOL_NO_SERIAL) { res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]); if (res) { int count = 0; ERRORA("gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG); while (res && count < 5) { switch_sleep(100000); //0.1 seconds res = gsmopen_serial_config(&globals.GSMOPEN_INTERFACES[interface_id]); count++; if (res) { ERRORA("%d: gsmopen_serial_config failed, let's try again\n", GSMOPEN_P_LOG, count); } } if (res) { ERRORA("STARTING interface_id=%u FAILED\n", GSMOPEN_P_LOG, interface_id); globals.GSMOPEN_INTERFACES[interface_id].running = 0; alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "gsmopen_serial_config failed"); globals.GSMOPEN_INTERFACES[interface_id].active = 0; globals.GSMOPEN_INTERFACES[interface_id].name[0] = '\0'; continue; } } } if (globals.GSMOPEN_INTERFACES[interface_id].no_sound == 0) { if (serial_audio_init(&globals.GSMOPEN_INTERFACES[interface_id])) { ERRORA("serial_audio_init failed\n", GSMOPEN_P_LOG); ERRORA("STARTING interface_id=%u FAILED\n", GSMOPEN_P_LOG, interface_id); globals.GSMOPEN_INTERFACES[interface_id].running = 0; alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "serial_audio_init failed"); globals.GSMOPEN_INTERFACES[interface_id].active = 0; globals.GSMOPEN_INTERFACES[interface_id].name[0] = '\0'; continue; } if (serial_audio_shutdown(&globals.GSMOPEN_INTERFACES[interface_id])) { ERRORA("serial_audio_shutdown failed\n", GSMOPEN_P_LOG); ERRORA("STARTING interface_id=%u FAILED\n", GSMOPEN_P_LOG, interface_id); globals.GSMOPEN_INTERFACES[interface_id].running = 0; alarm_event(&globals.GSMOPEN_INTERFACES[interface_id], ALARM_FAILED_INTERFACE, "serial_audio_shutdown failed"); globals.GSMOPEN_INTERFACES[interface_id].active = 0; globals.GSMOPEN_INTERFACES[interface_id].name[0] = '\0'; continue; } } globals.GSMOPEN_INTERFACES[interface_id].active = 1; //gsmopen_store_boost((char *) capture_boost, &globals.GSMOPEN_INTERFACES[interface_id].capture_boost); //FIXME //gsmopen_store_boost((char *) playback_boost, &globals.GSMOPEN_INTERFACES[interface_id].playback_boost); //FIXME switch_sleep(100000); switch_threadattr_create(&gsmopen_api_thread_attr, gsmopen_module_pool); switch_threadattr_stacksize_set(gsmopen_api_thread_attr, SWITCH_THREAD_STACKSIZE); switch_thread_create(&globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread, gsmopen_api_thread_attr, gsmopen_do_gsmopenapi_thread, &globals.GSMOPEN_INTERFACES[interface_id], gsmopen_module_pool); switch_sleep(100000); WARNINGA("STARTED interface_id=%u\n", GSMOPEN_P_LOG, interface_id); /* How many real intterfaces */ globals.real_interfaces++; } } for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { if (strlen(globals.GSMOPEN_INTERFACES[i].name)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; DEBUGA_GSMOPEN("id=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].id); DEBUGA_GSMOPEN("name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].name); DEBUGA_GSMOPEN("context=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].context); DEBUGA_GSMOPEN("hold-music=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].hold_music); DEBUGA_GSMOPEN("dialplan=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].dialplan); DEBUGA_GSMOPEN("destination=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].destination); DEBUGA_GSMOPEN("imei=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].imei); DEBUGA_GSMOPEN("imsi=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].imsi); DEBUGA_GSMOPEN("controldevice_name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].controldevice_name); DEBUGA_GSMOPEN("gsmopen_serial_sync_period=%d\n", GSMOPEN_P_LOG, (int) globals.GSMOPEN_INTERFACES[i].gsmopen_serial_sync_period); DEBUGA_GSMOPEN("controldevice_audio_name=%s\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].controldevice_audio_name); } } } switch_mutex_unlock(globals.mutex); switch_xml_free(xml); return SWITCH_STATUS_SUCCESS; } static switch_status_t chat_send(switch_event_t *message_event) { char *user = NULL, *host, *f_user = NULL, *f_host = NULL, *f_resource = NULL; private_t *tech_pvt = NULL; int i = 0, found = 0; const char *proto; const char *from; const char *to; const char *subject; const char *body; const char *hint; proto = switch_event_get_header(message_event, "proto"); from = switch_event_get_header(message_event, "from"); to = switch_event_get_header(message_event, "to"); subject = switch_event_get_header(message_event, "subject"); body = switch_event_get_body(message_event); hint = switch_event_get_header(message_event, "hint"); switch_assert(proto != NULL); 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, hint ? hint : "NULL"); if (!to || !strlen(to)) { ERRORA("Missing To: header.\n", GSMOPEN_P_LOG); return SWITCH_STATUS_SUCCESS; } if ((!from && !hint) || (!strlen(from) && !strlen(hint))) { ERRORA("Missing From: AND Hint: headers.\n", GSMOPEN_P_LOG); return SWITCH_STATUS_SUCCESS; } if (from && (f_user = strdup(from))) { if ((f_host = strchr(f_user, '@'))) { *f_host++ = '\0'; if ((f_resource = strchr(f_host, '/'))) { *f_resource++ = '\0'; } } } if (hint == NULL || !strlen(hint)) { //FIXME FIXME FIXME hint = from; } if (subject == NULL || !strlen(subject)) { //FIXME FIXME FIXME subject = "SIMPLE MESSAGE"; } if (to && (user = strdup(to))) { if ((host = strchr(user, '@'))) { *host++ = '\0'; } 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, hint ? hint : "NULL"); if (hint && strlen(hint)) { //in hint we receive the interface name to use for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, hint, strlen(hint)) == 0)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; DEBUGA_GSMOPEN("Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", GSMOPEN_P_LOG, i, globals.GSMOPEN_INTERFACES[i].name); found = 1; break; } } } if (!found) { ERRORA("ERROR: A GSMopen interface with name='%s' or one with SIM_number='%s' was not found\n", GSMOPEN_P_LOG, hint ? hint : "NULL", from ? from : "NULL"); goto end; } else { if (strcasecmp(to, "ussd") == 0) { gsmopen_ussd(tech_pvt, (char *) body, 0); } else { gsmopen_sendsms(tech_pvt, (char *) to, (char *) body); } } } end: switch_safe_free(user); switch_safe_free(f_user); return SWITCH_STATUS_SUCCESS; } static switch_status_t compat_chat_send(const char *proto, const char *from, const char *to, const char *subject, const char *body, const char *type, const char *hint) { switch_event_t *message_event; switch_status_t status; if (switch_event_create(&message_event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "proto", proto); switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "from", from); switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "to", to); switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "subject", subject); switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "type", type); switch_event_add_header_string(message_event, SWITCH_STACK_BOTTOM, "hint", hint); if (body) { switch_event_add_body(message_event, "%s", body); } } else { abort(); } status = chat_send(message_event); switch_event_destroy(&message_event); return status; } SWITCH_MODULE_LOAD_FUNCTION(mod_gsmopen_load) { switch_api_interface_t *commands_api_interface; switch_chat_interface_t *chat_interface; gsmopen_module_pool = pool; memset(&globals, '\0', sizeof(globals)); running = 1; if (load_config(FULL_RELOAD) != SWITCH_STATUS_SUCCESS) { running = 0; return SWITCH_STATUS_FALSE; } if (switch_event_reserve_subclass(MY_EVENT_INCOMING_SMS) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Couldn't register subclass!\n"); return SWITCH_STATUS_GENERR; } *module_interface = switch_loadable_module_create_module_interface(pool, modname); gsmopen_endpoint_interface = (switch_endpoint_interface_t *) switch_loadable_module_create_interface(*module_interface, SWITCH_ENDPOINT_INTERFACE); gsmopen_endpoint_interface->interface_name = "gsmopen"; gsmopen_endpoint_interface->io_routines = &gsmopen_io_routines; gsmopen_endpoint_interface->state_handler = &gsmopen_state_handlers; if (running) { SWITCH_ADD_API(commands_api_interface, "gsm", "gsm console AT_command", gsm_function, GSM_SYNTAX); SWITCH_ADD_API(commands_api_interface, "gsmopen", "gsmopen interface AT_command", gsmopen_function, GSMOPEN_SYNTAX); SWITCH_ADD_API(commands_api_interface, "gsmopen_boost_audio", "gsmopen_boost_audio interface AT_command", gsmopen_boost_audio_function, GSMOPEN_BOOST_AUDIO_SYNTAX); SWITCH_ADD_API(commands_api_interface, "gsmopen_dump", "gsmopen_dump interface", gsmopen_dump_function, GSMOPEN_DUMP_SYNTAX); SWITCH_ADD_API(commands_api_interface, "gsmopen_sendsms", "gsmopen_sendsms interface destination_number SMS_text", sendsms_function, SENDSMS_SYNTAX); SWITCH_ADD_API(commands_api_interface, "gsmopen_ussd", "gsmopen_ussd interface ussd_code wait_seconds", gsmopen_ussd_function, SENDSMS_SYNTAX); SWITCH_ADD_CHAT(chat_interface, GSMOPEN_CHAT_PROTO, chat_send); switch_console_set_complete("add gsm list"); switch_console_set_complete("add gsm list full"); switch_console_set_complete("add gsm console ::gsm::list_interfaces"); switch_console_set_complete("add gsm remove ::gsm::list_interfaces"); switch_console_set_complete("add gsm reload"); switch_console_set_complete("add gsmopen ::gsm::list_interfaces"); switch_console_set_complete("add gsmopen_dump list"); switch_console_set_complete("add gsmopen_dump ::gsm::list_interfaces"); switch_console_set_complete("add gsmopen_ussd ::gsm::list_interfaces"); switch_console_set_complete("add gsmopen_sendsms ::gsm::list_interfaces"); switch_console_set_complete("add gsmopen_boost_audio ::gsm::list_interfaces"); switch_console_add_complete_func("::gsm::list_interfaces", list_interfaces); /* indicate that the module should continue to be loaded */ return SWITCH_STATUS_SUCCESS; } else return SWITCH_STATUS_FALSE; } SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_gsmopen_shutdown) { int x; private_t *tech_pvt = NULL; switch_status_t status; #ifdef WIN32 switch_size_t howmany = 8; #else unsigned int howmany = 8; #endif int interface_id; int fd; running = 0; for (interface_id = 0; interface_id < GSMOPEN_MAX_INTERFACES; interface_id++) { tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id]; if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) { WARNINGA("SHUTDOWN interface_id=%d\n", GSMOPEN_P_LOG, interface_id); globals.GSMOPEN_INTERFACES[interface_id].running = 0; if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) { #ifdef WIN32 switch_file_write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", &howmany); // let's the controldev_thread die #else /* WIN32 */ howmany = write(tech_pvt->GSMopenHandles.fdesc[1], "sciutati", howmany); #endif /* WIN32 */ } x = 10; while (x) { //FIXME 0.5 seconds? x--; switch_yield(50000); } if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread) { switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_signaling_thread); } if (globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread) { switch_thread_join(&status, globals.GSMOPEN_INTERFACES[interface_id].gsmopen_api_thread); } x = 10; while (x) { //FIXME 0.5 seconds? x--; switch_yield(50000); } fd = tech_pvt->controldevfd; if (fd) { tech_pvt->controldevfd = -1; DEBUGA_GSMOPEN("SHUTDOWN tech_pvt->controldevfd=%d\n", GSMOPEN_P_LOG, tech_pvt->controldevfd); } if (!globals.GSMOPEN_INTERFACES[interface_id].no_sound) { serial_audio_shutdown(tech_pvt); } if (tech_pvt->serialPort_serial_control) { int res; res = tech_pvt->serialPort_serial_control->Close(); DEBUGA_GSMOPEN("serial_shutdown res=%d (controldevfd is %d)\n", GSMOPEN_P_LOG, res, tech_pvt->controldevfd); } #ifndef WIN32 shutdown(tech_pvt->audiogsmopenpipe[0], 2); close(tech_pvt->audiogsmopenpipe[0]); shutdown(tech_pvt->audiogsmopenpipe[1], 2); close(tech_pvt->audiogsmopenpipe[1]); shutdown(tech_pvt->audiopipe[0], 2); close(tech_pvt->audiopipe[0]); shutdown(tech_pvt->audiopipe[1], 2); close(tech_pvt->audiopipe[1]); shutdown(tech_pvt->GSMopenHandles.fdesc[0], 2); close(tech_pvt->GSMopenHandles.fdesc[0]); shutdown(tech_pvt->GSMopenHandles.fdesc[1], 2); close(tech_pvt->GSMopenHandles.fdesc[1]); #endif /* WIN32 */ } } switch_event_free_subclass(MY_EVENT_INCOMING_SMS); switch_safe_free(globals.dialplan); switch_safe_free(globals.context); switch_safe_free(globals.destination); switch_safe_free(globals.codec_string); switch_safe_free(globals.codec_rates_string); return SWITCH_STATUS_SUCCESS; } void *SWITCH_THREAD_FUNC gsmopen_do_gsmopenapi_thread(switch_thread_t *thread, void *obj) { return gsmopen_do_gsmopenapi_thread_func(obj); } int dtmf_received(private_t *tech_pvt, char *value) { switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; session = switch_core_session_locate(tech_pvt->session_uuid_str); channel = switch_core_session_get_channel(session); if (channel) { if (!switch_channel_test_flag(channel, CF_BRIDGED)) { switch_dtmf_t dtmf = { (char) value[0], switch_core_default_dtmf_duration(0) }; DEBUGA_GSMOPEN("received DTMF %c on channel %s\n", GSMOPEN_P_LOG, dtmf.digit, switch_channel_get_name(channel)); switch_mutex_lock(tech_pvt->flag_mutex); //FIXME: why sometimes DTMFs from here do not seems to be get by FS? switch_channel_queue_dtmf(channel, &dtmf); switch_set_flag(tech_pvt, TFLAG_DTMF); switch_mutex_unlock(tech_pvt->flag_mutex); } else { DEBUGA_GSMOPEN ("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)); } } else { WARNINGA("received %c DTMF, but no channel?\n", GSMOPEN_P_LOG, value[0]); } switch_core_session_rwunlock(session); return 0; } int new_inbound_channel(private_t *tech_pvt) { switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; switch_assert(tech_pvt != NULL); tech_pvt->ib_calls++; if ((session = switch_core_session_request(gsmopen_endpoint_interface, SWITCH_CALL_DIRECTION_INBOUND, SOF_NONE, NULL)) != 0) { DEBUGA_GSMOPEN("2 SESSION_REQUEST %s\n", GSMOPEN_P_LOG, switch_core_session_get_uuid(session)); switch_core_session_add_stream(session, NULL); channel = switch_core_session_get_channel(session); if (!channel) { ERRORA("Doh! no channel?\n", GSMOPEN_P_LOG); switch_core_session_destroy(&session); return 0; } if (gsmopen_tech_init(tech_pvt, session) != SWITCH_STATUS_SUCCESS) { ERRORA("Doh! no tech_init?\n", GSMOPEN_P_LOG); switch_core_session_destroy(&session); return 0; } if ((tech_pvt->caller_profile = switch_caller_profile_new(switch_core_session_get_pool(session), "gsmopen", tech_pvt->dialplan, tech_pvt->callid_name, tech_pvt->callid_number, NULL, NULL, NULL, NULL, "mod_gsmopen", tech_pvt->context, tech_pvt->destination)) != 0) { char name[128]; switch_snprintf(name, sizeof(name), "gsmopen/%s", tech_pvt->name); switch_channel_set_name(channel, name); switch_channel_set_caller_profile(channel, tech_pvt->caller_profile); } switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { ERRORA("Error spawning thread\n", GSMOPEN_P_LOG); switch_core_session_destroy(&session); return 0; } } DEBUGA_GSMOPEN("EXITING new_inbound_channel\n", GSMOPEN_P_LOG); return 0; } int remote_party_is_ringing(private_t *tech_pvt) { switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; if (!zstr(tech_pvt->session_uuid_str)) { session = switch_core_session_locate(tech_pvt->session_uuid_str); } else { ERRORA("No session???\n", GSMOPEN_P_LOG); goto done; } if (session) { channel = switch_core_session_get_channel(session); } else { ERRORA("No session???\n", GSMOPEN_P_LOG); goto done; } if (channel) { switch_channel_mark_ring_ready(channel); DEBUGA_GSMOPEN("gsmopen_call: REMOTE PARTY RINGING\n", GSMOPEN_P_LOG); } else { ERRORA("No channel???\n", GSMOPEN_P_LOG); } switch_core_session_rwunlock(session); done: return 0; } int remote_party_is_early_media(private_t *tech_pvt) { switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; if (!zstr(tech_pvt->session_uuid_str)) { session = switch_core_session_locate(tech_pvt->session_uuid_str); } else { ERRORA("No session???\n\n\n", GSMOPEN_P_LOG); //TODO: kill the bastard goto done; } if (session) { channel = switch_core_session_get_channel(session); switch_core_session_add_stream(session, NULL); } else { ERRORA("No session???\n", GSMOPEN_P_LOG); //TODO: kill the bastard goto done; } if (channel) { switch_channel_mark_pre_answered(channel); DEBUGA_GSMOPEN("gsmopen_call: REMOTE PARTY EARLY MEDIA\n", GSMOPEN_P_LOG); } else { ERRORA("No channel???\n", GSMOPEN_P_LOG); //TODO: kill the bastard } switch_core_session_rwunlock(session); done: return 0; } int outbound_channel_answered(private_t *tech_pvt) { switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; if (!zstr(tech_pvt->session_uuid_str)) { session = switch_core_session_locate(tech_pvt->session_uuid_str); } else { ERRORA("No session???\n", GSMOPEN_P_LOG); goto done; } if (session) { channel = switch_core_session_get_channel(session); } else { ERRORA("No channel???\n", GSMOPEN_P_LOG); goto done; } if (channel) { switch_channel_mark_answered(channel); tech_pvt->phone_callflow = GSMOPEN_STATE_UP; tech_pvt->interface_state = GSMOPEN_STATE_UP; } else { ERRORA("No channel???\n", GSMOPEN_P_LOG); } switch_core_session_rwunlock(session); done: DEBUGA_GSMOPEN("outbound_channel_answered!\n", GSMOPEN_P_LOG); return 0; } private_t *find_available_gsmopen_interface_rr(private_t *tech_pvt_calling) { private_t *tech_pvt = NULL; int i; switch_mutex_lock(globals.mutex); /* Fact is the real interface start from 1 */ //XXX no, is just a convention, but you can have it start from 0. I do not, for aestetic reasons :-) for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { int interface_id; interface_id = globals.next_interface; globals.next_interface = interface_id + 1 < GSMOPEN_MAX_INTERFACES ? interface_id + 1 : 0; if (strlen(globals.GSMOPEN_INTERFACES[interface_id].name)) { int gsmopen_state = 0; tech_pvt = &globals.GSMOPEN_INTERFACES[interface_id]; gsmopen_state = tech_pvt->interface_state; DEBUGA_GSMOPEN("gsmopen interface: %d, name: %s, state: %d\n", GSMOPEN_P_LOG, interface_id, globals.GSMOPEN_INTERFACES[interface_id].name, gsmopen_state); if ((tech_pvt_calling ? strcmp(tech_pvt->gsmopen_user, tech_pvt_calling->gsmopen_user) : 1) && (GSMOPEN_STATE_DOWN == gsmopen_state || 0 == gsmopen_state) && (tech_pvt->phone_callflow == CALLFLOW_STATUS_FINISHED || 0 == tech_pvt->phone_callflow)) { DEBUGA_GSMOPEN("returning as available gsmopen interface name: %s, state: %d callflow: %d\n", GSMOPEN_P_LOG, tech_pvt->name, gsmopen_state, tech_pvt->phone_callflow); if (tech_pvt_calling == NULL) { tech_pvt->interface_state = GSMOPEN_STATE_SELECTED; } switch_mutex_unlock(globals.mutex); return tech_pvt; } } } switch_mutex_unlock(globals.mutex); return NULL; } SWITCH_STANDARD_API(gsm_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; if (globals.gsm_console) stream->write_function(stream, "gsm console is: |||%s|||\n", globals.gsm_console->name); else stream->write_function(stream, "gsm console is NOT yet assigned\n"); if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if (!argc || !argv[0]) { stream->write_function(stream, "%s", GSM_SYNTAX); goto end; } if (!strcasecmp(argv[0], "list")) { int i; unsigned int ib = 0; unsigned int ib_failed = 0; unsigned int ob = 0; unsigned int ob_failed = 0; char next_flag_char = ' '; stream->write_function(stream, "F ID Name Operator IMEI IB (F/T) OB (F/T) State CallFlw UUID\n"); stream->write_function(stream, "= == ========== ================ =============== ========= ========= ======= =============== ====\n"); for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { if (strlen(globals.GSMOPEN_INTERFACES[i].name)) { next_flag_char = i == globals.next_interface ? '*' : ' '; ib += globals.GSMOPEN_INTERFACES[i].ib_calls; ib_failed += globals.GSMOPEN_INTERFACES[i].ib_failed_calls; ob += globals.GSMOPEN_INTERFACES[i].ob_calls; ob_failed += globals.GSMOPEN_INTERFACES[i].ob_failed_calls; stream->write_function(stream, "%c %-2d %-10s %-16.16s %-15s %4u/%-4u %4u/%-4u %-7s %-15s %s\n", next_flag_char, i, globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].operator_name, globals.GSMOPEN_INTERFACES[i].imei, globals.GSMOPEN_INTERFACES[i].ib_failed_calls, globals.GSMOPEN_INTERFACES[i].ib_calls, globals.GSMOPEN_INTERFACES[i].ob_failed_calls, globals.GSMOPEN_INTERFACES[i].ob_calls, interface_status[globals.GSMOPEN_INTERFACES[i].interface_state], phone_callflow[globals.GSMOPEN_INTERFACES[i].phone_callflow], globals.GSMOPEN_INTERFACES[i].session_uuid_str); } else if (argc > 1 && !strcasecmp(argv[1], "full")) { stream->write_function(stream, "%c %d\n", next_flag_char, i); } } stream->write_function(stream, "\nTotal Interfaces: %d IB Calls(Failed/Total): %u/%u OB Calls(Failed/Total): %u/%u\n", globals.real_interfaces > 0 ? globals.real_interfaces : 0, ib_failed, ib, ob_failed, ob); } else if (!strcasecmp(argv[0], "console")) { int i; int found = 0; if (argc == 2) { for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[1], strlen(argv[1])) == 0)) { globals.gsm_console = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "gsm console is now: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name); stream->write_function(stream, "gsm console is: |||%s|||\n", globals.gsm_console->name); found = 1; break; } } if (!found) stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[1]); } else { stream->write_function(stream, "-ERR Usage: gsm console interface_name\n"); goto end; } } else if (!strcasecmp(argv[0], "ciapalino")) { } else if (!strcasecmp(argv[0], "reload")) { if (load_config(SOFT_RELOAD) != SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "gsm reload failed\n"); } else { stream->write_function(stream, "gsm reload success\n"); } } else if (!strcasecmp(argv[0], "remove")) { if (argc == 2) { if (remove_interface(argv[1]) == SWITCH_STATUS_SUCCESS) { if (interface_exists(argv[1]) == SWITCH_STATUS_SUCCESS) { stream->write_function(stream, "gsm remove '%s' failed\n", argv[1]); } else { stream->write_function(stream, "gsm remove '%s' success\n", argv[1]); } } } else { stream->write_function(stream, "-ERR Usage: gsm remove interface_name\n"); goto end; } } else { if (globals.gsm_console) gsmopen_serial_write_AT_noack(globals.gsm_console, (char *) cmd); else stream->write_function(stream, "gsm console is NOT yet assigned\n"); } end: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(gsmopen_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; private_t *tech_pvt = NULL; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if (!argc) { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_SYNTAX); goto end; } if (argc < 2) { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_SYNTAX); goto end; } if (argv[0]) { int i; int found = 0; for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name); found = 1; break; } } if (!found) { stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]); switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } else { gsmopen_serial_write_AT_noack(tech_pvt, (char *) &cmd[strlen(argv[0]) + 1]); } } else { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_SYNTAX); } end: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(gsmopen_dump_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; private_t *tech_pvt = NULL; char value[512]; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if (!argc) { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_DUMP_SYNTAX); goto end; } if (argc == 1 && argv[0]) { int found = 0; int i = 0; for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; found = 1; break; } } if (!found && (strcmp("list", argv[0]) == 0)) { stream->write_function(stream, "gsmopen_dump LIST\n\n"); for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { if (strlen(globals.GSMOPEN_INTERFACES[i].name)) { stream->write_function(stream, "dumping interface '%s'\n\n", globals.GSMOPEN_INTERFACES[i].name); tech_pvt = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "interface_name = %s\n", tech_pvt->name); stream->write_function(stream, "interface_id = %s\n", tech_pvt->id); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->active); stream->write_function(stream, "active = %s\n", value); if (!tech_pvt->network_creg_not_supported) { snprintf(value, sizeof(value) - 1, "%d", tech_pvt->not_registered); stream->write_function(stream, "not_registered = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->home_network_registered); stream->write_function(stream, "home_network_registered = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->roaming_registered); stream->write_function(stream, "roaming_registered = %s\n", value); } else { stream->write_function(stream, "not_registered = %s\n", "N/A"); stream->write_function(stream, "home_network_registered = %s\n", "N/A"); stream->write_function(stream, "roaming_registered = %s\n", "N/A"); } snprintf(value, sizeof(value) - 1, "%d", tech_pvt->got_signal); stream->write_function(stream, "got_signal = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->signal_strength); stream->write_function(stream, "signal_strength = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->running); stream->write_function(stream, "running = %s\n", value); stream->write_function(stream, "subscriber_number = %s\n", tech_pvt->subscriber_number); stream->write_function(stream, "device_manufacturer = %s\n", tech_pvt->device_mfg); stream->write_function(stream, "device_model = %s\n", tech_pvt->device_model); stream->write_function(stream, "device_firmware = %s\n", tech_pvt->device_firmware); stream->write_function(stream, "operator = %s\n", tech_pvt->operator_name); stream->write_function(stream, "imei = %s\n", tech_pvt->imei); stream->write_function(stream, "imsi = %s\n", tech_pvt->imsi); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->controldev_dead); stream->write_function(stream, "controldev_dead = %s\n", value); stream->write_function(stream, "controldevice_name = %s\n", tech_pvt->controldevice_name); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->no_sound); stream->write_function(stream, "no_sound = %s\n", value); snprintf(value, sizeof(value) - 1, "%f", tech_pvt->playback_boost); stream->write_function(stream, "playback_boost = %s\n", value); snprintf(value, sizeof(value) - 1, "%f", tech_pvt->capture_boost); stream->write_function(stream, "capture_boost = %s\n", value); stream->write_function(stream, "dialplan = %s\n", tech_pvt->dialplan); stream->write_function(stream, "context = %s\n", tech_pvt->context); stream->write_function(stream, "destination = %s\n", tech_pvt->destination); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ib_calls); stream->write_function(stream, "ib_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ob_calls); stream->write_function(stream, "ob_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ib_failed_calls); stream->write_function(stream, "ib_failed_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ob_failed_calls); stream->write_function(stream, "ob_failed_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->interface_state); stream->write_function(stream, "interface_state = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->phone_callflow); stream->write_function(stream, "phone_callflow = %s\n", value); stream->write_function(stream, "session_uuid_str = %s\n", tech_pvt->session_uuid_str); stream->write_function(stream, "\n"); dump_event(tech_pvt); } } } else if (found) { stream->write_function(stream, "dumping interface '%s'\n\n", argv[0]); tech_pvt = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "interface_name = %s\n", tech_pvt->name); stream->write_function(stream, "interface_id = %s\n", tech_pvt->id); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->active); stream->write_function(stream, "active = %s\n", value); if (!tech_pvt->network_creg_not_supported) { snprintf(value, sizeof(value) - 1, "%d", tech_pvt->not_registered); stream->write_function(stream, "not_registered = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->home_network_registered); stream->write_function(stream, "home_network_registered = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->roaming_registered); stream->write_function(stream, "roaming_registered = %s\n", value); } else { stream->write_function(stream, "not_registered = %s\n", "N/A"); stream->write_function(stream, "home_network_registered = %s\n", "N/A"); stream->write_function(stream, "roaming_registered = %s\n", "N/A"); } snprintf(value, sizeof(value) - 1, "%d", tech_pvt->got_signal); stream->write_function(stream, "got_signal = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->signal_strength); stream->write_function(stream, "signal_strength = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->running); stream->write_function(stream, "running = %s\n", value); stream->write_function(stream, "subscriber_number = %s\n", tech_pvt->subscriber_number); stream->write_function(stream, "device_manufacturer = %s\n", tech_pvt->device_mfg); stream->write_function(stream, "device_model = %s\n", tech_pvt->device_model); stream->write_function(stream, "device_firmware = %s\n", tech_pvt->device_firmware); stream->write_function(stream, "operator = %s\n", tech_pvt->operator_name); stream->write_function(stream, "imei = %s\n", tech_pvt->imei); stream->write_function(stream, "imsi = %s\n", tech_pvt->imsi); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->controldev_dead); stream->write_function(stream, "controldev_dead = %s\n", value); stream->write_function(stream, "controldevice_name = %s\n", tech_pvt->controldevice_name); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->no_sound); stream->write_function(stream, "no_sound = %s\n", value); snprintf(value, sizeof(value) - 1, "%f", tech_pvt->playback_boost); stream->write_function(stream, "playback_boost = %s\n", value); snprintf(value, sizeof(value) - 1, "%f", tech_pvt->capture_boost); stream->write_function(stream, "capture_boost = %s\n", value); stream->write_function(stream, "dialplan = %s\n", tech_pvt->dialplan); stream->write_function(stream, "context = %s\n", tech_pvt->context); stream->write_function(stream, "destination = %s\n", tech_pvt->destination); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ib_calls); stream->write_function(stream, "ib_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ob_calls); stream->write_function(stream, "ob_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ib_failed_calls); stream->write_function(stream, "ib_failed_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ob_failed_calls); stream->write_function(stream, "ob_failed_calls = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->interface_state); stream->write_function(stream, "interface_state = %s\n", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->phone_callflow); stream->write_function(stream, "phone_callflow = %s\n", value); stream->write_function(stream, "session_uuid_str = %s\n", tech_pvt->session_uuid_str); stream->write_function(stream, "\n"); dump_event(tech_pvt); } else { stream->write_function(stream, "interface '%s' was not found\n", argv[0]); } } else { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_DUMP_SYNTAX); } end: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(gsmopen_boost_audio_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; private_t *tech_pvt = NULL; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if ((argc == 1 || argc == 3) && argv[0]) { int i; int found = 0; for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "Using interface: globals.GSMOPEN_INTERFACES[%d].name=|||%s|||\n", i, globals.GSMOPEN_INTERFACES[i].name); found = 1; break; } } if (!found) { stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]); } else { if (argc == 1) { stream->write_function(stream, "[%s] capture boost is %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].capture_boost); stream->write_function(stream, "[%s] playback boost is %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].playback_boost); stream->write_function(stream, "%s usage: %s", argv[0], GSMOPEN_BOOST_AUDIO_SYNTAX); goto end; } else if ((strncmp("play", argv[1], strlen(argv[1])) == 0)) { if (switch_is_number(argv[2])) { stream->write_function(stream, "[%s] playback boost was %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].playback_boost); gsmopen_store_boost(argv[2], &globals.GSMOPEN_INTERFACES[i].playback_boost); //FIXME stream->write_function(stream, "[%s] playback boost is now %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].playback_boost); } } else if ((strncmp("capt", argv[1], strlen(argv[1])) == 0)) { if (switch_is_number(argv[2])) { stream->write_function(stream, "[%s] capture boost was %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].capture_boost); gsmopen_store_boost(argv[2], &globals.GSMOPEN_INTERFACES[i].capture_boost); //FIXME stream->write_function(stream, "[%s] capture boost is now %f\n", globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].capture_boost); } } else { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_BOOST_AUDIO_SYNTAX); } } } else { stream->write_function(stream, "ERROR, usage: %s", GSMOPEN_BOOST_AUDIO_SYNTAX); } end: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } void *gsmopen_do_gsmopenapi_thread_func(void *obj) { private_t *tech_pvt = (private_t *) obj; time_t now_timestamp; while (running && tech_pvt && tech_pvt->running) { int res; res = gsmopen_serial_read(tech_pvt); if (res == -1) { //manage the graceful interface shutdown tech_pvt->controldev_dead = 1; close(tech_pvt->controldevfd); ERRORA("gsmopen_serial_monitor failed, declaring %s dead\n", GSMOPEN_P_LOG, tech_pvt->controldevice_name); tech_pvt->running = 0; alarm_event(tech_pvt, ALARM_FAILED_INTERFACE, "gsmopen_serial_monitor failed, declaring interface dead"); tech_pvt->active = 0; tech_pvt->name[0] = '\0'; switch_sleep(1000000); } else if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL && tech_pvt->interface_state == GSMOPEN_STATE_RING && tech_pvt->phone_callflow != CALLFLOW_CALL_HANGUP_REQUESTED) { gsmopen_ring(tech_pvt); } else if (tech_pvt->controldevprotocol != PROTOCOL_NO_SERIAL && tech_pvt->interface_state == GSMOPEN_STATE_DIALING) { DEBUGA_GSMOPEN("WE'RE DIALING, let's take the earlymedia\n", GSMOPEN_P_LOG); tech_pvt->interface_state = CALLFLOW_STATUS_EARLYMEDIA; remote_party_is_early_media(tech_pvt); } else if (tech_pvt->interface_state == CALLFLOW_CALL_REMOTEANSWER) { DEBUGA_GSMOPEN("REMOTE PARTY ANSWERED\n", GSMOPEN_P_LOG); outbound_channel_answered(tech_pvt); } switch_sleep(100); //give other threads a chance time(&now_timestamp); if ((now_timestamp - tech_pvt->gsmopen_serial_synced_timestamp) > tech_pvt->gsmopen_serial_sync_period) { //TODO find a sensible period. 5min? in config? gsmopen_serial_sync(tech_pvt); gsmopen_serial_getstatus_AT(tech_pvt); } } DEBUGA_GSMOPEN("EXIT\n", GSMOPEN_P_LOG); return NULL; } SWITCH_STANDARD_API(sendsms_function) { char *mycmd = NULL, *argv[3] = { 0 }; int argc = 0; private_t *tech_pvt = NULL; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if (!argc) { stream->write_function(stream, "ERROR, usage: %s", SENDSMS_SYNTAX); goto end; } if (argc < 3) { stream->write_function(stream, "ERROR, usage: %s", SENDSMS_SYNTAX); goto end; } if (argv[0]) { int i; int found = 0; for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; stream->write_function(stream, "Trying to send your SMS: interface=%s, dest=%s, text=%s\n", argv[0], argv[1], argv[2]); found = 1; break; } } if (!found) { stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]); switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } else { 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, argv[1], "SIMPLE MESSAGE", switch_str_nil(argv[2]), tech_pvt->name); compat_chat_send(GSMOPEN_CHAT_PROTO, tech_pvt->name, argv[1], "SIMPLE MESSAGE", switch_str_nil(argv[2]), NULL, tech_pvt->name); } } else { stream->write_function(stream, "ERROR, usage: %s", SENDSMS_SYNTAX); } end: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } SWITCH_STANDARD_API(gsmopen_ussd_function) { char *mycmd = NULL, *argv[3] = { 0 }; int argc = 0; int waittime = 20; private_t *tech_pvt = NULL; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); } if (!argc) { stream->write_function(stream, "ERROR, usage: %s", USSD_SYNTAX); goto end; } if (argc < 2) { stream->write_function(stream, "ERROR, usage: %s", USSD_SYNTAX); goto end; } if (argc >= 3 && strcasecmp(argv[2], "nowait")==0) { waittime = 0; } if (argv[0]) { int i; int found = 0; for (i = 0; !found && i < GSMOPEN_MAX_INTERFACES; i++) { /* we've been asked for a normal interface name, or we have not found idle interfaces to serve as the "ANY" interface */ if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strncmp(globals.GSMOPEN_INTERFACES[i].name, argv[0], strlen(argv[0])) == 0)) { tech_pvt = &globals.GSMOPEN_INTERFACES[i]; NOTICA("Trying to send USSD request: interface=%s, ussd=%s\n", GSMOPEN_P_LOG, argv[0], argv[1]); found = 1; break; } } if (!found) { stream->write_function(stream, "ERROR: A GSMopen interface with name='%s' was not found\n", argv[0]); switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } else { int err = gsmopen_ussd(tech_pvt, (char *) argv[1], waittime); if (err == AT_ERROR) { stream->write_function(stream, "ERROR: command failed\n"); } else if (!waittime) { stream->write_function(stream, "USSD request has been sent\n"); } else if (err) { stream->write_function(stream, "ERROR: USSD request timeout (%d)\n", err); } else if (!tech_pvt->ussd_received) { stream->write_function(stream, "ERROR: no response received\n"); } else { stream->write_function(stream, "Status: %d%s\n", tech_pvt->ussd_status, tech_pvt->ussd_status == 0 ? " - completed" : tech_pvt->ussd_status == 1 ? " - action required" : tech_pvt->ussd_status == 2 ? " - error" : ""); if (strlen(tech_pvt->ussd_message) != 0) stream->write_function(stream, "Text: %s\n", tech_pvt->ussd_message); } } } else { stream->write_function(stream, "ERROR, usage: %s", USSD_SYNTAX); } end: switch_safe_free(mycmd); return SWITCH_STATUS_SUCCESS; } int dump_event_full(private_t *tech_pvt, int is_alarm, int alarm_code, const char *alarm_message) { switch_event_t *event; char value[512]; switch_core_session_t *session = NULL; switch_channel_t *channel = NULL; switch_status_t status; if (!tech_pvt) { return -1; } session = switch_core_session_locate(tech_pvt->session_uuid_str); if (session) { channel = switch_core_session_get_channel(session); } if (is_alarm) { ERRORA("ALARM on interface %s: \n", GSMOPEN_P_LOG, tech_pvt->name); status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_ALARM); } else { DEBUGA_GSMOPEN("DUMP on interface %s: \n", GSMOPEN_P_LOG, tech_pvt->name); status = switch_event_create_subclass(&event, SWITCH_EVENT_CUSTOM, MY_EVENT_DUMP); } if (status == SWITCH_STATUS_SUCCESS) { if (is_alarm) { snprintf(value, sizeof(value) - 1, "%d", alarm_code); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm_code", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "alarm_message", alarm_message); } switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "interface_name", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "interface_id", tech_pvt->id); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->active); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "active", value); if (!tech_pvt->network_creg_not_supported) { snprintf(value, sizeof(value) - 1, "%d", tech_pvt->not_registered); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "not_registered", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->home_network_registered); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "home_network_registered", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->roaming_registered); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "roaming_registered", value); } else { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "not_registered", "N/A"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "home_network_registered", "N/A"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "roaming_registered", "N/A"); } snprintf(value, sizeof(value) - 1, "%d", tech_pvt->got_signal); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "got_signal", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->signal_strength); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "signal_strength", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->running); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "running", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subscriber_number", tech_pvt->subscriber_number); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "device_manufacturer", tech_pvt->device_mfg); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "device_model", tech_pvt->device_model); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "device_firmware", tech_pvt->device_firmware); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "operator", tech_pvt->operator_name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "imei", tech_pvt->imei); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "imsi", tech_pvt->imsi); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->controldev_dead); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "controldev_dead", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "controldevice_name", tech_pvt->controldevice_name); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->no_sound); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "no_sound", value); snprintf(value, sizeof(value) - 1, "%f", tech_pvt->playback_boost); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "playback_boost", value); snprintf(value, sizeof(value) - 1, "%f", tech_pvt->capture_boost); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "capture_boost", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "dialplan", tech_pvt->dialplan); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "context", tech_pvt->context); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "destination", tech_pvt->destination); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ib_calls); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ib_calls", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ob_calls); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ob_calls", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ib_failed_calls); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ib_failed_calls", value); snprintf(value, sizeof(value) - 1, "%lu", tech_pvt->ob_failed_calls); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "ob_failed_calls", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->interface_state); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "interface_state", value); snprintf(value, sizeof(value) - 1, "%d", tech_pvt->phone_callflow); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "phone_callflow", value); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "session_uuid_str", tech_pvt->session_uuid_str); if (strlen(tech_pvt->session_uuid_str)) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "true"); } else { //no session switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "during-call", "false"); } if (channel) { switch_channel_event_set_data(channel, event); } switch_event_fire(&event); } else { ERRORA("cannot create event on interface %s. WHY?????\n", GSMOPEN_P_LOG, tech_pvt->name); } if (session) { switch_core_session_rwunlock(session); } return 0; } int dump_event(private_t *tech_pvt) { return dump_event_full(tech_pvt, 0, 0, NULL); } int alarm_event(private_t *tech_pvt, int alarm_code, const char *alarm_message) { return dump_event_full(tech_pvt, 1, alarm_code, alarm_message); } int sms_incoming(private_t *tech_pvt) { switch_event_t *event; if (!tech_pvt) { return -1; } NOTICA("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, tech_pvt->sms_body); if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", GSMOPEN_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", tech_pvt->sms_sender); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "date", tech_pvt->sms_date); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "userdataheader", tech_pvt->sms_userdataheader); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "datacodingscheme", tech_pvt->sms_datacodingscheme); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "servicecentreaddress", tech_pvt->sms_servicecentreaddress); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "messagetype", "%d", tech_pvt->sms_messagetype); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "SIMPLE MESSAGE"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", GSMOPEN_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", tech_pvt->sms_sender); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", tech_pvt->name); switch_event_add_body(event, "%s\n", tech_pvt->sms_body); switch_core_chat_send("GLOBAL", event); /* mod_sms */ } else { ERRORA("cannot create event on interface %s. WHY?????\n", GSMOPEN_P_LOG, tech_pvt->name); } memset(tech_pvt->sms_message, '\0', sizeof(tech_pvt->sms_message)); memset(tech_pvt->sms_sender, '\0', sizeof(tech_pvt->sms_sender)); memset(tech_pvt->sms_date, '\0', sizeof(tech_pvt->sms_date)); memset(tech_pvt->sms_userdataheader, '\0', sizeof(tech_pvt->sms_userdataheader)); memset(tech_pvt->sms_body, '\0', sizeof(tech_pvt->sms_body)); memset(tech_pvt->sms_datacodingscheme, '\0', sizeof(tech_pvt->sms_datacodingscheme)); memset(tech_pvt->sms_servicecentreaddress, '\0', sizeof(tech_pvt->sms_servicecentreaddress)); return 0; } int ussd_incoming(private_t *tech_pvt) { switch_event_t *event; DEBUGA_GSMOPEN("received USSD on interface %s: TEXT=%s|\n", GSMOPEN_P_LOG, tech_pvt->name, tech_pvt->ussd_message); /* mod_sms begin */ if (switch_event_create(&event, SWITCH_EVENT_MESSAGE) == SWITCH_STATUS_SUCCESS) { switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "proto", GSMOPEN_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "login", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from", "ussd"); //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "date", tech_pvt->sms_date); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "datacodingscheme", tech_pvt->ussd_dcs); //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "servicecentreaddress", tech_pvt->sms_servicecentreaddress); //switch_event_add_header(event, SWITCH_STACK_BOTTOM, "messagetype", "%d", tech_pvt->sms_messagetype); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "subject", "USSD MESSAGE"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "hint", tech_pvt->name); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_proto", GSMOPEN_CHAT_PROTO); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_user", "ussd"); //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_host", "from_host"); //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "from_full", "from_full"); switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_user", tech_pvt->name); //switch_event_add_header_string(event, SWITCH_STACK_BOTTOM, "to_host", "to_host"); switch_event_add_header(event, SWITCH_STACK_BOTTOM, "ussd_status", "%d", tech_pvt->ussd_status); switch_event_add_body(event, "%s\n", tech_pvt->ussd_message); //switch_core_chat_send("GLOBAL", event); /* mod_sms */ switch_core_chat_send("GLOBAL", event); /* mod_sms */ } else { ERRORA("cannot create event on interface %s. WHY?????\n", GSMOPEN_P_LOG, tech_pvt->name); } /* mod_sms end */ return 0; } #ifndef WIN32 #define PATH_MAX_GIOVA PATH_MAX static struct { char path_idvendor[PATH_MAX_GIOVA]; char path_idproduct[PATH_MAX_GIOVA]; char tty_base[PATH_MAX_GIOVA]; char idvendor[PATH_MAX_GIOVA]; char idproduct[PATH_MAX_GIOVA]; char tty_data_dir[PATH_MAX_GIOVA]; char tty_audio_dir[PATH_MAX_GIOVA]; char data_dev_id[256]; char audio_dev_id[256]; char delimiter[256]; char txt_saved[PATH_MAX_GIOVA]; char tty_base_copied[PATH_MAX_GIOVA]; char tty_data_device_file[PATH_MAX_GIOVA]; char tty_data_device[256]; char tty_audio_device_file[PATH_MAX_GIOVA]; char tty_audio_device[256]; char answer[AT_BUFSIZ]; char imei[256]; char imsi[256]; } f; /* int times=0; int conta=0; */ void find_ttyusb_devices(private_t *tech_pvt, const char *dirname) { DIR *dir; struct dirent *entry; memset( f.path_idvendor, 0, sizeof(f.path_idvendor) ); memset( f.path_idproduct, 0, sizeof(f.path_idproduct) ); memset( f.tty_base, 0, sizeof(f.tty_base) ); memset( f.idvendor, 0, sizeof(f.idvendor) ); memset( f.idproduct, 0, sizeof(f.idproduct) ); memset( f.tty_data_dir, 0, sizeof(f.tty_data_dir) ); memset( f.tty_audio_dir, 0, sizeof(f.tty_audio_dir) ); memset( f.data_dev_id, 0, sizeof(f.data_dev_id) ); memset( f.audio_dev_id, 0, sizeof(f.audio_dev_id) ); memset( f.delimiter, 0, sizeof(f.delimiter) ); memset( f.txt_saved, 0, sizeof(f.txt_saved) ); memset( f.tty_base_copied, 0, sizeof(f.tty_base_copied) ); memset( f.tty_data_device_file, 0, sizeof(f.tty_data_device_file) ); memset( f.tty_data_device, 0, sizeof(f.tty_data_device) ); memset( f.tty_audio_device_file, 0, sizeof(f.tty_audio_device_file) ); memset( f.tty_audio_device, 0, sizeof(f.tty_audio_device) ); if (!(dir = opendir(dirname))){ ERRORA("ERRORA! dirname=%s\n", GSMOPEN_P_LOG, dirname); closedir(dir); //conta--; return; } if (!(entry = readdir(dir))){ ERRORA("ERRORA!\n", GSMOPEN_P_LOG); closedir(dir); //conta--; return; } //conta++; do { if (entry->d_type == DT_DIR) { char path[PATH_MAX_GIOVA]; int len; //times++; len = snprintf(path, sizeof(path)-1, "%s/%s", dirname, entry->d_name); path[len] = 0; if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; find_ttyusb_devices(tech_pvt, path); } else{ int fd=-1; int len2=-1; DIR *dir2=NULL; struct dirent *entry2=NULL; int counter; char *scratch=NULL; char *txt=NULL; if (strcmp(entry->d_name, "idVendor") == 0){ sprintf(f.tty_base, "%s", dirname); sprintf(f.path_idvendor, "%s/%s", dirname, entry->d_name); sprintf(f.path_idproduct, "%s/idProduct", dirname); fd = open(f.path_idvendor, O_RDONLY); len2=read(fd, f.idvendor, sizeof(f.idvendor)); close(fd); if(f.idvendor[len2-1]=='\n'){ f.idvendor[len2-1]='\0'; } if (strcmp(f.idvendor, "12d1") == 0){ fd = open(f.path_idproduct, O_RDONLY); len2=read(fd, f.idproduct, sizeof(f.idproduct)); close(fd); if(f.idproduct[len2-1]=='\n'){ f.idproduct[len2-1]='\0'; } if (strcmp(f.idproduct, "1001") == 0 || strcmp(f.idproduct, "140c") == 0 || strcmp(f.idproduct, "1436") == 0 || strcmp(f.idproduct, "1506") == 0 || strcmp(f.idproduct, "14ac") == 0 ){ if (strcmp(f.idproduct, "1001") == 0){ strcpy(f.data_dev_id, "2"); strcpy(f.audio_dev_id, "1"); }else if (strcmp(f.idproduct, "140c") == 0){ strcpy(f.data_dev_id, "3"); strcpy(f.audio_dev_id, "2"); }else if (strcmp(f.idproduct, "1436") == 0){ strcpy(f.data_dev_id, "4"); strcpy(f.audio_dev_id, "3"); }else if (strcmp(f.idproduct, "1506") == 0){ strcpy(f.data_dev_id, "1"); strcpy(f.audio_dev_id, "2"); }else if (strcmp(f.idproduct, "14ac") == 0){ strcpy(f.data_dev_id, "4"); strcpy(f.audio_dev_id, "3"); }else{ //not possible } strcpy(f.delimiter, "/"); strcpy(f.tty_base_copied, f.tty_base); counter=0; while((txt = strtok_r(!counter ? f.tty_base_copied : NULL, f.delimiter, &scratch))) { strcpy(f.txt_saved, txt); counter++; } sprintf(f.tty_data_dir, "%s/%s:1.%s", f.tty_base, f.txt_saved, f.data_dev_id); sprintf(f.tty_audio_dir, "%s/%s:1.%s", f.tty_base, f.txt_saved, f.audio_dev_id); if (!(dir2 = opendir(f.tty_data_dir))) { ERRORA("ERRORA!\n", GSMOPEN_P_LOG); } if (!(entry2 = readdir(dir2))){ ERRORA("ERRORA!\n", GSMOPEN_P_LOG); } do { if (strncmp(entry2->d_name, "ttyUSB", 6) == 0){ //char f.answer[AT_BUFSIZ]; ctb::SerialPort *serialPort_serial_control; int res; int read_count; char at_command[256]; sprintf(f.tty_data_device_file, "%s/%s", f.tty_data_dir, entry2->d_name); sprintf(f.tty_data_device, "/dev/%s", entry2->d_name); memset(f.answer,0,sizeof(f.answer)); memset(f.imei,0,sizeof(f.imei)); memset(f.imsi,0,sizeof(f.imsi)); serialPort_serial_control = new ctb::SerialPort(); if (serialPort_serial_control->Open(f.tty_data_device, 115200, "8N1", ctb::SerialPort::NoFlowControl) >= 0) { sprintf(at_command, "AT\r\n"); res = serialPort_serial_control->Write(at_command, 4); usleep(20000); //0.02 seconds res = serialPort_serial_control->Write(at_command, 4); usleep(20000); //0.02 seconds sprintf(at_command, "ATE1\r\n"); res = serialPort_serial_control->Write(at_command, 6); usleep(20000); //0.02 seconds read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); sprintf(at_command, "AT\r\n"); res = serialPort_serial_control->Write(at_command, 4); usleep(20000); //0.02 seconds read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); memset(f.answer,0,sizeof(f.answer)); read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); memset(f.answer,0,sizeof(f.answer)); /* IMEI */ sprintf(at_command, "AT+GSN\r\n"); res = serialPort_serial_control->Write(at_command, 8); if (res != 8) { ERRORA("writing AT+GSN failed: %d\n", GSMOPEN_P_LOG, res); }else { usleep(200000); //0.2 seconds read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); if (read_count < 32) { ERRORA("reading AT+GSN failed: |%s|, read_count=%d, probably harmless in 'gsm reload'\n", GSMOPEN_P_LOG, f.answer, read_count); } else { strncpy(f.imei, f.answer+9, 15); sprintf(at_command, "AT\r\n"); res = serialPort_serial_control->Write(at_command, 4); usleep(20000); //0.02 seconds res = serialPort_serial_control->Write(at_command, 4); usleep(20000); //0.02 seconds sprintf(at_command, "ATE1\r\n"); res = serialPort_serial_control->Write(at_command, 6); usleep(20000); //0.02 seconds read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); sprintf(at_command, "AT\r\n"); res = serialPort_serial_control->Write(at_command, 4); usleep(20000); //0.02 seconds read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); memset(f.answer,0,sizeof(f.answer)); read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); memset(f.answer,0,sizeof(f.answer)); /* IMSI */ sprintf(at_command, "AT+CIMI\r\n"); res = serialPort_serial_control->Write(at_command, 9); if (res != 9) { ERRORA("writing AT+CIMI failed: %d\n", GSMOPEN_P_LOG, res); }else { usleep(200000); //0.2 seconds read_count = serialPort_serial_control->Read(f.answer, AT_BUFSIZ); if (read_count < 33) { ERRORA("reading AT+CIMI failed: |%s|, read_count=%d\n", GSMOPEN_P_LOG, f.answer, read_count); } else { strncpy(f.imsi, f.answer+10, 15); } } } } res = serialPort_serial_control->Close(); } else { ERRORA("port %s, NOT open\n", GSMOPEN_P_LOG, f.tty_data_device); } } } while ((entry2 = readdir(dir2))); closedir(dir2); if (!(dir2 = opendir(f.tty_audio_dir))) { ERRORA("ERRORA!\n", GSMOPEN_P_LOG); } if (!(entry2 = readdir(dir2))){ ERRORA("ERRORA!\n", GSMOPEN_P_LOG); } do { if (strncmp(entry2->d_name, "ttyUSB", 6) == 0){ int i; sprintf(f.tty_audio_device_file, "%s/%s", f.tty_audio_dir, entry2->d_name); sprintf(f.tty_audio_device, "/dev/%s", entry2->d_name); NOTICA("************************************************\n", GSMOPEN_P_LOG, f.imei); NOTICA("f.imei=|%s|\n", GSMOPEN_P_LOG, f.imei); NOTICA("f.imsi=|%s|\n", GSMOPEN_P_LOG, f.imsi); NOTICA("f.tty_data_device = |%s|\n", GSMOPEN_P_LOG, f.tty_data_device); NOTICA("f.tty_audio_device = |%s|\n", GSMOPEN_P_LOG, f.tty_audio_device); NOTICA("************************************************\n", GSMOPEN_P_LOG, f.imei); for (i = 0; i < GSMOPEN_MAX_INTERFACES; i++) { switch_threadattr_t *gsmopen_api_thread_attr = NULL; int res = 0; int interface_id = i; if (strlen(globals.GSMOPEN_INTERFACES[i].name) && (strlen(globals.GSMOPEN_INTERFACES[i].imsi) || strlen(globals.GSMOPEN_INTERFACES[i].imei)) ) { //NOTICA("globals.GSMOPEN_INTERFACES[i].imei)=%s strlen(globals.GSMOPEN_INTERFACES[i].imei)=%d (strcmp(globals.GSMOPEN_INTERFACES[i].imei, f.imei) == 0)=%d \n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].imei, strlen(globals.GSMOPEN_INTERFACES[i].imei), (strcmp(globals.GSMOPEN_INTERFACES[i].imei, f.imei) == 0) ); if( ( strlen(globals.GSMOPEN_INTERFACES[i].imei) ? (strcmp(globals.GSMOPEN_INTERFACES[i].imei, f.imei) == 0) : 1) ) { if ( (strlen(globals.GSMOPEN_INTERFACES[i].imsi) ? (strcmp(globals.GSMOPEN_INTERFACES[i].imsi, f.imsi) == 0) : 1) ){ strcpy(globals.GSMOPEN_INTERFACES[i].controldevice_audio_name, f.tty_audio_device); strcpy(globals.GSMOPEN_INTERFACES[i].controldevice_name, f.tty_data_device); NOTICA("name = |%s|, controldevice_audio_name = |%s|, controldevice_name = |%s|\n", GSMOPEN_P_LOG, globals.GSMOPEN_INTERFACES[i].name, globals.GSMOPEN_INTERFACES[i].controldevice_audio_name, globals.GSMOPEN_INTERFACES[i].controldevice_name); break; } } } } } } while ((entry2 = readdir(dir2))); closedir(dir2); } } } } } while ((entry = readdir(dir))); closedir(dir); /* if(f.conta < 0){ ERRORA("f.conta=%d, dirs=%d, mem=%d\n", GSMOPEN_P_LOG, conta, times, conta*PATH_MAX_GIOVA); }else{ NOTICA("f.conta=%d, dirs=%d, mem=%d\n", GSMOPEN_P_LOG, conta, times, conta*PATH_MAX_GIOVA); } conta--; */ } #endif// WIN32 /* For Emacs: * Local Variables: * mode:c * indent-tabs-mode:t * tab-width:4 * c-basic-offset:4 * End: * For VIM: * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet expandtab: */