driver/sensor: add new feature about sensor driver

N/A

1.support for multi-user access
2.support special cmd to control sensor
3.support userspace to set size of intermediate buffer
  by ioctl: SNOIC_SET_BUFFER_SIZE

Change-Id: Ida1c01fb8f505de8a28349c1b26167614aa56acc
Signed-off-by: dongjiuzhu <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu
2020-11-03 17:59:57 +08:00
parent af068a3b48
commit de30e82f92
6 changed files with 135 additions and 50 deletions
+7
View File
@@ -11,6 +11,13 @@ menuconfig SENSORS
if SENSORS
config SENSORS_NPOLLWAITERS
int "Number of poll threads"
default 2
---help---
Maximum number of threads than can be waiting for POLL events.
Default: 2
config SENSORS_WTGAHRS2
bool "Wtgahrs2 Sensor Support"
default n
+1 -1
View File
@@ -534,7 +534,7 @@ int l3gd20_register(int devno, FAR struct spi_dev_s *spi,
priv->data.timestamp = 0;
priv->lower.type = SENSOR_TYPE_GYROSCOPE;
priv->lower.buffer_bytes = sizeof(struct sensor_event_gyro) * CONFIG_SENSORS_L3GD20_BUFFER_SIZE;
priv->lower.buffer_size = sizeof(struct sensor_event_gyro) * CONFIG_SENSORS_L3GD20_BUFFER_SIZE;
priv->lower.ops = &g_l2gd20_ops;
priv->lower.uncalibrated = true;
+87 -40
View File
@@ -73,9 +73,11 @@ struct sensor_buffer_s
struct sensor_upperhalf_s
{
/* poll structures of threads waiting for driver events. */
FAR struct pollfd *fds[CONFIG_SENSORS_NPOLLWAITERS];
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 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 */
@@ -297,20 +299,26 @@ static void sensor_buffer_release(FAR struct sensor_buffer_s *buffer)
static void sensor_pollnotify(FAR struct sensor_upperhalf_s *upper,
pollevent_t eventset)
{
FAR struct pollfd *fd;
int semcount;
int i;
if (upper->fds)
for (i = 0; i < CONFIG_SENSORS_NPOLLWAITERS; i++)
{
upper->fds->revents |= (upper->fds->events & eventset);
if (upper->fds->revents != 0)
fd = upper->fds[i];
if (fd)
{
sninfo("Report events: %02x\n", upper->fds->revents);
fd->revents |= (fd->events & eventset);
nxsem_get_value(upper->fds->sem, &semcount);
if (semcount < 1)
if (fd->revents != 0)
{
nxsem_post(upper->fds->sem);
sninfo("Report events: %02x\n", fd->revents);
nxsem_get_value(fd->sem, &semcount);
if (semcount < 1)
{
nxsem_post(fd->sem);
}
}
}
}
@@ -320,6 +328,7 @@ static int sensor_open(FAR struct file *filep)
{
FAR struct inode *inode = filep->f_inode;
FAR struct sensor_upperhalf_s *upper = inode->i_private;
uint8_t tmp;
int ret;
ret = nxsem_wait(&upper->exclsem);
@@ -328,17 +337,21 @@ static int sensor_open(FAR struct file *filep)
return ret;
}
if (upper->crefs)
tmp = upper->crefs + 1;
if (tmp == 0)
{
ret = -EBUSY;
/* More than 255 opens; uint8_t overflows to zero */
ret = -EMFILE;
goto err;
}
else
else if (tmp == 1)
{
upper->crefs++;
upper->fds = NULL;
sensor_buffer_reset(upper->buffer);
}
upper->crefs = tmp;
err:
nxsem_post(&upper->exclsem);
return ret;
}
@@ -421,16 +434,17 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
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.
/* 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)
upper->buffer->size > lower->buffer_size &&
sensor_buffer_len(upper->buffer) <= lower->buffer_size)
{
sensor_buffer_resize(&upper->buffer, lower->type, lower->buffer_bytes);
sensor_buffer_resize(&upper->buffer, lower->type,
lower->buffer_size);
}
again:
@@ -511,7 +525,7 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
/* Adjust length of buffer in batch mode */
sensor_buffer_resize(&upper->buffer, lower->type,
lower->buffer_bytes +
lower->buffer_size +
ROUNDUP(*val, upper->interval) /
upper->interval *
g_sensor_info[lower->type].esize);
@@ -522,12 +536,36 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case SNIOC_GET_NEVENTBUF:
{
*val = lower->buffer_bytes / g_sensor_info[lower->type].esize;
*val = lower->buffer_size / g_sensor_info[lower->type].esize;
}
break;
case SNIOC_SET_BUFFER_SIZE:
{
if (*val != 0)
{
lower->buffer_size = ROUNDUP(*val,
g_sensor_info[lower->type].esize);
sensor_buffer_resize(&upper->buffer, lower->type,
lower->buffer_size);
*val = lower->buffer_size;
}
}
break;
default:
ret = -ENOTTY;
/* Lowerhalf driver process other cmd. */
if (lower->ops->control)
{
ret = lower->ops->control(lower, cmd, arg);
}
else
{
ret = -ENOTTY;
}
break;
}
@@ -542,6 +580,7 @@ static int sensor_poll(FAR struct file *filep,
FAR struct sensor_upperhalf_s *upper = inode->i_private;
pollevent_t eventset = 0;
int ret;
int i;
ret = nxsem_wait(&upper->exclsem);
if (ret < 0)
@@ -551,14 +590,23 @@ static int sensor_poll(FAR struct file *filep,
if (setup)
{
if (upper->fds)
for (i = 0; i < CONFIG_SENSORS_NPOLLWAITERS; i++)
{
ret = -EBUSY;
goto errout;
if (NULL == upper->fds[i])
{
upper->fds[i] = fds;
fds->priv = &upper->fds[i];
break;
}
}
upper->fds = fds;
fds->priv = &upper->fds;
/* Don't have enough space to store fds */
if (i == CONFIG_SENSORS_NPOLLWAITERS)
{
ret = -ENOSPC;
goto errout;
}
if (!sensor_buffer_is_empty(upper->buffer))
{
@@ -572,16 +620,15 @@ static int sensor_poll(FAR struct file *filep,
}
else if (fds->priv != NULL)
{
FAR struct pollfd **slot = (FAR struct pollfd **)fds->priv;
if (!slot)
for (i = 0; i < CONFIG_SENSORS_NPOLLWAITERS; i++)
{
ret = -EIO;
goto errout;
if (fds == upper->fds[i])
{
upper->fds[i] = NULL;
fds->priv = NULL;
break;
}
}
*slot = NULL;
fds->priv = NULL;
}
errout:
@@ -590,7 +637,7 @@ errout:
}
static void sensor_push_event(FAR void *priv, FAR const void *data,
uint32_t bytes)
uint32_t bytes)
{
FAR struct sensor_upperhalf_s *upper = priv;
int semcount;
@@ -677,15 +724,15 @@ int sensor_register(FAR struct sensor_lowerhalf_s *lower, int devno)
lower->priv = upper;
lower->push_event = sensor_push_event;
if (!lower->buffer_bytes)
if (!lower->buffer_size)
{
lower->buffer_bytes = g_sensor_info[lower->type].esize;
lower->buffer_size = g_sensor_info[lower->type].esize;
}
/* Initialize sensor buffer */
ret = sensor_buffer_create(&upper->buffer,
lower->type, lower->buffer_bytes);
lower->type, lower->buffer_size);
if (ret)
{
goto buf_err;
+7 -7
View File
@@ -437,7 +437,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
{
FAR struct wtgahrs2_dev_s *rtdata;
FAR struct wtgahrs2_sensor_s *tmp;
#if CONFIG_SERIAL_TERMIOS
#ifdef CONFIG_SERIAL_TERMIOS
struct termios opt;
#endif
FAR char *argv[2];
@@ -466,7 +466,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
goto open_err;
}
#if CONFIG_SERIAL_TERMIOS
#ifdef CONFIG_SERIAL_TERMIOS
file_ioctl(&rtdata->file, TCGETS, &opt);
cfmakeraw(&opt);
cfsetispeed(&opt, B115200);
@@ -479,7 +479,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
tmp = &rtdata->dev[WTGAHRS2_ACCEL_IDX];
tmp->lower.ops = &g_wtgahrs2_ops;
tmp->lower.type = SENSOR_TYPE_ACCELEROMETER;
tmp->lower.buffer_bytes = sizeof(struct sensor_event_accel);
tmp->lower.buffer_size = sizeof(struct sensor_event_accel);
ret = sensor_register(&tmp->lower, devno);
if (ret < 0)
{
@@ -491,7 +491,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
tmp = &rtdata->dev[WTGAHRS2_GYRO_IDX];
tmp->lower.ops = &g_wtgahrs2_ops;
tmp->lower.type = SENSOR_TYPE_GYROSCOPE;
tmp->lower.buffer_bytes = sizeof(struct sensor_event_gyro);
tmp->lower.buffer_size = sizeof(struct sensor_event_gyro);
ret = sensor_register(&tmp->lower, devno);
if (ret < 0)
{
@@ -503,7 +503,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
tmp = &rtdata->dev[WTGAHRS2_MAG_IDX];
tmp->lower.ops = &g_wtgahrs2_ops;
tmp->lower.type = SENSOR_TYPE_MAGNETIC_FIELD;
tmp->lower.buffer_bytes = sizeof(struct sensor_event_mag);
tmp->lower.buffer_size = sizeof(struct sensor_event_mag);
ret = sensor_register(&tmp->lower, devno);
if (ret < 0)
{
@@ -515,7 +515,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
tmp = &rtdata->dev[WTGAHRS2_BARO_IDX];
tmp->lower.ops = &g_wtgahrs2_ops;
tmp->lower.type = SENSOR_TYPE_BAROMETER;
tmp->lower.buffer_bytes = sizeof(struct sensor_event_baro);
tmp->lower.buffer_size = sizeof(struct sensor_event_baro);
ret = sensor_register(&tmp->lower, devno);
if (ret < 0)
{
@@ -527,7 +527,7 @@ int wtgahrs2_initialize(FAR const char *path, int devno)
tmp = &rtdata->dev[WTGAHRS2_GPS_IDX];
tmp->lower.ops = &g_wtgahrs2_ops;
tmp->lower.type = SENSOR_TYPE_GPS;
tmp->lower.buffer_bytes = sizeof(struct sensor_event_gps);
tmp->lower.buffer_size = sizeof(struct sensor_event_gps);
ret = sensor_register(&tmp->lower, devno);
if (ret < 0)
{
+10
View File
@@ -273,4 +273,14 @@
#define SNIOC_GET_NEVENTBUF _SNIOC(0x0070)
/* Command: SNIOC_SET_BUFFER_SIZE
* Description: Use to set size of intermediate circual buffer in upper half driver.
* Argument: This is the size of buffer pointer.
* Note: The application layer can set size of intermediate circual buffer
* by this ioctl cmd. The size is in bytes, it should be a multiple of
* an event.
*/
#define SNIOC_SET_BUFFER_SIZE _SNIOC(0x0071)
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
+23 -2
View File
@@ -495,6 +495,27 @@ struct sensor_ops_s
CODE int (*batch)(FAR struct sensor_lowerhalf_s *lower,
FAR unsigned int *latency_us);
/**************************************************************************
* Name: control
*
* In this method, we allow user to set some special config for the sensor,
* such as changing the custom mode, setting the custom resolution, reset,
* etc, which are all parsed and implemented by lower half driver.
*
* Input Parameters:
* lower - The instance of lower half sensor driver.
* cmd - The special cmd for sensor.
* arg - The parameters associated with cmd.
*
* Returned Value:
* Zero (OK) on success; a negated errno value on failure.
* -ENOTTY - The cmd don't support.
*
**************************************************************************/
CODE int (*control)(FAR struct sensor_lowerhalf_s *lower,
int cmd, unsigned long arg);
};
/* This structure is the generic form of state structure used by lower half
@@ -507,7 +528,7 @@ struct sensor_lowerhalf_s
int type;
/* The bytes length of the circular buffer used.
/* The size of the circular buffer used, in bytes units.
* 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
@@ -517,7 +538,7 @@ struct sensor_lowerhalf_s
* or three length of sensor event.
*/
uint32_t buffer_bytes;
uint32_t buffer_size;
/* The uncalibrated use to describe whether the sensor event is
* uncalibrated. True is uncalibrated data, false is calibrated data,