From 069fac1c676ea14b01c9187e14bc36c38e7565ad Mon Sep 17 00:00:00 2001 From: wangbowen6 Date: Thu, 22 Dec 2022 11:39:29 +0800 Subject: [PATCH] power/relay: add relay driver framework for NuttX Signed-off-by: wangbowen6 --- drivers/power/Kconfig | 1 + drivers/power/Make.defs | 1 + drivers/power/relay/Kconfig | 18 ++++ drivers/power/relay/Make.defs | 30 ++++++ drivers/power/relay/relay.c | 164 +++++++++++++++++++++++++++++++ drivers/power/relay/relay_gpio.c | 148 ++++++++++++++++++++++++++++ include/nuttx/power/relay.h | 90 ++++++++++++++++- 7 files changed, 448 insertions(+), 4 deletions(-) create mode 100644 drivers/power/relay/Kconfig create mode 100644 drivers/power/relay/Make.defs create mode 100644 drivers/power/relay/relay.c create mode 100644 drivers/power/relay/relay_gpio.c diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 08842264a2..b76c448413 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -6,3 +6,4 @@ source "drivers/power/pm/Kconfig" source "drivers/power/battery/Kconfig" source "drivers/power/supply/Kconfig" +source "drivers/power/relay/Kconfig" diff --git a/drivers/power/Make.defs b/drivers/power/Make.defs index a7fe01b1f7..002149f333 100644 --- a/drivers/power/Make.defs +++ b/drivers/power/Make.defs @@ -21,3 +21,4 @@ include power/pm/Make.defs include power/battery/Make.defs include power/supply/Make.defs +include power/relay/Make.defs diff --git a/drivers/power/relay/Kconfig b/drivers/power/relay/Kconfig new file mode 100644 index 0000000000..8e00e3bfc6 --- /dev/null +++ b/drivers/power/relay/Kconfig @@ -0,0 +1,18 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +menu "Relay Support" + +config RELAY + bool "Relay driver support" + default n + +config RELAY_GPIO + bool "Relay gpio driver support" + default n + depends on RELAY + depends on IOEXPANDER + +endmenu diff --git a/drivers/power/relay/Make.defs b/drivers/power/relay/Make.defs new file mode 100644 index 0000000000..511d52f610 --- /dev/null +++ b/drivers/power/relay/Make.defs @@ -0,0 +1,30 @@ +############################################################################ +# drivers/power/relay/Make.defs +# +# 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. +# +############################################################################ + +ifeq ($(CONFIG_RELAY),y) +CSRCS += relay.c +endif + +ifeq ($(CONFIG_RELAY_GPIO),y) +CSRCS += relay_gpio.c +endif + +DEPPATH += --dep-path power/relay +VPATH += power/relay diff --git a/drivers/power/relay/relay.c b/drivers/power/relay/relay.c new file mode 100644 index 0000000000..86a12c8d30 --- /dev/null +++ b/drivers/power/relay/relay.c @@ -0,0 +1,164 @@ +/**************************************************************************** + * drivers/power/relay/relay.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 + +#include + +#include + +#include +#include +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static ssize_t relay_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static ssize_t relay_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen); +static int relay_ioctl(FAR struct file *filep, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations g_relay_ops = +{ + NULL, /* open */ + NULL, /* close */ + relay_read, /* read */ + relay_write, /* write */ + NULL, /* seek */ + relay_ioctl, /* ioctl */ + NULL /* poll */ +#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS + , NULL /* unlink */ +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static ssize_t relay_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) +{ + return 0; +} + +static ssize_t relay_write(FAR struct file *filep, FAR const char *buffer, + size_t buflen) +{ + return 0; +} + +static int relay_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct relay_dev_s *dev; + FAR struct inode *inode; + int ret; + + DEBUGASSERT(filep != NULL && filep->f_inode != NULL); + inode = filep->f_inode; + DEBUGASSERT(inode->i_private != NULL); + dev = inode->i_private; + + ret = nxmutex_lock(&dev->lock); + if (ret < 0) + { + return ret; + } + + switch (cmd) + { + case RELAYIOC_SET: + { + FAR bool *enable = (FAR bool *)((uintptr_t)arg); + DEBUGASSERT(enable != NULL); + ret = dev->ops->set(dev, *enable); + } + break; + + case RELAYIOC_GET: + DEBUGASSERT(arg != 0); + ret = dev->ops->get(dev, (FAR bool *)((uintptr_t)arg)); + break; + + default: + if (dev->ops->ioctl != NULL) + { + ret = dev->ops->ioctl(dev, cmd, arg); + } + else + { + ret = -ENOTSUP; + } + break; + } + + nxmutex_unlock(&dev->lock); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: relay_register + * + * Description: + * Register the relay driver to the vfs. + * + * Input Parameters: + * dev - the relay device + * devname - the relay device name + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int relay_register(FAR struct relay_dev_s *dev, FAR const char *devname) +{ + DEBUGASSERT(devname != NULL); + DEBUGASSERT(dev != NULL && dev->ops != NULL); + + if (dev->ops->set == NULL || dev->ops->get == NULL) + { + return -EINVAL; + } + + nxmutex_init(&dev->lock); + + return register_driver(devname, &g_relay_ops, 0666, dev); +} diff --git a/drivers/power/relay/relay_gpio.c b/drivers/power/relay/relay_gpio.c new file mode 100644 index 0000000000..6cc870099a --- /dev/null +++ b/drivers/power/relay/relay_gpio.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * drivers/power/relay/relay_gpio.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 + +#include + +#include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct relay_gpio_priv +{ + struct relay_dev_s dev; + FAR struct ioexpander_dev_s *iodev; + uint8_t iopin; + bool ioinvert; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int relay_gpio_set(FAR struct relay_dev_s *dev, bool enable); +static int relay_gpio_get(FAR struct relay_dev_s *dev, FAR bool *enable); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct relay_ops_s g_relay_gpio_ops = +{ + relay_gpio_set, /* set */ + relay_gpio_get, /* get */ + NULL, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int relay_gpio_set(FAR struct relay_dev_s *dev, bool enable) +{ + FAR struct relay_gpio_priv *priv = (FAR struct relay_gpio_priv *)dev; + + return IOEXP_WRITEPIN(priv->iodev, priv->iopin, enable ^ priv->ioinvert); +} + +static int relay_gpio_get(FAR struct relay_dev_s *dev, FAR bool *enable) +{ + FAR struct relay_gpio_priv *priv = (FAR struct relay_gpio_priv *)dev; + bool val; + int ret; + + ret = IOEXP_READPIN(priv->iodev, priv->iopin, &val); + if (ret < 0) + { + return ret; + } + + *enable = val ^ priv->ioinvert; + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: relay_gpio_register + * + * Description: + * Register the relay device based on the ioexpander device + * + * Input Parameters: + * iodev - The ioexpander dev pointer. + * iopin - The relay gpio pin number. + * ioinvert - true : enable (relay close) is low , disable (relay open) + * is high. + * false: enable (rekat close) is high, disable (relay open) + * is low. + * devname - The relay device name. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int relay_gpio_register(FAR struct ioexpander_dev_s *iodev, uint8_t iopin, + bool ioinvert, FAR const char *devname) +{ + FAR struct relay_gpio_priv *priv; + int ret; + + DEBUGASSERT(iodev != NULL && devname != NULL); + + priv = kmm_zalloc(sizeof(struct relay_gpio_priv)); + if (priv == NULL) + { + return -ENOMEM; + } + + priv->iodev = iodev; + priv->iopin = iopin; + priv->ioinvert = ioinvert; + priv->dev.ops = &g_relay_gpio_ops; + + ret = relay_register(&priv->dev, devname); + if (ret < 0) + { + goto errout; + } + + return ret; + +errout: + kmm_free(priv); + return ret; +} diff --git a/include/nuttx/power/relay.h b/include/nuttx/power/relay.h index ff3d8e4621..ae75f974e8 100644 --- a/include/nuttx/power/relay.h +++ b/include/nuttx/power/relay.h @@ -45,6 +45,7 @@ #include +#include #include /**************************************************************************** @@ -53,14 +54,95 @@ /* IOCTL Commands ***********************************************************/ -#define RELAYIOC_CTRL _RELAYIOC(0x0001) /* Relay control - * IN: unsigned long integer - * 0=open - * 1=close +#define RELAYIOC_SET _RELAYIOC(0x0001) /* Relay state set + * IN: pointer of bool + * false=disable, open + * true=enable, close * OUT: None */ +#define RELAYIOC_GET _RELAYIOC(0x0002) /* Relay state get + * IN: pointer of bool + * OUT: + * false=disable, open + * true=enable, close */ + /**************************************************************************** * Public Types ****************************************************************************/ +struct relay_dev_s; +struct relay_ops_s +{ + CODE int (*set)(FAR struct relay_dev_s *dev, bool onoff); + CODE int (*get)(FAR struct relay_dev_s *dev, FAR bool *onoff); + CODE int (*ioctl)(FAR struct relay_dev_s *dev, int cmd, + unsigned long arg); +}; + +struct relay_dev_s +{ + FAR const struct relay_ops_s *ops; + mutex_t lock; +}; + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: relay_register + * + * Description: + * Register the relay driver to the vfs. + * + * Input Parameters: + * dev - the relay device + * devname - the relay device name + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RELAY +int relay_register(FAR struct relay_dev_s *dev, FAR const char *devname); +#endif + +/**************************************************************************** + * Name: relay_gpio_register + * + * Description: + * Register the relay device based on the ioexpander device + * + * Input Parameters: + * iodev - The ioexpander dev pointer. + * iopin - The relay gpio pin number. + * ioinvert - true : enable (relay close) is low , disable (relay open) + * is high. + * false: enable (rekat close) is high, disable (relay open) + * is low. + * devname - The relay device name. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +#ifdef CONFIG_RELAY_GPIO +int relay_gpio_register(FAR struct ioexpander_dev_s *iodev, uint8_t iopin, + bool ioinvert, FAR const char *devname); +#endif + +#ifdef __cplusplus +} +#endif + #endif /* __INCLUDE_NUTTX_POWER_RELAY_H */