net: lwm2m: Single instance read&write with CBOR
Raw CBOR content format support. Signed-off-by: Veijo Pesonen <veijo.pesonen@nordicsemi.no>
This commit is contained in:
parent
24e04a2159
commit
8fd283a788
|
@ -55,6 +55,10 @@ zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_JSON_SUPPORT
|
|||
zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_SENML_JSON_SUPPORT
|
||||
lwm2m_rw_senml_json.c
|
||||
)
|
||||
# CBOR support
|
||||
zephyr_library_sources_ifdef(CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||
lwm2m_rw_cbor.c
|
||||
)
|
||||
|
||||
# IPSO Objects
|
||||
zephyr_library_sources_ifdef(CONFIG_LWM2M_IPSO_TEMP_SENSOR
|
||||
|
|
|
@ -434,6 +434,13 @@ config LWM2M_COMPOSITE_PATH_LIST_SIZE
|
|||
help
|
||||
Define path list size for Composite Read and send operation.
|
||||
|
||||
config LWM2M_RW_CBOR_SUPPORT
|
||||
bool "support for CBOR writer [EXPERIMENTAL]"
|
||||
select ZCBOR
|
||||
select EXPERIMENTAL
|
||||
help
|
||||
Include support for writing CBOR data
|
||||
|
||||
config LWM2M_DEVICE_PWRSRC_MAX
|
||||
int "Maximum # of device power source records"
|
||||
default 5
|
||||
|
|
|
@ -51,6 +51,9 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
|||
#ifdef CONFIG_LWM2M_RW_JSON_SUPPORT
|
||||
#include "lwm2m_rw_json.h"
|
||||
#endif
|
||||
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||
#include "lwm2m_rw_cbor.h"
|
||||
#endif
|
||||
#ifdef CONFIG_LWM2M_RD_CLIENT_SUPPORT
|
||||
#include "lwm2m_rd_client.h"
|
||||
#endif
|
||||
|
@ -1603,6 +1606,12 @@ static int select_writer(struct lwm2m_output_context *out, uint16_t accept)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||
case LWM2M_FORMAT_APP_CBOR:
|
||||
out->writer = &cbor_writer;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
LOG_WRN("Unknown content type %u", accept);
|
||||
return -ENOMSG;
|
||||
|
@ -1642,6 +1651,12 @@ static int select_reader(struct lwm2m_input_context *in, uint16_t format)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||
case LWM2M_FORMAT_APP_CBOR:
|
||||
in->reader = &cbor_reader;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
LOG_WRN("Unknown content type %u", format);
|
||||
return -ENOMSG;
|
||||
|
@ -3706,6 +3721,11 @@ static int do_read_op(struct lwm2m_message *msg, uint16_t content_format)
|
|||
return do_read_op_senml_json(msg);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_LWM2M_RW_CBOR_SUPPORT)
|
||||
case LWM2M_FORMAT_APP_CBOR:
|
||||
return do_read_op_cbor(msg);
|
||||
#endif
|
||||
|
||||
default:
|
||||
LOG_ERR("Unsupported content-format: %u", content_format);
|
||||
return -ENOMSG;
|
||||
|
@ -4252,6 +4272,11 @@ static int do_write_op(struct lwm2m_message *msg,
|
|||
return do_write_op_senml_json(msg);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LWM2M_RW_CBOR_SUPPORT
|
||||
case LWM2M_FORMAT_APP_CBOR:
|
||||
return do_write_op_cbor(msg);
|
||||
#endif
|
||||
|
||||
default:
|
||||
LOG_ERR("Unsupported format: %u", format);
|
||||
return -ENOMSG;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define LWM2M_FORMAT_APP_OCTET_STREAM 42
|
||||
#define LWM2M_FORMAT_APP_EXI 47
|
||||
#define LWM2M_FORMAT_APP_JSON 50
|
||||
#define LWM2M_FORMAT_APP_CBOR 60
|
||||
#define LWM2M_FORMAT_APP_SEML_JSON 110
|
||||
#define LWM2M_FORMAT_OMA_PLAIN_TEXT 1541
|
||||
#define LWM2M_FORMAT_OMA_OLD_TLV 1542
|
||||
|
|
|
@ -140,6 +140,13 @@ BUILD_ASSERT(CONFIG_LWM2M_COAP_BLOCK_SIZE <= CONFIG_LWM2M_COAP_MAX_MSG_SIZE,
|
|||
#define CPKT_BUF_W_PTR(cpkt) ((cpkt)->data + (cpkt)->offset)
|
||||
#define CPKT_BUF_W_SIZE(cpkt) ((cpkt)->max_len - (cpkt)->offset)
|
||||
|
||||
#define CPKT_BUF_W_REGION(cpkt) CPKT_BUF_W_PTR(cpkt), CPKT_BUF_W_SIZE(cpkt)
|
||||
|
||||
/* Input context buffer util macros */
|
||||
#define ICTX_BUF_R_LEFT_SZ(i_ctx) ((i_ctx)->in_cpkt->max_len - (i_ctx)->offset)
|
||||
#define ICTX_BUF_R_PTR(i_ctx) ((i_ctx)->in_cpkt->data + (i_ctx)->offset)
|
||||
#define ICTX_BUF_R_REGION(i_ctx) ICTX_BUF_R_PTR(i_ctx), ICTX_BUF_R_LEFT_SZ(i_ctx)
|
||||
|
||||
struct lwm2m_engine_obj;
|
||||
struct lwm2m_message;
|
||||
|
||||
|
|
550
subsys/net/lib/lwm2m/lwm2m_rw_cbor.c
Normal file
550
subsys/net/lib/lwm2m/lwm2m_rw_cbor.c
Normal file
|
@ -0,0 +1,550 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define LOG_MODULE_NAME net_lwm2m_cbor
|
||||
#define LOG_LEVEL CONFIG_LWM2M_LOG_LEVEL
|
||||
|
||||
#include <logging/log.h>
|
||||
#include <sys/util.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <zcbor_common.h>
|
||||
#include <zcbor_decode.h>
|
||||
#include <zcbor_encode.h>
|
||||
|
||||
#include <net/lwm2m.h>
|
||||
#include "lwm2m_object.h"
|
||||
#include "lwm2m_rw_cbor.h"
|
||||
#include "lwm2m_engine.h"
|
||||
#include "lwm2m_util.h"
|
||||
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
#define CPKT_CBOR_W_SZ(pos, cpkt) ((size_t)(pos) - (size_t)(cpkt)->data - (size_t)(cpkt)->offset)
|
||||
|
||||
#define ICTX_CBOR_R_SZ(pos, ictx) ((size_t)pos - (size_t)(ictx)->in_cpkt->data - (ictx)->offset)
|
||||
|
||||
static int put_time(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int64_t value)
|
||||
{
|
||||
/* CBOR time output format is unspecified but SenML CBOR uses string format.
|
||||
* Let's stick into the same format with plain CBOR
|
||||
*/
|
||||
struct tm dt;
|
||||
char time_str[sizeof("1970-01-01T00:00:00-00:00")] = { 0 };
|
||||
int len;
|
||||
int str_sz;
|
||||
int tag_sz;
|
||||
bool ret;
|
||||
|
||||
if (gmtime_r((time_t *)&value, &dt) != &dt) {
|
||||
LOG_ERR("unable to convert from secs since Epoch to a date/time construct");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Time construct to a string. Time in UTC, offset to local time not known */
|
||||
len = snprintk(time_str, sizeof(time_str),
|
||||
"%04d-%02d-%02dT%02d:%02d:%02d-00:00",
|
||||
dt.tm_year+1900,
|
||||
dt.tm_mon+1,
|
||||
dt.tm_mday,
|
||||
dt.tm_hour,
|
||||
dt.tm_min,
|
||||
dt.tm_sec);
|
||||
|
||||
if (len < 0 || len > sizeof(time_str) - 1) {
|
||||
LOG_ERR("unable to form a date/time string");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
/* Are tags required? V1.1 leaves this unspecified but some servers require tags */
|
||||
ret = zcbor_tag_encode(states, ZCBOR_TAG_TIME_TSTR);
|
||||
|
||||
if (!ret) {
|
||||
LOG_ERR("unable to encode date/time string tag");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tag_sz = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
|
||||
out->out_cpkt->offset += tag_sz;
|
||||
|
||||
ret = zcbor_tstr_put_term(states, time_str);
|
||||
if (!ret) {
|
||||
LOG_ERR("unable to encode date/time string");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
str_sz = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
|
||||
out->out_cpkt->offset += str_sz;
|
||||
|
||||
return tag_sz + str_sz;
|
||||
}
|
||||
|
||||
static int put_s64(struct lwm2m_output_context *out,
|
||||
struct lwm2m_obj_path *path, int64_t value)
|
||||
{
|
||||
int payload_len;
|
||||
bool ret;
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
ret = zcbor_int64_encode(states, &value);
|
||||
|
||||
if (ret) {
|
||||
payload_len = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
out->out_cpkt->offset += payload_len;
|
||||
} else {
|
||||
LOG_ERR("unable to encode a long long integer value");
|
||||
payload_len = -ENOMEM;
|
||||
}
|
||||
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int put_s32(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int32_t value)
|
||||
{
|
||||
int payload_len;
|
||||
bool ret;
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
ret = zcbor_int32_encode(states, &value);
|
||||
|
||||
if (ret) {
|
||||
payload_len = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
out->out_cpkt->offset += payload_len;
|
||||
} else {
|
||||
LOG_ERR("unable to encode an integer value");
|
||||
payload_len = -ENOMEM;
|
||||
}
|
||||
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int put_s16(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int16_t value)
|
||||
{
|
||||
return put_s32(out, path, value);
|
||||
}
|
||||
|
||||
static int put_s8(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, int8_t value)
|
||||
{
|
||||
return put_s32(out, path, value);
|
||||
}
|
||||
|
||||
static int put_float(struct lwm2m_output_context *out,
|
||||
struct lwm2m_obj_path *path, double *value)
|
||||
{
|
||||
int payload_len;
|
||||
bool ret;
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
ret = zcbor_float64_encode(states, value);
|
||||
|
||||
if (ret) {
|
||||
payload_len = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
out->out_cpkt->offset += payload_len;
|
||||
} else {
|
||||
payload_len = -ENOMEM;
|
||||
}
|
||||
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int put_string(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
int payload_len;
|
||||
bool ret;
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
ret = zcbor_tstr_encode_ptr(states, buf, buflen);
|
||||
|
||||
if (ret) {
|
||||
payload_len = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
out->out_cpkt->offset += payload_len;
|
||||
} else {
|
||||
payload_len = -ENOMEM;
|
||||
}
|
||||
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int put_opaque(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
|
||||
char *buf, size_t buflen)
|
||||
{
|
||||
int payload_len;
|
||||
bool ret;
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
ret = zcbor_bstr_encode_ptr(states, buf, buflen);
|
||||
|
||||
if (ret) {
|
||||
payload_len = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
out->out_cpkt->offset += payload_len;
|
||||
} else {
|
||||
payload_len = -ENOMEM;
|
||||
}
|
||||
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int put_bool(struct lwm2m_output_context *out, struct lwm2m_obj_path *path, bool value)
|
||||
{
|
||||
int payload_len;
|
||||
bool ret;
|
||||
|
||||
ZCBOR_STATE_E(states, 0, CPKT_BUF_W_PTR(out->out_cpkt), CPKT_BUF_W_SIZE(out->out_cpkt), 1);
|
||||
|
||||
ret = zcbor_bool_encode(states, &value);
|
||||
|
||||
if (ret) {
|
||||
payload_len = CPKT_CBOR_W_SZ(states[0].payload, out->out_cpkt);
|
||||
out->out_cpkt->offset += payload_len;
|
||||
} else {
|
||||
payload_len = -ENOMEM;
|
||||
}
|
||||
|
||||
return payload_len;
|
||||
}
|
||||
|
||||
static int put_objlnk(struct lwm2m_output_context *out, struct lwm2m_obj_path *path,
|
||||
struct lwm2m_objlnk *value)
|
||||
{
|
||||
char objlnk[sizeof("65535:65535")] = { 0 };
|
||||
|
||||
snprintk(objlnk, sizeof(objlnk), "%" PRIu16 ":%" PRIu16 "", value->obj_id, value->obj_inst);
|
||||
|
||||
return put_string(out, path, objlnk, strlen(objlnk) + 1);
|
||||
}
|
||||
|
||||
static int get_s64(struct lwm2m_input_context *in, int64_t *value)
|
||||
{
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_int64_decode(states, value)) {
|
||||
LOG_WRN("unable to decode a 64-bit integer value");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
int len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
|
||||
in->offset += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int get_s32(struct lwm2m_input_context *in, int32_t *value)
|
||||
{
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_int32_decode(states, value)) {
|
||||
LOG_WRN("unable to decode a 32-bit integer value, err: %d",
|
||||
states->constant_state->error);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
int len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
|
||||
in->offset += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int get_float(struct lwm2m_input_context *in, double *value)
|
||||
{
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_float_decode(states, value)) {
|
||||
LOG_ERR("unable to decode a floating-point value");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
int len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
|
||||
in->offset += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int get_string(struct lwm2m_input_context *in, uint8_t *value, size_t buflen)
|
||||
{
|
||||
struct zcbor_string hndl;
|
||||
int len;
|
||||
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_tstr_decode(states, &hndl)) {
|
||||
LOG_WRN("unable to decode a string");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
len = MIN(buflen-1, hndl.len);
|
||||
|
||||
memcpy(value, hndl.value, len);
|
||||
|
||||
value[len] = '\0';
|
||||
|
||||
len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
|
||||
in->offset += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/* Gets time decoded as a numeric string.
|
||||
*
|
||||
* return 0 on success, -EBADMSG if decoding fails or -EFAIL if value is invalid
|
||||
*/
|
||||
static int get_time_string(struct lwm2m_input_context *in, int64_t *value)
|
||||
{
|
||||
char time_str[sizeof("4294967295")] = { 0 };
|
||||
struct zcbor_string hndl = { .value = time_str, .len = sizeof(time_str) - 1 };
|
||||
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_tstr_decode(states, &hndl)) {
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
/* TODO: decode date/time string */
|
||||
LOG_DBG("decoding a date/time string not supported");
|
||||
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* Gets time decoded as a numerical.
|
||||
*
|
||||
* return 0 on success, -EBADMSG if decoding fails
|
||||
*/
|
||||
static int get_time_numerical(struct lwm2m_input_context *in, int64_t *value)
|
||||
{
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_int64_decode(states, value)) {
|
||||
LOG_WRN("unable to decode seconds since Epoch");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_time(struct lwm2m_input_context *in, int64_t *value)
|
||||
{
|
||||
uint32_t tag;
|
||||
int tag_sz = 0;
|
||||
int data_len;
|
||||
int ret;
|
||||
bool success;
|
||||
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
success = zcbor_tag_decode(states, &tag);
|
||||
|
||||
if (success) {
|
||||
tag_sz = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
in->offset += tag_sz;
|
||||
|
||||
switch (tag) {
|
||||
case ZCBOR_TAG_TIME_NUM:
|
||||
ret = get_time_numerical(in, value);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
case ZCBOR_TAG_TIME_TSTR:
|
||||
ret = get_time_string(in, value);
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_WRN("expected tagged date/time, got tag %" PRIu32 "", tag);
|
||||
return -EBADMSG;
|
||||
}
|
||||
} else { /* Assumption is that tags are optional */
|
||||
|
||||
/* Let's assume numeric string but in case that fails falls go back to numerical */
|
||||
ret = get_time_string(in, value);
|
||||
if (ret == -EBADMSG) {
|
||||
ret = get_time_numerical(in, value);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
data_len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
in->offset += data_len;
|
||||
|
||||
return tag_sz + data_len;
|
||||
|
||||
error:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_bool(struct lwm2m_input_context *in, bool *value)
|
||||
{
|
||||
ZCBOR_STATE_D(states, 0, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
if (!zcbor_bool_decode(states, value)) {
|
||||
LOG_WRN("unable to decode a boolean value");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
int len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
|
||||
in->offset += len;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int get_opaque(struct lwm2m_input_context *in, uint8_t *value, size_t buflen,
|
||||
struct lwm2m_opaque_context *opaque, bool *last_block)
|
||||
{
|
||||
struct zcbor_string_fragment hndl = { 0 };
|
||||
int ret;
|
||||
|
||||
ZCBOR_STATE_D(states, 1, ICTX_BUF_R_PTR(in), ICTX_BUF_R_LEFT_SZ(in), 1);
|
||||
|
||||
/* Get the CBOR header only on first read. */
|
||||
if (opaque->remaining == 0) {
|
||||
ret = zcbor_bstr_start_decode_fragment(states, &hndl);
|
||||
|
||||
if (!ret) {
|
||||
LOG_WRN("unable to decode opaque data header");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
opaque->len = hndl.total_len;
|
||||
opaque->remaining = hndl.total_len;
|
||||
|
||||
int len = ICTX_CBOR_R_SZ(states[0].payload, in);
|
||||
|
||||
in->offset += len;
|
||||
}
|
||||
|
||||
return lwm2m_engine_get_opaque_more(in, value, buflen, opaque, last_block);
|
||||
}
|
||||
|
||||
static int get_objlnk(struct lwm2m_input_context *in, struct lwm2m_objlnk *value)
|
||||
{
|
||||
char objlnk[sizeof("65535:65535")] = { 0 };
|
||||
char *end;
|
||||
char *idp = objlnk;
|
||||
|
||||
value->obj_id = LWM2M_OBJLNK_MAX_ID;
|
||||
value->obj_inst = LWM2M_OBJLNK_MAX_ID;
|
||||
|
||||
int len = get_string(in, objlnk, sizeof(objlnk) - 1);
|
||||
|
||||
|
||||
for (int idx = 0; idx < 2; idx++) {
|
||||
errno = 0;
|
||||
|
||||
unsigned long id = strtoul(idp, &end, 10);
|
||||
|
||||
idp = end;
|
||||
|
||||
if ((!id && errno == ERANGE) || id > LWM2M_OBJLNK_MAX_ID) {
|
||||
LOG_WRN("decoded id %lu out of range[0..65535]", id);
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
switch (idx) {
|
||||
case 0:
|
||||
value->obj_id = id;
|
||||
continue;
|
||||
case 1:
|
||||
value->obj_inst = id;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (value->obj_inst != LWM2M_OBJLNK_MAX_ID && (value->obj_inst == LWM2M_OBJLNK_MAX_ID)) {
|
||||
LOG_WRN("decoded obj inst id without obj id");
|
||||
return -EBADMSG;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
const struct lwm2m_writer cbor_writer = {
|
||||
.put_s8 = put_s8,
|
||||
.put_s16 = put_s16,
|
||||
.put_s32 = put_s32,
|
||||
.put_s64 = put_s64,
|
||||
.put_string = put_string,
|
||||
.put_float = put_float,
|
||||
.put_time = put_time,
|
||||
.put_bool = put_bool,
|
||||
.put_opaque = put_opaque,
|
||||
.put_objlnk = put_objlnk,
|
||||
};
|
||||
|
||||
const struct lwm2m_reader cbor_reader = {
|
||||
.get_s32 = get_s32,
|
||||
.get_s64 = get_s64,
|
||||
.get_time = get_time,
|
||||
.get_string = get_string,
|
||||
.get_float = get_float,
|
||||
.get_bool = get_bool,
|
||||
.get_opaque = get_opaque,
|
||||
.get_objlnk = get_objlnk,
|
||||
};
|
||||
|
||||
int do_read_op_cbor(struct lwm2m_message *msg)
|
||||
{
|
||||
/* Can only return single resource */
|
||||
if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
|
||||
return -EPERM;
|
||||
} else if (msg->path.level > LWM2M_PATH_LEVEL_RESOURCE_INST) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
return lwm2m_perform_read_op(msg, LWM2M_FORMAT_APP_CBOR);
|
||||
}
|
||||
|
||||
int do_write_op_cbor(struct lwm2m_message *msg)
|
||||
{
|
||||
struct lwm2m_engine_obj_inst *obj_inst = NULL;
|
||||
struct lwm2m_engine_obj_field *obj_field;
|
||||
struct lwm2m_engine_res *res = NULL;
|
||||
struct lwm2m_engine_res_inst *res_inst = NULL;
|
||||
int ret;
|
||||
uint8_t created = 0U;
|
||||
|
||||
ret = lwm2m_get_or_create_engine_obj(msg, &obj_inst, &created);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lwm2m_engine_validate_write_access(msg, obj_inst, &obj_field);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = lwm2m_engine_get_create_res_inst(&msg->path, &res, &res_inst);
|
||||
if (ret < 0) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (msg->path.level < LWM2M_PATH_LEVEL_RESOURCE) {
|
||||
msg->path.level = LWM2M_PATH_LEVEL_RESOURCE;
|
||||
}
|
||||
|
||||
return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg);
|
||||
}
|
18
subsys/net/lib/lwm2m/lwm2m_rw_cbor.h
Normal file
18
subsys/net/lib/lwm2m/lwm2m_rw_cbor.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef LWM2M_RW_CBOR_H_
|
||||
#define LWM2M_RW_CBOR_H_
|
||||
|
||||
#include "lwm2m_object.h"
|
||||
|
||||
extern const struct lwm2m_writer cbor_writer;
|
||||
extern const struct lwm2m_reader cbor_reader;
|
||||
|
||||
int do_read_op_cbor(struct lwm2m_message *msg);
|
||||
int do_write_op_cbor(struct lwm2m_message *msg);
|
||||
|
||||
#endif /* LWM2M_RW_CBOR_H_ */
|
Loading…
Reference in a new issue