You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ac...@apache.org on 2022/07/23 19:58:04 UTC
[incubator-nuttx-apps] 01/20: apps/system/uorb: c interfaces.
This is an automated email from the ASF dual-hosted git repository.
acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git
commit 3528b5515f2ad8bae0c640e81c47098fb422b201
Author: jihandong <ji...@xiaomi.com>
AuthorDate: Thu Mar 3 20:24:54 2022 +0800
apps/system/uorb: c interfaces.
refer to: https://docs.px4.io/v1.12/en/middleware/uorb.html
- orb_open: do real work for advertise() and subscribe(), if thre is
no user, register topic first, then save meta in driver;
only first user can successfully set buffer number.
- orb_exists: check topic state, if topic only has subscribers,
return "not exists".
Signed-off-by: jihandong <ji...@xiaomi.com>
---
system/uorb/Kconfig | 41 +++
system/uorb/Make.defs | 25 ++
system/uorb/Makefile | 25 ++
system/uorb/uORB/uORB.c | 314 +++++++++++++++++++++++
system/uorb/uORB/uORB.h | 645 ++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 1050 insertions(+)
diff --git a/system/uorb/Kconfig b/system/uorb/Kconfig
new file mode 100644
index 000000000..33b15ed35
--- /dev/null
+++ b/system/uorb/Kconfig
@@ -0,0 +1,41 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+menuconfig UORB
+ tristate "uorb(micro object request broker)"
+ depends on SENSORS && USENSOR
+ default n
+
+if UORB
+
+config DEBUG_UORB
+ bool "uorb debug output"
+ default n
+
+if DEBUG_UORB
+
+config UORB_ALERT
+ bool "uorb panic output"
+ default n
+ depends on DEBUG_ALERT
+
+config UORB_ERROR
+ bool "uorb error output"
+ default n
+ depends on DEBUG_ERROR
+
+config UORB_WARN
+ bool "uorb warn output"
+ default n
+ depends on DEBUG_WARN
+
+config UORB_INFO
+ bool "uorb info output"
+ default n
+ depends on DEBUG_INFO
+
+endif # DEBUG_UORB
+
+endif # UORB
diff --git a/system/uorb/Make.defs b/system/uorb/Make.defs
new file mode 100644
index 000000000..6c7bf0d73
--- /dev/null
+++ b/system/uorb/Make.defs
@@ -0,0 +1,25 @@
+############################################################################
+# apps/system/uorb/Make.defs
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+ifneq ($(CONFIG_UORB),)
+CONFIGURED_APPS += $(APPDIR)/system/uorb
+CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \
+ $(APPDIR)/system/uorb/}
+endif
diff --git a/system/uorb/Makefile b/system/uorb/Makefile
new file mode 100644
index 000000000..93d9f4d17
--- /dev/null
+++ b/system/uorb/Makefile
@@ -0,0 +1,25 @@
+############################################################################
+# apps/system/uorb/uORB/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+CSRCS += uORB/uORB.c
+
+include $(APPDIR)/Application.mk
diff --git a/system/uorb/uORB/uORB.c b/system/uorb/uORB/uORB.c
new file mode 100644
index 000000000..7c58806d2
--- /dev/null
+++ b/system/uorb/uORB/uORB.c
@@ -0,0 +1,314 @@
+/****************************************************************************
+ * apps/system/uorb/uORB/uORB.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <uORB/uORB.h>
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: orb_open
+ *
+ * Description:
+ * Open device node as advertiser / subscriber, regist node and save meta
+ * in driver for first user, set buffer number for advertisers.
+ *
+ * Input Parameters:
+ * meta The uORB metadata (usually from the ORB_ID() macro)
+ * advertiser Whether advertiser or subscriber.
+ * instance Instance number to open.
+ * queue_size Maximum number of buffered elements.
+ *
+ * Returned Value:
+ * fd on success, otherwise returns negative value and set errno.
+ ****************************************************************************/
+
+static int orb_open(FAR const struct orb_metadata *meta, bool advertiser,
+ int instance, unsigned int queue_size)
+{
+ char path[PATH_MAX];
+ bool first_open = false;
+ int fd;
+ int ret;
+
+ snprintf(path, PATH_MAX, ORB_SENSOR_PATH"%s%d", meta->o_name, instance);
+
+ /* Check existance before open */
+
+ ret = access(path, F_OK);
+ if (ret < 0)
+ {
+ struct sensor_reginfo_s reginfo;
+
+ reginfo.path = path;
+ reginfo.esize = meta->o_size;
+ reginfo.nbuffer = queue_size;
+
+ fd = open(ORB_USENSOR_PATH, O_WRONLY);
+ if (fd < 0)
+ {
+ return fd;
+ }
+
+ /* Register new device node */
+
+ ret = ioctl(fd, SNIOC_REGISTER, (unsigned long)(uintptr_t)®info);
+ close(fd);
+ if (ret < 0 && ret != -EEXIST)
+ {
+ return ret;
+ }
+
+ first_open = true;
+ }
+
+ fd = open(path, O_CLOEXEC | (advertiser ? O_WRONLY : O_RDONLY));
+ if (fd < 0)
+ {
+ return fd;
+ }
+
+ if (first_open)
+ {
+ ioctl(fd, SNIOC_SET_USERPRIV, (unsigned long)(uintptr_t)meta);
+ }
+
+ /* Only first advertiser can successfully set buffer number */
+
+ if (queue_size)
+ {
+ ioctl(fd, SNIOC_SET_BUFFER_NUMBER, (unsigned long)queue_size);
+ }
+
+ return fd;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int orb_advertise_multi_queue(FAR const struct orb_metadata *meta,
+ FAR const void *data, FAR int *instance,
+ unsigned int queue_size)
+{
+ int inst;
+ int fd;
+
+ /* Open the node as an advertiser */
+
+ inst = instance ? *instance : orb_group_count(meta);
+
+ fd = orb_open(meta, true, inst, queue_size);
+ if (fd < 0)
+ {
+ uorberr("%s advertise failed (%i)", meta->o_name, fd);
+ return -1;
+ }
+
+ /* The advertiser may perform an initial publish to initialise the object */
+
+ if (data != NULL)
+ {
+ int ret;
+
+ ret = orb_publish_multi(fd, data, meta->o_size);
+ if (ret != meta->o_size)
+ {
+ uorberr("%s publish %d, expect %d",
+ meta->o_name, ret, meta->o_size);
+ close(fd);
+ return -1;
+ }
+ }
+
+ return fd;
+}
+
+int orb_unadvertise(int fd)
+{
+ return close(fd);
+}
+
+ssize_t orb_publish_multi(int fd, const void *data, size_t len)
+{
+ return write(fd, data, len);
+}
+
+int orb_subscribe_multi(FAR const struct orb_metadata *meta,
+ unsigned instance)
+{
+ return orb_open(meta, false, instance, 0);
+}
+
+int orb_unsubscribe(int fd)
+{
+ return close(fd);
+}
+
+ssize_t orb_copy_multi(int fd, FAR void *buffer, size_t len)
+{
+ return read(fd, buffer, len);
+}
+
+int orb_get_state(int fd, FAR struct orb_state *state)
+{
+ struct sensor_state_s tmp;
+ int ret;
+
+ if (!state)
+ {
+ return -EINVAL;
+ }
+
+ ret = ioctl(fd, SNIOC_GET_STATE, (unsigned long)(uintptr_t)&tmp);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ state->max_frequency = tmp.min_interval ?
+ 1000000 / tmp.min_interval : 0;
+ state->min_batch_interval = tmp.min_latency;
+ state->queue_size = tmp.nbuffer;
+ state->enable = tmp.nsubscribers > 0;
+
+ return ret;
+}
+
+int orb_check(int fd, FAR bool *updated)
+{
+ struct pollfd fds[1];
+ int ret;
+
+ fds[0].fd = fd;
+ fds[0].events = POLLIN;
+
+ ret = poll(fds, 1, 0);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ *updated = (fds[0].revents & POLLIN) > 0;
+ return 0;
+}
+
+int orb_ioctl(int handle, int cmd, unsigned long arg)
+{
+ return ioctl(handle, cmd, arg);
+}
+
+int orb_set_interval(int fd, unsigned interval)
+{
+ return ioctl(fd, SNIOC_SET_INTERVAL, (unsigned long)interval);
+}
+
+int orb_get_interval(int fd, FAR unsigned *interval)
+{
+ struct sensor_state_s tmp;
+ int ret;
+
+ ret = ioctl(fd, SNIOC_GET_STATE, (unsigned long)(uintptr_t)&tmp);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ *interval = tmp.min_interval;
+ return ret;
+}
+
+int orb_set_batch_interval(int fd, unsigned batch_interval)
+{
+ return ioctl(fd, SNIOC_BATCH, (unsigned long)batch_interval);
+}
+
+int orb_get_batch_interval(int fd, FAR unsigned *batch_interval)
+{
+ struct sensor_state_s tmp;
+ int ret;
+
+ ret = ioctl(fd, SNIOC_GET_STATE, (unsigned long)(uintptr_t)&tmp);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ *batch_interval = tmp.min_latency;
+ return ret;
+}
+
+orb_abstime orb_absolute_time(void)
+{
+ struct timespec ts;
+
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ return 1000000ull * ts.tv_sec + ts.tv_nsec / 1000;
+}
+
+int orb_exists(FAR const struct orb_metadata *meta, int instance)
+{
+ struct sensor_state_s state;
+ char path[PATH_MAX];
+ int ret;
+ int fd;
+
+ snprintf(path, PATH_MAX, ORB_SENSOR_PATH"%s%d", meta->o_name, instance);
+ fd = open(path, 0);
+ if (fd < 0)
+ {
+ return -1;
+ }
+
+ ret = ioctl(fd, SNIOC_GET_STATE, (unsigned long)(uintptr_t)&state);
+ close(fd);
+ if (ret < 0)
+ {
+ return -1;
+ }
+
+ return state.nadvertisers > 0 ? 0 : -1;
+}
+
+int orb_group_count(FAR const struct orb_metadata *meta)
+{
+ unsigned instance = 0;
+
+ while (orb_exists(meta, instance) == 0)
+ {
+ ++instance;
+ }
+
+ return instance;
+}
diff --git a/system/uorb/uORB/uORB.h b/system/uorb/uORB/uORB.h
new file mode 100644
index 000000000..f31ba7063
--- /dev/null
+++ b/system/uorb/uORB/uORB.h
@@ -0,0 +1,645 @@
+/****************************************************************************
+ * apps/system/uorb/uORB/uORB.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __APP_SYSTEM_UORB_UORB_UORB_H
+#define __APP_SYSTEM_UORB_UORB_UORB_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/sensors/ioctl.h>
+#include <nuttx/sensors/sensor.h>
+
+#include <sys/time.h>
+#include <debug.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <syslog.h>
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+struct orb_metadata;
+typedef void (*orb_print_message)(FAR const struct orb_metadata *meta,
+ FAR const void *buffer);
+
+struct orb_metadata
+{
+ FAR const char *o_name; /* Unique object name */
+ uint16_t o_size; /* Object size */
+#ifdef CONFIG_DEBUG_UORB
+ orb_print_message o_cb; /* Function pointer of output topic message */
+#endif
+};
+
+typedef FAR const struct orb_metadata *orb_id_t;
+
+struct orb_state
+{
+ uint32_t max_frequency; /* Object maximum frequency, Hz */
+ uint32_t min_batch_interval; /* Object minimum batch interval, us */
+ uint32_t queue_size; /* The maximum number of buffered elements,
+ * if 1, no queuing is is used
+ */
+ bool enable; /* Indicates whether the current node is
+ * subscribed or activated
+ */
+};
+
+struct orb_object
+{
+ orb_id_t meta; /* The metadata of topic object */
+ int instance; /* The instance of topic object */
+};
+
+typedef uint64_t orb_abstime;
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define ORB_SENSOR_PATH "/dev/sensor/"
+#define ORB_USENSOR_PATH "/dev/usensor"
+
+#ifdef CONFIG_UORB_ALERT
+# define uorbpanic(fmt, ...) _alert(fmt "\n", ##__VA_ARGS__)
+#else
+# define uorbpanic _none
+#endif
+
+#ifdef CONFIG_UORB_ERROR
+# define uorberr(fmt, ...) _err(fmt "\n", ##__VA_ARGS__)
+#else
+# define uorberr _none
+#endif
+
+#ifdef CONFIG_UORB_WARN
+# define uorbwarn(fmt, ...) _warn(fmt "\n", ##__VA_ARGS__)
+#else
+# define uorbwarn _none
+#endif
+
+#ifdef CONFIG_UORB_INFO
+# define uorbinfo(fmt, ...) _info(fmt "\n", ##__VA_ARGS__)
+#else
+# define uorbinfo _none
+#endif
+
+#ifdef CONFIG_DEBUG_UORB
+# define uorbdebug(fmt, ...) syslog(LOG_INFO, fmt "\n", ##__VA_ARGS__)
+#else
+# define uorbdebug _none
+#endif
+
+#define uorbinfo_raw(fmt, ...) syslog(LOG_INFO, fmt "\n", ##__VA_ARGS__)
+
+/**
+ * Generates a pointer to the uORB metadata structure for
+ * a given topic.
+ *
+ * The topic must have been declared previously in scope
+ * with ORB_DECLARE().
+ *
+ * @param name The name of the topic.
+ */
+#define ORB_ID(name) &g_orb_##name
+
+/**
+ * Declare the uORB metadata for a topic (used by code generators).
+ *
+ * @param name The name of the topic.
+ */
+#if defined(__cplusplus)
+# define ORB_DECLARE(name) extern "C" const struct orb_metadata g_orb_##name
+#else
+# define ORB_DECLARE(name) extern const struct orb_metadata g_orb_##name
+#endif
+
+/**
+ * Define (instantiate) the uORB metadata for a topic.
+ *
+ * The uORB metadata is used to help ensure that updates and
+ * copies are accessing the right data.
+ *
+ * Note that there must be no more than one instance of this macro
+ * for each topic.
+ *
+ * @param name The name of the topic.
+ * @param struct The structure the topic provides.
+ * @param cb The function pointer of output topic message.
+ */
+#ifdef CONFIG_DEBUG_UORB
+#define ORB_DEFINE(name, structure, cb) \
+ const struct orb_metadata g_orb_##name = \
+ { \
+ #name, \
+ sizeof(structure), \
+ cb, \
+ };
+#else
+#define ORB_DEFINE(name, structure, cb) \
+ const struct orb_metadata g_orb_##name = \
+ { \
+ #name, \
+ sizeof(structure), \
+ };
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: orb_advertise_multi_queue
+ *
+ * Description:
+ * This performs the initial advertisement of a topic; it creates the topic
+ * node in /dev/sensor and publishes the initial data.
+ *
+ * Input Parameters:
+ * meta The uORB metadata (usually from the ORB_ID() macro)
+ * data A pointer to the initial data to be published.
+ * instance Pointer to an integer which yield the instance ID,
+ * (has default 0 if pointer is NULL).
+ * queue_size Maximum number of buffered elements.
+ *
+ * Returned Value:
+ * -1 on error, otherwise returns an file descriptor
+ * that can be used to publish to the topic.
+ * If the topic in question is not known (due to an
+ * ORB_DEFINE with no corresponding ORB_DECLARE)
+ * this function will return -1 and set errno to ENOENT.
+ ****************************************************************************/
+
+int orb_advertise_multi_queue(FAR const struct orb_metadata *meta,
+ FAR const void *data,
+ FAR int *instance,
+ unsigned int queue_size);
+
+static inline int orb_advertise(FAR const struct orb_metadata *meta,
+ FAR const void *data)
+{
+ return orb_advertise_multi_queue(meta, data, NULL, 1);
+}
+
+static inline int orb_advertise_queue(FAR const struct orb_metadata *meta,
+ FAR const void *data,
+ unsigned int queue_size)
+{
+ return orb_advertise_multi_queue(meta, data, NULL, queue_size);
+}
+
+static inline int orb_advertise_multi(FAR const struct orb_metadata *meta,
+ FAR const void *data,
+ FAR int *instance)
+{
+ return orb_advertise_multi_queue(meta, data, instance, 1);
+}
+
+/****************************************************************************
+ * Name: orb_unadvertise
+ *
+ * Description:
+ * Unadvertise a topic.
+ *
+ * Input Parameters:
+ * handle A handle returned by orb_advertise or orb_advertise_multi.
+ *
+ * Returned Value:
+ * 0 on success.
+ ****************************************************************************/
+
+int orb_unadvertise(int handle);
+
+/****************************************************************************
+ * Name: orb_publish_multi
+ *
+ * Description:
+ * Publish the specified length of new data to a topic.
+ *
+ * The data is published to the topic and any waiting subscribers will be
+ * notified. Subscribers that are not waiting can check the topic for
+ * updates using orb_check.
+ *
+ * Input Parameters:
+ * handle The handle returned from orb_advertise.
+ * data A pointer to the data to be published.
+ * len The length of the data to be published.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with errno set accordingly.
+ ****************************************************************************/
+
+ssize_t orb_publish_multi(int handle, FAR const void *data, size_t len);
+
+static inline int orb_publish(FAR const struct orb_metadata *meta,
+ int handle, FAR const void *data)
+{
+ int ret;
+
+ ret = orb_publish_multi(handle, data, meta->o_size);
+ return ret == meta->o_size ? 0 : -1;
+}
+
+static inline int orb_publish_auto(FAR const struct orb_metadata *meta,
+ FAR int *handle, FAR const void *data,
+ FAR int *instance)
+{
+ if (handle && *handle)
+ {
+ return orb_publish(meta, *handle, data);
+ }
+ else
+ {
+ int tmp;
+
+ tmp = orb_advertise_multi(meta, data, instance);
+ if (tmp < 0)
+ {
+ return tmp;
+ }
+
+ if (handle)
+ {
+ *handle = tmp;
+ return tmp;
+ }
+ else
+ {
+ return orb_unadvertise(tmp);
+ }
+ }
+}
+
+/****************************************************************************
+ * Name: orb_subscribe_multi
+ *
+ * Description:
+ * Subscribe to a topic.
+ *
+ * The data is published to the topic and any waiting subscribers will be
+ * notified. Subscribers that are not waiting can check the topic for
+ * updates using orb_check.
+ *
+ * If there were any publications of the topic prior to the subscription,
+ * an orb_check right after orb_subscribe_multi will return true.
+ *
+ * Subscription will succeed even if the topic has not been advertised;
+ * in this case, the topic will have a timestamp of zero, it will never
+ * signal a poll() event, checking will always return false and it cannot
+ * be copied, until the topic is subsequently advertised.
+ *
+ * Input Parameters:
+ * meta The uORB metadata (usually from the ORB_ID() macro)
+ * instance The instance of the topic. Instance 0 matches the topic of
+ * the orb_subscribe() call.
+ *
+ * Returned Value:
+ * -1 on error, otherwise returns a handle
+ * that can be used to read and update the topic.
+ * If the topic in question is not known (due to an
+ * ORB_DEFINE_OPTIONAL with no corresponding ORB_DECLARE)
+ * this function will return -1 and set errno to ENOENT.
+ ****************************************************************************/
+
+int orb_subscribe_multi(FAR const struct orb_metadata *meta,
+ unsigned instance);
+
+static inline int orb_subscribe(FAR const struct orb_metadata *meta)
+{
+ return orb_subscribe_multi(meta, 0);
+}
+
+/****************************************************************************
+ * Name: orb_unsubscribe
+ *
+ * Description:
+ * Unsubscribe from a topic.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ *
+ * Returned Value:
+ * 0 on success.
+ ****************************************************************************/
+
+int orb_unsubscribe(int handle);
+
+/****************************************************************************
+ * Name: orb_copy_multi
+ *
+ * Description:
+ * Fetch the specified length of data from a topic.
+ *
+ * This is the only operation that will reset the internal marker that
+ * indicates that a topic has been updated for a subscriber. Once poll
+ * or check return indicating that an updaet is available, this call
+ * must be used to update the subscription.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * buffer Pointer to the buffer receiving the data, or NULL if the
+ * caller wants to clear the updated flag without.
+ * len The length to the buffer receiving the data.
+ *
+ * Returned Value:
+ * The positive non-zero number of bytes read on success.
+ * 0 on if an end-of-file condition,
+ * -1 otherwise with errno set accordingly.
+ ****************************************************************************/
+
+ssize_t orb_copy_multi(int handle, FAR void *buffer, size_t len);
+
+static inline int orb_copy(FAR const struct orb_metadata *meta,
+ int handle, FAR void *buffer)
+{
+ int ret;
+
+ ret = orb_copy_multi(handle, buffer, meta->o_size);
+ return ret == meta->o_size ? 0 : -1;
+}
+
+/****************************************************************************
+ * Name: orb_get_state
+ *
+ * Description:
+ * Get some state about all subscriber of topic.
+ *
+ * This state contains the maximum frequency and minimum batch interval
+ * in all subscriber, and it also contanis enable to indicate whether
+ * the current node is subscribed or activated.
+ *
+ * If no one subscribes this topic, the state is set:
+ * max_frequency to 0. min_batch_interval to 0, enable to false.
+ *
+ * Input Parameters:
+ * handle The handle returned from orb_advertise / orb_subscribe.
+ * state Pointer to an state of struct orb_state type. This is an
+ * output parameter and will be set to the current state of topic.
+ *
+ * Returned Value:
+ * -1 on error.
+ ****************************************************************************/
+
+int orb_get_state(int handle, FAR struct orb_state *state);
+
+/****************************************************************************
+ * Name: orb_check
+ *
+ * Description:
+ * Check whether a topic has been published to since the last orb_copy.
+ *
+ * This check can be used to determine whether to copy the topic when
+ * not using poll(), or to avoid the overhead of calling poll() when the
+ * topic is likely to have updated.
+ *
+ * Updates are tracked on a per-handle basis; this call will continue to
+ * return true until orb_copy is called using the same handle.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * update Set to true if the topic has been updated since the
+ * last time it was copied using this handle.
+ *
+ * Returned Value:
+ * 0 if the check was successful,
+ * -1 otherwise with errno set accordingly.
+ ****************************************************************************/
+
+int orb_check(int handle, FAR bool *updated);
+
+/****************************************************************************
+ * Name: orb_ioctl
+ *
+ * Description:
+ * Ioctl control for the subscriber, the same as ioctl().
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_advertise / orb_subscribe.
+ * cmd Ioctl command.
+ * arg Ioctl argument.
+ *
+ * Returned Value:
+ * 0 on success.
+ ****************************************************************************/
+
+int orb_ioctl(int handle, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Name: orb_set_batch_interval
+ *
+ * Description:
+ * The batch interval set through api is just the value user wants,
+ * and the final value depends on the hardware FIFO capability.
+ * This API will send POLLPRI event to notify publisher and
+ * publisher determine the final batch interval.
+ *
+ * This API is only for topics with hardware fifo, such as sensor with
+ * hardware fifo, otherwise it's meaningless.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * batch_interval An batch interval in us.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with ERRNO set accordingly.
+ ****************************************************************************/
+
+int orb_set_batch_interval(int handle, unsigned batch_interval);
+
+/****************************************************************************
+ * Name: orb_get_batch_interval
+ *
+ * Description:
+ * Get the batch interval in batch mode.
+ *
+ * This API is only for topics with hardware fifo, such as sensor with
+ * hardware fifo, otherwise it's meaningless.
+ *
+ * @see orb_set_batch_interval()
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * batch_interval The returned batch interval in us.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with ERRNO set accordingly.
+ ****************************************************************************/
+
+int orb_get_batch_interval(int handle, FAR unsigned *batch_interval);
+
+/****************************************************************************
+ * Name:
+ *
+ * Description:
+ * Set the minimum interval between which updates seen for a subscription.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * interval An interval period in us.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with ERRNO set accordingly.
+ ****************************************************************************/
+
+int orb_set_interval(int handle, unsigned interval);
+
+/****************************************************************************
+ * Name:
+ *
+ * Description:
+ * Get the minimum interval between which updates seen for a subscription.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * interval The returned interval period in us.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with ERRNO set accordingly.
+ ****************************************************************************/
+
+int orb_get_interval(int handle, FAR unsigned *interval);
+
+/****************************************************************************
+ * Name:
+ * orb_set_frequency
+ *
+ * Description:
+ * Set the maximum frequency for a subscription.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * frequency A frequency in hz.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with ERRNO set accordingly.
+ ****************************************************************************/
+
+static inline int orb_set_frequency(int handle, unsigned frequency)
+{
+ return orb_set_interval(handle, frequency ? 1000000 / frequency : 0);
+}
+
+/****************************************************************************
+ * Name:
+ * orb_get_frequency
+ *
+ * Description:
+ * Get the maximum frequency for a subscription.
+ *
+ * Input Parameters:
+ * handle A handle returned from orb_subscribe.
+ * frequency The returned frequency in hz.
+ *
+ * Returned Value:
+ * 0 on success, -1 otherwise with ERRNO set accordingly.
+ ****************************************************************************/
+
+static inline int orb_get_frequency(int handle, FAR unsigned *frequency)
+{
+ unsigned interval;
+ int ret;
+
+ ret = orb_get_interval(handle, &interval);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ *frequency = interval ? 1000000 / interval : 0;
+
+ return 0;
+}
+
+/****************************************************************************
+ * Name: orb_elapsed_time
+ *
+ * Description:
+ * Get current value of system time in us.
+ *
+ * Returned Value:
+ * Absolute time.
+ ****************************************************************************/
+
+orb_abstime orb_absolute_time(void);
+
+/****************************************************************************
+ * Name: orb_elapsed_time
+ *
+ * Description:
+ * Compute the delta between a timestamp taken in the past and now.
+ *
+ * This function is not interrupt save.
+ *
+ * Input Parameters:
+ * then Past system time.
+ *
+ * Returned Value:
+ * Bewteen time.
+ ****************************************************************************/
+
+static inline orb_abstime orb_elapsed_time(FAR const orb_abstime *then)
+{
+ return orb_absolute_time() - *then;
+}
+
+/****************************************************************************
+ * Name: orb_exists
+ *
+ * Description:
+ * Check if a topic instance has already been advertised.
+ *
+ * Input Parameters:
+ * meta ORB topic metadata.
+ * instance ORB instance
+ *
+ * Returned Value:
+ * 0 if the topic exists, -1 otherwise.
+ ****************************************************************************/
+
+int orb_exists(FAR const struct orb_metadata *meta, int instance);
+
+/****************************************************************************
+ * Name: orb_group_count
+ *
+ * Description:
+ * Get instance amount of advertised topic instances.
+ *
+ * Input Parameters:
+ * meta ORB topic metadata.
+ *
+ * Returned Value:
+ * 0 if none
+ ****************************************************************************/
+
+int orb_group_count(FAR const struct orb_metadata *meta);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __APP_SYSTEM_UORB_UORB_UORB_H */