This is an automated email from the ASF dual-hosted git repository. jerpelea pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 4d3c5cac467232b985f48c29fab664f4f4543325 Author: Felipe Moura <[email protected]> AuthorDate: Sat Aug 1 12:37:00 2026 -0300 drivers/sensors/sensor: always report POLLIN for fetch only sensor A fetch() only lower half reads the device on demand, so its data is always available and there is never anything to wait for. The upper half did not reflect that: poll() only reported POLLIN when the descriptor was opened O_NONBLOCK, and a blocking read() waited on buffersem, which is only posted when the lower half drives notify_event from an interrupt of its own. A fetch() only sensor with no interrupt therefore never satisfied poll()/read() at all. This is not hypothetical: in the in tree nucleo-h563zi:dts configuration CONFIG_STM32_DTS_TRIGGER defaults to 0, which selects stm32_dts_fetch(), and no CONFIG_STM32_DTS_ITEN_* option is enabled, so the DTS interrupt never fires. A blocking read() on that sensor waits forever, even though stm32_dts_fetch() performs a complete software triggered measurement on its own and needs no interrupt at all. Applications had to work around this by forcing O_NONBLOCK on the descriptor themselves, see apache/nuttx-apps#3686. Drop the O_NONBLOCK special case in both paths: sensor_poll() now always reports POLLIN for a fetch only sensor and sensor_read() calls fetch() directly instead of waiting. Update the sensor_ops_s::fetch documentation, which described the old contract. With the wait gone, buffersem has no waiters left. Its only two readers were the ones removed here, both in the fetch path: the wait in sensor_read() and the nxsem_get_value() in sensor_poll(). The remaining nxsem_post() calls in sensor_push_event() and sensor_notify_event() had nothing left to wake, so drop the semaphore and those posts as well. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Felipe Moura <[email protected]> --- drivers/sensors/sensor.c | 54 +++++++++--------------------------------- include/nuttx/sensors/sensor.h | 8 +++---- 2 files changed, 15 insertions(+), 47 deletions(-) diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c index cb88cb33e17..ef08737ae82 100644 --- a/drivers/sensors/sensor.c +++ b/drivers/sensors/sensor.c @@ -101,7 +101,6 @@ struct sensor_user_s */ unsigned int event; /* The event of this sensor, eg: SENSOR_EVENT_FLUSH_COMPLETE. */ bool flushing; /* The is used to indicate user is flushing */ - sem_t buffersem; /* Wakeup user waiting for data in circular buffer */ size_t bufferpos; /* The index of user generation in buffer */ /* The subscriber info @@ -774,7 +773,6 @@ static int sensor_open(FAR struct file *filep) user->state.interval = UINT32_MAX; user->state.esize = upper->state.esize; user->state.nonwakeup = true; - nxsem_init(&user->buffersem, 0, 0); list_add_tail(&upper->userlist, &user->node); /* The new user generation, notify to other users */ @@ -835,7 +833,6 @@ static int sensor_close(FAR struct file *filep) } list_delete(&user->node); - nxsem_destroy(&user->buffersem); /* The user is closed, notify to other users */ @@ -871,24 +868,18 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer, return -EINVAL; } - if (!(filep->f_oflags & O_NONBLOCK)) - { - nxrmutex_unlock(&upper->lock); - ret = nxsem_wait_uninterruptible(&user->buffersem); - if (ret < 0) - { - return ret; - } + /* Fetch the data from the device directly, there is nothing to wait + * for. This matches the POLLIN sensor_poll() always reports for a + * fetch only sensor. + */ - nxrmutex_lock(&upper->lock); - } - else if (!upper->state.nsubscribers) + if (!upper->state.nsubscribers) { ret = -EAGAIN; goto out; } - ret = lower->ops->fetch(lower, filep, buffer, len); + ret = lower->ops->fetch(lower, filep, buffer, len); } else if (circbuf_is_empty(&upper->buffer)) { @@ -1166,7 +1157,6 @@ static int sensor_poll(FAR struct file *filep, FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user = filep->f_priv; pollevent_t eventset = 0; - int semcount; int ret = 0; nxrmutex_lock(&upper->lock); @@ -1184,20 +1174,12 @@ static int sensor_poll(FAR struct file *filep, fds->priv = filep; if (lower->ops->fetch) { - /* Always return POLLIN for fetch data directly(non-block) */ + /* Always return POLLIN for fetch only sensor: the data is read + * from the device on demand by sensor_read(), so there is never + * anything to wait for. + */ - if (filep->f_oflags & O_NONBLOCK) - { - eventset |= POLLIN; - } - else - { - nxsem_get_value(&user->buffersem, &semcount); - if (semcount > 0) - { - eventset |= POLLIN; - } - } + eventset |= POLLIN; } else if (sensor_is_updated(upper, user)) { @@ -1229,7 +1211,6 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data, FAR struct sensor_lowerhalf_s *lower = upper->lower; FAR struct sensor_user_s *user; unsigned long envcount; - int semcount; int ret; nxrmutex_lock(&upper->lock); @@ -1287,12 +1268,6 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data, { if (sensor_is_updated(upper, user)) { - nxsem_get_value(&user->buffersem, &semcount); - if (semcount < 1) - { - nxsem_post(&user->buffersem); - } - sensor_pollnotify_one(user, POLLIN, SENSOR_ROLE_RD); } } @@ -1305,17 +1280,10 @@ static void sensor_notify_event(FAR void *priv) { FAR struct sensor_upperhalf_s *upper = priv; FAR struct sensor_user_s *user; - int semcount; nxrmutex_lock(&upper->lock); list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node) { - nxsem_get_value(&user->buffersem, &semcount); - if (semcount < 1) - { - nxsem_post(&user->buffersem); - } - sensor_pollnotify_one(user, POLLIN, SENSOR_ROLE_RD); } diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h index e675be50a67..f266eb8cdd3 100644 --- a/include/nuttx/sensors/sensor.h +++ b/include/nuttx/sensors/sensor.h @@ -353,10 +353,10 @@ struct sensor_ops_s * If fetch isn't NULL, upper half driver will disable intermediate * buffer and userspace can't set buffer size by ioctl. * - * You can call this function to read sensor register data by I2C/SPI bus - * when open mode is non-block, and poll are always successful. - * When you call this function and open mode is block, you will wait - * until sensor data ready, then read sensor data. + * You can call this function to read sensor register data by I2C/SPI + * bus. The data is read from the device on demand, so it is always + * available: poll() always reports POLLIN and read() never blocks, + * whether or not the open mode is non-block. * * Input Parameters: * lower - The instance of lower half sensor driver.
