100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/* //device/system/reference-ril/atchannel.c 200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** 300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** Copyright 2006, The Android Open Source Project 400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** 500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License"); 600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** you may not use this file except in compliance with the License. 700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** You may obtain a copy of the License at 800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** 900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** http://www.apache.org/licenses/LICENSE-2.0 1000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** 1100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** Unless required by applicable law or agreed to in writing, software 1200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS, 1300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** See the License for the specific language governing permissions and 1500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project** limitations under the License. 1600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project*/ 1700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 1800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include "atchannel.h" 1900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include "at_tok.h" 2000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 2100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <stdio.h> 2200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <string.h> 2300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <pthread.h> 2400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <ctype.h> 2500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <stdlib.h> 2600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <errno.h> 2700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <fcntl.h> 2800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <sys/time.h> 2900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <time.h> 3000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <unistd.h> 3100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 3200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define LOG_NDEBUG 0 3300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define LOG_TAG "AT" 3400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include <utils/Log.h> 3500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 3600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#include "misc.h" 3700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 38894fbbd4272a5075d99a6aa245ca3f6bc2b62989Colin Cross#ifdef HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE 3900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define USE_NP 1 40894fbbd4272a5075d99a6aa245ca3f6bc2b62989Colin Cross#endif /* HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE */ 4100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 4200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 4300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define NUM_ELEMS(x) (sizeof(x)/sizeof(x[0])) 4400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 4500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define MAX_AT_RESPONSE (8 * 1024) 4600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define HANDSHAKE_RETRY_COUNT 8 4700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#define HANDSHAKE_TIMEOUT_MSEC 250 4800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 4900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic pthread_t s_tid_reader; 5000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int s_fd = -1; /* fd of the AT channel */ 5100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic ATUnsolHandler s_unsolHandler; 5200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 5300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/* for input buffering */ 5400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 5500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic char s_ATBuffer[MAX_AT_RESPONSE+1]; 5600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic char *s_ATBufferCur = s_ATBuffer; 5700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 5800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#if AT_DEBUG 5900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid AT_DUMP(const char* prefix, const char* buff, int len) 6000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 6100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (len < 0) 6200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project len = strlen(buff); 634dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGD("%.*s", len, buff); 6400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 6500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif 6600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 6700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/* 6800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * for current pending command 6900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * these are protected by s_commandmutex 7000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 7100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 7200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER; 7300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER; 7400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 7500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic ATCommandType s_type; 7600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic const char *s_responsePrefix = NULL; 7700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic const char *s_smsPDU = NULL; 7800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic ATResponse *sp_response = NULL; 7900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 8000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void (*s_onTimeout)(void) = NULL; 8100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void (*s_onReaderClosed)(void) = NULL; 8200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int s_readerClosed; 8300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 8400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void onReaderClosed(); 8500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int writeCtrlZ (const char *s); 8600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int writeline (const char *s); 8700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 8800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifndef USE_NP 8900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void setTimespecRelative(struct timespec *p_ts, long long msec) 9000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 9100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project struct timeval tv; 9200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 9300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project gettimeofday(&tv, (struct timezone *) NULL); 9400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 9500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* what's really funny about this is that I know 9600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_cond_timedwait just turns around and makes this 9700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project a relative time again */ 9800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_ts->tv_sec = tv.tv_sec + (msec / 1000); 9900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; 10000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 10100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif /*USE_NP*/ 10200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 10300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void sleepMsec(long long msec) 10400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 10500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project struct timespec ts; 10600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 10700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 10800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ts.tv_sec = (msec / 1000); 10900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ts.tv_nsec = (msec % 1000) * 1000 * 1000; 11000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 11100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project do { 11200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = nanosleep (&ts, &ts); 11300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } while (err < 0 && errno == EINTR); 11400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 11500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 11600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 11700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 11800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** add an intermediate response to sp_response*/ 11900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void addIntermediate(const char *line) 12000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 12100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATLine *p_new; 12200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 12300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_new = (ATLine *) malloc(sizeof(ATLine)); 12400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 12500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_new->line = strdup(line); 12600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 12700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* note: this adds to the head of the list, so the list 12800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project will be in reverse order of lines received. the order is flipped 12900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project again before passing on to the command issuer */ 13000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_new->p_next = sp_response->p_intermediates; 13100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response->p_intermediates = p_new; 13200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 13300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 13400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 13500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 13600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * returns 1 if line is a final response indicating error 13700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * See 27.007 annex B 13800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * WARNING: NO CARRIER and others are sometimes unsolicited 13900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 14000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic const char * s_finalResponsesError[] = { 14100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "ERROR", 14200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "+CMS ERROR:", 14300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "+CME ERROR:", 14400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "NO CARRIER", /* sometimes! */ 14500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "NO ANSWER", 14600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "NO DIALTONE", 14700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}; 14800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int isFinalResponseError(const char *line) 14900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 15000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t i; 15100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 15200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) { 15300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (strStartsWith(line, s_finalResponsesError[i])) { 15400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 1; 15500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 15600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 15700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 15800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 0; 15900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 16000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 16100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 16200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * returns 1 if line is a final response indicating success 16300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * See 27.007 annex B 16400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * WARNING: NO CARRIER and others are sometimes unsolicited 16500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 16600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic const char * s_finalResponsesSuccess[] = { 16700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "OK", 16800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "CONNECT" /* some stacks start up data on another channel */ 16900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}; 17000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int isFinalResponseSuccess(const char *line) 17100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 17200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t i; 17300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 17400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) { 17500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (strStartsWith(line, s_finalResponsesSuccess[i])) { 17600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 1; 17700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 17800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 17900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 18000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 0; 18100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 18200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 18300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 18400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * returns 1 if line is a final response, either error or success 18500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * See 27.007 annex B 18600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * WARNING: NO CARRIER and others are sometimes unsolicited 18700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 18800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int isFinalResponse(const char *line) 18900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 19000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return isFinalResponseSuccess(line) || isFinalResponseError(line); 19100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 19200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 19300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 19400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 19500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * returns 1 if line is the first line in (what will be) a two-line 19600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * SMS unsolicited response 19700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 19800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic const char * s_smsUnsoliciteds[] = { 19900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "+CMT:", 20000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "+CDS:", 20100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project "+CBM:" 20200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project}; 20300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int isSMSUnsolicited(const char *line) 20400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 20500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t i; 20600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 20700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) { 20800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (strStartsWith(line, s_smsUnsoliciteds[i])) { 20900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 1; 21000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 21100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 21200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 21300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 0; 21400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 21500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 21600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 21700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** assumes s_commandmutex is held */ 21800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void handleFinalResponse(const char *line) 21900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 22000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response->finalResponse = strdup(line); 22100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 22200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_cond_signal(&s_commandcond); 22300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 22400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 22500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void handleUnsolicited(const char *line) 22600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 22700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (s_unsolHandler != NULL) { 22800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_unsolHandler(line, NULL); 22900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 23000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 23100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 23200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void processLine(const char *line) 23300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 23400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_lock(&s_commandmutex); 23500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 23600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (sp_response == NULL) { 23700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* no command pending */ 23800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleUnsolicited(line); 23900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else if (isFinalResponseSuccess(line)) { 24000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response->success = 1; 24100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleFinalResponse(line); 24200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else if (isFinalResponseError(line)) { 24300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response->success = 0; 24400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleFinalResponse(line); 24500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) { 24600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // See eg. TS 27.005 4.3 24700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // Commands like AT+CMGS have a "> " prompt 24800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project writeCtrlZ(s_smsPDU); 24900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_smsPDU = NULL; 25000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else switch (s_type) { 25100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project case NO_RESULT: 25200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleUnsolicited(line); 25300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 25400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project case NUMERIC: 25500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (sp_response->p_intermediates == NULL 25600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && isdigit(line[0]) 25700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ) { 25800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project addIntermediate(line); 25900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 26000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* either we already have an intermediate response or 26100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project the line doesn't begin with a digit */ 26200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleUnsolicited(line); 26300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 26400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 26500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project case SINGLELINE: 26600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (sp_response->p_intermediates == NULL 26700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && strStartsWith (line, s_responsePrefix) 26800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ) { 26900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project addIntermediate(line); 27000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 27100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* we already have an intermediate response */ 27200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleUnsolicited(line); 27300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 27400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 27500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project case MULTILINE: 27600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (strStartsWith (line, s_responsePrefix)) { 27700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project addIntermediate(line); 27800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 27900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleUnsolicited(line); 28000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 28100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 28200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 28300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project default: /* this should never be reached */ 2844dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGE("Unsupported AT command type %d\n", s_type); 28500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project handleUnsolicited(line); 28600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 28700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 28800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 28900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_unlock(&s_commandmutex); 29000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 29100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 29200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 29300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 29400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Returns a pointer to the end of the next line 29500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * special-cases the "> " SMS prompt 29600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 29700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * returns NULL if there is no complete line 29800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 29900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic char * findNextEOL(char *cur) 30000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 30100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') { 30200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* SMS prompt character...not \r terminated */ 30300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return cur+2; 30400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 30500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 30600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // Find next newline 30700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++; 30800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 30900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return *cur == '\0' ? NULL : cur; 31000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 31100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 31200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 31300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 31400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Reads a line from the AT channel, returns NULL on timeout. 31500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Assumes it has exclusive read access to the FD 31600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 31700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * This line is valid only until the next call to readline 31800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 31900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * This function exists because as of writing, android libc does not 32000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * have buffered stdio. 32100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 32200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 32300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic const char *readline() 32400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 32500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ssize_t count; 32600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 32700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project char *p_read = NULL; 32800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project char *p_eol = NULL; 32900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project char *ret; 33000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 33100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* this is a little odd. I use *s_ATBufferCur == 0 to 33200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * mean "buffer consumed completely". If it points to a character, than 33300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * the buffer continues until a \0 33400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 33500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (*s_ATBufferCur == '\0') { 33600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* empty buffer */ 33700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_ATBufferCur = s_ATBuffer; 33800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *s_ATBufferCur = '\0'; 33900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_read = s_ATBuffer; 34000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { /* *s_ATBufferCur != '\0' */ 34100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* there's data in the buffer from the last read */ 34200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 34300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // skip over leading newlines 34400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') 34500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_ATBufferCur++; 34600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 34700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_eol = findNextEOL(s_ATBufferCur); 34800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 34900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (p_eol == NULL) { 35000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* a partial line. move it up and prepare to read more */ 35100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t len; 35200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 35300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project len = strlen(s_ATBufferCur); 35400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 35500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project memmove(s_ATBuffer, s_ATBufferCur, len + 1); 35600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_read = s_ATBuffer + len; 35700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_ATBufferCur = s_ATBuffer; 35800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 35900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* Otherwise, (p_eol !- NULL) there is a complete line */ 36000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* that will be returned the while () loop below */ 36100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 36200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 36300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (p_eol == NULL) { 36400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) { 3654dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGE("ERROR: Input line exceeded buffer\n"); 36600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* ditch buffer and start over again */ 36700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_ATBufferCur = s_ATBuffer; 36800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *s_ATBufferCur = '\0'; 36900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_read = s_ATBuffer; 37000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 37100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 37200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project do { 37300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project count = read(s_fd, p_read, 37400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project MAX_AT_RESPONSE - (p_read - s_ATBuffer)); 37500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } while (count < 0 && errno == EINTR); 37600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 37700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (count > 0) { 37800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project AT_DUMP( "<< ", p_read, count ); 37900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 38000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_read[count] = '\0'; 38100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 38200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // skip over leading newlines 38300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') 38400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_ATBufferCur++; 38500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 38600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_eol = findNextEOL(s_ATBufferCur); 38700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_read += count; 38800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else if (count <= 0) { 38900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* read error encountered or EOF reached */ 39000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if(count == 0) { 3914dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGD("atchannel: EOF reached"); 39200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 3934dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGD("atchannel: read error %s", strerror(errno)); 39400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 39500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return NULL; 39600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 39700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 39800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 39900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* a full line in the buffer. Place a \0 over the \r and return */ 40000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 40100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ret = s_ATBufferCur; 40200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *p_eol = '\0'; 40300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */ 40400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* and there will be a \0 at *p_read */ 40500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 4064dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGD("AT< %s\n", ret); 40700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return ret; 40800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 40900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 41000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 41100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void onReaderClosed() 41200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 41300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (s_onReaderClosed != NULL && s_readerClosed == 0) { 41400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 41500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_lock(&s_commandmutex); 41600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 41700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_readerClosed = 1; 41800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 41900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_cond_signal(&s_commandcond); 42000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 42100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_unlock(&s_commandmutex); 42200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 42300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_onReaderClosed(); 42400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 42500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 42600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 42700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 42800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void *readerLoop(void *arg) 42900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 43000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project for (;;) { 43100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char * line; 43200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 43300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project line = readline(); 43400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 43500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (line == NULL) { 43600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 43700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 43800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 43900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if(isSMSUnsolicited(line)) { 44000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project char *line1; 44100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *line2; 44200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 44300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // The scope of string returned by 'readline()' is valid only 44400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // till next call to 'readline()' hence making a copy of line 44500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project // before calling readline again. 44600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project line1 = strdup(line); 44700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project line2 = readline(); 44800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 44900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (line2 == NULL) { 45000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 45100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 45200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 45300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (s_unsolHandler != NULL) { 45400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_unsolHandler (line1, line2); 45500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 45600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project free(line1); 45700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 45800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project processLine(line); 45900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 46000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 46100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 46200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project onReaderClosed(); 46300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 46400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return NULL; 46500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 46600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 46700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 46800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Sends string s to the radio with a \r appended. 46900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Returns AT_ERROR_* on error, 0 on success 47000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 47100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * This function exists because as of writing, android libc does not 47200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * have buffered stdio. 47300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 47400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int writeline (const char *s) 47500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 47600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t cur = 0; 47700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t len = strlen(s); 47800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ssize_t written; 47900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 48000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (s_fd < 0 || s_readerClosed > 0) { 48100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_CHANNEL_CLOSED; 48200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 48300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 4844dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGD("AT> %s\n", s); 48500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 48600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project AT_DUMP( ">> ", s, strlen(s) ); 48700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 48800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* the main string */ 48900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (cur < len) { 49000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project do { 49100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project written = write (s_fd, s + cur, len - cur); 49200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } while (written < 0 && errno == EINTR); 49300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 49400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (written < 0) { 49500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_GENERIC; 49600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 49700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 49800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project cur += written; 49900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 50000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 50100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* the \r */ 50200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 50300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project do { 50400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project written = write (s_fd, "\r" , 1); 50500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } while ((written < 0 && errno == EINTR) || (written == 0)); 50600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 50700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (written < 0) { 50800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_GENERIC; 50900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 51000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 51100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 0; 51200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 51300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int writeCtrlZ (const char *s) 51400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 51500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t cur = 0; 51600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project size_t len = strlen(s); 51700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ssize_t written; 51800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 51900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (s_fd < 0 || s_readerClosed > 0) { 52000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_CHANNEL_CLOSED; 52100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 52200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 5234dcab4f90d2d49e40100e4888b1411dfbd1c9783Wink Saville RLOGD("AT> %s^Z\n", s); 52400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 52500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project AT_DUMP( ">* ", s, strlen(s) ); 52600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 52700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* the main string */ 52800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (cur < len) { 52900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project do { 53000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project written = write (s_fd, s + cur, len - cur); 53100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } while (written < 0 && errno == EINTR); 53200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 53300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (written < 0) { 53400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_GENERIC; 53500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 53600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 53700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project cur += written; 53800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 53900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 54000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* the ^Z */ 54100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 54200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project do { 54300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project written = write (s_fd, "\032" , 1); 54400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } while ((written < 0 && errno == EINTR) || (written == 0)); 54500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 54600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (written < 0) { 54700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_GENERIC; 54800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 54900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 55000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 0; 55100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 55200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 55300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void clearPendingCommand() 55400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 55500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (sp_response != NULL) { 55600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project at_response_free(sp_response); 55700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 55800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 55900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response = NULL; 56000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_responsePrefix = NULL; 56100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_smsPDU = NULL; 56200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 56300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 56400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 56500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 56600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Starts AT handler on stream "fd' 56700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * returns 0 on success, -1 on error 56800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 56900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_open(int fd, ATUnsolHandler h) 57000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 57100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int ret; 57200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_t tid; 57300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_attr_t attr; 57400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 57500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_fd = fd; 57600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_unsolHandler = h; 57700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_readerClosed = 0; 57800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 57900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_responsePrefix = NULL; 58000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_smsPDU = NULL; 58100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response = NULL; 58200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 58300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_attr_init (&attr); 58400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 58500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 58600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr); 58700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 58800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (ret < 0) { 58900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project perror ("pthread_create"); 59000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return -1; 59100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 59200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 59300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 59400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return 0; 59500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 59600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 59700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/* FIXME is it ok to call this from the reader and the command thread? */ 59800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid at_close() 59900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 60000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (s_fd >= 0) { 60100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project close(s_fd); 60200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 60300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_fd = -1; 60400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 60500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_lock(&s_commandmutex); 60600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 60700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_readerClosed = 1; 60800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 60900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_cond_signal(&s_commandcond); 61000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 61100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_unlock(&s_commandmutex); 61200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 61300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* the reader thread should eventually die */ 61400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 61500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 61600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic ATResponse * at_response_new() 61700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 61800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return (ATResponse *) calloc(1, sizeof(ATResponse)); 61900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 62000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 62100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid at_response_free(ATResponse *p_response) 62200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 62300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATLine *p_line; 62400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 62500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (p_response == NULL) return; 62600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 62700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_line = p_response->p_intermediates; 62800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 62900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (p_line != NULL) { 63000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATLine *p_toFree; 63100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 63200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_toFree = p_line; 63300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_line = p_line->p_next; 63400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 63500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project free(p_toFree->line); 63600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project free(p_toFree); 63700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 63800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 63900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project free (p_response->finalResponse); 64000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project free (p_response); 64100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 64200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 64300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 64400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * The line reader places the intermediate responses in reverse order 64500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * here we flip them back 64600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 64700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic void reverseIntermediates(ATResponse *p_response) 64800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 64900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATLine *pcur,*pnext; 65000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 65100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pcur = p_response->p_intermediates; 65200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_response->p_intermediates = NULL; 65300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 65400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (pcur != NULL) { 65500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pnext = pcur->p_next; 65600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pcur->p_next = p_response->p_intermediates; 65700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_response->p_intermediates = pcur; 65800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pcur = pnext; 65900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 66000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 66100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 66200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 66300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Internal send_command implementation 66400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Doesn't lock or call the timeout callback 66500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 66600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * timeoutMsec == 0 means infinite timeout 66700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 66800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 66900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int at_send_command_full_nolock (const char *command, ATCommandType type, 67000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *responsePrefix, const char *smspdu, 67100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project long long timeoutMsec, ATResponse **pp_outResponse) 67200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 67300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err = 0; 67400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifndef USE_NP 67500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project struct timespec ts; 67600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif /*USE_NP*/ 67700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 67800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if(sp_response != NULL) { 67900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = AT_ERROR_COMMAND_PENDING; 68000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project goto error; 68100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 68200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 68300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = writeline (command); 68400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 68500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err < 0) { 68600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project goto error; 68700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 68800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 68900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_type = type; 69000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_responsePrefix = responsePrefix; 69100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_smsPDU = smspdu; 69200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response = at_response_new(); 69300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 69400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifndef USE_NP 69500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (timeoutMsec != 0) { 69600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project setTimespecRelative(&ts, timeoutMsec); 69700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 69800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif /*USE_NP*/ 69900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 70000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project while (sp_response->finalResponse == NULL && s_readerClosed == 0) { 70100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (timeoutMsec != 0) { 70200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#ifdef USE_NP 70300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); 70400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#else 70500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts); 70600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project#endif /*USE_NP*/ 70700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 70800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = pthread_cond_wait(&s_commandcond, &s_commandmutex); 70900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 71000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 71100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == ETIMEDOUT) { 71200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = AT_ERROR_TIMEOUT; 71300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project goto error; 71400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 71500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 71600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 71700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (pp_outResponse == NULL) { 71800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project at_response_free(sp_response); 71900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } else { 72000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* line reader stores intermediate responses in reverse order */ 72100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project reverseIntermediates(sp_response); 72200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *pp_outResponse = sp_response; 72300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 72400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 72500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sp_response = NULL; 72600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 72700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if(s_readerClosed > 0) { 72800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = AT_ERROR_CHANNEL_CLOSED; 72900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project goto error; 73000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 73100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 73200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = 0; 73300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projecterror: 73400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project clearPendingCommand(); 73500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 73600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 73700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 73800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 73900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 74000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Internal send_command implementation 74100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 74200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * timeoutMsec == 0 means infinite timeout 74300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 74400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectstatic int at_send_command_full (const char *command, ATCommandType type, 74500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *responsePrefix, const char *smspdu, 74600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project long long timeoutMsec, ATResponse **pp_outResponse) 74700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 74800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 74900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 75000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (0 != pthread_equal(s_tid_reader, pthread_self())) { 75100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* cannot be called from reader thread */ 75200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_INVALID_THREAD; 75300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 75400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 75500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_lock(&s_commandmutex); 75600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 75700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full_nolock(command, type, 75800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project responsePrefix, smspdu, 75900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project timeoutMsec, pp_outResponse); 76000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 76100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_unlock(&s_commandmutex); 76200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 76300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) { 76400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_onTimeout(); 76500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 76600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 76700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 76800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 76900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 77000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 77100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 77200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Issue a single normal AT command with no intermediate response expected 77300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 77400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * "command" should not include \r 77500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * pp_outResponse can be NULL 77600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * 77700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * if non-NULL, the resulting ATResponse * must be eventually freed with 77800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * at_response_free 77900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 78000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_send_command (const char *command, ATResponse **pp_outResponse) 78100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 78200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 78300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 78400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full (command, NO_RESULT, NULL, 78500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project NULL, 0, pp_outResponse); 78600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 78700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 78800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 78900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 79000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 79100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_send_command_singleline (const char *command, 79200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *responsePrefix, 79300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATResponse **pp_outResponse) 79400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 79500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 79600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 79700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full (command, SINGLELINE, responsePrefix, 79800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project NULL, 0, pp_outResponse); 79900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 80000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == 0 && pp_outResponse != NULL 80100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && (*pp_outResponse)->success > 0 80200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && (*pp_outResponse)->p_intermediates == NULL 80300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ) { 80400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* successful command must have an intermediate response */ 80500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project at_response_free(*pp_outResponse); 80600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *pp_outResponse = NULL; 80700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_INVALID_RESPONSE; 80800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 80900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 81000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 81100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 81200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 81300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 81400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_send_command_numeric (const char *command, 81500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATResponse **pp_outResponse) 81600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 81700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 81800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 81900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full (command, NUMERIC, NULL, 82000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project NULL, 0, pp_outResponse); 82100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 82200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == 0 && pp_outResponse != NULL 82300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && (*pp_outResponse)->success > 0 82400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && (*pp_outResponse)->p_intermediates == NULL 82500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ) { 82600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* successful command must have an intermediate response */ 82700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project at_response_free(*pp_outResponse); 82800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *pp_outResponse = NULL; 82900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_INVALID_RESPONSE; 83000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 83100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 83200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 83300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 83400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 83500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 83600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_send_command_sms (const char *command, 83700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *pdu, 83800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *responsePrefix, 83900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATResponse **pp_outResponse) 84000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 84100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 84200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 84300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full (command, SINGLELINE, responsePrefix, 84400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pdu, 0, pp_outResponse); 84500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 84600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == 0 && pp_outResponse != NULL 84700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && (*pp_outResponse)->success > 0 84800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project && (*pp_outResponse)->p_intermediates == NULL 84900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ) { 85000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* successful command must have an intermediate response */ 85100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project at_response_free(*pp_outResponse); 85200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project *pp_outResponse = NULL; 85300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_INVALID_RESPONSE; 85400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 85500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 85600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 85700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 85800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 85900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 86000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_send_command_multiline (const char *command, 86100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project const char *responsePrefix, 86200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ATResponse **pp_outResponse) 86300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 86400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 86500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 86600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full (command, MULTILINE, responsePrefix, 86700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project NULL, 0, pp_outResponse); 86800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 86900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 87000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 87100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 87200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 87300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** This callback is invoked on the command thread */ 87400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid at_set_on_timeout(void (*onTimeout)(void)) 87500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 87600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_onTimeout = onTimeout; 87700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 87800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 87900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 88000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * This callback is invoked on the reader thread (like ATUnsolHandler) 88100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * when the input stream closes before you call at_close 88200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * (not when you call at_close()) 88300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * You should still call at_close() 88400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 88500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 88600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectvoid at_set_on_reader_closed(void (*onClose)(void)) 88700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 88800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project s_onReaderClosed = onClose; 88900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 89000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 89100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 89200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 89300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Periodically issue an AT command and wait for a response. 89400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Used to ensure channel has start up and is active 89500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 89600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 89700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Projectint at_handshake() 89800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 89900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int i; 90000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err = 0; 90100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 90200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (0 != pthread_equal(s_tid_reader, pthread_self())) { 90300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* cannot be called from reader thread */ 90400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return AT_ERROR_INVALID_THREAD; 90500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 90600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 90700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_lock(&s_commandmutex); 90800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 90900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) { 91000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* some stacks start with verbose off */ 91100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT, 91200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL); 91300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 91400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == 0) { 91500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project break; 91600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 91700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 91800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 91900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err == 0) { 92000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project /* pause for a bit to let the input buffer drain any unmatched OK's 92100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project (they will appear as extraneous unsolicited responses) */ 92200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 92300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project sleepMsec(HANDSHAKE_TIMEOUT_MSEC); 92400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 92500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 92600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project pthread_mutex_unlock(&s_commandmutex); 92700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 92800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return err; 92900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 93000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 93100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project/** 93200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Returns error code from response 93300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project * Assumes AT+CMEE=1 (numeric) mode 93400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project */ 93500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source ProjectAT_CME_Error at_get_cme_error(const ATResponse *p_response) 93600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project{ 93700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int ret; 93800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project int err; 93900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project char *p_cur; 94000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 94100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (p_response->success > 0) { 94200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return CME_SUCCESS; 94300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 94400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 94500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (p_response->finalResponse == NULL 94600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project || !strStartsWith(p_response->finalResponse, "+CME ERROR:") 94700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project ) { 94800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return CME_ERROR_NON_CME; 94900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 95000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 95100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project p_cur = p_response->finalResponse; 95200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_tok_start(&p_cur); 95300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 95400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err < 0) { 95500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return CME_ERROR_NON_CME; 95600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 95700f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 95800f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project err = at_tok_nextint(&p_cur, &ret); 95900f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 96000f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project if (err < 0) { 96100f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return CME_ERROR_NON_CME; 96200f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project } 96300f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 96400f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project return (AT_CME_Error) ret; 96500f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project} 96600f06fc3fdb05d4276e76091cacb42b6f6862222The Android Open Source Project 967