2 ******************************************************************************
3 * @addtogroup UAVObjects OpenPilot UAVObjects
5 * @addtogroup UAV Object Manager
6 * @brief The core UAV Objects functions, most of which are wrappered by
7 * autogenerated defines
11 * @file uavobjectmanager.h
12 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
13 * @brief Object manager library. This library holds a collection of all objects.
14 * It can be used by all modules/libraries to find an object reference.
15 * @see The GNU Public License (GPL) Version 3
17 *****************************************************************************/
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation; either version 3 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful, but
25 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
26 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
29 * You should have received a copy of the GNU General Public License along
30 * with this program; if not, write to the Free Software Foundation, Inc.,
31 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 #include "openpilot.h"
35 #include "pios_struct_helper.h"
36 #include "inc/uavobjectprivate.h"
39 static InstanceHandle
createInstance(struct UAVOData
*obj
, uint16_t instId
);
40 static int32_t connectObj(UAVObjHandle obj_handle
, xQueueHandle queue
, UAVObjEventCallback cb
, uint8_t eventMask
, bool fast
);
41 static int32_t disconnectObj(UAVObjHandle obj_handle
, xQueueHandle queue
, UAVObjEventCallback cb
);
42 static void instanceAutoUpdated(UAVObjHandle obj_handle
, uint16_t instId
);
45 int32_t UAVObjPers_stub(__attribute__((unused
)) UAVObjHandle obj_handle
, __attribute__((unused
)) uint16_t instId
)
49 int32_t UAVObjSave(UAVObjHandle obj_handle
, uint16_t instId
) __attribute__((weak
, alias("UAVObjPers_stub")));;
50 int32_t UAVObjLoad(UAVObjHandle obj_handle
, uint16_t instId
) __attribute__((weak
, alias("UAVObjPers_stub")));
51 int32_t UAVObjDelete(UAVObjHandle obj_handle
, uint16_t instId
) __attribute__((weak
, alias("UAVObjPers_stub")));
55 static xSemaphoreHandle mutex
;
56 static const UAVObjMetadata defMetadata
= {
57 .flags
= (ACCESS_READWRITE
<< UAVOBJ_ACCESS_SHIFT
|
58 ACCESS_READWRITE
<< UAVOBJ_GCS_ACCESS_SHIFT
|
59 1 << UAVOBJ_TELEMETRY_ACKED_SHIFT
|
60 1 << UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
|
61 UPDATEMODE_ONCHANGE
<< UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
|
62 UPDATEMODE_ONCHANGE
<< UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
),
63 .telemetryUpdatePeriod
= 0,
64 .gcsTelemetryUpdatePeriod
= 0,
65 .loggingUpdatePeriod
= 0,
68 static UAVObjStats stats
;
71 static inline bool IsMetaobject(UAVObjHandle obj_handle
)
73 /* Recover the common object header */
74 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
76 return uavo_base
->flags
.isMeta
;
79 static inline bool IsSingleInstance(UAVObjHandle obj_handle
)
81 /* Recover the common object header */
82 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
84 return uavo_base
->flags
.isSingle
;
87 static inline bool IsSettings(UAVObjHandle obj_handle
)
89 /* Recover the common object header */
90 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
92 return uavo_base
->flags
.isSettings
;
95 static inline bool IsPriority(UAVObjHandle obj_handle
)
97 /* Recover the common object header */
98 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
100 return uavo_base
->flags
.isPriority
;
104 * Is this a metaobject?
105 * \param[in] obj The object handle
106 * \return True (1) if this is metaobject
108 bool UAVObjIsMetaobject(UAVObjHandle obj_handle
)
110 PIOS_Assert(obj_handle
);
111 return IsMetaobject(obj_handle
);
115 * Does this object contains a single instance or multiple instances?
116 * \param[in] obj The object handle
117 * \return True (1) if this is a single instance object
119 bool UAVObjIsSingleInstance(UAVObjHandle obj_handle
)
121 PIOS_Assert(obj_handle
);
122 return IsSingleInstance(obj_handle
);
126 * Is this a settings object?
127 * \param[in] obj The object handle
128 * \return True (1) if this is a settings object
130 bool UAVObjIsSettings(UAVObjHandle obj_handle
)
132 PIOS_Assert(obj_handle
);
133 return IsSettings(obj_handle
);
138 * Is this a prioritized object?
139 * \param[in] obj The object handle
140 * \return True (1) if this is a prioritized object
142 bool UAVObjIsPriority(UAVObjHandle obj_handle
)
144 return IsPriority(obj_handle
);
149 * Initialize the object manager
153 int32_t UAVObjInitialize()
155 // Initialize variables
156 memset(&stats
, 0, sizeof(UAVObjStats
));
158 /* Initialize _uavo_handles start/stop pointers */
159 #if (defined(__MACH__) && defined(__APPLE__))
160 uint64_t aslr_offset
= (uint64_t)&_aslr_offset
- getsectbyname("__DATA", "_aslr")->addr
;
161 __start__uavo_handles
= (struct UAVOData
* *)(getsectbyname("__DATA", "_uavo_handles")->addr
+ aslr_offset
);
162 __stop__uavo_handles
= (struct UAVOData
* *)((uint64_t)__start__uavo_handles
+ getsectbyname("__DATA", "_uavo_handles")->size
);
165 // Initialize the uavo handle table
166 memset(__start__uavo_handles
, 0,
167 (uintptr_t)__stop__uavo_handles
- (uintptr_t)__start__uavo_handles
);
170 mutex
= xSemaphoreCreateRecursiveMutex();
184 * Get the statistics counters
185 * @param[out] statsOut The statistics counters will be copied there
187 void UAVObjGetStats(UAVObjStats
*statsOut
)
189 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
190 memcpy(statsOut
, &stats
, sizeof(UAVObjStats
));
191 xSemaphoreGiveRecursive(mutex
);
195 * Clear the statistics counters
197 void UAVObjClearStats()
199 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
200 memset(&stats
, 0, sizeof(UAVObjStats
));
201 xSemaphoreGiveRecursive(mutex
);
204 /************************
205 * Object Initialization
206 ***********************/
208 static void UAVObjInitMetaData(struct UAVOMeta
*obj_meta
)
210 /* Fill in the common part of the UAVO */
211 struct UAVOBase
*uavo_base
= &(obj_meta
->base
);
213 memset(uavo_base
, 0, sizeof(*uavo_base
));
214 uavo_base
->flags
.isMeta
= true;
215 uavo_base
->flags
.isSingle
= true;
216 uavo_base
->next_event
= NULL
;
218 /* Clear the instance data carried in the UAVO */
219 memset(&(obj_meta
->instance0
), 0, sizeof(obj_meta
->instance0
));
222 static struct UAVOData
*UAVObjAllocSingle(uint32_t num_bytes
)
224 /* Compute the complete size of the object, including the data for a single embedded instance */
225 uint32_t object_size
= sizeof(struct UAVOSingle
) + num_bytes
;
227 /* Allocate the object from the heap */
228 struct UAVOSingle
*uavo_single
= (struct UAVOSingle
*)pios_malloc(object_size
);
234 /* Fill in the common part of the UAVO */
235 struct UAVOBase
*uavo_base
= &(uavo_single
->uavo
.base
);
236 memset(uavo_base
, 0, sizeof(*uavo_base
));
237 uavo_base
->flags
.isSingle
= true;
238 uavo_base
->next_event
= NULL
;
240 /* Clear the instance data carried in the UAVO */
241 memset(&(uavo_single
->instance0
), 0, num_bytes
);
243 /* Give back the generic UAVO part */
244 return &(uavo_single
->uavo
);
247 static struct UAVOData
*UAVObjAllocMulti(uint32_t num_bytes
)
249 /* Compute the complete size of the object, including the data for a single embedded instance */
250 uint32_t object_size
= sizeof(struct UAVOMulti
) + num_bytes
;
252 /* Allocate the object from the heap */
253 struct UAVOMulti
*uavo_multi
= (struct UAVOMulti
*)pios_malloc(object_size
);
259 /* Fill in the common part of the UAVO */
260 struct UAVOBase
*uavo_base
= &(uavo_multi
->uavo
.base
);
261 memset(uavo_base
, 0, sizeof(*uavo_base
));
262 uavo_base
->flags
.isSingle
= false;
263 uavo_base
->next_event
= NULL
;
265 /* Set up the type-specific part of the UAVO */
266 uavo_multi
->num_instances
= 1;
268 /* Clear the multi instance data carried in the UAVO */
269 memset(&(uavo_multi
->instance0
), 0, sizeof(struct UAVOMultiInst
) + num_bytes
);
271 /* Give back the generic UAVO part */
272 return &(uavo_multi
->uavo
);
275 /**************************
276 * UAVObject Database APIs
277 *************************/
280 * Register and new object in the object manager.
281 * \param[in] id Unique object ID
282 * \param[in] isSingleInstance Is this a single instance or multi-instance object
283 * \param[in] isSettings Is this a settings object
284 * \param[in] numBytes Number of bytes of object data (for one instance)
285 * \param[in] initCb Default field and metadata initialization function
286 * \return Object handle, or NULL if failure.
289 UAVObjHandle
UAVObjRegister(uint32_t id
,
290 bool isSingleInstance
, bool isSettings
, bool isPriority
,
292 UAVObjInitializeCallback initCb
)
294 struct UAVOData
*uavo_data
= NULL
;
296 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
298 /* Don't allow duplicate registrations */
299 if (UAVObjGetByID(id
)) {
303 /* Map the various flags to one of the UAVO types we understand */
304 if (isSingleInstance
) {
305 uavo_data
= UAVObjAllocSingle(num_bytes
);
307 uavo_data
= UAVObjAllocMulti(num_bytes
);
314 /* Fill in the details about this UAVO */
316 uavo_data
->instance_size
= num_bytes
;
318 uavo_data
->base
.flags
.isSettings
= true;
319 // settings defaults to being sent with priority
320 uavo_data
->base
.flags
.isPriority
= true;
322 uavo_data
->base
.flags
.isPriority
= isPriority
;
324 /* Initialize the embedded meta UAVO */
325 UAVObjInitMetaData(&uavo_data
->metaObj
);
327 /* Initialize object fields and metadata to default values */
329 initCb((UAVObjHandle
)uavo_data
, 0);
332 /* Always try to load the meta object from flash */
333 UAVObjLoad((UAVObjHandle
) & (uavo_data
->metaObj
), 0);
335 /* Attempt to load settings object from flash */
336 if (uavo_data
->base
.flags
.isSettings
) {
337 UAVObjLoad((UAVObjHandle
)uavo_data
, 0);
340 // fire events for outer object and its embedded meta object
341 instanceAutoUpdated((UAVObjHandle
)uavo_data
, 0);
342 instanceAutoUpdated((UAVObjHandle
) & (uavo_data
->metaObj
), 0);
345 xSemaphoreGiveRecursive(mutex
);
346 return (UAVObjHandle
)uavo_data
;
350 * Retrieve an object from the list given its id
351 * \param[in] The object ID
352 * \return The object or NULL if not found.
354 UAVObjHandle
UAVObjGetByID(uint32_t id
)
356 UAVObjHandle
*found_obj
= (UAVObjHandle
*)NULL
;
359 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
362 UAVO_LIST_ITERATE(tmp_obj
)
363 if (tmp_obj
->id
== id
) {
364 found_obj
= (UAVObjHandle
*)tmp_obj
;
367 if (MetaObjectId(tmp_obj
->id
) == id
) {
368 found_obj
= (UAVObjHandle
*)&(tmp_obj
->metaObj
);
374 xSemaphoreGiveRecursive(mutex
);
379 * Get the object's ID
380 * \param[in] obj The object handle
381 * \return The object ID
383 uint32_t UAVObjGetID(UAVObjHandle obj_handle
)
385 PIOS_Assert(obj_handle
);
387 /* Recover the common object header */
388 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
390 if (IsMetaobject(obj_handle
)) {
391 /* We have a meta object, find our containing UAVO */
392 struct UAVOData
*uavo_data
= container_of((struct UAVOMeta
*)uavo_base
, struct UAVOData
, metaObj
);
394 return MetaObjectId(uavo_data
->id
);
396 /* We have a data object, augment our pointer */
397 struct UAVOData
*uavo_data
= (struct UAVOData
*)uavo_base
;
399 return uavo_data
->id
;
404 * Get the number of bytes of the object's data (for one instance)
405 * \param[in] obj The object handle
406 * \return The number of bytes
408 uint32_t UAVObjGetNumBytes(UAVObjHandle obj
)
412 uint32_t instance_size
;
414 /* Recover the common object header */
415 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj
;
417 if (uavo_base
->flags
.isMeta
) {
418 instance_size
= MetaNumBytes
;
420 /* We have a data object, augment our pointer */
421 struct UAVOData
*uavo
= (struct UAVOData
*)uavo_base
;
423 instance_size
= uavo
->instance_size
;
426 return instance_size
;
430 * Get the object this object is linked to. For regular objects, the linked object
431 * is the metaobject. For metaobjects the linked object is the parent object.
432 * This function is normally only needed by the telemetry module.
433 * \param[in] obj The object handle
434 * \return The object linked object handle
436 UAVObjHandle
UAVObjGetLinkedObj(UAVObjHandle obj_handle
)
438 PIOS_Assert(obj_handle
);
440 /* Recover the common object header */
441 struct UAVOBase
*uavo_base
= (struct UAVOBase
*)obj_handle
;
443 if (IsMetaobject(obj_handle
)) {
444 /* We have a meta object, find our containing UAVO. */
445 struct UAVOData
*uavo_data
= container_of((struct UAVOMeta
*)uavo_base
, struct UAVOData
, metaObj
);
447 return (UAVObjHandle
)uavo_data
;
449 /* We have a data object, augment our pointer */
450 struct UAVOData
*uavo_data
= (struct UAVOData
*)uavo_base
;
452 return (UAVObjHandle
) & (uavo_data
->metaObj
);
457 * Get the number of instances contained in the object.
458 * \param[in] obj The object handle
459 * \return The number of instances
461 uint16_t UAVObjGetNumInstances(UAVObjHandle obj_handle
)
463 PIOS_Assert(obj_handle
);
465 if (IsSingleInstance(obj_handle
)) {
466 /* Only one instance is allowed */
469 /* Multi-instance object. Inspect the object */
470 /* Augment our pointer to reflect the proper type */
471 struct UAVOMulti
*uavo_multi
= (struct UAVOMulti
*)obj_handle
;
472 return uavo_multi
->num_instances
;
477 * Create a new instance in the object.
478 * \param[in] obj The object handle
479 * \return The instance ID or 0 if an error
481 uint16_t UAVObjCreateInstance(UAVObjHandle obj_handle
,
482 UAVObjInitializeCallback initCb
)
484 PIOS_Assert(obj_handle
);
486 if (IsMetaobject(obj_handle
)) {
491 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
493 InstanceHandle instEntry
;
496 // Create new instance
497 instId
= UAVObjGetNumInstances(obj_handle
);
498 instEntry
= createInstance((struct UAVOData
*)obj_handle
, instId
);
499 if (instEntry
== NULL
) {
503 // Initialize instance data
505 initCb(obj_handle
, instId
);
509 xSemaphoreGiveRecursive(mutex
);
515 * Unpack an object from a byte array
516 * \param[in] obj The object handle
517 * \param[in] instId The instance ID
518 * \param[in] dataIn The byte array
519 * \return 0 if success or -1 if failure
521 int32_t UAVObjUnpack(UAVObjHandle obj_handle
, uint16_t instId
, const uint8_t *dataIn
)
523 PIOS_Assert(obj_handle
);
526 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
530 if (IsMetaobject(obj_handle
)) {
534 memcpy(MetaDataPtr((struct UAVOMeta
*)obj_handle
), dataIn
, MetaNumBytes
);
536 struct UAVOData
*obj
;
537 InstanceHandle instEntry
;
539 // Cast handle to object
540 obj
= (struct UAVOData
*)obj_handle
;
543 instEntry
= getInstance(obj
, instId
);
545 // If the instance does not exist create it and any other instances before it
546 if (instEntry
== NULL
) {
547 instEntry
= createInstance(obj
, instId
);
548 if (instEntry
== NULL
) {
553 memcpy(InstanceData(instEntry
), dataIn
, obj
->instance_size
);
557 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UNPACKED
);
561 xSemaphoreGiveRecursive(mutex
);
566 * Pack an object to a byte array
567 * \param[in] obj The object handle
568 * \param[in] instId The instance ID
569 * \param[out] dataOut The byte array
570 * \return 0 if success or -1 if failure
572 int32_t UAVObjPack(UAVObjHandle obj_handle
, uint16_t instId
, uint8_t *dataOut
)
574 PIOS_Assert(obj_handle
);
577 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
581 if (IsMetaobject(obj_handle
)) {
585 memcpy(dataOut
, MetaDataPtr((struct UAVOMeta
*)obj_handle
), MetaNumBytes
);
587 struct UAVOData
*obj
;
588 InstanceHandle instEntry
;
590 // Cast handle to object
591 obj
= (struct UAVOData
*)obj_handle
;
594 instEntry
= getInstance(obj
, instId
);
595 if (instEntry
== NULL
) {
599 memcpy(dataOut
, InstanceData(instEntry
), obj
->instance_size
);
605 xSemaphoreGiveRecursive(mutex
);
610 * Update a CRC with an object data
611 * \param[in] obj The object handle
612 * \param[in] instId The instance ID
613 * \param[in] crc The crc to update
614 * \return the updated crc
616 uint8_t UAVObjUpdateCRC(UAVObjHandle obj_handle
, uint16_t instId
, uint8_t crc
)
618 PIOS_Assert(obj_handle
);
621 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
623 if (IsMetaobject(obj_handle
)) {
629 struct UAVOData
*obj
;
630 InstanceHandle instEntry
;
632 // Cast handle to object
633 obj
= (struct UAVOData
*)obj_handle
;
636 instEntry
= getInstance(obj
, instId
);
637 if (instEntry
== NULL
) {
641 crc
= PIOS_CRC_updateCRC(crc
, (uint8_t *)InstanceData(instEntry
), (int32_t)obj
->instance_size
);
645 xSemaphoreGiveRecursive(mutex
);
650 * Actually write the object's data to the logfile
651 * \param[in] obj The object handle
652 * \param[in] instId The object instance ID
654 #ifdef PIOS_INCLUDE_DEBUGLOG
655 void UAVObjInstanceWriteToLog(UAVObjHandle obj_handle
, uint16_t instId
)
657 PIOS_Assert(obj_handle
);
660 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
662 if (IsMetaobject(obj_handle
)) {
666 PIOS_DEBUGLOG_UAVObject(UAVObjGetID(obj_handle
), instId
, MetaNumBytes
, (uint8_t *)MetaDataPtr((struct UAVOMeta
*)obj_handle
));
668 struct UAVOData
*obj
;
669 InstanceHandle instEntry
;
671 // Cast handle to object
672 obj
= (struct UAVOData
*)obj_handle
;
675 instEntry
= getInstance(obj
, instId
);
676 if (instEntry
== NULL
) {
680 PIOS_DEBUGLOG_UAVObject(UAVObjGetID(obj_handle
), instId
, obj
->instance_size
, (uint8_t *)InstanceData(instEntry
));
684 xSemaphoreGiveRecursive(mutex
);
686 #else /* ifdef PIOS_INCLUDE_DEBUGLOG */
687 void UAVObjInstanceWriteToLog(__attribute__((unused
)) UAVObjHandle obj_handle
, __attribute__((unused
)) uint16_t instId
) {}
688 #endif /* ifdef PIOS_INCLUDE_DEBUGLOG */
690 * Save all settings objects to the SD card.
691 * @return 0 if success or -1 if failure
693 int32_t UAVObjSaveSettings()
696 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
700 // Save all settings objects
701 UAVO_LIST_ITERATE(obj
)
702 // Check if this is a settings object
703 if (IsSettings(obj
)) {
705 if (UAVObjSave((UAVObjHandle
)obj
, 0) ==
715 xSemaphoreGiveRecursive(mutex
);
720 * Load all settings objects from the SD card.
721 * @return 0 if success or -1 if failure
723 int32_t UAVObjLoadSettings()
726 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
730 // Load all settings objects
731 UAVO_LIST_ITERATE(obj
)
732 // Check if this is a settings object
733 if (IsSettings(obj
)) {
735 if (UAVObjLoad((UAVObjHandle
)obj
, 0) ==
745 xSemaphoreGiveRecursive(mutex
);
750 * Delete all settings objects from the SD card.
751 * @return 0 if success or -1 if failure
753 int32_t UAVObjDeleteSettings()
756 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
760 // Save all settings objects
761 UAVO_LIST_ITERATE(obj
)
762 // Check if this is a settings object
763 if (IsSettings(obj
)) {
765 if (UAVObjDelete((UAVObjHandle
)obj
, 0)
775 xSemaphoreGiveRecursive(mutex
);
780 * Save all metaobjects to the SD card.
781 * @return 0 if success or -1 if failure
783 int32_t UAVObjSaveMetaobjects()
786 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
790 // Save all settings objects
791 UAVO_LIST_ITERATE(obj
)
793 if (UAVObjSave((UAVObjHandle
)MetaObjectPtr(obj
), 0) ==
802 xSemaphoreGiveRecursive(mutex
);
807 * Load all metaobjects from the SD card.
808 * @return 0 if success or -1 if failure
810 int32_t UAVObjLoadMetaobjects()
813 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
817 // Load all settings objects
818 UAVO_LIST_ITERATE(obj
)
820 if (UAVObjLoad((UAVObjHandle
)MetaObjectPtr(obj
), 0) ==
829 xSemaphoreGiveRecursive(mutex
);
834 * Delete all metaobjects from the SD card.
835 * @return 0 if success or -1 if failure
837 int32_t UAVObjDeleteMetaobjects()
840 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
844 // Load all settings objects
845 UAVO_LIST_ITERATE(obj
)
847 if (UAVObjDelete((UAVObjHandle
)MetaObjectPtr(obj
), 0)
856 xSemaphoreGiveRecursive(mutex
);
861 * Set the object data
862 * \param[in] obj The object handle
863 * \param[in] dataIn The object's data structure
864 * \return 0 if success or -1 if failure
866 int32_t UAVObjSetData(UAVObjHandle obj_handle
, const void *dataIn
)
868 return UAVObjSetInstanceData(obj_handle
, 0, dataIn
);
872 * Set the object data
873 * \param[in] obj The object handle
874 * \param[in] dataIn The object's data structure
875 * \return 0 if success or -1 if failure
877 int32_t UAVObjSetDataField(UAVObjHandle obj_handle
, const void *dataIn
, uint32_t offset
, uint32_t size
)
879 return UAVObjSetInstanceDataField(obj_handle
, 0, dataIn
, offset
, size
);
883 * Get the object data
884 * \param[in] obj The object handle
885 * \param[out] dataOut The object's data structure
886 * \return 0 if success or -1 if failure
888 int32_t UAVObjGetData(UAVObjHandle obj_handle
, void *dataOut
)
890 return UAVObjGetInstanceData(obj_handle
, 0, dataOut
);
894 * Get the object data
895 * \param[in] obj The object handle
896 * \param[out] dataOut The object's data structure
897 * \return 0 if success or -1 if failure
899 int32_t UAVObjGetDataField(UAVObjHandle obj_handle
, void *dataOut
, uint32_t offset
, uint32_t size
)
901 return UAVObjGetInstanceDataField(obj_handle
, 0, dataOut
, offset
, size
);
905 * Set the data of a specific object instance
906 * \param[in] obj The object handle
907 * \param[in] instId The object instance ID
908 * \param[in] dataIn The object's data structure
909 * \return 0 if success or -1 if failure
911 int32_t UAVObjSetInstanceData(UAVObjHandle obj_handle
, uint16_t instId
,
914 PIOS_Assert(obj_handle
);
917 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
921 if (IsMetaobject(obj_handle
)) {
925 memcpy(MetaDataPtr((struct UAVOMeta
*)obj_handle
), dataIn
, MetaNumBytes
);
927 struct UAVOData
*obj
;
928 InstanceHandle instEntry
;
930 // Cast to object info
931 obj
= (struct UAVOData
*)obj_handle
;
933 // Check access level
934 if (UAVObjReadOnly(obj_handle
)) {
937 // Get instance information
938 instEntry
= getInstance(obj
, instId
);
939 if (instEntry
== NULL
) {
943 memcpy(InstanceData(instEntry
), dataIn
, obj
->instance_size
);
947 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED
);
951 xSemaphoreGiveRecursive(mutex
);
956 * Set the data of a specific object instance
957 * \param[in] obj The object handle
958 * \param[in] instId The object instance ID
959 * \param[in] dataIn The object's data structure
960 * \return 0 if success or -1 if failure
962 int32_t UAVObjSetInstanceDataField(UAVObjHandle obj_handle
, uint16_t instId
, const void *dataIn
, uint32_t offset
, uint32_t size
)
964 PIOS_Assert(obj_handle
);
967 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
971 if (IsMetaobject(obj_handle
)) {
972 // Get instance information
978 if ((size
+ offset
) > MetaNumBytes
) {
983 memcpy(MetaDataPtr((struct UAVOMeta
*)obj_handle
) + offset
, dataIn
, size
);
985 struct UAVOData
*obj
;
986 InstanceHandle instEntry
;
988 // Cast to object info
989 obj
= (struct UAVOData
*)obj_handle
;
991 // Check access level
992 if (UAVObjReadOnly(obj_handle
)) {
996 // Get instance information
997 instEntry
= getInstance(obj
, instId
);
998 if (instEntry
== NULL
) {
1002 // Check for overrun
1003 if ((size
+ offset
) > obj
->instance_size
) {
1008 memcpy(InstanceData(instEntry
) + offset
, dataIn
, size
);
1013 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED
);
1017 xSemaphoreGiveRecursive(mutex
);
1022 * Get the data of a specific object instance
1023 * \param[in] obj The object handle
1024 * \param[in] instId The object instance ID
1025 * \param[out] dataOut The object's data structure
1026 * \return 0 if success or -1 if failure
1028 int32_t UAVObjGetInstanceData(UAVObjHandle obj_handle
, uint16_t instId
,
1031 PIOS_Assert(obj_handle
);
1034 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1038 if (IsMetaobject(obj_handle
)) {
1039 // Get instance information
1044 memcpy(dataOut
, MetaDataPtr((struct UAVOMeta
*)obj_handle
), MetaNumBytes
);
1046 struct UAVOData
*obj
;
1047 InstanceHandle instEntry
;
1049 // Cast to object info
1050 obj
= (struct UAVOData
*)obj_handle
;
1052 // Get instance information
1053 instEntry
= getInstance(obj
, instId
);
1054 if (instEntry
== NULL
) {
1058 memcpy(dataOut
, InstanceData(instEntry
), obj
->instance_size
);
1064 xSemaphoreGiveRecursive(mutex
);
1069 * Get the data of a specific object instance
1070 * \param[in] obj The object handle
1071 * \param[in] instId The object instance ID
1072 * \param[out] dataOut The object's data structure
1073 * \return 0 if success or -1 if failure
1075 int32_t UAVObjGetInstanceDataField(UAVObjHandle obj_handle
, uint16_t instId
, void *dataOut
, uint32_t offset
, uint32_t size
)
1077 PIOS_Assert(obj_handle
);
1080 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1084 if (IsMetaobject(obj_handle
)) {
1085 // Get instance information
1090 // Check for overrun
1091 if ((size
+ offset
) > MetaNumBytes
) {
1096 memcpy(dataOut
, MetaDataPtr((struct UAVOMeta
*)obj_handle
) + offset
, size
);
1098 struct UAVOData
*obj
;
1099 InstanceHandle instEntry
;
1101 // Cast to object info
1102 obj
= (struct UAVOData
*)obj_handle
;
1104 // Get instance information
1105 instEntry
= getInstance(obj
, instId
);
1106 if (instEntry
== NULL
) {
1110 // Check for overrun
1111 if ((size
+ offset
) > obj
->instance_size
) {
1116 memcpy(dataOut
, InstanceData(instEntry
) + offset
, size
);
1122 xSemaphoreGiveRecursive(mutex
);
1127 * Set the object metadata
1128 * \param[in] obj The object handle
1129 * \param[in] dataIn The object's metadata structure
1130 * \return 0 if success or -1 if failure
1132 int32_t UAVObjSetMetadata(UAVObjHandle obj_handle
, const UAVObjMetadata
*dataIn
)
1134 PIOS_Assert(obj_handle
);
1136 // Set metadata (metadata of metaobjects can not be modified)
1137 if (IsMetaobject(obj_handle
)) {
1141 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1143 UAVObjSetData((UAVObjHandle
)MetaObjectPtr((struct UAVOData
*)obj_handle
), dataIn
);
1145 xSemaphoreGiveRecursive(mutex
);
1150 * Get the object metadata
1151 * \param[in] obj The object handle
1152 * \param[out] dataOut The object's metadata structure
1153 * \return 0 if success or -1 if failure
1155 int32_t UAVObjGetMetadata(UAVObjHandle obj_handle
, UAVObjMetadata
*dataOut
)
1157 PIOS_Assert(obj_handle
);
1160 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1163 if (IsMetaobject(obj_handle
)) {
1164 memcpy(dataOut
, &defMetadata
, sizeof(UAVObjMetadata
));
1166 UAVObjGetData((UAVObjHandle
)MetaObjectPtr((struct UAVOData
*)obj_handle
),
1171 xSemaphoreGiveRecursive(mutex
);
1175 /*******************************
1176 * Object Metadata Manipulation
1177 ******************************/
1180 * Get the UAVObject metadata access member
1181 * \param[in] metadata The metadata object
1182 * \return the access type
1184 UAVObjAccessType
UAVObjGetAccess(const UAVObjMetadata
*metadata
)
1186 PIOS_Assert(metadata
);
1187 return (metadata
->flags
>> UAVOBJ_ACCESS_SHIFT
) & 1;
1191 * Set the UAVObject metadata access member
1192 * \param[in] metadata The metadata object
1193 * \param[in] mode The access mode
1195 void UAVObjSetAccess(UAVObjMetadata
*metadata
, UAVObjAccessType mode
)
1197 PIOS_Assert(metadata
);
1198 SET_BITS(metadata
->flags
, UAVOBJ_ACCESS_SHIFT
, mode
, 1);
1202 * Get the UAVObject metadata GCS access member
1203 * \param[in] metadata The metadata object
1204 * \return the GCS access type
1206 UAVObjAccessType
UAVObjGetGcsAccess(const UAVObjMetadata
*metadata
)
1208 PIOS_Assert(metadata
);
1209 return (metadata
->flags
>> UAVOBJ_GCS_ACCESS_SHIFT
) & 1;
1213 * Set the UAVObject metadata GCS access member
1214 * \param[in] metadata The metadata object
1215 * \param[in] mode The access mode
1217 void UAVObjSetGcsAccess(UAVObjMetadata
*metadata
, UAVObjAccessType mode
)
1219 PIOS_Assert(metadata
);
1220 SET_BITS(metadata
->flags
, UAVOBJ_GCS_ACCESS_SHIFT
, mode
, 1);
1224 * Get the UAVObject metadata telemetry acked member
1225 * \param[in] metadata The metadata object
1226 * \return the telemetry acked boolean
1228 uint8_t UAVObjGetTelemetryAcked(const UAVObjMetadata
*metadata
)
1230 PIOS_Assert(metadata
);
1231 return (metadata
->flags
>> UAVOBJ_TELEMETRY_ACKED_SHIFT
) & 1;
1235 * Set the UAVObject metadata telemetry acked member
1236 * \param[in] metadata The metadata object
1237 * \param[in] val The telemetry acked boolean
1239 void UAVObjSetTelemetryAcked(UAVObjMetadata
*metadata
, uint8_t val
)
1241 PIOS_Assert(metadata
);
1242 SET_BITS(metadata
->flags
, UAVOBJ_TELEMETRY_ACKED_SHIFT
, val
, 1);
1246 * Get the UAVObject metadata GCS telemetry acked member
1247 * \param[in] metadata The metadata object
1248 * \return the telemetry acked boolean
1250 uint8_t UAVObjGetGcsTelemetryAcked(const UAVObjMetadata
*metadata
)
1252 PIOS_Assert(metadata
);
1253 return (metadata
->flags
>> UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
) & 1;
1257 * Set the UAVObject metadata GCS telemetry acked member
1258 * \param[in] metadata The metadata object
1259 * \param[in] val The GCS telemetry acked boolean
1261 void UAVObjSetGcsTelemetryAcked(UAVObjMetadata
*metadata
, uint8_t val
)
1263 PIOS_Assert(metadata
);
1264 SET_BITS(metadata
->flags
, UAVOBJ_GCS_TELEMETRY_ACKED_SHIFT
, val
, 1);
1268 * Get the UAVObject metadata telemetry update mode
1269 * \param[in] metadata The metadata object
1270 * \return the telemetry update mode
1272 UAVObjUpdateMode
UAVObjGetTelemetryUpdateMode(const UAVObjMetadata
*metadata
)
1274 PIOS_Assert(metadata
);
1275 return (metadata
->flags
>> UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
) & UAVOBJ_UPDATE_MODE_MASK
;
1279 * Set the UAVObject metadata telemetry update mode member
1280 * \param[in] metadata The metadata object
1281 * \param[in] val The telemetry update mode
1283 void UAVObjSetTelemetryUpdateMode(UAVObjMetadata
*metadata
, UAVObjUpdateMode val
)
1285 PIOS_Assert(metadata
);
1286 SET_BITS(metadata
->flags
, UAVOBJ_TELEMETRY_UPDATE_MODE_SHIFT
, val
, UAVOBJ_UPDATE_MODE_MASK
);
1290 * Get the UAVObject metadata GCS telemetry update mode
1291 * \param[in] metadata The metadata object
1292 * \return the GCS telemetry update mode
1294 UAVObjUpdateMode
UAVObjGetGcsTelemetryUpdateMode(const UAVObjMetadata
*metadata
)
1296 PIOS_Assert(metadata
);
1297 return (metadata
->flags
>> UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
) & UAVOBJ_UPDATE_MODE_MASK
;
1301 * Set the UAVObject metadata GCS telemetry update mode member
1302 * \param[in] metadata The metadata object
1303 * \param[in] val The GCS telemetry update mode
1305 void UAVObjSetGcsTelemetryUpdateMode(UAVObjMetadata
*metadata
, UAVObjUpdateMode val
)
1307 PIOS_Assert(metadata
);
1308 SET_BITS(metadata
->flags
, UAVOBJ_GCS_TELEMETRY_UPDATE_MODE_SHIFT
, val
, UAVOBJ_UPDATE_MODE_MASK
);
1312 * Get the UAVObject metadata logging update mode
1313 * \param[in] metadata The metadata object
1314 * \return the GCS telemetry update mode
1316 UAVObjUpdateMode
UAVObjGetLoggingUpdateMode(const UAVObjMetadata
*metadata
)
1318 PIOS_Assert(metadata
);
1319 return (metadata
->flags
>> UAVOBJ_LOGGING_UPDATE_MODE_SHIFT
) & UAVOBJ_UPDATE_MODE_MASK
;
1323 * Set the UAVObject metadata logging update mode member
1324 * \param[in] metadata The metadata object
1325 * \param[in] val The GCS telemetry update mode
1327 void UAVObjSetLoggingUpdateMode(UAVObjMetadata
*metadata
, UAVObjUpdateMode val
)
1329 PIOS_Assert(metadata
);
1330 SET_BITS(metadata
->flags
, UAVOBJ_LOGGING_UPDATE_MODE_SHIFT
, val
, UAVOBJ_UPDATE_MODE_MASK
);
1335 * Check if an object is read only
1336 * \param[in] obj The object handle
1338 * \arg 0 if not read only
1339 * \arg 1 if read only
1340 * \arg -1 if unable to get meta data
1342 int8_t UAVObjReadOnly(UAVObjHandle obj_handle
)
1344 PIOS_Assert(obj_handle
);
1345 if (!IsMetaobject(obj_handle
)) {
1346 return UAVObjGetAccess(LinkedMetaDataPtr((struct UAVOData
*)obj_handle
)) == ACCESS_READONLY
;
1352 * Connect an event queue to the object, if the queue is already connected then the event mask is only updated.
1353 * All events matching the event mask will be pushed to the event queue.
1354 * \param[in] obj The object handle
1355 * \param[in] queue The event queue
1356 * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
1357 * \return 0 if success or -1 if failure
1359 int32_t UAVObjConnectQueue(UAVObjHandle obj_handle
, xQueueHandle queue
,
1362 PIOS_Assert(obj_handle
);
1365 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1366 res
= connectObj(obj_handle
, queue
, 0, eventMask
, false);
1367 xSemaphoreGiveRecursive(mutex
);
1372 * Disconnect an event queue from the object.
1373 * \param[in] obj The object handle
1374 * \param[in] queue The event queue
1375 * \return 0 if success or -1 if failure
1377 int32_t UAVObjDisconnectQueue(UAVObjHandle obj_handle
, xQueueHandle queue
)
1379 PIOS_Assert(obj_handle
);
1382 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1383 res
= disconnectObj(obj_handle
, queue
, 0);
1384 xSemaphoreGiveRecursive(mutex
);
1389 * Connect an event callback to the object, if the callback is already connected then the event mask is only updated.
1390 * The supplied callback will be invoked on all events matching the event mask.
1391 * \param[in] obj The object handle
1392 * \param[in] cb The event callback
1393 * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
1394 * \return 0 if success or -1 if failure
1396 int32_t UAVObjConnectCallback(UAVObjHandle obj_handle
, UAVObjEventCallback cb
,
1397 uint8_t eventMask
, bool fast
)
1399 PIOS_Assert(obj_handle
);
1401 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1402 res
= connectObj(obj_handle
, 0, cb
, eventMask
, fast
);
1403 xSemaphoreGiveRecursive(mutex
);
1408 * Disconnect an event callback from the object.
1409 * \param[in] obj The object handle
1410 * \param[in] cb The event callback
1411 * \return 0 if success or -1 if failure
1413 int32_t UAVObjDisconnectCallback(UAVObjHandle obj_handle
, UAVObjEventCallback cb
)
1415 PIOS_Assert(obj_handle
);
1417 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1418 res
= disconnectObj(obj_handle
, 0, cb
);
1419 xSemaphoreGiveRecursive(mutex
);
1424 * Request an update of the object's data from the GCS. The call will not wait for the response, a EV_UPDATED event
1425 * will be generated as soon as the object is updated.
1426 * \param[in] obj The object handle
1428 void UAVObjRequestUpdate(UAVObjHandle obj_handle
)
1430 UAVObjRequestInstanceUpdate(obj_handle
, UAVOBJ_ALL_INSTANCES
);
1434 * Request an update of the object's data from the GCS.
1435 * The call will not wait for the response, a EV_UPDATED event will be generated as soon as the object is updated.
1436 * \param[in] obj The object handle
1437 * \param[in] instId Object instance ID to update
1439 void UAVObjRequestInstanceUpdate(UAVObjHandle obj_handle
, uint16_t instId
)
1441 PIOS_Assert(obj_handle
);
1442 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1443 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATE_REQ
);
1444 xSemaphoreGiveRecursive(mutex
);
1448 * Trigger a EV_UPDATED_MANUAL event for an object.
1449 * \param[in] obj The object handle
1451 void UAVObjUpdated(UAVObjHandle obj_handle
)
1453 UAVObjInstanceUpdated(obj_handle
, UAVOBJ_ALL_INSTANCES
);
1457 * Trigger a EV_UPDATED_MANUAL event for an object instance.
1458 * \param[in] obj The object handle
1459 * \param[in] instId The object instance ID
1461 void UAVObjInstanceUpdated(UAVObjHandle obj_handle
, uint16_t instId
)
1463 PIOS_Assert(obj_handle
);
1464 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1465 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED_MANUAL
);
1466 xSemaphoreGiveRecursive(mutex
);
1470 * Trigger a EV_UPDATED event for an object instance.
1471 * \param[in] obj The object handle
1472 * \param[in] instId The object instance ID
1474 static void instanceAutoUpdated(UAVObjHandle obj_handle
, uint16_t instId
)
1476 PIOS_Assert(obj_handle
);
1477 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1478 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_UPDATED
);
1479 xSemaphoreGiveRecursive(mutex
);
1483 * Log the object's data (triggers a EV_LOGGING_MANUAL event on this object).
1484 * \param[in] obj The object handle
1486 void UAVObjLogging(UAVObjHandle obj_handle
)
1488 UAVObjInstanceLogging(obj_handle
, UAVOBJ_ALL_INSTANCES
);
1492 * Log the object's data (triggers a EV_LOGGING_MANUAL event on this object).
1493 * \param[in] obj The object handle
1494 * \param[in] instId The object instance ID
1496 void UAVObjInstanceLogging(UAVObjHandle obj_handle
, uint16_t instId
)
1498 PIOS_Assert(obj_handle
);
1499 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1500 sendEvent((struct UAVOBase
*)obj_handle
, instId
, EV_LOGGING_MANUAL
);
1501 xSemaphoreGiveRecursive(mutex
);
1505 * Iterate through all objects in the list.
1506 * \param iterator This function will be called once for each object,
1507 * the object will be passed as a parameter
1509 void UAVObjIterate(void (*iterator
)(UAVObjHandle obj
))
1511 PIOS_Assert(iterator
);
1514 xSemaphoreTakeRecursive(mutex
, portMAX_DELAY
);
1516 // Iterate through the list and invoke iterator for each object
1517 UAVO_LIST_ITERATE (obj
)
1518 (*iterator
)((UAVObjHandle
)obj
);
1519 (*iterator
)((UAVObjHandle
) &obj
->metaObj
);
1523 xSemaphoreGiveRecursive(mutex
);
1527 * Send a triggered event to all event queues registered on the object.
1529 int32_t sendEvent(struct UAVOBase
*obj
, uint16_t instId
, UAVObjEventType triggered_event
)
1531 /* Set up the message that will be sent to all registered listeners */
1533 .obj
= (UAVObjHandle
)obj
,
1534 .event
= triggered_event
,
1536 .lowPriority
= false,
1539 // Go through each object and push the event message in the queue (if event is activated for the queue)
1540 struct ObjectEventEntry
*event
;
1542 LL_FOREACH(obj
->next_event
, event
) {
1543 if (event
->eventMask
== 0 || (event
->eventMask
& triggered_event
) != 0) {
1544 // Send to queue if a valid queue is registered
1547 if (xQueueSend(event
->queue
, &msg
, 0) != pdTRUE
) {
1548 ++stats
.eventQueueErrors
;
1549 stats
.lastQueueErrorID
= UAVObjGetID(obj
);
1553 // Invoke callback (from event task) if a valid one is registered
1557 } else if (EventCallbackDispatch(&msg
, event
->cb
) != pdTRUE
) {
1558 // invoke callback from the event task, will not block
1559 ++stats
.eventCallbackErrors
;
1560 stats
.lastCallbackErrorID
= UAVObjGetID(obj
);
1570 * Create a new object instance, return the instance info or NULL if failure.
1572 static InstanceHandle
createInstance(struct UAVOData
*obj
, uint16_t instId
)
1574 struct UAVOMultiInst
*instEntry
;
1576 /* Don't allow more than one instance for single instance objects */
1577 if (IsSingleInstance(&(obj
->base
))) {
1582 /* Don't create more than the allowed number of instances */
1583 if (instId
>= UAVOBJ_MAX_INSTANCES
) {
1587 /* Don't allow duplicate instances */
1588 if (instId
< UAVObjGetNumInstances(&(obj
->base
))) {
1592 // Create any missing instances (all instance IDs must be sequential)
1593 for (uint16_t n
= UAVObjGetNumInstances(&(obj
->base
)); n
< instId
; ++n
) {
1594 if (createInstance(obj
, n
) == NULL
) {
1599 /* Create the actual instance */
1600 uint32_t size
= sizeof(struct UAVOMultiInst
) + obj
->instance_size
;
1601 instEntry
= (struct UAVOMultiInst
*)pios_malloc(size
);
1605 memset(instEntry
, 0, size
);
1606 LL_APPEND(((struct UAVOMulti
*)obj
)->instance0
.next
, instEntry
);
1608 ((struct UAVOMulti
*)obj
)->num_instances
++;
1611 instanceAutoUpdated((UAVObjHandle
)obj
, instId
);
1614 return InstanceDataOffset(instEntry
);
1618 * Get the instance information or NULL if the instance does not exist
1620 InstanceHandle
getInstance(struct UAVOData
*obj
, uint16_t instId
)
1622 if (IsMetaobject(&obj
->base
)) {
1623 /* Metadata Instance */
1629 /* Augment our pointer to reflect the proper type */
1630 struct UAVOMeta
*uavo_meta
= (struct UAVOMeta
*)obj
;
1631 return &(uavo_meta
->instance0
);
1632 } else if (IsSingleInstance(&(obj
->base
))) {
1633 /* Single Instance */
1639 /* Augment our pointer to reflect the proper type */
1640 struct UAVOSingle
*uavo_single
= (struct UAVOSingle
*)obj
;
1641 return &(uavo_single
->instance0
);
1643 /* Multi Instance */
1644 /* Augment our pointer to reflect the proper type */
1645 struct UAVOMulti
*uavo_multi
= (struct UAVOMulti
*)obj
;
1646 if (instId
>= uavo_multi
->num_instances
) {
1650 // Look for specified instance ID
1651 uint16_t instance
= 0;
1652 struct UAVOMultiInst
*instEntry
;
1653 LL_FOREACH(&(uavo_multi
->instance0
), instEntry
) {
1654 if (instance
++ == instId
) {
1656 return &(instEntry
->instance
);
1659 /* Instance was not found */
1665 * Connect an event queue to the object, if the queue is already connected then the event mask is only updated.
1666 * \param[in] obj The object handle
1667 * \param[in] queue The event queue
1668 * \param[in] cb The event callback
1669 * \param[in] eventMask The event mask, if EV_MASK_ALL then all events are enabled (e.g. EV_UPDATED | EV_UPDATED_MANUAL)
1670 * \return 0 if success or -1 if failure
1672 static int32_t connectObj(UAVObjHandle obj_handle
, xQueueHandle queue
,
1673 UAVObjEventCallback cb
, uint8_t eventMask
, bool fast
)
1675 struct ObjectEventEntry
*event
;
1676 struct UAVOBase
*obj
;
1678 // Check that the queue is not already connected, if it is simply update event mask
1679 obj
= (struct UAVOBase
*)obj_handle
;
1680 LL_FOREACH(obj
->next_event
, event
) {
1681 if (event
->queue
== queue
&& event
->cb
== cb
) {
1682 // Already connected, update event mask and return
1683 event
->eventMask
= eventMask
;
1689 // Add queue to list
1690 event
= (struct ObjectEventEntry
*)pios_malloc(sizeof(struct ObjectEventEntry
));
1691 if (event
== NULL
) {
1694 event
->queue
= queue
;
1696 event
->eventMask
= eventMask
;
1698 LL_APPEND(obj
->next_event
, event
);
1705 * Disconnect an event queue from the object
1706 * \param[in] obj The object handle
1707 * \param[in] queue The event queue
1708 * \param[in] cb The event callback
1709 * \return 0 if success or -1 if failure
1711 static int32_t disconnectObj(UAVObjHandle obj_handle
, xQueueHandle queue
,
1712 UAVObjEventCallback cb
)
1714 struct ObjectEventEntry
*event
;
1715 struct UAVOBase
*obj
;
1717 // Find queue and remove it
1718 obj
= (struct UAVOBase
*)obj_handle
;
1719 LL_FOREACH(obj
->next_event
, event
) {
1720 if ((event
->queue
== queue
1721 && event
->cb
== cb
)) {
1722 LL_DELETE(obj
->next_event
, event
);
1728 // If this point is reached the queue was not found