Skip to content

Commit

Permalink
lib: sms: Support for characters in hex format
Browse files Browse the repository at this point in the history
Added support for giving data as binary but sending to network is
still always occuring in 7bit GSM encoding.
This is required by certification to send certain special characters
that are not available in ASCII and 0x00 which is '@' sign in
7bit GSM encoding.

Modem shell also updated to support new input data format.

"SMS subscriber" library renamed to "SMS" library.

Jira: MOSH-492

Signed-off-by: Tommi Rantanen <tommi.rantanen@nordicsemi.no>
  • Loading branch information
trantanen committed Aug 23, 2023
1 parent 475b583 commit d9211de
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 47 deletions.
8 changes: 5 additions & 3 deletions doc/nrf/libraries/modem/sms.rst
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
.. _sms_readme:

SMS subscriber
##############
SMS
###

.. contents::
:local:
:depth: 2

The SMS subscriber module acts as a unique and global client in the system that can dispatch SMS notifications to many subscribers, which makes it possible for more than one module to receive SMS messages.
The SMS library acts as a unique and global client in the system that can dispatch SMS notifications to many subscribers,
which makes it possible for more than one module to receive SMS messages.
In addition, the library has functions for sending SMS messages.

The module provides functions to register and unregister SMS listeners, which are the modules that need to send or receive SMS messages.
Each listener is identified by a unique handle and receives the SMS data and metadata through a callback function.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ Cellular samples (renamed from nRF9160 samples)
* Added:

* Support for accessing nRF Cloud services using CoAP through the :ref:`lib_nrf_cloud_coap` library.
* Support for GSM 7bit encoded hexadecimal string in SMS messages.

* Updated:

Expand Down Expand Up @@ -588,6 +589,12 @@ Modem libraries

* Updated the :c:func:`modem_key_mgmt_cmp` function to return ``1`` if the buffer length does not match the certificate length.

* :ref:`sms_readme`:

* Added:

* Support for providing input text as a GSM 7bit encoded hexadecimal string to send some special characters that cannot be sent using ASCII string.

Libraries for networking
------------------------

Expand Down
48 changes: 45 additions & 3 deletions include/modem/sms.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ enum sms_type {
SMS_TYPE_STATUS_REPORT
};

/**
* @brief SMS data type.
*/
enum sms_data_type {
/** @brief ASCII string with ISO-8859-15 extension. */
SMS_DATA_TYPE_ASCII,
/** @brief GSM 7 bit Default Alphabet as specified in 3GPP TS 23.038 Section 6.2. */
SMS_DATA_TYPE_GSM7BIT,
};

/**
* @brief Maximum length of SMS in number of characters
* as specified in 3GPP TS 23.038 Section 4 and Section 6.1.2.1.1.
Expand Down Expand Up @@ -189,15 +199,18 @@ int sms_register_listener(sms_callback_t listener, void *context);
void sms_unregister_listener(int handle);

/**
* @brief Send SMS message.
* @brief Send SMS message as ASCII string with ISO-8859-15 extension.
*
* @details Sending is done with GSM 7bit encoding used to encode textual SMS messages.
* SMS-SUBMIT message is specified in 3GPP TS 23.040 Section 9.2.2.2 and data encoding
* in 3GPP TS 23.038 Section 4 and Section 6.2.
* This function doesn't support sending of 8bit binary data messages or UCS2 encoded text.
*
* This function does the same as if @c sms_send would be called with SMS_DATA_TYPE_ASCII type.
*
* This function doesn't support sending of 8 bit binary data messages or UCS2 encoded text.
*
* @param[in] number Recipient number in international format.
* @param[in] text Text to be sent.
* @param[in] text Text to be sent as ASCII string with ISO-8859-15 extension.
*
* @retval -EINVAL Invalid parameter.
* @return 0 on success, otherwise error code.
Expand All @@ -207,6 +220,35 @@ void sms_unregister_listener(int handle);
*/
int sms_send_text(const char *number, const char *text);

/**
* @brief Send SMS message in given message type.
*
* @details The message is sent with GSM 7bit encoding used to encode textual SMS messages.
* SMS-SUBMIT message is specified in 3GPP TS 23.040 Section 9.2.2.2 and data encoding
* in 3GPP TS 23.038 Section 4 and Section 6.2.
*
* If @c type is set to SMS_DATA_TYPE_GSM7BIT, input data is treated as string of hexadecimal
* characters where each pair of two characters form a single byte. Those bytes are treated as
* GSM 7 bit Default Alphabet as specified in 3GPP TS 23.038 Section 6.2.
*
* This function does not support sending of 8 bit binary data messages or UCS2 encoded text.
*
* Concatenated messages are not supported in this function.
*
* @param[in] number Recipient number in international format.
* @param[in] data Data to be sent.
* @param[in] data_len Data length.
* @param[in] type Input data type.
*
* @retval -EINVAL Invalid parameter.
* @retval -E2BIG Too much data.
* @return 0 on success, otherwise error code.
* A positive value on AT error with "ERROR", "+CME ERROR", and "+CMS ERROR" responses.
* The type can be resolved with @c nrf_modem_at_err_type and
* the error value with @c nrf_modem_at_err.
*/
int sms_send(const char *number, const uint8_t *data, uint16_t data_len, enum sms_data_type type);

/** @} */

#ifdef __cplusplus
Expand Down
14 changes: 13 additions & 1 deletion lib/sms/sms.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#if defined(CONFIG_LTE_LINK_CONTROL)
#include <modem/lte_lc.h>
#endif
#include <modem/sms.h>

#include "sms_submit.h"
#include "sms_deliver.h"
Expand Down Expand Up @@ -375,7 +376,18 @@ void sms_unregister_listener(int handle)

int sms_send_text(const char *number, const char *text)
{
return sms_submit_send(number, text);
if (text == NULL) {
return -EINVAL;
}
return sms_send(number, text, strlen(text), SMS_DATA_TYPE_ASCII);
}

int sms_send(const char *number, const uint8_t *data, uint16_t data_len, enum sms_data_type type)
{
if (data == NULL) {
return -EINVAL;
}
return sms_submit_send(number, data, data_len, type);
}

#if defined(CONFIG_LTE_LINK_CONTROL)
Expand Down
49 changes: 34 additions & 15 deletions lib/sms/sms_submit.c
Original file line number Diff line number Diff line change
Expand Up @@ -310,15 +310,17 @@ static int sms_submit_concat(
return err;
}

int sms_submit_send(const char *number, const char *text)
int sms_submit_send(
const char *number,
const uint8_t *data,
uint16_t data_len,
enum sms_data_type type)
{
static const char empty_string[] = "";
int err;
uint8_t encoded_number[SMS_MAX_ADDRESS_LEN_CHARS + 1];
uint8_t encoded_number_size;
uint8_t encoded_number_size_octets = SMS_MAX_ADDRESS_LEN_CHARS + 1;
uint8_t size = 0;
uint16_t text_size;
uint8_t encoded_data_size_octets = 0;
uint8_t encoded_data_size_septets = 0;
uint8_t concat_msg_count = 0;
Expand All @@ -327,11 +329,13 @@ int sms_submit_send(const char *number, const char *text)
LOG_ERR("SMS number not given but NULL");
return -EINVAL;
}
if (text == NULL) {
text = empty_string;
}
__ASSERT_NO_MSG(data != NULL);

LOG_DBG("Sending SMS to number=%s, text='%s'", number, text);
if (type == SMS_DATA_TYPE_ASCII) {
LOG_DBG("Sending SMS to number=%s, text='%s', data_len=%d", number, data, data_len);
} else {
LOG_DBG("Sending SMS to number=%s, data_len=%d", number, data_len);
}

/* Encode number into format required in SMS header */
encoded_number_size = strlen(number);
Expand All @@ -341,23 +345,38 @@ int sms_submit_send(const char *number, const char *text)
return err;
}

/* Encode text into GSM 7bit encoding */
text_size = strlen(text);
size = string_conversion_ascii_to_gsm7bit(
text, text_size, sms_payload_tmp,
&encoded_data_size_octets, &encoded_data_size_septets, true);
/* Encode data into GSM 7bit encoding */

if (type == SMS_DATA_TYPE_ASCII) {
size = string_conversion_ascii_to_gsm7bit(
data, data_len, sms_payload_tmp,
&encoded_data_size_octets, &encoded_data_size_septets, true);
} else {
__ASSERT_NO_MSG(type == SMS_DATA_TYPE_GSM7BIT);
if (data_len > SMS_MAX_PAYLOAD_LEN_CHARS) {
LOG_ERR("Maximum length (%d) for GMS 7bit encoded message exceeded %d",
SMS_MAX_PAYLOAD_LEN_CHARS, data_len);
return -E2BIG;
}

memcpy(sms_payload_tmp, data, data_len);
encoded_data_size_octets = string_conversion_7bit_sms_packing(
sms_payload_tmp, data_len);
encoded_data_size_septets = data_len;
size = data_len;
}

/* Check if this should be sent as concatenated SMS */
if (size < text_size) {
if (size < data_len) {
LOG_DBG("Entire message doesn't fit into one SMS message. Using concatenated SMS.");

/* Encode messages to get number of message parts required to send given text */
err = sms_submit_concat(text,
err = sms_submit_concat(data,
encoded_number, encoded_number_size, encoded_number_size_octets,
false, &concat_msg_count);

/* Then, encode and send message parts */
err = sms_submit_concat(text,
err = sms_submit_concat(data,
encoded_number, encoded_number_size, encoded_number_size_octets,
true, &concat_msg_count);
} else {
Expand Down
10 changes: 8 additions & 2 deletions lib/sms/sms_submit.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,17 @@
* SMS-SUBMIT message format is specified in 3GPP TS 23.040 chapter 9.2.2.2.
*
* @param[in] number Recipient number.
* @param[in] text Text to be sent.
* @param[in] data Data to be sent.
* @param[in] data_len Data length.
* @param[in] type Input data type.
*
* @retval -EINVAL Invalid parameter.
* @return Zero on success, otherwise error code.
*/
int sms_submit_send(const char *number, const char *text);
int sms_submit_send(
const char *number,
const uint8_t *data,
uint16_t data_len,
enum sms_data_type type);

#endif
40 changes: 36 additions & 4 deletions samples/cellular/modem_shell/src/sms/sms.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "sms.h"
#include "mosh_defines.h"
#include "mosh_print.h"
#include "str_utils.h"

#define PAYLOAD_BUF_SIZE 160
#define SMS_HANDLE_NONE -1
Expand Down Expand Up @@ -99,27 +100,58 @@ int sms_unregister(void)
}

/* Function name is not sms_send() because it's reserved by SMS library. */
int sms_send_msg(char *number, char *text)
int sms_send_msg(char *number, char *data, enum sms_data_type type)
{
int ret;
uint16_t data_len;
uint16_t data_bin_len;
uint8_t *data_bin;

if (number == NULL || strlen(number) == 0) {
mosh_error("Number not given");
return -EINVAL;
}
if (text == NULL || strlen(text) == 0) {
if (data == NULL || strlen(data) == 0) {
mosh_error("Text not given");
return -EINVAL;
}

mosh_print("Sending SMS to number=%s, text='%s'", number, text);
mosh_print("Sending SMS to number=%s, text='%s'", number, data);
if (type == SMS_DATA_TYPE_GSM7BIT) {
mosh_print("Input text is in GSM 7bit format");
}

ret = sms_register();
if (ret != 0) {
return ret;
}

ret = sms_send_text(number, text);
if (type == SMS_DATA_TYPE_GSM7BIT) {
/* Process data to be sent if it's in hex format */
data_len = strlen(data);
if (data_len % 2 != 0) {
mosh_error(
"Input data for 'gsm7bit' must be divisible by two in length (%d)",
data_len);
return -EINVAL;
}
data_bin_len = data_len / 2;
data_bin = k_malloc(data_bin_len);
if (data_bin != NULL) {
data_bin_len = str_hex_to_bytes(
data, strlen(data), data_bin, data_bin_len);

ret = sms_send(number, data_bin, data_bin_len, SMS_DATA_TYPE_GSM7BIT);
k_free(data_bin);
} else {
mosh_error("Out of memory when reserving buffer for hex data");
return -ENOMEM;
}
} else {
__ASSERT_NO_MSG(type == SMS_DATA_TYPE_ASCII);
ret = sms_send_text(number, data);
}

if (ret) {
mosh_error("Sending SMS failed with error: %d", ret);
}
Expand Down
2 changes: 1 addition & 1 deletion samples/cellular/modem_shell/src/sms/sms.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

int sms_register(void);
int sms_unregister(void);
int sms_send_msg(char *number, char *data);
int sms_send_msg(char *number, char *text, enum sms_data_type type);
int sms_recv(bool arg_receive_start);

#endif /* MOSH_SMS_H */
Loading

0 comments on commit d9211de

Please sign in to comment.