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 */
|
struct circbuf_s buffer; /* The circular buffer of sensor device */
|
||||||
sem_t exclsem; /* Manages exclusive access to file operations */
|
sem_t exclsem; /* Manages exclusive access to file operations */
|
||||||
struct list_node userlist; /* List of users */
|
struct list_node userlist; /* List of users */
|
||||||
|
bool readlast; /* The flag of readlast */
|
||||||
};
|
};
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -525,13 +526,35 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* We must make sure that when the semaphore is equal to 1, there must
|
/* If readlast is true, you can always read the last data
|
||||||
* be events available in the buffer, so we use a while statement to
|
* in the circbuffer as initial value for new users when the
|
||||||
* synchronize this case that other read operations consume events
|
* sensor device has not yet generated new data, otherwise,
|
||||||
* that have just entered the buffer.
|
* it will return 0 when there isn't new data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
while (circbuf_is_empty(&upper->buffer))
|
if (upper->readlast)
|
||||||
|
{
|
||||||
|
if (circbuf_is_empty(&upper->buffer))
|
||||||
|
{
|
||||||
|
ret = -ENODATA;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user->generation == upper->state.generation)
|
||||||
|
{
|
||||||
|
user->generation--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
while (circbuf_is_empty(&upper->buffer) ||
|
||||||
|
user->generation == upper->state.generation)
|
||||||
{
|
{
|
||||||
if (filep->f_oflags & O_NONBLOCK)
|
if (filep->f_oflags & O_NONBLOCK)
|
||||||
{
|
{
|
||||||
@ -540,36 +563,23 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nxsem_post(&upper->exclsem);
|
nxmutex_unlock(&upper->lock);
|
||||||
ret = nxsem_wait_uninterruptible(&user->buffersem);
|
ret = nxsem_wait_uninterruptible(&user->buffersem);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = nxsem_wait(&upper->exclsem);
|
nxmutex_lock(&upper->lock);
|
||||||
if (ret < 0)
|
|
||||||
{
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
|
||||||
{
|
|
||||||
user->generation--;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If user's generation isn't within circbuffer range, the
|
/* If user's generation isn't within circbuffer range, the
|
||||||
* oldest data in circbuffer are returned to the users.
|
* oldest data in circbuffer are returned to the users.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else if (!sensor_in_range(upper->state.generation - lower->nbuffer,
|
if (!sensor_in_range(upper->state.generation - lower->nbuffer,
|
||||||
user->generation, upper->state.generation))
|
user->generation, upper->state.generation))
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -704,6 +714,12 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SNIOC_READLAST:
|
||||||
|
{
|
||||||
|
upper->readlast = !!arg;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* Lowerhalf driver process other cmd. */
|
/* 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 */
|
/* Initialize the upper-half data structure */
|
||||||
|
|
||||||
list_initialize(&upper->userlist);
|
list_initialize(&upper->userlist);
|
||||||
|
upper->readlast = true;
|
||||||
upper->state.esize = esize;
|
upper->state.esize = esize;
|
||||||
upper->state.min_interval = ULONG_MAX;
|
upper->state.min_interval = ULONG_MAX;
|
||||||
upper->state.min_latency = ULONG_MAX;
|
upper->state.min_latency = ULONG_MAX;
|
||||||
|
@ -326,4 +326,13 @@
|
|||||||
#define SNIOC_UNREGISTER _SNIOC(0x0090)
|
#define SNIOC_UNREGISTER _SNIOC(0x0090)
|
||||||
#endif
|
#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 */
|
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user