From 0d95d6fa456c0f7fb45e36ccba511538d109b179 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Wed, 29 Sep 2021 10:56:56 +0800 Subject: [PATCH] battery_charger:add poll support Signed-off-by: anjiahao --- drivers/power/battery_charger.c | 218 ++++++++++++++++++++++++-- include/nuttx/power/battery_charger.h | 10 ++ include/nuttx/power/battery_ioctl.h | 9 ++ 3 files changed, 227 insertions(+), 10 deletions(-) diff --git a/drivers/power/battery_charger.c b/drivers/power/battery_charger.c index a5e898b778..173176ae42 100644 --- a/drivers/power/battery_charger.c +++ b/drivers/power/battery_charger.c @@ -28,9 +28,13 @@ #include #include +#include #include +#include +#include #include +#include #include #include @@ -46,9 +50,18 @@ ****************************************************************************/ /**************************************************************************** - * Private + * Private type ****************************************************************************/ +struct battery_charger_priv_s +{ + struct list_node node; + sem_t lock; + sem_t wait; + uint32_t mask; + FAR struct pollfd *fds; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ @@ -58,11 +71,13 @@ static int bat_charger_open(FAR struct file *filep); static int bat_charger_close(FAR struct file *filep); static ssize_t bat_charger_read(FAR struct file *filep, FAR char *buffer, - size_t buflen); + size_t buflen); static ssize_t bat_charger_write(FAR struct file *filep, - FAR const char *buffer, size_t buflen); + FAR const char *buffer, size_t buflen); static int bat_charger_ioctl(FAR struct file *filep, int cmd, - unsigned long arg); + unsigned long arg); +static int bat_charger_poll(FAR struct file *filep, + FAR struct pollfd *fds, bool setup); /**************************************************************************** * Private Data @@ -76,13 +91,48 @@ static const struct file_operations g_batteryops = bat_charger_write, NULL, bat_charger_ioctl, - NULL + bat_charger_poll, }; /**************************************************************************** * Private Functions ****************************************************************************/ +static int battery_charger_notify(FAR struct battery_charger_priv_s *priv, + uint32_t mask) +{ + FAR struct pollfd *fd = priv->fds; + int semcnt; + int ret; + + ret = nxsem_wait_uninterruptible(&priv->lock); + if (ret < 0) + { + return ret; + } + + priv->mask |= mask; + if (priv->mask) + { + fd->revents |= POLLIN; + nxsem_get_value(fd->sem, &semcnt); + if (semcnt < 1) + { + nxsem_post(fd->sem); + } + + nxsem_get_value(&priv->wait, &semcnt); + if (semcnt < 1) + { + nxsem_post(&priv->wait); + } + } + + nxsem_post(&priv->lock); + + return OK; +} + /**************************************************************************** * Name: bat_charger_open * @@ -93,7 +143,31 @@ static const struct file_operations g_batteryops = static int bat_charger_open(FAR struct file *filep) { - return OK; + FAR struct battery_charger_priv_s *priv; + FAR struct battery_charger_dev_s *dev = filep->f_inode->i_private; + int ret; + + priv = kmm_zalloc(sizeof(*priv)); + if (priv == NULL) + { + return -ENOMEM; + } + + ret = nxsem_wait(&dev->batsem); + if (ret < 0) + { + kmm_free(priv); + return ret; + } + + nxsem_init(&priv->lock, 0, 1); + nxsem_init(&priv->wait, 0, 0); + nxsem_set_protocol(&priv->wait, SEM_PRIO_NONE); + list_add_tail(&dev->flist, &priv->node); + nxsem_post(&dev->batsem); + filep->f_priv = priv; + + return ret; } /**************************************************************************** @@ -106,7 +180,23 @@ static int bat_charger_open(FAR struct file *filep) static int bat_charger_close(FAR struct file *filep) { - return OK; + FAR struct battery_charger_priv_s *priv = filep->f_priv; + FAR struct battery_charger_dev_s *dev = filep->f_inode->i_private; + int ret; + + ret = nxsem_wait(&dev->batsem); + if (ret < 0) + { + return ret; + } + + list_delete(&priv->node); + nxsem_post(&dev->batsem); + nxsem_destroy(&priv->lock); + nxsem_destroy(&priv->wait); + kmm_free(priv); + + return ret; } /**************************************************************************** @@ -116,9 +206,46 @@ static int bat_charger_close(FAR struct file *filep) static ssize_t bat_charger_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { - /* Return nothing read */ + FAR struct battery_charger_priv_s *priv = filep->f_priv; + int ret; - return 0; + if (buflen < sizeof(priv->mask)) + { + return -EINVAL; + } + + ret = nxsem_wait(&priv->lock); + if (ret < 0) + { + return ret; + } + + while (priv->mask == 0) + { + nxsem_post(&priv->lock); + if (filep->f_oflags & O_NONBLOCK) + { + return -EAGAIN; + } + + ret = nxsem_wait(&priv->wait); + if (ret < 0) + { + return ret; + } + + ret = nxsem_wait(&priv->lock); + if (ret < 0) + { + return ret; + } + } + + memcpy(buffer, &priv->mask, sizeof(priv->mask)); + priv->mask = 0; + + nxsem_post(&priv->lock); + return sizeof(priv->mask); } /**************************************************************************** @@ -243,10 +370,80 @@ static int bat_charger_ioctl(FAR struct file *filep, int cmd, return ret; } +/**************************************************************************** + * Name: bat_charger_poll + ****************************************************************************/ + +static ssize_t bat_charger_poll(FAR struct file *filep, + struct pollfd *fds, bool setup) +{ + FAR struct battery_charger_priv_s *priv = filep->f_priv; + int ret; + + ret = nxsem_wait(&priv->lock); + if (ret < 0) + { + return ret; + } + + if (setup) + { + if (priv->fds == NULL) + { + priv->fds = fds; + fds->priv = &priv->fds; + } + else + { + ret = -EBUSY; + } + } + else if (fds->priv != NULL) + { + priv->fds = NULL; + fds->priv = NULL; + } + + nxsem_post(&priv->lock); + + if (setup) + { + battery_charger_notify(priv, 0); + } + + return ret; +} + /**************************************************************************** * Public Functions ****************************************************************************/ +/**************************************************************************** + * Name: battery_charger_changed + ****************************************************************************/ + +int battery_charger_changed(FAR struct battery_charger_dev_s *dev, + uint32_t mask) +{ + FAR struct battery_charger_priv_s *priv; + int ret; + + ret = nxsem_wait_uninterruptible(&dev->batsem); + if (ret < 0) + { + return ret; + } + + list_for_every_entry(&dev->flist, priv, + struct battery_charger_priv_s, node) + { + battery_charger_notify(priv, mask); + } + + nxsem_post(&dev->batsem); + return OK; +} + /**************************************************************************** * Name: battery_charger_register * @@ -269,9 +466,10 @@ int battery_charger_register(FAR const char *devpath, { int ret; - /* Initialize the semaphore */ + /* Initialize the semaphore and the list */ nxsem_init(&dev->batsem, 0, 1); + list_initialize(&dev->flist); /* Register the character driver */ diff --git a/include/nuttx/power/battery_charger.h b/include/nuttx/power/battery_charger.h index bd841b194f..5ad01c1253 100644 --- a/include/nuttx/power/battery_charger.h +++ b/include/nuttx/power/battery_charger.h @@ -29,6 +29,7 @@ #include #include #include +#include #include @@ -127,6 +128,8 @@ struct battery_charger_dev_s sem_t batsem; /* Enforce mutually exclusive access */ + struct list_node flist; + /* Data fields specific to the lower-half driver may follow */ }; @@ -148,6 +151,13 @@ extern "C" * Public Function Prototypes ****************************************************************************/ +/**************************************************************************** + * Name: battery_charger_changed + ****************************************************************************/ + +int battery_charger_changed(FAR struct battery_charger_dev_s *dev, + uint32_t mask); + /**************************************************************************** * Name: battery_charger_register * diff --git a/include/nuttx/power/battery_ioctl.h b/include/nuttx/power/battery_ioctl.h index df91d56b58..237918d1c1 100644 --- a/include/nuttx/power/battery_ioctl.h +++ b/include/nuttx/power/battery_ioctl.h @@ -61,6 +61,15 @@ #define BATTERY_INPUT_CURRENT_EXT_LIM (-1) /* External input current limit */ +/* The change mask definition used to set the mask. */ + +#define BATTERY_STATE_CHANGED (1U << 0) +#define BATTERY_HEALTH_CHANGED (1U << 1) +#define BATTERY_ONLINE_CHANGED (1U << 2) +#define BATTERY_VOLTAGE_CHANGED (1U << 3) +#define BATTERY_CURRENT_CHANGED (1U << 4) +#define BATTERY_INPUT_CURRENT_CHANGED (1U << 5) + /**************************************************************************** * Public Types ****************************************************************************/