atchannel.c
资源名称:ril.rar [点击查看]
上传用户:rftzhifu
上传日期:2017-02-21
资源大小:229k
文件大小:24k
源码类别:
android开发
开发平台:
Unix_Linux
- /* //device/system/reference-ril/atchannel.c
- **
- ** Copyright 2006, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
- #include "atchannel.h"
- #include "at_tok.h"
- #include <stdio.h>
- #include <string.h>
- #include <pthread.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <sys/time.h>
- #include <time.h>
- #include <unistd.h>
- #define LOG_NDEBUG 0
- #define LOG_TAG "AT"
- #include <utils/Log.h>
- #ifdef HAVE_ANDROID_OS
- /* for IOCTL's */
- #include <linux/omap_csmi.h>
- #endif /*HAVE_ANDROID_OS*/
- #include "misc.h"
- #ifdef HAVE_ANDROID_OS
- #define USE_NP 1
- #endif /* HAVE_ANDROID_OS */
- #define NUM_ELEMS(x) (sizeof(x)/sizeof(x[0]))
- #define MAX_AT_RESPONSE (8 * 1024)
- #define HANDSHAKE_RETRY_COUNT 8
- #define HANDSHAKE_TIMEOUT_MSEC 250
- static pthread_t s_tid_reader;
- static int s_fd = -1; /* fd of the AT channel */
- static ATUnsolHandler s_unsolHandler;
- /* for input buffering */
- static char s_ATBuffer[MAX_AT_RESPONSE+1];
- static char *s_ATBufferCur = s_ATBuffer;
- static int s_ackPowerIoctl; /* true if TTY has android byte-count
- handshake for low power*/
- static int s_readCount = 0;
- #if AT_DEBUG
- void AT_DUMP(const char* prefix, const char* buff, int len)
- {
- if (len < 0)
- len = strlen(buff);
- LOGD("%.*s", len, buff);
- }
- #endif
- /*
- * for current pending command
- * these are protected by s_commandmutex
- */
- static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
- static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
- static ATCommandType s_type;
- static const char *s_responsePrefix = NULL;
- static const char *s_smsPDU = NULL;
- static ATResponse *sp_response = NULL;
- static void (*s_onTimeout)(void) = NULL;
- static void (*s_onReaderClosed)(void) = NULL;
- static int s_readerClosed;
- static void onReaderClosed();
- static int writeCtrlZ (const char *s);
- static int writeline (const char *s);
- #ifndef USE_NP
- static void setTimespecRelative(struct timespec *p_ts, long long msec)
- {
- struct timeval tv;
- gettimeofday(&tv, (struct timezone *) NULL);
- /* what's really funny about this is that I know
- pthread_cond_timedwait just turns around and makes this
- a relative time again */
- p_ts->tv_sec = tv.tv_sec + (msec / 1000);
- p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
- }
- #endif /*USE_NP*/
- static void sleepMsec(long long msec)
- {
- struct timespec ts;
- int err;
- ts.tv_sec = (msec / 1000);
- ts.tv_nsec = (msec % 1000) * 1000 * 1000;
- do {
- err = nanosleep (&ts, &ts);
- } while (err < 0 && errno == EINTR);
- }
- /** add an intermediate response to sp_response*/
- static void addIntermediate(const char *line)
- {
- ATLine *p_new;
- p_new = (ATLine *) malloc(sizeof(ATLine));
- p_new->line = strdup(line);
- /* note: this adds to the head of the list, so the list
- will be in reverse order of lines received. the order is flipped
- again before passing on to the command issuer */
- p_new->p_next = sp_response->p_intermediates;
- sp_response->p_intermediates = p_new;
- }
- /**
- * returns 1 if line is a final response indicating error
- * See 27.007 annex B
- * WARNING: NO CARRIER and others are sometimes unsolicited
- */
- static const char * s_finalResponsesError[] = {
- "ERROR",
- "+CMS ERROR:",
- "+CME ERROR:",
- "NO CARRIER", /* sometimes! */
- "NO ANSWER",
- "NO DIALTONE",
- };
- static int isFinalResponseError(const char *line)
- {
- size_t i;
- for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) {
- if (strStartsWith(line, s_finalResponsesError[i])) {
- return 1;
- }
- }
- return 0;
- }
- /**
- * returns 1 if line is a final response indicating success
- * See 27.007 annex B
- * WARNING: NO CARRIER and others are sometimes unsolicited
- */
- static const char * s_finalResponsesSuccess[] = {
- "OK",
- "CONNECT" /* some stacks start up data on another channel */
- };
- static int isFinalResponseSuccess(const char *line)
- {
- size_t i;
- for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) {
- if (strStartsWith(line, s_finalResponsesSuccess[i])) {
- return 1;
- }
- }
- return 0;
- }
- /**
- * returns 1 if line is a final response, either error or success
- * See 27.007 annex B
- * WARNING: NO CARRIER and others are sometimes unsolicited
- */
- static int isFinalResponse(const char *line)
- {
- return isFinalResponseSuccess(line) || isFinalResponseError(line);
- }
- /**
- * returns 1 if line is the first line in (what will be) a two-line
- * SMS unsolicited response
- */
- static const char * s_smsUnsoliciteds[] = {
- "+CMT:",
- "+CDS:",
- "+CBM:"
- };
- static int isSMSUnsolicited(const char *line)
- {
- size_t i;
- for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
- if (strStartsWith(line, s_smsUnsoliciteds[i])) {
- return 1;
- }
- }
- return 0;
- }
- /** assumes s_commandmutex is held */
- static void handleFinalResponse(const char *line)
- {
- sp_response->finalResponse = strdup(line);
- pthread_cond_signal(&s_commandcond);
- }
- static void handleUnsolicited(const char *line)
- {
- if (s_unsolHandler != NULL) {
- s_unsolHandler(line, NULL);
- }
- }
- static void processLine(const char *line)
- {
- pthread_mutex_lock(&s_commandmutex);
- if (sp_response == NULL) {
- /* no command pending */
- handleUnsolicited(line);
- } else if (isFinalResponseSuccess(line)) {
- sp_response->success = 1;
- handleFinalResponse(line);
- } else if (isFinalResponseError(line)) {
- sp_response->success = 0;
- handleFinalResponse(line);
- } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
- // See eg. TS 27.005 4.3
- // Commands like AT+CMGS have a "> " prompt
- writeCtrlZ(s_smsPDU);
- s_smsPDU = NULL;
- } else switch (s_type) {
- case NO_RESULT:
- handleUnsolicited(line);
- break;
- case NUMERIC:
- if (sp_response->p_intermediates == NULL
- && isdigit(line[0])
- ) {
- addIntermediate(line);
- } else {
- /* either we already have an intermediate response or
- the line doesn't begin with a digit */
- handleUnsolicited(line);
- }
- break;
- case SINGLELINE:
- if (sp_response->p_intermediates == NULL
- && strStartsWith (line, s_responsePrefix)
- ) {
- addIntermediate(line);
- } else {
- /* we already have an intermediate response */
- handleUnsolicited(line);
- }
- break;
- case MULTILINE:
- if (strStartsWith (line, s_responsePrefix)) {
- addIntermediate(line);
- } else {
- handleUnsolicited(line);
- }
- break;
- default: /* this should never be reached */
- LOGE("Unsupported AT command type %dn", s_type);
- handleUnsolicited(line);
- break;
- }
- pthread_mutex_unlock(&s_commandmutex);
- }
- /**
- * Returns a pointer to the end of the next line
- * special-cases the "> " SMS prompt
- *
- * returns NULL if there is no complete line
- */
- static char * findNextEOL(char *cur)
- {
- if (cur[0] == '>' && cur[1] == ' ' && cur[2] == ' ') {
- /* SMS prompt character...not r terminated */
- return cur+2;
- }
- // Find next newline
- while (*cur != ' ' && *cur != 'r' && *cur != 'n') cur++;
- return *cur == ' ' ? NULL : cur;
- }
- /**
- * Reads a line from the AT channel, returns NULL on timeout.
- * Assumes it has exclusive read access to the FD
- *
- * This line is valid only until the next call to readline
- *
- * This function exists because as of writing, android libc does not
- * have buffered stdio.
- */
- static const char *readline()
- {
- ssize_t count;
- char *p_read = NULL;
- char *p_eol = NULL;
- char *ret;
- /* this is a little odd. I use *s_ATBufferCur == 0 to
- * mean "buffer consumed completely". If it points to a character, than
- * the buffer continues until a