int at_handshake() { int i; int err = 0; if (0 != pthread_equal(s_tid_reader, pthread_self())) { /* cannot be called from reader thread */ return AT_ERROR_INVALID_THREAD; } pthread_mutex_lock(&s_commandmutex); for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) { /* some stacks start with verbose off */ err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT, NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL); if (err == 0) { break; } } if (err == 0) { /* pause for a bit to let the input buffer drain any unmatched OK's (they will appear as extraneous unsolicited responses) */ sleepMsec(HANDSHAKE_TIMEOUT_MSEC); } pthread_mutex_unlock(&s_commandmutex); return err; }
/** * Internal send_command implementation * * timeoutMsec == 0 means infinite timeout */ static int at_send_command_full (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) { int err; if (0 != pthread_equal(s_tid_reader, pthread_self())) { /* cannot be called from reader thread */ return AT_ERROR_INVALID_THREAD; } pthread_mutex_lock(&s_commandmutex); err = at_send_command_full_nolock(command, type, responsePrefix, smspdu, timeoutMsec, pp_outResponse); pthread_mutex_unlock(&s_commandmutex); if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) { s_onTimeout(); } return err; }
/** * Periodically issue an AT command and wait for a response. * Used to ensure channel has start up and is active. */ int at_handshake(void) { int i; int err = 0; struct atcontext *ac = getAtContext(); if (0 != pthread_equal(ac->tid_reader, pthread_self())) /* Cannot be called from reader thread. */ return AT_ERROR_INVALID_THREAD; pthread_mutex_lock(&ac->commandmutex); for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) { /* Some stacks start with verbose off. */ err = at_send_command_full_nolock ("ATE0V1", NO_RESULT, NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL); if (err == 0) break; } if (err == 0) { /* Pause for a bit to let the input buffer drain any unmatched OK's (they will appear as extraneous unsolicited responses). */ ALOGD("%s() pausing %d ms to drain unmatched OK's...", __func__, HANDSHAKE_TIMEOUT_MSEC); sleepMsec(HANDSHAKE_TIMEOUT_MSEC); } pthread_mutex_unlock(&ac->commandmutex); return err; }
/** * Internal send_command implementation. * * timeoutMsec == 0 means infinite timeout. */ static int at_send_command_full (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse, int useap, va_list ap) { int err; struct atcontext *ac = getAtContext(); static char strbuf[BUFFSIZE]; const char *ptr; if (0 != pthread_equal(ac->tid_reader, pthread_self())) /* Cannot be called from reader thread. */ return AT_ERROR_INVALID_THREAD; pthread_mutex_lock(&ac->commandmutex); if (useap) { if (!vsnprintf(strbuf, BUFFSIZE, command, ap)) { pthread_mutex_unlock(&ac->commandmutex); return AT_ERROR_STRING_CREATION; } ptr = strbuf; } else ptr = command; err = at_send_command_full_nolock(ptr, type, responsePrefix, smspdu, timeoutMsec, pp_outResponse); pthread_mutex_unlock(&ac->commandmutex); if (err == AT_ERROR_TIMEOUT && ac->onTimeout != NULL) ac->onTimeout(); return err; }
/** * Internal send_command implementation * * timeoutMsec == 0 means infinite timeout */ static int at_send_command_full(const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse, RILChannelCtx *p_channel) { int err; if (0 != pthread_equal(p_channel->tid_reader, pthread_self())) { /* cannot be called from reader thread */ RLOGD("Invalid Thread: send on %s, reader:%lu, self: %lu", p_channel->myName, p_channel->tid_reader, pthread_self()); return AT_ERROR_INVALID_THREAD; } if (0 != p_channel->tid_myProxy) { /* This channel is occupied by some proxy */ RLOGD("Occupied Thread: %s send on %s, pthread_self(): %lu, tid: %lu", command, p_channel->myName, pthread_self(), p_channel->tid_myProxy); assert(0); return AT_ERROR_INVALID_THREAD; } pthread_mutex_lock(&p_channel->commandmutex); /* Assign owner proxy */ p_channel->tid_myProxy = pthread_self(); RLOGD("AT send on %s, tid:%lu", p_channel->myName, p_channel->tid_myProxy); err = at_send_command_full_nolock(command, type, responsePrefix, smspdu, timeoutMsec, pp_outResponse, p_channel); RLOGD("response received on %s, tid:%lu", p_channel->myName, p_channel->tid_myProxy); /* Release the proxy */ p_channel->tid_myProxy = 0; pthread_mutex_unlock(&p_channel->commandmutex); if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) s_onTimeout(p_channel); return err; }
static int at_send_command_full_nolock (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) { int err = 0; #ifndef USE_NP struct timespec ts; #endif /*USE_NP*/ if(sp_response != NULL) { err = AT_ERROR_COMMAND_PENDING; goto error; } if (!strncmp(command, "ATD", 3)) s_last_cme_error = CME_NO_ERROR; err = writeline (command); if (err < 0) { goto error; } s_type = type; s_responsePrefix = responsePrefix; s_smsPDU = smspdu; sp_response = at_response_new(); #ifndef USE_NP if (timeoutMsec != 0) { setTimespecRelative(&ts, timeoutMsec); } #endif /*USE_NP*/ while (sp_response->finalResponse == NULL && s_readerClosed == 0) { if (timeoutMsec != 0) { #ifdef USE_NP err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); #else err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts); #endif /*USE_NP*/ } else { err = pthread_cond_wait(&s_commandcond, &s_commandmutex); } if (err == ETIMEDOUT) { err = AT_ERROR_TIMEOUT; goto error; } } if (pp_outResponse == NULL) { at_response_free(sp_response); } else { /* line reader stores intermediate responses in reverse order */ reverseIntermediates(sp_response); *pp_outResponse = sp_response; } sp_response = NULL; if(s_readerClosed > 0) { err = AT_ERROR_CHANNEL_CLOSED; goto error; } err = 0; error: clearPendingCommand(); /* Have to save the error message right away */ if (pp_outResponse && !(*pp_outResponse)->success && !err && !strncmp(command, "ATD", 3)) { ATResponse *err_resp; err = at_send_command_full_nolock("AT+CEER", SINGLELINE, "+CEER:", NULL, timeoutMsec, &err_resp); if (!err) { if (err_resp->p_intermediates != NULL) { free(s_last_errmsg); s_last_errmsg = strdup(err_resp->p_intermediates->line); } at_response_free(err_resp); } } return err; }