mirror of
https://github.com/apache/nuttx.git
synced 2026-05-30 05:16:47 +08:00
driver/sensors: support sensor flush operation
Supports the flush operation of the sensor. The application can initiate a flush action through ioctl SNIOC_FLUSH to trigger flush, and the call will be returned immediately. Using SNIOC_GET_EVENTS to clear flush event, However, the flush implementation is asynchronous, when all the flush data is push to upper circbuffer, the POLLPRI event(FLUSH_COMPLETED) will be reported. Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
@@ -87,6 +87,8 @@ struct sensor_user_s
|
|||||||
bool changed; /* This is used to indicate event happens and need to
|
bool changed; /* This is used to indicate event happens and need to
|
||||||
* asynchronous notify other users
|
* asynchronous notify other users
|
||||||
*/
|
*/
|
||||||
|
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 */
|
sem_t buffersem; /* Wakeup user waiting for data in circular buffer */
|
||||||
size_t bufferpos; /* The index of user generation in buffer */
|
size_t bufferpos; /* The index of user generation in buffer */
|
||||||
|
|
||||||
@@ -879,6 +881,51 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SNIOC_GET_EVENTS:
|
||||||
|
{
|
||||||
|
nxrmutex_lock(&upper->lock);
|
||||||
|
*(FAR unsigned int *)(uintptr_t)arg = user->event;
|
||||||
|
user->event = 0;
|
||||||
|
nxrmutex_unlock(&upper->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
case SNIOC_FLUSH:
|
||||||
|
{
|
||||||
|
nxrmutex_lock(&upper->lock);
|
||||||
|
|
||||||
|
/* If the sensor is not activated, return -EINVAL. */
|
||||||
|
|
||||||
|
if (upper->state.nsubscribers == 0)
|
||||||
|
{
|
||||||
|
nxrmutex_unlock(&upper->lock);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lower->ops->flush != NULL)
|
||||||
|
{
|
||||||
|
/* Lower half driver will do flush in asynchronous mode,
|
||||||
|
* flush will be completed until push event happened with
|
||||||
|
* bytes is zero.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = lower->ops->flush(lower, filep);
|
||||||
|
if (ret >= 0)
|
||||||
|
{
|
||||||
|
user->flushing = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If flush is not supported, complete immediately */
|
||||||
|
|
||||||
|
user->event |= SENSOR_EVENT_FLUSH_COMPLETE;
|
||||||
|
sensor_pollnotify_one(user, POLLPRI);
|
||||||
|
}
|
||||||
|
|
||||||
|
nxrmutex_unlock(&upper->lock);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
/* Lowerhalf driver process other cmd. */
|
/* Lowerhalf driver process other cmd. */
|
||||||
@@ -972,13 +1019,31 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
|
|||||||
int semcount;
|
int semcount;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
envcount = bytes / upper->state.esize;
|
nxrmutex_lock(&upper->lock);
|
||||||
if (!envcount || bytes != envcount * upper->state.esize)
|
if (bytes == 0)
|
||||||
{
|
{
|
||||||
|
list_for_every_entry(&upper->userlist, user, struct sensor_user_s,
|
||||||
|
node)
|
||||||
|
{
|
||||||
|
if (user->flushing)
|
||||||
|
{
|
||||||
|
user->flushing = false;
|
||||||
|
user->event |= SENSOR_EVENT_FLUSH_COMPLETE;
|
||||||
|
sensor_pollnotify_one(user, POLLPRI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nxrmutex_unlock(&upper->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
envcount = bytes / upper->state.esize;
|
||||||
|
if (bytes != envcount * upper->state.esize)
|
||||||
|
{
|
||||||
|
nxrmutex_unlock(&upper->lock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxrmutex_lock(&upper->lock);
|
|
||||||
if (!circbuf_is_init(&upper->buffer))
|
if (!circbuf_is_init(&upper->buffer))
|
||||||
{
|
{
|
||||||
/* Initialize sensor buffer when data is first generated */
|
/* Initialize sensor buffer when data is first generated */
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ struct sensor_rpmsg_stub_s
|
|||||||
FAR struct rpmsg_endpoint *ept;
|
FAR struct rpmsg_endpoint *ept;
|
||||||
uint64_t cookie;
|
uint64_t cookie;
|
||||||
struct file file;
|
struct file file;
|
||||||
|
bool flushing;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This structure describes the proxy info about remote advertisers. */
|
/* This structure describes the proxy info about remote advertisers. */
|
||||||
@@ -206,6 +207,8 @@ static int sensor_rpmsg_set_interval(FAR struct sensor_lowerhalf_s *lower,
|
|||||||
static int sensor_rpmsg_batch(FAR struct sensor_lowerhalf_s *lower,
|
static int sensor_rpmsg_batch(FAR struct sensor_lowerhalf_s *lower,
|
||||||
FAR struct file *filep,
|
FAR struct file *filep,
|
||||||
FAR unsigned long *latency_us);
|
FAR unsigned long *latency_us);
|
||||||
|
static int sensor_rpmsg_flush(FAR struct sensor_lowerhalf_s *lower,
|
||||||
|
FAR struct file *filep);
|
||||||
static int sensor_rpmsg_selftest(FAR struct sensor_lowerhalf_s *lower,
|
static int sensor_rpmsg_selftest(FAR struct sensor_lowerhalf_s *lower,
|
||||||
FAR struct file *filep,
|
FAR struct file *filep,
|
||||||
unsigned long arg);
|
unsigned long arg);
|
||||||
@@ -249,7 +252,8 @@ static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
|
|||||||
FAR void *data, size_t len,
|
FAR void *data, size_t len,
|
||||||
uint32_t src, FAR void *priv);
|
uint32_t src, FAR void *priv);
|
||||||
static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
||||||
FAR struct sensor_rpmsg_stub_s *stub);
|
FAR struct sensor_rpmsg_stub_s *stub,
|
||||||
|
bool flushed);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Private Data
|
* Private Data
|
||||||
@@ -262,6 +266,7 @@ static const struct sensor_ops_s g_sensor_rpmsg_ops =
|
|||||||
.activate = sensor_rpmsg_activate,
|
.activate = sensor_rpmsg_activate,
|
||||||
.set_interval = sensor_rpmsg_set_interval,
|
.set_interval = sensor_rpmsg_set_interval,
|
||||||
.batch = sensor_rpmsg_batch,
|
.batch = sensor_rpmsg_batch,
|
||||||
|
.flush = sensor_rpmsg_flush,
|
||||||
.selftest = sensor_rpmsg_selftest,
|
.selftest = sensor_rpmsg_selftest,
|
||||||
.set_calibvalue = sensor_rpmsg_set_calibvalue,
|
.set_calibvalue = sensor_rpmsg_set_calibvalue,
|
||||||
.calibrate = sensor_rpmsg_calibrate,
|
.calibrate = sensor_rpmsg_calibrate,
|
||||||
@@ -554,7 +559,7 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
|
|||||||
|
|
||||||
if (dev->lower.persist)
|
if (dev->lower.persist)
|
||||||
{
|
{
|
||||||
sensor_rpmsg_push_event_one(dev, stub);
|
sensor_rpmsg_push_event_one(dev, stub, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor_rpmsg_unlock(dev);
|
sensor_rpmsg_unlock(dev);
|
||||||
@@ -696,6 +701,25 @@ SENSOR_RPMSG_FUNCTION(set_calibvalue, SNIOC_SET_CALIBVALUE,
|
|||||||
arg, arg, 256, true)
|
arg, arg, 256, true)
|
||||||
SENSOR_RPMSG_FUNCTION(calibrate, SNIOC_CALIBRATE, arg, arg, 256, true)
|
SENSOR_RPMSG_FUNCTION(calibrate, SNIOC_CALIBRATE, arg, arg, 256, true)
|
||||||
|
|
||||||
|
static int sensor_rpmsg_flush(FAR struct sensor_lowerhalf_s *lower,
|
||||||
|
FAR struct file *filep)
|
||||||
|
{
|
||||||
|
FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
|
||||||
|
FAR struct sensor_lowerhalf_s *drv = dev->drv;
|
||||||
|
int ret = -ENOTTY;
|
||||||
|
|
||||||
|
if (drv->ops->flush)
|
||||||
|
{
|
||||||
|
ret = drv->ops->flush(drv, filep);
|
||||||
|
}
|
||||||
|
else if (!(filep->f_oflags & SENSOR_REMOTE))
|
||||||
|
{
|
||||||
|
ret = sensor_rpmsg_ioctl(dev, SNIOC_FLUSH, 0, 0, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int sensor_rpmsg_get_info(FAR struct sensor_lowerhalf_s *lower,
|
static int sensor_rpmsg_get_info(FAR struct sensor_lowerhalf_s *lower,
|
||||||
FAR struct file *filep,
|
FAR struct file *filep,
|
||||||
FAR struct sensor_device_info_s *info)
|
FAR struct sensor_device_info_s *info)
|
||||||
@@ -754,7 +778,8 @@ static void sensor_rpmsg_data_worker(FAR void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
||||||
FAR struct sensor_rpmsg_stub_s *stub)
|
FAR struct sensor_rpmsg_stub_s *stub,
|
||||||
|
bool flushed)
|
||||||
{
|
{
|
||||||
FAR struct sensor_rpmsg_cell_s *cell;
|
FAR struct sensor_rpmsg_cell_s *cell;
|
||||||
FAR struct sensor_rpmsg_ept_s *sre;
|
FAR struct sensor_rpmsg_ept_s *sre;
|
||||||
@@ -790,7 +815,7 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
|||||||
for (; ; )
|
for (; ; )
|
||||||
{
|
{
|
||||||
ret = file_ioctl(&stub->file, SNIOC_UPDATED, &updated);
|
ret = file_ioctl(&stub->file, SNIOC_UPDATED, &updated);
|
||||||
if (ret < 0 || !updated)
|
if (ret < 0 || (!updated && !flushed))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -823,11 +848,19 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
|||||||
}
|
}
|
||||||
|
|
||||||
cell = sre->buffer + sre->written;
|
cell = sre->buffer + sre->written;
|
||||||
ret = file_read(&stub->file, cell->data,
|
if (flushed)
|
||||||
sre->space - sre->written - sizeof(*cell));
|
|
||||||
if (ret <= 0)
|
|
||||||
{
|
{
|
||||||
break;
|
flushed = false;
|
||||||
|
stub->flushing = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = file_read(&stub->file, cell->data,
|
||||||
|
sre->space - sre->written - sizeof(*cell));
|
||||||
|
if (ret <= 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cell->len = ret;
|
cell->len = ret;
|
||||||
@@ -891,7 +924,8 @@ static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
|
|||||||
list_for_every_entry_safe(&dev->stublist, stub, stmp,
|
list_for_every_entry_safe(&dev->stublist, stub, stmp,
|
||||||
struct sensor_rpmsg_stub_s, node)
|
struct sensor_rpmsg_stub_s, node)
|
||||||
{
|
{
|
||||||
sensor_rpmsg_push_event_one(dev, stub);
|
sensor_rpmsg_push_event_one(dev, stub,
|
||||||
|
stub->flushing && bytes == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
sensor_rpmsg_unlock(dev);
|
sensor_rpmsg_unlock(dev);
|
||||||
@@ -1145,6 +1179,11 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
|||||||
if (stub->ept == ept)
|
if (stub->ept == ept)
|
||||||
{
|
{
|
||||||
msg->result = file_ioctl(&stub->file, msg->request, arg);
|
msg->result = file_ioctl(&stub->file, msg->request, arg);
|
||||||
|
if (msg->result >= 0 && msg->request == SNIOC_FLUSH)
|
||||||
|
{
|
||||||
|
stub->flushing = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (msg->cookie)
|
if (msg->cookie)
|
||||||
{
|
{
|
||||||
msg->command = SENSOR_RPMSG_IOCTL_ACK;
|
msg->command = SENSOR_RPMSG_IOCTL_ACK;
|
||||||
|
|||||||
@@ -451,4 +451,17 @@
|
|||||||
# define SNIOC_SET_INFO _SNIOC(0x009C)
|
# define SNIOC_SET_INFO _SNIOC(0x009C)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Command: SNIOC_FLUSH
|
||||||
|
* Description: Flush sensor harware fifo buffer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SNIOC_FLUSH _SNIOC(0x009D)
|
||||||
|
|
||||||
|
/* Command: SNIOC_GET_EVENTS
|
||||||
|
* Description: Get events of the sensor device.
|
||||||
|
* Argument: The events pointer, (unsigned int *)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SNIOC_GET_EVENTS _SNIOC(0x009E)
|
||||||
|
|
||||||
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
|
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
|
||||||
|
|||||||
@@ -352,6 +352,36 @@ struct sensor_ops_s
|
|||||||
FAR struct file *filep,
|
FAR struct file *filep,
|
||||||
FAR char *buffer, size_t buflen);
|
FAR char *buffer, size_t buflen);
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Name: flush
|
||||||
|
*
|
||||||
|
* When sensor data accumulates in the hardware buffer but does not
|
||||||
|
* reach the watermark, the upper-layer application can immediately push
|
||||||
|
* the fifo data to the upper layer circbuffer through the flush operation.
|
||||||
|
*
|
||||||
|
* The flush operation is an asynchronous operation. The lower half driver
|
||||||
|
* must call push event with data is NULL and len is zero when the flush
|
||||||
|
* action is completed, then upper half driver triggers the POLLPRI event,
|
||||||
|
* and update user state event to tell application the flush complete
|
||||||
|
* event.
|
||||||
|
*
|
||||||
|
* You can call the flush operation at any time. When the sensor is not
|
||||||
|
* activated, flsuh returns -EINVAL. When the sensor does not support fifo,
|
||||||
|
* it immediately returns the POLLPRI event, indicating that the flush
|
||||||
|
* is completed.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* lower - The instance of lower half sensor driver.
|
||||||
|
* filep - The pointer of file, represents each user using sensor.
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* Zero (OK) on success; a negated errno value on failure.
|
||||||
|
*
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
CODE int (*flush)(FAR struct sensor_lowerhalf_s *lower,
|
||||||
|
FAR struct file *filep);
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Name: selftest
|
* Name: selftest
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -321,6 +321,10 @@
|
|||||||
|
|
||||||
#define SENSOR_INFO_NAME_SIZE 32
|
#define SENSOR_INFO_NAME_SIZE 32
|
||||||
|
|
||||||
|
/* Sensor event flags */
|
||||||
|
|
||||||
|
#define SENSOR_EVENT_FLUSH_COMPLETE 0x01
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user