Some commands need to be processed before a "\r\n" is available and
there might also be commands that have "\r\n" as data but doesn't mean
the end of the command.
To solve this a MODEM_CMD_DIRECT has been added. cmd_handler_process()
will look for matching direct commands before checking if a whole line
is available for matching the normal commands.
A direct command can return either -EAGAIN, meaning that more data is
needed or it will return the number of bytes to skip forward, ie the
length of the command that was handled.
Signed-off-by: Tobias Svehagen <tobias.svehagen@gmail.com>
Some modem commands can determine if they have enough data pulled from
the modem to continue or not. Let's allow those functions to return
EAGAIN which means there's more data needed from the modem.
Signed-off-by: Michael Scott <mike@foundries.io>
This is a generic command handler implementation which uses the
supplied modem interface to process incoming data and hand it
back to the modem driver via callbacks defined for:
- modem responses
- unsolicited messages
- specified handlers for current operation
The individual modem drivers define functions as command handlers
via the MODEM_CMD_DEFINE() macro.
To use these handlers, a modem operation defines a series of
modem_cmd structures and passes them to the modem_cmd_send()
function. The modem_cmd includes data for:
- a matching string for when to execute the handler
- # of parameters to parse after the matching string
- delimeters for the parameters
Example modem driver setup code looks like this:
/* create modem context object */
static struct modem_context mctx;
/* net_buf receive pool */
NET_BUF_POOL_DEFINE(mdm_recv_pool, MDM_RECV_MAX_BUF,
MDM_RECV_BUF_SIZE, 0, NULL);
/* modem cmds */
static struct modem_cmd_handler_data cmd_handler_data;
static u8_t cmd_read_buf[MDM_RECV_BUF_SIZE];
static u8_t cmd_match_buf[MDM_RECV_BUF_SIZE];
/* modem response handlers */
static struct modem_cmd response_cmds[] = {
MODEM_CMD("OK", on_cmd_ok, 0U, ""),
MODEM_CMD("ERROR", on_cmd_error, 0U, ""),
MODEM_CMD("+CME ERROR: ", on_cmd_exterror, 1U, ""),
};
/* unsolicited handlers */
static struct modem_cmd unsol_cmds[] = {
MODEM_CMD("+UUSOCL: ", on_cmd_socknotifyclose, 1U, ""),
MODEM_CMD("+UUSORD: ", on_cmd_socknotifydata, 2U, ","),
MODEM_CMD("+UUSORF: ", on_cmd_socknotifydata, 2U, ","),
MODEM_CMD("+CREG: ", on_cmd_socknotifycreg, 1U, ""),
};
/* setup cmd handler data */
cmd_handler_data.cmds[CMD_RESP] = response_cmds;
cmd_handler_data.cmds_len[CMD_RESP] = ARRAY_SIZE(response_cmds);
cmd_handler_data.cmds[CMD_UNSOL] = unsol_cmds;
cmd_handler_data.cmds_len[CMD_UNSOL] = ARRAY_SIZE(unsol_cmds);
cmd_handler_data.read_buf = &cmd_read_buf[0];
cmd_handler_data.read_buf_len = sizeof(cmd_read_buf);
cmd_handler_data.match_buf = &cmd_match_buf[0];
cmd_handler_data.match_buf_len = sizeof(cmd_match_buf);
cmd_handler_data.buf_pool = &mdm_recv_pool;
cmd_handler_data.alloc_timeout = BUF_ALLOC_TIMEOUT;
ret = modem_cmd_handler_init(&mctx.cmd_handler, &cmd_handler_data);
Signed-off-by: Michael Scott <mike@foundries.io>