Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/prj.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ CONFIG_PICOLIBC_IO_FLOAT=y
CONFIG_RING_BUFFER=y
CONFIG_REBOOT=y
CONFIG_EVENTFD=y
CONFIG_POSIX_C_LIB_EXT=y

# Segger RTT
CONFIG_USE_SEGGER_RTT=y
Expand Down
167 changes: 103 additions & 64 deletions app/src/sm_at_sms.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/
#define _POSIX_C_SOURCE 200809L /* for strdup() */
#include <zephyr/logging/log.h>
#include <zephyr/kernel.h>
#include <stdio.h>
#include <string.h>
#include <modem/sms.h>
#include <assert.h>
#include "sm_util.h"
#include "sm_at_host.h"

Expand All @@ -22,18 +24,47 @@
AT_SMS_SEND
};

static int sms_handle = -1;
static struct modem_pipe *sms_pipe;
static void cleanup_handler(struct k_work *work);
struct sm_sms_context {
int sms_handle;
struct modem_pipe *pipe;
uint16_t ref_number;
uint8_t total_msgs;
uint8_t count;
char *messages[MAX_CONCATENATED_MESSAGE];
struct k_work_delayable cleanup_work;
} static sm_sms_ctx = {
.sms_handle = -1,
.cleanup_work = Z_WORK_DELAYABLE_INITIALIZER(cleanup_handler),
};

static void sms_callback(struct sms_data *const data, void *context)
#define MSG(i, _) ctx->messages[i]
#define MESSAGES() LISTIFY(MAX_CONCATENATED_MESSAGE, MSG, (,))

Check warning on line 42 in app/src/sm_at_sms.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACE_BEFORE_TAB

app/src/sm_at_sms.c:42 please, no space before tabs

static const char *concatenated_fmt(int total_msgs)
{
static uint16_t ref_number;
static uint8_t total_msgs;
static uint8_t count;
static char messages[MAX_CONCATENATED_MESSAGE - 1][SMS_MAX_PAYLOAD_LEN_CHARS + 1];
static char rsp_buf[MAX_CONCATENATED_MESSAGE * SMS_MAX_PAYLOAD_LEN_CHARS + 64] = {0};
switch (total_msgs) {
case 1:
return "\r\n#XSMS: \"%02d-%02d-%02d %02d:%02d:%02d\",\""
"%s\",\"%s\"\r\n";
case 2:
return "\r\n#XSMS: \"%02d-%02d-%02d %02d:%02d:%02d\",\""
"%s\",\"%s%s\"\r\n";
case 3:
return "\r\n#XSMS: \"%02d-%02d-%02d %02d:%02d:%02d\",\""
"%s\",\"%s%s%s\"\r\n";
default:
/* This should not happen */
assert(false);
return NULL;
}
}

ARG_UNUSED(context);


static void sms_callback(struct sms_data *const data, void *context)
{
struct sm_sms_context *ctx = (struct sm_sms_context *)context;

if (data == NULL) {
LOG_WRN("NULL data");
Expand All @@ -44,77 +75,69 @@
struct sms_deliver_header *header = &data->header.deliver;

if (!header->concatenated.present) {
sprintf(rsp_buf,
"\r\n#XSMS: \"%02d-%02d-%02d %02d:%02d:%02d UTC%+03d:%02d\",\"",
header->time.year, header->time.month, header->time.day,
header->time.hour, header->time.minute, header->time.second,
header->time.timezone * 15 / 60,
abs(header->time.timezone) * 15 % 60);
strcat(rsp_buf, header->originating_address.address_str);
strcat(rsp_buf, "\",\"");
strcat(rsp_buf, data->payload);
strcat(rsp_buf, "\"\r\n");
urc_send_to(sms_pipe, "%s", rsp_buf);
urc_send_to(ctx->pipe,
"\r\n#XSMS: \"%02d-%02d-%02d %02d:%02d:%02d UTC%+03d:%02d\",\""
"%s\",\"%s\"\r\n",
header->time.year, header->time.month, header->time.day,
header->time.hour, header->time.minute, header->time.second,
header->time.timezone * 15 / 60,
abs(header->time.timezone) * 15 % 60,
header->originating_address.address_str, data->payload);
} else {
LOG_DBG("concatenated message %d, %d, %d",
header->concatenated.ref_number,
total_msgs = header->concatenated.total_msgs,
header->concatenated.total_msgs,
header->concatenated.seq_number);
/* ref_number and total_msgs should remain unchanged */
if (ref_number == 0) {
ref_number = header->concatenated.ref_number;
if (ctx->ref_number == 0) {
ctx->ref_number = header->concatenated.ref_number;
}
if (ref_number != header->concatenated.ref_number) {
if (ctx->ref_number != header->concatenated.ref_number) {
LOG_ERR("SMS concatenated message ref_number error: %d, %d",
ref_number, header->concatenated.ref_number);
ctx->ref_number, header->concatenated.ref_number);
goto done;
}
if (total_msgs == 0) {
total_msgs = header->concatenated.total_msgs;
if (ctx->total_msgs == 0) {
ctx->total_msgs = header->concatenated.total_msgs;
}
if (total_msgs != header->concatenated.total_msgs) {
if (ctx->total_msgs != header->concatenated.total_msgs) {
LOG_ERR("SMS concatenated message total_msgs error: %d, %d",
total_msgs, header->concatenated.total_msgs);
ctx->total_msgs, header->concatenated.total_msgs);
goto done;
}
if (total_msgs > MAX_CONCATENATED_MESSAGE) {
LOG_ERR("SMS concatenated message no memory: %d", total_msgs);
if (ctx->total_msgs > MAX_CONCATENATED_MESSAGE) {
LOG_ERR("SMS concatenated message no memory: %d", ctx->total_msgs);
goto done;
}
/* seq_number should start with 1 but could arrive in random order */
if (header->concatenated.seq_number == 0 ||
header->concatenated.seq_number > total_msgs) {
header->concatenated.seq_number > ctx->total_msgs) {
LOG_ERR("SMS concatenated message seq_number error: %d, %d",
header->concatenated.seq_number, total_msgs);
header->concatenated.seq_number, ctx->total_msgs);
goto done;
}
if (header->concatenated.seq_number == 1) {
sprintf(rsp_buf, "\r\n#XSMS: \"%02d-%02d-%02d %02d:%02d:%02d\",\"",
header->time.year, header->time.month, header->time.day,
header->time.hour, header->time.minute,
header->time.second);
strcat(rsp_buf, header->originating_address.address_str);
strcat(rsp_buf, "\",\"");
strcat(rsp_buf, data->payload);
count++;
} else {
strcpy(messages[header->concatenated.seq_number - 2],
data->payload);
count++;

char *msg = strdup(data->payload);

if (msg == NULL) {
LOG_ERR("Failed to allocate memory for SMS message");
goto done;
}
if (count == total_msgs) {
for (int i = 0; i < (total_msgs - 1); i++) {
strcat(rsp_buf, messages[i]);
}
strcat(rsp_buf, "\"\r\n");
urc_send_to(sms_pipe, "%s", rsp_buf);
ctx->messages[header->concatenated.seq_number -1] = msg;

Check failure on line 126 in app/src/sm_at_sms.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

SPACING

app/src/sm_at_sms.c:126 need consistent spacing around '-' (ctx:WxV)
ctx->count++;

if (ctx->count == ctx->total_msgs) {
urc_send_to(ctx->pipe, concatenated_fmt(ctx->total_msgs), header->time.year, header->time.month,

Check warning on line 130 in app/src/sm_at_sms.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

app/src/sm_at_sms.c:130 line length of 128 exceeds 100 columns
header->time.day, header->time.hour, header->time.minute,

Check warning on line 131 in app/src/sm_at_sms.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

app/src/sm_at_sms.c:131 line length of 101 exceeds 100 columns
header->time.second, header->originating_address.address_str,

Check warning on line 132 in app/src/sm_at_sms.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

LONG_LINE

app/src/sm_at_sms.c:132 line length of 105 exceeds 100 columns
MESSAGES());
} else {
/* Wait for more messages */
k_work_reschedule(&ctx->cleanup_work, K_MINUTES(5));
return;
}
done:
ref_number = 0;
total_msgs = 0;
count = 0;
k_work_reschedule(&ctx->cleanup_work, K_NO_WAIT);
}
} else if (data->type == SMS_TYPE_STATUS_REPORT) {
LOG_INF("Status report received");
Expand All @@ -123,29 +146,45 @@
}
}

static void cleanup_handler(struct k_work *work)
{
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
struct sm_sms_context *ctx = CONTAINER_OF(dwork, struct sm_sms_context, cleanup_work);

ctx->ref_number = 0;
ctx->total_msgs = 0;
ctx->count = 0;
for (int i = 0; i < MAX_CONCATENATED_MESSAGE; i++) {
if (ctx->messages[i]) {
free(ctx->messages[i]);
ctx->messages[i] = NULL;
}
}
}

static int do_sms_start(void)
{
int err = 0;

if (sms_handle >= 0) {
if (sm_sms_ctx.sms_handle >= 0) {
/* already registered */
return -EBUSY;
}

sms_handle = sms_register_listener(sms_callback, NULL);
if (sms_handle < 0) {
err = sms_handle;
sm_sms_ctx.sms_handle = sms_register_listener(sms_callback, &sm_sms_ctx);
if (sm_sms_ctx.sms_handle < 0) {
err = sm_sms_ctx.sms_handle;
LOG_ERR("SMS start error: %d", err);
sms_handle = -1;
sm_sms_ctx.sms_handle = -1;
}

return err;
}

static int do_sms_stop(void)
{
sms_unregister_listener(sms_handle);
sms_handle = -1;
sms_unregister_listener(sm_sms_ctx.sms_handle);
sm_sms_ctx.sms_handle = -1;

return 0;
}
Expand All @@ -154,7 +193,7 @@
{
int err;

if (sms_handle < 0) {
if (sm_sms_ctx.sms_handle < 0) {
LOG_ERR("SMS not registered");
return -EPERM;
}
Expand Down Expand Up @@ -182,7 +221,7 @@
if (op == AT_SMS_STOP) {
err = do_sms_stop();
} else if (op == AT_SMS_START) {
sms_pipe = sm_at_host_get_current_pipe();
sm_sms_ctx.pipe = sm_at_host_get_current_pipe();
err = do_sms_start();
} else if (op == AT_SMS_SEND) {
char number[SMS_MAX_ADDRESS_LEN_CHARS + 1];
Expand Down
Loading