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