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)&reginfo);
+      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 */