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:
parent
703bb7e7b3
commit
403469336f
5 changed files with 163 additions and 12 deletions
|
|
@ -87,6 +87,8 @@ struct sensor_user_s
|
|||
bool changed; /* This is used to indicate event happens and need to
|
||||
* 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 */
|
||||
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;
|
||||
|
||||
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:
|
||||
|
||||
/* 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 ret;
|
||||
|
||||
envcount = bytes / upper->state.esize;
|
||||
if (!envcount || bytes != envcount * upper->state.esize)
|
||||
nxrmutex_lock(&upper->lock);
|
||||
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;
|
||||
}
|
||||
|
||||
nxrmutex_lock(&upper->lock);
|
||||
if (!circbuf_is_init(&upper->buffer))
|
||||
{
|
||||
/* Initialize sensor buffer when data is first generated */
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ struct sensor_rpmsg_stub_s
|
|||
FAR struct rpmsg_endpoint *ept;
|
||||
uint64_t cookie;
|
||||
struct file file;
|
||||
bool flushing;
|
||||
};
|
||||
|
||||
/* 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,
|
||||
FAR struct file *filep,
|
||||
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,
|
||||
FAR struct file *filep,
|
||||
unsigned long arg);
|
||||
|
|
@ -249,7 +252,8 @@ static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
|
|||
FAR void *data, size_t len,
|
||||
uint32_t src, FAR void *priv);
|
||||
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
|
||||
|
|
@ -262,6 +266,7 @@ static const struct sensor_ops_s g_sensor_rpmsg_ops =
|
|||
.activate = sensor_rpmsg_activate,
|
||||
.set_interval = sensor_rpmsg_set_interval,
|
||||
.batch = sensor_rpmsg_batch,
|
||||
.flush = sensor_rpmsg_flush,
|
||||
.selftest = sensor_rpmsg_selftest,
|
||||
.set_calibvalue = sensor_rpmsg_set_calibvalue,
|
||||
.calibrate = sensor_rpmsg_calibrate,
|
||||
|
|
@ -554,7 +559,7 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
|
|||
|
||||
if (dev->lower.persist)
|
||||
{
|
||||
sensor_rpmsg_push_event_one(dev, stub);
|
||||
sensor_rpmsg_push_event_one(dev, stub, false);
|
||||
}
|
||||
|
||||
sensor_rpmsg_unlock(dev);
|
||||
|
|
@ -696,6 +701,25 @@ SENSOR_RPMSG_FUNCTION(set_calibvalue, SNIOC_SET_CALIBVALUE,
|
|||
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,
|
||||
FAR struct file *filep,
|
||||
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,
|
||||
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_ept_s *sre;
|
||||
|
|
@ -790,7 +815,7 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
|||
for (; ; )
|
||||
{
|
||||
ret = file_ioctl(&stub->file, SNIOC_UPDATED, &updated);
|
||||
if (ret < 0 || !updated)
|
||||
if (ret < 0 || (!updated && !flushed))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
|
@ -823,11 +848,19 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
|
|||
}
|
||||
|
||||
cell = sre->buffer + sre->written;
|
||||
ret = file_read(&stub->file, cell->data,
|
||||
sre->space - sre->written - sizeof(*cell));
|
||||
if (ret <= 0)
|
||||
if (flushed)
|
||||
{
|
||||
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;
|
||||
|
|
@ -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,
|
||||
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);
|
||||
|
|
@ -1145,6 +1179,11 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
|
|||
if (stub->ept == ept)
|
||||
{
|
||||
msg->result = file_ioctl(&stub->file, msg->request, arg);
|
||||
if (msg->result >= 0 && msg->request == SNIOC_FLUSH)
|
||||
{
|
||||
stub->flushing = true;
|
||||
}
|
||||
|
||||
if (msg->cookie)
|
||||
{
|
||||
msg->command = SENSOR_RPMSG_IOCTL_ACK;
|
||||
|
|
|
|||
|
|
@ -451,4 +451,17 @@
|
|||
# define SNIOC_SET_INFO _SNIOC(0x009C)
|
||||
#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 */
|
||||
|
|
|
|||
|
|
@ -352,6 +352,36 @@ struct sensor_ops_s
|
|||
FAR struct file *filep,
|
||||
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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -321,6 +321,10 @@
|
|||
|
||||
#define SENSOR_INFO_NAME_SIZE 32
|
||||
|
||||
/* Sensor event flags */
|
||||
|
||||
#define SENSOR_EVENT_FLUSH_COMPLETE 0x01
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue