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 * for current pending command
65 * these are protected by s_commandmutex
68 static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
69 static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
71 static ATCommandType s_type;
72 static const char *s_responsePrefix = NULL;
73 static const char *s_smsPDU = NULL;
74 static ATResponse *sp_response = NULL;
76 static void (*s_onTimeout)(void) = NULL;
77 static void (*s_onReaderClosed)(void) = NULL;
78 static int s_readerClosed;
80 static void onReaderClosed();
81 static int writeCtrlZ (const char *s);
82 static int writeline (const char *s);
84 #define NS_PER_S 1000000000
85 static void setTimespecRelative(struct timespec *p_ts, long long msec)
89 gettimeofday(&tv, (struct timezone *) NULL);
91 p_ts->tv_sec = tv.tv_sec + (msec / 1000);
92 p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
93 /* assuming tv.tv_usec < 10^6 */
94 if (p_ts->tv_nsec >= NS_PER_S) {
96 p_ts->tv_nsec -= NS_PER_S;
100 static void sleepMsec(long long msec)
105 ts.tv_sec = (msec / 1000);
106 ts.tv_nsec = (msec % 1000) * 1000 * 1000;
109 err = nanosleep (&ts, &ts);
110 } while (err < 0 && errno == EINTR);
115 /** add an intermediate response to sp_response*/
116 static void addIntermediate(const char *line)
120 p_new = (ATLine *) malloc(sizeof(ATLine));
122 p_new->line = strdup(line);
124 /* note: this adds to the head of the list, so the list
125 will be in reverse order of lines received. the order is flipped
126 again before passing on to the command issuer */
127 p_new->p_next = sp_response->p_intermediates;
128 sp_response->p_intermediates = p_new;
133 * returns 1 if line is a final response indicating error
135 * WARNING: NO CARRIER and others are sometimes unsolicited
137 static const char * s_finalResponsesError[] = {
141 "NO CARRIER", /* sometimes! */
145 static int isFinalResponseError(const char *line)
149 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) {
150 if (strStartsWith(line, s_finalResponsesError[i])) {
159 * returns 1 if line is a final response indicating success
161 * WARNING: NO CARRIER and others are sometimes unsolicited
163 static const char * s_finalResponsesSuccess[] = {
165 "CONNECT" /* some stacks start up data on another channel */
167 static int isFinalResponseSuccess(const char *line)
171 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) {
172 if (strStartsWith(line, s_finalResponsesSuccess[i])) {
181 * returns 1 if line is a final response, either error or success
183 * WARNING: NO CARRIER and others are sometimes unsolicited
185 static int isFinalResponse(const char *line)
187 return isFinalResponseSuccess(line) || isFinalResponseError(line);
192 * returns 1 if line is the first line in (what will be) a two-line
193 * SMS unsolicited response
195 static const char * s_smsUnsoliciteds[] = {
200 static int isSMSUnsolicited(const char *line)
204 for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
205 if (strStartsWith(line, s_smsUnsoliciteds[i])) {
214 /** assumes s_commandmutex is held */
215 static void handleFinalResponse(const char *line)
217 sp_response->finalResponse = strdup(line);
219 pthread_cond_signal(&s_commandcond);
222 static void handleUnsolicited(const char *line)
224 if (s_unsolHandler != NULL) {
225 s_unsolHandler(line, NULL);
229 static void processLine(const char *line)
231 pthread_mutex_lock(&s_commandmutex);
233 if (sp_response == NULL) {
234 /* no command pending */
235 handleUnsolicited(line);
236 } else if (isFinalResponseSuccess(line)) {
237 sp_response->success = 1;
238 handleFinalResponse(line);
239 } else if (isFinalResponseError(line)) {
240 sp_response->success = 0;
241 handleFinalResponse(line);
242 } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
243 // See eg. TS 27.005 4.3
244 // Commands like AT+CMGS have a "> " prompt
245 writeCtrlZ(s_smsPDU);
247 } else switch (s_type) {
249 handleUnsolicited(line);
252 if (sp_response->p_intermediates == NULL
255 addIntermediate(line);
257 /* either we already have an intermediate response or
258 the line doesn't begin with a digit */
259 handleUnsolicited(line);
263 if (sp_response->p_intermediates == NULL
264 && strStartsWith (line, s_responsePrefix)
266 addIntermediate(line);
268 /* we already have an intermediate response */
269 handleUnsolicited(line);
273 if (strStartsWith (line, s_responsePrefix)) {
274 addIntermediate(line);
276 handleUnsolicited(line);
280 default: /* this should never be reached */
281 RLOGE("Unsupported AT command type %d\n", s_type);
282 handleUnsolicited(line);
286 pthread_mutex_unlock(&s_commandmutex);
291 * Returns a pointer to the end of the next line
292 * special-cases the "> " SMS prompt
294 * returns NULL if there is no complete line
296 static char * findNextEOL(char *cur)
298 if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
299 /* SMS prompt character...not \r terminated */
304 while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
306 return *cur == '\0' ? NULL : cur;
311 * Reads a line from the AT channel, returns NULL on timeout.
312 * Assumes it has exclusive read access to the FD
314 * This line is valid only until the next call to readline
316 * This function exists because as of writing, android libc does not
317 * have buffered stdio.
320 static const char *readline()
328 /* this is a little odd. I use *s_ATBufferCur == 0 to
329 * mean "buffer consumed completely". If it points to a character, than
330 * the buffer continues until a \0
332 if (*s_ATBufferCur == '\0') {
334 s_ATBufferCur = s_ATBuffer;
335 *s_ATBufferCur = '\0';
337 } else { /* *s_ATBufferCur != '\0' */
338 /* there's data in the buffer from the last read */
340 // skip over leading newlines
341 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
344 p_eol = findNextEOL(s_ATBufferCur);
347 /* a partial line. move it up and prepare to read more */
350 len = strlen(s_ATBufferCur);
352 memmove(s_ATBuffer, s_ATBufferCur, len + 1);
353 p_read = s_ATBuffer + len;
354 s_ATBufferCur = s_ATBuffer;
356 /* Otherwise, (p_eol !- NULL) there is a complete line */
357 /* that will be returned the while () loop below */
360 while (p_eol == NULL) {
361 if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
362 RLOGE("ERROR: Input line exceeded buffer\n");
363 /* ditch buffer and start over again */
364 s_ATBufferCur = s_ATBuffer;
365 *s_ATBufferCur = '\0';
370 count = read(s_fd, p_read,
371 MAX_AT_RESPONSE - (p_read - s_ATBuffer));
372 } while (count < 0 && errno == EINTR);
375 AT_DUMP( "<< ", p_read, count );
377 p_read[count] = '\0';
379 // skip over leading newlines
380 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
383 p_eol = findNextEOL(s_ATBufferCur);
385 } else if (count <= 0) {
386 /* read error encountered or EOF reached */
388 RLOGD("atchannel: EOF reached");
390 RLOGD("atchannel: read error %s", strerror(errno));
396 /* a full line in the buffer. Place a \0 over the \r and return */
400 s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */
401 /* and there will be a \0 at *p_read */
403 RLOGD("AT< %s\n", ret);
408 static void onReaderClosed()
410 if (s_onReaderClosed != NULL && s_readerClosed == 0) {
412 pthread_mutex_lock(&s_commandmutex);
416 pthread_cond_signal(&s_commandcond);
418 pthread_mutex_unlock(&s_commandmutex);
425 static void *readerLoop(void *arg)
436 if(isSMSUnsolicited(line)) {
440 // The scope of string returned by 'readline()' is valid only
441 // till next call to 'readline()' hence making a copy of line
442 // before calling readline again.
443 line1 = strdup(line);
451 if (s_unsolHandler != NULL) {
452 s_unsolHandler (line1, line2);
466 * Sends string s to the radio with a \r appended.
467 * Returns AT_ERROR_* on error, 0 on success
469 * This function exists because as of writing, android libc does not
470 * have buffered stdio.
472 static int writeline (const char *s)
475 size_t len = strlen(s);
478 if (s_fd < 0 || s_readerClosed > 0) {
479 return AT_ERROR_CHANNEL_CLOSED;
482 RLOGD("AT> %s\n", s);
484 AT_DUMP( ">> ", s, strlen(s) );
486 /* the main string */
489 written = write (s_fd, s + cur, len - cur);
490 } while (written < 0 && errno == EINTR);
493 return AT_ERROR_GENERIC;
502 written = write (s_fd, "\r" , 1);
503 } while ((written < 0 && errno == EINTR) || (written == 0));
506 return AT_ERROR_GENERIC;
511 static int writeCtrlZ (const char *s)
514 size_t len = strlen(s);
517 if (s_fd < 0 || s_readerClosed > 0) {
518 return AT_ERROR_CHANNEL_CLOSED;
521 RLOGD("AT> %s^Z\n", s);
523 AT_DUMP( ">* ", s, strlen(s) );
525 /* the main string */
528 written = write (s_fd, s + cur, len - cur);
529 } while (written < 0 && errno == EINTR);
532 return AT_ERROR_GENERIC;
541 written = write (s_fd, "\032" , 1);
542 } while ((written < 0 && errno == EINTR) || (written == 0));
545 return AT_ERROR_GENERIC;
551 static void clearPendingCommand()
553 if (sp_response != NULL) {
554 at_response_free(sp_response);
558 s_responsePrefix = NULL;
564 * Starts AT handler on stream "fd'
565 * returns 0 on success, -1 on error
567 int at_open(int fd, ATUnsolHandler h)
577 s_responsePrefix = NULL;
581 pthread_attr_init (&attr);
582 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
584 ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
587 perror ("pthread_create");
595 /* FIXME is it ok to call this from the reader and the command thread? */
603 pthread_mutex_lock(&s_commandmutex);
607 pthread_cond_signal(&s_commandcond);
609 pthread_mutex_unlock(&s_commandmutex);
611 /* the reader thread should eventually die */
614 static ATResponse * at_response_new()
616 return (ATResponse *) calloc(1, sizeof(ATResponse));
619 void at_response_free(ATResponse *p_response)
623 if (p_response == NULL) return;
625 p_line = p_response->p_intermediates;
627 while (p_line != NULL) {
631 p_line = p_line->p_next;
633 free(p_toFree->line);
637 free (p_response->finalResponse);
642 * The line reader places the intermediate responses in reverse order
643 * here we flip them back
645 static void reverseIntermediates(ATResponse *p_response)
649 pcur = p_response->p_intermediates;
650 p_response->p_intermediates = NULL;
652 while (pcur != NULL) {
653 pnext = pcur->p_next;
654 pcur->p_next = p_response->p_intermediates;
655 p_response->p_intermediates = pcur;
661 * Internal send_command implementation
662 * Doesn't lock or call the timeout callback
664 * timeoutMsec == 0 means infinite timeout
667 static int at_send_command_full_nolock (const char *command, ATCommandType type,
668 const char *responsePrefix, const char *smspdu,
669 long long timeoutMsec, ATResponse **pp_outResponse)
674 if(sp_response != NULL) {
675 err = AT_ERROR_COMMAND_PENDING;
679 err = writeline (command);
686 s_responsePrefix = responsePrefix;
688 sp_response = at_response_new();
690 if (timeoutMsec != 0) {
691 setTimespecRelative(&ts, timeoutMsec);
694 while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
695 if (timeoutMsec != 0) {
696 err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
698 err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
701 if (err == ETIMEDOUT) {
702 err = AT_ERROR_TIMEOUT;
707 if (pp_outResponse == NULL) {
708 at_response_free(sp_response);
710 /* line reader stores intermediate responses in reverse order */
711 reverseIntermediates(sp_response);
712 *pp_outResponse = sp_response;
717 if(s_readerClosed > 0) {
718 err = AT_ERROR_CHANNEL_CLOSED;
724 clearPendingCommand();
730 * Internal send_command implementation
732 * timeoutMsec == 0 means infinite timeout
734 static int at_send_command_full (const char *command, ATCommandType type,
735 const char *responsePrefix, const char *smspdu,
736 long long timeoutMsec, ATResponse **pp_outResponse)
740 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
741 /* cannot be called from reader thread */
742 return AT_ERROR_INVALID_THREAD;
745 pthread_mutex_lock(&s_commandmutex);
747 err = at_send_command_full_nolock(command, type,
748 responsePrefix, smspdu,
749 timeoutMsec, pp_outResponse);
751 pthread_mutex_unlock(&s_commandmutex);
753 if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
762 * Issue a single normal AT command with no intermediate response expected
764 * "command" should not include \r
765 * pp_outResponse can be NULL
767 * if non-NULL, the resulting ATResponse * must be eventually freed with
770 int at_send_command (const char *command, ATResponse **pp_outResponse)
774 err = at_send_command_full (command, NO_RESULT, NULL,
775 NULL, 0, pp_outResponse);
781 int at_send_command_singleline (const char *command,
782 const char *responsePrefix,
783 ATResponse **pp_outResponse)
787 err = at_send_command_full (command, SINGLELINE, responsePrefix,
788 NULL, 0, pp_outResponse);
790 if (err == 0 && pp_outResponse != NULL
791 && (*pp_outResponse)->success > 0
792 && (*pp_outResponse)->p_intermediates == NULL
794 /* successful command must have an intermediate response */
795 at_response_free(*pp_outResponse);
796 *pp_outResponse = NULL;
797 return AT_ERROR_INVALID_RESPONSE;
804 int at_send_command_numeric (const char *command,
805 ATResponse **pp_outResponse)
809 err = at_send_command_full (command, NUMERIC, NULL,
810 NULL, 0, pp_outResponse);
812 if (err == 0 && pp_outResponse != NULL
813 && (*pp_outResponse)->success > 0
814 && (*pp_outResponse)->p_intermediates == NULL
816 /* successful command must have an intermediate response */
817 at_response_free(*pp_outResponse);
818 *pp_outResponse = NULL;
819 return AT_ERROR_INVALID_RESPONSE;
826 int at_send_command_sms (const char *command,
828 const char *responsePrefix,
829 ATResponse **pp_outResponse)
833 err = at_send_command_full (command, SINGLELINE, responsePrefix,
834 pdu, 0, pp_outResponse);
836 if (err == 0 && pp_outResponse != NULL
837 && (*pp_outResponse)->success > 0
838 && (*pp_outResponse)->p_intermediates == NULL
840 /* successful command must have an intermediate response */
841 at_response_free(*pp_outResponse);
842 *pp_outResponse = NULL;
843 return AT_ERROR_INVALID_RESPONSE;
850 int at_send_command_multiline (const char *command,
851 const char *responsePrefix,
852 ATResponse **pp_outResponse)
856 err = at_send_command_full (command, MULTILINE, responsePrefix,
857 NULL, 0, pp_outResponse);
863 /** This callback is invoked on the command thread */
864 void at_set_on_timeout(void (*onTimeout)(void))
866 s_onTimeout = onTimeout;
870 * This callback is invoked on the reader thread (like ATUnsolHandler)
871 * when the input stream closes before you call at_close
872 * (not when you call at_close())
873 * You should still call at_close()
876 void at_set_on_reader_closed(void (*onClose)(void))
878 s_onReaderClosed = onClose;
883 * Periodically issue an AT command and wait for a response.
884 * Used to ensure channel has start up and is active
892 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
893 /* cannot be called from reader thread */
894 return AT_ERROR_INVALID_THREAD;
897 pthread_mutex_lock(&s_commandmutex);
899 for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
900 /* some stacks start with verbose off */
901 err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
902 NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
910 /* pause for a bit to let the input buffer drain any unmatched OK's
911 (they will appear as extraneous unsolicited responses) */
913 sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
916 pthread_mutex_unlock(&s_commandmutex);
922 * Returns error code from response
923 * Assumes AT+CMEE=1 (numeric) mode
925 AT_CME_Error at_get_cme_error(const ATResponse *p_response)
931 if (p_response->success > 0) {
935 if (p_response->finalResponse == NULL
936 || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
938 return CME_ERROR_NON_CME;
941 p_cur = p_response->finalResponse;
942 err = at_tok_start(&p_cur);
945 return CME_ERROR_NON_CME;
948 err = at_tok_nextint(&p_cur, &ret);
951 return CME_ERROR_NON_CME;
954 return (AT_CME_Error) ret;