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 RLOGD("%.*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 RLOGE("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 RLOGE("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 RLOGD("atchannel: EOF reached");
403 RLOGD("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 RLOGD("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;
502 RLOGD("AT> %s\n", s);
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 RLOGD("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_singleline (const char *command,
844 const char *responsePrefix,
845 ATResponse **pp_outResponse)
849 err = at_send_command_full (command, SINGLELINE, responsePrefix,
850 NULL, 0, pp_outResponse);
852 if (err == 0 && pp_outResponse != NULL
853 && (*pp_outResponse)->success > 0
854 && (*pp_outResponse)->p_intermediates == NULL
856 /* successful command must have an intermediate response */
857 at_response_free(*pp_outResponse);
858 *pp_outResponse = NULL;
859 return AT_ERROR_INVALID_RESPONSE;
866 int at_send_command_numeric (const char *command,
867 ATResponse **pp_outResponse)
871 err = at_send_command_full (command, NUMERIC, NULL,
872 NULL, 0, pp_outResponse);
874 if (err == 0 && pp_outResponse != NULL
875 && (*pp_outResponse)->success > 0
876 && (*pp_outResponse)->p_intermediates == NULL
878 /* successful command must have an intermediate response */
879 at_response_free(*pp_outResponse);
880 *pp_outResponse = NULL;
881 return AT_ERROR_INVALID_RESPONSE;
888 int at_send_command_sms (const char *command,
890 const char *responsePrefix,
891 ATResponse **pp_outResponse)
895 err = at_send_command_full (command, SINGLELINE, responsePrefix,
896 pdu, 0, pp_outResponse);
898 if (err == 0 && pp_outResponse != NULL
899 && (*pp_outResponse)->success > 0
900 && (*pp_outResponse)->p_intermediates == NULL
902 /* successful command must have an intermediate response */
903 at_response_free(*pp_outResponse);
904 *pp_outResponse = NULL;
905 return AT_ERROR_INVALID_RESPONSE;
912 int at_send_command_multiline (const char *command,
913 const char *responsePrefix,
914 ATResponse **pp_outResponse)
918 err = at_send_command_full (command, MULTILINE, responsePrefix,
919 NULL, 0, pp_outResponse);
925 /** This callback is invoked on the command thread */
926 void at_set_on_timeout(void (*onTimeout)(void))
928 s_onTimeout = onTimeout;
932 * This callback is invoked on the reader thread (like ATUnsolHandler)
933 * when the input stream closes before you call at_close
934 * (not when you call at_close())
935 * You should still call at_close()
938 void at_set_on_reader_closed(void (*onClose)(void))
940 s_onReaderClosed = onClose;
945 * Periodically issue an AT command and wait for a response.
946 * Used to ensure channel has start up and is active
954 if (0 != pthread_equal(s_tid_reader, pthread_self())) {
955 /* cannot be called from reader thread */
956 return AT_ERROR_INVALID_THREAD;
959 pthread_mutex_lock(&s_commandmutex);
961 for (i = 0 ; i < HANDSHAKE_RETRY_COUNT ; i++) {
962 /* some stacks start with verbose off */
963 err = at_send_command_full_nolock ("ATE0Q0V1", NO_RESULT,
964 NULL, NULL, HANDSHAKE_TIMEOUT_MSEC, NULL);
972 /* pause for a bit to let the input buffer drain any unmatched OK's
973 (they will appear as extraneous unsolicited responses) */
975 sleepMsec(HANDSHAKE_TIMEOUT_MSEC);
978 pthread_mutex_unlock(&s_commandmutex);
984 * Returns error code from response
985 * Assumes AT+CMEE=1 (numeric) mode
987 AT_CME_Error at_get_cme_error(const ATResponse *p_response)
993 if (p_response->success > 0) {
997 if (p_response->finalResponse == NULL
998 || !strStartsWith(p_response->finalResponse, "+CME ERROR:")
1000 return CME_ERROR_NON_CME;
1003 p_cur = p_response->finalResponse;
1004 err = at_tok_start(&p_cur);
1007 return CME_ERROR_NON_CME;
1010 err = at_tok_nextint(&p_cur, &ret);
1013 return CME_ERROR_NON_CME;
1016 return (AT_CME_Error) ret;