diff options
author | Magnus Reftel <magnus.xm.reftel@stericsson.com> | 2011-05-20 16:06:50 +0200 |
---|---|---|
committer | Sverre Vegge <sverre.vegge@stericsson.com> | 2011-07-25 09:45:01 +0200 |
commit | 97a8222f0d97fb87cd8f7f20f380d84fc763277e (patch) | |
tree | f205fb33d8dde7bb967c32554b1a09325ef0acff | |
parent | d72ffc1a1bba365e84e5b4685d2d1bca25787fa3 (diff) | |
download | u300-97a8222f0d97fb87cd8f7f20f380d84fc763277e.tar.gz |
AT channel: handle command without response prefix
Added at_send_command_with_echo, which can be used for sending AT commands that
have responses without prefixes. There is a race condition in
at_send_command_multiline etc. with such AT commands that can only be avoided
by having echo on while sending the command, which is what
at_send_command_with_echo does.
Signed-off-by: Sverre Vegge <sverre.vegge@stericsson.com>
-rw-r--r-- | atchannel.c | 60 | ||||
-rw-r--r-- | atchannel.h | 15 | ||||
-rw-r--r-- | u300-ril-information.c | 3 |
3 files changed, 75 insertions, 3 deletions
diff --git a/atchannel.c b/atchannel.c index 5e3d666..7df2117 100644 --- a/atchannel.c +++ b/atchannel.c @@ -97,6 +97,9 @@ struct atcontext { int readerClosed; int timeoutMsec; + + bool waitingForEcho; + const char* command; }; static struct atcontext *s_defaultAtContext = NULL; @@ -428,6 +431,17 @@ static void processLine(const char *line) handleUnsolicited(line); break; + case ECHOED: + if (ac->waitingForEcho) { + if (strcmp(line, ac->command) == 0) { + ac->waitingForEcho = false; + } else { + handleUnsolicited(line); + } + } else { + addIntermediate(line); + } + break; default: /* This should never be reached */ LOGE("Unsupported AT command type %d", ac->type); @@ -1038,6 +1052,8 @@ static int at_send_command_full_nolock(const char *command, ac->type = type; ac->responsePrefix = responsePrefix; ac->smsPDU = smspdu; + ac->waitingForEcho = true; /* Only actually used when type is ECHOED */ + ac->command = command; ac->response = (ATResponse *) calloc(1, sizeof(ATResponse)); assert(ac->response != NULL); @@ -1162,6 +1178,50 @@ int at_send_command(const char *command, ATResponse **pp_outResponse) return err; } +int at_send_command_with_echo(const char *command, ATResponse **pp_outResponse) +{ + int err; + int ate0_err; + + struct atcontext *ac = getAtContext(); + + if (0 != pthread_equal(ac->tid_reader, pthread_self())) + /* Cannot be called from reader thread. */ + return AT_ERROR_INVALID_THREAD; + + pthread_mutex_lock(&ac->commandmutex); + + err = at_send_command_full_nolock("ATE1", NO_RESULT, NULL, NULL, + ac->timeoutMsec, pp_outResponse); + if (err < 0 || (pp_outResponse != NULL && *pp_outResponse != NULL + && (*pp_outResponse)->success == 0)) + goto exit; + + if (pp_outResponse) { + at_response_free(*pp_outResponse); + *pp_outResponse = NULL; + } + + err = at_send_command_full_nolock(command, ECHOED, NULL, NULL, + ac->timeoutMsec, pp_outResponse); + if (err < 0 || (pp_outResponse != NULL && *pp_outResponse != NULL + && (*pp_outResponse)->success == 0)) + goto exit; + + ate0_err = at_send_command_full_nolock("ATE0", ECHOED, NULL, NULL, + ac->timeoutMsec, NULL); + if (ate0_err == AT_ERROR_TIMEOUT) + err = ate0_err; + +exit: + pthread_mutex_unlock(&ac->commandmutex); + + if (err == AT_ERROR_TIMEOUT && ac->onTimeout != NULL) + ac->onTimeout(); + + return err; +} + int at_send_command_with_timeout(const char *command, ATResponse **pp_outResponse, long long timeoutMsec) diff --git a/atchannel.h b/atchannel.h index 56fffa0..b3511e3 100644 --- a/atchannel.h +++ b/atchannel.h @@ -198,8 +198,10 @@ typedef enum { NO_RESULT, /* No intermediate response expected. */ NUMERIC, /* A single intermediate response starting with a 0-9. */ SINGLELINE, /* A single intermediate response starting with a prefix. */ - MULTILINE /* Multiple line intermediate response + MULTILINE, /* Multiple line intermediate response starting with a prefix. */ + ECHOED, /* One or more lines, without prefixes. Requires + echo to be on while sending the command. */ } ATCommandType; /** A singly-linked list of intermediate responses. */ @@ -274,6 +276,17 @@ int at_handshake(); int at_send_command(const char *command, ATResponse **pp_outResponse); +/* Send an AT command with echo-aware response handling. + * + * This function will enable echo before sending the command, and disable it + * afterwards. This means that if echo was already enabled, echo may be + * disabled on return. + * + * The default timeout is used for each individual command, so this function + * may return successfully after up to three times the default timeout. + */ +int at_send_command_with_echo(const char *command, ATResponse **pp_outResponse); + int at_send_command_with_timeout(const char *command, ATResponse **pp_outResponse, long long timeoutMsec); diff --git a/u300-ril-information.c b/u300-ril-information.c index d32ec2d..82f1fb8 100644 --- a/u300-ril-information.c +++ b/u300-ril-information.c @@ -325,8 +325,7 @@ void requestBasebandVersion(void *data, size_t datalen, RIL_Token t) ATLine *atline; char *line; - /* TODO: Check if we really should pass an empty string here */ - err = at_send_command_multiline("AT+CGMR", "", &atresponse); + err = at_send_command_with_echo("AT+CGMR", &atresponse); if (err < 0 || atresponse->success == 0 || atresponse->p_intermediates == NULL) |