This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 80a04ea953170a6eafbbdb7827fbcbb9bf05e5d7
Author: raiden00pl <[email protected]>
AuthorDate: Tue Jul 14 19:59:55 2026 +0200

    drivers/analog: add digital potentiometer driver support
    
    Add a common upper-half character driver for digital potentiometers
    with a generic set of ioctl commands (wiper set/get, terminal control,
    device properties) that can be shared by chip-specific lower halves.
    
    Signed-off-by: raiden00pl <[email protected]>
    Assisted-by: Claude Code
---
 .../components/drivers/character/analog/index.rst  |   1 +
 .../drivers/character/analog/pot/index.rst         |  63 +++
 drivers/analog/CMakeLists.txt                      |   7 +
 drivers/analog/Kconfig                             |  10 +
 drivers/analog/Make.defs                           |  16 +
 drivers/analog/pot.c                               | 422 +++++++++++++++++++++
 include/nuttx/analog/ioctl.h                       |   5 +
 include/nuttx/analog/pot.h                         | 222 +++++++++++
 8 files changed, 746 insertions(+)

diff --git a/Documentation/components/drivers/character/analog/index.rst 
b/Documentation/components/drivers/character/analog/index.rst
index 7d65b773725..c4c026ff065 100644
--- a/Documentation/components/drivers/character/analog/index.rst
+++ b/Documentation/components/drivers/character/analog/index.rst
@@ -26,4 +26,5 @@ The NuttX analog drivers are split into two parts:
 
   adc/index.rst
   dac/index.rst
+  pot/index.rst
 
diff --git a/Documentation/components/drivers/character/analog/pot/index.rst 
b/Documentation/components/drivers/character/analog/pot/index.rst
new file mode 100644
index 00000000000..829626ef178
--- /dev/null
+++ b/Documentation/components/drivers/character/analog/pot/index.rst
@@ -0,0 +1,63 @@
+======================
+Digital Potentiometers
+======================
+
+The digital potentiometer driver is split into an "upper half" character
+driver (``drivers/analog/pot.c``) and chip-specific "lower half" drivers.
+The application interface is defined in ``include/nuttx/analog/pot.h``.
+
+Device model
+============
+
+A potentiometer is modeled as a set of wipers, each with a position in
+``[0, max]``. Optional capabilities are advertised in ``pot_info_s.caps``
+so applications can discover what a given chip supports instead of
+probing commands:
+
+- ``POT_CAP_READBACK`` - wiper position can be read back
+- ``POT_CAP_MOVE`` - relative wiper move (the only interface available on
+  up/down-pin devices without readback, e.g. Renesas X9C10x)
+- ``POT_CAP_ENABLE`` - wiper enable/shutdown
+- ``POT_CAP_NV`` - non-volatile wiper store/recall
+
+If ``pot_info_s.rab`` (terminal A-B resistance in ohms) is non-zero, the
+wiper resistance is ``ohms = val * rab / max``. The value is supplied by
+board logic to the lower half initializer, since the resistance variant
+of a chip is not runtime-discoverable.
+
+Application interface
+=====================
+
+All commands take a pointer argument. Optional commands return
+``-ENOTSUP`` when the lower half does not implement them.
+
+======================== ========================== =====================
+IOCTL                    Argument                   Description
+======================== ========================== =====================
+``POTIOC_GET_INFO``      ``struct pot_info_s *``    Device properties
+``POTIOC_SET_WIPER``     ``struct pot_wiper_s *``   Set wiper position
+``POTIOC_GET_WIPER``     ``struct pot_wiper_s *``   Get wiper position
+``POTIOC_MOVE_WIPER``    ``struct pot_move_s *``    Move wiper by signed
+                                                    number of steps
+``POTIOC_SET_ENABLE``    ``struct pot_enable_s *``  Enable or shut down
+                                                    a wiper
+``POTIOC_STORE_WIPER``   ``struct pot_nv_s *``      Store wiper to a
+                                                    non-volatile slot
+``POTIOC_RECALL_WIPER``  ``struct pot_nv_s *``      Recall wiper from a
+                                                    non-volatile slot
+======================== ========================== =====================
+
+Vendor-specific features (e.g. per-terminal switches, register access,
+wiper lock) are not part of the common interface: lower halves expose
+them through chip-specific ioctl commands forwarded via ``po_ioctl``.
+
+Supported chips
+===============
+
+========== ===== ====================================================
+Chip       Bus   Notes
+========== ===== ====================================================
+MCP445X    I2C   Quad wiper, 257 taps. Terminal control via the
+                 ``ANIOC_MCP445X_*`` ioctls, see
+                 ``include/nuttx/analog/mcp445x.h``.
+========== ===== ====================================================
diff --git a/drivers/analog/CMakeLists.txt b/drivers/analog/CMakeLists.txt
index 47abb53ad82..bbd09c3c80f 100644
--- a/drivers/analog/CMakeLists.txt
+++ b/drivers/analog/CMakeLists.txt
@@ -64,6 +64,13 @@ if(CONFIG_OPAMP)
   list(APPEND SRCS opamp.c)
 endif()
 
+# Check for POT devices
+
+if(CONFIG_POT)
+  # Include the common POT character driver
+  list(APPEND SRCS pot.c)
+endif()
+
 # Check for ADC devices
 
 if(CONFIG_ADC)
diff --git a/drivers/analog/Kconfig b/drivers/analog/Kconfig
index c4f588fdf10..3161e2a234a 100644
--- a/drivers/analog/Kconfig
+++ b/drivers/analog/Kconfig
@@ -486,6 +486,16 @@ config MCP48XX_SPI_FREQUENCY
 
 endif # DAC
 
+config POT
+       bool "Digital Potentiometer"
+       default n
+       ---help---
+               Select to enable support for digital potentiometers.
+
+if POT
+
+endif # POT
+
 config OPAMP
        bool "Operational Amplifier"
        default n
diff --git a/drivers/analog/Make.defs b/drivers/analog/Make.defs
index 02a420cdbff..e60ba808d44 100644
--- a/drivers/analog/Make.defs
+++ b/drivers/analog/Make.defs
@@ -74,6 +74,16 @@ CSRCS += opamp.c
 
 endif
 
+# Check for POT devices
+
+ifeq ($(CONFIG_POT),y)
+
+# Include the common POT character driver
+
+CSRCS += pot.c
+
+endif
+
 # Check for ADC devices
 
 ifeq ($(CONFIG_ADC),y)
@@ -152,6 +162,12 @@ ifeq ($(CONFIG_OPAMP),y)
   DEPPATH += --dep-path analog
   VPATH += :analog
   CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)analog
+else
+ifeq ($(CONFIG_POT),y)
+  DEPPATH += --dep-path analog
+  VPATH += :analog
+  CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)drivers$(DELIM)analog
+endif
 endif
 endif
 endif
diff --git a/drivers/analog/pot.c b/drivers/analog/pot.c
new file mode 100644
index 00000000000..03ddb2d6745
--- /dev/null
+++ b/drivers/analog/pot.c
@@ -0,0 +1,422 @@
+/****************************************************************************
+ * drivers/analog/pot.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 <sys/types.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <errno.h>
+#include <nuttx/debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/analog/pot.h>
+
+#include <nuttx/irq.h>
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int pot_open(FAR struct file *filep);
+static int pot_close(FAR struct file *filep);
+static int pot_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_pot_fops =
+{
+  pot_open,                      /* open */
+  pot_close,                     /* close */
+  NULL,                          /* read */
+  NULL,                          /* write */
+  NULL,                          /* seek */
+  pot_ioctl,                     /* ioctl */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pot_open
+ *
+ * Description:
+ *   This function is called whenever the potentiometer device is opened.
+ *
+ ****************************************************************************/
+
+static int pot_open(FAR struct file *filep)
+{
+  FAR struct inode     *inode = filep->f_inode;
+  FAR struct pot_dev_s *dev   = inode->i_private;
+  uint8_t               tmp;
+  int                   ret;
+
+  /* If the port is the middle of closing, wait until the close is
+   * finished.
+   */
+
+  ret = nxmutex_lock(&dev->pd_closelock);
+  if (ret >= 0)
+    {
+      /* Increment the count of references to the device.  If this is the
+       * first time that the driver has been opened for this device, then
+       * initialize the device.
+       */
+
+      tmp = dev->pd_ocount + 1;
+      if (tmp == 0)
+        {
+          /* More than 255 opens; uint8_t overflows to zero */
+
+          ret = -EMFILE;
+        }
+      else
+        {
+          /* Check if this is the first time that the driver has been
+           * opened.
+           */
+
+          if (tmp == 1)
+            {
+              /* Yes.. perform one time hardware initialization. */
+
+              ret = dev->pd_ops->po_setup(dev);
+              if (ret == OK)
+                {
+                  /* Save the new open count on success */
+
+                  dev->pd_ocount = tmp;
+                }
+            }
+        }
+
+      nxmutex_unlock(&dev->pd_closelock);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pot_close
+ *
+ * Description:
+ *   This routine is called when the potentiometer device is closed.
+ *
+ ****************************************************************************/
+
+static int pot_close(FAR struct file *filep)
+{
+  FAR struct inode     *inode = filep->f_inode;
+  FAR struct pot_dev_s *dev   = inode->i_private;
+  int                   ret;
+
+  ret = nxmutex_lock(&dev->pd_closelock);
+  if (ret >= 0)
+    {
+      /* Decrement the references to the driver.  If the reference count
+       * will decrement to 0, then uninitialize the driver.
+       */
+
+      if (dev->pd_ocount > 1)
+        {
+          dev->pd_ocount--;
+        }
+      else
+        {
+          /* There are no more references to the port */
+
+          dev->pd_ocount = 0;
+
+          /* Disable the potentiometer device */
+
+          dev->pd_ops->po_shutdown(dev);
+        }
+
+      nxmutex_unlock(&dev->pd_closelock);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pot_ioctl
+ ****************************************************************************/
+
+static int pot_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode     *inode = filep->f_inode;
+  FAR struct pot_dev_s *dev   = inode->i_private;
+  int                   ret   = OK;
+
+  ret = nxmutex_lock(&dev->pd_lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  switch (cmd)
+    {
+      /* Get the device properties */
+
+      case POTIOC_GET_INFO:
+        {
+          FAR struct pot_info_s *info =
+            (FAR struct pot_info_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(info != NULL);
+          info->nwipers = dev->pd_nwipers;
+          info->max     = dev->pd_max;
+          info->rab     = dev->pd_rab;
+          info->caps    = 0;
+
+          if (dev->pd_ops->po_getwiper)
+            {
+              info->caps |= POT_CAP_READBACK;
+            }
+
+          if (dev->pd_ops->po_move)
+            {
+              info->caps |= POT_CAP_MOVE;
+            }
+
+          if (dev->pd_ops->po_enable)
+            {
+              info->caps |= POT_CAP_ENABLE;
+            }
+
+          if (dev->pd_ops->po_store || dev->pd_ops->po_recall)
+            {
+              info->caps |= POT_CAP_NV;
+            }
+
+          break;
+        }
+
+      /* Set a wiper value */
+
+      case POTIOC_SET_WIPER:
+        {
+          FAR struct pot_wiper_s *wiper =
+            (FAR struct pot_wiper_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(wiper != NULL);
+          if (wiper->wiper >= dev->pd_nwipers || wiper->val > dev->pd_max)
+            {
+              ret = -EINVAL;
+            }
+          else if (dev->pd_ops->po_setwiper == NULL)
+            {
+              ret = -ENOTSUP;
+            }
+          else
+            {
+              ret = dev->pd_ops->po_setwiper(dev, wiper->wiper, wiper->val);
+            }
+
+          break;
+        }
+
+      /* Get a wiper value */
+
+      case POTIOC_GET_WIPER:
+        {
+          FAR struct pot_wiper_s *wiper =
+            (FAR struct pot_wiper_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(wiper != NULL);
+          if (wiper->wiper >= dev->pd_nwipers)
+            {
+              ret = -EINVAL;
+            }
+          else if (dev->pd_ops->po_getwiper == NULL)
+            {
+              ret = -ENOTSUP;
+            }
+          else
+            {
+              ret = dev->pd_ops->po_getwiper(dev, wiper->wiper, &wiper->val);
+            }
+
+          break;
+        }
+
+      /* Move a wiper by a number of steps */
+
+      case POTIOC_MOVE_WIPER:
+        {
+          FAR struct pot_move_s *move =
+            (FAR struct pot_move_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(move != NULL);
+          if (move->wiper >= dev->pd_nwipers)
+            {
+              ret = -EINVAL;
+            }
+          else if (dev->pd_ops->po_move == NULL)
+            {
+              ret = -ENOTSUP;
+            }
+          else
+            {
+              ret = dev->pd_ops->po_move(dev, move->wiper, move->steps);
+            }
+
+          break;
+        }
+
+      /* Enable or force a wiper into shutdown */
+
+      case POTIOC_SET_ENABLE:
+        {
+          FAR struct pot_enable_s *enable =
+            (FAR struct pot_enable_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(enable != NULL);
+          if (enable->wiper >= dev->pd_nwipers)
+            {
+              ret = -EINVAL;
+            }
+          else if (dev->pd_ops->po_enable == NULL)
+            {
+              ret = -ENOTSUP;
+            }
+          else
+            {
+              ret = dev->pd_ops->po_enable(dev, enable->wiper,
+                                           enable->enable);
+            }
+
+          break;
+        }
+
+      /* Store a wiper value to a non-volatile slot */
+
+      case POTIOC_STORE_WIPER:
+        {
+          FAR struct pot_nv_s *nv = (FAR struct pot_nv_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(nv != NULL);
+          if (nv->wiper >= dev->pd_nwipers)
+            {
+              ret = -EINVAL;
+            }
+          else if (dev->pd_ops->po_store == NULL)
+            {
+              ret = -ENOTSUP;
+            }
+          else
+            {
+              ret = dev->pd_ops->po_store(dev, nv->wiper, nv->slot);
+            }
+
+          break;
+        }
+
+      /* Recall a wiper value from a non-volatile slot */
+
+      case POTIOC_RECALL_WIPER:
+        {
+          FAR struct pot_nv_s *nv = (FAR struct pot_nv_s *)((uintptr_t)arg);
+
+          DEBUGASSERT(nv != NULL);
+          if (nv->wiper >= dev->pd_nwipers)
+            {
+              ret = -EINVAL;
+            }
+          else if (dev->pd_ops->po_recall == NULL)
+            {
+              ret = -ENOTSUP;
+            }
+          else
+            {
+              ret = dev->pd_ops->po_recall(dev, nv->wiper, nv->slot);
+            }
+
+          break;
+        }
+
+      /* Forward any unrecognized commands to the lower half */
+
+      default:
+        {
+          if (dev->pd_ops->po_ioctl)
+            {
+              ret = dev->pd_ops->po_ioctl(dev, cmd, arg);
+            }
+          else
+            {
+              ret = -ENOTTY;
+            }
+
+          break;
+        }
+    }
+
+  nxmutex_unlock(&dev->pd_lock);
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pot_register
+ ****************************************************************************/
+
+int pot_register(FAR const char *path, FAR struct pot_dev_s *dev)
+{
+  int ret;
+
+  DEBUGASSERT(dev != NULL && dev->pd_ops != NULL);
+
+  /* Initialize the potentiometer device structure */
+
+  dev->pd_ocount = 0;
+
+  /* Initialize mutexes */
+
+  nxmutex_init(&dev->pd_closelock);
+  nxmutex_init(&dev->pd_lock);
+
+  /* Register the potentiometer character driver */
+
+  ret = register_driver(path, &g_pot_fops, 0666, dev);
+  if (ret < 0)
+    {
+      nxmutex_destroy(&dev->pd_closelock);
+      nxmutex_destroy(&dev->pd_lock);
+    }
+
+  return ret;
+}
diff --git a/include/nuttx/analog/ioctl.h b/include/nuttx/analog/ioctl.h
index abe46ec90ee..683c4185cf5 100644
--- a/include/nuttx/analog/ioctl.h
+++ b/include/nuttx/analog/ioctl.h
@@ -151,6 +151,11 @@
 #define AN_ADS7046_FIRST  (AN_MCP47X6_FIRST + AN_MCP47X6_NCMDS)
 #define AN_ADS7046_NCMDS  3
 
+/* See include/nuttx/analog/pot.h */
+
+#define AN_POT_FIRST      (AN_ADS7046_FIRST + AN_ADS7046_NCMDS)
+#define AN_POT_NCMDS      16
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
diff --git a/include/nuttx/analog/pot.h b/include/nuttx/analog/pot.h
new file mode 100644
index 00000000000..ed431f93ee7
--- /dev/null
+++ b/include/nuttx/analog/pot.h
@@ -0,0 +1,222 @@
+/****************************************************************************
+ * include/nuttx/analog/pot.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_ANALOG_POT_H
+#define __INCLUDE_NUTTX_ANALOG_POT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/compiler.h>
+#include <nuttx/analog/ioctl.h>
+#include <nuttx/mutex.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* IOCTL Commands ***********************************************************/
+
+/* Common IOCTL commands for all digital potentiometer drivers. Optional
+ * commands return -ENOTSUP if not implemented by the lower half; support
+ * is advertised in pot_info_s caps.
+ *
+ * Cmd: POTIOC_GET_INFO      Arg: struct pot_info_s *info
+ * Cmd: POTIOC_SET_WIPER     Arg: struct pot_wiper_s *wiper
+ * Cmd: POTIOC_GET_WIPER     Arg: struct pot_wiper_s *wiper
+ * Cmd: POTIOC_MOVE_WIPER    Arg: struct pot_move_s *move
+ * Cmd: POTIOC_SET_ENABLE    Arg: struct pot_enable_s *enable
+ * Cmd: POTIOC_STORE_WIPER   Arg: struct pot_nv_s *nv
+ * Cmd: POTIOC_RECALL_WIPER  Arg: struct pot_nv_s *nv
+ */
+
+#define POTIOC_GET_INFO     _ANIOC(AN_POT_FIRST + 0)
+#define POTIOC_SET_WIPER    _ANIOC(AN_POT_FIRST + 1)
+#define POTIOC_GET_WIPER    _ANIOC(AN_POT_FIRST + 2)
+#define POTIOC_MOVE_WIPER   _ANIOC(AN_POT_FIRST + 3)
+#define POTIOC_SET_ENABLE   _ANIOC(AN_POT_FIRST + 4)
+#define POTIOC_STORE_WIPER  _ANIOC(AN_POT_FIRST + 5)
+#define POTIOC_RECALL_WIPER _ANIOC(AN_POT_FIRST + 6)
+
+/* Device capabilities reported in pot_info_s */
+
+#define POT_CAP_READBACK    (1 << 0)  /* Wiper position can be read back */
+#define POT_CAP_MOVE        (1 << 1)  /* Relative wiper move supported */
+#define POT_CAP_ENABLE      (1 << 2)  /* Wiper enable/shutdown supported */
+#define POT_CAP_NV          (1 << 3)  /* Non-volatile store/recall supported */
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Device properties for POTIOC_GET_INFO */
+
+struct pot_info_s
+{
+  uint8_t  nwipers;              /* Number of wipers */
+  uint32_t max;                  /* Wiper full scale position */
+  uint32_t rab;                  /* Terminal A-B resistance in ohms,
+                                  * 0 if unknown. ohms = val * rab / max */
+  uint32_t caps;                 /* Capabilities, see POT_CAP_* */
+};
+
+/* Wiper access for POTIOC_SET_WIPER and POTIOC_GET_WIPER */
+
+struct pot_wiper_s
+{
+  uint8_t  wiper;                /* Wiper index */
+  uint32_t val;                  /* Wiper value */
+};
+
+/* Relative wiper move for POTIOC_MOVE_WIPER */
+
+struct pot_move_s
+{
+  uint8_t wiper;                 /* Wiper index */
+  int32_t steps;                 /* Steps to move, negative moves down */
+};
+
+/* Wiper enable control for POTIOC_SET_ENABLE */
+
+struct pot_enable_s
+{
+  uint8_t wiper;                 /* Wiper index */
+  bool    enable;                /* false forces wiper into shutdown */
+};
+
+/* Non-volatile transfer for POTIOC_STORE_WIPER and POTIOC_RECALL_WIPER */
+
+struct pot_nv_s
+{
+  uint8_t wiper;                 /* Wiper index */
+  uint8_t slot;                  /* Non-volatile slot index */
+};
+
+struct pot_dev_s;
+struct pot_ops_s
+{
+  /* Configure the potentiometer. This method is called the first time
+   * that the potentiometer device is opened.
+   */
+
+  CODE int (*po_setup)(FAR struct pot_dev_s *dev);
+
+  /* Disable the potentiometer. This method is called when the
+   * potentiometer device is closed. This method reverses the operation
+   * of the setup method.
+   */
+
+  CODE void (*po_shutdown)(FAR struct pot_dev_s *dev);
+
+  /* Set a wiper value. Optional. */
+
+  CODE int (*po_setwiper)(FAR struct pot_dev_s *dev, uint8_t wiper,
+                          uint32_t val);
+
+  /* Get a wiper value. Optional. */
+
+  CODE int (*po_getwiper)(FAR struct pot_dev_s *dev, uint8_t wiper,
+                          FAR uint32_t *val);
+
+  /* Move a wiper by a number of steps, negative moves down. Optional. */
+
+  CODE int (*po_move)(FAR struct pot_dev_s *dev, uint8_t wiper,
+                      int32_t steps);
+
+  /* Enable or force a wiper into shutdown. Optional. */
+
+  CODE int (*po_enable)(FAR struct pot_dev_s *dev, uint8_t wiper,
+                        bool enable);
+
+  /* Store a wiper value to a non-volatile slot. Optional. */
+
+  CODE int (*po_store)(FAR struct pot_dev_s *dev, uint8_t wiper,
+                       uint8_t slot);
+
+  /* Recall a wiper value from a non-volatile slot. Optional. */
+
+  CODE int (*po_recall)(FAR struct pot_dev_s *dev, uint8_t wiper,
+                        uint8_t slot);
+
+  /* Lower-half logic may support chip-specific ioctl commands */
+
+  CODE int (*po_ioctl)(FAR struct pot_dev_s *dev, int cmd,
+                       unsigned long arg);
+};
+
+struct pot_dev_s
+{
+  /* Fields managed by common upper half potentiometer logic */
+
+  uint8_t                    pd_ocount;    /* The number of times the device
+                                            * has been opened */
+  mutex_t                    pd_closelock; /* Locks out new opens while close
+                                            * is in progress */
+  mutex_t                    pd_lock;      /* Serializes ioctl access */
+
+  /* Fields provided by lower half potentiometer logic */
+
+  uint8_t                    pd_nwipers;   /* Number of wipers */
+  uint32_t                   pd_max;       /* Wiper full scale value */
+  uint32_t                   pd_rab;       /* A-B resistance in ohms,
+                                            * 0 if unknown */
+  FAR const struct pot_ops_s *pd_ops;      /* Arch-specific operations */
+  FAR void                   *pd_priv;     /* Used by the arch-specific
+                                            * logic */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Name: pot_register
+ *
+ * Description:
+ *   Register a digital potentiometer driver.
+ *
+ * Input Parameters:
+ *   path - The full path to the driver to register, e.g. "/dev/pot0"
+ *   dev  - An instance of the device-specific potentiometer interface
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int pot_register(FAR const char *path, FAR struct pot_dev_s *dev);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __INCLUDE_NUTTX_ANALOG_POT_H */

Reply via email to