From fa4cebce32e477590bd6c643807e71487436d5f5 Mon Sep 17 00:00:00 2001 From: Jiuzhu Dong Date: Sat, 21 May 2022 17:50:29 +0800 Subject: [PATCH] driver/sensor: support sensor data persist Signed-off-by: Jiuzhu Dong --- 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