718fcfac1e
Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
325 lines
8.1 KiB
C
325 lines
8.1 KiB
C
/****************************************************************************
|
|
* 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 <stdio.h>
|
|
#include <sys/ioctl.h>
|
|
#include <unistd.h>
|
|
|
|
#include <uORB/uORB.h>
|
|
|
|
/****************************************************************************
|
|
* Private Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: orb_advsub_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)
|
|
* flag The open flag.
|
|
* 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_advsub_open(FAR const struct orb_metadata *meta, int flags,
|
|
int instance, unsigned int queue_size)
|
|
{
|
|
char path[ORB_PATH_MAX];
|
|
int fd;
|
|
int ret;
|
|
int err;
|
|
|
|
snprintf(path, ORB_PATH_MAX, ORB_SENSOR_PATH"%s%d", meta->o_name,
|
|
instance);
|
|
|
|
/* Check existance before open */
|
|
|
|
flags |= O_CLOEXEC;
|
|
fd = open(path, flags);
|
|
if (fd < 0)
|
|
{
|
|
struct sensor_reginfo_s reginfo;
|
|
reginfo.path = path;
|
|
reginfo.esize = meta->o_size;
|
|
reginfo.nbuffer = queue_size;
|
|
reginfo.persist = !!(flags & SENSOR_PERSIST);
|
|
|
|
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);
|
|
err = errno;
|
|
close(fd);
|
|
if (ret < 0 && err != EEXIST)
|
|
{
|
|
return ret;
|
|
}
|
|
|
|
fd = open(path, flags);
|
|
if (fd < 0)
|
|
{
|
|
return fd;
|
|
}
|
|
|
|
if (err != EEXIST)
|
|
{
|
|
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;
|
|
}
|
|
|
|
static int
|
|
orb_advertise_multi_queue_flags(FAR const struct orb_metadata *meta,
|
|
FAR const void *data, FAR int *instance,
|
|
unsigned int queue_size, int flags)
|
|
{
|
|
int inst;
|
|
int fd;
|
|
|
|
/* Open the node as an advertiser */
|
|
|
|
inst = instance ? *instance : orb_group_count(meta);
|
|
|
|
fd = orb_advsub_open(meta, flags, 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;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
int orb_open(FAR const char *name, int instance, int flags)
|
|
{
|
|
char path[ORB_PATH_MAX];
|
|
|
|
snprintf(path, ORB_PATH_MAX, ORB_SENSOR_PATH"%s%d", name, instance);
|
|
return open(path, O_CLOEXEC | flags);
|
|
}
|
|
|
|
int orb_close(int fd)
|
|
{
|
|
return close(fd);
|
|
}
|
|
|
|
int orb_advertise_multi_queue(FAR const struct orb_metadata *meta,
|
|
FAR const void *data, FAR int *instance,
|
|
unsigned int queue_size)
|
|
{
|
|
return orb_advertise_multi_queue_flags(meta, data, instance,
|
|
queue_size, O_WRONLY);
|
|
}
|
|
|
|
int orb_advertise_multi_queue_persist(FAR const struct orb_metadata *meta,
|
|
FAR const void *data,
|
|
FAR int *instance,
|
|
unsigned int queue_size)
|
|
{
|
|
return orb_advertise_multi_queue_flags(meta, data, instance, queue_size,
|
|
O_WRONLY | SENSOR_PERSIST);
|
|
}
|
|
|
|
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_advsub_open(meta, O_RDONLY, instance, 0);
|
|
}
|
|
|
|
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->nsubscribers = tmp.nsubscribers;
|
|
state->generation = tmp.generation;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int orb_check(int fd, FAR bool *updated)
|
|
{
|
|
return ioctl(fd, SNIOC_UPDATED, (unsigned long)(uintptr_t)updated);
|
|
}
|
|
|
|
int orb_ioctl(int fd, int cmd, unsigned long arg)
|
|
{
|
|
return ioctl(fd, 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[ORB_PATH_MAX];
|
|
int ret;
|
|
int fd;
|
|
|
|
snprintf(path, ORB_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;
|
|
}
|