driver/sensor: add unified management for sensor
Signed-off-by: dongjiuzhu <dongjiuzhu1@xiaomi.com>
This commit is contained in:
parent
d1f82ced26
commit
fa09c6a8bc
@ -37,6 +37,8 @@
|
||||
|
||||
ifeq ($(CONFIG_SENSORS),y)
|
||||
|
||||
CSRCS += sensor.c
|
||||
|
||||
ifeq ($(CONFIG_SENSORS_HCSR04),y)
|
||||
CSRCS += hc_sr04.c
|
||||
endif
|
||||
|
756
drivers/sensors/sensor.c
Normal file
756
drivers/sensors/sensor.c
Normal file
@ -0,0 +1,756 @@
|
||||
/****************************************************************************
|
||||
* drivers/sensors/sensor.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 <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <poll.h>
|
||||
#include <fcntl.h>
|
||||
#include <nuttx/kmalloc.h>
|
||||
#include <nuttx/sensors/sensor.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Device naming ************************************************************/
|
||||
|
||||
#define ROUNDUP(x, esize) ((x + (esize - 1)) / (esize)) * (esize)
|
||||
#define DEVNAME_FMT "/dev/sensor/%s%s%d"
|
||||
#define DEVNAME_MAX 64
|
||||
#define DEVNAME_UNCAL "_uncal"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
/* This structure describes sensor info */
|
||||
|
||||
struct sensor_info
|
||||
{
|
||||
uint8_t idx;
|
||||
const uint8_t esize;
|
||||
FAR const char *name;
|
||||
};
|
||||
|
||||
/* This structure describes sensor circular buffer */
|
||||
|
||||
struct sensor_buffer_s
|
||||
{
|
||||
uint32_t head;
|
||||
uint32_t tail;
|
||||
uint32_t size;
|
||||
FAR void *data;
|
||||
};
|
||||
|
||||
/* This structure describes the state of the upper half driver */
|
||||
|
||||
struct sensor_upperhalf_s
|
||||
{
|
||||
FAR struct sensor_lowerhalf_s *lower; /* the handle of lower half driver */
|
||||
FAR struct sensor_buffer_s *buffer; /* The circualr buffer of sensor device */
|
||||
FAR struct pollfd *fds; /* poll structures of threads waiting for driver events. */
|
||||
uint8_t idx; /* The index number of node path */
|
||||
uint8_t crefs; /* Number of times the device has been opened */
|
||||
sem_t exclsem; /* Manages exclusive access to file operations */
|
||||
sem_t buffersem; /* Wakeup user waiting for data in circular buffer */
|
||||
bool enabled; /* The status of sensor enable or disable */
|
||||
unsigned int interval; /* The sample interval for sensor, in us */
|
||||
unsigned int latency; /* The batch latency for sensor, in us */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void sensor_pollnotify(FAR struct sensor_upperhalf_s *upper,
|
||||
pollevent_t eventset);
|
||||
static int sensor_open(FAR struct file *filep);
|
||||
static int sensor_close(FAR struct file *filep);
|
||||
static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int sensor_ioctl(FAR struct file *filep, int cmd,
|
||||
unsigned long arg);
|
||||
static int sensor_poll(FAR struct file *filep, FAR struct pollfd *fds,
|
||||
bool setup);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct sensor_info g_sensor_info[] =
|
||||
{
|
||||
{0, sizeof(struct sensor_event_accel), "accel"},
|
||||
{0, sizeof(struct sensor_event_mag), "mag"},
|
||||
{0, sizeof(struct sensor_event_gyro), "gyro"},
|
||||
{0, sizeof(struct sensor_event_light), "light"},
|
||||
{0, sizeof(struct sensor_event_baro), "baro"},
|
||||
{0, sizeof(struct sensor_event_prox), "prox"},
|
||||
{0, sizeof(struct sensor_event_humi), "humi"},
|
||||
{0, sizeof(struct sensor_event_temp), "temp"},
|
||||
{0, sizeof(struct sensor_event_rgb), "rgb"},
|
||||
{0, sizeof(struct sensor_event_hall), "hall"},
|
||||
{0, sizeof(struct sensor_event_ir), "ir"},
|
||||
{0, sizeof(struct sensor_event_gps), "gps"},
|
||||
{0, sizeof(struct sensor_event_uv), "uv"},
|
||||
{0, sizeof(struct sensor_event_noise), "noise"},
|
||||
{0, sizeof(struct sensor_event_pm25), "pm25"},
|
||||
{0, sizeof(struct sensor_event_pm1p0), "pm1p0"},
|
||||
{0, sizeof(struct sensor_event_pm10), "pm10"},
|
||||
{0, sizeof(struct sensor_event_co2), "co2"},
|
||||
{0, sizeof(struct sensor_event_hcho), "hcho"},
|
||||
{0, sizeof(struct sensor_event_tvoc), "tvoc"},
|
||||
{0, sizeof(struct sensor_event_ph), "ph"},
|
||||
{0, sizeof(struct sensor_event_dust), "dust"},
|
||||
{0, sizeof(struct sensor_event_hrate), "hrate"},
|
||||
{0, sizeof(struct sensor_event_hbeat), "hbeat"},
|
||||
};
|
||||
|
||||
static const struct file_operations g_sensor_fops =
|
||||
{
|
||||
sensor_open, /* open */
|
||||
sensor_close, /* close */
|
||||
sensor_read, /* read */
|
||||
NULL, /* write */
|
||||
NULL, /* seek */
|
||||
sensor_ioctl, /* ioctl */
|
||||
sensor_poll /* poll */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static bool sensor_buffer_is_empty(FAR struct sensor_buffer_s *buffer)
|
||||
{
|
||||
return buffer->head == buffer->tail;
|
||||
}
|
||||
|
||||
static uint32_t sensor_buffer_len(FAR struct sensor_buffer_s *buffer)
|
||||
{
|
||||
return buffer->head - buffer->tail;
|
||||
}
|
||||
|
||||
static uint32_t sensor_buffer_unused(FAR struct sensor_buffer_s *buffer)
|
||||
{
|
||||
return buffer->size - sensor_buffer_len(buffer);
|
||||
}
|
||||
|
||||
static void sensor_buffer_reset(FAR struct sensor_buffer_s *buffer)
|
||||
{
|
||||
buffer->head = buffer->tail = 0;
|
||||
}
|
||||
|
||||
static void sensor_buffer_push(FAR struct sensor_buffer_s *buffer,
|
||||
FAR const void *data, uint32_t bytes)
|
||||
{
|
||||
uint32_t space = sensor_buffer_unused(buffer);
|
||||
uint32_t off = buffer->head % buffer->size;
|
||||
uint32_t overwrite = 0;
|
||||
|
||||
/* If buffer is full or there is not enough space, overwriting of old
|
||||
* data will occur, we should move tail point after pushing data
|
||||
* completely.
|
||||
*/
|
||||
|
||||
if (bytes > buffer->size)
|
||||
{
|
||||
data += bytes - buffer->size;
|
||||
bytes = buffer->size;
|
||||
}
|
||||
|
||||
if (bytes > space)
|
||||
{
|
||||
overwrite = bytes - space;
|
||||
}
|
||||
|
||||
space = buffer->size - off;
|
||||
if (bytes < space)
|
||||
{
|
||||
space = bytes;
|
||||
}
|
||||
|
||||
memcpy(buffer->data + off, data, space);
|
||||
memcpy(buffer->data, data + space, bytes - space);
|
||||
buffer->head += bytes;
|
||||
buffer->tail += overwrite;
|
||||
}
|
||||
|
||||
static uint32_t sensor_buffer_pop(FAR struct sensor_buffer_s *buffer,
|
||||
FAR void *data, uint32_t bytes)
|
||||
{
|
||||
uint32_t len = sensor_buffer_len(buffer);
|
||||
uint32_t off;
|
||||
|
||||
if (bytes > len)
|
||||
{
|
||||
bytes = len;
|
||||
}
|
||||
|
||||
if (!data)
|
||||
{
|
||||
goto skip;
|
||||
}
|
||||
|
||||
off = buffer->tail % buffer->size;
|
||||
len = buffer->size - off;
|
||||
if (bytes < len)
|
||||
{
|
||||
len = bytes;
|
||||
}
|
||||
|
||||
memcpy(data, buffer->data + off, len);
|
||||
memcpy(data + len, buffer->data, bytes - len);
|
||||
|
||||
skip:
|
||||
buffer->tail += bytes;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int sensor_buffer_resize(FAR struct sensor_buffer_s **buffer,
|
||||
int type, uint32_t bytes)
|
||||
{
|
||||
FAR struct sensor_buffer_s *tmp;
|
||||
int len = sensor_buffer_len(*buffer);
|
||||
int skipped;
|
||||
|
||||
bytes = ROUNDUP(bytes, g_sensor_info[type].esize);
|
||||
tmp = kmm_malloc(sizeof(*tmp) + bytes);
|
||||
if (!tmp)
|
||||
{
|
||||
snerr("Faild to alloc memory for circular buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tmp->data = tmp + 1;
|
||||
|
||||
skipped = (bytes > len) ? 0 : len - bytes;
|
||||
len -= skipped;
|
||||
sensor_buffer_pop(*buffer, NULL, skipped);
|
||||
sensor_buffer_pop(*buffer, tmp->data, len);
|
||||
|
||||
tmp->size = bytes;
|
||||
tmp->head = len;
|
||||
tmp->tail = 0;
|
||||
|
||||
kmm_free(*buffer);
|
||||
*buffer = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sensor_buffer_create(FAR struct sensor_buffer_s **buffer,
|
||||
int type, uint32_t bytes)
|
||||
{
|
||||
FAR struct sensor_buffer_s *tmp;
|
||||
|
||||
bytes = ROUNDUP(bytes, g_sensor_info[type].esize);
|
||||
|
||||
tmp = kmm_malloc(sizeof(*tmp) + bytes);
|
||||
if (!tmp)
|
||||
{
|
||||
snerr("Faild to malloc memory for circular buffer\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
tmp->size = bytes;
|
||||
tmp->data = tmp + 1;
|
||||
tmp->head = 0;
|
||||
tmp->tail = 0;
|
||||
|
||||
*buffer = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sensor_buffer_release(FAR struct sensor_buffer_s *buffer)
|
||||
{
|
||||
kmm_free(buffer);
|
||||
}
|
||||
|
||||
static void sensor_pollnotify(FAR struct sensor_upperhalf_s *upper,
|
||||
pollevent_t eventset)
|
||||
{
|
||||
int semcount;
|
||||
|
||||
if (upper->fds)
|
||||
{
|
||||
upper->fds->revents |= (upper->fds->events & eventset);
|
||||
|
||||
if (upper->fds->revents != 0)
|
||||
{
|
||||
sninfo("Report events: %02x\n", upper->fds->revents);
|
||||
|
||||
nxsem_get_value(upper->fds->sem, &semcount);
|
||||
if (semcount < 1)
|
||||
{
|
||||
nxsem_post(upper->fds->sem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sensor_open(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
int ret;
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (upper->crefs)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
}
|
||||
else
|
||||
{
|
||||
upper->crefs++;
|
||||
upper->fds = NULL;
|
||||
sensor_buffer_reset(upper->buffer);
|
||||
}
|
||||
|
||||
nxsem_post(&upper->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_close(FAR struct file *filep)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct sensor_lowerhalf_s *lower = upper->lower;
|
||||
int ret;
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (--upper->crefs <= 0 && upper->enabled)
|
||||
{
|
||||
ret = lower->ops->activate ?
|
||||
lower->ops->activate(lower, false) : -ENOTSUP;
|
||||
if (ret >= 0)
|
||||
{
|
||||
upper->enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
nxsem_post(&upper->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
||||
size_t len)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct sensor_lowerhalf_s *lower = upper->lower;
|
||||
ssize_t ret;
|
||||
|
||||
if (!buffer || !len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We must make sure that when the semaphore is equal to 1, there must
|
||||
* be events avaliable in the buffer, so we use a while statement to
|
||||
* synchronize this case that other read operations consume events
|
||||
* that have just entered the buffer.
|
||||
*/
|
||||
|
||||
while (sensor_buffer_is_empty(upper->buffer))
|
||||
{
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
goto again;
|
||||
}
|
||||
else
|
||||
{
|
||||
nxsem_post(&upper->exclsem);
|
||||
ret = nxsem_wait_uninterruptible(&upper->buffersem);
|
||||
if (ret)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = sensor_buffer_pop(upper->buffer, buffer, len);
|
||||
|
||||
/* Release some buffer space when current mode isn't batch mode and last
|
||||
* mode is batch mode, and the number of bytes avaliable in buffer is
|
||||
* less than the number of bytes origin.
|
||||
*/
|
||||
|
||||
if (upper->latency == 0 &&
|
||||
upper->buffer->size > lower->buffer_bytes &&
|
||||
sensor_buffer_len(upper->buffer) <= lower->buffer_bytes)
|
||||
{
|
||||
sensor_buffer_resize(&upper->buffer, lower->type, lower->buffer_bytes);
|
||||
}
|
||||
|
||||
again:
|
||||
nxsem_post(&upper->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
FAR struct sensor_lowerhalf_s *lower = upper->lower;
|
||||
FAR unsigned int *val = (unsigned int *)(uintptr_t)arg;
|
||||
int ret;
|
||||
|
||||
sninfo("cmd=%x arg=%08x\n", cmd, arg);
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case SNIOC_ACTIVATE:
|
||||
{
|
||||
if (upper->enabled == !!arg)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lower->ops->activate ?
|
||||
lower->ops->activate(lower, !!arg) : -ENOTSUP;
|
||||
if (ret >= 0)
|
||||
{
|
||||
upper->enabled = !!arg;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SNIOC_SET_INTERVAL:
|
||||
{
|
||||
if (upper->interval == *val)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lower->ops->set_interval ?
|
||||
lower->ops->set_interval(lower, val) : -ENOTSUP;
|
||||
if (ret >= 0)
|
||||
{
|
||||
upper->interval = *val;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SNIOC_BATCH:
|
||||
{
|
||||
if (upper->interval == 0)
|
||||
{
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (upper->latency == *val)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ret = lower->ops->batch ?
|
||||
lower->ops->batch(lower, val) : -ENOTSUP;
|
||||
if (ret >= 0)
|
||||
{
|
||||
upper->latency = *val;
|
||||
if (*val != 0)
|
||||
{
|
||||
/* Adjust length of buffer in batch mode */
|
||||
|
||||
sensor_buffer_resize(&upper->buffer, lower->type,
|
||||
lower->buffer_bytes +
|
||||
ROUNDUP(*val, upper->interval) /
|
||||
upper->interval *
|
||||
g_sensor_info[lower->type].esize);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SNIOC_GET_NEVENTBUF:
|
||||
{
|
||||
*val = lower->buffer_bytes / g_sensor_info[lower->type].esize;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = -ENOTTY;
|
||||
break;
|
||||
}
|
||||
|
||||
nxsem_post(&upper->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sensor_poll(FAR struct file *filep,
|
||||
struct pollfd *fds, bool setup)
|
||||
{
|
||||
FAR struct inode *inode = filep->f_inode;
|
||||
FAR struct sensor_upperhalf_s *upper = inode->i_private;
|
||||
pollevent_t eventset = 0;
|
||||
int ret;
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (setup)
|
||||
{
|
||||
if (upper->fds)
|
||||
{
|
||||
ret = -EBUSY;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
upper->fds = fds;
|
||||
fds->priv = &upper->fds;
|
||||
|
||||
if (!sensor_buffer_is_empty(upper->buffer))
|
||||
{
|
||||
eventset |= (fds->events & POLLIN);
|
||||
}
|
||||
|
||||
if (eventset)
|
||||
{
|
||||
sensor_pollnotify(upper, eventset);
|
||||
}
|
||||
}
|
||||
else if (fds->priv != NULL)
|
||||
{
|
||||
FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
|
||||
|
||||
if (!slot)
|
||||
{
|
||||
ret = -EIO;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
*slot = NULL;
|
||||
fds->priv = NULL;
|
||||
}
|
||||
|
||||
errout:
|
||||
nxsem_post(&upper->exclsem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sensor_push_event(FAR void *priv, FAR const void *data,
|
||||
uint32_t bytes)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper = priv;
|
||||
int semcount;
|
||||
|
||||
if (!bytes || nxsem_wait(&upper->exclsem) < 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sensor_buffer_push(upper->buffer, data, bytes);
|
||||
sensor_pollnotify(upper, POLLIN);
|
||||
nxsem_get_value(&upper->buffersem, &semcount);
|
||||
if (semcount < 1)
|
||||
{
|
||||
nxsem_post(&upper->buffersem);
|
||||
}
|
||||
|
||||
nxsem_post(&upper->exclsem);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_register
|
||||
*
|
||||
* Description:
|
||||
* This function binds an instance of a "lower half" Sensor driver with the
|
||||
* "upper half" Sensor device and registers that device so that can be used
|
||||
* by application code.
|
||||
*
|
||||
* We will register the chararter device by node name format based on the
|
||||
* type of sensor. Multiple types of the same type are distinguished by
|
||||
* numbers. eg: accel0, accel1
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if the driver was successfully register; A negated errno value is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sensor_register(FAR struct sensor_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper;
|
||||
char path[DEVNAME_MAX];
|
||||
int ret = -EINVAL;
|
||||
|
||||
DEBUGASSERT(lower != NULL);
|
||||
|
||||
if (lower->type >= SENSOR_TYPE_COUNT)
|
||||
{
|
||||
snerr("ERROR: Type is invalid\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Allocate the upper-half data structure */
|
||||
|
||||
upper = kmm_zalloc(sizeof(struct sensor_upperhalf_s));
|
||||
if (!upper)
|
||||
{
|
||||
snerr("ERROR: Allocation failed\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* Initialize the upper-half data structure */
|
||||
|
||||
upper->lower = lower;
|
||||
|
||||
nxsem_init(&upper->exclsem, 0, 1);
|
||||
nxsem_init(&upper->buffersem, 0, 0);
|
||||
|
||||
nxsem_set_protocol(&upper->buffersem, SEM_PRIO_NONE);
|
||||
|
||||
/* Bind the lower half data structure member */
|
||||
|
||||
lower->priv = upper;
|
||||
lower->push_event = sensor_push_event;
|
||||
|
||||
if (!lower->buffer_bytes)
|
||||
{
|
||||
lower->buffer_bytes = g_sensor_info[lower->type].esize;
|
||||
}
|
||||
|
||||
/* Initialize sensor buffer */
|
||||
|
||||
ret = sensor_buffer_create(&upper->buffer,
|
||||
lower->type, lower->buffer_bytes);
|
||||
if (ret)
|
||||
{
|
||||
goto buf_err;
|
||||
}
|
||||
|
||||
upper->idx = g_sensor_info[lower->type].idx++;
|
||||
snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
|
||||
g_sensor_info[lower->type].name,
|
||||
lower->uncalibrated ? DEVNAME_UNCAL : "",
|
||||
upper->idx);
|
||||
sninfo("Registering %s\n", path);
|
||||
|
||||
ret = register_driver(path, &g_sensor_fops, 0666, upper);
|
||||
if (ret)
|
||||
{
|
||||
goto drv_err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
drv_err:
|
||||
sensor_buffer_release(upper->buffer);
|
||||
g_sensor_info[lower->type].idx--;
|
||||
buf_err:
|
||||
nxsem_destroy(&upper->exclsem);
|
||||
nxsem_destroy(&upper->buffersem);
|
||||
|
||||
kmm_free(upper);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function unregister character node and release all resource about
|
||||
* upper half driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
****************************************************************************/
|
||||
|
||||
void sensor_unregister(FAR struct sensor_lowerhalf_s *lower)
|
||||
{
|
||||
FAR struct sensor_upperhalf_s *upper;
|
||||
char path[DEVNAME_MAX];
|
||||
|
||||
DEBUGASSERT(lower != NULL);
|
||||
DEBUGASSERT(lower->priv != NULL);
|
||||
|
||||
upper = lower->priv;
|
||||
|
||||
snprintf(path, DEVNAME_MAX, DEVNAME_FMT,
|
||||
g_sensor_info[lower->type].name,
|
||||
lower->uncalibrated ? DEVNAME_UNCAL : "",
|
||||
upper->idx);
|
||||
sninfo("UnRegistering %s\n", path);
|
||||
unregister_driver(path);
|
||||
|
||||
nxsem_destroy(&upper->exclsem);
|
||||
nxsem_destroy(&upper->buffersem);
|
||||
|
||||
sensor_buffer_release(upper->buffer);
|
||||
kmm_free(upper);
|
||||
}
|
@ -181,8 +181,11 @@
|
||||
/* IOCTL commands unique to the SCD30 */
|
||||
|
||||
/* SNIOC_RESET */ /* Arg: None */
|
||||
|
||||
/* SNIOC_START */ /* Arg: None */
|
||||
|
||||
/* SNIOC_STOP */ /* Arg: None */
|
||||
|
||||
/* SNIOC_READ_CONVERT_DATA */ /* Arg: struct scd30_conv_data_s* */
|
||||
#define SNIOC_SET_INTERVAL _SNIOC(0x0054) /* Arg: uint16_t value (seconds) */
|
||||
#define SNIOC_SET_TEMP_OFFSET _SNIOC(0x0055) /* Arg: uint16_t value (0.01 Kelvin) */
|
||||
@ -194,9 +197,13 @@
|
||||
/* IOCTL commands unique to the SGP30 */
|
||||
|
||||
/* SNIOC_RESET */ /* Arg: None */
|
||||
|
||||
/* SNIOC_START_SELFTEST */ /* Arg: None */
|
||||
|
||||
/* SNIOC_READ_CONVERT_DATA */ /* Arg: struct sgp30_conv_data_s* */
|
||||
|
||||
/* SNIOC_READ_RAW_DATA */ /* Arg: struct sgp30_raw_data_s* */
|
||||
|
||||
#define SNIOC_GET_BASELINE _SNIOC(0x005a) /* Arg: struct sgp30_baseline_s* */
|
||||
#define SNIOC_SET_BASELINE _SNIOC(0x005b) /* Arg: const struct sgp30_baseline_s* */
|
||||
#define SNIOC_SET_HUMIDITY _SNIOC(0x005c) /* Arg: uint32_t value (mg/m³) */
|
||||
@ -204,9 +211,13 @@
|
||||
/* IOCTL commands unique to the SPS30 */
|
||||
|
||||
/* SNIOC_RESET */ /* Arg: None */
|
||||
|
||||
/* SNIOC_START */ /* Arg: None */
|
||||
|
||||
/* SNIOC_STOP */ /* Arg: None */
|
||||
|
||||
/* SNIOC_READ_CONVERT_DATA */ /* Arg: struct sps30_conv_data_s* */
|
||||
|
||||
#define SNIOC_SET_CLEAN_INTERVAL _SNIOC(0x005d) /* Arg: uint32_t value (seconds) */
|
||||
#define SNIOC_START_FAN_CLEANING _SNIOC(0x005e) /* Arg: None */
|
||||
|
||||
@ -227,4 +238,39 @@
|
||||
#define SNIOC_SET_RESOLUTION _SNIOC(0x0065) /* Arg: uint8_t value */
|
||||
#define SNIOC_SET_RANGE _SNIOC(0x0066) /* Arg: uint8_t value */
|
||||
|
||||
/* Command: SNIOC_ACTIVATE
|
||||
* Description: Enable or disable sensor
|
||||
* Argument: true or false.
|
||||
*/
|
||||
|
||||
#define SNIOC_ACTIVATE _SNIOC(0x0067)
|
||||
|
||||
/* Command: SNIOC_SET_INTERVAL
|
||||
* Description: Set interval between samples
|
||||
* Argument: This is the interval pointer, in microseconds
|
||||
*/
|
||||
|
||||
#define SNIOC_SET_INTERVAL _SNIOC(0x0068)
|
||||
|
||||
/* Command: SNIOC_BATCH
|
||||
* Description: Set batch latency between batch data.
|
||||
* Argument: This is the latency pointer, in microseconds
|
||||
*/
|
||||
|
||||
#define SNIOC_BATCH _SNIOC(0x0069)
|
||||
|
||||
/* Command: SNIOC_GET_NEVENTBUF
|
||||
* Description: the number of sensor events that sensor buffer of upper half holds.
|
||||
* Argument: This is the number of events pointer, is output parameter.
|
||||
* Note: We need to tell the application layer number of sensor events in
|
||||
* sensor buffer. This buffer is used to solve the problem that the
|
||||
* application layer can't read the sensor event in time. We recommend
|
||||
* the number of sensor events in application layer's buffer is same as
|
||||
* result by call this function.
|
||||
* This is number of sensor events rather than the length of buffer.
|
||||
* See sensor.h(struct sensor_lower_half_s buffer_bytes).
|
||||
*/
|
||||
|
||||
#define SNIOC_GET_NEVENTBUF _SNIOC(0x0070)
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
|
||||
|
615
include/nuttx/sensors/sensor.h
Normal file
615
include/nuttx/sensors/sensor.h
Normal file
@ -0,0 +1,615 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/sensors/sensors.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 __INCLUDE_NUTTX_SENSORS_SENSOR_H
|
||||
#define __INCLUDE_NUTTX_SENSORS_SENSOR_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <nuttx/sensors/ioctl.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* sensor type definition */
|
||||
|
||||
/* Accelerometer
|
||||
* All values are in SI units (m/s^2), and measure the acceleration of the
|
||||
* device minus the acceleration dut to gravity.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_ACCELEROMETER 0
|
||||
|
||||
/* Magneric Field
|
||||
* All values are in micro-Tesla (uT) and measure the geomagnetic field
|
||||
* in X, Y and Z axis.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_MAGNETIC_FIELD 1
|
||||
|
||||
/* Gyroscope
|
||||
* All values are in radians/second and measure the rate of rotation around
|
||||
* the X, Y and Z axis.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_GYROSCOPE 2
|
||||
|
||||
/* Ambient Light
|
||||
* The ambient light sensor value is returned in SI units lux.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_LIGHT 3
|
||||
|
||||
/* Barometer
|
||||
* All values are in hectopascal (hPa) and measure the athmospheric pressure
|
||||
* we can calculate altitude by perssure.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_BAROMETER 4
|
||||
|
||||
/* Proximity
|
||||
* The values correspond to the distance to the nearest
|
||||
* object in centimeters.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PROXIMITY 5
|
||||
|
||||
/* Relative Humidity
|
||||
* A relative humidity sensor measure relative ambient air humidity and
|
||||
* return a value in percent.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_RELATIVE_HUMIDITY 6
|
||||
|
||||
/* Ambient Temperature
|
||||
* The ambient (room) temperature in degree Celsius
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 7
|
||||
|
||||
/* RGB
|
||||
* We use these values of RGB to weighted to obtain the color of LED.
|
||||
* These values is in unit percent.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_RGB 8
|
||||
|
||||
/* Hall
|
||||
* All values are in bool type (0 or 1) and it often is used to as switch.
|
||||
* A values of 1 indicates that switch on.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HALL 9
|
||||
|
||||
/* IR (Infrared Ray)
|
||||
* This sensor can detect a human approach and outputs a signal from
|
||||
* interrupt pins. This sensor value is in lux.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_IR 10
|
||||
|
||||
/* GPS
|
||||
* A sensor of this type returns gps data. Include year, month, day,
|
||||
* hour, minutes, seconds, altitude, longitude, latitude.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_GPS 11
|
||||
|
||||
/* Ultraviolet light sensor
|
||||
* This sensor can identify the UV index in ambient light help people
|
||||
* to effectively protect themselves from sunburns, cancer or eye damage.
|
||||
* This value range is 0 - 15.
|
||||
*/
|
||||
#define SENSOR_TYPE_ULTRAVIOLET 12
|
||||
|
||||
/* Noise Loudness
|
||||
* A sensor of this type returns the loudness of noise in SI units (db)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_NOISE 13
|
||||
|
||||
/* PM25
|
||||
* A sensor of this type returns the content of pm2.5 in the air
|
||||
* This value is in SI units (ug/m^3)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PM25 14
|
||||
|
||||
/* PM1P0
|
||||
* A sensor of this type returns the content of pm1.0 in the air
|
||||
* This value is in SI units (ug/m^3)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PM1P0 15
|
||||
|
||||
/* PM10
|
||||
* A sensor of this type returns the content of pm10 in the air
|
||||
* This value is in SI units (ug/m^3)
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PM10 16
|
||||
|
||||
/* CO2
|
||||
* A sensor of this type returns the content of CO2 in the air
|
||||
* This vaule is in units (ppm-part per million).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_CO2 17
|
||||
|
||||
/* HCHO
|
||||
* The HCHO pollution is an important indicator of household air
|
||||
* pollution. This value is in units (ppm-part per million).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HCHO 18
|
||||
|
||||
/* TVOC (total volatile organic compounds)
|
||||
* The indoor TVOC is cause indoor air pollution is one of the
|
||||
* main reasons why. This value is in units (ppb-part per billion).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_TVOC 19
|
||||
|
||||
/* PH
|
||||
* The acid-base degree describes the strength of the aqueous
|
||||
* solution, expressed by pH. In the thermodynamic standard
|
||||
* condition, the aqueous solution with pH=7 is neutral,
|
||||
* pH<7 is acidic, and pH>7 is alkaline.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_PH 20
|
||||
|
||||
/* Dust
|
||||
* A sensor of this type returns the content of dust in the air
|
||||
* values is in ug/m^3.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_DUST 21
|
||||
|
||||
/* Heart Rate
|
||||
* A sensor of this type returns the current heart rate.
|
||||
* Current heart rate is in beats per minute (BPM).
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HEART_RATE 22
|
||||
|
||||
/* Heart Beat
|
||||
* A sensor of this type returns an event evetytime
|
||||
* a hear beat peek is detected. Peak here ideally corresponds
|
||||
* to the positive peak in the QRS complex of and ECG signal.
|
||||
*/
|
||||
|
||||
#define SENSOR_TYPE_HEART_BEAT 23
|
||||
|
||||
/* The total number of sensor */
|
||||
|
||||
#define SENSOR_TYPE_COUNT 24
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
static inline uint64_t sensor_get_timestamp(void)
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
#ifdef CONFIG_CLOCK_MONOTONIC
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#endif
|
||||
|
||||
return 1000000ull * ts.tv_sec + ts.tv_nsec / 1000;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* These structures prefixed with sensor_event are sensor data, and member
|
||||
* that are not used must be written as NAN or INT_MIN/INT_MAX, than
|
||||
* reported.
|
||||
*/
|
||||
|
||||
struct sensor_event_accel /* Type: Accerometer */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float x; /* Axis X in m/s^2 */
|
||||
float y; /* Axis Y in m/s^2 */
|
||||
float z; /* Axis Z in m/s^2 */
|
||||
float temperature; /* Temperature in degrees celsius */
|
||||
};
|
||||
|
||||
struct sensor_event_gyro /* Type: Gyroscope */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float x; /* Axis X in rad/s */
|
||||
float y; /* Axis Y in rad/s */
|
||||
float z; /* Axis Z in rad/s */
|
||||
float temperature; /* Temperature in degrees celsius */
|
||||
};
|
||||
|
||||
struct sensor_event_mag /* Type: Magnetic Field */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float x; /* Axis X in Gauss or micro Tesla (uT) */
|
||||
float y; /* Axis Y in Gauss or micro Tesla (uT) */
|
||||
float z; /* Axis Z in Gauss or micro Tesla (uT) */
|
||||
float temperature; /* Temperature in degrees celsius */
|
||||
};
|
||||
|
||||
struct sensor_event_baro /* Type: Barometer */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float pressure; /* pressure measurement in millibar or hpa */
|
||||
float temperature; /* Temperature in degrees celsius */
|
||||
};
|
||||
|
||||
struct sensor_event_prox /* Type: proximity */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float proximity; /* distance to the nearest object in centimeters */
|
||||
};
|
||||
|
||||
struct sensor_event_light /* Type: Light */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float light; /* in SI lux units */
|
||||
};
|
||||
|
||||
struct sensor_event_humi /* Type: Relative Humidity */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float humidity; /* in percent */
|
||||
};
|
||||
|
||||
struct sensor_event_temp /* Type: Ambient Temperature */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float temperature; /* Temperature in degrees celsius */
|
||||
};
|
||||
|
||||
struct sensor_event_rgb /* Type: RGB */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float r; /* Units is percent */
|
||||
float g; /* Units is percent */
|
||||
float b; /* Units is percent */
|
||||
};
|
||||
|
||||
struct sensor_event_hall /* Type: HALL */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
bool hall; /* Boolean type */
|
||||
};
|
||||
|
||||
struct sensor_event_ir /* Type: Infrared Ray */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float ir; /* in SI units lux */
|
||||
};
|
||||
|
||||
struct sensor_event_gps /* Type: Gps */
|
||||
{
|
||||
int year; /* Time */
|
||||
int month;
|
||||
int day;
|
||||
int hour;
|
||||
int min;
|
||||
int sec;
|
||||
int msec;
|
||||
|
||||
float yaw; /* Unit is Si degrees */
|
||||
float height; /* Unit is SI m */
|
||||
float speed; /* Unit is m/s */
|
||||
float latitude; /* Unit is degrees */
|
||||
float longitude; /* Unit is degrees */
|
||||
};
|
||||
|
||||
struct sensor_event_uv /* Type: Ultraviolet Light */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float uvi; /* the vaule range is 0 - 15 */
|
||||
};
|
||||
|
||||
struct sensor_event_noise /* Type: Noise Loudness */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float db; /* in SI units db */
|
||||
};
|
||||
|
||||
struct sensor_event_pm25 /* Type: PM25 */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float pm25; /* in SI units ug/m^3 */
|
||||
};
|
||||
|
||||
struct sensor_event_pm10 /* Type: PM10 */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float pm10; /* in SI units ug/m^3 */
|
||||
};
|
||||
|
||||
struct sensor_event_pm1p0 /* Type: PM1P0 */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float pm1p0; /* in SI units ug/m^3 */
|
||||
};
|
||||
|
||||
struct sensor_event_co2 /* Type: CO2 */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float co2; /* in SI units ppm */
|
||||
};
|
||||
|
||||
struct sensor_event_hcho /* Type: HCHO */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float hcho; /* in SI units ppm */
|
||||
};
|
||||
|
||||
struct sensor_event_tvoc /* Type: TVOC */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float tvoc; /* in SI units ppm */
|
||||
};
|
||||
|
||||
struct sensor_event_ph /* Type: PH */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float ph; /* PH = 7.0 neutral, PH < 7.0 acidic, PH > 7.0 alkaline */
|
||||
};
|
||||
|
||||
struct sensor_event_dust /* Type: DUST */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float dust; /* is SI units ug/m^3 */
|
||||
};
|
||||
|
||||
struct sensor_event_hrate /* Type: Heart Rate */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float bpm; /* is SI units BPM */
|
||||
};
|
||||
|
||||
struct sensor_event_hbeat /* Type: Heart Beat */
|
||||
{
|
||||
uint64_t timestamp; /* Units is microseconds */
|
||||
float beat; /* Units is times/minutes */
|
||||
};
|
||||
|
||||
/* The sensor lower half driver interface */
|
||||
|
||||
struct sensor_lowerhalf_s;
|
||||
struct sensor_ops_s
|
||||
{
|
||||
/**************************************************************************
|
||||
* Name: activate
|
||||
*
|
||||
* Description:
|
||||
* Enable or disable sensor device. when enable sensor, sensor will
|
||||
* work in current mode(if not set, use default mode). when disable
|
||||
* sensor, it will disable sense path and stop convert.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half sensor driver
|
||||
* enable - true(enable) and false(disable)
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*activate)(FAR struct sensor_lowerhalf_s *lower, bool enable);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: set_interval
|
||||
*
|
||||
* Description:
|
||||
* Set the sensor output data period in microseconds for a given sensor.
|
||||
* If *period_us > max_delay it will be truncated to max_dealy and if
|
||||
* *period_us < min_delay it will be replaced by min_delay.
|
||||
*
|
||||
* Before changing the interval, we need to push the prepared data to
|
||||
* ensure that they are not lost.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half sensor driver.
|
||||
* period_us - the time between samples, in us, it may be overwrite by
|
||||
* lower half driver.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*set_interval)(FAR struct sensor_lowerhalf_s *lower,
|
||||
FAR unsigned int *period_us);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: batch
|
||||
*
|
||||
* Description:
|
||||
* Set sensor's maximum report latency in microseconds.
|
||||
*
|
||||
* This function can be called while the sensor is activated,
|
||||
* in which case it must not cause any sensor measurements to be lost.
|
||||
* So, it is necessary to flush fifo or read ready data from data
|
||||
* register to prevent data lost before we using batch mode.
|
||||
*
|
||||
* This sensor default mode isn't batch mode, so we need call this
|
||||
* function and *latency_us != 0.
|
||||
* If *latency_us > max_report_latency it will be truncated to
|
||||
* max_report_latency and return *latency_us to user
|
||||
* And we must flush fifo data to prevent data lost, then adjust latency.
|
||||
*
|
||||
* We can exit batch mode by call this function with *latency_us = 0.
|
||||
* And we must flush fifo data to prevent data lost, then stop batch.
|
||||
*
|
||||
* If sensor doesn't support batching (FIFO size zero), set batch to
|
||||
* NULL.
|
||||
*
|
||||
* We must set interval by calling set_interval before calling batch(),
|
||||
* othrewise, -EINVAL is returned.
|
||||
*
|
||||
* The reason why we don't have flush operation is that we need to push
|
||||
* the prepared data out before adjusting the latency to ensure that the
|
||||
* data will not be lost.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half sensor driver.
|
||||
* latency_us - the time between batch data, in us. It may by overwrite
|
||||
* by lower half driver.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*batch)(FAR struct sensor_lowerhalf_s *lower,
|
||||
FAR unsigned int *latency_us);
|
||||
};
|
||||
|
||||
/* This structure is the generic form of state structure used by lower half
|
||||
* Sensor driver.
|
||||
*/
|
||||
|
||||
struct sensor_lowerhalf_s
|
||||
{
|
||||
/* The type of sensor device */
|
||||
|
||||
int type;
|
||||
|
||||
/* The bytes length of the circular buffer used.
|
||||
* This sensor circular buffer is used to slove issue that application
|
||||
* can't read sensor event in time. If this length of buffer is too large,
|
||||
* the latency of sensor event will be too larage. If the length of buffer
|
||||
* is too small, the event will be overwrite before application read them.
|
||||
* So, it's recommended to set according to sensor odr. If odr is low, you
|
||||
* can set to a length of sensor event. If odr is high, you can set to two
|
||||
* or three length of sensor event.
|
||||
*/
|
||||
|
||||
uint32_t buffer_bytes;
|
||||
|
||||
/* The uncalibrated use to describe whether the sensor event is
|
||||
* uncalibrated. True is uncalibrated data, false is calibrated data,
|
||||
* default false.
|
||||
*/
|
||||
|
||||
bool uncalibrated;
|
||||
|
||||
/* The lower half sensor driver operations */
|
||||
|
||||
FAR const struct sensor_ops_s *ops;
|
||||
|
||||
/**************************************************************************
|
||||
* Name: push_event
|
||||
*
|
||||
* Description:
|
||||
* Lower half driver push sensor event by calling this function.
|
||||
* It is provided by upper half driver to lower half driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* priv - Upper half driver handle
|
||||
* data - The buffer of event, it can be all type of sensor events.
|
||||
* bytes - The number of bytes of sensor event
|
||||
**************************************************************************/
|
||||
|
||||
CODE void (*push_event)(FAR void *priv, FAR const void *data,
|
||||
uint32_t bytes);
|
||||
|
||||
/* The private opaque pointer to be passed to upper-layer during callback */
|
||||
|
||||
FAR void *priv;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* "Upper Half" Sensor Driver Interfaces
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_register
|
||||
*
|
||||
* Description:
|
||||
* This function binds an instance of a "lower half" Sensor driver with the
|
||||
* "upper half" Sensor device and registers that device so that can be used
|
||||
* by application code.
|
||||
*
|
||||
* We will register the chararter device by node name format based on the
|
||||
* type of sensor. Multiple types of the same type are distinguished by
|
||||
* numbers. eg: accel0, accel1
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if the driver was successfully register; A negated errno value is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int sensor_register(FAR struct sensor_lowerhalf_s *dev);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sensor_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function unregister character node and release all resource about
|
||||
* upper half driver.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half sensor driver. This
|
||||
* instance is bound to the sensor driver and must persists as long
|
||||
* as the driver persists.
|
||||
****************************************************************************/
|
||||
|
||||
void sensor_unregister(FAR struct sensor_lowerhalf_s *dev);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __INCLUDE_NUTTX_SENSORS_SENSOR_H */
|
Loading…
Reference in New Issue
Block a user