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[] = {
212 static int isSMSUnsolicited(const char *line)
216 for (i = 0 ; i < NUM_ELEMS(s_smsUnsoliciteds) ; i++) {
217 if (strStartsWith(line, s_smsUnsoliciteds[i])) {
226 /** assumes s_commandmutex is held */
227 static void handleFinalResponse(const char *line)
229 sp_response->finalResponse = strdup(line);
231 pthread_cond_signal(&s_commandcond);
234 static void handleUnsolicited(const char *line)
236 if (s_unsolHandler != NULL) {
237 s_unsolHandler(line, NULL);
241 static void processLine(const char *line)
243 pthread_mutex_lock(&s_commandmutex);
245 if (sp_response == NULL) {
246 /* no command pending */
247 handleUnsolicited(line);
248 } else if (isFinalResponseSuccess(line)) {
249 sp_response->success = 1;
250 handleFinalResponse(line);
251 } else if (isFinalResponseError(line)) {
252 sp_response->success = 0;
253 handleFinalResponse(line);
254 } else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
255 // See eg. TS 27.005 4.3
256 // Commands like AT+CMGS have a "> " prompt
257 writeCtrlZ(s_smsPDU);
259 } else switch (s_type) {
261 handleUnsolicited(line);
264 if (sp_response->p_intermediates == NULL
267 addIntermediate(line);
269 /* either we already have an intermediate response or
270 the line doesn't begin with a digit */
271 handleUnsolicited(line);
275 if (sp_response->p_intermediates == NULL
276 && strStartsWith (line, s_responsePrefix)
278 addIntermediate(line);
280 /* we already have an intermediate response */
281 handleUnsolicited(line);
285 if (strStartsWith (line, s_responsePrefix)) {
286 addIntermediate(line);
288 handleUnsolicited(line);
292 default: /* this should never be reached */
293 LOGE("Unsupported AT command type %d\n", s_type);
294 handleUnsolicited(line);
298 pthread_mutex_unlock(&s_commandmutex);
303 * Returns a pointer to the end of the next line
304 * special-cases the "> " SMS prompt
306 * returns NULL if there is no complete line
308 static char * findNextEOL(char *cur)
310 if (cur[0] == '>' && cur[1] == ' ' && cur[2] == '\0') {
311 /* SMS prompt character...not \r terminated */
316 while (*cur != '\0' && *cur != '\r' && *cur != '\n') cur++;
318 return *cur == '\0' ? NULL : cur;
323 * Reads a line from the AT channel, returns NULL on timeout.
324 * Assumes it has exclusive read access to the FD
326 * This line is valid only until the next call to readline
328 * This function exists because as of writing, android libc does not
329 * have buffered stdio.
332 static const char *readline()
340 /* this is a little odd. I use *s_ATBufferCur == 0 to
341 * mean "buffer consumed completely". If it points to a character, than
342 * the buffer continues until a \0
344 if (*s_ATBufferCur == '\0') {
346 s_ATBufferCur = s_ATBuffer;
347 *s_ATBufferCur = '\0';
349 } else { /* *s_ATBufferCur != '\0' */
350 /* there's data in the buffer from the last read */
352 // skip over leading newlines
353 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
356 p_eol = findNextEOL(s_ATBufferCur);
359 /* a partial line. move it up and prepare to read more */
362 len = strlen(s_ATBufferCur);
364 memmove(s_ATBuffer, s_ATBufferCur, len + 1);
365 p_read = s_ATBuffer + len;
366 s_ATBufferCur = s_ATBuffer;
368 /* Otherwise, (p_eol !- NULL) there is a complete line */
369 /* that will be returned the while () loop below */
372 while (p_eol == NULL) {
373 if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) {
374 LOGE("ERROR: Input line exceeded buffer\n");
375 /* ditch buffer and start over again */
376 s_ATBufferCur = s_ATBuffer;
377 *s_ATBufferCur = '\0';
382 count = read(s_fd, p_read,
383 MAX_AT_RESPONSE - (p_read - s_ATBuffer));
384 } while (count < 0 && errno == EINTR);
387 AT_DUMP( "<< ", p_read, count );
388 s_readCount += count;
390 p_read[count] = '\0';
392 // skip over leading newlines
393 while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n')
396 p_eol = findNextEOL(s_ATBufferCur);
398 } else if (count <= 0) {
399 /* read error encountered or EOF reached */
401 LOGD("atchannel: EOF reached");
403 LOGD("atchannel: read error %s", strerror(errno));
409 /* a full line in the buffer. Place a \0 over the \r and return */
413 s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */
414 /* and there will be a \0 at *p_read */
416 LOGD("AT< %s\n", ret);
421 static void onReaderClosed()
423 if (s_onReaderClosed != NULL && s_readerClosed == 0) {
425 pthread_mutex_lock(&s_commandmutex);
429 pthread_cond_signal(&s_commandcond);
431 pthread_mutex_unlock(&s_commandmutex);
438 static void *readerLoop(void *arg)
449 if(isSMSUnsolicited(line)) {
453 // The scope of string returned by 'readline()' is valid only
454 // till next call to 'readline()' hence making a copy of line
455 // before calling readline again.
456 line1 = strdup(line);
463 if (s_unsolHandler != NULL) {
464 s_unsolHandler (line1, line2);
471 #ifdef HAVE_ANDROID_OS
472 if (s_ackPowerIoctl > 0) {
473 /* acknowledge that bytes have been read and processed */
474 ioctl(s_fd, OMAP_CSMI_TTY_ACK, &s_readCount);
477 #endif /*HAVE_ANDROID_OS*/
486 * Sends string s to the radio with a \r appended.
487 * Returns AT_ERROR_* on error, 0 on success
489 * This function exists because as of writing, android libc does not
490 * have buffered stdio.
492 static int writeline (const char *s)
495 size_t len = strlen(s);
498 if (s_fd < 0 || s_readerClosed > 0) {
499 return AT_ERROR_CHANNEL_CLOSED;
504 AT_DUMP( ">> ", s, strlen(s) );
506 /* the main string */
509 written = write (s_fd, s + cur, len - cur);
510 } while (written < 0 && errno == EINTR);
513 return AT_ERROR_GENERIC;
522 written = write (s_fd, "\r" , 1);
523 } while ((written < 0 && errno == EINTR) || (written == 0));
526 return AT_ERROR_GENERIC;
531 static int writeCtrlZ (const char *s)
534 size_t len = strlen(s);
537 if (s_fd < 0 || s_readerClosed > 0) {
538 return AT_ERROR_CHANNEL_CLOSED;
541 LOGD("AT> %s^Z\n", s);
543 AT_DUMP( ">* ", s, strlen(s) );
545 /* the main string */
548 written = write (s_fd, s + cur, len - cur);
549 } while (written < 0 && errno == EINTR);
552 return AT_ERROR_GENERIC;
561 written = write (s_fd, "\032" , 1);
562 } while ((written < 0 && errno == EINTR) || (written == 0));
565 return AT_ERROR_GENERIC;
571 static void clearPendingCommand()
573 if (sp_response != NULL) {
574 at_response_free(sp_response);
578 s_responsePrefix = NULL;
584 * Starts AT handler on stream "fd'
585 * returns 0 on success, -1 on error
587 int at_open(int fd, ATUnsolHandler h)
597 s_responsePrefix = NULL;
601 /* Android power control ioctl */
602 #ifdef HAVE_ANDROID_OS
603 #ifdef OMAP_CSMI_POWER_CONTROL
604 ret = ioctl(fd, OMAP_CSMI_TTY_ENABLE_ACK);
610 old_flags = fcntl(fd, F_GETFL, 0);
611 fcntl(fd, F_SETFL, old_flags | O_NONBLOCK);
613 ioctl(fd, OMAP_CSMI_TTY_READ_UNACKED, &ack_count);
616 ret = read(fd, sync_buf, sizeof(sync_buf));
619 } while(ret > 0 || (ret < 0 && errno == EINTR));
620 ioctl(fd, OMAP_CSMI_TTY_ACK, &ack_count);
621 } while(ack_count > 0 || read_count > 0);
622 fcntl(fd, F_SETFL, old_flags);
629 #else // OMAP_CSMI_POWER_CONTROL
632 #endif // OMAP_CSMI_POWER_CONTROL
633 #endif /*HAVE_ANDROID_OS*/
635 pthread_attr_init (&attr);
636 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
638 ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);
641 perror ("pthread_create");
649 /* FIXME is it ok to call this from the reader and the command thread? */
657 pthread_mutex_lock(&s_commandmutex);
661 pthread_cond_signal(&s_commandcond);
663 pthread_mutex_unlock(&s_commandmutex);
665 /* the reader thread should eventually die */
668 static ATResponse * at_response_new()
670 return (ATResponse *) calloc(1, sizeof(ATResponse));
673 void at_response_free(ATResponse *p_response)
677 if (p_response == NULL) return;
679 p_line = p_response->p_intermediates;
681 while (p_line != NULL) {
685 p_line = p_line->p_next;
687 free(p_toFree->line);
691 free (p_response->finalResponse);
696 * The line reader places the intermediate responses in reverse order
697 * here we flip them back
699 static void reverseIntermediates(ATResponse *p_response)
703 pcur = p_response->p_intermediates;
704 p_response->p_intermediates = NULL;
706 while (pcur != NULL) {
707 pnext = pcur->p_next;
708 pcur->p_next = p_response->p_intermediates;
709 p_response->p_intermediates = pcur;
715 * Internal send_command implementation
716 * Doesn't lock or call the timeout callback
718 * timeoutMsec == 0 means infinite timeout
721 static int at_send_command_full_nolock (const char *command, ATCommandType type,
722 const char *responsePrefix, const char *smspdu,
723 long long timeoutMsec, ATResponse **pp_outResponse)
730 if(sp_response != NULL) {
731 err = AT_ERROR_COMMAND_PENDING;
735 err = writeline (command);
742 s_responsePrefix = responsePrefix;
744 sp_response = at_response_new();
747 if (timeoutMsec != 0) {
748 setTimespecRelative(&ts, timeoutMsec);
752 while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
753 if (timeoutMsec != 0) {
755 err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec);
757 err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
760 err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
763 if (err == ETIMEDOUT) {
764 err = AT_ERROR_TIMEOUT;
769 if (pp_outResponse == NULL) {
770 at_response_free(sp_response);
772 /* line reader stores intermediate responses in reverse order */
773 reverseIntermediates(sp_response);
774 *pp_outResponse = sp_response;
779 if(s_readerClosed > 0) {
780 err = AT_ERROR_CHANNEL_CLOSED;
786 clearPendingCommand();
792 * Internal send_command implementation
794 * timeoutMsec == 0 means infinite timeout
796 static int at_send_command_full (const char *command, ATCommandType type,
797 const char *responsePrefix, const char *smspdu,
798 long long timeoutMsec, ATResponse **pp_outResponse)
802 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
803 /* cannot be called from reader thread */
804 return AT_ERROR_INVALID_THREAD;
807 pthread_mutex_lock(&s_commandmutex);
809 err = at_send_command_full_nolock(command, type,
810 responsePrefix, smspdu,
811 timeoutMsec, pp_outResponse);
813 pthread_mutex_unlock(&s_commandmutex);
815 if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
824 * Issue a single normal AT command with no intermediate response expected
826 * "command" should not include \r
827 * pp_outResponse can be NULL
829 * if non-NULL, the resulting ATResponse * must be eventually freed with
832 int at_send_command (const char *command, ATResponse **pp_outResponse)
836 err = at_send_command_full (command, NO_RESULT, NULL,
837 NULL, 0, pp_outResponse);
843 int at_send_command_timeout (const char *command, long long timeout, ATResponse **pp_outResponse)
847 err = at_send_command_full (command, NO_RESULT, NULL,
848 NULL, timeout, pp_outResponse);
854 int at_send_command_singleline (const char *command,
855 const char *responsePrefix,
856 ATResponse **pp_outResponse)
860 err = at_send_command_full (command, SINGLELINE, responsePrefix,
861 NULL, 0, pp_outResponse);
863 if (err == 0 && pp_outResponse != NULL
864 && (*pp_outResponse)->success > 0
865 && (*pp_outResponse)->p_intermediates == NULL
867 /* successful command must have an intermediate response */
868 at_response_free(*pp_outResponse);
869 *pp_outResponse = NULL;
870 return AT_ERROR_INVALID_RESPONSE;
877 int at_send_command_numeric (const char *command,
878 ATResponse **pp_outResponse)
882 err = at_send_command_full (command, NUMERIC, NULL,
883 NULL, 0, pp_outResponse);
885 if (err == 0 && pp_outResponse != NULL
886 && (*pp_outResponse)->success > 0
887 && (*pp_outResponse)->p_intermediates == NULL
889 /* successful command must have an intermediate response */
890 at_response_free(*pp_outResponse);
891 *pp_outResponse = NULL;
892 return AT_ERROR_INVALID_RESPONSE;
899 int at_send_command_sms (const char *command,
901 const char *responsePrefix,
902 ATResponse **pp_outResponse)
906 err = at_send_command_full (command, SINGLELINE, responsePrefix,
907 pdu, 0, pp_outResponse);
909 if (err == 0 && pp_outResponse != NULL
910 && (*pp_outResponse)->success > 0
911 && (*pp_outResponse)->p_intermediates == NULL
913 /* successful command must have an intermediate response */
914 at_response_free(*pp_outResponse);
915 *pp_outResponse = NULL;
916 return AT_ERROR_INVALID_RESPONSE;
923 int at_send_command_multiline (const char *command,
924 const char *responsePrefix,
925 ATResponse **pp_outResponse)
929 err = at_send_command_full (command, MULTILINE, responsePrefix,
930 NULL, 0, pp_outResponse);
936 /** This callback is invoked on the command thread */
937 void at_set_on_timeout(void (*onTimeout)(void))
939 s_onTimeout = onTimeout;
943 * This callback is invoked on the reader thread (like ATUnsolHandler)
944 * when the input stream closes before you call at_close
945 * (not when you call at_close())
946 * You should still call at_close()
949 void at_set_on_reader_closed(void (*onClose)(void))
951 s_onReaderClosed = onClose;
956 * Periodically issue an AT command and wait for a response.
957 * Used to ensure channel has start up and is active
965 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
966 /* cannot be called from reader thread */
967 return AT_ERROR_INVALID_THREAD;
970 pthread_mutex_lock(&s_commandmutex);
972 for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
973 /* some stacks start with verbose off */
974 err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
975 NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
983 /* pause for a bit to let the input buffer drain any unmatched OK's
984 (they will appear as extraneous unsolicited responses) */
986 sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
989 pthread_mutex_unlock(&s_commandmutex);
995 * Returns error code from response
996 * Assumes AT+CMEE=1 (numeric) mode
998 AT_CME_Error at_get_cme_error(const ATResponse *p_response)
1004 if (p_response->success > 0) {
1008 if (p_response->finalResponse == NULL
1009 || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
1011 return CME_ERROR_NON_CME;
1014 p_cur = p_response->finalResponse;
1015 err = at_tok_start(&p_cur);
1018 return CME_ERROR_NON_CME;
1021 err = at_tok_nextint(&p_cur, &ret);
1024 return CME_ERROR_NON_CME;
1027 return (AT_CME_Error) ret;