Loading...
Searching...
No Matches
AT (Hayes) command set library

AT (Hayes) command set library. More...

Detailed Description

AT (Hayes) command set library.

This module provides functions to interact with devices using AT commands.

Most functions compare the bytes echoed by the device with what they intended to send, and bail out if there's no match.

Furthermore, the library tries to cope with difficulties regarding different line endings. It usually sends <command><CR>, but expects <command>\LF\CR as echo.

As a debugging aid, when compiled with -DAT_PRINT_INCOMING=1, every input byte gets printed.

Command echoing

Most DCEs (Data Circuit-terminating Equipment, aka modem) support command echoing and enable it by default, and so does this driver. If you disabled echoing on the DCE, you can compile this driver NOT to expect echoing by defining CONFIG_AT_SEND_SKIP_ECHO. Note, if the driver is NOT expecting command echoing but the DCE is echoing, it should work just fine if and only if the EOL sequences of both DCE and DTE (Data Terminal Equipmend - i.e. the device using this driver) match, i.e. AT_RECV_EOL_1 AT_RECV_EOL_2 == AT_SEND_EOL. In other words, if you are unsure about the echoing behavior of the DCE or want to support both, set AT_SEND_EOL = AT_RECV_EOL_1 AT_RECV_EOL_2 and define CONFIG_AT_SEND_SKIP_ECHO. This works because the URC (Unsolicited Result Code) logic will intercept the echoes (see below).

Unsolicited Result Codes (URC)

An unsolicited result code is a string message that is not triggered as a information text response to a previous AT command and can be output at any time to inform a specific event or status change.

Some DCEs (Data Circuit-terminating Equipment, aka modem), like the LTE modules from uBlox define a grace period where URCs are guaranteed NOT to be sent as the time span between:

As follows, there is an indeterminate amount of time between:

In other words, we can get a URC (or more?) just after issuing the command and before the first line of response. The net effect is that such URCs will appear to be the first line of response to the last issued command.

Regardless of whether URC handling is enabled or not, URC interception mechanics depend on command echoing:

  1. echo enabled: by observation, it seems that the grace period begins BEFORE the echoed command. This has the advantage that we ALWAYS know what the first line of response must look like and so if it doesn't, then it's a URC. Thus, any procedure that calls at_send_cmd() internally will catch any URC.
  2. echo disabled: commands that expect a particular type of response (e.g. at_send_cmd_get_resp_wait_ok() with a non-trivial prefix, at_send_cmd_wait_ok() etc.) will catch any URC. For the rest, it is the application's responsibility to decide whether the received answer is an URC or not and if yes, then at_postprocess_urc() can be called with the response as parameter.

URC handling can be enabled by adding the at_urc module to the application. This allows to register and de-register URC strings to check. Later, URCs can be processed in three different ways:

Error reporting

Most DCEs (Data Circuit-terminating Equipment, aka modem) can return extra error information instead of the rather opaque "ERROR" message. They have the form:

For +CME, this behavior is usually off by default and can be toggled with: AT+CMEE=<type> where <type> may be:

Some of the API calls below support detailed error reporting. Whenever they detect extended error responses, -AT_ERR_EXTENDED is returned and <err_code> can be retrieved by calling at_get_err_info().

Modules

 AT driver compile configuration
 

Files

file  at.h
 AT (Hayes) library interface.
 

Data Structures

struct  at_urc_t
 Unsolicited result code data structure. More...
 
struct  at_dev_t
 AT device structure. More...
 
struct  at_dev_init_t
 AT device initialization parameters. More...
 

Macros

#define AT_ERR_EXTENDED   200
 Error cause can be further investigated.
 
#define AT_SEND_EOL_LEN   (sizeof(CONFIG_AT_SEND_EOL) - 1)
 Shortcut for getting send end of line length.
 

Typedefs

typedef void(* at_urc_cb_t) (void *arg, const char *code)
 Unsolicited result code callback.
 

Functions

static char const * at_get_err_info (at_dev_t const *dev)
 Get extended error information of the last command sent.
 
int at_dev_init (at_dev_t *dev, at_dev_init_t const *init)
 Initialize AT device struct.
 
int at_send_cmd_wait_ok (at_dev_t *dev, const char *command, uint32_t timeout)
 Simple command helper.
 
int at_send_cmd_wait_prompt (at_dev_t *dev, const char *command, uint32_t timeout)
 Send AT command, wait for a prompt.
 
int at_wait_prompt (at_dev_t *dev, uint32_t timeout)
 Waits for the prompt character (>).
 
ssize_t at_send_cmd_get_resp (at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout)
 Send AT command, wait for response.
 
ssize_t at_get_resp_with_prefix (at_dev_t *dev, const char *resp_prefix, char *resp_buf, size_t len, uint32_t timeout)
 Wait for a response with a specific prefix.
 
ssize_t at_send_cmd_get_resp_wait_ok (at_dev_t *dev, const char *command, const char *resp_prefix, char *resp_buf, size_t len, uint32_t timeout)
 Send AT command, wait for response plus OK.
 
ssize_t at_send_cmd_get_lines (at_dev_t *dev, const char *command, char *resp_buf, size_t len, uint32_t timeout)
 Send AT command, wait for multiline response.
 
int at_expect_bytes (at_dev_t *dev, const char *bytes, uint32_t timeout)
 Expect bytes from device.
 
int at_wait_bytes (at_dev_t *dev, const char *bytes, uint32_t timeout)
 Repeatedly calls at_expect_bytes() until a match or timeout occurs.
 
int at_recv_bytes_until_string (at_dev_t *dev, const char *string, char *bytes, size_t *bytes_len, uint32_t timeout)
 Receives bytes into bytes buffer until the string pattern string is received or the buffer is full.
 
void at_send_bytes (at_dev_t *dev, const char *bytes, size_t len)
 Send raw bytes to a device.
 
ssize_t at_recv_bytes (at_dev_t *dev, char *bytes, size_t len, uint32_t timeout)
 Receive raw bytes from a device.
 
int at_send_cmd (at_dev_t *dev, const char *command, uint32_t timeout)
 Send command to device.
 
int at_parse_resp (at_dev_t *dev, char const *resp)
 Parse a response from the device.
 
ssize_t at_readline (at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, uint32_t timeout)
 Read a line from device.
 
ssize_t at_readline_skip_empty (at_dev_t *dev, char *resp_buf, size_t len, bool keep_eol, uint32_t timeout)
 Read a line from device, skipping a possibly empty line.
 
int at_wait_ok (at_dev_t *dev, uint32_t timeout)
 Wait for an OK response.
 
void at_drain (at_dev_t *dev)
 Drain device input buffer.
 
void at_dev_poweron (at_dev_t *dev)
 Power device on.
 
void at_dev_poweroff (at_dev_t *dev)
 Power device off.
 
void at_add_urc (at_dev_t *dev, at_urc_t *urc)
 Add a callback for an unsolicited response code.
 
void at_remove_urc (at_dev_t *dev, at_urc_t *urc)
 Remove an unsolicited response code from the list.
 
void at_process_urc (at_dev_t *dev, uint32_t timeout)
 Process out-of-band data received from the device.
 
void at_postprocess_urc (at_dev_t *dev, char *buf)
 Process one URC from the provided buffer.
 
void at_postprocess_urc_all (at_dev_t *dev, char *buf)
 Process all URCs from the provided buffer.
 

Macro Definition Documentation

◆ AT_ERR_EXTENDED

#define AT_ERR_EXTENDED   200

Error cause can be further investigated.

Definition at line 216 of file at.h.

◆ AT_SEND_EOL_LEN

#define AT_SEND_EOL_LEN   (sizeof(CONFIG_AT_SEND_EOL) - 1)

Shortcut for getting send end of line length.

Definition at line 219 of file at.h.

Typedef Documentation

◆ at_urc_cb_t

typedef void(* at_urc_cb_t) (void *arg, const char *code)

Unsolicited result code callback.

Parameters
[in]argoptional argument
[in]codeurc string received from the device

Definition at line 201 of file at.h.

Function Documentation

◆ at_add_urc()

void at_add_urc ( at_dev_t dev,
at_urc_t urc 
)

Add a callback for an unsolicited response code.

Parameters
[in]devdevice to operate on
[in]urcunsolicited result code to register

◆ at_dev_init()

int at_dev_init ( at_dev_t dev,
at_dev_init_t const *  init 
)

Initialize AT device struct.

Parameters
[in]devstruct to initialize
[in]initinit struct, may be destroyed after return
Return values
successcode UART_OK on success
errorcode UART_NODEV or UART_NOBAUD otherwise

◆ at_dev_poweroff()

void at_dev_poweroff ( at_dev_t dev)

Power device off.

Parameters
[in]devdevice to power off

◆ at_dev_poweron()

void at_dev_poweron ( at_dev_t dev)

Power device on.

Parameters
[in]devdevice to power on

◆ at_drain()

void at_drain ( at_dev_t dev)

Drain device input buffer.

This function drains any possible bytes waiting in the device's input buffer.

Parameters
[in]devdevice to operate on

◆ at_expect_bytes()

int at_expect_bytes ( at_dev_t dev,
const char *  bytes,
uint32_t  timeout 
)

Expect bytes from device.

Parameters
[in]devdevice to operate on
[in]bytesbuffer containing bytes to expect (NULL-terminated)
[in]timeouttimeout (in usec)
Return values
0on success
<0otherwise

◆ at_get_err_info()

static char const * at_get_err_info ( at_dev_t const *  dev)
inlinestatic

Get extended error information of the last command sent.

If a previous at_* method returned with -AT_ERR_EXTENDED, you can retrieve a pointer to the error string with this.

Parameters
[in]devdevice to operate on
Return values
stringcontaining the error value.

Definition at line 267 of file at.h.

◆ at_get_resp_with_prefix()

ssize_t at_get_resp_with_prefix ( at_dev_t dev,
const char *  resp_prefix,
char *  resp_buf,
size_t  len,
uint32_t  timeout 
)

Wait for a response with a specific prefix.

If the provided prefix is NULL or empty, this behaves just like at_readline_skip_empty(). Otherwise, it repeatedly calls at_readline_skip_empty() and:

  • if the prefix matches: discards the prefix from the response, copies the rest to resp_buf, stops and returns the resulting response length
  • if the prefix does not match:
    • if the response is OK: stops and returns 0
    • if the response is ERROR/CMx ERROR: stops and returns <0
    • none of the above: handles response as URC and repeats with the next line
Parameters
[in]devdevice to operate on
[in]resp_prefixexpected prefix in the response
[out]resp_bufbuffer for storing response
[in]lenlen of buffer
[in]timeouttimeout (in usec)
Return values
nresponse length if the prefix of the response matches
0if the response was OK
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
<0on error

◆ at_parse_resp()

int at_parse_resp ( at_dev_t dev,
char const *  resp 
)

Parse a response from the device.

This is always called automatically in functions that may return -AT_ERR_EXTENDED. However, if you read the response by other methods (e.g. with at_recv_bytes()), you might want to call this on the response so that you don't have to parse it yourself.

Return values
0if the response is "OK"
-AT_ERR_EXTENDEDif the response is +CMx ERROR: <err>, and <err> has been successfully copied to dev->rp_buf
-1if the response is "ERROR", or +CMx ERROR: <err> but <err> could not be copied
1otherwise

◆ at_postprocess_urc()

void at_postprocess_urc ( at_dev_t dev,
char *  buf 
)

Process one URC from the provided buffer.

Useful if you e.g. called at_send_cmd_get_lines() and the first lines are URCs.

Parameters
[in]devdevice to operate on
[in]bufbuffer containing an URC

◆ at_postprocess_urc_all()

void at_postprocess_urc_all ( at_dev_t dev,
char *  buf 
)

Process all URCs from the provided buffer.

Useful if you e.g. called at_recv_bytes(), found what you were interested in, and there might be some URCs left in the buffer.

Parameters
[in]devdevice to operate on
[in]bufbuffer containing URCs

◆ at_process_urc()

void at_process_urc ( at_dev_t dev,
uint32_t  timeout 
)

Process out-of-band data received from the device.

Parameters
[in]devdevice to operate on
[in]timeouttimeout (in usec)

◆ at_readline()

ssize_t at_readline ( at_dev_t dev,
char *  resp_buf,
size_t  len,
bool  keep_eol,
uint32_t  timeout 
)

Read a line from device.

Stops at the first DCE EOL sequence. The response is guaranteed null-terminated.

Parameters
[in]devdevice to operate on
[in]resp_bufbuffer to store line
[in]lensize of resp_buf
[in]keep_eoltrue to keep the trailing EOL sequence in the response
[in]timeouttimeout (in usec)
Return values
nline length on success
-ENOBUFSif the supplied buffer was to small.
<0on error

◆ at_readline_skip_empty()

ssize_t at_readline_skip_empty ( at_dev_t dev,
char *  resp_buf,
size_t  len,
bool  keep_eol,
uint32_t  timeout 
)

Read a line from device, skipping a possibly empty line.

Stops at the first DCE EOL sequence AFTER any non-EOL sequence. The response is guaranteed null-terminated.

Parameters
[in]devdevice to operate on
[in]resp_bufbuffer to store line
[in]lensize of resp_buf
[in]keep_eoltrue to keep the trailing EOL sequence in the response
[in]timeouttimeout (in usec)
Return values
nline length on success
-ENOBUFSif the supplied buffer was to small.
<0on error

◆ at_recv_bytes()

ssize_t at_recv_bytes ( at_dev_t dev,
char *  bytes,
size_t  len,
uint32_t  timeout 
)

Receive raw bytes from a device.

Parameters
[in]devdevice to operate on
[in]bytesbuffer where store received bytes
[in]lenmaximum number of bytes to receive
[in]timeouttimeout (in usec) of inactivity to finish read
Return values
nNumber of bytes read, eventually zero if no bytes available

◆ at_recv_bytes_until_string()

int at_recv_bytes_until_string ( at_dev_t dev,
const char *  string,
char *  bytes,
size_t *  bytes_len,
uint32_t  timeout 
)

Receives bytes into bytes buffer until the string pattern string is received or the buffer is full.

Parameters
[in]devdevice to operate on
[in]stringstring pattern to expect
[out]bytesbuffer to store received bytes
[in,out]bytes_lenpointer to the maximum number of bytes to receive. On return stores the amount of received bytes.
[in]timeouttimeout (in usec) of inactivity to finish read
Return values
0on success
<0on error

◆ at_remove_urc()

void at_remove_urc ( at_dev_t dev,
at_urc_t urc 
)

Remove an unsolicited response code from the list.

Parameters
[in]devdevice to operate on
[in]urcunsolicited result code to remove

◆ at_send_bytes()

void at_send_bytes ( at_dev_t dev,
const char *  bytes,
size_t  len 
)

Send raw bytes to a device.

Parameters
[in]devdevice to operate on
[in]bytesbuffer containing bytes to send
[in]lennumber of bytes to send

◆ at_send_cmd()

int at_send_cmd ( at_dev_t dev,
const char *  command,
uint32_t  timeout 
)

Send command to device.

Some URCs may be handled.

Parameters
[in]devdevice to operate on
[in]commandcommand to send
[in]timeouttimeout (in usec)
Return values
0on success
<0otherwise

◆ at_send_cmd_get_lines()

ssize_t at_send_cmd_get_lines ( at_dev_t dev,
const char *  command,
char *  resp_buf,
size_t  len,
uint32_t  timeout 
)

Send AT command, wait for multiline response.

This function sends the supplied command, then returns all response lines until the device sends "OK". The response is guaranteed null-terminated.

Some URCs are automatically handled. The first m response lines can be URCs. In that case, at_postprocess_urc() can be called with each line as parameter.

If a line contains a DTE error response, this function stops and returns accordingly. Any lines received prior to that are considered to be URCs and thus handled.

Parameters
[in]devdevice to operate on
[in]commandcommand to send
[out]resp_bufbuffer for storing response
[in]lenlen of resp_buf
[in]timeouttimeout (in usec)
Return values
nlength of response on success
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
-ENOBUFSif the supplied buffer was to small.
<0other failures

◆ at_send_cmd_get_resp()

ssize_t at_send_cmd_get_resp ( at_dev_t dev,
const char *  command,
char *  resp_buf,
size_t  len,
uint32_t  timeout 
)

Send AT command, wait for response.

This function sends the supplied command, then waits and returns one line of response. The response is guaranteed null-terminated.

Some URCs are automatically handled. The response returned can be an URC. In that case, at_postprocess_urc() can be called with the response as parameter.

A possible empty line will be skipped.

Parameters
[in]devdevice to operate on
[in]commandcommand to send
[out]resp_bufbuffer for storing response
[in]lenlen of buffer
[in]timeouttimeout (in usec)
Return values
nlength of response on success
-ENOBUFSif the supplied buffer was to small.
<0on error

◆ at_send_cmd_get_resp_wait_ok()

ssize_t at_send_cmd_get_resp_wait_ok ( at_dev_t dev,
const char *  command,
const char *  resp_prefix,
char *  resp_buf,
size_t  len,
uint32_t  timeout 
)

Send AT command, wait for response plus OK.

This function sends the supplied command, then waits and returns one line of response. The response is guaranteed null-terminated.

Calls following in order:

URCs are automatically handled. If no prefix is provided, the response may be an URC. In that case, at_postprocess_urc() can be called with the response as parameter.

Parameters
[in]devdevice to operate on
[in]commandcommand to send
[in]resp_prefixexpected prefix in the response
[out]resp_bufbuffer for storing response
[in]lenlen of buffer
[in]timeouttimeout (in usec)
Return values
nlength of response on success
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
-ENOBUFSif the supplied buffer was to small.
<0other failures

◆ at_send_cmd_wait_ok()

int at_send_cmd_wait_ok ( at_dev_t dev,
const char *  command,
uint32_t  timeout 
)

Simple command helper.

This function sends an AT command to the device and waits for "OK".

URCs are automatically handled

Parameters
[in]devdevice to operate on
[in]commandcommand string to send
[in]timeouttimeout (in usec)
Return values
0when device answers "OK"
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
<0other failures

◆ at_send_cmd_wait_prompt()

int at_send_cmd_wait_prompt ( at_dev_t dev,
const char *  command,
uint32_t  timeout 
)

Send AT command, wait for a prompt.

This function sends the supplied command, then waits for the prompt (>) character and returns

URCs are automatically handled

Parameters
[in]devdevice to operate on
[in]commandcommand string to send
[in]timeouttimeout (in usec)
Return values
0when prompt is received
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
<0other failures

◆ at_wait_bytes()

int at_wait_bytes ( at_dev_t dev,
const char *  bytes,
uint32_t  timeout 
)

Repeatedly calls at_expect_bytes() until a match or timeout occurs.

Parameters
[in]devdevice to operate on
[in]bytesbuffer containing bytes to expect (NULL-terminated)
[in]timeouttimeout (in usec)
Return values
0on success
<0otherwise

◆ at_wait_ok()

int at_wait_ok ( at_dev_t dev,
uint32_t  timeout 
)

Wait for an OK response.

Useful when crafting the command-response sequence by yourself.

URCs are automatically handled

Parameters
[in]devdevice to operate on
[in]timeouttimeout (in usec)
Return values
0when device answers "OK"
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
<0other failures

◆ at_wait_prompt()

int at_wait_prompt ( at_dev_t dev,
uint32_t  timeout 
)

Waits for the prompt character (>).

Parameters
[in]devdevice to operate on
[in]timeouttimeout (in usec)
Return values
0when prompt is received
-AT_ERR_EXTENDEDif failed and a error code can be retrieved with at_get_err_info() (i.e. DCE answered with CMx ERROR)
<0other failures