Commit graph

36 commits

Author SHA1 Message Date
Jordan Yates 1c2dba2107 drivers: modem: cache delimiter string length
Cache the delimiter string length in `parse_params`, instead of
calculating it on each character in the match buffer.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
2023-07-13 09:23:05 +02:00
Jordan Yates 76c1a2019a drivers: modem: skip quoted delimiters
Given the following response: `+CIPSTA:ip6ll:"FE80::EDC:7EFF:FEDD:110C"`

The response delimiter is `:`, but there is also a quoted string that
contains the delimiter character. These delimiters should not be
considered when searching for the end of a parameter.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
2023-07-13 09:23:05 +02:00
Bjarki Arge Andreasen aa6ecc59d1 drivers/modem/modem_cmd_handler: Update API
There is currently not a clear separation between
user configuration and internal context when using the
modem_cmd_handler library. This update adds a clear
separation, placing user configuration in a seperate
struct passed to modem_cmd_handler_init alongside the
internal context modem_cmd_handler_data.

There is also a lack of documentation of the user
configurations, these have been added to the new config
struct.

The new API function modem_cmd_handler_process has been
added to remove the need for the user to directly access
the process member of the internal context. This ensures
that the user is not encouraged to access any internal
context members.

Some whitespace errors exist in the modem_cmd_handler.c
file, these are outside of the scope of this PR. These
can be addressed in a later PR as they are not functional
changes.

Signed-off-by: Bjarki Arge Andreasen <baa@trackunit.com>
2023-04-11 11:42:00 +02:00
Jeppe Odgaard 4503377cac drivers: modem: delay after each AT command
Change logic in `modem_cmd_handler_setup_cmds` and
`modem_cmd_handler_setup_cmds_nolock` to always sleep
after each sent AT command.

The issue was found using a logic analyzer while debugging 'NO CARRIER'
from a BG95 modem while being in data mode.
The reason 'NO CARRIER' occured was due to crosstalk to DTR which
terminated data mode.

The logic analyzer also revealed that without the delay the next AT
command is sent before the whole 'OK\r\n' is received. This is not
addressed in this commit.

Fixes https://github.com/zephyrproject-rtos/zephyr/issues/47082

Signed-off-by: Jeppe Odgaard <jeppe.odgaard@prevas.dk>
2022-07-02 14:15:49 +02:00
Krzysztof Chruscinski 041f0e5379 all: logging: Remove log_strdup function
Logging v1 has been removed and log_strdup wrapper function is no
longer needed. Removing the function and its use in the tree.

Signed-off-by: Krzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
2022-06-23 13:42:23 +02:00
Gerard Marull-Paretas fb60aab245 drivers: migrate includes to <zephyr/...>
In order to bring consistency in-tree, migrate all drivers to the new
prefix <zephyr/...>. Note that the conversion has been scripted, refer
to #45388 for more details.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2022-05-06 19:58:21 +02:00
Xavier Chapron 5cc583bf3a drivers: modem: modem_cmd_handler.c: Drop cmd from buf if args are missing
In 90c6dc5e7f, a change was introduced to
allow modem commands determine if they have enough data or not.
In a situation where some data is missing, the command should return
-EAGAIN and this should lead to another call of the command with more
data.
In this commit, the argument parser was also allowed to return -EAGAIN
to request more data due to missing arguments.

However, this can't work because in cmd_handler_process_rx_buf() before
calling process_cmd():
- we make sure that a CR/LF has been found.
- we compute match_len which can't be greater than the distance to the
  next CR/LF.
Therefore, even if the command argument parser ask for more data by
returning -EAGAIN, next call will have the same value for match_len,
meaning that the parsing of argument will result in the same missing
argument situation.
This leads to an infinite loop of parsing the same data over and over in
an infinite loop.

This commit change this behavior to always drop the data in such a
situation. The command will not be answered and will therefore timeout,
but at least, next commands will correctly parse their returned data.

Signed-off-by: Xavier Chapron <xavier.chapron@stimio.fr>
2022-03-17 11:33:17 +01:00
Nazar Kazakov 9713f0d47c everywhere: fix typos
Fix a lot of typos

Signed-off-by: Nazar Kazakov <nazar.kazakov.work@gmail.com>
2022-03-14 20:22:24 -04:00
Guillaume Lager 4d777b43fd drivers: modem: Fix loop variables type
int was used regardless of the type used in the
end-loop condition

Signed-off-by: Guillaume Lager <g.lager@innoseis.com>
2022-02-04 11:19:28 +01:00
Kumar Gala a1a895e331 drivers: modem: Fix compiler warning
When building tests/drivers/build_all/modem on native_posix_64 we get:

	modem_cmd_handler.c:545:9: error: ret may be used
	uninitialized in this function
	[-Werror=maybe-uninitialized]

Fix by adding simple initialization of ret = 0 at start of function.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
2021-08-02 11:32:02 -05:00
Marcin Niestroj 1a4cb7e0e3 drivers: modem: add modem_cmd_send_ext()
There are currently modem_cmd_send() and modem_cmd_send_nolock()
functions, each with slightly different behavior regarding acquiring (or
not) sem_tx_lock. Introduce a generic function that will allow caller to
select behavior using flags.

While at it, add possibility to disable setting and unsetting command
handlers. This will be useful in situations when there are multiple
replies expected one after the other coming as a response to single
command. This is the case for example with ESP-AT driver, which expects
following data as response to AT+CIPSEND command:

  OK
  >

where 'OK' is handled by static CMD_RESP (so releasing response
semaphore right away), while '>' is handled by dynamic
CMD_HANDLER (which is releasing another semaphore). Keeping command
handlers in place allows to receive '>' without race condition because
of small period of time where command handlers are not set.

Convert modem_cmd_send_nolock() and modem_cmd_send() to static inline
functions, as they are just a specific invocation of
modem_cmd_send_ext() function.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2021-07-28 21:08:51 -04:00
Kumar Gala 27e33e25c9 drivers: modem: Fix build errors on 64-bit platforms
If the modem drivers are built on a 64-bit platform we get errors with
the logging code due to use of size_t.  Update to use %zX to handle this
correctly between 32-bit and 64-bit platforms.

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
2021-05-07 16:08:09 -05:00
Marcin Niestroj 5cbf2ec1f7 drivers: modem: fix sending with zero timeout and no semaphore
There was a regression introduced when reordering function parameters
check. It is valid to pass NULL semaphore with zero timeout, so fix
parameter check to respect that.

Fixes: 67976f8686 ("drivers: modem: verify send semaphore before
  taking any action")
Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-12-07 10:25:56 +02:00
Xavier Chapron 3d61989bc7 drivers: modem: modem_cmd_handler: Allow dynamic number of commands args
This is necessary to allow parsing of commands with dynamic number of
arguments.

Signed-off-by: Xavier Chapron <xavier.chapron@stimio.fr>
2020-12-03 17:37:48 -05:00
Marcin Niestroj 9fe279f744 drivers: modem: don't clear out cmd handlers if they were not setup
There is no point in clearing out command handlers if they were not
setup properly. Just skip to next instruction.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-12-01 11:15:19 -05:00
Marcin Niestroj eae32b7e7a drivers: modem: fix race condition when waiting on cmd reply
Command was sent first, then a semaphore was reset. This semaphore could
be released by received reply even before semaphore was reset. This is
quite unlikely, but possible result of race condition.

Move k_sem_reset() call before attempt to send command over modem
interface. This makes sure that receiving reply momentarily after
sending request will always be handled properly.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-12-01 11:15:19 -05:00
Marcin Niestroj 67976f8686 drivers: modem: verify send semaphore before taking any action
Semaphore argument is checked only after requested command is already
sent over modem interface. It makes little sense to return -EINVAL when
half of the requested operation (send) has already been done.

Check timeout and semaphore arguments just on the beginning of
function. Return -EINVAL early, before sending any data or taking any
locks.

Clear out 'sem' variable when there is no need to wait. Use this
variable later on as an indication to actually wait on semaphore or not.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-12-01 11:15:19 -05:00
Marcin Niestroj 1d25e9c6ae drivers: modem: constify modem_cmd and setup_cmd structures
modem_cmd and setup_cmd structures are used only to store static
information about commands to be sent and replies to be
received. Reference it as const, so that it is possible to define const
instances and save some RAM space by placing those definitions entirely
in ROM.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-11-24 12:59:50 +02:00
Marcin Niestroj 318cbe649a drivers: modem: cmd_handler: rework reading from interface
So far a dedicated buffer was used for data read from modem
interface. New net_bufs were allocated and filled later, which means
that data was lost when no more net_bufs were available in the pool.

Prevent data loss by allocating net_buf before attempting any read on
modem interface. Process incoming data in a loop as long as reading from
interface results in new data. Also remove dedicated buffer
(data->read_buf) and directly fill net_buf content instead. As a side
effect there are less memory copy operations and RAM usage is reduced.

Pre-allocated net_buf is now always appended to data->rx_buf. When there
was no (more) data read from interface to such net_buf, then this empty
net_buf will be on the end of data->rx_buf fragment list. Update
skipcrlf() and findcrlf() implementations to explicitly check for each
net_buf length, instead of blindly assuming them to have at least single
byte.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-10-27 09:24:38 -05:00
Marcin Niestroj 3d659a35bb drivers: modem: cmd_handler: split cmd_handler_process() implementation
cmd_handler_process() does two major things:

 - reads data from modem interface and fills data->rx_buf,
 - processes data in data->rx_buf.

Split implementation accordingly to two separate functions, which
improves readability (less automatic variables to follow at once) and
simplifies refactoring of each action.

No functional change was intended in this commit.

Signed-off-by: Marcin Niestroj <m.niestroj@grinn-global.com>
2020-10-27 09:24:38 -05:00
Benjamin Lindqvist 820bb07c81 drivers: modem: cmd_handler: Allow locking TX
A semaphore is used by modem_cmd_handler to protect against concurrent
UART access. This is only used for the duration of sending a command,
but there are cases when one wants to prevent UART access for other
reasons, such as when powering off the modem.

This commit exposes functionality for hogging this semaphore without
having to send a command. Furthermore, a non-locking equivalent for
modem_cmd_handler_setup_cmds is added which was previously missing.

Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
2020-10-21 10:15:45 +03:00
Benjamin Lindqvist 54cb2bcd41 drivers: modem: gsm_ppp: Enable start/stop
These changes enable applications to restart the networking stack which
was previously not possible without rebooting the device. This was a
major show-stopper because it made power management impossible, and
furthermore made it impossible to recover from a bad modem state without
rebooting.

This has been verified to work on a SIMCOM7600E modem, both with and
without CONFIG_GSM_MUX enabled.

Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
2020-10-19 18:29:02 +02:00
Benjamin Lindqvist 966932a033 drivers: modem: add forgotten log_strdup call
The char pointer that is logged could get scoped out and so should be
strduped before logging.

Signed-off-by: Benjamin Lindqvist <benjamin.lindqvist@endian.se>
2020-10-19 18:29:02 +02:00
Tobias Svehagen 0d50372ce9 drivers: modem: Add debug log for matching direct cmds
Add a log message for when a direct cmd is matched to ease debugging.

Signed-off-by: Tobias Svehagen <tobias.svehagen@gmail.com>
2020-10-02 11:35:47 +02:00
Kumar Gala a1b77fd589 zephyr: replace zephyr integer types with C99 types
git grep -l 'u\(8\|16\|32\|64\)_t' | \
		xargs sed -i "s/u\(8\|16\|32\|64\)_t/uint\1_t/g"
	git grep -l 's\(8\|16\|32\|64\)_t' | \
		xargs sed -i "s/s\(8\|16\|32\|64\)_t/int\1_t/g"

Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
2020-06-08 08:23:57 -05:00
Carles Cufi 94861a438b drivers: modem: Port to new timeout API
Port the internal modem API to the new timeout API, using the native
k_timeout_t.

Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
2020-05-07 11:01:55 +02:00
Tobias Svehagen 990ab00e30 drivers: modem: Add support for commands that don't have a line ending
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>
2020-03-11 23:48:06 +02:00
Jukka Rissanen ded0ea62a1 driver: modem: Print sent data if verbose debugging is enabled
User is currently able to enable verbose packet debugging for
received packets. This commit enables the same for sent packets.

Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
2020-03-10 15:20:02 +02:00
Michael Scott 90c6dc5e7f drivers: modem: cmd_handler: add return value to modem commands
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>
2020-02-10 12:29:41 +02:00
Michael Scott 5185b8cf40 drivers: modem: cmd_handler: honor num of params in parse_params
Modem commands are setup with arg_count to denote the number of params
to parse before returning.  Let's honor that setting and return once
we've parse them.

This fixes a run-on bug where the parser would find as many of the
parameters via the supplied delimiter as it could.

Signed-off-by: Michael Scott <mike@foundries.io>
2020-02-10 12:29:41 +02:00
Michael Scott 82dc1665af drivers: modem: cmd_handler: fix findcrlf() indentation
Missed during previous rework.

Signed-off-by: Michael Scott <mike@foundries.io>
2020-02-10 12:29:41 +02:00
Michael Scott 74bb1a9be9 drivers: modem: cmd_handler: remove extra comment
Remove extra comment left over from prototype driver.

Signed-off-by: Michael Scott <mike@foundries.io>
2020-02-10 12:29:41 +02:00
Michael Scott 44e977c467 drivers: modem: cmd_handler: save 1 char for NUL in match_buf
For parsing purposes we need to add a NUL to the end of match_buf.

When there is no CR/LF in the incoming rx bufs then we fill match_buf
to its max size.  This ended up with an off by one error which was
overflowing match_buf into the following data.

To account for this, let's fill the buffer to size - 1 so that we
leave room for the NUL at the end and stop corrupting data.

Signed-off-by: Michael Scott <mike@foundries.io>
2020-02-10 12:29:41 +02:00
Michael Scott f4b49fbb90 drivers: modem: cmd_handler: cleanup parse_params()
- rename buf_len to match_len for clarity
- pass in modem_cmd_handler_data instead of buffer pointer directly
- buffer adjustments for the command length are kept inside
  parse_params()

Signed-off-by: Michael Scott <mike@foundries.io>
2020-02-10 12:29:41 +02:00
Tobias Svehagen 8a9c9d43bf drivers: modem: Add support for different line endings
This makes it possible to handle devices that use different line
endings.

Signed-off-by: Tobias Svehagen <tobias.svehagen@gmail.com>
2020-02-05 23:31:56 +02:00
Michael Scott 02abddccd6 drivers: modem: cmd handler: introduce cmd handler driver layer
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>
2019-08-10 00:03:39 +02:00