Пример #1
0
/**
 * Send a new command to the modem.
 *
 * @param cmd - Pointer to the command
 * @param eol - Optional EOL char
 * @param timeout - Timeout of the operation in milliseconds.
 */
static void gprs_command_timeout(gprs_t * gprs,const char * cmd,u8_t eol,u32_t timeout)
{
#if GPRS_COMMAND_DELAY
	u32_t delay = sys_now() - gprs->commandTime;
#endif

	gprs->sentCommand = cmd;

#if GPRS_COMMAND_DELAY
	if (delay < GPRS_COMMAND_DELAY)
	{
		delay = GPRS_COMMAND_DELAY - delay;
		timeout += delay;
		TIMEOUT(timeout);
		modem_set_state(gprs,MODEM_STATE_NONE);
		//LWIP_DEBUGF(GPRS_DEBUG,("gprs_command_timeout: Delayed %lu milliseconds\n",delay));
		TIMEOUT1(delay);
		gprs->delayedCommand = cmd;
		gprs->delayedEol = eol;

	}
	else
	{
		TIMEOUT(timeout);
		modem_set_state(gprs,MODEM_STATE_ECHO);
		gprs_raw_send(gprs,cmd,eol);
	}
#else
	TIMEOUT(timeout);
	modem_set_state(gprs,MODEM_STATE_ECHO);
	gprs_raw_send(gprs,cmd,eol);

#endif
}
Пример #2
0
/**
 * Callback function for delayed command.
 *
 * Called when the delay between 2 command expire.
 */
static void gprs_command_delayed(void *arg)
{
	//LWIP_DEBUGF(GPRS_DEBUG,("gprs_command_delayed: timeout\n"));
	gprs_t * gprs = (gprs_t *)arg;
	gprs_raw_send(gprs,gprs->delayedCommand,gprs->delayedEol);
	modem_set_state(gprs,MODEM_STATE_ECHO);

}
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 = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	switch (msg->message_id) {
	case SWITCH_MESSAGE_INDICATE_ANSWER:
		t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_CONNECTED);
		modem_set_state(tech_pvt->modem, MODEM_STATE_CONNECTED);
		mod_spandsp_indicate_data(session, SWITCH_FALSE, SWITCH_TRUE);
		break;
	case SWITCH_MESSAGE_INDICATE_PROGRESS:
		t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_CONNECTED);
		modem_set_state(tech_pvt->modem, MODEM_STATE_CONNECTED);
		mod_spandsp_indicate_data(session, SWITCH_FALSE, SWITCH_TRUE);
		break;
	case SWITCH_MESSAGE_INDICATE_RINGING:
		break;
	case SWITCH_MESSAGE_INDICATE_BRIDGE:
		mod_spandsp_indicate_data(session, SWITCH_FALSE, SWITCH_TRUE);
				
		break;
	case SWITCH_MESSAGE_INDICATE_UNBRIDGE:

		mod_spandsp_indicate_data(session, SWITCH_FALSE, SWITCH_TRUE);

		break;
	default:
		break;
	}

	return SWITCH_STATUS_SUCCESS;
}
static switch_status_t channel_on_destroy(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);
	
	if ((tech_pvt = switch_core_session_get_private(session))) {

		switch_core_timer_destroy(&tech_pvt->timer);

		if (tech_pvt->modem) {
			*tech_pvt->modem->uuid_str = '\0';
			*tech_pvt->modem->digits = '\0';
			modem_set_state(tech_pvt->modem, MODEM_STATE_ONHOOK);
			tech_pvt->modem = NULL;
		}
	}

	return SWITCH_STATUS_SUCCESS;
}
static modem_t *acquire_modem(int index)
{
    modem_t *modem = NULL;
	switch_time_t now = switch_time_now();
	int64_t idle_debounce = 2000000;

    switch_mutex_lock(globals.mutex);
    if (index > -1 && index < globals.SOFT_MAX_MODEMS) {
        modem = &globals.MODEM_POOL[index];
    } else {
        int x;

        for(x = 0; x < globals.SOFT_MAX_MODEMS; x++) {
            if (globals.MODEM_POOL[x].state == MODEM_STATE_ONHOOK && (now - globals.MODEM_POOL[x].last_event) > idle_debounce) {
                modem = &globals.MODEM_POOL[x];
                break;
            }
        }
    }

    if (modem && (modem->state != MODEM_STATE_ONHOOK || (now - modem->last_event) < idle_debounce)) {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Modem %s In Use!\n", modem->devlink);
        modem = NULL;
    }

    if (modem) {
        modem_set_state(modem, MODEM_STATE_ACQUIRED);
		modem->last_event = switch_time_now();
    } else {
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "No Modems Available!\n");
    }

    switch_mutex_unlock(globals.mutex);

    return modem;
}
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)
{
	char name[128];
	switch_call_cause_t cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER;

	if ((*new_session = switch_core_session_request(modem_endpoint_interface, SWITCH_CALL_DIRECTION_OUTBOUND, flags, pool)) != 0) {
		private_t *tech_pvt;
		switch_channel_t *channel;
		switch_caller_profile_t *caller_profile;
		char *dest = switch_core_session_strdup(*new_session, outbound_profile->destination_number);
		char *modem_id_string = NULL;
		char *number = NULL;
		int modem_id = 0;
		modem_t *modem = NULL;

		if ((modem_id_string = dest)) {
			if ((number = strchr(modem_id_string, '/'))) {
				*number++ = '\0';
			}
		}

		if (zstr(modem_id_string) || zstr(number)) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Invalid dial string.\n");
			cause = SWITCH_CAUSE_INVALID_NUMBER_FORMAT; goto fail;
		}

		if (!strcasecmp(modem_id_string, "a")) {
			modem_id = -1;
		} else {
			modem_id = atoi(modem_id_string);
		}

		if (!(modem = acquire_modem(modem_id))) {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Cannot find a modem.\n");
			cause = SWITCH_CAUSE_USER_BUSY; goto fail;
		}
		
		switch_core_session_add_stream(*new_session, NULL);

		if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) {
			channel = switch_core_session_get_channel(*new_session);
			switch_snprintf(name, sizeof(name), "modem/%d/%s", modem->slot, number);
			switch_channel_set_name(channel, name);

			if (tech_init(tech_pvt, *new_session) != SWITCH_STATUS_SUCCESS) {
				cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail;
			}

			switch_set_string(modem->digits, number);
			tech_attach(tech_pvt, modem);
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_CRIT, "Hey where is my memory pool?\n");
			switch_core_session_destroy(new_session);
			cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail;
		}

		if (outbound_profile) {
			caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
			caller_profile->source = switch_core_strdup(caller_profile->pool, "mod_spandsp");
			switch_channel_set_caller_profile(channel, caller_profile);
			tech_pvt->caller_profile = caller_profile;
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(*new_session), SWITCH_LOG_ERROR, "Doh! no caller profile\n");
			cause = SWITCH_CAUSE_DESTINATION_OUT_OF_ORDER; goto fail;
		}

		switch_channel_set_state(channel, CS_INIT);

		return SWITCH_CAUSE_SUCCESS;

	fail:

		if (new_session) {
			switch_core_session_destroy(new_session);
		}

		if (modem) {
			modem_set_state(modem, MODEM_STATE_ONHOOK);
		}
	}

	return cause;
}
int modem_close(modem_t *modem) 
{
	int r = 0;
	switch_status_t was_running = switch_test_flag(modem, MODEM_FLAG_RUNNING);

	switch_clear_flag(modem, MODEM_FLAG_RUNNING);

#ifndef WIN32
	if (modem->master > -1) {
		shutdown(modem->master, 2);
		close(modem->master);
		modem->master = -1;
#else
	if (modem->master) {
		SetEvent(modem->threadAbort);
		CloseHandle(modem->threadAbort);
		CloseHandle(modem->master);
		modem->master = 0;
#endif
		
		r++;
	}

	if (modem->slave > -1) {
		shutdown(modem->slave, 2);
		close(modem->slave);
		modem->slave = -1;
		r++;
	}


   	if (modem->t31_state) {
		t31_free(modem->t31_state);
		modem->t31_state = NULL;
	}

	unlink(modem->devlink);

	if (was_running) {
		switch_mutex_lock(globals.mutex);
		globals.REF_COUNT--;
		switch_mutex_unlock(globals.mutex);
	}

	return r;
}


switch_status_t modem_init(modem_t *modem, modem_control_handler_t control_handler)
{
	switch_status_t status = SWITCH_STATUS_SUCCESS;
#ifdef WIN32
	COMMTIMEOUTS timeouts={0};
#endif
	
	memset(modem, 0, sizeof(*modem));

	modem->master = -1;
	modem->slave = -1;

	/* windows will have to try something like:
	   http://com0com.cvs.sourceforge.net/viewvc/com0com/com0com/ReadMe.txt?revision=RELEASED

	 */

#if USE_OPENPTY
    if (openpty(&modem->master, &modem->slave, NULL, NULL, NULL)) {

	if (modem->master < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to initialize pty\n");
		status = SWITCH_STATUS_FALSE;
		goto end;
    }

	modem->stty = ttyname(modem->slave);
#else
#if WIN32
	modem->slot = 4+globals.NEXT_ID++; /* need work here we start at COM4 for now*/
	snprintf(modem->devlink, sizeof(modem->devlink), "COM%d", modem->slot);

	modem->master = CreateFile(modem->devlink,
	GENERIC_READ | GENERIC_WRITE,
	0,
	0,
	OPEN_EXISTING,
	FILE_FLAG_OVERLAPPED,
	0);
	if(modem->master==INVALID_HANDLE_VALUE) {
		status = SWITCH_STATUS_FALSE;
		if(GetLastError()==ERROR_FILE_NOT_FOUND) {
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: Serial port does not exist\n");
			goto end;
		}
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: Serial port open error\n");
		goto end;
	}
#elif !defined(HAVE_POSIX_OPENPT)
    modem->master = open("/dev/ptmx", O_RDWR);
#else
    modem->master = posix_openpt(O_RDWR | O_NOCTTY);
#endif

#ifndef WIN32
    if (modem->master < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to initialize UNIX98 master pty\n");
		
    }

    if (grantpt(modem->master) < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to grant access to slave pty\n");
		
    }

    if (unlockpt(modem->master) < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to unlock slave pty\n");
		
    }

    modem->stty = ptsname(modem->master);

    if (modem->stty == NULL) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to obtain slave pty filename\n");
		
    }

    modem->slave = open(modem->stty, O_RDWR);

    if (modem->slave < 0) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to open slave pty %s\n", modem->stty);
    }
#endif

#ifdef SOLARIS
    ioctl(modem->slave, I_PUSH, "ptem");  /* push ptem */
    ioctl(modem->slave, I_PUSH, "ldterm");    /* push ldterm*/
#endif
#endif

#ifndef WIN32
	modem->slot = globals.NEXT_ID++;
	snprintf(modem->devlink, sizeof(modem->devlink), "/dev/FS%d", modem->slot);
	
    unlink(modem->devlink);

    if (symlink(modem->stty, modem->devlink)) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Fatal error: failed to create %s symbolic link\n", modem->devlink);
		modem_close(modem);
		status = SWITCH_STATUS_FALSE;
		goto end;
    }

    if (fcntl(modem->master, F_SETFL, fcntl(modem->master, F_GETFL, 0) | O_NONBLOCK)) {
	    switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot set up non-blocking read on %s\n", ttyname(modem->master));
	    modem_close(modem);
	    status = SWITCH_STATUS_FALSE;
	    goto end;
    }
#else
	timeouts.ReadIntervalTimeout=50;
	timeouts.ReadTotalTimeoutConstant=50;
	timeouts.ReadTotalTimeoutMultiplier=10;

	timeouts.WriteTotalTimeoutConstant=50;
	timeouts.WriteTotalTimeoutMultiplier=10;

	SetCommMask(modem->master, EV_RXCHAR);

	if(!SetCommTimeouts(modem->master, &timeouts)){
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot set up non-blocking read on %s\n", modem->devlink);
		modem_close(modem);
		status = SWITCH_STATUS_FALSE;
		goto end;
	}
	modem->threadAbort = CreateEvent(NULL, TRUE, FALSE, NULL);
#endif
	
	if (!(modem->t31_state = t31_init(NULL, t31_at_tx_handler, modem, t31_call_control_handler, modem, NULL, NULL))) {
		switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Cannot initialize the T.31 modem\n");
		modem_close(modem);
		status = SWITCH_STATUS_FALSE;
		goto end;
	}

	if (spandsp_globals.modem_verbose) {
		span_log_set_message_handler(&modem->t31_state->logging, spanfax_log_message, NULL);
		span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v17_rx.logging, spanfax_log_message, NULL);
		span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v29_rx.logging, spanfax_log_message, NULL);
		span_log_set_message_handler(&modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging, spanfax_log_message, NULL);

		modem->t31_state->logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
		modem->t31_state->audio.modems.fast_modems.v17_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
		modem->t31_state->audio.modems.fast_modems.v29_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
		modem->t31_state->audio.modems.fast_modems.v27ter_rx.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
	}

	modem->control_handler = control_handler;
	modem->flags = 0;
	switch_set_flag(modem, MODEM_FLAG_RUNNING);

	switch_mutex_init(&modem->mutex, SWITCH_MUTEX_NESTED, globals.pool);
	switch_mutex_init(&modem->cond_mutex, SWITCH_MUTEX_NESTED, globals.pool);
	switch_thread_cond_create(&modem->cond, globals.pool);

	modem_set_state(modem, MODEM_STATE_INIT);

	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Modem [%s]->[%s] Ready\n", modem->devlink, modem->stty);

	switch_mutex_lock(globals.mutex);
	globals.REF_COUNT++;
	switch_mutex_unlock(globals.mutex);

end:
	return status;
}

static switch_endpoint_interface_t *modem_endpoint_interface = NULL;

struct private_object {
	switch_mutex_t *mutex;
	switch_core_session_t *session;
	switch_channel_t *channel;
	switch_codec_t read_codec;
	switch_codec_t write_codec;
	switch_frame_t read_frame;
	unsigned char databuf[SWITCH_RECOMMENDED_BUFFER_SIZE];
	switch_timer_t timer;
	modem_t *modem;
	switch_caller_profile_t *caller_profile;
	int dead;
};

typedef struct private_object private_t;

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_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);


/* 
   State methods they 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;
	int to_ticks = 60, ring_ticks = 10, rt = ring_ticks;
	int rest = 500000;
	
	tech_pvt = switch_core_session_get_private(session);
	switch_assert(tech_pvt != NULL);

	channel = switch_core_session_get_channel(session);
	switch_assert(channel != NULL);

	if (switch_channel_direction(channel) == SWITCH_CALL_DIRECTION_OUTBOUND) {
#ifndef WIN32
		int tioflags;
#endif
		char call_time[16];
		char call_date[16];
		switch_size_t retsize;
		switch_time_exp_t tm;

		switch_time_exp_lt(&tm, switch_micro_time_now());
		switch_strftime(call_date, &retsize, sizeof(call_date), "%m%d", &tm);
		switch_strftime(call_time, &retsize, sizeof(call_time), "%H%M", &tm);

#ifndef WIN32
		ioctl(tech_pvt->modem->slave, TIOCMGET, &tioflags);
		tioflags |= TIOCM_RI;
		ioctl(tech_pvt->modem->slave, TIOCMSET, &tioflags);
#endif

		at_reset_call_info(&tech_pvt->modem->t31_state->at_state);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "DATE", call_date);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "TIME", call_time);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NAME", tech_pvt->caller_profile->caller_id_name);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NMBR", tech_pvt->caller_profile->caller_id_number);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "ANID", tech_pvt->caller_profile->ani);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "USER", tech_pvt->caller_profile->username);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "CDID", tech_pvt->caller_profile->context);
		at_set_call_info(&tech_pvt->modem->t31_state->at_state, "NDID", tech_pvt->caller_profile->destination_number);

		modem_set_state(tech_pvt->modem, MODEM_STATE_RINGING);
		t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ALERTING);
		
		while(to_ticks > 0 && switch_channel_up(channel) && modem_get_state(tech_pvt->modem) == MODEM_STATE_RINGING) {
			if (--rt <= 0) {
				t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ALERTING);
				rt = ring_ticks;
			}
			
			switch_yield(rest);
			to_ticks--;
		}
		
		if (to_ticks < 1 || modem_get_state(tech_pvt->modem) != MODEM_STATE_ANSWERED) {
			t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_NO_ANSWER);
			switch_channel_hangup(channel, SWITCH_CAUSE_NO_ANSWER);
		} else {
			t31_call_event(tech_pvt->modem->t31_state, AT_CALL_EVENT_ANSWERED);
			modem_set_state(tech_pvt->modem, MODEM_STATE_CONNECTED);
			switch_channel_mark_answered(channel);
		}
	}

	switch_channel_set_state(channel, CS_ROUTING);
	
	return SWITCH_STATUS_SUCCESS;
}
static int control_handler(modem_t *modem, const char *num, int op)
{
	switch_core_session_t *session = NULL;
	
	switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1, "Control Handler op:%d state:[%s] %s\n", 
					  op, modem_state2name(modem_get_state(modem)), modem->devlink);

    switch (op) {

    case AT_MODEM_CONTROL_ANSWER:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - Answering\n", modem->devlink, modem_state2name(modem_get_state(modem)));
		modem_set_state(modem, MODEM_STATE_ANSWERED);
        break;
    case AT_MODEM_CONTROL_CALL:
		{
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
							  "Modem %s [%s] - Dialing '%s'\n", modem->devlink, modem_state2name(modem_get_state(modem)), num);
			modem_set_state(modem, MODEM_STATE_DIALING);
			switch_clear_flag(modem, MODEM_FLAG_XOFF);
			wake_modem_thread(modem);

			switch_set_string(modem->digits, num);
			
			if (create_session(&session, modem) != SWITCH_STATUS_SUCCESS) {
				t31_call_event(modem->t31_state, AT_CALL_EVENT_HANGUP);
			} else {
				switch_core_session_thread_launch(session);
			}
		}
		break;
    case AT_MODEM_CONTROL_OFFHOOK:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - Going off hook\n", modem->devlink, modem_state2name(modem_get_state(modem)));
		modem_set_state(modem, MODEM_STATE_OFFHOOK);
		break;
    case AT_MODEM_CONTROL_ONHOOK:
    case AT_MODEM_CONTROL_HANGUP: 
		{
			if (modem_get_state(modem) != MODEM_STATE_RINGING) {
				int set_state = 1;
				
				switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
								  "Modem %s [%s] - Hanging up\n", modem->devlink, modem_state2name(modem_get_state(modem)));
				switch_clear_flag(modem, MODEM_FLAG_XOFF);
				wake_modem_thread(modem);
				

				modem_set_state(modem, MODEM_STATE_HANGUP);
			

				if (!zstr(modem->uuid_str)) {
					switch_core_session_t *session;
					
					if ((session = switch_core_session_force_locate(modem->uuid_str))) {
						switch_channel_t *channel = switch_core_session_get_channel(session);
						
						if (switch_channel_up(channel)) {
							switch_channel_hangup(channel, SWITCH_CAUSE_NORMAL_CLEARING);
							set_state = 0;
						}
						switch_core_session_rwunlock(session);
					}
				}
				

				if (set_state) {
					modem_set_state(modem, MODEM_STATE_ONHOOK);
				}
			}
		}
        break;
    case AT_MODEM_CONTROL_DTR:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - DTR %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num);
        break;
    case AT_MODEM_CONTROL_RTS:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - RTS %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num);
        break;
    case AT_MODEM_CONTROL_CTS:
		{
			u_char x[1];
			switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG1,
							  "Modem %s [%s] - CTS %s\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num ? "XON" : "XOFF");

			if (num) {
				x[0] = 0x11;
				t31_at_tx_handler(&modem->t31_state->at_state, modem, x, 1);
				switch_clear_flag(modem, MODEM_FLAG_XOFF);
				wake_modem_thread(modem);
			} else {
				x[0] = 0x13;
				t31_at_tx_handler(&modem->t31_state->at_state, modem, x, 1);
				switch_set_flag(modem, MODEM_FLAG_XOFF);
			}
		}
        break;
    case AT_MODEM_CONTROL_CAR:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - CAR %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num);
        break;
    case AT_MODEM_CONTROL_RNG:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - RNG %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num);
        break;
    case AT_MODEM_CONTROL_DSR:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - DSR %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), (int) (intptr_t) num);
        break;
    default:
        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG,
						  "Modem %s [%s] - operation %d\n", modem->devlink, modem_state2name(modem_get_state(modem)), op);
        break;
    }
    /*endswitch*/
    return 0;
}
Пример #9
0
/**
 * Check reply from the modem.
 *
 * @return  0 - No valid reply received
 * @return  1 - OK received
 * @return 2 - Error received.
 */
static int modem_check_reply(gprs_t * gprs,const u8_t *data,u32_t length,void (*callback)(gprs_t * gprs,const char *reply))
{
	u8_t c;
	int reply = MODEM_REPLY_NONE;


	while (length-- > 0 && reply == MODEM_REPLY_NONE)
	{
		c = *data++;

		switch (gprs->modem)
		{
			default:
			case MODEM_STATE_NONE:
				break;

			case MODEM_STATE_ECHO:
				if (gprs->sentCommand[gprs->modemCount] == c)
				{
					if (gprs->sentCommand[++gprs->modemCount] < 32)
					{

						modem_set_state(gprs,MODEM_STATE_WAITEOL);
					}
				}
				else
				{
					gprs->modemCount = 0;
				}
				break;

			case MODEM_STATE_WAITEOL:
				if (c < 32)
				{
					//LWIP_DEBUGF(GPRS_DEBUG,("Modem_check_reply: echo received\n"));
					modem_set_state(gprs,MODEM_STATE_REPLY);
				}
				break;

			case MODEM_STATE_REPLY:
				if (c < 32)
				{
					if (gprs->modemCount > 0)
					{
						gprs->replyBuffer[gprs->modemCount] = 0;
						LWIP_DEBUGF(MODEM_DEBUG,("gprs: Modem reply '%s'\n",gprs->replyBuffer));
						gprs->modemCount = 0;
						if (!strcmp(gprs->replyBuffer,"OK"))
						{
#if GPRS_COMMAND_DELAY > 0
							gprs->commandTime  = sys_now();
#endif
							//LWIP_DEBUGF(MODEM_DEBUG,("modem_check_reply: OK received\n"));
							reply = MODEM_REPLY_OK;
						}
						else if(!strncmp(gprs->replyBuffer,"ERROR",5))
						{
#if GPRS_COMMAND_DELAY > 0
							gprs->commandTime  = sys_now();
#endif
							LWIP_DEBUGF(MODEM_DEBUG,("gprs: Modem reply ERROR ERROR received\n"));
							reply = MODEM_REPLY_ERROR;
						}
						else
						{

							if (callback != 0)
							{
								(*callback)(gprs,gprs->replyBuffer);
							}
						}

					}
				}
				else
				{
					if (gprs->modemCount < sizeof(gprs->replyBuffer) - 1)
					{
						gprs->replyBuffer[gprs->modemCount++] = c;
					}
					else
					{
						LWIP_DEBUGF(GPRS_DEBUG,("gprs: GPRS_REPLY_BUFFER_SIZE too short"));
					}

				}
				break;
		}
	}

	return reply;
}