/**************************************************************************** * 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 #include #include #include #include #include #include /**************************************************************************** * 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 */ uint32_t nsubscribers; /* Number of subscribers */ uint64_t generation; /* Mainline generation */ }; 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" #define ORB_PATH_MAX (NAME_MAX + 16) #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_open * * Description: * Open device exist node with name, instance and flags. * * Input Parameters: * name The topic name. * instance Instance number to open. * flags The open flags. * * Returned Value: * fd on success, otherwise returns negative value and set errno. ****************************************************************************/ int orb_open(FAR const char *name, int instance, int flags); /**************************************************************************** * Name: orb_close * * Description: * Close fd. * * Input Parameters: * fd A fd returned by orb_open. * * Returned Value: * 0 on success. ****************************************************************************/ int orb_close(int fd); /**************************************************************************** * 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) { int instance = 0; return orb_advertise_multi_queue(meta, data, &instance, 1); } static inline int orb_advertise_queue(FAR const struct orb_metadata *meta, FAR const void *data, unsigned int queue_size) { int instance = 0; return orb_advertise_multi_queue(meta, data, &instance, 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_advertise_multi_queue_persist * * Description: * orb_advertise_multi_queue_persist is similar to orb_advertise_mult and * it can ensures that every subscriber has access to current and * future 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). * * 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_persist(FAR const struct orb_metadata *meta, FAR const void *data, FAR int *instance, unsigned int queue_size); /**************************************************************************** * Name: orb_unadvertise * * Description: * Unadvertise a topic. * * Input Parameters: * fd A fd returned by orb_advertise or orb_advertise_multi. * * Returned Value: * 0 on success. ****************************************************************************/ static inline int orb_unadvertise(int fd) { return orb_close(fd); } /**************************************************************************** * 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: * fd The fd 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 fd, FAR const void *data, size_t len); static inline int orb_publish(FAR const struct orb_metadata *meta, int fd, FAR const void *data) { int ret; ret = orb_publish_multi(fd, 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 *fd, FAR const void *data, FAR int *instance) { if (fd && *fd) { return orb_publish(meta, *fd, data); } else { int tmp; tmp = orb_advertise_multi_queue_persist(meta, data, instance, 1); if (tmp < 0) { return tmp; } if (fd) { *fd = 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 fd * 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: * fd A fd returned from orb_subscribe. * * Returned Value: * 0 on success. ****************************************************************************/ static inline int orb_unsubscribe(int fd) { return orb_close(fd); } /**************************************************************************** * 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: * fd A fd 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 fd, FAR void *buffer, size_t len); static inline int orb_copy(FAR const struct orb_metadata *meta, int fd, FAR void *buffer) { int ret; ret = orb_copy_multi(fd, 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: * fd The fd 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 fd, 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-fd basis; this call will continue to * return true until orb_copy is called using the same fd. * * Input Parameters: * fd A fd returned from orb_subscribe. * update Set to true if the topic has been updated since the * last time it was copied using this fd. * * Returned Value: * 0 if the check was successful, * -1 otherwise with errno set accordingly. ****************************************************************************/ int orb_check(int fd, FAR bool *updated); /**************************************************************************** * Name: orb_ioctl * * Description: * Ioctl control for the subscriber, the same as ioctl(). * * Input Parameters: * fd A fd returned from orb_advertise / orb_subscribe. * cmd Ioctl command. * arg Ioctl argument. * * Returned Value: * 0 on success. ****************************************************************************/ int orb_ioctl(int fd, 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: * fd A fd 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 fd, 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: * fd A fd 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 fd, FAR unsigned *batch_interval); /**************************************************************************** * Name: * * Description: * Set the minimum interval between which updates seen for a subscription. * * Input Parameters: * fd A fd 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 fd, unsigned interval); /**************************************************************************** * Name: * * Description: * Get the minimum interval between which updates seen for a subscription. * * Input Parameters: * fd A fd 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 fd, FAR unsigned *interval); /**************************************************************************** * Name: * orb_set_frequency * * Description: * Set the maximum frequency for a subscription. * * Input Parameters: * fd A fd 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 fd, unsigned frequency) { return orb_set_interval(fd, frequency ? 1000000 / frequency : 0); } /**************************************************************************** * Name: * orb_get_frequency * * Description: * Get the maximum frequency for a subscription. * * Input Parameters: * fd A fd 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 fd, FAR unsigned *frequency) { unsigned interval; int ret; ret = orb_get_interval(fd, &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); /**************************************************************************** * Name: orb_get_meta * * Description: * Get the metadata of topic object by name string. * * Input Parameters: * name The name of topic, ex: sensor_accel, sensor_accel0. * * Returned Value: * The metadata on success. NULL on failure. ****************************************************************************/ FAR const struct orb_metadata *orb_get_meta(FAR const char *name); #ifdef __cplusplus } #endif #endif /* __APP_SYSTEM_UORB_UORB_UORB_H */