/****************************************************************************
 * include/nuttx/sensors/cluster_driver.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_SENSORS_CLUSTER_DRIVER_H
#define __INCLUDE_NUTTX_SENSORS_CLUSTER_DRIVER_H

/* Definitions for the cluster driver interface:
 *
 * The sensor cluster driver interface is created to permit high performance
 * collection and processing of sensor data. Normally when high performance
 * sensor data collection is required, data is needed from multiple sensors
 * and the collection/processing task needs to run as a "higher than user
 * priority" priority level. This mechanism is commonly supported by writing
 * the collection/processing task as a kernel driver worker thread that can
 * access multiple sensors.
 *
 * A clean way to implement this is to implement this collection/processing
 * mechanism is as a driver that has efficient kernel-to-kernel access to
 * other sensor leaf-drivers that support the cluster driver interface.
 * (This documentation describes the "cluster driver interface" from the
 * perspective of a "cluster driver interface" enabled leaf driver.)
 *
 * The file_operations interface typically deals with the caller's parameters
 * and buffers being in user space, while the driver's code, variables, and
 * buffers are in kernel space. There is also a layer of kernel code between
 *  the caller and driver that deals with security and assists helps with the
 * driver's access of user space memory. So the file_operations interface
 * is not appropriate for driver-to-driver communication.
 *
 * Since the driver registration function is not part of the file_operations
 * interface and is permitted to be called from a kernel task, this function
 * is reused. But rather than being called by the board initialization
 * function, the cluster drivers registration function is called from the
 * board initialization function; and the cluster drivers registration
 * function calls the leaf driver's registration function.
 *
 * To be "cluster driver interface" enabled the leaf driver's registration
 * function must communicate the leaf driver's instance back to the cluster
 * driver's registration function. This is done by storing the leaf
 * driver's instance handle into the caller provided config structure.
 * This handle is provided as a parameter in cluster driver interface calls.
 *
 * dvr_open(): Reserve this sensor.
 *
 * dvr_close(): Places the sensor into low power standby mode, frees driver
 *   resources associated with the sensor, and release the reservation
 *   . of the sensor.
 *
 * To perform I/O to a sensor, the cluster driver needs...
 *
 * > A pointer to the spi instance (struct spi_dev_s *). The cluster driver
 *   has this pointer, because it provides it to the leaf driver as an input
 *   parameter to the leaf driver's registration function.
 * > The chip select gpio pin identifier for the sensor device. The cluster
 *   driver knows this identifier,because it provides it to the leaf driver
 *   as an input parameter to the leaf driver's registration function.
 * > A pointer to the leaf driver instance. The leaf driver communicates this
 *   pointer to the cluster driver by storing it into the config struct
 *   leaf_handle (struct spi_dev_s *) field that is also passed as an in/out
 *   parameter in the leaf driver's registration function.
 *
 * With the above information, the sensor cluster driver may efficiently
 * access multiple sensors and aggregate their data.
 *
 ****************************************************************************/

/****************************************************************************
 * Public Types
 ****************************************************************************/

/* Cluster driver operations interface */

struct sensor_cluster_operations_s
{
  CODE int (*driver_open)(FAR void *instance_handle, int32_t arg);
  CODE int (*driver_close)(FAR void *instance_handle, int32_t arg);
  CODE ssize_t (*driver_read)(FAR void *instance_handle, FAR char *buffer,
            size_t buflen);
  CODE ssize_t (*driver_write)(FAR void *instance_handle,
            FAR const char *buffer, size_t buflen);
  CODE off_t (*driver_seek)(FAR void *instance_handle, off_t offset,
            int whence);
  CODE int (*driver_ioctl)(FAR void *instance_handle, int cmd,
            unsigned long arg);
  CODE int (*driver_suspend)(FAR void *instance_handle, int32_t arg);
  CODE int (*driver_resume)(FAR void *instance_handle, int32_t arg);
};

/****************************************************************************
 * Public Function Prototypes
 ****************************************************************************/

#ifdef __cplusplus
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif

/****************************************************************************
 * Name: xxxxxx_register   <-- for a leaf driver.
 *
 * Description:
 *   Example of a driver register function for a "sensor leaf driver" that
 *   can be controlled by a "sensor cluster driver".  The specific format of
 *   the registration function will vary based on the characteristics of the
 *   driver. The below is an example, which describes common aspects of the
 *   function and and its parameters.
 *
 *   Normally, sensor driver register functions are called by the board
 *   initialization code. In the case of a "sensor cluster driver", the board
 *   initialization code calls the register function of the "sensor cluster
 *   driver"; and the "sensor cluster driver" calls the register function of
 *   each of the sensor (leaf) drivers that it will be controlling.
 *
 * Input Parameters:
 *   devpath  - The full path to the leaf driver to register. E.g.,
 *           "/dev/acl0"
 *   spi      - An instance of the SPI interface to use to communicate with
 *              the leaf driver. Or, it could be the I2C driver instance if
 *              the sensor is on an I2C bus.
 *   config   - configuration struct for the sensor leaf driver.
 *              This struct is defined in the leaf driver's xxxxxx.h file.
 *
 *  For a SPI sensor, this structure must contain:
 *
 *   int spi_devid;   The spi device id, which is used by NuttX to
 *        select/deselect the device. This is usually some
 *        type of reference to the chip_select gpio pin.
 *   FAR void *leaf_handle; The handle to the leaf driver instance.
 *        This is an opaque handle that provided by the
 *        leaf driver's register function.
 *        It is passed as a parameter to the leaf driver's
 *        driver_open() and driver_close() functions.
 *
 *  For an I2C sensor, this struct must contain:
 *
 *   int i2c_devid;   The i2c device id, which is used by NuttX to
 *        address the sensor device on an I2C bus..
 *   FAR void *leaf_handle; The handle to the leaf driver instance.
 *        This is an opaque handle that provided by the
 *        leaf driver's register function.
 *        It is passed as a parameter to the leaf driver's
 *        driver_open() and driver_close() functions.
 *
 * Returned Value:
 *   Zero (OK) on success; a negated errno value on failure.
 *
 * int xxxxxx_register(FAR const char *devpath,
 *                     FAR struct spi_dev_s *spi,
 *                     FAR struct xxxxxx_config_s *config);
 *
 ****************************************************************************/

#undef EXTERN
#ifdef __cplusplus
}
#endif

#endif /* __INCLUDE_NUTTX_SENSORS_CLUSTER_DRIVER_H */
