<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LwM2M Callback Reentrancy</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/95306/lwm2m-callback-reentrancy</link><description>Hi, 
 A few questions regarding LwM2M engine I haven&amp;#39;t been able to find the answers to in documentation: 
 
 Do callbacks registered for LwM2M by calling lwm2m_engine_register_validate_callback() or lwm2m_engine_register_post_write_callback() need to</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 09 Jan 2023 11:23:45 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/95306/lwm2m-callback-reentrancy" /><item><title>RE: LwM2M Callback Reentrancy</title><link>https://devzone.nordicsemi.com/thread/403812?ContentTypeID=1</link><pubDate>Mon, 09 Jan 2023 11:23:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:dec8d482-7f7a-467e-badc-111ec1edcfe6</guid><dc:creator>&amp;#216;yvind</dc:creator><description>&lt;p&gt;Hello,&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Our LwM2M team has provided the following answers:&lt;/p&gt;
[quote user=""]Do callbacks registered for LwM2M by calling &lt;span style="font-family:courier new, courier;"&gt;lwm2m_engine_register_validate_callback()&lt;/span&gt; or &lt;span style="font-family:courier new, courier;"&gt;lwm2m_engine_register_post_write_callback()&lt;/span&gt; need to be &lt;em&gt;reentrant safe&lt;/em&gt;, or does the LwM2M engine take care of not calling the same callback until previous invocation has returned?[/quote]
&lt;p&gt;Callbacks from LwM2M engine are coming from its thread context while processing the data. So callback effectively blocks the LwM2M engine until it returns. Therefore simultaneous callbacks cannot happen at a same time.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div&gt;[quote user=""]If the server writes multiple values to the same path (same object, instance and resource ID), does the write callback get fired for all the values, or does the engine only call the callback with the most recent value?[/quote]
&lt;p&gt;Callback happens every time the value changes in the LwM2M resource buffer. So if a message contains multiple values for one resource, it causes multiple callbacks. Callbacks are executed while parsing the message.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;div&gt;[quote user=""]If the engine calls the callback for each write operation, does it mean the engine will manage the buffer for all the write operations? For instance, if the LwM2M server writes 128 bytes of data to /1234/0/0, 10 times in a row, does the LwM2M engine consume up to one kilobyte of memory while calling the callback for each write operation?[/quote]
&lt;p&gt;Each resource has only one buffer. Pointers in the callback are pointing the same buffer space that is set for the resource, these are not temporary buffers. Buffers are set up by the object, or can be overwritten by an application using lwm2m_engine_set_res_buf().&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Øyvind&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LwM2M Callback Reentrancy</title><link>https://devzone.nordicsemi.com/thread/403364?ContentTypeID=1</link><pubDate>Thu, 05 Jan 2023 11:22:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:e96dd970-e8ea-439e-a3c2-65e72847f45b</guid><dc:creator>ibiglari</dc:creator><description>&lt;p&gt;Hi,&lt;/p&gt;
&lt;p&gt;Thanks for your reply.&lt;/p&gt;
[quote userid="77062" url="~/f/nordic-q-a/95306/lwm2m-callback-reentrancy/402998"]I will need to forward your questions to our LwM2M team.&amp;nbsp;[/quote]
&lt;p&gt;That would be great!&lt;/p&gt;
&lt;p&gt;Kind Regards,&lt;br /&gt;Iman&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: LwM2M Callback Reentrancy</title><link>https://devzone.nordicsemi.com/thread/402998?ContentTypeID=1</link><pubDate>Tue, 03 Jan 2023 14:22:35 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:82dc1826-f53f-4f31-bee8-14c0fc20444c</guid><dc:creator>&amp;#216;yvind</dc:creator><description>&lt;p&gt;Hello Imam,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I will need to forward your questions to our LwM2M team.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;From&amp;nbsp;&lt;em&gt;zephyr\include\zephyr\net\lwm2m.h &lt;/em&gt;it states&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**
 * @brief Asynchronous callback when data has been set to a resource buffer.
 *
 * After changing the data of a resource buffer, the LwM2M engine can
 * make use of this callback to pass the data back to the client or LwM2M
 * objects.
 *
 * A function of this type can be registered via:
 * lwm2m_engine_register_validate_callback()
 * 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
 *                       block of data. For non-block transfers this is always
 *                       false.
 * @param[in] total_size Expected total size of data for a block transfer.
 *                       For non-block transfers this is 0.
 *
 * @return Callback returns a negative error code (errno.h) indicating
 *         reason of failure or 0 for success.
 */
typedef int (*lwm2m_engine_set_data_cb_t)(uint16_t obj_inst_id,
					  uint16_t res_id, uint16_t res_inst_id,
					  uint8_t *data, uint16_t data_len,
					  bool last_block, size_t total_size);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/**
 * @brief Set resource (instance) validation callback
 *
 * This callback is triggered before setting the value of a resource to the
 * resource data buffer.
 *
 * The callback allows an LwM2M client or object to validate the data before
 * writing and notify an error if the data should be discarded for any reason
 * (by returning a negative error code).
 *
 * @note All resources that have a validation callback registered are initially
 *       decoded into a temporary validation buffer. Make sure that
 *       ``CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE`` is large enough to
 *       store each of the validated resources (individually).
 *
 * @param[in] pathstr LwM2M path string &amp;quot;obj/obj-inst/res(/res-inst)&amp;quot;
 * @param[in] cb Validate resource data callback
 *
 * @return 0 for success or negative in case of error.
 */
int lwm2m_engine_register_validate_callback(const char *pathstr,
					    lwm2m_engine_set_data_cb_t cb);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt; /**
 * @brief Set resource (instance) post-write callback
 *
 * This callback is triggered after setting the value of a resource to the
 * resource data buffer.
 *
 * It allows an LwM2M client or object to post-process the value of a resource
 * or trigger other related resource calculations.
 *
 * @param[in] pathstr LwM2M path string &amp;quot;obj/obj-inst/res(/res-inst)&amp;quot;
 * @param[in] cb Post-write resource callback
 *
 * @return 0 for success or negative in case of error.
 */
int lwm2m_engine_register_post_write_callback(const char *pathstr,
					      lwm2m_engine_set_data_cb_t cb);&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;From &lt;em&gt;zephyr\subsys\net\lib\lwm2m\Kconfig&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;config LWM2M_ENGINE_VALIDATION_BUFFER_SIZE
	int &amp;quot;Size of the validation buffer for the incoming data&amp;quot;
	default 64
	help
	  LwM2M will use the validation buffer during the write operation, to
	  decode the resource value before validating it (applies for resources
	  for which validation callback has been registered). Set this value to
	  the maximum expected size of the resources that need to be validated
	  (and thus have validation callback registered).
	  Setting the validation buffer size to 0 disables validation support.&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;From&amp;nbsp;&lt;em&gt;zephyr\subsys\net\lib\lwm2m\lwm2m_registry.c&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;int lwm2m_engine_register_validate_callback(const char *pathstr, lwm2m_engine_set_data_cb_t cb)
{
#if CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE &amp;gt; 0
	int ret;
	struct lwm2m_engine_res *res = NULL;

	ret = lwm2m_engine_get_resource(pathstr, &amp;amp;res);
	if (ret &amp;lt; 0) {
		return ret;
	}

	res-&amp;gt;validate_cb = cb;
	return 0;
#else
	ARG_UNUSED(pathstr);
	ARG_UNUSED(cb);

	LOG_ERR(&amp;quot;Validation disabled. Set &amp;quot;
		&amp;quot;CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE &amp;gt; 0 to &amp;quot;
		&amp;quot;enable validation support.&amp;quot;);
	return -ENOTSUP;
#endif /* CONFIG_LWM2M_ENGINE_VALIDATION_BUFFER_SIZE &amp;gt; 0 */
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;int lwm2m_engine_register_post_write_callback(const char *pathstr, lwm2m_engine_set_data_cb_t cb)
{
	int ret;
	struct lwm2m_engine_res *res = NULL;

	ret = lwm2m_engine_get_resource(pathstr, &amp;amp;res);
	if (ret &amp;lt; 0) {
		return ret;
	}

	res-&amp;gt;post_write_cb = cb;
	return 0;
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Kind regards,&lt;br /&gt;Øyvind&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>