diff --git a/include/net/lwm2m.h b/include/net/lwm2m.h index 4b11c4110d6..77b8edde4ae 100644 --- a/include/net/lwm2m.h +++ b/include/net/lwm2m.h @@ -117,12 +117,16 @@ struct lwm2m_ctx { * lwm2m_engine_register_pre_write_callback() * * @param[in] obj_inst_id Object instance ID generating the callback. + * @param[in] res_id Resource ID generating the callback. + * @param[in] res_inst_id Resource instance ID generating the callback + * (typically 0 for non-multi instance resources). * @param[out] data_len Length of the data buffer. * * @return Callback returns a pointer to the data buffer or NULL for failure. */ typedef void *(*lwm2m_engine_get_data_cb_t)(u16_t obj_inst_id, - size_t *data_len); + u16_t res_id, u16_t res_inst_id, + size_t *data_len); /** * @brief Asynchronous callback when data has been set to a resource buffer. @@ -135,6 +139,9 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(u16_t obj_inst_id, * lwm2m_engine_register_post_write_callback() * * @param[in] obj_inst_id Object instance ID generating the callback. + * @param[in] res_id Resource ID generating the callback. + * @param[in] res_inst_id Resource instance ID generating the callback + * (typically 0 for non-multi instance resources). * @param[in] data Pointer to data. * @param[in] data_len Length of the data. * @param[in] last_block Flag used during block transfer to indicate the last @@ -147,8 +154,9 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(u16_t obj_inst_id, * reason of failure or 0 for success. */ typedef int (*lwm2m_engine_set_data_cb_t)(u16_t obj_inst_id, - u8_t *data, u16_t data_len, - bool last_block, size_t total_size); + u16_t res_id, u16_t res_inst_id, + u8_t *data, u16_t data_len, + bool last_block, size_t total_size); /** * @brief Asynchronous event notification callback. @@ -221,7 +229,7 @@ typedef int (*lwm2m_engine_user_cb_t)(u16_t obj_inst_id); * @return The newly added index of the power source. The index is used * for removing the power source, setting voltage or setting current. */ -int lwm2m_device_add_pwrsrc(u8_t pwr_src_type); /* returns index */ +__deprecated int lwm2m_device_add_pwrsrc(u8_t pwr_src_type); /** * @brief Remove power source previously registered in the LwM2M Device object. @@ -231,7 +239,7 @@ int lwm2m_device_add_pwrsrc(u8_t pwr_src_type); /* returns index */ * * @return 0 for success or negative in case of error. */ -int lwm2m_device_remove_pwrsrc(int index); +__deprecated int lwm2m_device_remove_pwrsrc(int index); /** * @brief Set power source voltage (in millivolts). @@ -242,7 +250,7 @@ int lwm2m_device_remove_pwrsrc(int index); * * @return 0 for success or negative in case of error. */ -int lwm2m_device_set_pwrsrc_voltage_mv(int index, int voltage_mv); +__deprecated int lwm2m_device_set_pwrsrc_voltage_mv(int index, int voltage_mv); /** * @brief Set power source current (in milliamps). @@ -253,7 +261,7 @@ int lwm2m_device_set_pwrsrc_voltage_mv(int index, int voltage_mv); * * @return 0 for success or negative in case of error. */ -int lwm2m_device_set_pwrsrc_current_ma(int index, int current_ma); +__deprecated int lwm2m_device_set_pwrsrc_current_ma(int index, int current_ma); /** * @brief Register a new error code with LwM2M Device object. @@ -772,6 +780,30 @@ int lwm2m_engine_set_res_data(char *pathstr, void *data_ptr, u16_t data_len, int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr, u16_t *data_len, u8_t *data_flags); +/** + * @brief Create a resource instance + * + * LwM2M clients use this function to create multi-resource instances: + * Example to create 0 instance of device available power sources: + * lwm2m_engine_create_res_inst("3/0/6/0"); + * + * @param[in] pathstr LwM2M path string "obj/obj-inst/res/res-inst" + * + * @return 0 for success or negative in case of error. + */ +int lwm2m_engine_create_res_inst(char *pathstr); + +/** + * @brief Delete a resource instance + * + * Use this function to remove an existing resource instance + * + * @param[in] pathstr LwM2M path string "obj/obj-inst/res/res-inst" + * + * @return 0 for success or negative in case of error. + */ +int lwm2m_engine_delete_res_inst(char *pathstr); + /** * @brief Start the LwM2M engine * diff --git a/samples/net/lwm2m_client/src/lwm2m-client.c b/samples/net/lwm2m_client/src/lwm2m-client.c index 1246ec50428..3a18cb36cdc 100644 --- a/samples/net/lwm2m_client/src/lwm2m-client.c +++ b/samples/net/lwm2m_client/src/lwm2m-client.c @@ -63,12 +63,16 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define LED_GPIO_PORT DT_ALIAS_LED0_GPIOS_CONTROLLER #define LED_GPIO_PIN DT_ALIAS_LED0_GPIOS_PIN -static int pwrsrc_bat; -static int pwrsrc_usb; -static int battery_voltage = 3800; -static int battery_current = 125; -static int usb_voltage = 5000; -static int usb_current = 900; +static u8_t bat_idx = LWM2M_DEVICE_PWR_SRC_TYPE_BAT_INT; +static int bat_mv = 3800; +static int bat_ma = 125; +static u8_t usb_idx = LWM2M_DEVICE_PWR_SRC_TYPE_USB; +static int usb_mv = 5000; +static int usb_ma = 900; +static u8_t bat_level = 95; +static u8_t bat_status = LWM2M_DEVICE_BATTERY_STATUS_CHARGING; +static int mem_free = 15; +static int mem_total = 25; static struct device *led_dev; static u32_t led_state; @@ -94,7 +98,8 @@ static u8_t firmware_buf[64]; #endif /* TODO: Move to a pre write hook that can handle ret codes once available */ -static int led_on_off_cb(u16_t obj_inst_id, u8_t *data, u16_t data_len, +static int led_on_off_cb(u16_t obj_inst_id, u16_t res_id, u16_t res_inst_id, + u8_t *data, u16_t data_len, bool last_block, size_t total_size) { int ret = 0; @@ -150,7 +155,7 @@ static int device_reboot_cb(u16_t obj_inst_id) /* Add an error for testing */ lwm2m_device_add_err(LWM2M_DEVICE_ERROR_LOW_POWER); /* Change the battery voltage for testing */ - lwm2m_device_set_pwrsrc_voltage_mv(pwrsrc_bat, --battery_voltage); + lwm2m_engine_set_s32("3/0/7/0", (bat_mv - 1)); return 0; } @@ -161,7 +166,7 @@ static int device_factory_default_cb(u16_t obj_inst_id) /* Add an error for testing */ lwm2m_device_add_err(LWM2M_DEVICE_ERROR_GPS_FAILURE); /* Change the USB current for testing */ - lwm2m_device_set_pwrsrc_current_ma(pwrsrc_usb, --usb_current); + lwm2m_engine_set_s32("3/0/8/1", (usb_ma - 1)); return 0; } @@ -183,7 +188,8 @@ static int firmware_update_cb(u16_t obj_inst_id) #endif -static void *temperature_get_buf(u16_t obj_inst_id, size_t *data_len) +static void *temperature_get_buf(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, size_t *data_len) { /* Last read temperature value, will use 25.5C if no sensor available */ static struct float32_value v = { 25, 500000 }; @@ -211,13 +217,15 @@ static void *temperature_get_buf(u16_t obj_inst_id, size_t *data_len) #if defined(CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT) -static void *firmware_get_buf(u16_t obj_inst_id, size_t *data_len) +static void *firmware_get_buf(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, size_t *data_len) { *data_len = sizeof(firmware_buf); return firmware_buf; } static int firmware_block_received_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { @@ -228,6 +236,7 @@ static int firmware_block_received_cb(u16_t obj_inst_id, #endif static int timer_digital_state_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { @@ -291,34 +300,30 @@ static int lwm2m_setup(void) LWM2M_RES_DATA_FLAG_RO); lwm2m_engine_register_exec_callback("3/0/4", device_reboot_cb); lwm2m_engine_register_exec_callback("3/0/5", device_factory_default_cb); - lwm2m_engine_set_u8("3/0/9", 95); /* battery level */ - lwm2m_engine_set_u32("3/0/10", 15); /* mem free */ + lwm2m_engine_set_res_data("3/0/9", &bat_level, sizeof(bat_level), 0); + lwm2m_engine_set_res_data("3/0/10", &mem_free, sizeof(mem_free), 0); lwm2m_engine_set_res_data("3/0/17", CLIENT_DEVICE_TYPE, sizeof(CLIENT_DEVICE_TYPE), LWM2M_RES_DATA_FLAG_RO); lwm2m_engine_set_res_data("3/0/18", CLIENT_HW_VER, sizeof(CLIENT_HW_VER), LWM2M_RES_DATA_FLAG_RO); - lwm2m_engine_set_u8("3/0/20", LWM2M_DEVICE_BATTERY_STATUS_CHARGING); - lwm2m_engine_set_u32("3/0/21", 25); /* mem total */ + lwm2m_engine_set_res_data("3/0/20", &bat_status, sizeof(bat_status), 0); + lwm2m_engine_set_res_data("3/0/21", &mem_total, sizeof(mem_total), 0); - pwrsrc_bat = lwm2m_device_add_pwrsrc(LWM2M_DEVICE_PWR_SRC_TYPE_BAT_INT); - if (pwrsrc_bat < 0) { - LOG_ERR("LWM2M battery power source enable error (err:%d)", - pwrsrc_bat); - return pwrsrc_bat; - } - lwm2m_device_set_pwrsrc_voltage_mv(pwrsrc_bat, battery_voltage); - lwm2m_device_set_pwrsrc_current_ma(pwrsrc_bat, battery_current); - - pwrsrc_usb = lwm2m_device_add_pwrsrc(LWM2M_DEVICE_PWR_SRC_TYPE_USB); - if (pwrsrc_usb < 0) { - LOG_ERR("LWM2M usb power source enable error (err:%d)", - pwrsrc_usb); - return pwrsrc_usb; - } - lwm2m_device_set_pwrsrc_voltage_mv(pwrsrc_usb, usb_voltage); - lwm2m_device_set_pwrsrc_current_ma(pwrsrc_usb, usb_current); + /* add power source resource instances */ + lwm2m_engine_create_res_inst("3/0/6/0"); + lwm2m_engine_set_res_data("3/0/6/0", &bat_idx, sizeof(bat_idx), 0); + lwm2m_engine_create_res_inst("3/0/7/0"); + lwm2m_engine_set_res_data("3/0/7/0", &bat_mv, sizeof(bat_mv), 0); + lwm2m_engine_create_res_inst("3/0/8/0"); + lwm2m_engine_set_res_data("3/0/8/0", &bat_ma, sizeof(bat_ma), 0); + lwm2m_engine_create_res_inst("3/0/6/1"); + lwm2m_engine_set_res_data("3/0/6/1", &usb_idx, sizeof(usb_idx), 0); + lwm2m_engine_create_res_inst("3/0/7/1"); + lwm2m_engine_set_res_data("3/0/7/1", &usb_mv, sizeof(usb_mv), 0); + lwm2m_engine_create_res_inst("3/0/8/1"); + lwm2m_engine_set_res_data("3/0/8/1", &usb_ma, sizeof(usb_ma), 0); /* setup FIRMWARE object */ diff --git a/subsys/net/lib/lwm2m/ipso_light_control.c b/subsys/net/lib/lwm2m/ipso_light_control.c index f9a155b32b0..048125d7bb4 100644 --- a/subsys/net/lib/lwm2m/ipso_light_control.c +++ b/subsys/net/lib/lwm2m/ipso_light_control.c @@ -40,6 +40,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define LIGHT_STRING_SHORT 8 #define LIGHT_STRING_LONG 64 +/* + * Calculate resource instances as follows: + * start with LIGHT_MAX_ID + */ +#define RESOURCE_INSTANCE_COUNT (LIGHT_MAX_ID) + /* resource state variables */ static bool on_off_value[MAX_INSTANCE_COUNT]; static u8_t dimmer_value[MAX_INSTANCE_COUNT]; @@ -63,9 +69,12 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; -static struct lwm2m_engine_res_inst res[MAX_INSTANCE_COUNT][LIGHT_MAX_ID]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][LIGHT_MAX_ID]; +static struct lwm2m_engine_res_inst + res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; -static void *on_time_read_cb(u16_t obj_inst_id, size_t *data_len) +static void *on_time_read_cb(u16_t obj_inst_id, u16_t res_id, u16_t res_inst_id, + size_t *data_len) { int i; @@ -87,6 +96,7 @@ static void *on_time_read_cb(u16_t obj_inst_id, size_t *data_len) } static int on_time_post_write_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { @@ -117,7 +127,7 @@ static int on_time_post_write_cb(u16_t obj_inst_id, static struct lwm2m_engine_obj_inst *light_control_create(u16_t obj_inst_id) { - int index, avail = -1, i = 0; + int index, avail = -1, i = 0, j = 0; /* Check that there is no other instance with this ID */ for (index = 0; index < MAX_INSTANCE_COUNT; index++) { @@ -151,24 +161,33 @@ static struct lwm2m_engine_obj_inst *light_control_create(u16_t obj_inst_id) colour[avail][0] = '\0'; units[avail][0] = '\0'; + init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail])); + /* initialize instance resource data */ - INIT_OBJ_RES_DATA(res[avail], i, LIGHT_ON_OFF_ID, - &on_off_value[avail], sizeof(*on_off_value)); - INIT_OBJ_RES_DATA(res[avail], i, LIGHT_DIMMER_ID, - &dimmer_value[avail], sizeof(*dimmer_value)); - INIT_OBJ_RES(res[avail], i, LIGHT_ON_TIME_ID, 0, &on_time_value[avail], - sizeof(*on_time_value), on_time_read_cb, - NULL, on_time_post_write_cb, NULL); - INIT_OBJ_RES_DATA(res[avail], i, LIGHT_CUMULATIVE_ACTIVE_POWER_ID, - &cumulative_active_value[avail], - sizeof(*cumulative_active_value)); - INIT_OBJ_RES_DATA(res[avail], i, LIGHT_POWER_FACTOR_ID, - &power_factor_value[avail], sizeof(*power_factor_value)); - INIT_OBJ_RES_DATA(res[avail], i, LIGHT_COLOUR_ID, - colour[avail], LIGHT_STRING_LONG); - INIT_OBJ_RES_DATA(res[avail], i, LIGHT_SENSOR_UNITS_ID, - units[avail], LIGHT_STRING_SHORT); - INIT_OBJ_RES_DUMMY(res[avail], i, LIGHT_APPLICATION_TYPE_ID); + INIT_OBJ_RES_DATA(LIGHT_ON_OFF_ID, res[avail], i, res_inst[avail], j, + &on_off_value[avail], sizeof(*on_off_value)); + INIT_OBJ_RES_DATA(LIGHT_DIMMER_ID, res[avail], i, res_inst[avail], j, + &dimmer_value[avail], sizeof(*dimmer_value)); + INIT_OBJ_RES(LIGHT_ON_TIME_ID, res[avail], i, + res_inst[avail], j, 1, true, + &on_time_value[avail], sizeof(*on_time_value), + on_time_read_cb, NULL, on_time_post_write_cb, NULL); + INIT_OBJ_RES_DATA(LIGHT_CUMULATIVE_ACTIVE_POWER_ID, res[avail], i, + res_inst[avail], j, + &cumulative_active_value[avail], + sizeof(*cumulative_active_value)); + INIT_OBJ_RES_DATA(LIGHT_POWER_FACTOR_ID, res[avail], i, + res_inst[avail], j, + &power_factor_value[avail], + sizeof(*power_factor_value)); + INIT_OBJ_RES_DATA(LIGHT_COLOUR_ID, res[avail], i, + res_inst[avail], j, + colour[avail], LIGHT_STRING_LONG); + INIT_OBJ_RES_DATA(LIGHT_SENSOR_UNITS_ID, res[avail], i, + res_inst[avail], j, + units[avail], LIGHT_STRING_SHORT); + INIT_OBJ_RES_OPTDATA(LIGHT_APPLICATION_TYPE_ID, res[avail], i, + res_inst[avail], j); inst[avail].resources = res[avail]; inst[avail].resource_count = i; @@ -182,7 +201,7 @@ static int ipso_light_control_init(struct device *dev) { /* Set default values */ (void)memset(inst, 0, sizeof(*inst) * MAX_INSTANCE_COUNT); - (void)memset(res, 0, sizeof(struct lwm2m_engine_res_inst) * + (void)memset(res, 0, sizeof(struct lwm2m_engine_res) * MAX_INSTANCE_COUNT * LIGHT_MAX_ID); light_control.obj_id = IPSO_OBJECT_LIGHT_CONTROL_ID; diff --git a/subsys/net/lib/lwm2m/ipso_temp_sensor.c b/subsys/net/lib/lwm2m/ipso_temp_sensor.c index dde1cec953a..8947ee3be19 100644 --- a/subsys/net/lib/lwm2m/ipso_temp_sensor.c +++ b/subsys/net/lib/lwm2m/ipso_temp_sensor.c @@ -38,6 +38,13 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define TEMP_STRING_SHORT 8 +/* + * Calculate resource instances as follows: + * start with TEMP_MAX_ID + * subtract EXEC resources (1) + */ +#define RESOURCE_INSTANCE_COUNT (TEMP_MAX_ID - 1) + /* resource state variables */ static float32_value_t sensor_value[MAX_INSTANCE_COUNT]; static char units[MAX_INSTANCE_COUNT][TEMP_STRING_SHORT]; @@ -58,7 +65,9 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; -static struct lwm2m_engine_res_inst res[MAX_INSTANCE_COUNT][TEMP_MAX_ID]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][TEMP_MAX_ID]; +static struct lwm2m_engine_res_inst + res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; static void update_min_measured(u16_t obj_inst_id, int index) { @@ -93,6 +102,7 @@ static int reset_min_max_measured_values_cb(u16_t obj_inst_id) } static int sensor_value_write_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { @@ -136,7 +146,7 @@ static int sensor_value_write_cb(u16_t obj_inst_id, static struct lwm2m_engine_obj_inst *temp_sensor_create(u16_t obj_inst_id) { - int index, i = 0; + int index, i = 0, j = 0; /* Check that there is no other instance with this ID */ for (index = 0; index < MAX_INSTANCE_COUNT; index++) { @@ -172,27 +182,29 @@ static struct lwm2m_engine_obj_inst *temp_sensor_create(u16_t obj_inst_id) max_range_value[index].val1 = 0; max_range_value[index].val2 = 0; + init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index])); + /* initialize instance resource data */ - INIT_OBJ_RES(res[index], i, TEMP_SENSOR_VALUE_ID, 0, + INIT_OBJ_RES(TEMP_SENSOR_VALUE_ID, res[index], i, + res_inst[index], j, 1, true, &sensor_value[index], sizeof(*sensor_value), NULL, NULL, sensor_value_write_cb, NULL); - INIT_OBJ_RES_DATA(res[index], i, TEMP_UNITS_ID, + INIT_OBJ_RES_DATA(TEMP_UNITS_ID, res[index], i, res_inst[index], j, units[index], TEMP_STRING_SHORT); - INIT_OBJ_RES_DATA(res[index], i, TEMP_MIN_MEASURED_VALUE_ID, - &min_measured_value[index], + INIT_OBJ_RES_DATA(TEMP_MIN_MEASURED_VALUE_ID, res[index], i, + res_inst[index], j, &min_measured_value[index], sizeof(*min_measured_value)); - INIT_OBJ_RES_DATA(res[index], i, TEMP_MAX_MEASURED_VALUE_ID, - &max_measured_value[index], + INIT_OBJ_RES_DATA(TEMP_MAX_MEASURED_VALUE_ID, res[index], i, + res_inst[index], j, &max_measured_value[index], sizeof(*max_measured_value)); - INIT_OBJ_RES_DATA(res[index], i, TEMP_MIN_RANGE_VALUE_ID, - &min_range_value[index], + INIT_OBJ_RES_DATA(TEMP_MIN_RANGE_VALUE_ID, res[index], i, + res_inst[index], j, &min_range_value[index], sizeof(*min_range_value)); - INIT_OBJ_RES_DATA(res[index], i, TEMP_MAX_RANGE_VALUE_ID, - &max_range_value[index], + INIT_OBJ_RES_DATA(TEMP_MAX_RANGE_VALUE_ID, res[index], i, + res_inst[index], j, &max_range_value[index], sizeof(*max_range_value)); - INIT_OBJ_RES_EXECUTE(res[index], i, - TEMP_RESET_MIN_MAX_MEASURED_VALUES_ID, - reset_min_max_measured_values_cb); + INIT_OBJ_RES_EXECUTE(TEMP_RESET_MIN_MAX_MEASURED_VALUES_ID, + res[index], i, reset_min_max_measured_values_cb); inst[index].resources = res[index]; inst[index].resource_count = i; @@ -204,7 +216,7 @@ static int ipso_temp_sensor_init(struct device *dev) { /* Set default values */ (void)memset(inst, 0, sizeof(*inst) * MAX_INSTANCE_COUNT); - (void)memset(res, 0, sizeof(struct lwm2m_engine_res_inst) * + (void)memset(res, 0, sizeof(struct lwm2m_engine_res) * MAX_INSTANCE_COUNT * TEMP_MAX_ID); temp_sensor.obj_id = IPSO_OBJECT_TEMP_SENSOR_ID; diff --git a/subsys/net/lib/lwm2m/ipso_timer.c b/subsys/net/lib/lwm2m/ipso_timer.c index 97425050b74..dc8208ccb5e 100644 --- a/subsys/net/lib/lwm2m/ipso_timer.c +++ b/subsys/net/lib/lwm2m/ipso_timer.c @@ -38,6 +38,13 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define MAX_INSTANCE_COUNT CONFIG_LWM2M_IPSO_TIMER_INSTANCE_COUNT +/* + * Calculate resource instances as follows: + * start with TIMER_MAX_ID + * subtract EXEC resources (1) + */ +#define RESOURCE_INSTANCE_COUNT (TIMER_MAX_ID - 1) + enum ipso_timer_mode { TIMER_MODE_OFF = 0, TIMER_MODE_ONE_SHOT, @@ -83,7 +90,9 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; -static struct lwm2m_engine_res_inst res[MAX_INSTANCE_COUNT][TIMER_MAX_ID]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][TIMER_MAX_ID]; +static struct lwm2m_engine_res_inst + res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; static int ms2float(u32_t ms, float64_value_t *f) { @@ -170,7 +179,9 @@ static int stop_timer(struct ipso_timer_data *timer, bool cancel) return 0; } -static void *remaining_time_read_cb(u16_t obj_inst_id, size_t *data_len) +static void *remaining_time_read_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, + size_t *data_len) { u32_t temp = 0U; int i; @@ -193,7 +204,9 @@ static void *remaining_time_read_cb(u16_t obj_inst_id, size_t *data_len) return &timer_data[i].remaining_time; } -static void *cumulative_time_read_cb(u16_t obj_inst_id, size_t *data_len) +static void *cumulative_time_read_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, + size_t *data_len) { int i; u32_t temp; @@ -215,6 +228,7 @@ static void *cumulative_time_read_cb(u16_t obj_inst_id, size_t *data_len) } static int cumulative_time_post_write_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { @@ -229,7 +243,9 @@ static int cumulative_time_post_write_cb(u16_t obj_inst_id, return 0; } -static int enabled_post_write_cb(u16_t obj_inst_id, u8_t *data, u16_t data_len, +static int enabled_post_write_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, + u8_t *data, u16_t data_len, bool last_block, size_t total_size) { int i; @@ -248,6 +264,7 @@ static int enabled_post_write_cb(u16_t obj_inst_id, u8_t *data, u16_t data_len, } static int trigger_counter_post_write_cb(u16_t obj_inst_id, + u16_t res_id, u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { @@ -284,7 +301,7 @@ static int timer_trigger_cb(u16_t obj_inst_id) static struct lwm2m_engine_obj_inst *timer_create(u16_t obj_inst_id) { - int index, avail = -1, i = 0; + int index, avail = -1, i = 0, j = 0; /* Check that there is no other instance with this ID */ for (index = 0; index < MAX_INSTANCE_COUNT; index++) { @@ -322,37 +339,46 @@ static struct lwm2m_engine_obj_inst *timer_create(u16_t obj_inst_id) timer_data[avail].timer_mode = TIMER_MODE_ONE_SHOT; timer_data[avail].obj_inst_id = obj_inst_id; + init_res_instance(res_inst[avail], ARRAY_SIZE(res_inst[avail])); + /* initialize instance resource data */ - INIT_OBJ_RES_DATA(res[avail], i, TIMER_DELAY_DURATION_ID, - &timer_data[avail].delay_duration, - sizeof(timer_data[avail].delay_duration)); - INIT_OBJ_RES(res[avail], i, TIMER_REMAINING_TIME_ID, 0, - &timer_data[avail].remaining_time, - sizeof(timer_data[avail].remaining_time), - remaining_time_read_cb, NULL, NULL, NULL); - INIT_OBJ_RES_DATA(res[avail], i, TIMER_MINIMUM_OFF_TIME_ID, - &timer_data[avail].min_off_time, - sizeof(timer_data[avail].min_off_time)); - INIT_OBJ_RES_EXECUTE(res[avail], i, TIMER_TRIGGER_ID, + INIT_OBJ_RES_DATA(TIMER_DELAY_DURATION_ID, res[avail], i, + res_inst[avail], j, &timer_data[avail].delay_duration, + sizeof(timer_data[avail].delay_duration)); + INIT_OBJ_RES(TIMER_REMAINING_TIME_ID, res[avail], i, + res_inst[avail], j, 1, true, + &timer_data[avail].remaining_time, + sizeof(timer_data[avail].remaining_time), + remaining_time_read_cb, NULL, NULL, NULL); + INIT_OBJ_RES_DATA(TIMER_MINIMUM_OFF_TIME_ID, res[avail], i, + res_inst[avail], j, &timer_data[avail].min_off_time, + sizeof(timer_data[avail].min_off_time)); + INIT_OBJ_RES_EXECUTE(TIMER_TRIGGER_ID, res[avail], i, timer_trigger_cb); - INIT_OBJ_RES(res[avail], i, TIMER_ON_OFF_ID, 0, - &timer_data[avail].enabled, sizeof(timer_data[avail].enabled), - NULL, NULL, enabled_post_write_cb, NULL); - INIT_OBJ_RES(res[avail], i, TIMER_CUMULATIVE_TIME_ID, 0, - &timer_data[avail].cumulative_time, - sizeof(timer_data[avail].cumulative_time), - cumulative_time_read_cb, NULL, cumulative_time_post_write_cb, - NULL); - INIT_OBJ_RES_DATA(res[avail], i, TIMER_DIGITAL_STATE_ID, - &timer_data[avail].active, sizeof(timer_data[avail].active)); - INIT_OBJ_RES(res[avail], i, TIMER_COUNTER_ID, 0, - &timer_data[avail].trigger_counter, - sizeof(timer_data[avail].trigger_counter), - NULL, NULL, trigger_counter_post_write_cb, NULL); - INIT_OBJ_RES_DATA(res[avail], i, TIMER_MODE_ID, - &timer_data[avail].timer_mode, - sizeof(timer_data[avail].timer_mode)); - INIT_OBJ_RES_DUMMY(res[avail], i, TIMER_APPLICATION_TYPE_ID); + INIT_OBJ_RES(TIMER_ON_OFF_ID, res[avail], i, + res_inst[avail], j, 1, true, + &timer_data[avail].enabled, + sizeof(timer_data[avail].enabled), + NULL, NULL, enabled_post_write_cb, NULL); + INIT_OBJ_RES(TIMER_CUMULATIVE_TIME_ID, res[avail], i, + res_inst[avail], j, 1, true, + &timer_data[avail].cumulative_time, + sizeof(timer_data[avail].cumulative_time), + cumulative_time_read_cb, NULL, + cumulative_time_post_write_cb, NULL); + INIT_OBJ_RES_DATA(TIMER_DIGITAL_STATE_ID, res[avail], i, + res_inst[avail], j, &timer_data[avail].active, + sizeof(timer_data[avail].active)); + INIT_OBJ_RES(TIMER_COUNTER_ID, res[avail], i, + res_inst[avail], j, 1, true, + &timer_data[avail].trigger_counter, + sizeof(timer_data[avail].trigger_counter), + NULL, NULL, trigger_counter_post_write_cb, NULL); + INIT_OBJ_RES_DATA(TIMER_MODE_ID, res[avail], i, res_inst[avail], j, + &timer_data[avail].timer_mode, + sizeof(timer_data[avail].timer_mode)); + INIT_OBJ_RES_OPTDATA(TIMER_APPLICATION_TYPE_ID, res[avail], i, + res_inst[avail], j); inst[avail].resources = res[avail]; inst[avail].resource_count = i; @@ -366,7 +392,7 @@ static int ipso_timer_init(struct device *dev) { /* Set default values */ (void)memset(inst, 0, sizeof(*inst) * MAX_INSTANCE_COUNT); - (void)memset(res, 0, sizeof(struct lwm2m_engine_res_inst) * + (void)memset(res, 0, sizeof(struct lwm2m_engine_res) * MAX_INSTANCE_COUNT * TIMER_MAX_ID); timer.obj_id = IPSO_OBJECT_TIMER_ID; diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.c b/subsys/net/lib/lwm2m/lwm2m_engine.c index b9824a0d73d..6fbac854f2f 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.c +++ b/subsys/net/lib/lwm2m/lwm2m_engine.c @@ -778,7 +778,7 @@ int lwm2m_delete_obj_inst(u16_t obj_id, u16_t obj_inst_id) for (i = 0; i < obj_inst->resource_count; i++) { clear_attrs(&obj_inst->resources[i]); (void)memset(obj_inst->resources + i, 0, - sizeof(struct lwm2m_engine_res_inst)); + sizeof(struct lwm2m_engine_res)); } clear_attrs(obj_inst); @@ -1246,11 +1246,13 @@ static int string_to_path(char *pathstr, struct lwm2m_obj_path *path, static int path_to_objs(const struct lwm2m_obj_path *path, struct lwm2m_engine_obj_inst **obj_inst, struct lwm2m_engine_obj_field **obj_field, - struct lwm2m_engine_res_inst **res) + struct lwm2m_engine_res **res, + struct lwm2m_engine_res_inst **res_inst) { struct lwm2m_engine_obj_inst *oi; struct lwm2m_engine_obj_field *of; - struct lwm2m_engine_res_inst *r = NULL; + struct lwm2m_engine_res *r = NULL; + struct lwm2m_engine_res_inst *ri = NULL; int i; if (!path) { @@ -1283,10 +1285,19 @@ static int path_to_objs(const struct lwm2m_obj_path *path, } if (!r) { - LOG_ERR("res instance %d not found", path->res_id); + LOG_ERR("resource %d not found", path->res_id); return -ENOENT; } + for (i = 0; i < r->res_inst_count; i++) { + if (r->res_instances[i].res_inst_id == path->res_inst_id) { + ri = &r->res_instances[i]; + break; + } + } + + /* specifically don't complain about missing resource instance */ + if (obj_inst) { *obj_inst = oi; } @@ -1299,6 +1310,10 @@ static int path_to_objs(const struct lwm2m_obj_path *path, *res = r; } + if (ri && res_inst) { + *res_inst = ri; + } + return 0; } @@ -1328,7 +1343,7 @@ int lwm2m_engine_set_res_data(char *pathstr, void *data_ptr, u16_t data_len, u8_t data_flags) { struct lwm2m_obj_path path; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; int ret = 0; /* translate path -> path_obj */ @@ -1338,20 +1353,25 @@ int lwm2m_engine_set_res_data(char *pathstr, void *data_ptr, u16_t data_len, } if (path.level < 3) { - LOG_ERR("path must have 3 parts"); + LOG_ERR("path must have at least 3 parts"); return -EINVAL; } /* look up resource obj */ - ret = path_to_objs(&path, NULL, NULL, &res); + ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst); if (ret < 0) { return ret; } + if (!res_inst) { + LOG_ERR("res instance %d not found", path.res_inst_id); + return -ENOENT; + } + /* assign data elements */ - res->data_ptr = data_ptr; - res->data_len = data_len; - res->data_flags = data_flags; + res_inst->data_ptr = data_ptr; + res_inst->data_len = data_len; + res_inst->data_flags = data_flags; return ret; } @@ -1361,7 +1381,8 @@ static int lwm2m_engine_set(char *pathstr, void *value, u16_t len) struct lwm2m_obj_path path; struct lwm2m_engine_obj_inst *obj_inst; struct lwm2m_engine_obj_field *obj_field; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; void *data_ptr = NULL; size_t data_len = 0; int ret = 0; @@ -1376,44 +1397,46 @@ static int lwm2m_engine_set(char *pathstr, void *value, u16_t len) } if (path.level < 3) { - LOG_ERR("path must have 3 parts"); + LOG_ERR("path must have at least 3 parts"); return -EINVAL; } /* look up resource obj */ - ret = path_to_objs(&path, &obj_inst, &obj_field, &res); + ret = path_to_objs(&path, &obj_inst, &obj_field, &res, &res_inst); if (ret < 0) { return ret; } - if (!res) { - LOG_ERR("res instance %d not found", path.res_id); + if (!res_inst) { + LOG_ERR("res instance %d not found", path.res_inst_id); return -ENOENT; } - if (LWM2M_HAS_RES_FLAG(res, LWM2M_RES_DATA_FLAG_RO)) { - LOG_ERR("res data pointer is read-only"); + if (LWM2M_HAS_RES_FLAG(res_inst, LWM2M_RES_DATA_FLAG_RO)) { + LOG_ERR("res instance data pointer is read-only"); return -EACCES; } /* setup initial data elements */ - data_ptr = res->data_ptr; - data_len = res->data_len; + data_ptr = res_inst->data_ptr; + data_len = res_inst->data_len; /* allow user to override data elements via callback */ if (res->pre_write_cb) { - data_ptr = res->pre_write_cb(obj_inst->obj_inst_id, &data_len); + data_ptr = res->pre_write_cb(obj_inst->obj_inst_id, + res->res_id, res_inst->res_inst_id, + &data_len); } if (!data_ptr) { - LOG_ERR("res data pointer is NULL"); + LOG_ERR("res instance data pointer is NULL"); return -EINVAL; } /* check length (note: we add 1 to string length for NULL pad) */ - if (len > res->data_len - + if (len > res_inst->data_len - (obj_field->data_type == LWM2M_RES_TYPE_STRING ? 1 : 0)) { - LOG_ERR("length %u is too long for resource %d data", + LOG_ERR("length %u is too long for res instance %d data", len, path.res_id); return -ENOMEM; } @@ -1491,8 +1514,9 @@ static int lwm2m_engine_set(char *pathstr, void *value, u16_t len) } if (res->post_write_cb) { - ret = res->post_write_cb(obj_inst->obj_inst_id, data_ptr, len, - false, 0); + ret = res->post_write_cb(obj_inst->obj_inst_id, + res->res_id, res_inst->res_inst_id, + data_ptr, len, false, 0); } if (changed) { @@ -1575,7 +1599,7 @@ int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr, u16_t *data_len, u8_t *data_flags) { struct lwm2m_obj_path path; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; int ret = 0; /* translate path -> path_obj */ @@ -1585,19 +1609,24 @@ int lwm2m_engine_get_res_data(char *pathstr, void **data_ptr, u16_t *data_len, } if (path.level < 3) { - LOG_ERR("path must have 3 parts"); + LOG_ERR("path must have at least 3 parts"); return -EINVAL; } /* look up resource obj */ - ret = path_to_objs(&path, NULL, NULL, &res); + ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst); if (ret < 0) { return ret; } - *data_ptr = res->data_ptr; - *data_len = res->data_len; - *data_flags = res->data_flags; + if (!res_inst) { + LOG_ERR("res instance %d not found", path.res_inst_id); + return -ENOENT; + } + + *data_ptr = res_inst->data_ptr; + *data_len = res_inst->data_len; + *data_flags = res_inst->data_flags; return 0; } @@ -1608,7 +1637,8 @@ static int lwm2m_engine_get(char *pathstr, void *buf, u16_t buflen) struct lwm2m_obj_path path; struct lwm2m_engine_obj_inst *obj_inst; struct lwm2m_engine_obj_field *obj_field; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; void *data_ptr = NULL; size_t data_len = 0; @@ -1621,28 +1651,30 @@ static int lwm2m_engine_get(char *pathstr, void *buf, u16_t buflen) } if (path.level < 3) { - LOG_ERR("path must have 3 parts"); + LOG_ERR("path must have at least 3 parts"); return -EINVAL; } /* look up resource obj */ - ret = path_to_objs(&path, &obj_inst, &obj_field, &res); + ret = path_to_objs(&path, &obj_inst, &obj_field, &res, &res_inst); if (ret < 0) { return ret; } - if (!res) { - LOG_ERR("res instance %d not found", path.res_id); + if (!res_inst) { + LOG_ERR("res instance %d not found", path.res_inst_id); return -ENOENT; } /* setup initial data elements */ - data_ptr = res->data_ptr; - data_len = res->data_len; + data_ptr = res_inst->data_ptr; + data_len = res_inst->data_len; /* allow user to override data elements via callback */ if (res->read_cb) { - data_ptr = res->read_cb(obj_inst->obj_inst_id, &data_len); + data_ptr = res->read_cb(obj_inst->obj_inst_id, + res->res_id, res_inst->res_inst_id, + &data_len); } /* TODO: handle data_len > buflen case */ @@ -1797,7 +1829,7 @@ int lwm2m_engine_get_float64(char *pathstr, float64_value_t *buf) return lwm2m_engine_get(pathstr, buf, sizeof(float64_value_t)); } -int lwm2m_engine_get_resource(char *pathstr, struct lwm2m_engine_res_inst **res) +int lwm2m_engine_get_resource(char *pathstr, struct lwm2m_engine_res **res) { int ret; struct lwm2m_obj_path path; @@ -1812,14 +1844,100 @@ int lwm2m_engine_get_resource(char *pathstr, struct lwm2m_engine_res_inst **res) return -EINVAL; } - return path_to_objs(&path, NULL, NULL, res); + return path_to_objs(&path, NULL, NULL, res, NULL); +} + +int lwm2m_engine_create_res_inst(char *pathstr) +{ + int ret, i; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; + struct lwm2m_obj_path path; + + ret = string_to_path(pathstr, &path, '/'); + if (ret < 0) { + return ret; + } + + if (path.level < 4) { + LOG_ERR("path must have 4 parts"); + return -EINVAL; + } + + ret = path_to_objs(&path, NULL, NULL, &res, &res_inst); + if (ret < 0) { + return ret; + } + + if (!res) { + LOG_ERR("resource %u not found", path.res_id); + return -ENOENT; + } + + if (res_inst && res_inst->res_inst_id != RES_INSTANCE_NOT_CREATED) { + LOG_ERR("res instance %u already exists", path.res_inst_id); + return -EINVAL; + } + + if (!res->res_instances || res->res_inst_count == 0) { + LOG_ERR("no available res instances"); + return -ENOMEM; + } + + for (i = 0; i < res->res_inst_count; i++) { + if (res->res_instances[i].res_inst_id == + RES_INSTANCE_NOT_CREATED) { + break; + } + } + + if (i >= res->res_inst_count) { + LOG_ERR("no available res instances"); + return -ENOMEM; + } + + res->res_instances[i].res_inst_id = path.res_inst_id; + return 0; +} + +int lwm2m_engine_delete_res_inst(char *pathstr) +{ + int ret; + struct lwm2m_engine_res_inst *res_inst = NULL; + struct lwm2m_obj_path path; + + ret = string_to_path(pathstr, &path, '/'); + if (ret < 0) { + return ret; + } + + if (path.level < 4) { + LOG_ERR("path must have 4 parts"); + return -EINVAL; + } + + ret = path_to_objs(&path, NULL, NULL, NULL, &res_inst); + if (ret < 0) { + return ret; + } + + if (!res_inst) { + LOG_ERR("res instance %u not found", path.res_inst_id); + return -ENOENT; + } + + res_inst->data_ptr = NULL; + res_inst->data_len = 0U; + res_inst->res_inst_id = RES_INSTANCE_NOT_CREATED; + + return 0; } int lwm2m_engine_register_read_callback(char *pathstr, lwm2m_engine_get_data_cb_t cb) { int ret; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; ret = lwm2m_engine_get_resource(pathstr, &res); if (ret < 0) { @@ -1834,7 +1952,7 @@ int lwm2m_engine_register_pre_write_callback(char *pathstr, lwm2m_engine_get_data_cb_t cb) { int ret; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; ret = lwm2m_engine_get_resource(pathstr, &res); if (ret < 0) { @@ -1849,7 +1967,7 @@ int lwm2m_engine_register_post_write_callback(char *pathstr, lwm2m_engine_set_data_cb_t cb) { int ret; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; ret = lwm2m_engine_get_resource(pathstr, &res); if (ret < 0) { @@ -1864,7 +1982,7 @@ int lwm2m_engine_register_exec_callback(char *pathstr, lwm2m_engine_user_cb_t cb) { int ret; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; ret = lwm2m_engine_get_resource(pathstr, &res); if (ret < 0) { @@ -1908,11 +2026,11 @@ int lwm2m_engine_register_delete_callback(u16_t obj_id, /* generic data handlers */ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst, - struct lwm2m_engine_res_inst *res, + struct lwm2m_engine_res *res, struct lwm2m_engine_obj_field *obj_field, struct lwm2m_message *msg) { - int i, loop_max = 1; + int i, loop_max = 1, found_values = 0; u16_t res_inst_id_tmp = 0U; void *data_ptr = NULL; size_t data_len = 0; @@ -1921,33 +2039,50 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst, return -EINVAL; } - /* setup initial data elements */ - data_ptr = res->data_ptr; - data_len = res->data_len; + loop_max = res->res_inst_count; + if (loop_max > 1) { + /* search for valid resource instances */ + for (i = 0; i < loop_max; i++) { + if (res->res_instances[i].res_inst_id != + RES_INSTANCE_NOT_CREATED) { + found_values = 1; + break; + } + } - /* allow user to override data elements via callback */ - if (res->read_cb) { - data_ptr = res->read_cb(obj_inst->obj_inst_id, &data_len); - } - - if (!data_ptr || data_len == 0) { - return -ENOENT; - } - - if (res->multi_count_var != NULL) { - /* if multi_count_var is 0 (none assigned) return NOT_FOUND */ - if (*res->multi_count_var == 0U) { + if (!found_values) { return -ENOENT; } engine_put_begin_ri(&msg->out, &msg->path); - loop_max = *res->multi_count_var; res_inst_id_tmp = msg->path.res_inst_id; } for (i = 0; i < loop_max; i++) { - if (res->multi_count_var != NULL) { - msg->path.res_inst_id = (u16_t) i; + if (res->res_instances[i].res_inst_id == + RES_INSTANCE_NOT_CREATED) { + continue; + } + + if (res->res_inst_count > 1) { + msg->path.res_inst_id = + res->res_instances[i].res_inst_id; + } + + /* setup initial data elements */ + data_ptr = res->res_instances[i].data_ptr; + data_len = res->res_instances[i].data_len; + + /* allow user to override data elements via callback */ + if (res->read_cb) { + data_ptr = res->read_cb(obj_inst->obj_inst_id, + res->res_id, + res->res_instances[i].res_inst_id, + &data_len); + } + + if (!data_ptr || data_len == 0) { + return -ENOENT; } switch (obj_field->data_type) { @@ -1956,7 +2091,6 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst, case LWM2M_RES_TYPE_OPAQUE: break; - /* TODO: handle multi count for string? */ case LWM2M_RES_TYPE_STRING: engine_put_string(&msg->out, &msg->path, (u8_t *)data_ptr, @@ -1965,58 +2099,58 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst, case LWM2M_RES_TYPE_U64: engine_put_s64(&msg->out, &msg->path, - (s64_t)((u64_t *)data_ptr)[i]); + (s64_t)*(u64_t *)data_ptr); break; case LWM2M_RES_TYPE_U32: case LWM2M_RES_TYPE_TIME: engine_put_s32(&msg->out, &msg->path, - (s32_t)((u32_t *)data_ptr)[i]); + (s32_t)*(u32_t *)data_ptr); break; case LWM2M_RES_TYPE_U16: engine_put_s16(&msg->out, &msg->path, - (s16_t)((u16_t *)data_ptr)[i]); + (s16_t)*(u16_t *)data_ptr); break; case LWM2M_RES_TYPE_U8: engine_put_s8(&msg->out, &msg->path, - (s8_t)((u8_t *)data_ptr)[i]); + (s8_t)*(u8_t *)data_ptr); break; case LWM2M_RES_TYPE_S64: engine_put_s64(&msg->out, &msg->path, - ((s64_t *)data_ptr)[i]); + *(s64_t *)data_ptr); break; case LWM2M_RES_TYPE_S32: engine_put_s32(&msg->out, &msg->path, - ((s32_t *)data_ptr)[i]); + *(s32_t *)data_ptr); break; case LWM2M_RES_TYPE_S16: engine_put_s16(&msg->out, &msg->path, - ((s16_t *)data_ptr)[i]); + *(s16_t *)data_ptr); break; case LWM2M_RES_TYPE_S8: engine_put_s8(&msg->out, &msg->path, - ((s8_t *)data_ptr)[i]); + *(s8_t *)data_ptr); break; case LWM2M_RES_TYPE_BOOL: engine_put_bool(&msg->out, &msg->path, - ((bool *)data_ptr)[i]); + *(bool *)data_ptr); break; case LWM2M_RES_TYPE_FLOAT32: engine_put_float32fix(&msg->out, &msg->path, - &((float32_value_t *)data_ptr)[i]); + (float32_value_t *)data_ptr); break; case LWM2M_RES_TYPE_FLOAT64: engine_put_float64fix(&msg->out, &msg->path, - &((float64_value_t *)data_ptr)[i]); + (float64_value_t *)data_ptr); break; default: @@ -2027,7 +2161,7 @@ static int lwm2m_read_handler(struct lwm2m_engine_obj_inst *obj_inst, } } - if (res->multi_count_var != NULL) { + if (res->res_inst_count > 1) { engine_put_end_ri(&msg->out, &msg->path); msg->path.res_inst_id = res_inst_id_tmp; } @@ -2059,7 +2193,8 @@ size_t lwm2m_engine_get_opaque_more(struct lwm2m_input_context *in, } static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, - struct lwm2m_engine_res_inst *res, + struct lwm2m_engine_res *res, + struct lwm2m_engine_res_inst *res_inst, struct lwm2m_input_context *in, void *data_ptr, size_t data_len, bool last_block, size_t total_size) @@ -2090,6 +2225,8 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, if (res->post_write_cb) { ret = res->post_write_cb(obj_inst->obj_inst_id, + res->res_id, + res_inst->res_inst_id, data_ptr, len, last_pkt_block && last_block, total_size); @@ -2104,7 +2241,8 @@ static int lwm2m_write_handler_opaque(struct lwm2m_engine_obj_inst *obj_inst, /* This function is exposed for the content format writers */ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, - struct lwm2m_engine_res_inst *res, + struct lwm2m_engine_res *res, + struct lwm2m_engine_res_inst *res_inst, struct lwm2m_engine_obj_field *obj_field, struct lwm2m_message *msg) { @@ -2120,21 +2258,23 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, u8_t tkl = 0U; bool last_block = true; - if (!obj_inst || !res || !obj_field || !msg) { + if (!obj_inst || !res || !res_inst || !obj_field || !msg) { return -EINVAL; } - if (LWM2M_HAS_RES_FLAG(res, LWM2M_RES_DATA_FLAG_RO)) { + if (LWM2M_HAS_RES_FLAG(res_inst, LWM2M_RES_DATA_FLAG_RO)) { return -EACCES; } /* setup initial data elements */ - data_ptr = res->data_ptr; - data_len = res->data_len; + data_ptr = res_inst->data_ptr; + data_len = res_inst->data_len; /* allow user to override data elements via callback */ if (res->pre_write_cb) { - data_ptr = res->pre_write_cb(obj_inst->obj_inst_id, &data_len); + data_ptr = res->pre_write_cb(obj_inst->obj_inst_id, + res->res_id, res_inst->res_inst_id, + &data_len); } if (res->post_write_cb) { @@ -2161,7 +2301,7 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, case LWM2M_RES_TYPE_OPAQUE: ret = lwm2m_write_handler_opaque(obj_inst, res, - &msg->in, + res_inst, &msg->in, data_ptr, data_len, last_block, total_size); @@ -2252,7 +2392,9 @@ int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, if (res->post_write_cb && obj_field->data_type != LWM2M_RES_TYPE_OPAQUE) { - ret = res->post_write_cb(obj_inst->obj_inst_id, data_ptr, len, + ret = res->post_write_cb(obj_inst->obj_inst_id, + res->res_id, res_inst->res_inst_id, + data_ptr, len, last_block, total_size); } @@ -2269,7 +2411,7 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj, int nr_opt, i, ret = 0; struct coap_option options[NR_LWM2M_ATTR]; struct lwm2m_engine_obj_inst *obj_inst = NULL; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; struct lwm2m_attr *attr; struct notification_attrs nattrs = { 0 }; struct observe_node *obs; @@ -2298,7 +2440,7 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj, /* get lwm2m_attr slist */ if (msg->path.level == 3U) { - ret = path_to_objs(&msg->path, NULL, NULL, &res); + ret = path_to_objs(&msg->path, NULL, NULL, &res, NULL); if (ret < 0) { return ret; } @@ -2571,7 +2713,7 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj, if (!res || res->res_id != obs->path.res_id) { ret = path_to_objs(&obs->path, NULL, NULL, - &res); + &res, NULL); if (ret < 0) { return ret; } @@ -2599,14 +2741,14 @@ static int lwm2m_write_attr_handler(struct lwm2m_engine_obj *obj, static int lwm2m_exec_handler(struct lwm2m_message *msg) { struct lwm2m_engine_obj_inst *obj_inst; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; int ret; if (!msg) { return -EINVAL; } - ret = path_to_objs(&msg->path, &obj_inst, NULL, &res); + ret = path_to_objs(&msg->path, &obj_inst, NULL, &res, NULL); if (ret < 0) { return ret; } @@ -2666,7 +2808,7 @@ static int do_read_op(struct lwm2m_message *msg, u16_t content_format) int lwm2m_perform_read_op(struct lwm2m_message *msg, u16_t content_format) { struct lwm2m_engine_obj_inst *obj_inst = NULL; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; struct lwm2m_engine_obj_field *obj_field; struct lwm2m_obj_path temp_path; int ret = 0, index; diff --git a/subsys/net/lib/lwm2m/lwm2m_engine.h b/subsys/net/lib/lwm2m/lwm2m_engine.h index 33e58cfe506..2f5f8a2a205 100644 --- a/subsys/net/lib/lwm2m/lwm2m_engine.h +++ b/subsys/net/lib/lwm2m/lwm2m_engine.h @@ -84,7 +84,8 @@ u16_t lwm2m_get_rd_data(u8_t *client_data, u16_t size); int lwm2m_perform_read_op(struct lwm2m_message *msg, u16_t content_format); int lwm2m_write_handler(struct lwm2m_engine_obj_inst *obj_inst, - struct lwm2m_engine_res_inst *res, + struct lwm2m_engine_res *res, + struct lwm2m_engine_res_inst *res_inst, struct lwm2m_engine_obj_field *obj_field, struct lwm2m_message *msg); @@ -93,7 +94,7 @@ enum coap_block_size lwm2m_default_block_size(void); int lwm2m_engine_add_service(k_work_handler_t service, u32_t period_ms); int lwm2m_engine_get_resource(char *pathstr, - struct lwm2m_engine_res_inst **res); + struct lwm2m_engine_res **res); size_t lwm2m_engine_get_opaque_more(struct lwm2m_input_context *in, u8_t *buf, size_t buflen, bool *last_block); diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_device.c b/subsys/net/lib/lwm2m/lwm2m_obj_device.c index f285ea9019a..acc3154b7e8 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_device.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_device.c @@ -67,21 +67,22 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define DEVICE_SERVICE_INTERVAL K_SECONDS(10) +/* + * Calculate resource instances as follows: + * start with DEVICE_MAX_ID + * subtract EXEC resources (3) + * subtract MULTI resources because their counts include 0 resource (4) + * add 3x DEVICE_PWRSRC_MAX for POWER SOURCES resource instances + * add DEVICE_ERROR_CODE_MAX for ERROR CODE resource instances + */ +#define RESOURCE_INSTANCE_COUNT (DEVICE_MAX_ID - 3 - 4 + \ + DEVICE_PWRSRC_MAX*3 + DEVICE_ERROR_CODE_MAX) + /* resource state variables */ -static s8_t pwrsrc_available[DEVICE_PWRSRC_MAX]; -static s32_t pwrsrc_voltage_mv[DEVICE_PWRSRC_MAX]; -static s32_t pwrsrc_current_ma[DEVICE_PWRSRC_MAX]; -static u8_t battery_level; -static s32_t mem_free_kb; static u8_t error_code_list[DEVICE_ERROR_CODE_MAX]; static s32_t time_temp; static u32_t time_offset; static u8_t binding_mode[DEVICE_STRING_SHORT]; -static u8_t battery_status; -static s32_t mem_total_kb; - -static u8_t pwrsrc_count; -static u8_t error_code_count; /* only 1 instance of device object exists */ static struct lwm2m_engine_obj device; @@ -112,29 +113,29 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst; -static struct lwm2m_engine_res_inst res[DEVICE_MAX_ID]; +static struct lwm2m_engine_res res[DEVICE_MAX_ID]; +static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT]; + +/* save error code resource instance point so we can easily clear later */ +static struct lwm2m_engine_res_inst *error_code_ri; /* callbacks */ -static int reboot_cb(u16_t obj_inst_id) -{ - LOG_DBG("REBOOT"); - return -EPERM; -} - -static int factory_default_cb(u16_t obj_inst_id) -{ - LOG_DBG("FACTORY_DEFAULT"); - return -EPERM; -} - static int reset_error_list_cb(u16_t obj_inst_id) { - error_code_count = 0U; + int i; + + /* "delete" error codes */ + for (i = 0; i < DEVICE_ERROR_CODE_MAX; i++) { + error_code_list[i] = 0; + error_code_ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED; + } + return 0; } -static void *current_time_read_cb(u16_t obj_inst_id, size_t *data_len) +static void *current_time_read_cb(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, size_t *data_len) { time_temp = time_offset + (k_uptime_get() / 1000); *data_len = sizeof(time_temp); @@ -142,15 +143,17 @@ static void *current_time_read_cb(u16_t obj_inst_id, size_t *data_len) return &time_temp; } -static void *current_time_pre_write_cb(u16_t obj_inst_id, size_t *data_len) +static void *current_time_pre_write_cb(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, size_t *data_len) { *data_len = sizeof(time_temp); return &time_temp; } -static int current_time_post_write_cb(u16_t obj_inst_id, - u8_t *data, u16_t data_len, - bool last_block, size_t total_size) +static int current_time_post_write_cb(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, + u8_t *data, u16_t data_len, + bool last_block, size_t total_size) { if (data_len == 4U) { time_offset = *(s32_t *)data - (s32_t)(k_uptime_get() / 1000); @@ -163,106 +166,132 @@ static int current_time_post_write_cb(u16_t obj_inst_id, /* special setter functions */ -int lwm2m_device_add_pwrsrc(u8_t pwrsrc_type) +__deprecated int lwm2m_device_add_pwrsrc(u8_t pwrsrc_type) { - int index; + int i; + struct lwm2m_engine_res *res; if (pwrsrc_type >= LWM2M_DEVICE_PWR_SRC_TYPE_MAX) { LOG_ERR("power source id %d is invalid", pwrsrc_type); return -EINVAL; } - for (index = 0; index < DEVICE_PWRSRC_MAX; index++) { - if (pwrsrc_available[index] < 0) { + i = lwm2m_engine_get_resource("3/0/6", &res); + if (i < 0 || !res || !res->res_instances) { + return -ENOENT; + } + + for (i = 0; i < res->res_inst_count; i++) { + if (res->res_instances[i].res_inst_id == + RES_INSTANCE_NOT_CREATED && + res->res_instances[i].data_ptr != NULL) { break; } } - if (index >= DEVICE_PWRSRC_MAX) { + if (i >= res->res_inst_count) { return -ENOMEM; } - pwrsrc_available[index] = pwrsrc_type; - pwrsrc_voltage_mv[index] = 0; - pwrsrc_current_ma[index] = 0; - pwrsrc_count++; + *(u8_t *)res->res_instances[i].data_ptr = pwrsrc_type; + res->res_instances[i].res_inst_id = i; NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_AVAILABLE_POWER_SOURCES_ID); - return index; + + return 0; } /* * TODO: this will disable the index, but current printing function expects * all indexes to be in order up to pwrsrc_count */ -int lwm2m_device_remove_pwrsrc(int index) +__deprecated int lwm2m_device_remove_pwrsrc(int index) { - if (index < 0 || index >= DEVICE_PWRSRC_MAX) { - LOG_ERR("index is out of range: %d", index); + int ret; + struct lwm2m_engine_res *res; + + ret = lwm2m_engine_get_resource("3/0/6", &res); + if (ret < 0 || !res || !res->res_instances) { + return -ENOENT; + } + + if (index >= res->res_inst_count) { + LOG_ERR("index %d is invalid", index); return -EINVAL; } - if (pwrsrc_available[index] < 0) { - LOG_ERR("Power source index %d isn't registered", index); - return -EINVAL; + if (res->res_instances[index].res_inst_id == + RES_INSTANCE_NOT_CREATED || + !res->res_instances[index].data_ptr) { + return -ENOMEM; } - pwrsrc_available[index] = -1; - pwrsrc_voltage_mv[index] = 0; - pwrsrc_current_ma[index] = 0; - pwrsrc_count--; + *(u8_t *)res->res_instances[index].data_ptr = 0; + res->res_instances[index].res_inst_id = RES_INSTANCE_NOT_CREATED; NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_AVAILABLE_POWER_SOURCES_ID); + return 0; } -int lwm2m_device_set_pwrsrc_voltage_mv(int index, int voltage_mv) +static int device_set_pwrsrc_value(char *pathstr, int index, s32_t value) { - if (index < 0 || index >= DEVICE_PWRSRC_MAX) { - LOG_ERR("index is out of range: %d", index); + int ret; + struct lwm2m_engine_res *res; + + ret = lwm2m_engine_get_resource(pathstr, &res); + if (ret < 0 || !res || !res->res_instances) { + return -ENOENT; + } + + if (index >= res->res_inst_count) { + LOG_ERR("index %d is invalid", index); return -EINVAL; } - if (pwrsrc_available[index] < 0) { - LOG_ERR("Power source index %d isn't registered.", index); - return -EINVAL; + if (res->res_instances[index].res_inst_id == + RES_INSTANCE_NOT_CREATED || + !res->res_instances[index].data_ptr) { + return -ENOMEM; } - pwrsrc_voltage_mv[index] = voltage_mv; - NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, - DEVICE_POWER_SOURCE_VOLTAGE_ID); + *(s32_t *)res->res_instances[index].data_ptr = value; + NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, res->res_id); + return 0; } -int lwm2m_device_set_pwrsrc_current_ma(int index, int current_ma) +__deprecated int lwm2m_device_set_pwrsrc_voltage_mv(int index, int voltage_mv) { - if (index < 0 || index >= DEVICE_PWRSRC_MAX) { - LOG_ERR("index is out of range: %d", index); - return -EINVAL; - } + return device_set_pwrsrc_value("3/0/7", index, voltage_mv); +} - if (pwrsrc_available[index] < 0) { - LOG_ERR("Power source index %d isn't registered.", index); - return -EINVAL; - } - - pwrsrc_current_ma[index] = current_ma; - NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, - DEVICE_POWER_SOURCE_CURRENT_ID); - return 0; +__deprecated int lwm2m_device_set_pwrsrc_current_ma(int index, int current_ma) +{ + return device_set_pwrsrc_value("3/0/8", index, current_ma); } /* error code function */ int lwm2m_device_add_err(u8_t error_code) { - if (error_code_count < DEVICE_ERROR_CODE_MAX) { - error_code_list[error_code_count] = error_code; - error_code_count++; - return 0; + int i; + + for (i = 0; i < DEVICE_ERROR_CODE_MAX; i++) { + if (error_code_ri[i].res_inst_id == RES_INSTANCE_NOT_CREATED) { + break; + } } - return -ENOMEM; + if (i >= DEVICE_ERROR_CODE_MAX) { + return -ENOMEM; + } + + error_code_list[i] = error_code; + error_code_ri[i].res_inst_id = i; + NOTIFY_OBSERVER(LWM2M_OBJECT_DEVICE_ID, 0, DEVICE_ERROR_CODE_ID); + + return 0; } static void device_periodic_service(struct k_work *work) @@ -272,49 +301,46 @@ static void device_periodic_service(struct k_work *work) static struct lwm2m_engine_obj_inst *device_create(u16_t obj_inst_id) { - int i = 0; + int i = 0, j = 0; + + init_res_instance(res_inst, ARRAY_SIZE(res_inst)); /* initialize instance resource data */ - INIT_OBJ_RES_DUMMY(res, i, DEVICE_MANUFACTURER_ID); - INIT_OBJ_RES_DUMMY(res, i, DEVICE_MODEL_NUMBER_ID); - INIT_OBJ_RES_DUMMY(res, i, DEVICE_SERIAL_NUMBER_ID); - INIT_OBJ_RES_DUMMY(res, i, DEVICE_FIRMWARE_VERSION_ID); - INIT_OBJ_RES_EXECUTE(res, i, DEVICE_REBOOT_ID, reboot_cb); - INIT_OBJ_RES_EXECUTE(res, i, DEVICE_FACTORY_DEFAULT_ID, - factory_default_cb); - INIT_OBJ_RES_MULTI_DATA(res, i, DEVICE_AVAILABLE_POWER_SOURCES_ID, - &pwrsrc_count, pwrsrc_available, - sizeof(*pwrsrc_available)); - INIT_OBJ_RES_MULTI_DATA(res, i, DEVICE_POWER_SOURCE_VOLTAGE_ID, - &pwrsrc_count, pwrsrc_voltage_mv, - sizeof(*pwrsrc_voltage_mv)); - INIT_OBJ_RES_MULTI_DATA(res, i, DEVICE_POWER_SOURCE_CURRENT_ID, - &pwrsrc_count, pwrsrc_current_ma, - sizeof(*pwrsrc_current_ma)); - INIT_OBJ_RES_DATA(res, i, DEVICE_BATTERY_LEVEL_ID, - &battery_level, sizeof(battery_level)); - INIT_OBJ_RES_DATA(res, i, DEVICE_MEMORY_FREE_ID, - &mem_free_kb, sizeof(mem_free_kb)); - INIT_OBJ_RES_MULTI_DATA(res, i, DEVICE_ERROR_CODE_ID, - &error_code_count, error_code_list, - sizeof(*error_code_list)); - INIT_OBJ_RES_EXECUTE(res, i, DEVICE_RESET_ERROR_CODE_ID, + INIT_OBJ_RES_OPTDATA(DEVICE_MANUFACTURER_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_MODEL_NUMBER_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_SERIAL_NUMBER_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_FIRMWARE_VERSION_ID, res, i, res_inst, j); + INIT_OBJ_RES_EXECUTE(DEVICE_REBOOT_ID, res, i, NULL); + INIT_OBJ_RES_EXECUTE(DEVICE_FACTORY_DEFAULT_ID, res, i, NULL); + INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_AVAILABLE_POWER_SOURCES_ID, res, i, + res_inst, j, DEVICE_PWRSRC_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_POWER_SOURCE_VOLTAGE_ID, res, i, + res_inst, j, DEVICE_PWRSRC_MAX, false); + INIT_OBJ_RES_MULTI_OPTDATA(DEVICE_POWER_SOURCE_CURRENT_ID, res, i, + res_inst, j, DEVICE_PWRSRC_MAX, false); + INIT_OBJ_RES_OPTDATA(DEVICE_BATTERY_LEVEL_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_MEMORY_FREE_ID, res, i, res_inst, j); + error_code_ri = &res_inst[j]; + INIT_OBJ_RES_MULTI_DATA(DEVICE_ERROR_CODE_ID, res, i, + res_inst, j, DEVICE_ERROR_CODE_MAX, false, + error_code_list, sizeof(*error_code_list)); + INIT_OBJ_RES_EXECUTE(DEVICE_RESET_ERROR_CODE_ID, res, i, reset_error_list_cb); - INIT_OBJ_RES(res, i, DEVICE_CURRENT_TIME_ID, 0, NULL, 0, - current_time_read_cb, current_time_pre_write_cb, - current_time_post_write_cb, NULL); - INIT_OBJ_RES_DATA(res, i, DEVICE_SUPPORTED_BINDING_MODES_ID, - binding_mode, DEVICE_STRING_SHORT); - INIT_OBJ_RES_DUMMY(res, i, DEVICE_TYPE_ID); - INIT_OBJ_RES_DUMMY(res, i, DEVICE_HARDWARE_VERSION_ID); - INIT_OBJ_RES_DUMMY(res, i, DEVICE_SOFTWARE_VERSION_ID); - INIT_OBJ_RES_DATA(res, i, DEVICE_BATTERY_STATUS_ID, - &battery_status, sizeof(battery_status)); - INIT_OBJ_RES_DATA(res, i, DEVICE_MEMORY_TOTAL_ID, - &mem_total_kb, sizeof(mem_total_kb)); + INIT_OBJ_RES_OPT(DEVICE_CURRENT_TIME_ID, res, i, res_inst, j, 1, true, + current_time_read_cb, + current_time_pre_write_cb, + current_time_post_write_cb, NULL); + INIT_OBJ_RES_DATA(DEVICE_SUPPORTED_BINDING_MODES_ID, res, i, + res_inst, j, binding_mode, DEVICE_STRING_SHORT); + INIT_OBJ_RES_OPTDATA(DEVICE_TYPE_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_HARDWARE_VERSION_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_SOFTWARE_VERSION_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_BATTERY_STATUS_ID, res, i, res_inst, j); + INIT_OBJ_RES_OPTDATA(DEVICE_MEMORY_TOTAL_ID, res, i, res_inst, j); inst.resources = res; inst.resource_count = i; + LOG_DBG("Create LWM2M device instance: %d", obj_inst_id); return &inst; } @@ -322,21 +348,13 @@ static struct lwm2m_engine_obj_inst *device_create(u16_t obj_inst_id) static int lwm2m_device_init(struct device *dev) { struct lwm2m_engine_obj_inst *obj_inst = NULL; - int ret = 0, i; + int ret = 0; /* Set default values */ time_offset = 0U; - mem_total_kb = 0; - mem_free_kb = -1; - pwrsrc_count = 0U; - error_code_count = 0U; /* currently only support UDP binding mode (no SMS or Queue mode) */ strcpy(binding_mode, "U"); - for (i = 0; i < DEVICE_PWRSRC_MAX; i++) { - pwrsrc_available[i] = -1; - } - /* initialize the device field data */ device.obj_id = LWM2M_OBJECT_DEVICE_ID; device.fields = fields; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c index 6a8cd4dc94a..e34d3db481e 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware.c @@ -36,6 +36,13 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define PACKAGE_URI_LEN 255 +/* + * Calculate resource instances as follows: + * start with FIRMWARE_MAX_ID + * subtract EXEC resources (1) + */ +#define RESOURCE_INSTANCE_COUNT (FIRMWARE_MAX_ID - 1) + /* resource state variables */ static u8_t update_state; static u8_t update_result; @@ -57,7 +64,8 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst; -static struct lwm2m_engine_res_inst res[FIRMWARE_MAX_ID]; +static struct lwm2m_engine_res res[FIRMWARE_MAX_ID]; +static struct lwm2m_engine_res_inst res_inst[RESOURCE_INSTANCE_COUNT]; static lwm2m_engine_set_data_cb_t write_cb; static lwm2m_engine_user_cb_t update_cb; @@ -179,8 +187,8 @@ void lwm2m_firmware_set_update_result(u8_t result) LOG_DBG("Update result = %d", update_result); } -static int package_write_cb(u16_t obj_inst_id, - u8_t *data, u16_t data_len, +static int package_write_cb(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { u8_t state; @@ -203,7 +211,8 @@ static int package_write_cb(u16_t obj_inst_id, return -EPERM; } - ret = write_cb ? write_cb(obj_inst_id, data, data_len, + ret = write_cb ? write_cb(obj_inst_id, res_id, res_inst_id, + data, data_len, last_block, total_size) : 0; if (ret >= 0) { if (last_block) { @@ -227,8 +236,8 @@ static int package_write_cb(u16_t obj_inst_id, return ret; } -static int package_uri_write_cb(u16_t obj_inst_id, - u8_t *data, u16_t data_len, +static int package_uri_write_cb(u16_t obj_inst_id, u16_t res_id, + u16_t res_inst_id, u8_t *data, u16_t data_len, bool last_block, size_t total_size) { LOG_DBG("PACKAGE_URI WRITE: %s", log_strdup(package_uri)); @@ -301,25 +310,27 @@ static int firmware_update_cb(u16_t obj_inst_id) static struct lwm2m_engine_obj_inst *firmware_create(u16_t obj_inst_id) { - int i = 0; + int i = 0, j = 0; + + init_res_instance(res_inst, ARRAY_SIZE(res_inst)); /* initialize instance resource data */ - INIT_OBJ_RES(res, i, FIRMWARE_PACKAGE_ID, 0, NULL, 0, - NULL, NULL, package_write_cb, NULL); - INIT_OBJ_RES(res, i, FIRMWARE_PACKAGE_URI_ID, 0, + INIT_OBJ_RES_OPT(FIRMWARE_PACKAGE_ID, res, i, res_inst, j, 1, true, + NULL, NULL, package_write_cb, NULL); + INIT_OBJ_RES(FIRMWARE_PACKAGE_URI_ID, res, i, res_inst, j, 1, true, package_uri, PACKAGE_URI_LEN, NULL, NULL, package_uri_write_cb, NULL); - INIT_OBJ_RES_EXECUTE(res, i, FIRMWARE_UPDATE_ID, - firmware_update_cb); - INIT_OBJ_RES_DATA(res, i, FIRMWARE_STATE_ID, + INIT_OBJ_RES_EXECUTE(FIRMWARE_UPDATE_ID, res, i, firmware_update_cb); + INIT_OBJ_RES_DATA(FIRMWARE_STATE_ID, res, i, res_inst, j, &update_state, sizeof(update_state)); - INIT_OBJ_RES_DATA(res, i, FIRMWARE_UPDATE_RESULT_ID, + INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_RESULT_ID, res, i, res_inst, j, &update_result, sizeof(update_result)); - INIT_OBJ_RES_DATA(res, i, FIRMWARE_UPDATE_DELIV_METHOD_ID, + INIT_OBJ_RES_DATA(FIRMWARE_UPDATE_DELIV_METHOD_ID, res, i, res_inst, j, &delivery_method, sizeof(delivery_method)); inst.resources = res; inst.resource_count = i; + LOG_DBG("Create LWM2M firmware instance: %d", obj_inst_id); return &inst; } diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c b/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c index e6fe9ffd031..e58502983fa 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_firmware_pull.c @@ -238,7 +238,7 @@ do_firmware_transfer_reply_cb(const struct coap_packet *response, u8_t tkl; u16_t payload_len, payload_offset, len; struct coap_packet *check_response = (struct coap_packet *)response; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; lwm2m_engine_set_data_cb_t write_cb; size_t write_buflen; u8_t resp_code, *write_buf; @@ -311,12 +311,12 @@ do_firmware_transfer_reply_cb(const struct coap_packet *response, } /* get buffer data */ - write_buf = res->data_ptr; - write_buflen = res->data_len; + write_buf = res->res_instances->data_ptr; + write_buflen = res->res_instances->data_len; /* check for user override to buffer */ if (res->pre_write_cb) { - write_buf = res->pre_write_cb(0, &write_buflen); + write_buf = res->pre_write_cb(0, 0, 0, &write_buflen); } write_cb = lwm2m_firmware_get_write_cb(); @@ -335,7 +335,8 @@ do_firmware_transfer_reply_cb(const struct coap_packet *response, goto error; } - ret = write_cb(0, write_buf, len, last_block, + ret = write_cb(0, 0, 0, + write_buf, len, last_block, firmware_block_ctx.total_size); if (ret < 0) { goto error; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_security.c b/subsys/net/lib/lwm2m/lwm2m_obj_security.c index 8e4b3d66da1..0d2fa0bfeef 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_security.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_security.c @@ -40,6 +40,12 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define IDENTITY_LEN 128 #define KEY_LEN CONFIG_LWM2M_SECURITY_KEY_SIZE +/* + * Calculate resource instances as follows: + * start with SECURITY_MAX_ID + */ +#define RESOURCE_INSTANCE_COUNT (SECURITY_MAX_ID) + /* resource state variables */ static char security_uri[MAX_INSTANCE_COUNT][SECURITY_URI_LEN]; static u8_t client_identity[MAX_INSTANCE_COUNT][IDENTITY_LEN]; @@ -67,11 +73,13 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; -static struct lwm2m_engine_res_inst res[MAX_INSTANCE_COUNT][SECURITY_MAX_ID]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SECURITY_MAX_ID]; +static struct lwm2m_engine_res_inst + res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; static struct lwm2m_engine_obj_inst *security_create(u16_t obj_inst_id) { - int index, i = 0; + int index, i = 0, j = 0; /* Check that there is no other instance with this ID */ for (index = 0; index < MAX_INSTANCE_COUNT; index++) { @@ -101,25 +109,35 @@ static struct lwm2m_engine_obj_inst *security_create(u16_t obj_inst_id) security_mode[index] = 0U; short_server_id[index] = 0U; + init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index])); + /* initialize instance resource data */ - INIT_OBJ_RES_DATA(res[index], i, SECURITY_SERVER_URI_ID, + INIT_OBJ_RES_DATA(SECURITY_SERVER_URI_ID, res[index], i, + res_inst[index], j, security_uri[index], SECURITY_URI_LEN); - INIT_OBJ_RES_DATA(res[index], i, SECURITY_BOOTSTRAP_FLAG_ID, + INIT_OBJ_RES_DATA(SECURITY_BOOTSTRAP_FLAG_ID, res[index], i, + res_inst[index], j, &bootstrap_flag[index], sizeof(*bootstrap_flag)); - INIT_OBJ_RES_DATA(res[index], i, SECURITY_MODE_ID, + INIT_OBJ_RES_DATA(SECURITY_MODE_ID, res[index], i, + res_inst[index], j, &security_mode[index], sizeof(*security_mode)); - INIT_OBJ_RES_DATA(res[index], i, SECURITY_CLIENT_PK_ID, - &client_identity[index], IDENTITY_LEN), - INIT_OBJ_RES_DATA(res[index], i, SECURITY_SERVER_PK_ID, - &server_pk[index], KEY_LEN), - INIT_OBJ_RES_DATA(res[index], i, SECURITY_SECRET_KEY_ID, - &secret_key[index], KEY_LEN), - INIT_OBJ_RES_DATA(res[index], i, SECURITY_SHORT_SERVER_ID, + INIT_OBJ_RES_DATA(SECURITY_CLIENT_PK_ID, res[index], i, + res_inst[index], j, + &client_identity[index], IDENTITY_LEN); + INIT_OBJ_RES_DATA(SECURITY_SERVER_PK_ID, res[index], i, + res_inst[index], j, + &server_pk[index], KEY_LEN); + INIT_OBJ_RES_DATA(SECURITY_SECRET_KEY_ID, res[index], i, + res_inst[index], j, + &secret_key[index], KEY_LEN); + INIT_OBJ_RES_DATA(SECURITY_SHORT_SERVER_ID, res[index], i, + res_inst[index], j, &short_server_id[index], sizeof(*short_server_id)); inst[index].resources = res[index]; inst[index].resource_count = i; LOG_DBG("Create LWM2M security instance: %d", obj_inst_id); + return &inst[index]; } @@ -157,7 +175,7 @@ static int lwm2m_security_init(struct device *dev) /* Set default values */ (void)memset(inst, 0, sizeof(*inst) * MAX_INSTANCE_COUNT); - (void)memset(res, 0, sizeof(struct lwm2m_engine_res_inst) * + (void)memset(res, 0, sizeof(struct lwm2m_engine_res) * MAX_INSTANCE_COUNT * SECURITY_MAX_ID); security.obj_id = LWM2M_OBJECT_SECURITY_ID; diff --git a/subsys/net/lib/lwm2m/lwm2m_obj_server.c b/subsys/net/lib/lwm2m/lwm2m_obj_server.c index 12712dcb99c..c5fa5dde0af 100644 --- a/subsys/net/lib/lwm2m/lwm2m_obj_server.c +++ b/subsys/net/lib/lwm2m/lwm2m_obj_server.c @@ -41,6 +41,13 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define TRANSPORT_BINDING_LEN 4 +/* + * Calculate resource instances as follows: + * start with SERVER_MAX_ID + * subtract EXEC resources (2) + */ +#define RESOURCE_INSTANCE_COUNT (SERVER_MAX_ID - 2) + /* resource state variables */ static u16_t server_id[MAX_INSTANCE_COUNT]; static u32_t lifetime[MAX_INSTANCE_COUNT]; @@ -71,7 +78,9 @@ static struct lwm2m_engine_obj_field fields[] = { }; static struct lwm2m_engine_obj_inst inst[MAX_INSTANCE_COUNT]; -static struct lwm2m_engine_res_inst res[MAX_INSTANCE_COUNT][SERVER_MAX_ID]; +static struct lwm2m_engine_res res[MAX_INSTANCE_COUNT][SERVER_MAX_ID]; +static struct lwm2m_engine_res_inst + res_inst[MAX_INSTANCE_COUNT][RESOURCE_INSTANCE_COUNT]; static int disable_cb(u16_t obj_inst_id) { @@ -126,7 +135,7 @@ s32_t lwm2m_server_get_pmax(u16_t obj_inst_id) static struct lwm2m_engine_obj_inst *server_create(u16_t obj_inst_id) { - int index, i = 0; + int index, i = 0, j = 0; /* Check that there is no other instance with this ID */ for (index = 0; index < MAX_INSTANCE_COUNT; index++) { @@ -159,29 +168,38 @@ static struct lwm2m_engine_obj_inst *server_create(u16_t obj_inst_id) disabled_timeout[index] = 86400U; strcpy(transport_binding[index], "U"); + init_res_instance(res_inst[index], ARRAY_SIZE(res_inst[index])); + /* initialize instance resource data */ - INIT_OBJ_RES_DATA(res[index], i, SERVER_SHORT_SERVER_ID, + INIT_OBJ_RES_DATA(SERVER_SHORT_SERVER_ID, res[index], i, + res_inst[index], j, &server_id[index], sizeof(*server_id)); - INIT_OBJ_RES_DATA(res[index], i, SERVER_LIFETIME_ID, + INIT_OBJ_RES_DATA(SERVER_LIFETIME_ID, res[index], i, + res_inst[index], j, &lifetime[index], sizeof(*lifetime)); - INIT_OBJ_RES_DATA(res[index], i, SERVER_DEFAULT_MIN_PERIOD_ID, + INIT_OBJ_RES_DATA(SERVER_DEFAULT_MIN_PERIOD_ID, res[index], i, + res_inst[index], j, &default_min_period[index], sizeof(*default_min_period)); - INIT_OBJ_RES_DATA(res[index], i, SERVER_DEFAULT_MAX_PERIOD_ID, + INIT_OBJ_RES_DATA(SERVER_DEFAULT_MAX_PERIOD_ID, res[index], i, + res_inst[index], j, &default_max_period[index], sizeof(*default_max_period)); - INIT_OBJ_RES_EXECUTE(res[index], i, SERVER_DISABLE_ID, disable_cb); - INIT_OBJ_RES_DATA(res[index], i, SERVER_DISABLE_TIMEOUT_ID, + INIT_OBJ_RES_EXECUTE(SERVER_DISABLE_ID, res[index], i, disable_cb); + INIT_OBJ_RES_DATA(SERVER_DISABLE_TIMEOUT_ID, res[index], i, + res_inst[index], j, &disabled_timeout[index], sizeof(*disabled_timeout)); - INIT_OBJ_RES_DATA(res[index], i, SERVER_STORE_NOTIFY_ID, + INIT_OBJ_RES_DATA(SERVER_STORE_NOTIFY_ID, res[index], i, + res_inst[index], j, &server_flag_store_notify[index], sizeof(*server_flag_store_notify)); /* Mark Transport Binding RO as we only support UDP atm */ - INIT_OBJ_RES_DATA(res[index], i, SERVER_TRANSPORT_BINDING_ID, + INIT_OBJ_RES_DATA(SERVER_TRANSPORT_BINDING_ID, res[index], i, + res_inst[index], j, transport_binding[index], TRANSPORT_BINDING_LEN); - INIT_OBJ_RES_EXECUTE(res[index], i, SERVER_REG_UPDATE_TRIGGER_ID, - update_trigger_cb); + INIT_OBJ_RES_EXECUTE(SERVER_REG_UPDATE_TRIGGER_ID, res[index], i, + update_trigger_cb); inst[index].resources = res[index]; inst[index].resource_count = i; @@ -196,7 +214,7 @@ static int lwm2m_server_init(struct device *dev) /* Set default values */ (void)memset(inst, 0, sizeof(*inst) * MAX_INSTANCE_COUNT); - (void)memset(res, 0, sizeof(struct lwm2m_engine_res_inst) * + (void)memset(res, 0, sizeof(struct lwm2m_engine_res) * MAX_INSTANCE_COUNT * SERVER_MAX_ID); server.obj_id = LWM2M_OBJECT_SERVER_ID; diff --git a/subsys/net/lib/lwm2m/lwm2m_object.h b/subsys/net/lib/lwm2m/lwm2m_object.h index 43688d987bf..7a6a7f1e61f 100644 --- a/subsys/net/lib/lwm2m/lwm2m_object.h +++ b/subsys/net/lib/lwm2m/lwm2m_object.h @@ -192,32 +192,112 @@ struct lwm2m_engine_obj { u16_t max_instance_count; }; -#define INIT_OBJ_RES(res_var, index_var, id_val, multi_var, \ - data_val, data_val_len, r_cb, pre_w_cb, post_w_cb, ex_cb) \ - res_var[index_var].res_id = id_val; \ - res_var[index_var].multi_count_var = multi_var; \ - res_var[index_var].data_ptr = data_val; \ - res_var[index_var].data_len = data_val_len; \ - res_var[index_var].read_cb = r_cb; \ - res_var[index_var].pre_write_cb = pre_w_cb; \ - res_var[index_var].post_write_cb = post_w_cb; \ - res_var[index_var++].execute_cb = ex_cb +/* Resource instances with this value are considered "not created" yet */ +#define RES_INSTANCE_NOT_CREATED 65535 -#define INIT_OBJ_RES_MULTI_DATA(res_var, index_var, id_val, multi_var, \ - data_val, data_val_len) \ - INIT_OBJ_RES(res_var, index_var, id_val, multi_var, data_val, \ - data_val_len, NULL, NULL, NULL, NULL) +/* Resource macros */ +#define _INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_count, \ + _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \ + _r_ptr[_r_idx].res_id = _id; \ + _r_ptr[_r_idx].res_instances = _ri_ptr; \ + _r_ptr[_r_idx].res_inst_count = _ri_count; \ + _r_ptr[_r_idx].read_cb = _r_cb; \ + _r_ptr[_r_idx].pre_write_cb = _pre_w_cb; \ + _r_ptr[_r_idx].post_write_cb = _post_w_cb; \ + _r_ptr[_r_idx].execute_cb = _ex_cb -#define INIT_OBJ_RES_DATA(res_var, index_var, id_val, data_val, data_val_len) \ - INIT_OBJ_RES_MULTI_DATA(res_var, index_var, id_val, NULL, \ - data_val, data_val_len) +#define _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \ + _data_ptr, _data_len) \ + do { \ + if (_ri_ptr != NULL && _ri_count > 0) { \ + for (int _i = 0; _i < _ri_count; _i++) { \ + _ri_ptr[_ri_idx + _i].data_ptr = \ + (_data_ptr + _i); \ + _ri_ptr[_ri_idx + _i].data_len = \ + _data_len; \ + if (_ri_create) { \ + _ri_ptr[_ri_idx + _i].res_inst_id = \ + _i; \ + } else { \ + _ri_ptr[_ri_idx + _i].res_inst_id = \ + RES_INSTANCE_NOT_CREATED; \ + } \ + } \ + } \ + _ri_idx += _ri_count; \ + } while (false) -#define INIT_OBJ_RES_DUMMY(res_var, index_var, id_val) \ - INIT_OBJ_RES_MULTI_DATA(res_var, index_var, id_val, NULL, NULL, 0) +#define _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create) \ + do { \ + if (_ri_count > 0) { \ + for (int _i = 0; _i < _ri_count; _i++) { \ + _ri_ptr[_ri_idx + _i].data_ptr = NULL; \ + _ri_ptr[_ri_idx + _i].data_len = 0; \ + if (_ri_create) { \ + _ri_ptr[_ri_idx + _i].res_inst_id = \ + _i; \ + } else { \ + _ri_ptr[_ri_idx + _i].res_inst_id = \ + RES_INSTANCE_NOT_CREATED; \ + } \ + } \ + } \ + _ri_idx += _ri_count; \ + } while (false) -#define INIT_OBJ_RES_EXECUTE(res_var, index_var, id_val, ex_cb) \ - INIT_OBJ_RES(res_var, index_var, id_val, NULL, NULL, 0, \ - NULL, NULL, NULL, ex_cb) +#define INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ + _ri_ptr, _ri_idx, _ri_count, _ri_create, \ + _data_ptr, _data_len, \ + _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \ + do { \ + _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ + (_ri_ptr + _ri_idx), _ri_count, \ + _r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \ + _INIT_OBJ_RES_INST(_ri_ptr, _ri_idx, _ri_count, _ri_create, \ + _data_ptr, _data_len); \ + ++_r_idx; \ + } while (false) + + +#define INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \ + _ri_ptr, _ri_idx, _ri_count, _ri_create, \ + _r_cb, _pre_w_cb, _post_w_cb, _ex_cb) \ + do { \ + _INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ + (_ri_ptr + _ri_idx), _ri_count, \ + _r_cb, _pre_w_cb, _post_w_cb, _ex_cb); \ + _INIT_OBJ_RES_INST_OPT(_ri_ptr, _ri_idx, _ri_count, _ri_create); \ + ++_r_idx; \ + } while (false) + +#define INIT_OBJ_RES_MULTI_DATA(_id, _r_ptr, _r_idx, \ + _ri_ptr, _ri_idx, _ri_count, _ri_create, \ + _data_ptr, _data_len) \ + INIT_OBJ_RES(_id, _r_ptr, _r_idx, \ + _ri_ptr, _ri_idx, _ri_count, _ri_create, \ + _data_ptr, _data_len, NULL, NULL, NULL, NULL) + +#define INIT_OBJ_RES_MULTI_OPTDATA(_id, _r_ptr, _r_idx, \ + _ri_ptr, _ri_idx, _ri_count, _ri_create) \ + INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, \ + _ri_ptr, _ri_idx, _ri_count, _ri_create, \ + NULL, NULL, NULL, NULL) + +#define INIT_OBJ_RES_DATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, \ + _data_ptr, _data_len) \ + INIT_OBJ_RES(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, true, \ + _data_ptr, _data_len, NULL, NULL, NULL, NULL) + +#define INIT_OBJ_RES_OPTDATA(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx) \ + INIT_OBJ_RES_OPT(_id, _r_ptr, _r_idx, _ri_ptr, _ri_idx, 1U, true, \ + NULL, NULL, NULL, NULL) + +#define INIT_OBJ_RES_EXECUTE(_id, _r_ptr, _r_idx, _ex_cb) \ + do { \ + _INIT_OBJ_RES(_id, _r_ptr, _r_idx, NULL, 0, \ + NULL, NULL, NULL, _ex_cb); \ + ++_r_idx; \ + } while (false) #define LWM2M_ATTR_PMIN 0 @@ -241,31 +321,47 @@ struct lwm2m_attr { }; struct lwm2m_engine_res_inst { - /* callbacks set by user code on obj instance */ - lwm2m_engine_get_data_cb_t read_cb; - lwm2m_engine_get_data_cb_t pre_write_cb; - lwm2m_engine_set_data_cb_t post_write_cb; - lwm2m_engine_user_cb_t execute_cb; - - u8_t *multi_count_var; void *data_ptr; u16_t data_len; - u16_t res_id; + u16_t res_inst_id; /* 65535 == not "created" */ u8_t data_flags; }; +struct lwm2m_engine_res { + lwm2m_engine_get_data_cb_t read_cb; + lwm2m_engine_get_data_cb_t pre_write_cb; + lwm2m_engine_set_data_cb_t post_write_cb; + lwm2m_engine_user_cb_t execute_cb; + + struct lwm2m_engine_res_inst *res_instances; + u16_t res_id; + u8_t res_inst_count; +}; + struct lwm2m_engine_obj_inst { /* instance list */ sys_snode_t node; struct lwm2m_engine_obj *obj; - struct lwm2m_engine_res_inst *resources; + struct lwm2m_engine_res *resources; /* object instance member data */ u16_t obj_inst_id; u16_t resource_count; }; +/* Initialize resource instances prior to use */ +static inline void init_res_instance(struct lwm2m_engine_res_inst *ri, + size_t ri_len) +{ + size_t i; + + memset(ri, 0, sizeof(*ri) * ri_len); + for (i = 0; i < ri_len; i++) { + ri[i].res_inst_id = RES_INSTANCE_NOT_CREATED; + } +} + struct lwm2m_output_context { const struct lwm2m_writer *writer; struct coap_packet *out_cpkt; diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_json.c b/subsys/net/lib/lwm2m/lwm2m_rw_json.c index d55eaeb0dcd..c5c29d6653b 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_json.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_json.c @@ -747,6 +747,8 @@ static int parse_path(const u8_t *buf, u16_t buflen, path->obj_inst_id = val; } else if (ret == 2) { path->res_id = val; + } else if (ret == 3) { + path->res_inst_id = val; } ret++; @@ -763,9 +765,10 @@ static int parse_path(const u8_t *buf, u16_t buflen, int do_write_op_json(struct lwm2m_message *msg) { - struct lwm2m_engine_obj_field *obj_field; + struct lwm2m_engine_obj_field *obj_field = NULL; struct lwm2m_engine_obj_inst *obj_inst = NULL; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; struct lwm2m_obj_path orig_path; struct json_in_formatter_data fd; int ret = 0, index; @@ -881,11 +884,24 @@ int do_write_op_json(struct lwm2m_message *msg) ret = -ENOENT; break; } - } else if (res) { + + for (index = 0; index < res->res_inst_count; index++) { + if (res->res_instances[index].res_inst_id == + msg->path.res_inst_id) { + res_inst = &res->res_instances[index]; + break; + } + } + + if (!res_inst) { + ret = -ENOENT; + break; + } + } else if (res && res_inst) { /* handle value assignment */ - ret = lwm2m_write_handler(obj_inst, res, obj_field, - msg); - if (orig_path.level == 3U && ret < 0) { + ret = lwm2m_write_handler(obj_inst, res, res_inst, + obj_field, msg); + if (orig_path.level >= 3U && ret < 0) { /* return errors on a single write */ break; } diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c b/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c index 2bdca18105e..7b48fd55798 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_oma_tlv.c @@ -492,7 +492,7 @@ static size_t put_string(struct lwm2m_output_context *out, } tlv_setup(&tlv, tlv_calc_type(fd->writer_flags), - path->res_id, (u32_t)buflen); + tlv_calc_id(fd->writer_flags, path), (u32_t)buflen); len = oma_tlv_put(&tlv, out, (u8_t *)buf, false); return len; } @@ -807,7 +807,8 @@ static int do_write_op_tlv_dummy_read(struct lwm2m_message *msg) static int do_write_op_tlv_item(struct lwm2m_message *msg) { struct lwm2m_engine_obj_inst *obj_inst = NULL; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; struct lwm2m_engine_obj_field *obj_field = NULL; u8_t created = 0U; int ret, i; @@ -841,7 +842,17 @@ static int do_write_op_tlv_item(struct lwm2m_message *msg) } } - if (!res) { + if (res) { + for (i = 0; i < res->res_inst_count; i++) { + if (res->res_instances[i].res_inst_id == + msg->path.res_inst_id) { + res_inst = &res->res_instances[i]; + break; + } + } + } + + if (!res || !res_inst) { /* if OPTIONAL and BOOTSTRAP-WRITE or CREATE use ENOTSUP */ if ((msg->ctx->bootstrap_mode || msg->operation == LWM2M_OP_CREATE) && @@ -854,7 +865,7 @@ static int do_write_op_tlv_item(struct lwm2m_message *msg) goto error; } - ret = lwm2m_write_handler(obj_inst, res, obj_field, msg); + ret = lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg); if (ret == -EACCES || ret == -ENOENT) { /* if read-only or non-existent data buffer move on */ do_write_op_tlv_dummy_read(msg); diff --git a/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c b/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c index 154c9c74819..45fa0d8ad97 100644 --- a/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c +++ b/subsys/net/lib/lwm2m/lwm2m_rw_plain_text.c @@ -330,7 +330,8 @@ int do_write_op_plain_text(struct lwm2m_message *msg) { struct lwm2m_engine_obj_inst *obj_inst = NULL; struct lwm2m_engine_obj_field *obj_field; - struct lwm2m_engine_res_inst *res = NULL; + struct lwm2m_engine_res *res = NULL; + struct lwm2m_engine_res_inst *res_inst = NULL; int ret, i; u8_t created = 0U; @@ -363,6 +364,21 @@ int do_write_op_plain_text(struct lwm2m_message *msg) return -ENOENT; } - msg->path.level = 3U; - return lwm2m_write_handler(obj_inst, res, obj_field, msg); + for (i = 0; i < res->res_inst_count; i++) { + if (res->res_instances[i].res_inst_id == + msg->path.res_inst_id) { + res_inst = &res->res_instances[i]; + break; + } + } + + if (!res_inst) { + return -ENOENT; + } + + if (msg->path.level < 3) { + msg->path.level = 3U; + } + + return lwm2m_write_handler(obj_inst, res, res_inst, obj_field, msg); }