You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/01 17:29:04 UTC
[incubator-nuttx] branch master updated (1cc7f6e63a -> 78381f9fc4)
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
from 1cc7f6e63a Add MIT license kconfig symbol
new c5f87bb5c6 driver/sensor: support access remote sensor by rpmsg
new 8de6c29aa4 driver/sensor: enable usensor and rpmsg_sensor
new 2f5727b102 driver/sensor: add _SNIOCVALID check to command
new 6f3873dfa2 sensor: add SNIOC_READLAST
new 74b2be20d0 driver/sensor: move readlast for each user
new 2a910b7ca9 driver/sensor: using re-entrant mutex for sensor access to avoid deadlock
new fa4cebce32 driver/sensor: support sensor data persist
new 67f156c2f7 driver/sensor: add cpuname info about failed case
new bf6063cc04 driver/sensor/rpmsg: fix deadlock case: push event in ioctl_ack handler
new 38393cfc94 driver/sensor: move register_driver to end to avoid race condition
new 78eb832e23 driver/sensor: using standard recursive mutex api
new 8e03f213e3 driver/sensor: convert interval 0 to ULONG_MAX
new ddd4a0d635 driver/sensor: sync batch and interval when update interval
new 01254de1bf driver/sensor: update batch initial value
new 48b4667318 driver/sensor: slove deadlock issue because ept/devlist using same lock
new 107e3e5d52 driver/sensor: export upper half lock
new fe1d83c41b driver/sensor: solve the deadlock problem caused by sensor_close
new 12e5371a05 uorb: fix, should check min_interval modified by lowerhalf.
new 5b91641a09 driver/sensor: add cmd SNIOC_UPDATED and remove readlast
new 9485174ff0 nuttx/dirvers/sensor: down-sampling 2.0
new ad20bd4bb3 driver/sensor: fix rpmsg send failed when buffer is NULL
new 78381f9fc4 driver/sensor: fix deadlock about sensor_rpmsg
The 22 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
drivers/drivers_initialize.c | 11 +-
drivers/sensors/Kconfig | 7 +
drivers/sensors/Make.defs | 4 +
drivers/sensors/sensor.c | 533 ++++++++++------
drivers/sensors/sensor_rpmsg.c | 1377 ++++++++++++++++++++++++++++++++++++++++
drivers/sensors/usensor.c | 1 +
include/nuttx/sensors/ioctl.h | 15 +
include/nuttx/sensors/sensor.h | 102 ++-
8 files changed, 1857 insertions(+), 193 deletions(-)
create mode 100644 drivers/sensors/sensor_rpmsg.c
[incubator-nuttx] 18/22: uorb: fix, should check min_interval modified by lowerhalf.
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 12e5371a05a279ffde9618af205d3c9e0dd5477f
Author: jihandong <ji...@xiaomi.com>
AuthorDate: Sat Jun 25 17:12:39 2022 +0800
uorb: fix, should check min_interval modified by lowerhalf.
Signed-off-by: jihandong <ji...@xiaomi.com>
---
drivers/sensors/sensor.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 4d61eb2c9b..99544231bf 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -250,11 +250,16 @@ static int sensor_update_interval(FAR struct file *filep,
if (min_interval != ULONG_MAX &&
min_interval != upper->state.min_interval)
{
+ unsigned long expected_interval = min_interval;
ret = lower->ops->set_interval(lower, filep, &min_interval);
if (ret < 0)
{
return ret;
}
+ else if (min_interval > expected_interval)
+ {
+ return -EINVAL;
+ }
}
if (min_latency == ULONG_MAX)
[incubator-nuttx] 13/22: driver/sensor: sync batch and interval when update interval
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit ddd4a0d63583c4b9027a1140f443e685814e33dc
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Jun 16 14:26:42 2022 +0800
driver/sensor: sync batch and interval when update interval
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index e054116a8d..fb22d1c855 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -245,6 +245,11 @@ update:
{
return ret;
}
+
+ if (upper->state.min_latency != ULONG_MAX)
+ {
+ lower->ops->batch(filep, lower, &upper->state.min_latency);
+ }
}
upper->state.min_interval = min_interval;
[incubator-nuttx] 11/22: driver/sensor: using standard recursive mutex api
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 78eb832e23109387e3eb5c45e17f414cf0ec6987
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Jun 14 11:33:13 2022 +0800
driver/sensor: using standard recursive mutex api
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 104 ++++++++++++++++-------------------------------
1 file changed, 35 insertions(+), 69 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index ac487bb39f..41717cb9bb 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -37,6 +37,7 @@
#include <nuttx/list.h>
#include <nuttx/kmalloc.h>
#include <nuttx/mm/circbuf.h>
+#include <nuttx/mutex.h>
#include <nuttx/sensors/sensor.h>
/****************************************************************************
@@ -94,9 +95,7 @@ struct sensor_upperhalf_s
FAR struct sensor_lowerhalf_s *lower; /* The handle of lower half driver */
struct sensor_state_s state; /* The state of sensor device */
struct circbuf_s buffer; /* The circular buffer of sensor device */
- sem_t exclsem; /* Manages exclusive access to file operations */
- pid_t semholder; /* The current holder of the semaphore */
- int16_t semcount; /* Number of counts held */
+ rmutex_t lock; /* Manages exclusive access to file operations */
struct list_node userlist; /* List of users */
};
@@ -178,38 +177,6 @@ static const struct file_operations g_sensor_fops =
* Private Functions
****************************************************************************/
-static void sensor_semtake(FAR struct sensor_upperhalf_s *upper)
-{
- pid_t pid = gettid();
-
- if (pid == upper->semholder)
- {
- upper->semcount++;
- }
- else
- {
- nxsem_wait_uninterruptible(&upper->exclsem);
- upper->semholder = pid;
- upper->semcount = 1;
- }
-}
-
-static void sensor_semgive(FAR struct sensor_upperhalf_s *upper)
-{
- DEBUGASSERT(upper->semholder == gettid());
-
- if (upper->semcount > 1)
- {
- upper->semcount--;
- }
- else
- {
- upper->semholder = INVALID_PROCESS_ID;
- upper->semcount = 0;
- nxsem_post(&upper->exclsem);
- }
-}
-
static bool sensor_in_range(unsigned long left, unsigned long value,
unsigned long right)
{
@@ -392,7 +359,7 @@ static int sensor_open(FAR struct file *filep)
FAR struct sensor_user_s *user;
int ret = 0;
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
user = kmm_zalloc(sizeof(struct sensor_user_s));
if (user == NULL)
{
@@ -464,7 +431,7 @@ errout_with_open:
errout_with_user:
kmm_free(user);
errout_with_sem:
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
return ret;
}
@@ -476,13 +443,13 @@ static int sensor_close(FAR struct file *filep)
FAR struct sensor_user_s *user = filep->f_priv;
int ret = 0;
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
if (lower->ops->close)
{
ret = lower->ops->close(lower, filep);
if (ret < 0)
{
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
return ret;
}
}
@@ -509,7 +476,7 @@ static int sensor_close(FAR struct file *filep)
/* The user is closed, notify to other users */
sensor_pollnotify(upper, POLLPRI);
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
kmm_free(user);
return ret;
@@ -530,19 +497,19 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
return -EINVAL;
}
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
if (lower->ops->fetch)
{
if (!(filep->f_oflags & O_NONBLOCK))
{
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
ret = nxsem_wait_uninterruptible(&user->buffersem);
if (ret < 0)
{
return ret;
}
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
}
else if (!upper->state.nsubscribers)
{
@@ -604,14 +571,14 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
}
else
{
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
ret = nxsem_wait_uninterruptible(&user->buffersem);
if (ret < 0)
{
return ret;
}
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
}
}
}
@@ -641,7 +608,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
}
out:
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
return ret;
}
@@ -669,27 +636,27 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
case SNIOC_GET_STATE:
{
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
memcpy((FAR void *)(uintptr_t)arg,
&upper->state, sizeof(upper->state));
user->changed = false;
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
break;
case SNIOC_SET_INTERVAL:
{
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
ret = sensor_update_interval(filep, upper, user, arg);
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
break;
case SNIOC_BATCH:
{
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
ret = sensor_update_latency(filep, upper, user, arg);
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
break;
@@ -731,15 +698,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case SNIOC_SET_USERPRIV:
{
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
upper->state.priv = (FAR void *)(uintptr_t)arg;
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
break;
case SNIOC_SET_BUFFER_NUMBER:
{
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
if (!circbuf_is_init(&upper->buffer))
{
if (arg >= lower->nbuffer)
@@ -756,15 +723,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
ret = -EBUSY;
}
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
break;
case SNIOC_READLAST:
{
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
user->readlast = !!arg;
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
break;
@@ -798,7 +765,7 @@ static int sensor_poll(FAR struct file *filep,
int semcount;
int ret = 0;
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
if (setup)
{
/* Don't have enough space to store fds */
@@ -850,7 +817,7 @@ static int sensor_poll(FAR struct file *filep,
}
errout:
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
return ret;
}
@@ -870,7 +837,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
return -EINVAL;
}
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
if (!circbuf_is_init(&upper->buffer))
{
/* Initialize sensor buffer when data is first generated */
@@ -879,7 +846,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
upper->state.esize);
if (ret < 0)
{
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
return ret;
}
}
@@ -900,7 +867,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
}
}
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
return bytes;
}
@@ -910,7 +877,7 @@ static void sensor_notify_event(FAR void *priv)
FAR struct sensor_user_s *user;
int semcount;
- sensor_semtake(upper);
+ nxrmutex_lock(&upper->lock);
list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node)
{
nxsem_get_value(&user->buffersem, &semcount);
@@ -922,7 +889,7 @@ static void sensor_notify_event(FAR void *priv)
sensor_pollnotify_one(user, POLLIN);
}
- sensor_semgive(upper);
+ nxrmutex_unlock(&upper->lock);
}
/****************************************************************************
@@ -1026,8 +993,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
upper->state.nadvertisers = 1;
}
- upper->semholder = INVALID_PROCESS_ID;
- nxsem_init(&upper->exclsem, 0, 1);
+ nxrmutex_init(&upper->lock);
/* Bind the lower half data structure member */
@@ -1069,7 +1035,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
return ret;
drv_err:
- nxsem_destroy(&upper->exclsem);
+ nxrmutex_destroy(&upper->lock);
kmm_free(upper);
@@ -1132,7 +1098,7 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
sensor_rpmsg_unregister(lower);
#endif
- nxsem_destroy(&upper->exclsem);
+ nxrmutex_destroy(&upper->lock);
if (circbuf_is_init(&upper->buffer))
{
circbuf_uninit(&upper->buffer);
[incubator-nuttx] 08/22: driver/sensor: add cpuname info about failed case
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 67f156c2f73b42ca2e1d657f7519409e8968c816
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed May 25 19:46:29 2022 +0800
driver/sensor: add cpuname info about failed case
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor_rpmsg.c | 34 ++++++++++++++++++++--------------
1 file changed, 20 insertions(+), 14 deletions(-)
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 58ba632c7d..0111ca38bc 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -297,8 +297,8 @@ static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
msg = rpmsg_get_tx_payload_buffer(ept, &space, true);
if (!msg)
{
- snerr("ERROR: advsub:%d get buffer failed:%s\n",
- command, dev->path);
+ snerr("ERROR: advsub:%d get buffer failed:%s, %s\n",
+ command, dev->path, rpmsg_get_cpuname(ept->rdev));
return;
}
@@ -310,8 +310,8 @@ static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
ret = rpmsg_send_nocopy(ept, msg, sizeof(*msg) + len);
if (ret < 0)
{
- snerr("ERROR: advsub:%d rpmsg send failed:%s %d\n",
- command, dev->path, ret);
+ snerr("ERROR: advsub:%d rpmsg send failed:%s, %d, %s\n",
+ command, dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
}
@@ -362,7 +362,8 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
if (!msg)
{
ret = -ENOMEM;
- snerr("ERROR: ioctl get buffer failed:%s\n", dev->path);
+ snerr("ERROR: ioctl get buffer failed:%s, %s\n",
+ dev->path, rpmsg_get_cpuname(proxy->ept->rdev));
break;
}
@@ -383,7 +384,8 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
ret = rpmsg_send_nocopy(proxy->ept, msg, sizeof(*msg) + len);
if (ret < 0)
{
- snerr("ERROR: ioctl rpmsg send failed:%s %d\n", dev->path, ret);
+ snerr("ERROR: ioctl rpmsg send failed:%s, %d, %s\n",
+ dev->path, ret, rpmsg_get_cpuname(proxy->ept->rdev));
break;
}
@@ -397,7 +399,8 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
nxmutex_lock(&dev->lock);
if (ret < 0)
{
- snerr("ERROR: ioctl rpmsg wait failed:%s %d\n", dev->path, ret);
+ snerr("ERROR: ioctl rpmsg wait failed:%s, %d, %s\n",
+ dev->path, ret, rpmsg_get_cpuname(proxy->ept->rdev));
break;
}
@@ -786,8 +789,8 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
sre->buffer = NULL;
if (ret < 0)
{
- snerr("ERROR: push event rpmsg send failed:%s %d\n",
- rpmsg_get_cpuname(sre->ept.rdev), ret);
+ snerr("ERROR: push event rpmsg send failed:%d, %s\n",
+ ret, rpmsg_get_cpuname(sre->ept.rdev));
}
}
else
@@ -882,7 +885,8 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
if (ret < 0)
{
sensor_rpmsg_free_proxy(proxy);
- snerr("ERROR: adv rpmsg send failed:%s %d\n", dev->path, ret);
+ snerr("ERROR: adv rpmsg send failed:%s, %d, %s\n",
+ dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
}
@@ -900,7 +904,8 @@ static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
if (dev && !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie))
{
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNADVERTISE);
- snerr("ERROR: advack failed:%s\n", dev->path);
+ snerr("ERROR: advack failed:%s, %s\n", dev->path,
+ rpmsg_get_cpuname(ept->rdev));
}
return 0;
@@ -965,7 +970,8 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
if (ret < 0)
{
sensor_rpmsg_free_stub(stub);
- snerr("ERROR: sub rpmsg send failed:%s %d\n", dev->path, ret);
+ snerr("ERROR: sub rpmsg send failed:%s, %d, %s\n",
+ dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
}
@@ -1067,8 +1073,8 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
ret = rpmsg_send(ept, msg, len);
if (ret < 0)
{
- snerr("ERROR: ioctl rpmsg send failed:%s %d\n",
- dev->path, ret);
+ snerr("ERROR: ioctl rpmsg send failed:%s, %d, %s\n",
+ dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
}
}
[incubator-nuttx] 17/22: driver/sensor: solve the deadlock problem caused by sensor_close
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit fe1d83c41b4ff752ad17c596998cbaa522ba0c96
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Jun 23 12:15:12 2022 +0800
driver/sensor: solve the deadlock problem caused by sensor_close
note: replace dev lock by upper driver lock
rptun:
sem_wait
sched/semaphore/sem_wait.c:273
nxmutex_lock
/home/neo/projects/monkey/nuttx/include/nuttx/mutex.h:161
sensor_close (wait upper driver lock)
drivers/sensors/sensor.c:509
sensor_rpmsg_free_stub (get dev lock)
drivers/sensors/sensor_rpmsg.c:546
sensor_rpmsg_unsub_handler
drivers/sensors/sensor_rpmsg.c:1025
rptun_thread
apps:
sem_wait
sched/semaphore/sem_wait.c:273
sensor_rpmsg_close (wait dev lock)
drivers/sensors/sensor_rpmsg.c:613
sensor_close (get upper driver lock)
drivers/sensors/sensor.c:512
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor_rpmsg.c | 77 +++++++++++++++++++++++++-----------------
1 file changed, 46 insertions(+), 31 deletions(-)
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 074da1737f..8aa9f263d2 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -82,7 +82,6 @@ struct sensor_rpmsg_dev_s
{
struct sensor_lowerhalf_s lower;
FAR struct sensor_lowerhalf_s *drv;
- rmutex_t lock;
struct list_node node;
struct list_node stublist;
struct list_node proxylist;
@@ -286,6 +285,16 @@ static mutex_t g_dev_lock = NXMUTEX_INITIALIZER;
* Private Functions
****************************************************************************/
+static void sensor_rpmsg_lock(FAR struct sensor_rpmsg_dev_s *dev)
+{
+ dev->lower.sensor_lock(dev->upper);
+}
+
+static void sensor_rpmsg_unlock(FAR struct sensor_rpmsg_dev_s *dev)
+{
+ dev->lower.sensor_unlock(dev->upper);
+}
+
static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
FAR struct rpmsg_endpoint *ept,
int command)
@@ -355,7 +364,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
* if device doesn't have proxy, it must return -ENOTTY.
*/
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->proxylist, proxy,
struct sensor_rpmsg_proxy_s, node)
{
@@ -395,9 +404,9 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
continue;
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
ret = rpmsg_wait(proxy->ept, &cookie.sem);
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
if (ret < 0)
{
snerr("ERROR: ioctl rpmsg wait failed:%s, %d, %s\n",
@@ -412,7 +421,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
}
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
if (wait)
{
nxsem_destroy(&cookie.sem);
@@ -431,15 +440,19 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
struct file file;
int ret;
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->proxylist, proxy,
struct sensor_rpmsg_proxy_s, node)
{
if (proxy->ept == ept && proxy->cookie == msg->cookie)
{
+ sensor_rpmsg_unlock(dev);
return proxy;
}
}
+ sensor_rpmsg_unlock(dev);
+
/* Create new proxy to represent a remote advertiser */
proxy = kmm_malloc(sizeof(*proxy));
@@ -461,7 +474,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
file_ioctl(&file, SNIOC_GET_STATE, &state);
file_close(&file);
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
if (msg->persist)
{
dev->drv->persist = true;
@@ -469,7 +482,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
}
list_add_tail(&dev->proxylist, &proxy->node);
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
/* sync interval and latency */
@@ -495,15 +508,19 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
FAR struct sensor_rpmsg_stub_s *stub;
int ret;
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
if (stub->ept == ept && stub->cookie == cookie)
{
+ sensor_rpmsg_unlock(dev);
return stub;
}
}
+ sensor_rpmsg_unlock(dev);
+
/* Create new stub to represent a remote subscribers */
stub = kmm_malloc(sizeof(*stub));
@@ -523,9 +540,9 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
}
file_ioctl(&stub->file, SNIOC_READLAST, false);
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_add_tail(&dev->stublist, &stub->node);
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
if (dev->lower.persist)
{
@@ -569,7 +586,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
return 0;
}
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
if (filep->f_oflags & O_WROK)
{
if (dev->nadvertisers++ == 0)
@@ -586,7 +603,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
}
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
return 0;
}
@@ -611,7 +628,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
return ret;
}
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
if (filep->f_oflags & O_WROK)
{
if (dev->nadvertisers == 1)
@@ -642,7 +659,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
dev->nsubscribers--;
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
return ret;
}
@@ -828,14 +845,14 @@ static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
* is successful, and must return length of written.
*/
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
sensor_rpmsg_push_event_one(dev, stub);
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
return ret;
}
@@ -885,9 +902,9 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
ret = rpmsg_send(ept, msg, len);
if (ret < 0)
{
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
sensor_rpmsg_free_proxy(proxy);
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
snerr("ERROR: adv rpmsg send failed:%s, %d, %s\n",
dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
@@ -928,7 +945,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
return 0;
}
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->proxylist, proxy,
struct sensor_rpmsg_proxy_s, node)
{
@@ -939,7 +956,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
}
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
return 0;
}
@@ -972,9 +989,9 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
ret = rpmsg_send(ept, msg, len);
if (ret < 0)
{
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
sensor_rpmsg_free_stub(stub);
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
snerr("ERROR: sub rpmsg send failed:%s, %d, %s\n",
dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
@@ -1015,7 +1032,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
return 0;
}
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
@@ -1026,7 +1043,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
}
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
return 0;
}
@@ -1065,7 +1082,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
arg = msg->arglen > 0 ? (unsigned long)(uintptr_t)msg->argbuf :
msg->arg;
dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)msg->proxy;
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
@@ -1087,7 +1104,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
}
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
return 0;
}
@@ -1142,7 +1159,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
list_for_every_entry(&g_devlist, dev,
struct sensor_rpmsg_dev_s, node)
{
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
list_for_every_entry(&dev->proxylist, proxy,
struct sensor_rpmsg_proxy_s, node)
{
@@ -1163,7 +1180,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
}
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
}
nxmutex_unlock(&g_dev_lock);
@@ -1194,7 +1211,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
list_for_every_entry(&g_devlist, dev,
struct sensor_rpmsg_dev_s, node)
{
- nxrmutex_lock(&dev->lock);
+ sensor_rpmsg_lock(dev);
if (dev->nadvertisers > 0)
{
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_ADVERTISE);
@@ -1205,7 +1222,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_SUBSCRIBE);
}
- nxrmutex_unlock(&dev->lock);
+ sensor_rpmsg_unlock(dev);
}
nxmutex_unlock(&g_dev_lock);
@@ -1277,7 +1294,6 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
list_initialize(&dev->stublist);
list_initialize(&dev->proxylist);
- nxrmutex_init(&dev->lock);
strcpy(dev->path, path);
dev->nadvertisers = !!lower->ops->activate;
@@ -1333,7 +1349,6 @@ void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
list_delete(&dev->node);
nxmutex_unlock(&g_dev_lock);
- nxrmutex_destroy(&dev->lock);
kmm_free(dev);
}
[incubator-nuttx] 15/22: driver/sensor: slove deadlock issue because ept/devlist using same lock
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 48b46673186b2c1261182dbe52786d617be68e43
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 22 21:37:14 2022 +0800
driver/sensor: slove deadlock issue because ept/devlist using same lock
CHAMPION-6418
rptun sensor:
[ap] [ 5] [<0x2c352c68>] arm_switchcontext+0xc/0x10
[ap] [ 5] [<0x2c322eae>] sem_wait+0x5a/0xbc
[ap] [ 5] [<0x2c3376cc>] sensor_rpmsg_find_dev+0x8/0x78 (wait g_lock)
[ap] [ 5] [<0x2c338d96>] sensor_rpmsg_suback_handler+0xa/0x4c
[ap] [ 5] [<0x2c7630f6>] rpmsg_virtio_rx_callback+0xba/0x1b4
[ap] [ 5] [<0x2c762788>] rproc_virtio_notified+0x44/0x5c
[ap] [ 5] [<0x2c762154>] remoteproc_get_notification+0x1c/0x2c
[ap] [ 5] [<0x2c335576>] rptun_thread+0x6e/0x164
[ap] [ 5] [<0x2c324aba>] nxtask_start+0x3a/0x60
apps:(note: ipc buffer is busy, it's not enough for dual core.)
[ap] [26] [<0x2c323a5e>] nxsig_timedwait+0x8a/0x184
[ap] [26] [<0x2c324344>] nxsig_nanosleep+0x34/0xa4
[ap] [26] [<0x2c324446>] nxsig_usleep+0x26/0x38
[ap] [26] [<0x2c76338e>] rpmsg_virtio_get_tx_payload_buffer+0x5e/0x100 (wait ipc buffer)
[ap] [26] [<0x2c33775a>] sensor_rpmsg_advsub_one+0x1e/0xdc (get g_lock)
[ap] [26] [<0x2c338312>] sensor_rpmsg_open+0xee/0x178
[ap] [26] [<0x2c3365bc>] sensor_open+0x50/0x234
[ap] [26] [<0x2c749cb8>] open+0xc8/0x194
[ap] [26] [<0x2c375324>] orb_subscribe_multi+0x1c/0x94
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor_rpmsg.c | 61 ++++++++++++++++++++++++++----------------
1 file changed, 38 insertions(+), 23 deletions(-)
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 8338a592a9..074da1737f 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -279,7 +279,8 @@ static const rpmsg_ept_cb g_sensor_rpmsg_handler[] =
static struct list_node g_devlist = LIST_INITIAL_VALUE(g_devlist);
static struct list_node g_eptlist = LIST_INITIAL_VALUE(g_eptlist);
-static mutex_t g_lock = MUTEX_INITIALIZER;
+static mutex_t g_ept_lock = NXMUTEX_INITIALIZER;
+static mutex_t g_dev_lock = NXMUTEX_INITIALIZER;
/****************************************************************************
* Private Functions
@@ -322,14 +323,14 @@ static void sensor_rpmsg_advsub(FAR struct sensor_rpmsg_dev_s *dev,
/* Broadcast advertise/subscribe message to all ready ept */
- nxmutex_lock(&g_lock);
+ nxmutex_lock(&g_ept_lock);
list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
node)
{
sensor_rpmsg_advsub_one(dev, &sre->ept, command);
}
- nxmutex_unlock(&g_lock);
+ nxmutex_unlock(&g_ept_lock);
}
static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
@@ -843,17 +844,17 @@ sensor_rpmsg_find_dev(FAR const char *path)
{
FAR struct sensor_rpmsg_dev_s *dev;
- nxmutex_lock(&g_lock);
+ nxmutex_lock(&g_dev_lock);
list_for_every_entry(&g_devlist, dev, struct sensor_rpmsg_dev_s, node)
{
if (strcmp(dev->path, path) == 0)
{
- nxmutex_unlock(&g_lock);
+ nxmutex_unlock(&g_dev_lock);
return dev;
}
}
- nxmutex_unlock(&g_lock);
+ nxmutex_unlock(&g_dev_lock);
return NULL;
}
@@ -884,7 +885,9 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
ret = rpmsg_send(ept, msg, len);
if (ret < 0)
{
+ nxrmutex_lock(&dev->lock);
sensor_rpmsg_free_proxy(proxy);
+ nxrmutex_unlock(&dev->lock);
snerr("ERROR: adv rpmsg send failed:%s, %d, %s\n",
dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
@@ -969,7 +972,9 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
ret = rpmsg_send(ept, msg, len);
if (ret < 0)
{
+ nxrmutex_lock(&dev->lock);
sensor_rpmsg_free_stub(stub);
+ nxrmutex_unlock(&dev->lock);
snerr("ERROR: sub rpmsg send failed:%s, %d, %s\n",
dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
@@ -1077,6 +1082,8 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
dev->path, ret, rpmsg_get_cpuname(ept->rdev));
}
}
+
+ break;
}
}
@@ -1123,9 +1130,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
FAR struct sensor_rpmsg_ept_s *sre;
FAR struct sensor_rpmsg_dev_s *dev;
FAR struct sensor_rpmsg_stub_s *stub;
- FAR struct sensor_rpmsg_stub_s *stmp;
FAR struct sensor_rpmsg_proxy_s *proxy;
- FAR struct sensor_rpmsg_proxy_s *ptmp;
sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
@@ -1133,37 +1138,43 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
* destoryed.
*/
- nxmutex_lock(&g_lock);
+ nxmutex_lock(&g_dev_lock);
list_for_every_entry(&g_devlist, dev,
struct sensor_rpmsg_dev_s, node)
{
nxrmutex_lock(&dev->lock);
- list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
- struct sensor_rpmsg_proxy_s, node)
+ list_for_every_entry(&dev->proxylist, proxy,
+ struct sensor_rpmsg_proxy_s, node)
{
if (proxy->ept == ept)
{
sensor_rpmsg_free_proxy(proxy);
+ break;
}
}
- list_for_every_entry_safe(&dev->stublist, stub, stmp,
- struct sensor_rpmsg_stub_s, node)
+ list_for_every_entry(&dev->stublist, stub,
+ struct sensor_rpmsg_stub_s, node)
{
if (stub->ept == ept)
{
sensor_rpmsg_free_stub(stub);
+ break;
}
}
nxrmutex_unlock(&dev->lock);
}
+ nxmutex_unlock(&g_dev_lock);
+
+ nxmutex_lock(&g_ept_lock);
list_delete(&sre->node);
- nxmutex_unlock(&g_lock);
- rpmsg_destroy_ept(ept);
+ nxmutex_unlock(&g_ept_lock);
+
nxmutex_destroy(&sre->lock);
kmm_free(sre);
+ rpmsg_destroy_ept(ept);
}
static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
@@ -1173,11 +1184,13 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
- nxmutex_lock(&g_lock);
+ nxmutex_lock(&g_ept_lock);
list_add_tail(&g_eptlist, &sre->node);
+ nxmutex_unlock(&g_ept_lock);
/* Broadcast all device to ready ept */
+ nxmutex_lock(&g_dev_lock);
list_for_every_entry(&g_devlist, dev,
struct sensor_rpmsg_dev_s, node)
{
@@ -1195,7 +1208,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
nxrmutex_unlock(&dev->lock);
}
- nxmutex_unlock(&g_lock);
+ nxmutex_unlock(&g_dev_lock);
}
static void sensor_rpmsg_device_created(FAR struct rpmsg_device *rdev,
@@ -1267,6 +1280,7 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
nxrmutex_init(&dev->lock);
strcpy(dev->path, path);
+ dev->nadvertisers = !!lower->ops->activate;
dev->push_event = lower->push_event;
dev->upper = lower->priv;
lower->push_event = sensor_rpmsg_push_event;
@@ -1277,19 +1291,20 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
/* If openamp is ready, send advertisement to remote proc */
- nxmutex_lock(&g_lock);
+ nxmutex_lock(&g_dev_lock);
list_add_tail(&g_devlist, &dev->node);
+ nxmutex_unlock(&g_dev_lock);
if (lower->ops->activate)
{
- dev->nadvertisers = 1;
+ nxmutex_lock(&g_ept_lock);
list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
node)
{
sensor_rpmsg_advsub_one(dev, &sre->ept, SENSOR_RPMSG_ADVERTISE);
}
- }
- nxmutex_unlock(&g_lock);
+ nxmutex_unlock(&g_ept_lock);
+ }
return &dev->lower;
}
@@ -1314,9 +1329,9 @@ void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
return;
}
- nxmutex_lock(&g_lock);
+ nxmutex_lock(&g_dev_lock);
list_delete(&dev->node);
- nxmutex_unlock(&g_lock);
+ nxmutex_unlock(&g_dev_lock);
nxrmutex_destroy(&dev->lock);
kmm_free(dev);
[incubator-nuttx] 04/22: sensor: add SNIOC_READLAST
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 6f3873dfa2f47b241c79e0500bc55c1a31a96fa4
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Apr 26 14:01:11 2022 +0800
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 <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 73 ++++++++++++++++++++++++++-----------------
include/nuttx/sensors/ioctl.h | 9 ++++++
2 files changed, 54 insertions(+), 28 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 29add29309..a1ce148cf3 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -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
+
+ if (user->generation == upper->state.generation)
{
- nxsem_post(&upper->exclsem);
- ret = nxsem_wait_uninterruptible(&user->buffersem);
- if (ret < 0)
+ 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)
{
- return ret;
+ ret = -EAGAIN;
+ goto out;
}
-
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
+ else
{
- return ret;
+ nxmutex_unlock(&upper->lock);
+ ret = nxsem_wait_uninterruptible(&user->buffersem);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ nxmutex_lock(&upper->lock);
}
}
}
- /* 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
* 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;
diff --git a/include/nuttx/sensors/ioctl.h b/include/nuttx/sensors/ioctl.h
index 7cee985204..1e415a98cc 100644
--- a/include/nuttx/sensors/ioctl.h
+++ b/include/nuttx/sensors/ioctl.h
@@ -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 */
[incubator-nuttx] 05/22: driver/sensor: move readlast for each user
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 74b2be20d061d520ff2073d3002b2ad7936a060a
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue May 10 22:15:54 2022 +0800
driver/sensor: move readlast for each user
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index a1ce148cf3..1bcb977393 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -84,6 +84,7 @@ struct sensor_user_s
unsigned long generation; /* Last generation subscriber has seen */
unsigned long interval; /* The interval for subscriber */
unsigned long latency; /* The bactch latency for subscriber */
+ bool readlast; /* The flag of readlast */
};
/* This structure describes the state of the upper half driver */
@@ -95,7 +96,6 @@ 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 */
};
/****************************************************************************
@@ -402,6 +402,7 @@ static int sensor_open(FAR struct file *filep)
user->interval = ULONG_MAX;
user->latency = ULONG_MAX;
user->generation = upper->state.generation;
+ user->readlast = true;
nxsem_init(&user->buffersem, 0, 0);
nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
list_add_tail(&upper->userlist, &user->node);
@@ -532,7 +533,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
* it will return 0 when there isn't new data.
*/
- if (upper->readlast)
+ if (user->readlast)
{
if (circbuf_is_empty(&upper->buffer))
{
@@ -716,7 +717,9 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case SNIOC_READLAST:
{
- upper->readlast = !!arg;
+ sensor_semtake(upper);
+ user->readlast = !!arg;
+ sensor_semgive(upper);
}
break;
@@ -985,7 +988,6 @@ 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;
[incubator-nuttx] 20/22: nuttx/dirvers/sensor: down-sampling 2.0
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 9485174ff08edd2d57bed2209e8306ac57d71a5a
Author: jihandong <ji...@xiaomi.com>
AuthorDate: Wed May 11 13:49:39 2022 +0800
nuttx/dirvers/sensor: down-sampling 2.0
1. about interval:
If interval is not set, generation is increased by 1 along with
publish and copy, multi-copy is continuous.
If interval is set, pick proper samples from buffer based on
mainline/user generation, multi-copy is one-by-one.
2. about bufferpos:
user->bufferpos always point to next position to check.
data user last read
----------v--------------------------
| | | |
-------------------^-----------------
bufferpos
If buffer is full, bufferpos point to buffer.head
Examples:
If a buffer contains 4 samples, newest generatoin is 40.
-------------------------------------
|10 |20 |30 |40
------------------------------^------
|
if user's next generation is 42, notify user to copy No.40 sample,
because 42 is closer to 40 than 50.
-------------------------------------
|10 |20 |30 |40
----------------------------------^--
|
if user's next generation is 48, do not notify user,
because 48 is closer to 50, which is next mainline sample.
Signed-off-by: jihandong <ji...@xiaomi.com>
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 268 +++++++++++++++++++++++++++++++++--------------
1 file changed, 192 insertions(+), 76 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 50e9d33cc8..cd8b06eccc 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -46,9 +46,10 @@
/* Device naming ************************************************************/
-#define ROUNDUP(x, esize) ((x + (esize - 1)) / (esize)) * (esize)
-#define DEVNAME_FMT "/dev/sensor/sensor_%s%s%d"
-#define DEVNAME_UNCAL "_uncal"
+#define ROUND_DOWN(x, y) (((x) / (y)) * (y))
+#define DEVNAME_FMT "/dev/sensor/sensor_%s%s%d"
+#define DEVNAME_UNCAL "_uncal"
+#define TIMING_BUF_ESIZE (sizeof(unsigned long))
/****************************************************************************
* Private Types
@@ -76,6 +77,7 @@ struct sensor_user_s
* asynchronous notify other users
*/
sem_t buffersem; /* Wakeup user waiting for data in circular buffer */
+ size_t bufferpos; /* The index of user generation in buffer */
/* The subscriber info
* Support multi advertisers to subscribe their own data when they
@@ -93,7 +95,8 @@ struct sensor_upperhalf_s
{
FAR struct sensor_lowerhalf_s *lower; /* The handle of lower half driver */
struct sensor_state_s state; /* The state of sensor device */
- struct circbuf_s buffer; /* The circular buffer of sensor device */
+ struct circbuf_s timing; /* The circular buffer of generation */
+ struct circbuf_s buffer; /* The circular buffer of data */
rmutex_t lock; /* Manages exclusive access to file operations */
struct list_node userlist; /* List of users */
};
@@ -188,27 +191,6 @@ static void sensor_unlock(FAR void *priv)
nxrmutex_unlock(&upper->lock);
}
-static bool sensor_in_range(unsigned long left, unsigned long value,
- unsigned long right)
-{
- if (left < right)
- {
- return left <= value && value < right;
- }
- else
- {
- /* Maybe the data overflowed and a wraparound occurred */
-
- return left <= value || value < right;
- }
-}
-
-static bool sensor_is_updated(unsigned long generation,
- unsigned long ugeneration)
-{
- return generation > ugeneration;
-}
-
static int sensor_update_interval(FAR struct file *filep,
FAR struct sensor_upperhalf_s *upper,
FAR struct sensor_user_s *user,
@@ -350,6 +332,159 @@ update:
return ret;
}
+static void sensor_generate_timing(FAR struct sensor_upperhalf_s *upper,
+ unsigned long nums)
+{
+ unsigned long interval = upper->state.min_interval != ULONG_MAX ?
+ upper->state.min_interval : 1;
+ while (nums-- > 0)
+ {
+ upper->state.generation += interval;
+ circbuf_overwrite(&upper->timing, &upper->state.generation,
+ TIMING_BUF_ESIZE);
+ }
+}
+
+static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper,
+ FAR struct sensor_user_s *user)
+{
+ long delta = upper->state.generation - user->generation;
+
+ if (delta <= 0)
+ {
+ return false;
+ }
+ else if (user->interval == ULONG_MAX)
+ {
+ return true;
+ }
+ else
+ {
+ /* Check whether next generation user want in buffer.
+ * generation next generation(not published yet)
+ * ____v_____________v
+ * ////|//////^ |
+ * ^ middle point
+ * next generation user want
+ */
+
+ return delta >= user->interval - (upper->state.min_interval >> 1);
+ }
+}
+
+static void sensor_catch_up(FAR struct sensor_upperhalf_s *upper,
+ FAR struct sensor_user_s *user)
+{
+ unsigned long generation;
+ long delta;
+
+ circbuf_peek(&upper->timing, &generation, TIMING_BUF_ESIZE);
+ delta = generation - user->generation;
+ if (delta > 0)
+ {
+ user->bufferpos = upper->timing.tail / TIMING_BUF_ESIZE;
+ if (user->interval == ULONG_MAX)
+ {
+ user->generation = generation - 1;
+ }
+ else
+ {
+ delta -= upper->state.min_interval >> 1;
+ user->generation += ROUND_DOWN(delta, user->interval);
+ }
+ }
+}
+
+static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
+ FAR struct sensor_user_s *user,
+ FAR char *buffer, size_t len)
+{
+ unsigned long generation;
+ ssize_t ret = 0;
+ size_t nums;
+ size_t pos;
+ size_t end;
+
+ sensor_catch_up(upper, user);
+ nums = upper->timing.head / TIMING_BUF_ESIZE - user->bufferpos;
+ if (len < nums * upper->state.esize)
+ {
+ nums = len / upper->state.esize;
+ }
+
+ len = nums * upper->state.esize;
+
+ /* Take samples continuously */
+
+ if (user->interval == ULONG_MAX)
+ {
+ ret = circbuf_peekat(&upper->buffer,
+ user->bufferpos * upper->state.esize,
+ buffer, len);
+ user->bufferpos += nums;
+ circbuf_peekat(&upper->timing,
+ (user->bufferpos - 1) * TIMING_BUF_ESIZE,
+ &user->generation, TIMING_BUF_ESIZE);
+ return ret;
+ }
+
+ /* Take samples one-bye-one, to determine whether a sample needed:
+ *
+ * If user's next generation is on the left side of middle point,
+ * we should copy this sample for user.
+ * next_generation(or end)
+ * ________________v____
+ * timing buffer: //|//////. |
+ * ^ middle
+ * generation
+ * next sample(or end)
+ * ________________v____
+ * data buffer: | |
+ * ^
+ * sample
+ */
+
+ pos = user->bufferpos;
+ end = upper->timing.head / TIMING_BUF_ESIZE;
+ circbuf_peekat(&upper->timing, pos * TIMING_BUF_ESIZE,
+ &generation, TIMING_BUF_ESIZE);
+ while (pos++ != end)
+ {
+ unsigned long next_generation;
+ long delta;
+
+ if (pos * TIMING_BUF_ESIZE == upper->timing.head)
+ {
+ next_generation = upper->state.generation +
+ upper->state.min_interval;
+ }
+ else
+ {
+ circbuf_peekat(&upper->timing, pos * TIMING_BUF_ESIZE,
+ &next_generation, TIMING_BUF_ESIZE);
+ }
+
+ delta = next_generation + generation -
+ ((user->generation + user->interval) << 1);
+ if (delta >= 0)
+ {
+ ret += circbuf_peekat(&upper->buffer,
+ (pos - 1) * upper->state.esize,
+ buffer + ret, upper->state.esize);
+ user->bufferpos = pos;
+ user->generation += user->interval;
+ if (ret >= len)
+ {
+ break;
+ }
+ }
+
+ generation = next_generation;
+ }
+
+ return ret;
+}
+
static void sensor_pollnotify_one(FAR struct sensor_user_s *user,
pollevent_t eventset)
{
@@ -439,10 +574,12 @@ static int sensor_open(FAR struct file *filep)
if (upper->state.generation && lower->persist)
{
user->generation = upper->state.generation - 1;
+ user->bufferpos = upper->timing.head / TIMING_BUF_ESIZE - 1;
}
else
{
user->generation = upper->state.generation;
+ user->bufferpos = upper->timing.head / TIMING_BUF_ESIZE;
}
user->interval = ULONG_MAX;
@@ -524,7 +661,6 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
FAR struct sensor_upperhalf_s *upper = inode->i_private;
FAR struct sensor_lowerhalf_s *lower = upper->lower;
FAR struct sensor_user_s *user = filep->f_priv;
- unsigned long nums;
ssize_t ret;
if (!buffer || !len)
@@ -554,54 +690,25 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
ret = lower->ops->fetch(lower, filep, buffer, len);
}
- else
+ else if (circbuf_is_empty(&upper->buffer))
{
- if (circbuf_is_empty(&upper->buffer))
- {
- ret = -ENODATA;
- goto out;
- }
-
- /* If the device data is persistent, and when the device has
- * no new data, the user can copy the old data, otherwise
- * return -ENODATA.
- */
-
- if (user->generation == upper->state.generation)
- {
- if (lower->persist)
- {
- user->generation--;
- }
- else
- {
- ret = -ENODATA;
- goto out;
- }
- }
-
- /* If user's generation isn't within circbuffer range, the
- * oldest data in circbuffer are returned to the users.
- */
-
- if (!sensor_in_range(upper->state.generation - lower->nbuffer,
- user->generation, upper->state.generation))
-
- {
- user->generation = upper->state.generation - lower->nbuffer;
- }
-
- nums = upper->state.generation - user->generation;
- if (len < nums * upper->state.esize)
- {
- nums = len / upper->state.esize;
- }
+ ret = -ENODATA;
+ }
+ else if (sensor_is_updated(upper, user))
+ {
+ ret = sensor_do_samples(upper, user, buffer, len);
+ }
+ else if (lower->persist)
+ {
+ /* Persistent device can get latest old data if not updated. */
- len = nums * upper->state.esize;
ret = circbuf_peekat(&upper->buffer,
- user->generation * upper->state.esize,
- buffer, len);
- user->generation += nums;
+ (user->bufferpos - 1) * upper->state.esize,
+ buffer, upper->state.esize);
+ }
+ else
+ {
+ ret = -ENODATA;
}
out:
@@ -728,8 +835,7 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case SNIOC_UPDATED:
{
nxrmutex_lock(&upper->lock);
- *(FAR bool *)(uintptr_t)arg =
- sensor_is_updated(upper->state.generation, user->generation);
+ *(FAR bool *)(uintptr_t)arg = sensor_is_updated(upper, user);
nxrmutex_unlock(&upper->lock);
}
break;
@@ -794,7 +900,7 @@ static int sensor_poll(FAR struct file *filep,
}
}
}
- else if (sensor_is_updated(upper->state.generation, user->generation))
+ else if (sensor_is_updated(upper, user))
{
eventset |= (fds->events & POLLIN);
}
@@ -848,13 +954,22 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
nxrmutex_unlock(&upper->lock);
return ret;
}
+
+ ret = circbuf_init(&upper->timing, NULL, lower->nbuffer *
+ TIMING_BUF_ESIZE);
+ if (ret < 0)
+ {
+ circbuf_uninit(&upper->buffer);
+ nxrmutex_unlock(&upper->lock);
+ return ret;
+ }
}
circbuf_overwrite(&upper->buffer, data, bytes);
- upper->state.generation += envcount;
+ sensor_generate_timing(upper, envcount);
list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node)
{
- if (sensor_is_updated(upper->state.generation, user->generation))
+ if (sensor_is_updated(upper, user))
{
nxsem_get_value(&user->buffersem, &semcount);
if (semcount < 1)
@@ -1102,6 +1217,7 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
if (circbuf_is_init(&upper->buffer))
{
circbuf_uninit(&upper->buffer);
+ circbuf_uninit(&upper->timing);
}
kmm_free(upper);
[incubator-nuttx] 22/22: driver/sensor: fix deadlock about sensor_rpmsg
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 78381f9fc439f2d9d84ed738a3405ed269fda0be
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Mon Jul 4 11:08:30 2022 +0800
driver/sensor: fix deadlock about sensor_rpmsg
task1:
nuttx/arch/arm/src/common/arm_blocktask.c:151
nxsem_wait
nuttx/arch/arm/src/../../../sched/semaphore/sem_wait.c:155 (discriminator 2)
sem_wait
nuttx/arch/arm/src/../../../sched/semaphore/sem_wait.c:273
nxmutex_lock.lto_priv.2
nuttx/include/nuttx/mutex.h:161
sensor_rpmsg_push_event_one
nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:748
up_unblock_task
nuttx/arch/arm/src/common/arm_unblocktask.c:75 (discriminator 2)
sensor_rpmsg_push_event
nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:858
write
orb_publish_multi
nuttx/arch/arm/src/../../../../apps/system/uorb/uORB/uORB.c:188
task2:
nxrmutex_lock.isra.0
sensor_read
nuttx/arch/arm/src/../../../drivers/sensors/sensor.c:753
sem_post
nuttx/arch/arm/src/../../../sched/semaphore/sem_post.c:224
nxmutex_unlock.lto_priv.1
nuttx/include/nuttx/mutex.h:259
sensor_rpmsg_push_event_one
nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:787
nxmutex_unlock.lto_priv.1
nuttx/include/nuttx/mutex.h:259
nuttx/arch/arm/src/../../../drivers/sensors/sensor.c:969
sensor_rpmsg_alloc_stub
nuttx/arch/arm/src/../../../drivers/sensors/sensor_rpmsg.c:549
sensor_rpmsg_advack_handler
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor_rpmsg.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 0243119f3a..37351fd23d 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -541,13 +541,14 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
sensor_rpmsg_lock(dev);
list_add_tail(&dev->stublist, &stub->node);
- sensor_rpmsg_unlock(dev);
if (dev->lower.persist)
{
sensor_rpmsg_push_event_one(dev, stub);
}
+ sensor_rpmsg_unlock(dev);
+
return stub;
}
[incubator-nuttx] 19/22: driver/sensor: add cmd SNIOC_UPDATED and remove readlast
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 5b91641a09374e7bf798b11c8903067bf0fb0f37
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Jun 28 15:50:37 2022 +0800
driver/sensor: add cmd SNIOC_UPDATED and remove readlast
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 75 ++++++++++--------------------------------
drivers/sensors/sensor_rpmsg.c | 8 ++++-
include/nuttx/sensors/ioctl.h | 11 +++----
3 files changed, 30 insertions(+), 64 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 99544231bf..50e9d33cc8 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -85,7 +85,6 @@ struct sensor_user_s
unsigned long generation; /* Last generation subscriber has seen */
unsigned long interval; /* The interval for subscriber */
unsigned long latency; /* The bactch latency for subscriber */
- bool readlast; /* The flag of readlast */
};
/* This structure describes the state of the upper half driver */
@@ -447,7 +446,6 @@ static int sensor_open(FAR struct file *filep)
}
user->interval = ULONG_MAX;
- user->readlast = true;
nxsem_init(&user->buffersem, 0, 0);
nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
list_add_tail(&upper->userlist, &user->node);
@@ -558,65 +556,27 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
}
else
{
- /* 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.
+ if (circbuf_is_empty(&upper->buffer))
+ {
+ ret = -ENODATA;
+ goto out;
+ }
+
+ /* If the device data is persistent, and when the device has
+ * no new data, the user can copy the old data, otherwise
+ * return -ENODATA.
*/
- if (user->readlast)
+ if (user->generation == upper->state.generation)
{
- if (circbuf_is_empty(&upper->buffer))
+ if (lower->persist)
{
- ret = -ENODATA;
- goto out;
+ user->generation--;
}
-
- /* If the device data is persistent, and when the device has no
- * new data, the user can copy the old data, otherwise return
- * -ENODATA.
- */
-
- if (user->generation == upper->state.generation)
- {
- if (lower->persist)
- {
- user->generation--;
- }
- else
- {
- ret = -ENODATA;
- goto out;
- }
- }
- }
- 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)
+ else
{
- if (filep->f_oflags & O_NONBLOCK)
- {
- ret = -EAGAIN;
- goto out;
- }
- else
- {
- nxrmutex_unlock(&upper->lock);
- ret = nxsem_wait_uninterruptible(&user->buffersem);
- if (ret < 0)
- {
- return ret;
- }
-
- nxrmutex_lock(&upper->lock);
- }
+ ret = -ENODATA;
+ goto out;
}
}
@@ -765,10 +725,11 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
- case SNIOC_READLAST:
+ case SNIOC_UPDATED:
{
nxrmutex_lock(&upper->lock);
- user->readlast = !!arg;
+ *(FAR bool *)(uintptr_t)arg =
+ sensor_is_updated(upper->state.generation, user->generation);
nxrmutex_unlock(&upper->lock);
}
break;
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 8aa9f263d2..2b608d3f3e 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -539,7 +539,6 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
return NULL;
}
- file_ioctl(&stub->file, SNIOC_READLAST, false);
sensor_rpmsg_lock(dev);
list_add_tail(&dev->stublist, &stub->node);
sensor_rpmsg_unlock(dev);
@@ -729,6 +728,7 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
FAR struct sensor_rpmsg_data_s *msg;
struct sensor_state_s state;
uint64_t now;
+ bool updated;
int ret;
/* Get state of device to do send data with timeout */
@@ -756,6 +756,12 @@ 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)
+ {
+ break;
+ }
+
/* If buffer isn't created or it doesn't have enough space to fill
* new data, you should create or send this buffer at once.
*/
diff --git a/include/nuttx/sensors/ioctl.h b/include/nuttx/sensors/ioctl.h
index 1e415a98cc..992367cc14 100644
--- a/include/nuttx/sensors/ioctl.h
+++ b/include/nuttx/sensors/ioctl.h
@@ -326,13 +326,12 @@
#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
+/* Command: SNIOC_UPDATED
+ * Description: Check whether the topic has been updated since
+ * it was last read.
+ * Argument: Sets *(bool *)arg
*/
-#define SNIOC_READLAST _SNIOC(0x0091)
+#define SNIOC_UPDATED _SNIOC(0x0091)
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
[incubator-nuttx] 10/22: driver/sensor: move register_driver to end to avoid race condition
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 38393cfc940d3032325c6dc6de60b870fc0ea0ac
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Tue Jun 14 11:44:24 2022 +0800
driver/sensor: move register_driver to end to avoid race condition
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 89b47813ba..ac487bb39f 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -1048,14 +1048,6 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
lower->nbuffer = 0;
}
- upper->state.nbuffer = lower->nbuffer;
- sninfo("Registering %s\n", path);
- ret = register_driver(path, &g_sensor_fops, 0666, upper);
- if (ret)
- {
- goto drv_err;
- }
-
#ifdef CONFIG_SENSORS_RPMSG
lower = sensor_rpmsg_register(lower, path);
if (lower == NULL)
@@ -1065,7 +1057,15 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
}
#endif
+ upper->state.nbuffer = lower->nbuffer;
upper->lower = lower;
+ sninfo("Registering %s\n", path);
+ ret = register_driver(path, &g_sensor_fops, 0666, upper);
+ if (ret)
+ {
+ goto drv_err;
+ }
+
return ret;
drv_err:
[incubator-nuttx] 02/22: driver/sensor: enable usensor and rpmsg_sensor
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 8de6c29aa4be51f4902c0c2eea64b9534f0f2c4e
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Apr 14 12:21:45 2022 +0800
driver/sensor: enable usensor and rpmsg_sensor
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/drivers_initialize.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/drivers_initialize.c b/drivers/drivers_initialize.c
index bb62e23f88..7ba9363479 100644
--- a/drivers/drivers_initialize.c
+++ b/drivers/drivers_initialize.c
@@ -31,9 +31,10 @@
#include <nuttx/net/telnet.h>
#include <nuttx/note/note_driver.h>
#include <nuttx/power/pm.h>
+#include <nuttx/sensors/sensor.h>
+#include <nuttx/serial/pty.h>
#include <nuttx/syslog/syslog.h>
#include <nuttx/syslog/syslog_console.h>
-#include <nuttx/serial/pty.h>
/****************************************************************************
* Public Functions
@@ -143,4 +144,12 @@ void drivers_initialize(void)
telnet_initialize();
#endif
+
+#ifdef CONFIG_USENSOR
+ usensor_initialize();
+#endif
+
+#ifdef CONFIG_SENSORS_RPMSG
+ sensor_rpmsg_initialize();
+#endif
}
[incubator-nuttx] 16/22: driver/sensor: export upper half lock
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 107e3e5d5276bce6f0f24e2af19dd266fd177616
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Thu Jun 23 12:13:56 2022 +0800
driver/sensor: export upper half lock
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 16 +++++++++++++++-
include/nuttx/sensors/sensor.h | 13 +++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 45b67b011a..4d61eb2c9b 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -177,6 +177,18 @@ static const struct file_operations g_sensor_fops =
* Private Functions
****************************************************************************/
+static void sensor_lock(FAR void *priv)
+{
+ FAR struct sensor_upperhalf_s *upper = priv;
+ nxrmutex_lock(&upper->lock);
+}
+
+static void sensor_unlock(FAR void *priv)
+{
+ FAR struct sensor_upperhalf_s *upper = priv;
+ nxrmutex_unlock(&upper->lock);
+}
+
static bool sensor_in_range(unsigned long left, unsigned long value,
unsigned long right)
{
@@ -1017,7 +1029,9 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
/* Bind the lower half data structure member */
- lower->priv = upper;
+ lower->priv = upper;
+ lower->sensor_lock = sensor_lock;
+ lower->sensor_unlock = sensor_unlock;
if (!lower->ops->fetch)
{
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index 35172a6080..8af4eca43f 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -937,6 +937,19 @@ struct sensor_lowerhalf_s
sensor_notify_event_t notify_event;
};
+/****************************************************************************
+ * Name: sensor_lock/sensor_unlock
+ *
+ * Description:
+ * Lower half driver can lock/unlock upper half driver by this interface.
+ *
+ * Input Parameters:
+ * priv - Upper half driver handle
+ ****************************************************************************/
+
+ void (*sensor_lock)(void * priv);
+ void (*sensor_unlock)(void * priv);
+
/* The private opaque pointer to be passed to upper-layer during callback */
FAR void *priv;
[incubator-nuttx] 09/22: driver/sensor/rpmsg: fix deadlock case: push event in ioctl_ack handler
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit bf6063cc046be6287ed7803000c889abef60cd11
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Jun 10 22:46:04 2022 +0800
driver/sensor/rpmsg: fix deadlock case: push event in ioctl_ack handler
using recursive mutex to fix this issue.
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor_rpmsg.c | 54 +++++++++++++++++++++---------------------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 0111ca38bc..8338a592a9 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -82,7 +82,7 @@ struct sensor_rpmsg_dev_s
{
struct sensor_lowerhalf_s lower;
FAR struct sensor_lowerhalf_s *drv;
- mutex_t lock;
+ rmutex_t lock;
struct list_node node;
struct list_node stublist;
struct list_node proxylist;
@@ -354,7 +354,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
* if device doesn't have proxy, it must return -ENOTTY.
*/
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_for_every_entry(&dev->proxylist, proxy,
struct sensor_rpmsg_proxy_s, node)
{
@@ -394,9 +394,9 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
continue;
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
ret = rpmsg_wait(proxy->ept, &cookie.sem);
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
if (ret < 0)
{
snerr("ERROR: ioctl rpmsg wait failed:%s, %d, %s\n",
@@ -411,7 +411,7 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
}
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
if (wait)
{
nxsem_destroy(&cookie.sem);
@@ -460,7 +460,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
file_ioctl(&file, SNIOC_GET_STATE, &state);
file_close(&file);
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
if (msg->persist)
{
dev->drv->persist = true;
@@ -468,7 +468,7 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
}
list_add_tail(&dev->proxylist, &proxy->node);
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
/* sync interval and latency */
@@ -522,9 +522,9 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
}
file_ioctl(&stub->file, SNIOC_READLAST, false);
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_add_tail(&dev->stublist, &stub->node);
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
if (dev->lower.persist)
{
@@ -568,7 +568,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
return 0;
}
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
if (filep->f_oflags & O_WROK)
{
if (dev->nadvertisers++ == 0)
@@ -585,7 +585,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
}
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
return 0;
}
@@ -610,7 +610,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
return ret;
}
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
if (filep->f_oflags & O_WROK)
{
if (dev->nadvertisers == 1)
@@ -641,7 +641,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
dev->nsubscribers--;
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
return ret;
}
@@ -827,14 +827,14 @@ static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
* is successful, and must return length of written.
*/
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
sensor_rpmsg_push_event_one(dev, stub);
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
return ret;
}
@@ -925,7 +925,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
return 0;
}
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_for_every_entry(&dev->proxylist, proxy,
struct sensor_rpmsg_proxy_s, node)
{
@@ -936,7 +936,7 @@ static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
}
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
return 0;
}
@@ -1010,7 +1010,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
return 0;
}
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
@@ -1021,7 +1021,7 @@ static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
}
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
return 0;
}
@@ -1060,7 +1060,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
arg = msg->arglen > 0 ? (unsigned long)(uintptr_t)msg->argbuf :
msg->arg;
dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)msg->proxy;
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_for_every_entry(&dev->stublist, stub,
struct sensor_rpmsg_stub_s, node)
{
@@ -1080,7 +1080,7 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
}
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
return 0;
}
@@ -1137,7 +1137,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
list_for_every_entry(&g_devlist, dev,
struct sensor_rpmsg_dev_s, node)
{
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
struct sensor_rpmsg_proxy_s, node)
{
@@ -1156,7 +1156,7 @@ static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
}
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
}
list_delete(&sre->node);
@@ -1181,7 +1181,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
list_for_every_entry(&g_devlist, dev,
struct sensor_rpmsg_dev_s, node)
{
- nxmutex_lock(&dev->lock);
+ nxrmutex_lock(&dev->lock);
if (dev->nadvertisers > 0)
{
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_ADVERTISE);
@@ -1192,7 +1192,7 @@ static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_SUBSCRIBE);
}
- nxmutex_unlock(&dev->lock);
+ nxrmutex_unlock(&dev->lock);
}
nxmutex_unlock(&g_lock);
@@ -1264,7 +1264,7 @@ sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
list_initialize(&dev->stublist);
list_initialize(&dev->proxylist);
- nxmutex_init(&dev->lock);
+ nxrmutex_init(&dev->lock);
strcpy(dev->path, path);
dev->push_event = lower->push_event;
@@ -1318,7 +1318,7 @@ void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
list_delete(&dev->node);
nxmutex_unlock(&g_lock);
- nxmutex_destroy(&dev->lock);
+ nxrmutex_destroy(&dev->lock);
kmm_free(dev);
}
[incubator-nuttx] 12/22: driver/sensor: convert interval 0 to ULONG_MAX
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 8e03f213e330d50f14309f706f0932eb96fe5d7f
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 15 21:26:09 2022 +0800
driver/sensor: convert interval 0 to ULONG_MAX
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 41717cb9bb..e054116a8d 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -647,7 +647,8 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case SNIOC_SET_INTERVAL:
{
nxrmutex_lock(&upper->lock);
- ret = sensor_update_interval(filep, upper, user, arg);
+ ret = sensor_update_interval(filep, upper, user,
+ arg ? arg : ULONG_MAX);
nxrmutex_unlock(&upper->lock);
}
break;
[incubator-nuttx] 03/22: driver/sensor: add _SNIOCVALID check to command
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 2f5727b1021dfe969feb689ee58f6e9b1c232f4e
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Mon May 23 14:50:14 2022 +0800
driver/sensor: add _SNIOCVALID check to command
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor_rpmsg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index e69e2fe6f6..1b2a1176cd 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -646,7 +646,7 @@ static int sensor_rpmsg_control(FAR struct file *filep,
{
return drv->ops->control(filep, drv, cmd, arg);
}
- else if (!(filep->f_oflags & O_REMOTE))
+ else if (!(filep->f_oflags & O_REMOTE) && _SNIOCVALID(cmd))
{
return sensor_rpmsg_ioctl(dev, cmd, arg,
sizeof(*ioctl) + ioctl->len, true);
[incubator-nuttx] 01/22: driver/sensor: support access remote sensor by rpmsg
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit c5f87bb5c60e162ef23d604249373bdfa4ba06ca
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Apr 8 22:46:29 2022 +0800
driver/sensor: support access remote sensor by rpmsg
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/Kconfig | 7 +
drivers/sensors/Make.defs | 4 +
drivers/sensors/sensor.c | 19 +-
drivers/sensors/sensor_rpmsg.c | 1303 ++++++++++++++++++++++++++++++++++++++++
include/nuttx/sensors/sensor.h | 62 +-
5 files changed, 1389 insertions(+), 6 deletions(-)
diff --git a/drivers/sensors/Kconfig b/drivers/sensors/Kconfig
index 1f2fc138ac..c3033070ac 100644
--- a/drivers/sensors/Kconfig
+++ b/drivers/sensors/Kconfig
@@ -18,6 +18,13 @@ config USENSOR
---help---
Allow application to register user sensor by /dev/usensor.
+config SENSORS_RPMSG
+ bool "Sensor rpmsg Support"
+ default n
+ depends on RPTUN
+ ---help---
+ Allow application to read or control remote sensor device by rpmsg.
+
config SENSORS_WTGAHRS2
bool "Wtgahrs2 Sensor Support"
default n
diff --git a/drivers/sensors/Make.defs b/drivers/sensors/Make.defs
index f372b78ec2..4543a3e9a3 100644
--- a/drivers/sensors/Make.defs
+++ b/drivers/sensors/Make.defs
@@ -28,6 +28,10 @@ ifeq ($(CONFIG_USENSOR),y)
CSRCS += usensor.c
endif
+ifeq ($(CONFIG_SENSORS_RPMSG),y)
+CSRCS += sensor_rpmsg.c
+endif
+
ifeq ($(CONFIG_SENSORS_WTGAHRS2),y)
CSRCS += wtgahrs2.c
endif
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 25431ae489..29add29309 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -599,8 +599,9 @@ static ssize_t sensor_write(FAR struct file *filep, FAR const char *buffer,
{
FAR struct inode *inode = filep->f_inode;
FAR struct sensor_upperhalf_s *upper = inode->i_private;
+ FAR struct sensor_lowerhalf_s *lower = upper->lower;
- return sensor_push_event(upper, buffer, buflen);
+ return lower->push_event(lower->priv, buffer, buflen);
}
static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
@@ -967,8 +968,6 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
/* Initialize the upper-half data structure */
- upper->lower = lower;
-
list_initialize(&upper->userlist);
upper->state.esize = esize;
upper->state.min_interval = ULONG_MAX;
@@ -1007,6 +1006,16 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
goto drv_err;
}
+#ifdef CONFIG_SENSORS_RPMSG
+ lower = sensor_rpmsg_register(lower, path);
+ if (lower == NULL)
+ {
+ ret = -EIO;
+ goto drv_err;
+ }
+#endif
+
+ upper->lower = lower;
return ret;
drv_err:
@@ -1069,6 +1078,10 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *lower,
sninfo("UnRegistering %s\n", path);
unregister_driver(path);
+#ifdef CONFIG_SENSORS_RPMSG
+ sensor_rpmsg_unregister(lower);
+#endif
+
nxsem_destroy(&upper->exclsem);
if (circbuf_is_init(&upper->buffer))
{
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
new file mode 100644
index 0000000000..e69e2fe6f6
--- /dev/null
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -0,0 +1,1303 @@
+/****************************************************************************
+ * drivers/sensors/sensor_rpmsg.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <fcntl.h>
+#include <debug.h>
+
+#include <nuttx/list.h>
+#include <nuttx/kmalloc.h>
+#include <nuttx/mutex.h>
+#include <nuttx/sensors/sensor.h>
+#include <nuttx/rptun/openamp.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define O_REMOTE (1 << 31)
+
+#define SENSOR_RPMSG_EPT_NAME "rpmsg-sensor"
+#define SENSOR_RPMSG_ADVERTISE 0
+#define SENSOR_RPMSG_ADVERTISE_ACK 1
+#define SENSOR_RPMSG_UNADVERTISE 2
+#define SENSOR_RPMSG_SUBSCRIBE 3
+#define SENSOR_RPMSG_SUBSCRIBE_ACK 4
+#define SENSOR_RPMSG_UNSUBSCRIBE 5
+#define SENSOR_RPMSG_PUBLISH 6
+#define SENSOR_RPMSG_IOCTL 7
+#define SENSOR_RPMSG_IOCTL_ACK 8
+
+#define SENSOR_RPMSG_FUNCTION(name, cmd, arg1, arg2, size, wait) \
+static int sensor_rpmsg_##name(FAR struct file *filep, \
+ FAR struct sensor_lowerhalf_s *lower, \
+ unsigned long arg1) \
+{ \
+ FAR struct sensor_rpmsg_dev_s *dev = lower->priv; \
+ FAR struct sensor_lowerhalf_s *drv = dev->drv; \
+ int ret; \
+\
+ if (drv->ops->name) \
+ { \
+ return drv->ops->name(filep, drv, arg2); \
+ } \
+ else if (!(filep->f_oflags & O_REMOTE)) \
+ { \
+ ret = sensor_rpmsg_ioctl(dev, cmd, arg1, size, wait); \
+ return wait ? ret : 0; \
+ } \
+ else \
+ { \
+ return wait ? -ENOTSUP : 0; \
+ } \
+} \
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure describes the context of sensor rpmsg device driver. */
+
+struct sensor_rpmsg_dev_s
+{
+ struct sensor_lowerhalf_s lower;
+ FAR struct sensor_lowerhalf_s *drv;
+ mutex_t lock;
+ struct list_node node;
+ struct list_node stublist;
+ struct list_node proxylist;
+ uint8_t nadvertisers;
+ uint8_t nsubscribers;
+ FAR void *upper;
+ sensor_push_event_t push_event;
+ char path[1];
+};
+
+/* This structure describes the context of sensor rpmsg endpoint. */
+
+struct sensor_rpmsg_ept_s
+{
+ struct list_node node;
+ struct rpmsg_endpoint ept;
+ FAR struct rpmsg_device *rdev;
+ struct work_s work;
+ mutex_t lock;
+ FAR void *buffer;
+ uint64_t expire;
+ uint32_t space;
+ size_t written;
+};
+
+/* This structure describes the stub info about remote subscribers. */
+
+struct sensor_rpmsg_stub_s
+{
+ struct list_node node;
+ FAR struct rpmsg_endpoint *ept;
+ uint64_t cookie;
+ struct file file;
+};
+
+/* This structure describes the proxy info about remote advertisers. */
+
+struct sensor_rpmsg_proxy_s
+{
+ struct list_node node;
+ FAR struct rpmsg_endpoint *ept;
+ uint64_t cookie;
+};
+
+/* Remote message structure */
+
+/* This structure describes the message about initiating a remote
+ * subscription and remote advertisement.
+ */
+
+struct sensor_rpmsg_advsub_s
+{
+ uint32_t command;
+ uint32_t nbuffer;
+ uint64_t cookie;
+ char path[1];
+};
+
+/* The structure sensor_rpmsg_cell_s describes a data message,
+ * include remote receiver, the length of data and the data payload.
+ * The structure sensor_rpmsg_data_s describes a set of data message.
+ */
+
+struct sensor_rpmsg_cell_s
+{
+ uint64_t cookie;
+ uint32_t len;
+ char data[0];
+};
+
+struct sensor_rpmsg_data_s
+{
+ uint32_t command;
+ uint32_t reserved;
+ struct sensor_rpmsg_cell_s cell[0];
+};
+
+/* This structure uses to send ioctl from remote device to physical device,
+ * it supports pass pointer to remove device by cookie_xx member.
+ */
+
+struct sensor_rpmsg_ioctl_cookie_s
+{
+ sem_t sem;
+ FAR void *data;
+ int result;
+};
+
+struct sensor_rpmsg_ioctl_s
+{
+ uint32_t command;
+ int32_t result;
+ uint64_t cookie;
+ uint64_t proxy;
+
+ int32_t request;
+ uint32_t arglen;
+ union
+ {
+ uint64_t arg;
+ char argbuf[0];
+ };
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int sensor_rpmsg_open(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower);
+static int sensor_rpmsg_close(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower);
+static int sensor_rpmsg_activate(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ bool enable);
+static int sensor_rpmsg_set_interval(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ FAR unsigned long *period_us);
+static int sensor_rpmsg_batch(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ FAR unsigned long *latency_us);
+static int sensor_rpmsg_selftest(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ unsigned long arg);
+static int sensor_rpmsg_set_calibvalue(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ unsigned long arg);
+static int sensor_rpmsg_calibrate(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ unsigned long arg);
+static int sensor_rpmsg_control(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ int cmd, unsigned long arg);
+static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_suback_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_publish_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct sensor_ops_s g_sensor_rpmsg_ops =
+{
+ .open = sensor_rpmsg_open,
+ .close = sensor_rpmsg_close,
+ .activate = sensor_rpmsg_activate,
+ .set_interval = sensor_rpmsg_set_interval,
+ .batch = sensor_rpmsg_batch,
+ .selftest = sensor_rpmsg_selftest,
+ .set_calibvalue = sensor_rpmsg_set_calibvalue,
+ .calibrate = sensor_rpmsg_calibrate,
+ .control = sensor_rpmsg_control
+};
+
+static const rpmsg_ept_cb g_sensor_rpmsg_handler[] =
+{
+ [SENSOR_RPMSG_ADVERTISE] = sensor_rpmsg_adv_handler,
+ [SENSOR_RPMSG_ADVERTISE_ACK] = sensor_rpmsg_advack_handler,
+ [SENSOR_RPMSG_UNADVERTISE] = sensor_rpmsg_unadv_handler,
+ [SENSOR_RPMSG_SUBSCRIBE] = sensor_rpmsg_sub_handler,
+ [SENSOR_RPMSG_SUBSCRIBE_ACK] = sensor_rpmsg_suback_handler,
+ [SENSOR_RPMSG_UNSUBSCRIBE] = sensor_rpmsg_unsub_handler,
+ [SENSOR_RPMSG_PUBLISH] = sensor_rpmsg_publish_handler,
+ [SENSOR_RPMSG_IOCTL] = sensor_rpmsg_ioctl_handler,
+ [SENSOR_RPMSG_IOCTL_ACK] = sensor_rpmsg_ioctlack_handler,
+};
+
+static struct list_node g_devlist = LIST_INITIAL_VALUE(g_devlist);
+static struct list_node g_eptlist = LIST_INITIAL_VALUE(g_eptlist);
+static mutex_t g_lock = MUTEX_INITIALIZER;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
+ FAR struct rpmsg_endpoint *ept,
+ int command)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg;
+ uint32_t space;
+ int len = strlen(dev->path) + 1;
+ int ret;
+
+ msg = rpmsg_get_tx_payload_buffer(ept, &space, true);
+ if (!msg)
+ {
+ snerr("ERROR: advsub:%d get buffer failed:%s\n",
+ command, dev->path);
+ return;
+ }
+
+ msg->command = command;
+ msg->cookie = (uint64_t)(uintptr_t)dev;
+ msg->nbuffer = dev->lower.nbuffer;
+ memcpy(msg->path, dev->path, len);
+ ret = rpmsg_send_nocopy(ept, msg, sizeof(*msg) + len);
+ if (ret < 0)
+ {
+ snerr("ERROR: advsub:%d rpmsg send failed:%s %d\n",
+ command, dev->path, ret);
+ }
+}
+
+static void sensor_rpmsg_advsub(FAR struct sensor_rpmsg_dev_s *dev,
+ int command)
+{
+ FAR struct sensor_rpmsg_ept_s *sre;
+
+ /* Broadcast advertise/subscribe message to all ready ept */
+
+ nxmutex_lock(&g_lock);
+ list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
+ node)
+ {
+ sensor_rpmsg_advsub_one(dev, &sre->ept, command);
+ }
+
+ nxmutex_unlock(&g_lock);
+}
+
+static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
+ int cmd, unsigned long arg, size_t len,
+ bool wait)
+{
+ struct sensor_rpmsg_ioctl_cookie_s cookie;
+ FAR struct sensor_rpmsg_proxy_s *proxy;
+ FAR struct sensor_rpmsg_ioctl_s *msg;
+ uint32_t space;
+ int ret = -ENOTTY;
+
+ if (wait)
+ {
+ cookie.data = (FAR void *)(uintptr_t)arg;
+ cookie.result = -ENXIO;
+ nxsem_init(&cookie.sem, 0, 0);
+ nxsem_set_protocol(&cookie.sem, SEM_PRIO_NONE);
+ }
+
+ /* All control is always send to own proxy(remote advertisers),
+ * if device doesn't have proxy, it must return -ENOTTY.
+ */
+
+ nxmutex_lock(&dev->lock);
+ list_for_every_entry(&dev->proxylist, proxy,
+ struct sensor_rpmsg_proxy_s, node)
+ {
+ msg = rpmsg_get_tx_payload_buffer(proxy->ept, &space, true);
+ if (!msg)
+ {
+ ret = -ENOMEM;
+ snerr("ERROR: ioctl get buffer failed:%s\n", dev->path);
+ break;
+ }
+
+ msg->command = SENSOR_RPMSG_IOCTL;
+ msg->cookie = wait ? (uint64_t)(uintptr_t)&cookie : 0;
+ msg->proxy = proxy->cookie;
+ msg->request = cmd;
+ msg->arglen = len;
+ if (len > 0)
+ {
+ memcpy(msg->argbuf, (FAR void *)(uintptr_t)arg, len);
+ }
+ else
+ {
+ msg->arg = arg;
+ }
+
+ ret = rpmsg_send_nocopy(proxy->ept, msg, sizeof(*msg) + len);
+ if (ret < 0)
+ {
+ snerr("ERROR: ioctl rpmsg send failed:%s %d\n", dev->path, ret);
+ break;
+ }
+
+ if (!wait)
+ {
+ continue;
+ }
+
+ nxmutex_unlock(&dev->lock);
+ ret = rpmsg_wait(proxy->ept, &cookie.sem);
+ nxmutex_lock(&dev->lock);
+ if (ret < 0)
+ {
+ snerr("ERROR: ioctl rpmsg wait failed:%s %d\n", dev->path, ret);
+ break;
+ }
+
+ ret = cookie.result;
+ if (ret < 0 && ret != -ENOTTY)
+ {
+ break;
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+ if (wait)
+ {
+ nxsem_destroy(&cookie.sem);
+ }
+
+ return ret;
+}
+
+static FAR struct sensor_rpmsg_proxy_s *
+sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
+ FAR struct rpmsg_endpoint *ept,
+ uint64_t cookie, uint32_t nbuffer)
+{
+ FAR struct sensor_rpmsg_proxy_s *proxy;
+ struct sensor_state_s state;
+ struct file file;
+ int ret;
+
+ /* Create new proxy to represent a remote advertiser */
+
+ proxy = kmm_malloc(sizeof(*proxy));
+ if (!proxy)
+ {
+ return NULL;
+ }
+
+ proxy->ept = ept;
+ proxy->cookie = cookie;
+ ret = file_open(&file, dev->path, O_REMOTE);
+ if (ret < 0)
+ {
+ kmm_free(proxy);
+ return NULL;
+ }
+
+ file_ioctl(&file, SNIOC_SET_BUFFER_NUMBER, nbuffer);
+ file_ioctl(&file, SNIOC_GET_STATE, &state);
+ file_close(&file);
+
+ nxmutex_lock(&dev->lock);
+ list_add_tail(&dev->proxylist, &proxy->node);
+ nxmutex_unlock(&dev->lock);
+
+ /* sync interval and latency */
+
+ if (state.min_interval != ULONG_MAX)
+ {
+ sensor_rpmsg_ioctl(dev, SNIOC_SET_INTERVAL, state.min_interval,
+ 0, false);
+ }
+
+ if (state.min_latency != ULONG_MAX)
+ {
+ sensor_rpmsg_ioctl(dev, SNIOC_BATCH, state.min_latency, 0, false);
+ }
+
+ return proxy;
+}
+
+static FAR struct sensor_rpmsg_stub_s *
+sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
+ FAR struct rpmsg_endpoint *ept,
+ uint64_t cookie)
+{
+ FAR struct sensor_rpmsg_stub_s *stub;
+ int ret;
+
+ /* Create new stub to represent a remote subscribers */
+
+ stub = kmm_malloc(sizeof(*stub));
+ if (!stub)
+ {
+ return NULL;
+ }
+
+ stub->ept = ept;
+ stub->cookie = cookie;
+ ret = file_open(&stub->file, dev->path,
+ O_RDOK | O_NONBLOCK | O_REMOTE);
+ if (ret < 0)
+ {
+ kmm_free(stub);
+ return NULL;
+ }
+
+ file_ioctl(&stub->file, SNIOC_READLAST, false);
+ nxmutex_lock(&dev->lock);
+ list_add_tail(&dev->stublist, &stub->node);
+ nxmutex_unlock(&dev->lock);
+
+ return stub;
+}
+
+static void sensor_rpmsg_free_proxy(FAR struct sensor_rpmsg_proxy_s *proxy)
+{
+ list_delete(&proxy->node);
+ kmm_free(proxy);
+}
+
+static void sensor_rpmsg_free_stub(FAR struct sensor_rpmsg_stub_s *stub)
+{
+ list_delete(&stub->node);
+ file_close(&stub->file);
+ kmm_free(stub);
+}
+
+static int sensor_rpmsg_open(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower)
+{
+ FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+ FAR struct sensor_lowerhalf_s *drv = dev->drv;
+ int ret;
+
+ if (drv->ops->open)
+ {
+ ret = drv->ops->open(filep, drv);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+
+ if (filep->f_oflags & O_REMOTE)
+ {
+ return 0;
+ }
+
+ nxmutex_lock(&dev->lock);
+ if (filep->f_oflags & O_WROK)
+ {
+ if (dev->nadvertisers++ == 0)
+ {
+ sensor_rpmsg_advsub(dev, SENSOR_RPMSG_ADVERTISE);
+ }
+ }
+
+ if (filep->f_oflags & O_RDOK)
+ {
+ if (dev->nsubscribers++ == 0)
+ {
+ sensor_rpmsg_advsub(dev, SENSOR_RPMSG_SUBSCRIBE);
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+ return 0;
+}
+
+static int sensor_rpmsg_close(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower)
+{
+ FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+ FAR struct sensor_lowerhalf_s *drv = dev->drv;
+ FAR struct sensor_rpmsg_proxy_s *proxy;
+ FAR struct sensor_rpmsg_proxy_s *ptmp;
+ FAR struct sensor_rpmsg_stub_s *stub;
+ FAR struct sensor_rpmsg_stub_s *stmp;
+ int ret = 0;
+
+ if (drv->ops->close)
+ {
+ ret = drv->ops->close(filep, drv);
+ }
+
+ if (filep->f_oflags & O_REMOTE)
+ {
+ return ret;
+ }
+
+ nxmutex_lock(&dev->lock);
+ if (filep->f_oflags & O_WROK)
+ {
+ if (dev->nadvertisers == 1)
+ {
+ sensor_rpmsg_advsub(dev, SENSOR_RPMSG_UNADVERTISE);
+ list_for_every_entry_safe(&dev->stublist, stub, stmp,
+ struct sensor_rpmsg_stub_s, node)
+ {
+ sensor_rpmsg_free_stub(stub);
+ }
+ }
+
+ dev->nadvertisers--;
+ }
+
+ if (filep->f_oflags & O_RDOK)
+ {
+ if (dev->nsubscribers == 1)
+ {
+ sensor_rpmsg_advsub(dev, SENSOR_RPMSG_UNSUBSCRIBE);
+ list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
+ struct sensor_rpmsg_proxy_s, node)
+ {
+ sensor_rpmsg_free_proxy(proxy);
+ }
+ }
+
+ dev->nsubscribers--;
+ }
+
+ nxmutex_unlock(&dev->lock);
+ return ret;
+}
+
+static int sensor_rpmsg_activate(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ bool enable)
+{
+ FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+ FAR struct sensor_lowerhalf_s *drv = dev->drv;
+
+ if (drv->ops->activate)
+ {
+ return drv->ops->activate(filep, drv, enable);
+ }
+
+ return 0;
+}
+
+SENSOR_RPMSG_FUNCTION(set_interval, SNIOC_SET_INTERVAL,
+ *interval, interval, 0, false)
+SENSOR_RPMSG_FUNCTION(batch, SNIOC_BATCH, *latency, latency, 0, false)
+SENSOR_RPMSG_FUNCTION(selftest, SNIOC_SELFTEST, arg, arg, 0, true)
+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_control(FAR struct file *filep,
+ FAR struct sensor_lowerhalf_s *lower,
+ int cmd, unsigned long arg)
+{
+ FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+ FAR struct sensor_lowerhalf_s *drv = dev->drv;
+ FAR struct sensor_ioctl_s *ioctl = (FAR void *)(uintptr_t)arg;
+
+ if (drv->ops->control)
+ {
+ return drv->ops->control(filep, drv, cmd, arg);
+ }
+ else if (!(filep->f_oflags & O_REMOTE))
+ {
+ return sensor_rpmsg_ioctl(dev, cmd, arg,
+ sizeof(*ioctl) + ioctl->len, true);
+ }
+
+ return -ENOTTY;
+}
+
+static void sensor_rpmsg_data_worker(FAR void *arg)
+{
+ FAR struct sensor_rpmsg_ept_s *sre = arg;
+
+ nxmutex_lock(&sre->lock);
+ if (sre->buffer)
+ {
+ rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
+ sre->buffer = NULL;
+ }
+
+ nxmutex_unlock(&sre->lock);
+}
+
+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_cell_s *cell;
+ FAR struct sensor_rpmsg_ept_s *sre;
+ FAR struct sensor_rpmsg_data_s *msg;
+ struct sensor_state_s state;
+ uint64_t now;
+ int ret;
+
+ /* Get state of device to do send data with timeout */
+
+ ret = file_ioctl(&stub->file, SNIOC_GET_STATE, &state);
+ if (ret < 0)
+ {
+ return;
+ }
+
+ if (state.min_interval == ULONG_MAX)
+ {
+ state.min_interval = 0;
+ }
+
+ sre = container_of(stub->ept, struct sensor_rpmsg_ept_s, ept);
+ nxmutex_lock(&sre->lock);
+
+ /* Cancel work to fill new data to buffer */
+
+ if (sre->buffer)
+ {
+ work_cancel(HPWORK, &sre->work);
+ }
+
+ for (; ; )
+ {
+ /* If buffer isn't created or it doesn't have enough space to fill
+ * new data, you should create or send this buffer at once.
+ */
+
+ if (!sre->buffer ||
+ sre->written + sizeof(*cell) + state.esize > sre->space)
+ {
+ if (sre->buffer)
+ {
+ rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
+ }
+
+ msg = rpmsg_get_tx_payload_buffer(&sre->ept, &sre->space, true);
+ sre->buffer = msg;
+ if (!msg)
+ {
+ snerr("ERROR: push event get buffer failed:%s\n",
+ rpmsg_get_cpuname(sre->ept.rdev));
+ nxmutex_unlock(&sre->lock);
+ return;
+ }
+
+ msg->command = SENSOR_RPMSG_PUBLISH;
+ sre->written = sizeof(*msg);
+ sre->expire = UINT64_MAX;
+ }
+
+ cell = sre->buffer + sre->written;
+ ret = file_read(&stub->file, cell->data,
+ sre->space - sre->written - sizeof(*cell));
+ if (ret <= 0)
+ {
+ break;
+ }
+
+ cell->len = ret;
+ cell->cookie = stub->cookie;
+ sre->written += (sizeof(*cell) + ret + 0x7) & ~0x7;
+ }
+
+ /* If buffer timeout is expired, do rpmsg_send_nocopy, otherwise using
+ * delay work to send data.
+ */
+
+ now = sensor_get_timestamp();
+ if (sre->expire <= now)
+ {
+ ret = rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
+ sre->buffer = NULL;
+ if (ret < 0)
+ {
+ snerr("ERROR: push event rpmsg send failed:%s %d\n",
+ rpmsg_get_cpuname(sre->ept.rdev), ret);
+ }
+ }
+ else
+ {
+ if (sre->expire == UINT64_MAX ||
+ sre->expire - now > state.min_interval / 2)
+ {
+ sre->expire = now + state.min_interval / 2;
+ }
+
+ work_queue(HPWORK, &sre->work, sensor_rpmsg_data_worker, sre,
+ (sre->expire - now) / USEC_PER_TICK);
+ }
+
+ nxmutex_unlock(&sre->lock);
+}
+
+static ssize_t sensor_rpmsg_push_event(FAR void *priv, FAR const void *data,
+ size_t bytes)
+{
+ FAR struct sensor_rpmsg_dev_s *dev = priv;
+ FAR struct sensor_rpmsg_stub_s *stub;
+ ssize_t ret;
+
+ /* Push new data to upperhalf driver's circular buffer */
+
+ ret = dev->push_event(dev->upper, data, bytes);
+ if (ret < 0)
+ {
+ return ret;
+ }
+
+ /* Send new data to own proxy(remote subscribers), don't care whether
+ * is successful, and must return length of written.
+ */
+
+ nxmutex_lock(&dev->lock);
+ list_for_every_entry(&dev->stublist, stub,
+ struct sensor_rpmsg_stub_s, node)
+ {
+ sensor_rpmsg_push_event_one(dev, stub);
+ }
+
+ nxmutex_unlock(&dev->lock);
+ return ret;
+}
+
+static FAR struct sensor_rpmsg_dev_s *
+sensor_rpmsg_find_dev(FAR const char *path)
+{
+ FAR struct sensor_rpmsg_dev_s *dev;
+
+ nxmutex_lock(&g_lock);
+ list_for_every_entry(&g_devlist, dev, struct sensor_rpmsg_dev_s, node)
+ {
+ if (strcmp(dev->path, path) == 0)
+ {
+ nxmutex_unlock(&g_lock);
+ return dev;
+ }
+ }
+
+ nxmutex_unlock(&g_lock);
+ return NULL;
+}
+
+static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+ FAR struct sensor_rpmsg_proxy_s *proxy;
+ FAR struct sensor_rpmsg_dev_s *dev;
+ int ret;
+
+ dev = sensor_rpmsg_find_dev(msg->path);
+ if (!dev || !dev->nsubscribers)
+ {
+ return 0;
+ }
+
+ proxy = sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer);
+ if (!proxy)
+ {
+ snerr("ERROR: adv alloc proxy failed:%s\n", dev->path);
+ }
+ else
+ {
+ msg->cookie = (uint64_t)(uintptr_t)dev;
+ msg->command = SENSOR_RPMSG_ADVERTISE_ACK;
+ ret = rpmsg_send(ept, msg, len);
+ if (ret < 0)
+ {
+ sensor_rpmsg_free_proxy(proxy);
+ snerr("ERROR: adv rpmsg send failed:%s %d\n", dev->path, ret);
+ }
+ }
+
+ return 0;
+}
+
+static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+ FAR struct sensor_rpmsg_dev_s *dev;
+
+ dev = sensor_rpmsg_find_dev(msg->path);
+ if (dev && (!dev->nadvertisers ||
+ !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie)))
+ {
+ sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNADVERTISE);
+ snerr("ERROR: advack failed:%s\n", dev->path);
+ }
+
+ return 0;
+}
+
+static int sensor_rpmsg_unadv_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+ FAR struct sensor_rpmsg_proxy_s *proxy;
+ FAR struct sensor_rpmsg_dev_s *dev;
+
+ dev = sensor_rpmsg_find_dev(msg->path);
+ if (!dev)
+ {
+ return 0;
+ }
+
+ nxmutex_lock(&dev->lock);
+ list_for_every_entry(&dev->proxylist, proxy,
+ struct sensor_rpmsg_proxy_s, node)
+ {
+ if (proxy->ept == ept && proxy->cookie == msg->cookie)
+ {
+ sensor_rpmsg_free_proxy(proxy);
+ break;
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+ return 0;
+}
+
+static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+ FAR struct sensor_rpmsg_dev_s *dev;
+ FAR struct sensor_rpmsg_stub_s *stub;
+ int ret;
+
+ dev = sensor_rpmsg_find_dev(msg->path);
+ if (!dev || !dev->nadvertisers)
+ {
+ return 0;
+ }
+
+ stub = sensor_rpmsg_alloc_stub(dev, ept, msg->cookie);
+ if (!stub)
+ {
+ snerr("ERROR: sub alloc stub failed:%s\n", dev->path);
+ }
+ else
+ {
+ msg->cookie = (uint64_t)(uintptr_t)dev;
+ msg->command = SENSOR_RPMSG_SUBSCRIBE_ACK;
+ msg->nbuffer = dev->lower.nbuffer;
+ ret = rpmsg_send(ept, msg, len);
+ if (ret < 0)
+ {
+ sensor_rpmsg_free_stub(stub);
+ snerr("ERROR: sub rpmsg send failed:%s %d\n", dev->path, ret);
+ }
+ }
+
+ return 0;
+}
+
+static int sensor_rpmsg_suback_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+ FAR struct sensor_rpmsg_dev_s *dev;
+
+ dev = sensor_rpmsg_find_dev(msg->path);
+ if (dev && (!dev->nsubscribers ||
+ !sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer)))
+ {
+ sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNSUBSCRIBE);
+ snerr("ERROR: suback failed:%s\n", dev->path);
+ }
+
+ return 0;
+}
+
+static int sensor_rpmsg_unsub_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+ FAR struct sensor_rpmsg_dev_s *dev;
+ FAR struct sensor_rpmsg_stub_s *stub;
+
+ dev = sensor_rpmsg_find_dev(msg->path);
+ if (!dev)
+ {
+ return 0;
+ }
+
+ nxmutex_lock(&dev->lock);
+ list_for_every_entry(&dev->stublist, stub,
+ struct sensor_rpmsg_stub_s, node)
+ {
+ if (stub->ept == ept && stub->cookie == msg->cookie)
+ {
+ sensor_rpmsg_free_stub(stub);
+ break;
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+ return 0;
+}
+
+static int sensor_rpmsg_publish_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_data_s *msg = data;
+ FAR struct sensor_rpmsg_cell_s *cell;
+ FAR struct sensor_rpmsg_dev_s *dev;
+ size_t written = sizeof(*msg);
+
+ while (written < len)
+ {
+ cell = (FAR struct sensor_rpmsg_cell_s *)
+ ((FAR char *)data + written);
+ dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)cell->cookie;
+ dev->push_event(dev->upper, cell->data, cell->len);
+ written += sizeof(*cell) + cell->len + 0x7;
+ written &= ~0x7;
+ }
+
+ return 0;
+}
+
+static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_ioctl_s *msg = data;
+ FAR struct sensor_rpmsg_stub_s *stub;
+ FAR struct sensor_rpmsg_dev_s *dev;
+ unsigned long arg;
+ int ret;
+
+ arg = msg->arglen > 0 ? (unsigned long)(uintptr_t)msg->argbuf :
+ msg->arg;
+ dev = (FAR struct sensor_rpmsg_dev_s *)(uintptr_t)msg->proxy;
+ nxmutex_lock(&dev->lock);
+ list_for_every_entry(&dev->stublist, stub,
+ struct sensor_rpmsg_stub_s, node)
+ {
+ if (stub->ept == ept)
+ {
+ msg->result = file_ioctl(&stub->file, msg->request, arg);
+ if (msg->cookie)
+ {
+ msg->command = SENSOR_RPMSG_IOCTL_ACK;
+ ret = rpmsg_send(ept, msg, len);
+ if (ret < 0)
+ {
+ snerr("ERROR: ioctl rpmsg send failed:%s %d\n",
+ dev->path, ret);
+ }
+ }
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+ return 0;
+}
+
+static int sensor_rpmsg_ioctlack_handler(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len,
+ uint32_t src, FAR void *priv)
+{
+ FAR struct sensor_rpmsg_ioctl_cookie_s *cookie;
+ FAR struct sensor_rpmsg_ioctl_s *msg = data;
+
+ cookie = (FAR struct sensor_rpmsg_ioctl_cookie_s *)
+ (uintptr_t)msg->cookie;
+ cookie->result = msg->result;
+ if (msg->result >= 0 && msg->arglen > 0)
+ {
+ memcpy(cookie->data, msg->argbuf, msg->arglen);
+ }
+
+ rpmsg_post(ept, &cookie->sem);
+ return 0;
+}
+
+static int sensor_rpmsg_ept_cb(FAR struct rpmsg_endpoint *ept,
+ FAR void *data, size_t len, uint32_t src,
+ FAR void *priv)
+{
+ FAR struct sensor_rpmsg_advsub_s *msg = data;
+
+ if (msg->command < sizeof(g_sensor_rpmsg_handler) /
+ sizeof(g_sensor_rpmsg_handler[0]))
+ {
+ return g_sensor_rpmsg_handler[msg->command](ept, data, len, src, priv);
+ }
+
+ return -EINVAL;
+}
+
+static void sensor_rpmsg_ns_unbind_cb(FAR struct rpmsg_endpoint *ept)
+{
+ FAR struct sensor_rpmsg_ept_s *sre;
+ FAR struct sensor_rpmsg_dev_s *dev;
+ FAR struct sensor_rpmsg_stub_s *stub;
+ FAR struct sensor_rpmsg_stub_s *stmp;
+ FAR struct sensor_rpmsg_proxy_s *proxy;
+ FAR struct sensor_rpmsg_proxy_s *ptmp;
+
+ sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
+
+ /* Remove all proxy and stub info in sensor device with the ept
+ * destoryed.
+ */
+
+ nxmutex_lock(&g_lock);
+ list_for_every_entry(&g_devlist, dev,
+ struct sensor_rpmsg_dev_s, node)
+ {
+ nxmutex_lock(&dev->lock);
+ list_for_every_entry_safe(&dev->proxylist, proxy, ptmp,
+ struct sensor_rpmsg_proxy_s, node)
+ {
+ if (proxy->ept == ept)
+ {
+ sensor_rpmsg_free_proxy(proxy);
+ }
+ }
+
+ list_for_every_entry_safe(&dev->stublist, stub, stmp,
+ struct sensor_rpmsg_stub_s, node)
+ {
+ if (stub->ept == ept)
+ {
+ sensor_rpmsg_free_stub(stub);
+ }
+ }
+
+ nxmutex_unlock(&dev->lock);
+ }
+
+ list_delete(&sre->node);
+ nxmutex_unlock(&g_lock);
+ rpmsg_destroy_ept(ept);
+ nxmutex_destroy(&sre->lock);
+ kmm_free(sre);
+}
+
+static void sensor_rpmsg_device_ns_bound(FAR struct rpmsg_endpoint *ept)
+{
+ FAR struct sensor_rpmsg_ept_s *sre;
+ FAR struct sensor_rpmsg_dev_s *dev;
+
+ sre = container_of(ept, struct sensor_rpmsg_ept_s, ept);
+
+ nxmutex_lock(&g_lock);
+ list_add_tail(&g_eptlist, &sre->node);
+
+ /* Broadcast all device to ready ept */
+
+ list_for_every_entry(&g_devlist, dev,
+ struct sensor_rpmsg_dev_s, node)
+ {
+ nxmutex_lock(&dev->lock);
+ if (dev->nadvertisers > 0)
+ {
+ sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_ADVERTISE);
+ }
+
+ if (dev->nsubscribers > 0)
+ {
+ sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_SUBSCRIBE);
+ }
+
+ nxmutex_unlock(&dev->lock);
+ }
+
+ nxmutex_unlock(&g_lock);
+}
+
+static void sensor_rpmsg_device_created(FAR struct rpmsg_device *rdev,
+ FAR void *priv)
+{
+ FAR struct sensor_rpmsg_ept_s *sre;
+
+ sre = kmm_zalloc(sizeof(*sre));
+ if (!sre)
+ {
+ return;
+ }
+
+ sre->rdev = rdev;
+ sre->ept.priv = sre;
+ nxmutex_init(&sre->lock);
+ sre->ept.ns_bound_cb = sensor_rpmsg_device_ns_bound;
+ if (rpmsg_create_ept(&sre->ept, rdev, SENSOR_RPMSG_EPT_NAME,
+ RPMSG_ADDR_ANY, RPMSG_ADDR_ANY,
+ sensor_rpmsg_ept_cb,
+ sensor_rpmsg_ns_unbind_cb) < 0)
+ {
+ nxmutex_destroy(&sre->lock);
+ kmm_free(sre);
+ }
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sensor_rpmsg_register
+ *
+ * Description:
+ * This function registers rpmsg takeover for the real lower half, and
+ * initialize rpmsg resource.
+ *
+ * Input Parameters:
+ * lower - The instance of lower half sensor driver.
+ * path - The path of character node, ex: /dev/sensor/xxx.
+ *
+ * Returned Value:
+ * The takeover rpmsg lowerhalf returned on success, NULL on failure.
+ ****************************************************************************/
+
+FAR struct sensor_lowerhalf_s *
+sensor_rpmsg_register(FAR struct sensor_lowerhalf_s *lower,
+ FAR const char *path)
+{
+ FAR struct sensor_rpmsg_ept_s *sre;
+ FAR struct sensor_rpmsg_dev_s *dev;
+
+ if (lower->ops->fetch)
+ {
+ return lower;
+ }
+
+ dev = kmm_zalloc(sizeof(*dev) + strlen(path));
+ if (!dev)
+ {
+ return NULL;
+ }
+
+ /* Initialize the sensor rpmsg device structure */
+
+ list_initialize(&dev->stublist);
+ list_initialize(&dev->proxylist);
+ nxmutex_init(&dev->lock);
+ strcpy(dev->path, path);
+
+ dev->push_event = lower->push_event;
+ dev->upper = lower->priv;
+ lower->push_event = sensor_rpmsg_push_event;
+ lower->priv = dev;
+ memcpy(&dev->lower, lower, sizeof(*lower));
+ dev->lower.ops = &g_sensor_rpmsg_ops;
+ dev->drv = lower;
+
+ /* If openamp is ready, send advertisement to remote proc */
+
+ nxmutex_lock(&g_lock);
+ list_add_tail(&g_devlist, &dev->node);
+ if (lower->ops->activate)
+ {
+ dev->nadvertisers = 1;
+ list_for_every_entry(&g_eptlist, sre, struct sensor_rpmsg_ept_s,
+ node)
+ {
+ sensor_rpmsg_advsub_one(dev, &sre->ept, SENSOR_RPMSG_ADVERTISE);
+ }
+ }
+
+ nxmutex_unlock(&g_lock);
+
+ return &dev->lower;
+}
+
+/****************************************************************************
+ * Name: sensor_rpmsg_unregister
+ *
+ * Description:
+ * This function unregisters rpmsg takeover for the real lower half, and
+ * release rpmsg resource. This API corresponds to sensor_rpmsg_register.
+ *
+ * Input Parameters:
+ * lower - The instance of lower half sensor driver.
+ ****************************************************************************/
+
+void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower)
+{
+ FAR struct sensor_rpmsg_dev_s *dev = lower->priv;
+
+ if (lower->ops != &g_sensor_rpmsg_ops)
+ {
+ return;
+ }
+
+ nxmutex_lock(&g_lock);
+ list_delete(&dev->node);
+ nxmutex_unlock(&g_lock);
+
+ nxmutex_destroy(&dev->lock);
+ kmm_free(dev);
+}
+
+/****************************************************************************
+ * Name: sensor_rpmsg_initialize
+ *
+ * Description:
+ * This function initializes the context of sensor rpmsg, registers
+ * rpmsg callback and prepares enviroment to intercat with remote sensor.
+ *
+ * Returned Value:
+ * OK on success; A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+int sensor_rpmsg_initialize(void)
+{
+ return rpmsg_register_callback(NULL, sensor_rpmsg_device_created,
+ NULL, NULL);
+}
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index 0658d5c788..ef0f2442a3 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -857,6 +857,11 @@ struct sensor_ops_s
* Sensor driver.
*/
+typedef CODE ssize_t (*sensor_push_event_t)(FAR void *priv,
+ FAR const void *data,
+ size_t bytes);
+typedef CODE void (*sensor_notify_event_t)(FAR void *priv);
+
struct sensor_lowerhalf_s
{
/* The type of sensor device */
@@ -908,8 +913,7 @@ struct sensor_lowerhalf_s
* A negated errno value is returned on any failure.
**********************************************************************/
- CODE ssize_t (*push_event)(FAR void *priv, FAR const void *data,
- size_t bytes);
+ sensor_push_event_t push_event;
/**********************************************************************
* Name: notify_event
@@ -925,7 +929,7 @@ struct sensor_lowerhalf_s
* priv - Upper half driver handle
**********************************************************************/
- CODE void (*notify_event)(FAR void *priv);
+ sensor_notify_event_t notify_event;
};
/* The private opaque pointer to be passed to upper-layer during callback */
@@ -1084,6 +1088,58 @@ void sensor_custom_unregister(FAR struct sensor_lowerhalf_s *dev,
int usensor_initialize(void);
#endif
+/****************************************************************************
+ * Name: sensor_rpmsg_register
+ *
+ * Description:
+ * This function registers rpmsg takeover for the real lower half, and
+ * initialize rpmsg resource.
+ *
+ * Input Parameters:
+ * lower - The instance of lower half sensor driver.
+ * path - The path of character node, ex: /dev/sensor/xxx.
+ *
+ * Returned Value:
+ * The takeover rpmsg lowerhalf returned on success, NULL on failure.
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_RPMSG
+FAR struct sensor_lowerhalf_s *sensor_rpmsg_register(
+ FAR struct sensor_lowerhalf_s *lower,
+ FAR const char *path);
+#endif
+
+/****************************************************************************
+ * Name: sensor_rpmsg_unregister
+ *
+ * Description:
+ * This function unregisters rpmsg takeover for the real lower half, and
+ * release rpmsg resource. This API corresponds to the
+ * sensor_rpmsg_register.
+ *
+ * Input Parameters:
+ * lower - The instance of lower half sensor driver.
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_RPMSG
+void sensor_rpmsg_unregister(FAR struct sensor_lowerhalf_s *lower);
+#endif
+
+/****************************************************************************
+ * Name: sensor_rpmsg_initialize
+ *
+ * Description:
+ * This function initializes the context of sensor rpmsg, registers
+ * rpmsg callback and prepares enviroment to intercat with remote sensor.
+ *
+ * Returned Value:
+ * OK on success; A negated errno value is returned on any failure.
+ ****************************************************************************/
+
+#ifdef CONFIG_SENSORS_RPMSG
+int sensor_rpmsg_initialize(void);
+#endif
+
#undef EXTERN
#if defined(__cplusplus)
}
[incubator-nuttx] 07/22: driver/sensor: support sensor data persist
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit fa4cebce32e477590bd6c643807e71487436d5f5
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Sat May 21 17:50:29 2022 +0800
driver/sensor: support sensor data persist
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 29 +++++++++++++++++--
drivers/sensors/sensor_rpmsg.c | 63 +++++++++++++++++++++++++++++++-----------
drivers/sensors/usensor.c | 1 +
include/nuttx/sensors/sensor.h | 17 ++++++++++++
4 files changed, 92 insertions(+), 18 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 93fba9e504..89b47813ba 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -426,11 +426,23 @@ static int sensor_open(FAR struct file *filep)
if (filep->f_oflags & O_WROK)
{
upper->state.nadvertisers++;
+ if (filep->f_oflags & SENSOR_PERSIST)
+ {
+ lower->persist = true;
+ }
+ }
+
+ if (upper->state.generation && lower->persist)
+ {
+ user->generation = upper->state.generation - 1;
+ }
+ else
+ {
+ user->generation = upper->state.generation;
}
user->interval = ULONG_MAX;
user->latency = ULONG_MAX;
- user->generation = upper->state.generation;
user->readlast = true;
nxsem_init(&user->buffersem, 0, 0);
nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
@@ -556,9 +568,22 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
goto out;
}
+ /* If the device data is persistent, and when the device has no
+ * new data, the user can copy the old data, otherwise return
+ * -ENODATA.
+ */
+
if (user->generation == upper->state.generation)
{
- user->generation--;
+ if (lower->persist)
+ {
+ user->generation--;
+ }
+ else
+ {
+ ret = -ENODATA;
+ goto out;
+ }
}
}
else
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 1b2a1176cd..58ba632c7d 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -37,8 +37,6 @@
* Pre-processor Definitions
****************************************************************************/
-#define O_REMOTE (1 << 31)
-
#define SENSOR_RPMSG_EPT_NAME "rpmsg-sensor"
#define SENSOR_RPMSG_ADVERTISE 0
#define SENSOR_RPMSG_ADVERTISE_ACK 1
@@ -63,7 +61,7 @@ static int sensor_rpmsg_##name(FAR struct file *filep, \
{ \
return drv->ops->name(filep, drv, arg2); \
} \
- else if (!(filep->f_oflags & O_REMOTE)) \
+ else if (!(filep->f_oflags & SENSOR_REMOTE)) \
{ \
ret = sensor_rpmsg_ioctl(dev, cmd, arg1, size, wait); \
return wait ? ret : 0; \
@@ -140,6 +138,7 @@ struct sensor_rpmsg_advsub_s
uint32_t command;
uint32_t nbuffer;
uint64_t cookie;
+ uint32_t persist;
char path[1];
};
@@ -245,6 +244,8 @@ static int sensor_rpmsg_ioctl_handler(FAR struct rpmsg_endpoint *ept,
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);
/****************************************************************************
* Private Data
@@ -304,6 +305,7 @@ static void sensor_rpmsg_advsub_one(FAR struct sensor_rpmsg_dev_s *dev,
msg->command = command;
msg->cookie = (uint64_t)(uintptr_t)dev;
msg->nbuffer = dev->lower.nbuffer;
+ msg->persist = dev->lower.persist;
memcpy(msg->path, dev->path, len);
ret = rpmsg_send_nocopy(ept, msg, sizeof(*msg) + len);
if (ret < 0)
@@ -418,13 +420,22 @@ static int sensor_rpmsg_ioctl(FAR struct sensor_rpmsg_dev_s *dev,
static FAR struct sensor_rpmsg_proxy_s *
sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
FAR struct rpmsg_endpoint *ept,
- uint64_t cookie, uint32_t nbuffer)
+ FAR struct sensor_rpmsg_advsub_s *msg)
{
FAR struct sensor_rpmsg_proxy_s *proxy;
struct sensor_state_s state;
struct file file;
int ret;
+ list_for_every_entry(&dev->proxylist, proxy,
+ struct sensor_rpmsg_proxy_s, node)
+ {
+ if (proxy->ept == ept && proxy->cookie == msg->cookie)
+ {
+ return proxy;
+ }
+ }
+
/* Create new proxy to represent a remote advertiser */
proxy = kmm_malloc(sizeof(*proxy));
@@ -434,19 +445,25 @@ sensor_rpmsg_alloc_proxy(FAR struct sensor_rpmsg_dev_s *dev,
}
proxy->ept = ept;
- proxy->cookie = cookie;
- ret = file_open(&file, dev->path, O_REMOTE);
+ proxy->cookie = msg->cookie;
+ ret = file_open(&file, dev->path, SENSOR_REMOTE);
if (ret < 0)
{
kmm_free(proxy);
return NULL;
}
- file_ioctl(&file, SNIOC_SET_BUFFER_NUMBER, nbuffer);
+ file_ioctl(&file, SNIOC_SET_BUFFER_NUMBER, msg->nbuffer);
file_ioctl(&file, SNIOC_GET_STATE, &state);
file_close(&file);
nxmutex_lock(&dev->lock);
+ if (msg->persist)
+ {
+ dev->drv->persist = true;
+ dev->lower.persist = true;
+ }
+
list_add_tail(&dev->proxylist, &proxy->node);
nxmutex_unlock(&dev->lock);
@@ -474,6 +491,15 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
FAR struct sensor_rpmsg_stub_s *stub;
int ret;
+ list_for_every_entry(&dev->stublist, stub,
+ struct sensor_rpmsg_stub_s, node)
+ {
+ if (stub->ept == ept && stub->cookie == cookie)
+ {
+ return stub;
+ }
+ }
+
/* Create new stub to represent a remote subscribers */
stub = kmm_malloc(sizeof(*stub));
@@ -485,7 +511,7 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
stub->ept = ept;
stub->cookie = cookie;
ret = file_open(&stub->file, dev->path,
- O_RDOK | O_NONBLOCK | O_REMOTE);
+ O_RDOK | O_NONBLOCK | SENSOR_REMOTE);
if (ret < 0)
{
kmm_free(stub);
@@ -497,6 +523,11 @@ sensor_rpmsg_alloc_stub(FAR struct sensor_rpmsg_dev_s *dev,
list_add_tail(&dev->stublist, &stub->node);
nxmutex_unlock(&dev->lock);
+ if (dev->lower.persist)
+ {
+ sensor_rpmsg_push_event_one(dev, stub);
+ }
+
return stub;
}
@@ -529,7 +560,7 @@ static int sensor_rpmsg_open(FAR struct file *filep,
}
}
- if (filep->f_oflags & O_REMOTE)
+ if (filep->f_oflags & SENSOR_REMOTE)
{
return 0;
}
@@ -571,7 +602,7 @@ static int sensor_rpmsg_close(FAR struct file *filep,
ret = drv->ops->close(filep, drv);
}
- if (filep->f_oflags & O_REMOTE)
+ if (filep->f_oflags & SENSOR_REMOTE)
{
return ret;
}
@@ -646,7 +677,7 @@ static int sensor_rpmsg_control(FAR struct file *filep,
{
return drv->ops->control(filep, drv, cmd, arg);
}
- else if (!(filep->f_oflags & O_REMOTE) && _SNIOCVALID(cmd))
+ else if (!(filep->f_oflags & SENSOR_REMOTE) && _SNIOCVALID(cmd))
{
return sensor_rpmsg_ioctl(dev, cmd, arg,
sizeof(*ioctl) + ioctl->len, true);
@@ -838,7 +869,7 @@ static int sensor_rpmsg_adv_handler(FAR struct rpmsg_endpoint *ept,
return 0;
}
- proxy = sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer);
+ proxy = sensor_rpmsg_alloc_proxy(dev, ept, msg);
if (!proxy)
{
snerr("ERROR: adv alloc proxy failed:%s\n", dev->path);
@@ -866,8 +897,7 @@ static int sensor_rpmsg_advack_handler(FAR struct rpmsg_endpoint *ept,
FAR struct sensor_rpmsg_dev_s *dev;
dev = sensor_rpmsg_find_dev(msg->path);
- if (dev && (!dev->nadvertisers ||
- !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie)))
+ if (dev && !sensor_rpmsg_alloc_stub(dev, ept, msg->cookie))
{
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNADVERTISE);
snerr("ERROR: advack failed:%s\n", dev->path);
@@ -915,7 +945,7 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
int ret;
dev = sensor_rpmsg_find_dev(msg->path);
- if (!dev || !dev->nadvertisers)
+ if (!dev)
{
return 0;
}
@@ -930,6 +960,7 @@ static int sensor_rpmsg_sub_handler(FAR struct rpmsg_endpoint *ept,
msg->cookie = (uint64_t)(uintptr_t)dev;
msg->command = SENSOR_RPMSG_SUBSCRIBE_ACK;
msg->nbuffer = dev->lower.nbuffer;
+ msg->persist = dev->lower.persist;
ret = rpmsg_send(ept, msg, len);
if (ret < 0)
{
@@ -950,7 +981,7 @@ static int sensor_rpmsg_suback_handler(FAR struct rpmsg_endpoint *ept,
dev = sensor_rpmsg_find_dev(msg->path);
if (dev && (!dev->nsubscribers ||
- !sensor_rpmsg_alloc_proxy(dev, ept, msg->cookie, msg->nbuffer)))
+ !sensor_rpmsg_alloc_proxy(dev, ept, msg)))
{
sensor_rpmsg_advsub_one(dev, ept, SENSOR_RPMSG_UNSUBSCRIBE);
snerr("ERROR: suback failed:%s\n", dev->path);
diff --git a/drivers/sensors/usensor.c b/drivers/sensors/usensor.c
index ef203b51f4..a011b9a7f2 100644
--- a/drivers/sensors/usensor.c
+++ b/drivers/sensors/usensor.c
@@ -105,6 +105,7 @@ static int usensor_register(FAR struct usensor_context_s *usensor,
}
lower->driver.nbuffer = info->nbuffer;
+ lower->driver.persist = info->persist;
lower->driver.ops = &g_usensor_ops;
strcpy(lower->path, info->path);
ret = sensor_custom_register(&lower->driver, lower->path, info->esize);
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index ef0f2442a3..35172a6080 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -293,6 +293,11 @@
#define SENSOR_TYPE_COUNT 33
+/* The additional sensor open flags */
+
+#define SENSOR_REMOTE (1 << 31)
+#define SENSOR_PERSIST (1 << 30)
+
/****************************************************************************
* Inline Functions
****************************************************************************/
@@ -935,6 +940,12 @@ struct sensor_lowerhalf_s
/* The private opaque pointer to be passed to upper-layer during callback */
FAR void *priv;
+
+ /* The flag is used to indicate that the validity of sensor data is
+ * persistent, such as battery status information, switch information, etc.
+ */
+
+ bool persist;
};
/* This structure describes the state for the sensor device */
@@ -959,6 +970,12 @@ struct sensor_reginfo_s
FAR const char *path; /* The path of user sensor */
unsigned long esize; /* The element size of user sensor */
unsigned long nbuffer; /* The number of queue buffered elements */
+
+ /* The flag is used to indicate that the validity of sensor data
+ * is persistent.
+ */
+
+ bool persist;
};
#endif
[incubator-nuttx] 14/22: driver/sensor: update batch initial value
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 01254de1bf105f86a568ce302e5a53b54b065324
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 15 12:17:51 2022 +0800
driver/sensor: update batch initial value
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 68 +++++++++++++++++++++++++++++-------------------
1 file changed, 41 insertions(+), 27 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index fb22d1c855..45b67b011a 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -206,6 +206,8 @@ static int sensor_update_interval(FAR struct file *filep,
FAR struct sensor_lowerhalf_s *lower = upper->lower;
FAR struct sensor_user_s *tmp;
unsigned long min_interval = interval;
+ unsigned long min_latency = interval != ULONG_MAX ?
+ user->latency : ULONG_MAX;
int ret = 0;
if (interval == user->interval)
@@ -213,14 +215,9 @@ static int sensor_update_interval(FAR struct file *filep,
return 0;
}
- if (interval <= upper->state.min_interval)
- {
- goto update;
- }
-
list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
{
- if (tmp == user)
+ if (tmp == user || tmp->interval == ULONG_MAX)
{
continue;
}
@@ -229,26 +226,39 @@ static int sensor_update_interval(FAR struct file *filep,
{
min_interval = tmp->interval;
}
- }
-update:
- if (min_interval == upper->state.min_interval)
- {
- user->interval = interval;
- return ret;
+ if (min_latency > tmp->latency)
+ {
+ min_latency = tmp->latency;
+ }
}
- if (min_interval != ULONG_MAX && lower->ops->set_interval)
+ if (lower->ops->set_interval)
{
- ret = lower->ops->set_interval(lower, filep, &min_interval);
- if (ret < 0)
+ if (min_interval != ULONG_MAX &&
+ min_interval != upper->state.min_interval)
{
- return ret;
+ ret = lower->ops->set_interval(lower, filep, &min_interval);
+ if (ret < 0)
+ {
+ return ret;
+ }
+ }
+
+ if (min_latency == ULONG_MAX)
+ {
+ min_latency = 0;
}
- if (upper->state.min_latency != ULONG_MAX)
+ if (lower->ops->batch &&
+ (min_latency != upper->state.min_latency ||
+ (min_interval != upper->state.min_interval && min_latency)))
{
- lower->ops->batch(filep, lower, &upper->state.min_latency);
+ ret = lower->ops->batch(lower, filep, &min_latency);
+ if (ret >= 0)
+ {
+ upper->state.min_latency = min_latency;
+ }
}
}
@@ -268,13 +278,14 @@ static int sensor_update_latency(FAR struct file *filep,
unsigned long min_latency = latency;
int ret = 0;
- if (upper->state.min_interval == 0)
+ if (latency == user->latency)
{
- return -EINVAL;
+ return 0;
}
- if (latency == user->latency)
+ if (user->interval == ULONG_MAX)
{
+ user->latency = latency;
return 0;
}
@@ -285,7 +296,7 @@ static int sensor_update_latency(FAR struct file *filep,
list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
{
- if (tmp == user)
+ if (tmp == user || tmp->interval == ULONG_MAX)
{
continue;
}
@@ -297,13 +308,18 @@ static int sensor_update_latency(FAR struct file *filep,
}
update:
+ if (min_latency == ULONG_MAX)
+ {
+ min_latency = 0;
+ }
+
if (min_latency == upper->state.min_latency)
{
user->latency = latency;
return ret;
}
- if (min_latency != ULONG_MAX && lower->ops->batch)
+ if (lower->ops->batch)
{
ret = lower->ops->batch(lower, filep, &min_latency);
if (ret < 0)
@@ -413,9 +429,8 @@ static int sensor_open(FAR struct file *filep)
user->generation = upper->state.generation;
}
- user->interval = ULONG_MAX;
- user->latency = ULONG_MAX;
- user->readlast = true;
+ user->interval = ULONG_MAX;
+ user->readlast = true;
nxsem_init(&user->buffersem, 0, 0);
nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
list_add_tail(&upper->userlist, &user->node);
@@ -993,7 +1008,6 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
list_initialize(&upper->userlist);
upper->state.esize = esize;
upper->state.min_interval = ULONG_MAX;
- upper->state.min_latency = ULONG_MAX;
if (lower->ops->activate)
{
upper->state.nadvertisers = 1;
[incubator-nuttx] 21/22: driver/sensor: fix rpmsg send failed when buffer is NULL
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit ad20bd4bb35361a633169dec4557811b38197742
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Wed Jun 29 17:34:55 2022 +0800
driver/sensor: fix rpmsg send failed when buffer is NULL
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 76 ++++++++++++++++++++++++------------------
drivers/sensors/sensor_rpmsg.c | 14 ++++----
include/nuttx/sensors/ioctl.h | 7 ++++
include/nuttx/sensors/sensor.h | 10 ++++++
4 files changed, 67 insertions(+), 40 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index cd8b06eccc..6e793801af 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -84,9 +84,7 @@ struct sensor_user_s
* appear in dual role
*/
- unsigned long generation; /* Last generation subscriber has seen */
- unsigned long interval; /* The interval for subscriber */
- unsigned long latency; /* The bactch latency for subscriber */
+ struct sensor_ustate_s state;
};
/* This structure describes the state of the upper half driver */
@@ -200,29 +198,29 @@ static int sensor_update_interval(FAR struct file *filep,
FAR struct sensor_user_s *tmp;
unsigned long min_interval = interval;
unsigned long min_latency = interval != ULONG_MAX ?
- user->latency : ULONG_MAX;
+ user->state.latency : ULONG_MAX;
int ret = 0;
- if (interval == user->interval)
+ if (interval == user->state.interval)
{
return 0;
}
list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
{
- if (tmp == user || tmp->interval == ULONG_MAX)
+ if (tmp == user || tmp->state.interval == ULONG_MAX)
{
continue;
}
- if (min_interval > tmp->interval)
+ if (min_interval > tmp->state.interval)
{
- min_interval = tmp->interval;
+ min_interval = tmp->state.interval;
}
- if (min_latency > tmp->latency)
+ if (min_latency > tmp->state.latency)
{
- min_latency = tmp->latency;
+ min_latency = tmp->state.latency;
}
}
@@ -261,7 +259,7 @@ static int sensor_update_interval(FAR struct file *filep,
}
upper->state.min_interval = min_interval;
- user->interval = interval;
+ user->state.interval = interval;
sensor_pollnotify(upper, POLLPRI);
return ret;
}
@@ -276,14 +274,14 @@ static int sensor_update_latency(FAR struct file *filep,
unsigned long min_latency = latency;
int ret = 0;
- if (latency == user->latency)
+ if (latency == user->state.latency)
{
return 0;
}
- if (user->interval == ULONG_MAX)
+ if (user->state.interval == ULONG_MAX)
{
- user->latency = latency;
+ user->state.latency = latency;
return 0;
}
@@ -294,14 +292,14 @@ static int sensor_update_latency(FAR struct file *filep,
list_for_every_entry(&upper->userlist, tmp, struct sensor_user_s, node)
{
- if (tmp == user || tmp->interval == ULONG_MAX)
+ if (tmp == user || tmp->state.interval == ULONG_MAX)
{
continue;
}
- if (min_latency > tmp->latency)
+ if (min_latency > tmp->state.latency)
{
- min_latency = tmp->latency;
+ min_latency = tmp->state.latency;
}
}
@@ -313,7 +311,7 @@ update:
if (min_latency == upper->state.min_latency)
{
- user->latency = latency;
+ user->state.latency = latency;
return ret;
}
@@ -327,7 +325,7 @@ update:
}
upper->state.min_latency = min_latency;
- user->latency = latency;
+ user->state.latency = latency;
sensor_pollnotify(upper, POLLPRI);
return ret;
}
@@ -348,13 +346,13 @@ static void sensor_generate_timing(FAR struct sensor_upperhalf_s *upper,
static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper,
FAR struct sensor_user_s *user)
{
- long delta = upper->state.generation - user->generation;
+ long delta = upper->state.generation - user->state.generation;
if (delta <= 0)
{
return false;
}
- else if (user->interval == ULONG_MAX)
+ else if (user->state.interval == ULONG_MAX)
{
return true;
}
@@ -368,7 +366,8 @@ static bool sensor_is_updated(FAR struct sensor_upperhalf_s *upper,
* next generation user want
*/
- return delta >= user->interval - (upper->state.min_interval >> 1);
+ return delta >= user->state.interval -
+ (upper->state.min_interval >> 1);
}
}
@@ -379,18 +378,19 @@ static void sensor_catch_up(FAR struct sensor_upperhalf_s *upper,
long delta;
circbuf_peek(&upper->timing, &generation, TIMING_BUF_ESIZE);
- delta = generation - user->generation;
+ delta = generation - user->state.generation;
if (delta > 0)
{
user->bufferpos = upper->timing.tail / TIMING_BUF_ESIZE;
- if (user->interval == ULONG_MAX)
+ if (user->state.interval == ULONG_MAX)
{
- user->generation = generation - 1;
+ user->state.generation = generation - 1;
}
else
{
delta -= upper->state.min_interval >> 1;
- user->generation += ROUND_DOWN(delta, user->interval);
+ user->state.generation += ROUND_DOWN(delta,
+ user->state.interval);
}
}
}
@@ -416,7 +416,7 @@ static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
/* Take samples continuously */
- if (user->interval == ULONG_MAX)
+ if (user->state.interval == ULONG_MAX)
{
ret = circbuf_peekat(&upper->buffer,
user->bufferpos * upper->state.esize,
@@ -424,7 +424,7 @@ static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
user->bufferpos += nums;
circbuf_peekat(&upper->timing,
(user->bufferpos - 1) * TIMING_BUF_ESIZE,
- &user->generation, TIMING_BUF_ESIZE);
+ &user->state.generation, TIMING_BUF_ESIZE);
return ret;
}
@@ -465,14 +465,14 @@ static ssize_t sensor_do_samples(FAR struct sensor_upperhalf_s *upper,
}
delta = next_generation + generation -
- ((user->generation + user->interval) << 1);
+ ((user->state.generation + user->state.interval) << 1);
if (delta >= 0)
{
ret += circbuf_peekat(&upper->buffer,
(pos - 1) * upper->state.esize,
buffer + ret, upper->state.esize);
user->bufferpos = pos;
- user->generation += user->interval;
+ user->state.generation += user->state.interval;
if (ret >= len)
{
break;
@@ -573,16 +573,17 @@ static int sensor_open(FAR struct file *filep)
if (upper->state.generation && lower->persist)
{
- user->generation = upper->state.generation - 1;
+ user->state.generation = upper->state.generation - 1;
user->bufferpos = upper->timing.head / TIMING_BUF_ESIZE - 1;
}
else
{
- user->generation = upper->state.generation;
+ user->state.generation = upper->state.generation;
user->bufferpos = upper->timing.head / TIMING_BUF_ESIZE;
}
- user->interval = ULONG_MAX;
+ user->state.interval = ULONG_MAX;
+ user->state.esize = upper->state.esize;
nxsem_init(&user->buffersem, 0, 0);
nxsem_set_protocol(&user->buffersem, SEM_PRIO_NONE);
list_add_tail(&upper->userlist, &user->node);
@@ -748,6 +749,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
}
break;
+ case SNIOC_GET_USTATE:
+ {
+ nxrmutex_lock(&upper->lock);
+ memcpy((FAR void *)(uintptr_t)arg,
+ &user->state, sizeof(user->state));
+ nxrmutex_unlock(&upper->lock);
+ }
+ break;
+
case SNIOC_SET_INTERVAL:
{
nxrmutex_lock(&upper->lock);
diff --git a/drivers/sensors/sensor_rpmsg.c b/drivers/sensors/sensor_rpmsg.c
index 2b608d3f3e..0243119f3a 100644
--- a/drivers/sensors/sensor_rpmsg.c
+++ b/drivers/sensors/sensor_rpmsg.c
@@ -726,22 +726,22 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
FAR struct sensor_rpmsg_cell_s *cell;
FAR struct sensor_rpmsg_ept_s *sre;
FAR struct sensor_rpmsg_data_s *msg;
- struct sensor_state_s state;
+ struct sensor_ustate_s state;
uint64_t now;
bool updated;
int ret;
/* Get state of device to do send data with timeout */
- ret = file_ioctl(&stub->file, SNIOC_GET_STATE, &state);
+ ret = file_ioctl(&stub->file, SNIOC_GET_USTATE, &state);
if (ret < 0)
{
return;
}
- if (state.min_interval == ULONG_MAX)
+ if (state.interval == ULONG_MAX)
{
- state.min_interval = 0;
+ state.interval = 0;
}
sre = container_of(stub->ept, struct sensor_rpmsg_ept_s, ept);
@@ -807,7 +807,7 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
*/
now = sensor_get_timestamp();
- if (sre->expire <= now)
+ if (sre->expire <= now && sre->buffer)
{
ret = rpmsg_send_nocopy(&sre->ept, sre->buffer, sre->written);
sre->buffer = NULL;
@@ -820,9 +820,9 @@ static void sensor_rpmsg_push_event_one(FAR struct sensor_rpmsg_dev_s *dev,
else
{
if (sre->expire == UINT64_MAX ||
- sre->expire - now > state.min_interval / 2)
+ sre->expire - now > state.interval / 2)
{
- sre->expire = now + state.min_interval / 2;
+ sre->expire = now + state.interval / 2;
}
work_queue(HPWORK, &sre->work, sensor_rpmsg_data_worker, sre,
diff --git a/include/nuttx/sensors/ioctl.h b/include/nuttx/sensors/ioctl.h
index 992367cc14..403bac1a28 100644
--- a/include/nuttx/sensors/ioctl.h
+++ b/include/nuttx/sensors/ioctl.h
@@ -334,4 +334,11 @@
#define SNIOC_UPDATED _SNIOC(0x0091)
+/* Command: SNIOC_GET_USTATE
+ * Description: Get state for user.
+ * Argument: This is the state pointer(struct sensor_state_s)
+ */
+
+#define SNIOC_GET_USTATE _SNIOC(0x0092)
+
#endif /* __INCLUDE_NUTTX_SENSORS_IOCTL_H */
diff --git a/include/nuttx/sensors/sensor.h b/include/nuttx/sensors/sensor.h
index 8af4eca43f..e58f41d3af 100644
--- a/include/nuttx/sensors/sensor.h
+++ b/include/nuttx/sensors/sensor.h
@@ -975,6 +975,16 @@ struct sensor_state_s
FAR void *priv; /* The pointer to private data of userspace user */
};
+/* This structure describes the state for the sensor user */
+
+struct sensor_ustate_s
+{
+ unsigned long esize; /* The element size of circular buffer */
+ unsigned long latency; /* The batch latency for user, in us */
+ unsigned long interval; /* The subscription interval for user, in us */
+ unsigned long generation; /* The recent generation of circular buffer */
+};
+
/* This structure describes the register info for the user sensor */
#ifdef CONFIG_USENSOR
[incubator-nuttx] 06/22: driver/sensor: using re-entrant mutex for sensor access to avoid deadlock
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 2a910b7ca9661cdcd2a691d809b2bedde4a7d2f0
Author: Jiuzhu Dong <do...@xiaomi.com>
AuthorDate: Fri Apr 29 23:08:59 2022 +0800
driver/sensor: using re-entrant mutex for sensor access to avoid deadlock
Signed-off-by: Jiuzhu Dong <do...@xiaomi.com>
---
drivers/sensors/sensor.c | 130 +++++++++++++++++++++++++----------------------
1 file changed, 68 insertions(+), 62 deletions(-)
diff --git a/drivers/sensors/sensor.c b/drivers/sensors/sensor.c
index 1bcb977393..93fba9e504 100644
--- a/drivers/sensors/sensor.c
+++ b/drivers/sensors/sensor.c
@@ -95,6 +95,8 @@ struct sensor_upperhalf_s
struct sensor_state_s state; /* The state of sensor device */
struct circbuf_s buffer; /* The circular buffer of sensor device */
sem_t exclsem; /* Manages exclusive access to file operations */
+ pid_t semholder; /* The current holder of the semaphore */
+ int16_t semcount; /* Number of counts held */
struct list_node userlist; /* List of users */
};
@@ -176,6 +178,38 @@ static const struct file_operations g_sensor_fops =
* Private Functions
****************************************************************************/
+static void sensor_semtake(FAR struct sensor_upperhalf_s *upper)
+{
+ pid_t pid = gettid();
+
+ if (pid == upper->semholder)
+ {
+ upper->semcount++;
+ }
+ else
+ {
+ nxsem_wait_uninterruptible(&upper->exclsem);
+ upper->semholder = pid;
+ upper->semcount = 1;
+ }
+}
+
+static void sensor_semgive(FAR struct sensor_upperhalf_s *upper)
+{
+ DEBUGASSERT(upper->semholder == gettid());
+
+ if (upper->semcount > 1)
+ {
+ upper->semcount--;
+ }
+ else
+ {
+ upper->semholder = INVALID_PROCESS_ID;
+ upper->semcount = 0;
+ nxsem_post(&upper->exclsem);
+ }
+}
+
static bool sensor_in_range(unsigned long left, unsigned long value,
unsigned long right)
{
@@ -356,14 +390,9 @@ static int sensor_open(FAR struct file *filep)
FAR struct sensor_upperhalf_s *upper = inode->i_private;
FAR struct sensor_lowerhalf_s *lower = upper->lower;
FAR struct sensor_user_s *user;
- int ret;
-
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
+ int ret = 0;
+ sensor_semtake(upper);
user = kmm_zalloc(sizeof(struct sensor_user_s));
if (user == NULL)
{
@@ -423,7 +452,7 @@ errout_with_open:
errout_with_user:
kmm_free(user);
errout_with_sem:
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
return ret;
}
@@ -433,20 +462,15 @@ static int sensor_close(FAR struct file *filep)
FAR struct sensor_upperhalf_s *upper = inode->i_private;
FAR struct sensor_lowerhalf_s *lower = upper->lower;
FAR struct sensor_user_s *user = filep->f_priv;
- int ret;
-
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
+ int ret = 0;
+ sensor_semtake(upper);
if (lower->ops->close)
{
ret = lower->ops->close(lower, filep);
if (ret < 0)
{
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
return ret;
}
}
@@ -473,7 +497,7 @@ static int sensor_close(FAR struct file *filep)
/* The user is closed, notify to other users */
sensor_pollnotify(upper, POLLPRI);
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
kmm_free(user);
return ret;
@@ -494,28 +518,19 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
return -EINVAL;
}
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
-
+ sensor_semtake(upper);
if (lower->ops->fetch)
{
if (!(filep->f_oflags & O_NONBLOCK))
{
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
ret = nxsem_wait_uninterruptible(&user->buffersem);
if (ret < 0)
{
return ret;
}
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
+ sensor_semtake(upper);
}
else if (!upper->state.nsubscribers)
{
@@ -564,14 +579,14 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
}
else
{
- nxmutex_unlock(&upper->lock);
+ sensor_semgive(upper);
ret = nxsem_wait_uninterruptible(&user->buffersem);
if (ret < 0)
{
return ret;
}
- nxmutex_lock(&upper->lock);
+ sensor_semtake(upper);
}
}
}
@@ -601,7 +616,7 @@ static ssize_t sensor_read(FAR struct file *filep, FAR char *buffer,
}
out:
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
return ret;
}
@@ -621,35 +636,35 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
FAR struct sensor_upperhalf_s *upper = inode->i_private;
FAR struct sensor_lowerhalf_s *lower = upper->lower;
FAR struct sensor_user_s *user = filep->f_priv;
- int ret;
+ int ret = 0;
sninfo("cmd=%x arg=%08lx\n", cmd, arg);
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
-
switch (cmd)
{
case SNIOC_GET_STATE:
{
+ sensor_semtake(upper);
memcpy((FAR void *)(uintptr_t)arg,
&upper->state, sizeof(upper->state));
user->changed = false;
+ sensor_semgive(upper);
}
break;
case SNIOC_SET_INTERVAL:
{
+ sensor_semtake(upper);
ret = sensor_update_interval(filep, upper, user, arg);
+ sensor_semgive(upper);
}
break;
case SNIOC_BATCH:
{
+ sensor_semtake(upper);
ret = sensor_update_latency(filep, upper, user, arg);
+ sensor_semgive(upper);
}
break;
@@ -691,12 +706,15 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
case SNIOC_SET_USERPRIV:
{
+ sensor_semtake(upper);
upper->state.priv = (FAR void *)(uintptr_t)arg;
+ sensor_semgive(upper);
}
break;
case SNIOC_SET_BUFFER_NUMBER:
{
+ sensor_semtake(upper);
if (!circbuf_is_init(&upper->buffer))
{
if (arg >= lower->nbuffer)
@@ -712,6 +730,8 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{
ret = -EBUSY;
}
+
+ sensor_semgive(upper);
}
break;
@@ -739,7 +759,6 @@ static int sensor_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
break;
}
- nxsem_post(&upper->exclsem);
return ret;
}
@@ -752,14 +771,9 @@ static int sensor_poll(FAR struct file *filep,
FAR struct sensor_user_s *user = filep->f_priv;
pollevent_t eventset = 0;
int semcount;
- int ret;
-
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
+ int ret = 0;
+ sensor_semtake(upper);
if (setup)
{
/* Don't have enough space to store fds */
@@ -811,7 +825,7 @@ static int sensor_poll(FAR struct file *filep,
}
errout:
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
return ret;
}
@@ -831,12 +845,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
return -EINVAL;
}
- ret = nxsem_wait(&upper->exclsem);
- if (ret < 0)
- {
- return ret;
- }
-
+ sensor_semtake(upper);
if (!circbuf_is_init(&upper->buffer))
{
/* Initialize sensor buffer when data is first generated */
@@ -845,7 +854,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
upper->state.esize);
if (ret < 0)
{
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
return ret;
}
}
@@ -866,7 +875,7 @@ static ssize_t sensor_push_event(FAR void *priv, FAR const void *data,
}
}
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
return bytes;
}
@@ -876,11 +885,7 @@ static void sensor_notify_event(FAR void *priv)
FAR struct sensor_user_s *user;
int semcount;
- if (nxsem_wait(&upper->exclsem) < 0)
- {
- return;
- }
-
+ sensor_semtake(upper);
list_for_every_entry(&upper->userlist, user, struct sensor_user_s, node)
{
nxsem_get_value(&user->buffersem, &semcount);
@@ -892,7 +897,7 @@ static void sensor_notify_event(FAR void *priv)
sensor_pollnotify_one(user, POLLIN);
}
- nxsem_post(&upper->exclsem);
+ sensor_semgive(upper);
}
/****************************************************************************
@@ -996,6 +1001,7 @@ int sensor_custom_register(FAR struct sensor_lowerhalf_s *lower,
upper->state.nadvertisers = 1;
}
+ upper->semholder = INVALID_PROCESS_ID;
nxsem_init(&upper->exclsem, 0, 1);
/* Bind the lower half data structure member */