1 /* //device/system/reference-ril/atchannel.c
3 ** Copyright 2006, The Android Open Source Project
5 ** Licensed under the Apache License, Version 2.0 (the "License");
6 ** you may not use this file except in compliance with the License.
7 ** You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
18 #include "atchannel.h"
37 #include <utils/Log.h>
39 #ifdef HAVE_ANDROID_OS
41 #include <linux/omap_csmi.h>
42 #endif /*HAVE_ANDROID_OS*/
46 #define MAX_AT_RESPONSE (8 * 1024)
47 #define HANDSHAKE_RETRY_COUNT 8
48 #define HANDSHAKE_TIMEOUT_MSEC 250
49 #define DEFAULT_AT_TIMEOUT_MSEC (3 * 60 * 1000)
54 int fd; /* fd of the AT channel. */
57 ATUnsolHandler unsolHandler;
59 /* For input buffering. */
60 char ATBuffer[MAX_AT_RESPONSE+1];
66 * For current pending command, these are protected by commandmutex.
68 * The mutex and cond struct is memset in the getAtChannel() function,
69 * so no initializer should be needed.
71 pthread_mutex_t requestmutex;
72 pthread_mutex_t commandmutex;
73 pthread_cond_t requestcond;
74 pthread_cond_t commandcond;
77 const char *responsePrefix;
81 void (*onTimeout)(void);
82 void (*onReaderClosed)(void);
88 static struct atcontext *s_defaultAtContext = NULL;
89 static va_list empty = {0};
91 static pthread_key_t key;
92 static pthread_once_t key_once = PTHREAD_ONCE_INIT;
94 static int writeCtrlZ (const char *s);
95 static int writeline (const char *s);
96 static void onReaderClosed(void);
98 static void make_key(void)
100 (void) pthread_key_create(&key, NULL);
104 * Set the atcontext pointer. Useful for sub-threads that needs to hold
105 * the same state information.
107 * The caller IS responsible for freeing any memory already allocated
108 * for any previous atcontexts.
110 static void setAtContext(struct atcontext *ac)
112 (void) pthread_once(&key_once, make_key);
113 (void) pthread_setspecific(key, ac);
116 static void ac_free(void)
118 struct atcontext *ac = NULL;
119 (void) pthread_once(&key_once, make_key);
120 if ((ac = (struct atcontext *) pthread_getspecific(key)) != NULL) {
122 ALOGD("%s() freed current thread AT context", __func__);
124 ALOGW("%s() No AT context exist for current thread, cannot free it",
129 static int initializeAtContext(void)
131 struct atcontext *ac = NULL;
133 if (pthread_once(&key_once, make_key)) {
134 ALOGE("%s() Pthread_once failed!", __func__);
138 ac = (struct atcontext *)pthread_getspecific(key);
141 ac = (struct atcontext *) malloc(sizeof(struct atcontext));
143 ALOGE("%s() Failed to allocate memory", __func__);
147 memset(ac, 0, sizeof(struct atcontext));
150 ac->readerCmdFds[0] = -1;
151 ac->readerCmdFds[1] = -1;
152 ac->ATBufferCur = ac->ATBuffer;
154 if (pipe(ac->readerCmdFds)) {
155 ALOGE("%s() Failed to create pipe: %s", __func__, strerror(errno));
159 pthread_mutex_init(&ac->commandmutex, NULL);
160 pthread_mutex_init(&ac->requestmutex, NULL);
161 pthread_cond_init(&ac->requestcond, NULL);
162 pthread_cond_init(&ac->commandcond, NULL);
164 ac->timeoutMsec = DEFAULT_AT_TIMEOUT_MSEC;
166 if (pthread_setspecific(key, ac)) {
167 ALOGE("%s() Calling pthread_setspecific failed!", __func__);
172 ALOGI("Initialized new AT Context!");
177 ALOGE("%s() Failed initializing new AT Context!", __func__);
182 static struct atcontext *getAtContext(void)
184 struct atcontext *ac = NULL;
186 (void) pthread_once(&key_once, make_key);
188 if ((ac = (struct atcontext *) pthread_getspecific(key)) == NULL) {
189 if (s_defaultAtContext) {
190 ALOGW("WARNING! external thread use default AT Context");
191 ac = s_defaultAtContext;
193 ALOGE("WARNING! %s() called from external thread with "
194 "no defaultAtContext set!! This IS a bug! "
195 "A crash is probably nearby!", __func__);
203 * This function will make the current at thread the default channel,
204 * meaning that calls from a thread that is not a queuerunner will
205 * be executed in this context.
207 void at_make_default_channel(void)
209 struct atcontext *ac = getAtContext();
211 if (ac->isInitialized)
212 s_defaultAtContext = ac;
216 void AT_DUMP(const char* prefix, const char* buff, int len)
220 ALOGD("%.*s", len, buff);
224 #ifndef HAVE_ANDROID_OS
225 int pthread_cond_timeout_np(pthread_cond_t *cond,
226 pthread_mutex_t * mutex,
230 clock_gettime(CLOCK_REALTIME, &ts);
232 ts.tv_sec += msecs / 1000;
233 ts.tv_nsec += (msecs % 1000) * 1000000;
234 return pthread_cond_timedwait(cond, mutex, &ts);
236 #endif /*HAVE_ANDROID_OS*/
238 static void sleepMsec(long long msec)
243 ts.tv_sec = (msec / 1000);
244 ts.tv_nsec = (msec % 1000) * 1000 * 1000;
247 err = nanosleep (&ts, &ts);
248 } while (err < 0 && errno == EINTR);
253 /** Add an intermediate response to sp_response. */
254 static void addIntermediate(const char *line)
257 struct atcontext *ac = getAtContext();
259 p_new = (ATLine *) malloc(sizeof(ATLine));
261 p_new->line = strdup(line);
263 /* Note: This adds to the head of the list, so the list will
264 be in reverse order of lines received. the order is flipped
265 again before passing on to the command issuer. */
266 p_new->p_next = ac->response->p_intermediates;
267 ac->response->p_intermediates = p_new;
272 * Returns 1 if line is a final response indicating error.
273 * See 27.007 annex B.
274 * WARNING: NO CARRIER and others are sometimes unsolicited.
276 static const char * s_finalResponsesError[] = {
280 "NO CARRIER", /* Sometimes! */
285 static int isFinalResponseError(const char *line)
289 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) {
290 if (strStartsWith(line, s_finalResponsesError[i])) {
299 * Returns 1 if line is a final response indicating success.
300 * See 27.007 annex B.
301 * WARNING: NO CARRIER and others are sometimes unsolicited.
303 static const char * s_finalResponsesSuccess[] = {
305 "CONNECT" /* Some stacks start up data on another channel. */
307 static int isFinalResponseSuccess(const char *line)
311 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) {
312 if (strStartsWith(line, s_finalResponsesSuccess[i])) {
321 * Returns 1 if line is the first line in (what will be) a two-line
322 * SMS unsolicited response.
324 static const char * s_smsUnsoliciteds[] = {
329 static int isSMSUnsolicited(const char *line)
333 for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
334 if (strStartsWith(line, s_smsUnsoliciteds[i])) {
343 /** Assumes s_commandmutex is held. */
344 static void handleFinalResponse(const char *line)
346 struct atcontext *ac = getAtContext();
348 ac->response->finalResponse = strdup(line);
350 pthread_cond_signal(&ac->commandcond);
353 static void handleUnsolicited(const char *line)
355 struct atcontext *ac = getAtContext();
357 if (ac->unsolHandler != NULL) {
358 ac->unsolHandler(line, NULL);
362 static void processLine(const char *line)
364 struct atcontext *ac = getAtContext();
365 pthread_mutex_lock(&ac->commandmutex);
367 if (ac->response == NULL) {
368 /* No command pending. */
369 handleUnsolicited(line);
370 } else if (isFinalResponseSuccess(line)) {
371 ac->response->success = 1;
372 handleFinalResponse(line);
373 } else if (isFinalResponseError(line)) {
374 ac->response->success = 0;
375 handleFinalResponse(line);
376 } else if (ac->smsPDU != NULL && 0 == strcmp(line, "> ")) {
377 /* See eg. TS 27.005 4.3.
378 Commands like AT+CMGS have a "> " prompt. */
379 writeCtrlZ(ac->smsPDU);
381 } else switch (ac->type) {
383 handleUnsolicited(line);
386 if (ac->response->p_intermediates == NULL
387 && isdigit(line[0])) {
388 addIntermediate(line);
390 /* Either we already have an intermediate response or
391 the line doesn't begin with a digit. */
392 handleUnsolicited(line);
396 if (ac->response->p_intermediates == NULL
397 && strStartsWith (line, ac->responsePrefix)) {
398 addIntermediate(line);
400 /* We already have an intermediate response. */
401 handleUnsolicited(line);
405 if (strStartsWith (line, ac->responsePrefix)) {
406 addIntermediate(line);
408 handleUnsolicited(line);
412 default: /* This should never be reached */
413 ALOGE("%s() Unsupported AT command type %d", __func__, ac->type);
414 handleUnsolicited(line);
418 pthread_mutex_unlock(&ac->commandmutex);
423 * Returns a pointer to the end of the next line,
424 * special-cases the "> " SMS prompt.
426 * returns NULL if there is no complete line.
428 static char * findNextEOL(char *cur)
430 if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
431 /* SMS prompt character...not \r terminated */
435 /* Find next newline */
436 while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
438 return *cur == '\0' ? NULL : cur;
443 * Reads a line from the AT channel, returns NULL on timeout.
444 * Assumes it has exclusive read access to the FD.
446 * This line is valid only until the next call to readline.
448 * This function exists because as of writing, android libc does not
449 * have buffered stdio.
452 static const char *readline(void)
460 struct atcontext *ac = getAtContext();
463 /* This is a little odd. I use *s_ATBufferCur == 0 to mean
464 * "buffer consumed completely". If it points to a character,
465 * then the buffer continues until a \0.
467 if (*ac->ATBufferCur == '\0') {
469 ac->ATBufferCur = ac->ATBuffer;
470 *ac->ATBufferCur = '\0';
471 p_read = ac->ATBuffer;
472 } else { /* *s_ATBufferCur != '\0' */
473 /* There's data in the buffer from the last read. */
475 /* skip over leading newlines */
476 while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n')
479 p_eol = findNextEOL(ac->ATBufferCur);
482 /* A partial line. Move it up and prepare to read more. */
485 len = strlen(ac->ATBufferCur);
487 memmove(ac->ATBuffer, ac->ATBufferCur, len + 1);
488 p_read = ac->ATBuffer + len;
489 ac->ATBufferCur = ac->ATBuffer;
491 /* Otherwise, (p_eol !- NULL) there is a complete line
492 that will be returned from the while () loop below. */
495 while (p_eol == NULL) {
497 struct pollfd pfds[2];
499 /* This condition should be synchronized with the read function call
500 * size argument below.
502 if (0 >= MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2) {
503 ALOGE("%s() ERROR: Input line exceeded buffer", __func__);
504 /* Ditch buffer and start over again. */
505 ac->ATBufferCur = ac->ATBuffer;
506 *ac->ATBufferCur = '\0';
507 p_read = ac->ATBuffer;
510 /* If our fd is invalid, we are probably closed. Return. */
515 pfds[0].events = POLLIN | POLLERR;
517 pfds[1].fd = ac->readerCmdFds[0];
518 pfds[1].events = POLLIN;
520 err = poll(pfds, 2, -1);
523 ALOGE("%s() poll: error: %s", __func__, strerror(errno));
527 if (pfds[1].revents & POLLIN) {
530 /* Just drain it. We don't care, this is just for waking up. */
531 read(pfds[1].fd, &buf, 1);
535 if (pfds[0].revents & POLLERR) {
536 ALOGE("%s() POLLERR event! Returning...", __func__);
540 if (!(pfds[0].revents & POLLIN))
544 /* The size argument should be synchronized to the ditch buffer
547 count = read(ac->fd, p_read,
548 MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2);
550 while (count < 0 && errno == EINTR);
553 AT_DUMP( "<< ", p_read, count );
554 ac->readCount += count;
556 /* Implementation requires extra EOS or EOL to get it right if
557 * there are no trailing newlines in the read buffer. Adding extra
558 * EOS does not harm even if there actually were trailing EOLs.
560 p_read[count] = '\0';
561 p_read[count+1] = '\0';
563 /* Skip over leading newlines. */
564 while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n')
567 p_eol = findNextEOL(ac->ATBufferCur);
569 } else if (count <= 0) {
570 /* Read error encountered or EOF reached. */
572 ALOGD("%s() atchannel: EOF reached.", __func__);
574 ALOGD("%s() atchannel: read error %s", __func__, strerror(errno));
580 /* A full line in the buffer. Place a \0 over the \r and return. */
582 ret = ac->ATBufferCur;
585 /* The extra EOS added after read takes care of the case when there is no
586 * valid data after p_eol.
588 ac->ATBufferCur = p_eol + 1; /* This will always be <= p_read,
589 and there will be a \0 at *p_read. */
591 ALOGI("AT(%d)< %s", ac->fd, ret);
595 static void onReaderClosed(void)
597 struct atcontext *ac = getAtContext();
598 if (ac->onReaderClosed != NULL && ac->readerClosed == 0) {
600 pthread_mutex_lock(&ac->commandmutex);
602 ac->readerClosed = 1;
604 pthread_cond_signal(&ac->commandcond);
606 pthread_mutex_unlock(&ac->commandmutex);
608 ac->onReaderClosed();
612 static void *readerLoop(void *arg)
614 struct atcontext *ac = NULL;
616 ALOGI("Entering readerloop!");
618 setAtContext((struct atcontext *) arg);
629 if(isSMSUnsolicited(line)) {
633 /* The scope of string returned by 'readline()' is valid only
634 until next call to 'readline()' hence making a copy of line
635 before calling readline again. */
636 line1 = strdup(line);
644 if (ac->unsolHandler != NULL)
645 ac->unsolHandler(line1, line2);
653 ALOGI("Exiting readerloop!");
658 * Sends string s to the radio with a \r appended.
659 * Returns AT_ERROR_* on error, 0 on success.
661 * This function exists because as of writing, android libc does not
662 * have buffered stdio.
664 static int writeline (const char *s)
667 size_t len = strlen(s);
670 struct atcontext *ac = getAtContext();
672 if (ac->fd < 0 || ac->readerClosed > 0) {
673 return AT_ERROR_CHANNEL_CLOSED;
676 ALOGD("AT(%d)> %s", ac->fd, s);
678 AT_DUMP( ">> ", s, strlen(s) );
680 /* The main string. */
683 written = write (ac->fd, s + cur, len - cur);
684 } while (written < 0 && errno == EINTR);
687 return AT_ERROR_GENERIC;
696 written = write (ac->fd, "\r" , 1);
697 } while ((written < 0 && errno == EINTR) || (written == 0));
700 return AT_ERROR_GENERIC;
706 static int writeCtrlZ (const char *s)
709 size_t len = strlen(s);
712 struct atcontext *ac = getAtContext();
714 if (ac->fd < 0 || ac->readerClosed > 0)
715 return AT_ERROR_CHANNEL_CLOSED;
717 ALOGD("AT> %s^Z\n", s);
719 AT_DUMP( ">* ", s, strlen(s) );
721 /* The main string. */
724 written = write (ac->fd, s + cur, len - cur);
725 } while (written < 0 && errno == EINTR);
728 return AT_ERROR_GENERIC;
735 written = write (ac->fd, "\032" , 1);
736 } while ((written < 0 && errno == EINTR) || (written == 0));
739 return AT_ERROR_GENERIC;
744 static void clearPendingCommand(void)
746 struct atcontext *ac = getAtContext();
748 if (ac->response != NULL)
749 at_response_free(ac->response);
752 ac->responsePrefix = NULL;
756 static AT_Error merror(int type, int error)
760 return (AT_Error)(AT_ERROR_BASE + error);
762 return (AT_Error)(CME_ERROR_BASE + error);
764 return (AT_Error)(CMS_ERROR_BASE + error);
766 return (AT_Error)(GENERIC_ERROR_BASE + error);
768 return (AT_Error)(GENERIC_ERROR_UNSPECIFIED);
772 static AT_Error at_get_error(const ATResponse *p_response)
778 if (p_response == NULL)
779 return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);
781 if (p_response->success > 0)
784 if (p_response->finalResponse == NULL)
785 return AT_ERROR_INVALID_RESPONSE;
787 if (isFinalResponseSuccess(p_response->finalResponse))
790 p_cur = p_response->finalResponse;
791 err = at_tok_start(&p_cur);
793 return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);
795 err = at_tok_nextint(&p_cur, &ret);
797 return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);
799 if(strStartsWith(p_response->finalResponse, "+CME ERROR:"))
800 return merror(CME_ERROR, ret);
801 else if (strStartsWith(p_response->finalResponse, "+CMS ERROR:"))
802 return merror(CMS_ERROR, ret);
803 else if (strStartsWith(p_response->finalResponse, "ERROR:"))
804 return merror(GENERIC_ERROR, GENERIC_ERROR_RESPONSE);
805 else if (strStartsWith(p_response->finalResponse, "+NO CARRIER:"))
806 return merror(GENERIC_ERROR, GENERIC_NO_CARRIER_RESPONSE);
807 else if (strStartsWith(p_response->finalResponse, "+NO ANSWER:"))
808 return merror(GENERIC_ERROR, GENERIC_NO_ANSWER_RESPONSE);
809 else if (strStartsWith(p_response->finalResponse, "+NO DIALTONE:"))
810 return merror(GENERIC_ERROR, GENERIC_NO_DIALTONE_RESPONSE);
812 return merror(GENERIC_ERROR, GENERIC_ERROR_UNSPECIFIED);
816 * Starts AT handler on stream "fd'.
817 * returns 0 on success, -1 on error.
819 int at_open(int fd, ATUnsolHandler h)
824 struct atcontext *ac = NULL;
826 if (initializeAtContext()) {
827 ALOGE("%s() InitializeAtContext failed!", __func__);
834 ac->isInitialized = 1;
835 ac->unsolHandler = h;
836 ac->readerClosed = 0;
838 ac->responsePrefix = NULL;
842 pthread_attr_init (&attr);
843 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
845 ret = pthread_create(&ac->tid_reader, &attr, readerLoop, ac);
848 perror ("pthread_create");
859 /* FIXME is it ok to call this from the reader and the command thread? */
862 struct atcontext *ac = getAtContext();
865 if (close(ac->fd) != 0)
866 ALOGE("%s() FAILED to close fd %d!", __func__, ac->fd);
870 pthread_mutex_lock(&ac->commandmutex);
872 ac->readerClosed = 1;
874 pthread_cond_signal(&ac->commandcond);
876 pthread_mutex_unlock(&ac->commandmutex);
878 /* Kick readerloop. */
879 write(ac->readerCmdFds[1], "x", 1);
882 static ATResponse *at_response_new(void)
884 return (ATResponse *) calloc(1, sizeof(ATResponse));
887 void at_response_free(ATResponse *p_response)
891 if (p_response == NULL) return;
893 p_line = p_response->p_intermediates;
895 while (p_line != NULL) {
899 p_line = p_line->p_next;
901 free(p_toFree->line);
905 free (p_response->finalResponse);
910 * The line reader places the intermediate responses in reverse order,
911 * here we flip them back.
913 static void reverseIntermediates(ATResponse *p_response)
917 pcur = p_response->p_intermediates;
918 p_response->p_intermediates = NULL;
920 while (pcur != NULL) {
921 pnext = pcur->p_next;
922 pcur->p_next = p_response->p_intermediates;
923 p_response->p_intermediates = pcur;
929 * Internal send_command implementation.
930 * Doesn't lock or call the timeout callback.
932 * timeoutMsec == 0 means infinite timeout.
934 static int at_send_command_full_nolock (const char *command, ATCommandType type,
935 const char *responsePrefix, const char *smspdu,
936 long long timeoutMsec, ATResponse **pp_outResponse)
938 int err = AT_NOERROR;
940 struct atcontext *ac = getAtContext();
942 /* Default to NULL, to allow caller to free securely even if
943 * no response will be set below */
944 if (pp_outResponse != NULL)
945 *pp_outResponse = NULL;
947 /* FIXME This is to prevent future problems due to calls from other threads; should be revised. */
948 while (pthread_mutex_trylock(&ac->requestmutex) == EBUSY)
949 pthread_cond_wait(&ac->requestcond, &ac->commandmutex);
951 if(ac->response != NULL) {
952 err = AT_ERROR_COMMAND_PENDING;
957 ac->responsePrefix = responsePrefix;
959 ac->response = at_response_new();
960 if (ac->response == NULL) {
961 err = AT_ERROR_MEMORY_ALLOCATION;
965 err = writeline (command);
967 if (err != AT_NOERROR)
970 while (ac->response->finalResponse == NULL && ac->readerClosed == 0) {
971 if (timeoutMsec != 0)
972 err = pthread_cond_timeout_np(&ac->commandcond, &ac->commandmutex, timeoutMsec);
974 err = pthread_cond_wait(&ac->commandcond, &ac->commandmutex);
976 if (err == ETIMEDOUT) {
977 err = AT_ERROR_TIMEOUT;
982 if (ac->response->success == 0) {
983 err = at_get_error(ac->response);
986 if (pp_outResponse == NULL)
987 at_response_free(ac->response);
989 /* Line reader stores intermediate responses in reverse order. */
990 reverseIntermediates(ac->response);
991 *pp_outResponse = ac->response;
996 if(ac->readerClosed > 0) {
997 err = AT_ERROR_CHANNEL_CLOSED;
1002 clearPendingCommand();
1004 pthread_cond_broadcast(&ac->requestcond);
1005 pthread_mutex_unlock(&ac->requestmutex);
1011 * Internal send_command implementation.
1013 * timeoutMsec == 0 means infinite timeout.
1015 static int at_send_command_full (const char *command, ATCommandType type,
1016 const char *responsePrefix, const char *smspdu,
1017 long long timeoutMsec, ATResponse **pp_outResponse, int useap, va_list ap)
1021 struct atcontext *ac = getAtContext();
1022 static char strbuf[BUFFSIZE];
1025 if (0 != pthread_equal(ac->tid_reader, pthread_self()))
1026 /* Cannot be called from reader thread. */
1027 return AT_ERROR_INVALID_THREAD;
1029 pthread_mutex_lock(&ac->commandmutex);
1031 if (!vsnprintf(strbuf, BUFFSIZE, command, ap)) {
1032 pthread_mutex_unlock(&ac->commandmutex);
1033 return AT_ERROR_STRING_CREATION;
1039 err = at_send_command_full_nolock(ptr, type,
1040 responsePrefix, smspdu,
1041 timeoutMsec, pp_outResponse);
1043 pthread_mutex_unlock(&ac->commandmutex);
1045 if (err == AT_ERROR_TIMEOUT && ac->onTimeout != NULL)
1051 /* Only call this from onTimeout, since we're not locking or anything. */
1052 void at_send_escape (void)
1054 struct atcontext *ac = getAtContext();
1058 written = write (ac->fd, "\033" , 1);
1059 while ((written < 0 && errno == EINTR) || (written == 0));
1063 * Issue a single normal AT command with no intermediate response expected.
1065 * "command" should not include \r.
1067 int at_send_command (const char *command, ...)
1071 struct atcontext *ac = getAtContext();
1073 va_start(ap, command);
1075 err = at_send_command_full (command, NO_RESULT, NULL,
1076 NULL, ac->timeoutMsec, NULL, 1, ap);
1079 if (err != AT_NOERROR)
1080 ALOGI(" --- %s", at_str_err(-err));
1085 int at_send_command_raw (const char *command, ATResponse **pp_outResponse)
1087 struct atcontext *ac = getAtContext();
1090 err = at_send_command_full (command, MULTILINE, "",
1091 NULL, ac->timeoutMsec, pp_outResponse, 0, empty);
1093 /* Don't check for intermediate responses as it is unknown if any
1094 * intermediate responses are expected. Don't free the response, instead,
1095 * let calling function free the allocated response.
1098 if (err != AT_NOERROR)
1099 ALOGI(" --- %s", at_str_err(-err));
1104 int at_send_command_singleline (const char *command,
1105 const char *responsePrefix,
1106 ATResponse **pp_outResponse, ...)
1110 struct atcontext *ac = getAtContext();
1112 va_start(ap, pp_outResponse);
1114 err = at_send_command_full (command, SINGLELINE, responsePrefix,
1115 NULL, ac->timeoutMsec, pp_outResponse, 1, ap);
1117 if (err == AT_NOERROR && pp_outResponse != NULL
1118 && (*pp_outResponse) != NULL
1119 && (*pp_outResponse)->p_intermediates == NULL)
1120 /* Command with pp_outResponse must have an intermediate response */
1121 err = AT_ERROR_INVALID_RESPONSE;
1123 /* Free response in case of error */
1124 if (err != AT_NOERROR && pp_outResponse != NULL
1125 && (*pp_outResponse) != NULL) {
1126 at_response_free(*pp_outResponse);
1127 *pp_outResponse = NULL;
1132 if (err != AT_NOERROR)
1133 ALOGI(" --- %s", at_str_err(-err));
1138 int at_send_command_numeric (const char *command,
1139 ATResponse **pp_outResponse)
1143 struct atcontext *ac = getAtContext();
1145 err = at_send_command_full (command, NUMERIC, NULL,
1146 NULL, ac->timeoutMsec, pp_outResponse, 0, empty);
1148 if (err == AT_NOERROR && pp_outResponse != NULL
1149 && (*pp_outResponse) != NULL
1150 && (*pp_outResponse)->p_intermediates == NULL)
1151 /* Command with pp_outResponse must have an intermediate response */
1152 err = AT_ERROR_INVALID_RESPONSE;
1154 /* Free response in case of error */
1155 if (err != AT_NOERROR && pp_outResponse != NULL
1156 && (*pp_outResponse) != NULL) {
1157 at_response_free(*pp_outResponse);
1158 *pp_outResponse = NULL;
1161 if (err != AT_NOERROR)
1162 ALOGI(" --- %s", at_str_err(-err));
1168 int at_send_command_sms (const char *command,
1170 const char *responsePrefix,
1171 ATResponse **pp_outResponse)
1175 struct atcontext *ac = getAtContext();
1177 err = at_send_command_full (command, SINGLELINE, responsePrefix,
1178 pdu, ac->timeoutMsec, pp_outResponse, 0, empty);
1180 if (err == AT_NOERROR && pp_outResponse != NULL
1181 && (*pp_outResponse) != NULL
1182 && (*pp_outResponse)->p_intermediates == NULL)
1183 /* Command with pp_outResponse must have an intermediate response */
1184 err = AT_ERROR_INVALID_RESPONSE;
1186 /* Free response in case of error */
1187 if (err != AT_NOERROR && pp_outResponse != NULL
1188 && (*pp_outResponse) != NULL) {
1189 at_response_free(*pp_outResponse);
1190 *pp_outResponse = NULL;
1193 if (err != AT_NOERROR)
1194 ALOGI(" --- %s", at_str_err(-err));
1200 int at_send_command_multiline (const char *command,
1201 const char *responsePrefix,
1202 ATResponse **pp_outResponse, ...)
1206 struct atcontext *ac = getAtContext();
1208 va_start(ap, pp_outResponse);
1210 err = at_send_command_full (command, MULTILINE, responsePrefix,
1211 NULL, ac->timeoutMsec, pp_outResponse, 1, ap);
1214 /* Free response in case of error */
1215 if (err != AT_NOERROR && pp_outResponse != NULL
1216 && (*pp_outResponse) != NULL) {
1217 at_response_free(*pp_outResponse);
1218 *pp_outResponse = NULL;
1221 if (err != AT_NOERROR)
1222 ALOGI(" --- %s", at_str_err(-err));
1228 * Set the default timeout. Let it be reasonably high, some commands
1229 * take their time. Default is 10 minutes.
1231 void at_set_timeout_msec(int timeout)
1233 struct atcontext *ac = getAtContext();
1235 ac->timeoutMsec = timeout;
1238 /** This callback is invoked on the command thread. */
1239 void at_set_on_timeout(void (*onTimeout)(void))
1241 struct atcontext *ac = getAtContext();
1243 ac->onTimeout = onTimeout;
1248 * This callback is invoked on the reader thread (like ATUnsolHandler), when the
1249 * input stream closes before you call at_close (not when you call at_close()).
1250 * You should still call at_close(). It may also be invoked immediately from the
1251 * current thread if the read channel is already closed.
1253 void at_set_on_reader_closed(void (*onClose)(void))
1255 struct atcontext *ac = getAtContext();
1257 ac->onReaderClosed = onClose;
1262 * Periodically issue an AT command and wait for a response.
1263 * Used to ensure channel has start up and is active.
1265 int at_handshake(void)
1270 struct atcontext *ac = getAtContext();
1272 if (0 != pthread_equal(ac->tid_reader, pthread_self()))
1273 /* Cannot be called from reader thread. */
1274 return AT_ERROR_INVALID_THREAD;
1276 pthread_mutex_lock(&ac->commandmutex);
1278 for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
1279 /* Some stacks start with verbose off. */
1280 err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
1281 NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
1288 /* Pause for a bit to let the input buffer drain any unmatched OK's
1289 (they will appear as extraneous unsolicited responses). */
1290 ALOGD("%s() pausing %d ms to drain unmatched OK's...",
1291 __func__, HANDSHAKE_TIMEOUT_MSEC);
1292 sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
1295 pthread_mutex_unlock(&ac->commandmutex);
1300 AT_Error at_get_at_error(int error)
1303 if (error >= AT_ERROR_BASE && error < AT_ERROR_TOP)
1304 return (AT_Error)(error - AT_ERROR_BASE);
1306 return AT_ERROR_NON_AT;
1309 AT_CME_Error at_get_cme_error(int error)
1312 if (error >= CME_ERROR_BASE && error < CME_ERROR_TOP)
1313 return (AT_CME_Error)(error - CME_ERROR_BASE);
1315 return CME_ERROR_NON_CME;
1318 AT_CMS_Error at_get_cms_error(int error)
1321 if (error >= CMS_ERROR_BASE && error < CMS_ERROR_TOP)
1322 return (AT_CMS_Error)(error - CMS_ERROR_BASE);
1324 return CMS_ERROR_NON_CMS;
1327 AT_Generic_Error at_get_generic_error(int error)
1330 if (error >= GENERIC_ERROR_BASE && error < GENERIC_ERROR_TOP)
1331 return (AT_Generic_Error)(error - GENERIC_ERROR_BASE);
1333 return GENERIC_ERROR_NON_GENERIC;
1336 AT_Error_type at_get_error_type(int error)
1339 if (error == AT_NOERROR)
1342 if (error > AT_ERROR_BASE && error <= AT_ERROR_TOP)
1345 if (error >= CME_ERROR_BASE && error <= CME_ERROR_TOP)
1348 if (error >= CMS_ERROR_BASE && error <= CMS_ERROR_TOP)
1351 if (error >= GENERIC_ERROR_BASE && error <= GENERIC_ERROR_TOP)
1352 return GENERIC_ERROR;
1354 return UNKNOWN_ERROR;
1359 const char *at_str_err(int error)
1361 const char *s = "--UNKNOWN--";
1365 #define AT(name, num) case num + AT_ERROR_BASE: s = quote(AT_##name); break;
1366 #define CME(name, num) case num + CME_ERROR_BASE: s = quote(CME_##name); break;
1367 #define CMS(name, num) case num + CMS_ERROR_BASE: s = quote(CMS_##name); break;
1368 #define GENERIC(name, num) case num + GENERIC_ERROR_BASE: s = quote(GENERIC_##name); break;