sensor: add SNIOC_READLAST
If enable SNIOC_READLAST, sensor_read will return 0 when there is no new data until last read. Signed-off-by: Jiuzhu Dong <dongjiuzhu1@xiaomi.com>
This commit is contained in:
parent
2f5727b102
commit
6f3873dfa2
@ -95,6 +95,7 @@ struct sensor_upperhalf_s
|
||||
struct circbuf_s buffer; /* The circular buffer of sensor device */
|
||||
sem_t exclsem; /* Manages exclusive access to file operations */
|
||||
struct list_node userlist; /* List of users */
|
||||
bool readlast; /* The flag of readlast */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -525,52 +526,61 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We must make sure that when the semaphore is equal to 1, there must
|
||||
* be events available 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.
|
||||
/* If readlast is true, you can always read the last data
|
||||
* in the circbuffer as initial value for new users when the
|
||||
* sensor device has not yet generated new data, otherwise,
|
||||
* it will return 0 when there isn't new data.
|
||||
*/
|
||||
|
||||
while (circbuf_is_empty(&upper->buffer))
|
||||
if (upper->readlast)
|
||||
{
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
if (circbuf_is_empty(&upper->buffer))
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
ret = -ENODATA;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
nxsem_post(&upper->exclsem);
|
||||
ret = nxsem_wait_uninterruptible(&user->buffersem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = nxsem_wait(&upper->exclsem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (user->generation == upper->state.generation)
|
||||
{
|
||||
user->generation--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Always read the last data in the circbuffer as initial value
|
||||
* for new users when the sensor device has not yet generated
|
||||
* new data.
|
||||
*/
|
||||
|
||||
if (user->generation == upper->state.generation)
|
||||
else
|
||||
{
|
||||
user->generation--;
|
||||
/* We must make sure that when the semaphore is equal to 1,
|
||||
* there must be events available 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 (circbuf_is_empty(&upper->buffer) ||
|
||||
user->generation == upper->state.generation)
|
||||
{
|
||||
if (filep->f_oflags & O_NONBLOCK)
|
||||
{
|
||||
ret = -EAGAIN;
|
||||
goto out;
|
||||
}
|
||||
else
|
||||
{
|
||||
nxmutex_unlock(&upper->lock);
|
||||
ret = nxsem_wait_uninterruptible(&user->buffersem);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
nxmutex_lock(&upper->lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If user's generation isn't within circbuffer range, the
|
||||
* oldest data in circbuffer are returned to the users.
|
||||
*/
|
||||
|
||||
else if (!sensor_in_range(upper->state.generation - lower->nbuffer,
|
||||
user->generation, upper->state.generation))
|
||||
if (!sensor_in_range(upper->state.generation - lower->nbuffer,
|
||||
user->generation, upper->state.generation))
|
||||
|
||||
{
|
||||
user->generation = upper->state.generation - lower->nbuffer;
|
||||
@ -704,6 +714,12 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
}
|
||||
break;
|
||||
|
||||
case SNIOC_READLAST:
|
||||
{
|
||||
upper->readlast = !!arg;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Lowerhalf driver process other cmd. */
|
||||
@ -969,6 +985,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
|
||||
/* Initialize the upper-half data structure */
|
||||
|
||||
list_initialize(&upper->userlist);
|
||||
upper->readlast = true;
|
||||
upper->state.esize = esize;
|
||||
upper->state.min_interval = ULONG_MAX;
|
||||
upper->state.min_latency = ULONG_MAX;
|
||||
|
@ -326,4 +326,13 @@
|
||||
#define SNIOC_UNREGISTER _SNIOC(0x0090)
|
||||
#endif
|
||||
|
||||
/* Command: SNIOC_READLAST
|
||||
* Description: If enable readlast, there is no data update in time,
|
||||
* the latest data can always be returned.
|
||||
* Disable readlast, if there is no data update, return 0.
|
||||
* Argument: True or false
|
||||
*/
|
||||
|
||||
#define SNIOC_READLAST _SNIOC(0x0091)
|
||||
|
||||
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
|
||||
|
Loading…
Reference in New Issue
Block a user