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>
36 #ifdef HAVE_ANDROID_OS
38 #include <linux/omap_csmi.h>
39 #endif /*HAVE_ANDROID_OS*/
43 #ifdef HAVE_ANDROID_OS
45 #endif /* HAVE_ANDROID_OS */
48 #define NUM_ELEMS(x) (sizeof(x)/sizeof(x[0]))
50 #define MAX_AT_RESPONSE (8 * 1024)
51 #define HANDSHAKE_RETRY_COUNT 8
52 #define HANDSHAKE_TIMEOUT_MSEC 250
54 static pthread_t s_tid_reader;
55 static int s_fd = -1; /* fd of the AT channel */
56 static ATUnsolHandler s_unsolHandler;
58 /* for input buffering */
60 static char s_ATBuffer[MAX_AT_RESPONSE+1];
61 static char *s_ATBufferCur = s_ATBuffer;
63 static int s_ackPowerIoctl; /* true if TTY has android byte-count
64 handshake for low power*/
65 static int s_readCount = 0;
68 void AT_DUMP(const char* prefix, const char* buff, int len)
72 LOGD("%.*s", len, buff);
77 * for current pending command
78 * these are protected by s_commandmutex
81 static pthread_mutex_t s_commandmutex = PTHREAD_MUTEX_INITIALIZER;
82 static pthread_cond_t s_commandcond = PTHREAD_COND_INITIALIZER;
84 static ATCommandType s_type;
85 static const char *s_responsePrefix = NULL;
86 static const char *s_smsPDU = NULL;
87 static ATResponse *sp_response = NULL;
89 static void (*s_onTimeout)(void) = NULL;
90 static void (*s_onReaderClosed)(void) = NULL;
91 static int s_readerClosed;
93 static void onReaderClosed();
94 static int writeCtrlZ (const char *s);
95 static int writeline (const char *s);
98 static void setTimespecRelative(struct timespec *p_ts, long long msec)
102 gettimeofday(&tv, (struct timezone *) NULL);
104 /* what's really funny about this is that I know
105 pthread_cond_timedwait just turns around and makes this
106 a relative time again */
107 p_ts->tv_sec = tv.tv_sec + (msec / 1000);
108 p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L;
112 static void sleepMsec(long long msec)
117 ts.tv_sec = (msec / 1000);
118 ts.tv_nsec = (msec % 1000) * 1000 * 1000;
121 err = nanosleep (&ts, &ts);
122 } while (err < 0 && errno == EINTR);
127 /** add an intermediate response to sp_response*/
128 static void addIntermediate(const char *line)
132 p_new = (ATLine *) malloc(sizeof(ATLine));
134 p_new->line = strdup(line);
136 /* note: this adds to the head of the list, so the list
137 will be in reverse order of lines received. the order is flipped
138 again before passing on to the command issuer */
139 p_new->p_next = sp_response->p_intermediates;
140 sp_response->p_intermediates = p_new;
145 * returns 1 if line is a final response indicating error
147 * WARNING: NO CARRIER and others are sometimes unsolicited
149 static const char * s_finalResponsesError[] = {
153 "NO CARRIER", /* sometimes! */
157 static int isFinalResponseError(const char *line)
161 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesError) ; i++) {
162 if (strStartsWith(line, s_finalResponsesError[i])) {
171 * returns 1 if line is a final response indicating success
173 * WARNING: NO CARRIER and others are sometimes unsolicited
175 static const char * s_finalResponsesSuccess[] = {
177 "CONNECT" /* some stacks start up data on another channel */
179 static int isFinalResponseSuccess(const char *line)
183 for (i = 0 ; i < NUM_ELEMS(s_finalResponsesSuccess) ; i++) {
184 if (strStartsWith(line, s_finalResponsesSuccess[i])) {
193 * returns 1 if line is a final response, either error or success
195 * WARNING: NO CARRIER and others are sometimes unsolicited
197 static int isFinalResponse(const char *line)
199 return isFinalResponseSuccess(line) || isFinalResponseError(line);
204 * returns 1 if line is the first line in (what will be) a two-line
205 * SMS unsolicited response
207 static const char * s_smsUnsoliciteds[] = {
214 static int isSMSUnsolicited(const char *line)
218 for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
219 if (strStartsWith(line, s_smsUnsoliciteds[i])) {
228 /** assumes s_commandmutex is held */
229 static void handleFinalResponse(const char *line)
231 sp_response->finalResponse = strdup(line);
233 pthread_cond_signal(&s_commandcond);
236 static void handleUnsolicited(const char *line)
238 if (s_unsolHandler != NULL) {
239 s_unsolHandler(line, NULL);
243 static void processLine(const char *line)
245 pthread_mutex_lock(&s_commandmutex);
247 if (sp_response == NULL) {
248 /* no command pending */
249 handleUnsolicited(line);
250 } else if (isFinalResponseSuccess(line)) {
251 sp_response->success = 1;
252 handleFinalResponse(line);
253 } else if (isFinalResponseError(line)) {
254 sp_response->success = 0;
255 handleFinalResponse(line);
256 } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
257 // See eg. TS 27.005 4.3
258 // Commands like AT+CMGS have a "> " prompt
259 writeCtrlZ(s_smsPDU);
261 } else switch (s_type) {
263 handleUnsolicited(line);
266 if (sp_response->p_intermediates == NULL
269 addIntermediate(line);
271 /* either we already have an intermediate response or
272 the line doesn't begin with a digit */
273 handleUnsolicited(line);
277 if (sp_response->p_intermediates == NULL
278 && strStartsWith (line, s_responsePrefix)
280 addIntermediate(line);
282 /* we already have an intermediate response */
283 handleUnsolicited(line);
287 if (strStartsWith (line, s_responsePrefix)) {
288 addIntermediate(line);
290 handleUnsolicited(line);
294 default: /* this should never be reached */
295 LOGE("Unsupported AT command type %d\n", s_type);
296 handleUnsolicited(line);
300 pthread_mutex_unlock(&s_commandmutex);
305 * Returns a pointer to the end of the next line
306 * special-cases the "> " SMS prompt
308 * returns NULL if there is no complete line
310 static char * findNextEOL(char *cur)
312 if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
313 /* SMS prompt character...not \r terminated */
318 while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
320 return *cur == '\0' ? NULL : cur;
325 * Reads a line from the AT channel, returns NULL on timeout.
326 * Assumes it has exclusive read access to the FD
328 * This line is valid only until the next call to readline
330 * This function exists because as of writing, android libc does not
331 * have buffered stdio.
334 static const char *readline()
342 /* this is a little odd. I use *s_ATBufferCur == 0 to
343 * mean "buffer consumed completely". If it points to a character, than
344 * the buffer continues until a \0
346 if (*s_ATBufferCur == '\0') {
348 s_ATBufferCur = s_ATBuffer;
349 *s_ATBufferCur = '\0';
351 } else { /* *s_ATBufferCur != '\0' */
352 /* there's data in the buffer from the last read */
354 // skip over leading newlines
355 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
358 p_eol = findNextEOL(s_ATBufferCur);
361 /* a partial line. move it up and prepare to read more */
364 len = strlen(s_ATBufferCur);
366 memmove(s_ATBuffer, s_ATBufferCur, len + 1);
367 p_read = s_ATBuffer + len;
368 s_ATBufferCur = s_ATBuffer;
370 /* Otherwise, (p_eol !- NULL) there is a complete line */
371 /* that will be returned the while () loop below */
374 while (p_eol == NULL) {
375 if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
376 LOGE("ERROR: Input line exceeded buffer\n");
377 /* ditch buffer and start over again */
378 s_ATBufferCur = s_ATBuffer;
379 *s_ATBufferCur = '\0';
384 count = read(s_fd, p_read,
385 MAX_AT_RESPONSE - (p_read - s_ATBuffer));
386 } while (count < 0 && errno == EINTR);
389 AT_DUMP( "<< ", p_read, count );
390 s_readCount += count;
392 p_read[count] = '\0';
394 // skip over leading newlines
395 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
398 p_eol = findNextEOL(s_ATBufferCur);
400 } else if (count <= 0) {
401 /* read error encountered or EOF reached */
403 LOGD("atchannel: EOF reached");
405 LOGD("atchannel: read error %s", strerror(errno));
411 /* a full line in the buffer. Place a \0 over the \r and return */
415 s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */
416 /* and there will be a \0 at *p_read */
418 LOGD("AT< %s\n", ret);
423 static void onReaderClosed()
425 if (s_onReaderClosed != NULL && s_readerClosed == 0) {
427 pthread_mutex_lock(&s_commandmutex);
431 pthread_cond_signal(&s_commandcond);
433 pthread_mutex_unlock(&s_commandmutex);
440 static void *readerLoop(void *arg)
451 if(isSMSUnsolicited(line)) {
455 // The scope of string returned by 'readline()' is valid only
456 // till next call to 'readline()' hence making a copy of line
457 // before calling readline again.
458 line1 = strdup(line);
465 if (s_unsolHandler != NULL) {
466 s_unsolHandler (line1, line2);
473 #ifdef HAVE_ANDROID_OS
474 if (s_ackPowerIoctl > 0) {
475 /* acknowledge that bytes have been read and processed */
476 ioctl(s_fd, OMAP_CSMI_TTY_ACK, &s_readCount);
479 #endif /*HAVE_ANDROID_OS*/
488 * Sends string s to the radio with a \r appended.
489 * Returns AT_ERROR_* on error, 0 on success
491 * This function exists because as of writing, android libc does not
492 * have buffered stdio.
494 static int writeline (const char *s)
497 size_t len = strlen(s);
500 if (s_fd < 0 || s_readerClosed > 0) {
501 return AT_ERROR_CHANNEL_CLOSED;
506 AT_DUMP( ">> ", s, strlen(s) );
508 /* the main string */
511 written = write (s_fd, s + cur, len - cur);
512 } while (written < 0 && errno == EINTR);
515 return AT_ERROR_GENERIC;
524 written = write (s_fd, "\r" , 1);
525 } while ((written < 0 && errno == EINTR) || (written == 0));
528 return AT_ERROR_GENERIC;
533 static int writeCtrlZ (const char *s)
536 size_t len = strlen(s);
539 if (s_fd < 0 || s_readerClosed > 0) {
540 return AT_ERROR_CHANNEL_CLOSED;
543 LOGD("AT> %s^Z\n", s);
545 AT_DUMP( ">* ", s, strlen(s) );
547 /* the main string */
550 written = write (s_fd, s + cur, len - cur);
551 } while (written < 0 && errno == EINTR);
554 return AT_ERROR_GENERIC;
563 written = write (s_fd, "\032" , 1);
564 } while ((written < 0 && errno == EINTR) || (written == 0));
567 return AT_ERROR_GENERIC;
573 static void clearPendingCommand()
575 if (sp_response != NULL) {
576 at_response_free(sp_response);
580 s_responsePrefix = NULL;
586 * Starts AT handler on stream "fd'
587 * returns 0 on success, -1 on error
589 int at_open(int fd, ATUnsolHandler h)
599 s_responsePrefix = NULL;
603 /* Android power control ioctl */
604 #ifdef HAVE_ANDROID_OS
605 #ifdef OMAP_CSMI_POWER_CONTROL
606 ret = ioctl(fd, OMAP_CSMI_TTY_ENABLE_ACK);
612 old_flags = fcntl(fd, F_GETFL, 0);
613 fcntl(fd, F_SETFL, old_flags | O_NONBLOCK);
615 ioctl(fd, OMAP_CSMI_TTY_READ_UNACKED, &ack_count);
618 ret = read(fd, sync_buf, sizeof(sync_buf));
621 } while(ret > 0 || (ret < 0 && errno == EINTR));
622 ioctl(fd, OMAP_CSMI_TTY_ACK, &ack_count);
623 } while(ack_count > 0 || read_count > 0);
624 fcntl(fd, F_SETFL, old_flags);
631 #else // OMAP_CSMI_POWER_CONTROL
634 #endif // OMAP_CSMI_POWER_CONTROL
635 #endif /*HAVE_ANDROID_OS*/
637 pthread_attr_init (&attr);
638 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
640 ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
643 perror ("pthread_create");
651 /* FIXME is it ok to call this from the reader and the command thread? */
659 pthread_mutex_lock(&s_commandmutex);
663 pthread_cond_signal(&s_commandcond);
665 pthread_mutex_unlock(&s_commandmutex);
667 /* the reader thread should eventually die */
670 static ATResponse * at_response_new()
672 return (ATResponse *) calloc(1, sizeof(ATResponse));
675 void at_response_free(ATResponse *p_response)
679 if (p_response == NULL) return;
681 p_line = p_response->p_intermediates;
683 while (p_line != NULL) {
687 p_line = p_line->p_next;
689 free(p_toFree->line);
693 free (p_response->finalResponse);
698 * The line reader places the intermediate responses in reverse order
699 * here we flip them back
701 static void reverseIntermediates(ATResponse *p_response)
705 pcur = p_response->p_intermediates;
706 p_response->p_intermediates = NULL;
708 while (pcur != NULL) {
709 pnext = pcur->p_next;
710 pcur->p_next = p_response->p_intermediates;
711 p_response->p_intermediates = pcur;
717 * Internal send_command implementation
718 * Doesn't lock or call the timeout callback
720 * timeoutMsec == 0 means infinite timeout
723 static int at_send_command_full_nolock (const char *command, ATCommandType type,
724 const char *responsePrefix, const char *smspdu,
725 long long timeoutMsec, ATResponse **pp_outResponse)
732 if(sp_response != NULL) {
733 err = AT_ERROR_COMMAND_PENDING;
737 err = writeline (command);
744 s_responsePrefix = responsePrefix;
746 sp_response = at_response_new();
749 if (timeoutMsec != 0) {
750 setTimespecRelative(&ts, timeoutMsec);
754 while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
755 if (timeoutMsec != 0) {
757 err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec);
759 err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
762 err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
765 if (err == ETIMEDOUT) {
766 err = AT_ERROR_TIMEOUT;
771 if (pp_outResponse == NULL) {
772 at_response_free(sp_response);
774 /* line reader stores intermediate responses in reverse order */
775 reverseIntermediates(sp_response);
776 *pp_outResponse = sp_response;
781 if(s_readerClosed > 0) {
782 err = AT_ERROR_CHANNEL_CLOSED;
788 clearPendingCommand();
794 * Internal send_command implementation
796 * timeoutMsec == 0 means infinite timeout
798 static int at_send_command_full (const char *command, ATCommandType type,
799 const char *responsePrefix, const char *smspdu,
800 long long timeoutMsec, ATResponse **pp_outResponse)
804 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
805 /* cannot be called from reader thread */
806 return AT_ERROR_INVALID_THREAD;
809 pthread_mutex_lock(&s_commandmutex);
811 err = at_send_command_full_nolock(command, type,
812 responsePrefix, smspdu,
813 timeoutMsec, pp_outResponse);
815 pthread_mutex_unlock(&s_commandmutex);
817 if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
826 * Issue a single normal AT command with no intermediate response expected
828 * "command" should not include \r
829 * pp_outResponse can be NULL
831 * if non-NULL, the resulting ATResponse * must be eventually freed with
834 int at_send_command (const char *command, ATResponse **pp_outResponse)
838 err = at_send_command_full (command, NO_RESULT, NULL,
839 NULL, 0, pp_outResponse);
845 int at_send_command_singleline (const char *command,
846 const char *responsePrefix,
847 ATResponse **pp_outResponse)
851 err = at_send_command_full (command, SINGLELINE, responsePrefix,
852 NULL, 0, pp_outResponse);
854 if (err == 0 && pp_outResponse != NULL
855 && (*pp_outResponse)->success > 0
856 && (*pp_outResponse)->p_intermediates == NULL
858 /* successful command must have an intermediate response */
859 at_response_free(*pp_outResponse);
860 *pp_outResponse = NULL;
861 return AT_ERROR_INVALID_RESPONSE;
868 int at_send_command_numeric (const char *command,
869 ATResponse **pp_outResponse)
873 err = at_send_command_full (command, NUMERIC, NULL,
874 NULL, 0, pp_outResponse);
876 if (err == 0 && pp_outResponse != NULL
877 && (*pp_outResponse)->success > 0
878 && (*pp_outResponse)->p_intermediates == NULL
880 /* successful command must have an intermediate response */
881 at_response_free(*pp_outResponse);
882 *pp_outResponse = NULL;
883 return AT_ERROR_INVALID_RESPONSE;
890 int at_send_command_sms (const char *command,
892 const char *responsePrefix,
893 ATResponse **pp_outResponse)
897 err = at_send_command_full (command, SINGLELINE, responsePrefix,
898 pdu, 0, pp_outResponse);
900 if (err == 0 && pp_outResponse != NULL
901 && (*pp_outResponse)->success > 0
902 && (*pp_outResponse)->p_intermediates == NULL
904 /* successful command must have an intermediate response */
905 at_response_free(*pp_outResponse);
906 *pp_outResponse = NULL;
907 return AT_ERROR_INVALID_RESPONSE;
914 int at_send_command_multiline (const char *command,
915 const char *responsePrefix,
916 ATResponse **pp_outResponse)
920 err = at_send_command_full (command, MULTILINE, responsePrefix,
921 NULL, 0, pp_outResponse);
927 /** This callback is invoked on the command thread */
928 void at_set_on_timeout(void (*onTimeout)(void))
930 s_onTimeout = onTimeout;
934 * This callback is invoked on the reader thread (like ATUnsolHandler)
935 * when the input stream closes before you call at_close
936 * (not when you call at_close())
937 * You should still call at_close()
940 void at_set_on_reader_closed(void (*onClose)(void))
942 s_onReaderClosed = onClose;
947 * Periodically issue an AT command and wait for a response.
948 * Used to ensure channel has start up and is active
956 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
957 /* cannot be called from reader thread */
958 return AT_ERROR_INVALID_THREAD;
961 pthread_mutex_lock(&s_commandmutex);
963 for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
964 /* some stacks start with verbose off */
965 err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
966 NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
974 /* pause for a bit to let the input buffer drain any unmatched OK's
975 (they will appear as extraneous unsolicited responses) */
977 sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
980 pthread_mutex_unlock(&s_commandmutex);
986 * Returns error code from response
987 * Assumes AT+CMEE=1 (numeric) mode
989 AT_CME_Error at_get_cme_error(const ATResponse *p_response)
995 if (p_response->success > 0) {
999 if (p_response->finalResponse == NULL
1000 || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
1002 return CME_ERROR_NON_CME;
1005 p_cur = p_response->finalResponse;
1006 err = at_tok_start(&p_cur);
1009 return CME_ERROR_NON_CME;
1012 err = at_tok_nextint(&p_cur, &ret);
1015 return CME_ERROR_NON_CME;
1018 return (AT_CME_Error) ret;