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"
34 #include <utils/Log.h>
39 #define NUM_ELEMS(x) (sizeof(x)/sizeof((x)[0]))
41 #define MAX_AT_RESPONSE (8 * 1024)
42 #define HANDSHAKE_RETRY_COUNT 8
43 #define HANDSHAKE_TIMEOUT_MSEC 250
45 static pthread_t s_tid_reader;
46 static int s_fd = -1; /* fd of the AT channel */
47 static ATUnsolHandler s_unsolHandler;
49 /* for input buffering */
51 static char s_ATBuffer[MAX_AT_RESPONSE+1];
52 static char *s_ATBufferCur = s_ATBuffer;
55 void AT_DUMP(const char* prefix, const char* buff, int len)
59 RLOGD("%.*s", len, buff);
64 * There is one reader thread |s_tid_reader| and potentially multiple writer
65 * threads. |s_commandmutex| and |s_commandcond| are used to maintain the
66 * condition that the writer thread will not read from |sp_response| until the
67 * reader thread has signaled itself is finished, etc. |s_writeMutex| is used to
68 * prevent multiple writer threads from calling at_send_command_full_nolock
69 * function at the same time.
72 static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
73 static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
74 static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;
76 static ATCommandType s_type;
77 static const char *s_responsePrefix = NULL;
78 static const char *s_smsPDU = NULL;
79 static ATResponse *sp_response = NULL;
81 static void (*s_onTimeout)(void) = NULL;
82 static void (*s_onReaderClosed)(void) = NULL;
83 static int s_readerClosed;
85 static void onReaderClosed();
86 static int writeCtrlZ (const char *s);
87 static int writeline (const char *s);
89 #define NS_PER_S 1000000000
90 static void setTimespecRelative(struct timespec *p_ts, long long msec)
94 gettimeofday(&tv, (struct timezone *) NULL);
96 p_ts->tv_sec = tv.tv_sec + (msec / 1000);
97 p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
98 /* assuming tv.tv_usec < 10^6 */
99 if (p_ts->tv_nsec >= NS_PER_S) {
101 p_ts->tv_nsec -= NS_PER_S;
105 static void sleepMsec(long long msec)
110 ts.tv_sec = (msec / 1000);
111 ts.tv_nsec = (msec % 1000) * 1000 * 1000;
114 err = nanosleep (&ts, &ts);
115 } while (err < 0 && errno == EINTR);
120 /** add an intermediate response to sp_response*/
121 static void addIntermediate(const char *line)
125 p_new = (ATLine *) malloc(sizeof(ATLine));
127 p_new->line = strdup(line);
129 /* note: this adds to the head of the list, so the list
130 will be in reverse order of lines received. the order is flipped
131 again before passing on to the command issuer */
132 p_new->p_next = sp_response->p_intermediates;
133 sp_response->p_intermediates = p_new;
138 * returns 1 if line is a final response indicating error
140 * WARNING: NO CARRIER and others are sometimes unsolicited
142 static const char * s_finalResponsesError[] = {
146 "NO CARRIER", /* sometimes! */
150 static int isFinalResponseError(const char *line)
154 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) {
155 if (strStartsWith(line, s_finalResponsesError[i])) {
164 * returns 1 if line is a final response indicating success
166 * WARNING: NO CARRIER and others are sometimes unsolicited
168 static const char * s_finalResponsesSuccess[] = {
170 "CONNECT" /* some stacks start up data on another channel */
172 static int isFinalResponseSuccess(const char *line)
176 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) {
177 if (strStartsWith(line, s_finalResponsesSuccess[i])) {
186 * returns 1 if line is a final response, either error or success
188 * WARNING: NO CARRIER and others are sometimes unsolicited
190 static int isFinalResponse(const char *line)
192 return isFinalResponseSuccess(line) || isFinalResponseError(line);
197 * returns 1 if line is the first line in (what will be) a two-line
198 * SMS unsolicited response
200 static const char * s_smsUnsoliciteds[] = {
205 static int isSMSUnsolicited(const char *line)
209 for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
210 if (strStartsWith(line, s_smsUnsoliciteds[i])) {
219 /** assumes s_commandmutex is held */
220 static void handleFinalResponse(const char *line)
222 sp_response->finalResponse = strdup(line);
224 pthread_cond_signal(&s_commandcond);
227 static void handleUnsolicited(const char *line)
229 if (s_unsolHandler != NULL) {
230 s_unsolHandler(line, NULL);
234 static void processLine(const char *line)
236 pthread_mutex_lock(&s_commandmutex);
238 if (sp_response == NULL) {
239 /* no command pending */
240 handleUnsolicited(line);
241 } else if (isFinalResponseSuccess(line)) {
242 sp_response->success = 1;
243 handleFinalResponse(line);
244 } else if (isFinalResponseError(line)) {
245 sp_response->success = 0;
246 handleFinalResponse(line);
247 } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
248 // See eg. TS 27.005 4.3
249 // Commands like AT+CMGS have a "> " prompt
250 writeCtrlZ(s_smsPDU);
252 } else switch (s_type) {
254 handleUnsolicited(line);
257 if (sp_response->p_intermediates == NULL
260 addIntermediate(line);
262 /* either we already have an intermediate response or
263 the line doesn't begin with a digit */
264 handleUnsolicited(line);
268 if (sp_response->p_intermediates == NULL
269 && strStartsWith (line, s_responsePrefix)
271 addIntermediate(line);
273 /* we already have an intermediate response */
274 handleUnsolicited(line);
278 if (strStartsWith (line, s_responsePrefix)) {
279 addIntermediate(line);
281 handleUnsolicited(line);
285 default: /* this should never be reached */
286 RLOGE("Unsupported AT command type %d\n", s_type);
287 handleUnsolicited(line);
291 pthread_mutex_unlock(&s_commandmutex);
296 * Returns a pointer to the end of the next line
297 * special-cases the "> " SMS prompt
299 * returns NULL if there is no complete line
301 static char * findNextEOL(char *cur)
303 if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
304 /* SMS prompt character...not \r terminated */
309 while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
311 return *cur == '\0' ? NULL : cur;
316 * Reads a line from the AT channel, returns NULL on timeout.
317 * Assumes it has exclusive read access to the FD
319 * This line is valid only until the next call to readline
321 * This function exists because as of writing, android libc does not
322 * have buffered stdio.
325 static const char *readline()
333 /* this is a little odd. I use *s_ATBufferCur == 0 to
334 * mean "buffer consumed completely". If it points to a character, than
335 * the buffer continues until a \0
337 if (*s_ATBufferCur == '\0') {
339 s_ATBufferCur = s_ATBuffer;
340 *s_ATBufferCur = '\0';
342 } else { /* *s_ATBufferCur != '\0' */
343 /* there's data in the buffer from the last read */
345 // skip over leading newlines
346 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
349 p_eol = findNextEOL(s_ATBufferCur);
352 /* a partial line. move it up and prepare to read more */
355 len = strlen(s_ATBufferCur);
357 memmove(s_ATBuffer, s_ATBufferCur, len + 1);
358 p_read = s_ATBuffer + len;
359 s_ATBufferCur = s_ATBuffer;
361 /* Otherwise, (p_eol !- NULL) there is a complete line */
362 /* that will be returned the while () loop below */
365 while (p_eol == NULL) {
366 if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
367 RLOGE("ERROR: Input line exceeded buffer\n");
368 /* ditch buffer and start over again */
369 s_ATBufferCur = s_ATBuffer;
370 *s_ATBufferCur = '\0';
375 count = read(s_fd, p_read,
376 MAX_AT_RESPONSE - (p_read - s_ATBuffer));
377 } while (count < 0 && errno == EINTR);
380 AT_DUMP( "<< ", p_read, count );
382 p_read[count] = '\0';
384 // skip over leading newlines
385 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
388 p_eol = findNextEOL(s_ATBufferCur);
390 } else if (count <= 0) {
391 /* read error encountered or EOF reached */
393 RLOGD("atchannel: EOF reached");
395 RLOGD("atchannel: read error %s", strerror(errno));
401 /* a full line in the buffer. Place a \0 over the \r and return */
405 s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */
406 /* and there will be a \0 at *p_read */
408 RLOGD("AT< %s\n", ret);
413 static void onReaderClosed()
415 if (s_onReaderClosed != NULL && s_readerClosed == 0) {
417 pthread_mutex_lock(&s_commandmutex);
421 pthread_cond_signal(&s_commandcond);
423 pthread_mutex_unlock(&s_commandmutex);
430 static void *readerLoop(void *arg __unused)
441 if(isSMSUnsolicited(line)) {
445 // The scope of string returned by 'readline()' is valid only
446 // till next call to 'readline()' hence making a copy of line
447 // before calling readline again.
448 line1 = strdup(line);
456 if (s_unsolHandler != NULL) {
457 s_unsolHandler (line1, line2);
471 * Sends string s to the radio with a \r appended.
472 * Returns AT_ERROR_* on error, 0 on success
474 * This function exists because as of writing, android libc does not
475 * have buffered stdio.
477 static int writeline (const char *s)
480 size_t len = strlen(s);
483 if (s_fd < 0 || s_readerClosed > 0) {
484 return AT_ERROR_CHANNEL_CLOSED;
487 RLOGD("AT> %s\n", s);
489 AT_DUMP( ">> ", s, strlen(s) );
491 /* the main string */
494 written = write (s_fd, s + cur, len - cur);
495 } while (written < 0 && errno == EINTR);
498 return AT_ERROR_GENERIC;
507 written = write (s_fd, "\r" , 1);
508 } while ((written < 0 && errno == EINTR) || (written == 0));
511 return AT_ERROR_GENERIC;
516 static int writeCtrlZ (const char *s)
519 size_t len = strlen(s);
522 if (s_fd < 0 || s_readerClosed > 0) {
523 return AT_ERROR_CHANNEL_CLOSED;
526 RLOGD("AT> %s^Z\n", s);
528 AT_DUMP( ">* ", s, strlen(s) );
530 /* the main string */
533 written = write (s_fd, s + cur, len - cur);
534 } while (written < 0 && errno == EINTR);
537 return AT_ERROR_GENERIC;
546 written = write (s_fd, "\032" , 1);
547 } while ((written < 0 && errno == EINTR) || (written == 0));
550 return AT_ERROR_GENERIC;
556 static void clearPendingCommand()
558 if (sp_response != NULL) {
559 at_response_free(sp_response);
563 s_responsePrefix = NULL;
569 * Starts AT handler on stream "fd'
570 * returns 0 on success, -1 on error
572 int at_open(int fd, ATUnsolHandler h)
582 s_responsePrefix = NULL;
586 pthread_attr_init (&attr);
587 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
589 ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
592 perror ("pthread_create");
600 /* FIXME is it ok to call this from the reader and the command thread? */
608 pthread_mutex_lock(&s_commandmutex);
612 pthread_cond_signal(&s_commandcond);
614 pthread_mutex_unlock(&s_commandmutex);
616 /* the reader thread should eventually die */
619 static ATResponse * at_response_new()
621 return (ATResponse *) calloc(1, sizeof(ATResponse));
624 void at_response_free(ATResponse *p_response)
628 if (p_response == NULL) return;
630 p_line = p_response->p_intermediates;
632 while (p_line != NULL) {
636 p_line = p_line->p_next;
638 free(p_toFree->line);
642 free (p_response->finalResponse);
647 * The line reader places the intermediate responses in reverse order
648 * here we flip them back
650 static void reverseIntermediates(ATResponse *p_response)
654 pcur = p_response->p_intermediates;
655 p_response->p_intermediates = NULL;
657 while (pcur != NULL) {
658 pnext = pcur->p_next;
659 pcur->p_next = p_response->p_intermediates;
660 p_response->p_intermediates = pcur;
666 * Internal send_command implementation
667 * Doesn't lock or call the timeout callback
669 * timeoutMsec == 0 means infinite timeout
672 static int at_send_command_full_nolock (const char *command, ATCommandType type,
673 const char *responsePrefix, const char *smspdu,
674 long long timeoutMsec, ATResponse **pp_outResponse)
679 if(sp_response != NULL) {
680 err = AT_ERROR_COMMAND_PENDING;
684 err = writeline (command);
691 s_responsePrefix = responsePrefix;
693 sp_response = at_response_new();
695 if (timeoutMsec != 0) {
696 setTimespecRelative(&ts, timeoutMsec);
699 while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
700 if (timeoutMsec != 0) {
701 err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
703 err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
706 if (err == ETIMEDOUT) {
707 err = AT_ERROR_TIMEOUT;
712 if (pp_outResponse == NULL) {
713 at_response_free(sp_response);
715 /* line reader stores intermediate responses in reverse order */
716 reverseIntermediates(sp_response);
717 *pp_outResponse = sp_response;
722 if(s_readerClosed > 0) {
723 err = AT_ERROR_CHANNEL_CLOSED;
729 clearPendingCommand();
735 * Internal send_command implementation
737 * timeoutMsec == 0 means infinite timeout
739 static int at_send_command_full (const char *command, ATCommandType type,
740 const char *responsePrefix, const char *smspdu,
741 long long timeoutMsec, ATResponse **pp_outResponse)
746 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
747 /* cannot be called from reader thread */
748 return AT_ERROR_INVALID_THREAD;
750 inEmulator = isInEmulator();
752 pthread_mutex_lock(&s_writeMutex);
754 pthread_mutex_lock(&s_commandmutex);
756 err = at_send_command_full_nolock(command, type,
757 responsePrefix, smspdu,
758 timeoutMsec, pp_outResponse);
760 pthread_mutex_unlock(&s_commandmutex);
762 pthread_mutex_unlock(&s_writeMutex);
765 if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
774 * Issue a single normal AT command with no intermediate response expected
776 * "command" should not include \r
777 * pp_outResponse can be NULL
779 * if non-NULL, the resulting ATResponse * must be eventually freed with
782 int at_send_command (const char *command, ATResponse **pp_outResponse)
786 err = at_send_command_full (command, NO_RESULT, NULL,
787 NULL, 0, pp_outResponse);
793 int at_send_command_singleline (const char *command,
794 const char *responsePrefix,
795 ATResponse **pp_outResponse)
799 err = at_send_command_full (command, SINGLELINE, responsePrefix,
800 NULL, 0, pp_outResponse);
802 if (err == 0 && pp_outResponse != NULL
803 && (*pp_outResponse)->success > 0
804 && (*pp_outResponse)->p_intermediates == NULL
806 /* successful command must have an intermediate response */
807 at_response_free(*pp_outResponse);
808 *pp_outResponse = NULL;
809 return AT_ERROR_INVALID_RESPONSE;
816 int at_send_command_numeric (const char *command,
817 ATResponse **pp_outResponse)
821 err = at_send_command_full (command, NUMERIC, NULL,
822 NULL, 0, pp_outResponse);
824 if (err == 0 && pp_outResponse != NULL
825 && (*pp_outResponse)->success > 0
826 && (*pp_outResponse)->p_intermediates == NULL
828 /* successful command must have an intermediate response */
829 at_response_free(*pp_outResponse);
830 *pp_outResponse = NULL;
831 return AT_ERROR_INVALID_RESPONSE;
838 int at_send_command_sms (const char *command,
840 const char *responsePrefix,
841 ATResponse **pp_outResponse)
845 err = at_send_command_full (command, SINGLELINE, responsePrefix,
846 pdu, 0, pp_outResponse);
848 if (err == 0 && pp_outResponse != NULL
849 && (*pp_outResponse)->success > 0
850 && (*pp_outResponse)->p_intermediates == NULL
852 /* successful command must have an intermediate response */
853 at_response_free(*pp_outResponse);
854 *pp_outResponse = NULL;
855 return AT_ERROR_INVALID_RESPONSE;
862 int at_send_command_multiline (const char *command,
863 const char *responsePrefix,
864 ATResponse **pp_outResponse)
868 err = at_send_command_full (command, MULTILINE, responsePrefix,
869 NULL, 0, pp_outResponse);
875 /** This callback is invoked on the command thread */
876 void at_set_on_timeout(void (*onTimeout)(void))
878 s_onTimeout = onTimeout;
882 * This callback is invoked on the reader thread (like ATUnsolHandler)
883 * when the input stream closes before you call at_close
884 * (not when you call at_close())
885 * You should still call at_close()
888 void at_set_on_reader_closed(void (*onClose)(void))
890 s_onReaderClosed = onClose;
895 * Periodically issue an AT command and wait for a response.
896 * Used to ensure channel has start up and is active
905 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
906 /* cannot be called from reader thread */
907 return AT_ERROR_INVALID_THREAD;
909 inEmulator = isInEmulator();
911 pthread_mutex_lock(&s_writeMutex);
913 pthread_mutex_lock(&s_commandmutex);
915 for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
916 /* some stacks start with verbose off */
917 err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
918 NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
926 /* pause for a bit to let the input buffer drain any unmatched OK's
927 (they will appear as extraneous unsolicited responses) */
929 sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
932 pthread_mutex_unlock(&s_commandmutex);
934 pthread_mutex_unlock(&s_writeMutex);
941 * Returns error code from response
942 * Assumes AT+CMEE=1 (numeric) mode
944 AT_CME_Error at_get_cme_error(const ATResponse *p_response)
950 if (p_response->success > 0) {
954 if (p_response->finalResponse == NULL
955 || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
957 return CME_ERROR_NON_CME;
960 p_cur = p_response->finalResponse;
961 err = at_tok_start(&p_cur);
964 return CME_ERROR_NON_CME;
967 err = at_tok_nextint(&p_cur, &ret);
970 return CME_ERROR_NON_CME;
973 return (AT_CME_Error) ret;