diff --git a/include/platform/dac_if.h b/include/platform/dac_if.h
new file mode 100644
index 0000000000000000000000000000000000000000..84dfeb73ae25dff1f096ed8a18c3be58567df3dc
--- /dev/null
+++ b/include/platform/dac_if.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+/**
+ * @addtogroup DAC
+ * @{
+ *
+ * @brief Provides Digital to analog converter (DAC) interfaces.
+ *
+ * This module allows a driver to perform operations on an DAC controller for accessing devices on the DAC channel,
+ * Including creating and destroying DAC controller handles and writing data
+ *
+ * @since 1.0
+ */
+/**
+ * @file dac_if.h
+ *
+ * @brief Declares the standard DAC interface functions.
+ *
+ * @since 1.0
+ */
+
+#ifndef DAC_IF_H
+#define DAC_IF_H
+
+#include "hdf_platform.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+struct DacIoMsg {
+ uint32_t number;
+ uint32_t channel;
+};
+
+ /**
+ * @brief Obtains the handle of an DAC controller.
+ *
+ * You must call this function before accessing the DAC CHANNEL.
+ *
+ * @param number Indicates the DAC controller ID.
+ *
+ * @return Returns the pointer to the {@link DevHandle} of the DAC controller if the operation is successful;
+ * returns NULL otherwise.
+ * @since 1.0
+ */
+DevHandle DacOpen(uint32_t number);
+
+ /**
+ * @brief Releases the handle of an DAC controller.
+ *
+ * If you no longer need to access the DAC controller, you should call this function to close its handle so as
+ * to release unused memory resources.
+ *
+ * @param handle Indicates the pointer to the device handle of the DAC controller.
+ *
+ * @since 1.0
+ */
+void DacClose(DevHandle handle);
+
+ /**
+ * @brief Start the DAC device for transmission and write the target value in the specified DAC channel.
+ *
+ * @param handle Indicates the pointer to the device handle of the DAC controller obtained via {@link DacOpen}.
+ * @param channel represents the channel through which the DAC transmits messages.
+ * @param val represents the set digital target value.
+ *
+ * @return Returns 0 if the operation is successful; Returns a negative value otherwise..
+ *
+ * @since 1.0
+ */
+int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif /* DAC_IF_H */
diff --git a/support/platform/include/dac/dac_core.h b/support/platform/include/dac/dac_core.h
new file mode 100644
index 0000000000000000000000000000000000000000..8c04f35cdb8293b026592a42739ade7bbbc892d8
--- /dev/null
+++ b/support/platform/include/dac/dac_core.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#ifndef DAC_CORE_H
+#define DAC_CORE_H
+
+#include "osal_spinlock.h"
+#include "hdf_base.h"
+#include "dac_if.h"
+#include "platform_core.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+#define DAC_DEVICES_MAX 15
+
+struct DacDevice;
+struct DacMethod;
+struct DacLockMethod;
+
+struct DacDevice {
+ const struct DacMethod *ops;
+ OsalSpinlock spin;
+ uint32_t devNum;
+ uint32_t chanNum;
+ const struct DacLockMethod *lockOps;
+ void *priv;
+};
+
+struct DacMethod {
+ int32_t (*write)(struct DacDevice *device, uint32_t channel, uint32_t val);
+ int32_t (*start)(struct DacDevice *device);
+ int32_t (*stop)(struct DacDevice *device);
+};
+
+struct DacLockMethod {
+ int32_t (*lock)(struct DacDevice *device);
+ void (*unlock)(struct DacDevice *device);
+};
+
+enum DacIoCmd {
+ DAC_IO_READ = 0,
+ DAC_IO_OPEN,
+ DAC_IO_CLOSE,
+};
+
+int32_t DacDeviceAdd(struct DacDevice *device);
+
+void DacDeviceRemove(struct DacDevice *device);
+
+struct DacDevice *DacDeviceGet(uint32_t number);
+
+void DacDevicePut(struct DacDevice *device);
+
+int32_t DacDeviceWrite(struct DacDevice *device, uint32_t channel, uint32_t val);
+
+int32_t DacDeviceStart(struct DacDevice *device);
+
+int32_t DacDeviceStop(struct DacDevice *device);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif /* DAC_CORE_H */
diff --git a/support/platform/src/dac/dac_core.c b/support/platform/src/dac/dac_core.c
new file mode 100644
index 0000000000000000000000000000000000000000..8bb3a6bcc2cb90f94d39745c6c660194b92a2a40
--- /dev/null
+++ b/support/platform/src/dac/dac_core.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include "dac_core.h"
+#include "hdf_device_desc.h"
+#include "hdf_log.h"
+#include "osal_mem.h"
+#include "osal_spinlock.h"
+#include "osal_time.h"
+#include "platform_core.h"
+
+#define HDF_LOG_TAG dac_core_c
+
+struct DacManager {
+ struct IDeviceIoService service;
+ struct HdfDeviceObject *device;
+ struct DacDevice *devices[DAC_DEVICES_MAX];
+ OsalSpinlock spin;
+};
+
+static struct DacManager *g_dacManager = NULL;
+
+static int32_t DacDeviceLockDefault(struct DacDevice *device)
+{
+ if (device == NULL) {
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ return OsalSpinLock(&device->spin);
+}
+
+static void DacDeviceUnlockDefault(struct DacDevice *device)
+{
+ if (device == NULL) {
+ return;
+ }
+ (void)OsalSpinUnlock(&device->spin);
+}
+
+static const struct DacLockMethod g_dacLockOpsDefault = {
+ .lock = DacDeviceLockDefault,
+ .unlock = DacDeviceUnlockDefault,
+};
+
+static int32_t DacManagerAddDevice(struct DacDevice *device)
+{
+ int32_t ret;
+ struct DacManager *manager = g_dacManager;
+
+ if (device->devNum >= DAC_DEVICES_MAX) {
+ HDF_LOGE("%s: devNum:%u exceed", __func__, device->devNum);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ if (manager == NULL) {
+ HDF_LOGE("%s: get dac manager fail", __func__);
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) {
+ HDF_LOGE("%s: lock dac manager fail", __func__);
+ return HDF_ERR_DEVICE_BUSY;
+ }
+
+ if (manager->devices[device->devNum] != NULL) {
+ HDF_LOGE("%s: dac device num:%u alwritey exits", __func__, device->devNum);
+ ret = HDF_FAILURE;
+ } else {
+ manager->devices[device->devNum] = device;
+ HDF_LOGE("%s: device:%p", __func__, manager->devices[0]);
+ ret = HDF_SUCCESS;
+ }
+
+ (void)OsalSpinUnlockIrq(&manager->spin);
+ return ret;
+}
+
+static void DacManagerRemoveDevice(struct DacDevice *device)
+{
+ struct DacManager *manager = g_dacManager;
+
+ if (device->devNum < 0 || device->devNum >= DAC_DEVICES_MAX) {
+ HDF_LOGE("%s: invalid devNum:%u", __func__, device->devNum);
+ return;
+ }
+
+ if (manager == NULL) {
+ HDF_LOGE("%s: get dac manager fail", __func__);
+ return;
+ }
+
+ if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) {
+ HDF_LOGE("%s: lock dac manager fail", __func__);
+ return;
+ }
+
+ if (manager->devices[device->devNum] != device) {
+ HDF_LOGE("%s: dac device(%u) not in manager", __func__, device->devNum);
+ } else {
+ manager->devices[device->devNum] = NULL;
+ }
+
+ (void)OsalSpinUnlockIrq(&manager->spin);
+}
+
+static struct DacDevice *DacManagerFindDevice(uint32_t number)
+{
+ struct DacDevice *device = NULL;
+ struct DacManager *manager = g_dacManager;
+
+ if (number < 0 || number >= DAC_DEVICES_MAX) {
+ HDF_LOGE("%s: invalid devNum:%u", __func__, number);
+ return NULL;
+ }
+
+ if (manager == NULL) {
+ HDF_LOGE("%s: get dac manager fail", __func__);
+ return NULL;
+ }
+
+ if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) {
+ HDF_LOGE("%s: lock dac manager fail", __func__);
+ return NULL;
+ }
+
+ device = manager->devices[number];
+ (void)OsalSpinUnlockIrq(&manager->spin);
+
+ return device;
+}
+
+int32_t DacDeviceAdd(struct DacDevice *device)
+{
+ int32_t ret;
+
+ if (device == NULL) {
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ if (device->ops == NULL) {
+ HDF_LOGE("%s: no ops supplied", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ if (device->lockOps == NULL) {
+ HDF_LOGI("%s: use default lockOps!", __func__);
+ device->lockOps = &g_dacLockOpsDefault;
+ }
+
+ if (OsalSpinInit(&device->spin) != HDF_SUCCESS) {
+ HDF_LOGE("%s: init lock failed", __func__);
+ return HDF_FAILURE;
+ }
+
+ ret = DacManagerAddDevice(device);
+ if (ret != HDF_SUCCESS) {
+ (void)OsalSpinDestroy(&device->spin);
+ }
+ return ret;
+}
+
+void DacDeviceRemove(struct DacDevice *device)
+{
+ if (device == NULL) {
+ return;
+ }
+ DacManagerRemoveDevice(device);
+ (void)OsalSpinDestroy(&device->spin);
+}
+
+struct DacDevice *DacDeviceGet(uint32_t number)
+{
+ return DacManagerFindDevice(number);
+}
+
+void DacDevicePut(struct DacDevice *device)
+{
+ (void)device;
+}
+
+static inline int32_t DacDeviceLock(struct DacDevice *device)
+{
+ if (device->lockOps == NULL || device->lockOps->lock == NULL) {
+ return HDF_ERR_NOT_SUPPORT;
+ }
+ return device->lockOps->lock(device);
+}
+
+static inline void DacDeviceUnlock(struct DacDevice *device)
+{
+ if (device->lockOps != NULL && device->lockOps->unlock != NULL) {
+ device->lockOps->unlock(device);
+ }
+}
+
+int32_t DacDeviceWrite(struct DacDevice *device, uint32_t channel, uint32_t val)
+{
+ int32_t ret;
+
+ if (device == NULL) {
+ HDF_LOGE("%s: device is null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ if (device->ops == NULL || device->ops->write == NULL) {
+ HDF_LOGE("%s: ops or write is null", __func__);
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ if (DacDeviceLock(device) != HDF_SUCCESS) {
+ HDF_LOGE("%s: lock add device failed", __func__);
+ return HDF_ERR_DEVICE_BUSY;
+ }
+
+ ret = device->ops->write(device, channel, val);
+ DacDeviceUnlock(device);
+ return ret;
+}
+
+int32_t DacDeviceStart(struct DacDevice *device)
+{
+ int32_t ret;
+
+ if (device == NULL) {
+ HDF_LOGE("%s: device is null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ if (device->ops == NULL || device->ops->start == NULL) {
+ HDF_LOGE("%s: ops or start is null", __func__);
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ if (DacDeviceLock(device) != HDF_SUCCESS) {
+ HDF_LOGE("%s: lock add device failed", __func__);
+ return HDF_ERR_DEVICE_BUSY;
+ }
+
+ ret = device->ops->start(device);
+ DacDeviceUnlock(device);
+ return ret;
+}
+
+int32_t DacDeviceStop(struct DacDevice *device)
+{
+ int32_t ret;
+
+ if (device == NULL) {
+ HDF_LOGE("%s: device is null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ if (device->ops == NULL || device->ops->stop == NULL) {
+ HDF_LOGE("%s: ops or stop is null", __func__);
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ if (DacDeviceLock(device) != HDF_SUCCESS) {
+ HDF_LOGE("%s: lock add device failed", __func__);
+ return HDF_ERR_DEVICE_BUSY;
+ }
+
+ ret = device->ops->stop(device);
+ DacDeviceUnlock(device);
+ return ret;
+}
+
+static int32_t DacManagerIoOpen(struct HdfSBuf *data, struct HdfSBuf *reply)
+{
+ uint32_t number;
+
+ if (!HdfSbufReadUint32(data, &number)) {
+ return HDF_ERR_IO;
+ }
+
+ if (number < 0 || number >= DAC_DEVICES_MAX || reply == NULL) {
+ return HDF_ERR_INVALID_PARAM;
+ }
+
+ if (DacDeviceGet(number) == NULL) {
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ if (!HdfSbufWriteUint32(reply, number)) {
+ return HDF_ERR_IO;
+ }
+ return HDF_SUCCESS;
+}
+
+static int32_t DacManagerIoClose(struct HdfSBuf *data, struct HdfSBuf *reply)
+{
+ uint32_t number;
+
+ if (!HdfSbufReadUint32(data, &number)) {
+ return HDF_ERR_IO;
+ }
+
+ if (number < 0 || number >= DAC_DEVICES_MAX) {
+ return HDF_ERR_INVALID_PARAM;
+ }
+ DacDevicePut(DacManagerFindDevice(number));
+ return HDF_SUCCESS;
+}
+
+static int32_t DacManagerIoRead(struct HdfSBuf *data, struct HdfSBuf *reply)
+{
+ (void)data;
+ (void)reply;
+ return HDF_SUCCESS;
+}
+
+static int32_t DacManagerDispatch(struct HdfDeviceIoClient *client, int cmd,
+ struct HdfSBuf *data, struct HdfSBuf *reply)
+{
+ int32_t ret;
+
+ switch (cmd) {
+ case DAC_IO_OPEN:
+ return DacManagerIoOpen(data, reply);
+ case DAC_IO_CLOSE:
+ return DacManagerIoClose(data, reply);
+ case DAC_IO_READ:
+ return DacManagerIoRead(data, reply);
+ default:
+ ret = HDF_ERR_NOT_SUPPORT;
+ break;
+ }
+ return ret;
+}
+
+static int32_t DacManagerInit(struct HdfDeviceObject *device)
+{
+ int32_t ret;
+ struct DacManager *manager = NULL;
+
+ if (device == NULL) {
+ HDF_LOGE("%s: device is null", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ manager = (struct DacManager *)OsalMemCalloc(sizeof(*manager));
+ if (manager == NULL) {
+ HDF_LOGE("%s: alloc manager failed", __func__);
+ return HDF_ERR_MALLOC_FAIL;
+ }
+
+ ret = OsalSpinInit(&manager->spin);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: spinlock init failed", __func__);
+ OsalMemFree(manager);
+ return HDF_FAILURE;
+ }
+
+ manager->device = device;
+ g_dacManager = manager;
+ device->service = &manager->service;
+ device->service->Dispatch = DacManagerDispatch;
+ return HDF_SUCCESS;
+}
+
+static void DacManagerRelease(struct HdfDeviceObject *device)
+{
+ struct DacManager *manager = NULL;
+
+ if (device == NULL) {
+ HDF_LOGE("%s: device is null", __func__);
+ return;
+ }
+
+ manager = (struct DacManager *)device->service;
+ if (manager == NULL) {
+ HDF_LOGI("%s: no service bind", __func__);
+ return;
+ }
+
+ g_dacManager = NULL;
+ OsalMemFree(manager);
+}
+
+struct HdfDriverEntry g_dacManagerEntry = {
+ .moduleVersion = 1,
+ .Init = DacManagerInit,
+ .Release = DacManagerRelease,
+ .moduleName = "HDF_PLATFORM_DAC_MANAGER",
+};
+HDF_INIT(g_dacManagerEntry);
diff --git a/support/platform/src/dac/dac_if.c b/support/platform/src/dac/dac_if.c
new file mode 100644
index 0000000000000000000000000000000000000000..4d188d944c1d9ad77cf124368e9230f5e496efaa
--- /dev/null
+++ b/support/platform/src/dac/dac_if.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include "dac_if.h"
+#include "dac_core.h"
+#include "hdf_log.h"
+#include "osal_mem.h"
+#include "securec.h"
+#define HDF_LOG_TAG dac_if_c
+#define DAC_SERVICE_NAME "HDF_PLATFORM_DAC_MANAGER"
+
+DevHandle DacOpen(uint32_t number)
+{
+ int32_t ret;
+ struct DacDevice *device = NULL;
+
+ device = DacDeviceGet(number);
+ if (device == NULL) {
+ HDF_LOGE("%s: Get device failed!", __func__);
+ return NULL;
+ }
+
+ ret = DacDeviceStart(device);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: start device failed!", __func__);
+ return NULL;
+ }
+
+ return (DevHandle)device;
+}
+
+void DacClose(DevHandle handle)
+{
+ struct DacDevice *device = (struct DacDevice *)handle;
+
+ if (device == NULL) {
+ return;
+ }
+
+ (void)DacDeviceStop(device);
+ DacDevicePut(device);
+}
+
+int32_t DacWrite(DevHandle handle, uint32_t channel, uint32_t val)
+{
+ if (handle == NULL) {
+ HDF_LOGE("%s: invalid handle!", __func__);
+ return HDF_ERR_INVALID_PARAM;
+ }
+ return DacDeviceWrite((struct DacDevice *)handle, channel, val);
+}
diff --git a/support/platform/test/unittest/common/hdf_dac_test.cpp b/support/platform/test/unittest/common/hdf_dac_test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..808d90dccdc416b3216bcef4a2bd7c6721f331b3
--- /dev/null
+++ b/support/platform/test/unittest/common/hdf_dac_test.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "hdf_uhdf_test.h"
+#include "dac_test.h"
+#include "hdf_io_service_if.h"
+
+using namespace testing::ext;
+
+class HdfLiteDacTest : public testing::Test {
+public:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+ void SetUp();
+ void TearDown();
+};
+
+void HdfLiteDacTest::SetUpTestCase()
+{
+ HdfTestOpenService();
+}
+
+void HdfLiteDacTest::TearDownTestCase()
+{
+ HdfTestCloseService();
+}
+
+void HdfLiteDacTest::SetUp()
+{
+}
+
+void HdfLiteDacTest::TearDown()
+{
+}
+
+/**
+ * @tc.name: DacTestRead001
+ * @tc.desc: dac write test
+ * @tc.type: FUNC
+ * @tc.require: NA
+ */
+HWTEST_F(HdfLiteDacTest, DacTestWrite001, TestSize.Level1)
+{
+ struct HdfTestMsg msg = {TEST_PAL_DAC_TYPE, DAC_TEST_CMD_WRITE, -1};
+ EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
+}
+
+/**
+ * @tc.name: DacTestMultiThread001
+ * @tc.desc: dac multi thread test
+ * @tc.type: FUNC
+ * @tc.require: NA
+ */
+HWTEST_F(HdfLiteDacTest, DacTestMultiThread001, TestSize.Level1)
+{
+ struct HdfTestMsg msg = {TEST_PAL_DAC_TYPE, DAC_TEST_CMD_MULTI_THREAD, -1};
+ EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
+}
+
+/**
+ * @tc.name: DacTestReliability001
+ * @tc.desc: dac reliability test
+ * @tc.type: FUNC
+ * @tc.require: NA
+ */
+HWTEST_F(HdfLiteDacTest, DacTestReliability001, TestSize.Level1)
+{
+ struct HdfTestMsg msg = {TEST_PAL_DAC_TYPE, DAC_TEST_CMD_RELIABILITY, -1};
+ EXPECT_EQ(0, HdfTestSendMsgToService(&msg));
+}
+
+
diff --git a/test/unittest/common/hdf_main_test.c b/test/unittest/common/hdf_main_test.c
index ec7bf84c933ad6b6d809bf955b914817df0df8ba..52a8d2f1d559e8076beeddac1687f828bce52868 100644
--- a/test/unittest/common/hdf_main_test.c
+++ b/test/unittest/common/hdf_main_test.c
@@ -32,6 +32,9 @@
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_ADC)
#include "hdf_adc_entry_test.h"
#endif
+#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_DAC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_DAC)
+#include "hdf_dac_entry_test.h"
+#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I3C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I3C)
#include "hdf_i3c_entry_test.h"
#endif
@@ -101,6 +104,9 @@ HdfTestFuncList g_hdfTestFuncList[] = {
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_ADC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_ADC)
{ TEST_PAL_ADC_TYPE, HdfAdcTestEntry },
#endif
+#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_DAC) || defined(CONFIG_DRIVERS_HDF_PLATFORM_DAC)
+ { TEST_PAL_DAC_TYPE, HdfDacTestEntry },
+#endif
#if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I3C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I3C)
{ TEST_PAL_I3C_TYPE, HdfI3cTestEntry },
#endif
diff --git a/test/unittest/common/hdf_main_test.h b/test/unittest/common/hdf_main_test.h
index fc4cd43eb2f48b9d41901e62061b340ee99834ef..173b2294b4183daeac8d21c2b2bcb825ca44ea16 100644
--- a/test/unittest/common/hdf_main_test.h
+++ b/test/unittest/common/hdf_main_test.h
@@ -59,6 +59,7 @@ typedef enum {
TEST_PAL_WDT_TYPE = 21,
TEST_PAL_I3C_TYPE = 22,
TEST_PAL_MIPI_CSI_TYPE = 23,
+ TEST_PAL_DAC_TYPE = 24,
TEST_PAL_END = 200,
TEST_OSAL_BEGIN = TEST_PAL_END,
#define HDF_OSAL_TEST_ITEM(v) (TEST_OSAL_BEGIN + (v))
diff --git a/test/unittest/include/hdf_uhdf_test.h b/test/unittest/include/hdf_uhdf_test.h
index 41f419f7af54d428363d3e88a3ef78059ba5e4b0..8dcc54f65f6150c93e52f5219f6dfd086df74604 100644
--- a/test/unittest/include/hdf_uhdf_test.h
+++ b/test/unittest/include/hdf_uhdf_test.h
@@ -55,6 +55,7 @@ enum HdfTestSubModuleCmd {
TEST_PAL_WDT_TYPE = 21,
TEST_PAL_I3C_TYPE = 22,
TEST_PAL_MIPI_CSI_TYPE = 23,
+ TEST_PAL_DAC_TYPE = 24,
TEST_PAL_END = 200,
TEST_OSAL_BEGIN = TEST_PAL_END,
#define HDF_OSAL_TEST_ITEM(v) (TEST_OSAL_BEGIN + (v))
diff --git a/test/unittest/platform/common/adc_test.c b/test/unittest/platform/common/adc_test.c
index 3cdc10f0024baf50ab780da89706bbd5688d85dc..ca71e5fc1436dbff2948d63ead64c174d60d335f 100644
--- a/test/unittest/platform/common/adc_test.c
+++ b/test/unittest/platform/common/adc_test.c
@@ -31,7 +31,6 @@ static int32_t AdcTestGetConfig(struct AdcTestConfig *config)
const void *buf = NULL;
uint32_t len;
- HDF_LOGD("%s: enter", __func__);
service = HdfIoServiceBind("ADC_TEST");
if (service == NULL) {
return HDF_ERR_NOT_SUPPORT;
@@ -77,7 +76,6 @@ struct AdcTester *AdcTesterGet(void)
static struct AdcTester tester;
static bool hasInit = false;
- HDF_LOGE("%s: enter", __func__);
if (hasInit) {
return &tester;
}
@@ -92,7 +90,6 @@ struct AdcTester *AdcTesterGet(void)
return NULL;
}
hasInit = true;
- HDF_LOGI("%s: done", __func__);
return &tester;
}
@@ -103,7 +100,6 @@ int32_t AdcTestRead(void)
int32_t ret;
int i;
- HDF_LOGI("%s: enter", __func__);
tester = AdcTesterGet();
if (tester == NULL) {
HDF_LOGE("%s: get tester failed", __func__);
@@ -118,7 +114,6 @@ int32_t AdcTestRead(void)
}
}
- HDF_LOGI("%s: done", __func__);
return HDF_SUCCESS;
}
@@ -129,7 +124,6 @@ static int AdcTestThreadFunc(void *param)
int i;
int32_t ret;
- HDF_LOGI("%s: enter", __func__);
tester = AdcTesterGet();
if (tester == NULL) {
HDF_LOGE("%s: get tester failed", __func__);
@@ -146,7 +140,6 @@ static int AdcTestThreadFunc(void *param)
}
*((int32_t *)param) = 1;
- HDF_LOGI("%s: done", __func__);
return val;
}
@@ -158,7 +151,6 @@ int32_t AdcTestMultiThread(void)
int32_t count1, count2;
count1 = count2 = 0;
- HDF_LOGI("%s: enter", __func__);
ret = OsalThreadCreate(&thread1, (OsalThreadEntry)AdcTestThreadFunc, (void *)&count1);
if (ret != HDF_SUCCESS) {
HDF_LOGE("create test thread1 fail:%d", ret);
@@ -195,7 +187,6 @@ int32_t AdcTestMultiThread(void)
(void)OsalThreadDestroy(&thread1);
(void)OsalThreadDestroy(&thread2);
- HDF_LOGI("%s: done", __func__);
return HDF_SUCCESS;
}
@@ -204,7 +195,6 @@ int32_t AdcTestReliability(void)
struct AdcTester *tester = NULL;
uint32_t val;
- HDF_LOGI("%s: enter", __func__);
tester = AdcTesterGet();
if (tester == NULL || tester->handle == NULL) {
return HDF_ERR_INVALID_OBJECT;
@@ -216,7 +206,6 @@ int32_t AdcTestReliability(void)
(void)AdcRead(tester->handle, tester->config.maxChannel + 1, &val);
// invalid val pointer
(void)AdcRead(tester->handle, tester->config.channel, NULL);
- HDF_LOGI("%s: done", __func__);
return HDF_SUCCESS;
}
@@ -252,6 +241,6 @@ int32_t AdcTestExecute(int cmd)
}
__EXIT__:
- HDF_LOGE("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
+ HDF_LOGI("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
return ret;
}
diff --git a/test/unittest/platform/common/dac_driver_test.c b/test/unittest/platform/common/dac_driver_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..3b8f5a7d991ac4fd9076abb38e331604e2910f33
--- /dev/null
+++ b/test/unittest/platform/common/dac_driver_test.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include "dac_test.h"
+#include "device_resource_if.h"
+#include "hdf_base.h"
+#include "hdf_device_desc.h" // The HDF framework opens the header file of the relevant capability interface to the driver
+#include "hdf_log.h"
+
+#define HDF_LOG_TAG dac_test_driver_c // Print the tags contained in the log, if not defined, use the HDF_TAG tag defined by default
+
+static struct DacTestConfig g_config;
+
+static int32_t DacTestDispatch(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
+{
+ HDF_LOGD("%s: enter!", __func__);
+
+ if (cmd == 0) {
+ if (reply == NULL) {
+ HDF_LOGE("%s: reply is null!", __func__);
+ return HDF_ERR_INVALID_PARAM;
+ }
+ if (!HdfSbufWriteBuffer(reply, &g_config, sizeof(g_config))) {
+ HDF_LOGE("%s: write reply failed", __func__);
+ return HDF_ERR_IO;
+ }
+ } else {
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ return HDF_SUCCESS;
+}
+
+static int32_t DacTestReadConfig(struct DacTestConfig *config, const struct DeviceResourceNode *node)
+{
+ int32_t ret;
+ struct DeviceResourceIface *drsOps = NULL;
+
+ drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
+ if (drsOps == NULL || drsOps->GetUint32 == NULL) {
+ HDF_LOGE("%s: invalid drs ops", __func__);
+ return HDF_FAILURE;
+ }
+
+ ret = drsOps->GetUint32(node, "devNum", &config->devNum, 0);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read devNum failed", __func__);
+ return ret;
+ }
+
+ ret = drsOps->GetUint32(node, "channel", &config->channel, 0);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read channel failed", __func__);
+ return ret;
+ }
+
+ ret = drsOps->GetUint32(node, "maxChannel", &config->maxChannel, 0);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read maxChannel failed", __func__);
+ return ret;
+ }
+
+ ret = drsOps->GetUint32(node, "dataWidth", &config->dataWidth, 0);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read dataWidth failed", __func__);
+ return ret;
+ }
+
+ ret = drsOps->GetUint32(node, "rate", &config->rate, 0);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read rate failed", __func__);
+ return ret;
+ }
+
+ return HDF_SUCCESS;
+}
+
+static int32_t DacTestBind(struct HdfDeviceObject *device)
+{
+ int32_t ret;
+ static struct IDeviceIoService service;
+
+ if (device == NULL || device->property == NULL) {
+ HDF_LOGE("%s: device or config is null!", __func__);
+ return HDF_ERR_IO;
+ }
+
+ ret = DacTestReadConfig(&g_config, device->property);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read config failed", __func__);
+ return ret;
+ }
+ service.Dispatch = DacTestDispatch;
+ device->service = &service;
+ HDF_LOGI("%s: Done!", __func__);
+ return HDF_SUCCESS;
+}
+
+static int32_t DacTestInit(struct HdfDeviceObject *device)
+{
+ (void)device;
+ HDF_LOGI("%s: Done!", __func__);
+ return HDF_SUCCESS;
+}
+
+static void DacTestRelease(struct HdfDeviceObject *device)
+{
+ if (device != NULL) {
+ device->service = NULL;
+ }
+ HDF_LOGI("%s: Done!", __func__);
+ return;
+}
+
+struct HdfDriverEntry g_dacTestEntry = {
+ .moduleVersion = 1,
+ .Bind = DacTestBind,
+ .Init = DacTestInit,
+ .Release = DacTestRelease,
+ .moduleName = "PLATFORM_DAC_TEST",
+};
+HDF_INIT(g_dacTestEntry);
diff --git a/test/unittest/platform/common/dac_test.c b/test/unittest/platform/common/dac_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..b9d6b8a49410823fa9a7e81ca3b6e92ecf369233
--- /dev/null
+++ b/test/unittest/platform/common/dac_test.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include "dac_test.h"
+#include "dac_if.h"
+#include "hdf_base.h"
+#include "hdf_io_service_if.h"
+#include "hdf_log.h"
+#include "osal_mem.h"
+#include "securec.h"
+#include "osal_thread.h"
+#include "osal_time.h"
+
+
+#define HDF_LOG_TAG dac_test_c
+#define DAC_TEST_WAIT_TIMES 100
+#define TEST_DAC_VAL_NUM 50
+#define DAC_TEST_STACK_SIZE (1024 * 64)
+
+static int32_t DacTestGetConfig(struct DacTestConfig *config)
+{
+ int32_t ret;
+ struct HdfSBuf *reply = NULL;
+ struct HdfIoService *service = NULL;
+ const void *buf = NULL;
+ uint32_t len;
+
+ service = HdfIoServiceBind("DAC_TEST");
+ if (service == NULL) {
+ return HDF_ERR_NOT_SUPPORT;
+ }
+
+ reply = HdfSBufObtain(sizeof(*config) + sizeof(uint64_t));
+ if (reply == NULL) {
+ HDF_LOGE("%s: failed to obtain reply", __func__);
+ return HDF_ERR_MALLOC_FAIL;
+ }
+
+ ret = service->dispatcher->Dispatch(&service->object, 0, NULL, reply);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: remote dispatch failed", __func__);
+ return ret;
+ }
+
+ if (!HdfSbufReadBuffer(reply, &buf, &len)) {
+ HDF_LOGE("%s: read buf failed", __func__);
+ HdfSBufRecycle(reply);
+ return HDF_ERR_IO;
+ }
+
+ if (len != sizeof(*config)) {
+ HDF_LOGE("%s: config size:%zu, read size:%u", __func__, sizeof(*config), len);
+ HdfSBufRecycle(reply);
+ return HDF_ERR_IO;
+ }
+
+ if (memcpy_s(config, sizeof(*config), buf, sizeof(*config)) != EOK) {
+ HDF_LOGE("%s: memcpy buf failed", __func__);
+ HdfSBufRecycle(reply);
+ return HDF_ERR_IO;
+ }
+ HdfSBufRecycle(reply);
+ HDF_LOGD("%s: exit", __func__);
+ return HDF_SUCCESS;
+}
+
+struct DacTester *DacTesterGet(void)
+{
+ int32_t ret;
+ static struct DacTester tester;
+ static bool hasInit = false;
+
+ if (hasInit) {
+ return &tester;
+ }
+ ret = DacTestGetConfig(&tester.config);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: write config failed:%d", __func__, ret);
+ return NULL;
+ }
+ tester.handle = DacOpen(tester.config.devNum);
+ if (tester.handle == NULL) {
+ HDF_LOGE("%s: open dac device:%u failed", __func__, tester.config.devNum);
+ return NULL;
+ }
+ hasInit = true;
+ return &tester;
+}
+
+int32_t DacTestWrite(void)
+{
+ struct DacTester *tester = NULL;
+ uint32_t value[TEST_DAC_VAL_NUM];
+ int32_t ret;
+ int i;
+
+ tester = DacTesterGet();
+ if (tester == NULL || tester->handle == NULL) {
+ HDF_LOGE("%s: get tester failed", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ for (i = 0; i < TEST_DAC_VAL_NUM; i++) {
+ value[i] = 0;
+ ret = DacWrite(tester->handle, tester->config.channel, value[i]);
+ if (ret != HDF_SUCCESS || value[i] >= (1U << tester->config.dataWidth)) {
+ HDF_LOGE("%s: write value invalid:%u, ret:%d", __func__, value[i], ret);
+ return HDF_ERR_IO;
+ }
+ }
+
+ return HDF_SUCCESS;
+}
+
+static int DacTestThreadFunc(void *param)
+{
+ struct DacTester *tester = NULL;
+ uint32_t val;
+ int i;
+ int32_t ret;
+ tester = DacTesterGet();
+ if (tester == NULL) {
+ HDF_LOGE("%s: get tester failed", __func__);
+ *((int32_t *)param) = 1;
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ for (i = 0; i < DAC_TEST_WAIT_TIMES; i++) {
+ val = i;
+ ret = DacWrite(tester->handle, tester->config.channel, val);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: DacWrite failed, ret:%d", __func__, ret);
+ return HDF_ERR_IO;
+ }
+ }
+
+ *((int32_t *)param) = 1;
+ return val;
+}
+
+int32_t DacTestMultiThread(void)
+{
+ int32_t ret;
+ struct OsalThread thread1, thread2;
+ struct OsalThreadParam cfg1, cfg2;
+ int32_t count1, count2;
+
+ count1 = count2 = 0;
+ ret = OsalThreadCreate(&thread1, (OsalThreadEntry)DacTestThreadFunc, (void *)&count1);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("create test thread1 fail:%d", ret);
+ return HDF_FAILURE;
+ }
+
+ ret = OsalThreadCreate(&thread2, (OsalThreadEntry)DacTestThreadFunc, (void *)&count2);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("create test thread1 fail:%d", ret);
+ return HDF_FAILURE;
+ }
+
+ cfg1.name = "DacTestThread-1";
+ cfg2.name = "DacTestThread-2";
+ cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT;
+ cfg1.stackSize = cfg2.stackSize = DAC_TEST_STACK_SIZE;
+
+ ret = OsalThreadStart(&thread1, &cfg1);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("start test thread1 fail:%d", ret);
+ return HDF_FAILURE;
+ }
+
+ ret = OsalThreadStart(&thread2, &cfg2);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("start test thread2 fail:%d", ret);
+ return HDF_FAILURE;
+ }
+
+ while (count1 == 0 || count2 == 0) {
+ HDF_LOGE("waitting testing thread finish...");
+ OsalMSleep(DAC_TEST_WAIT_TIMES);
+ }
+
+ (void)OsalThreadDestroy(&thread1);
+ (void)OsalThreadDestroy(&thread2);
+ return HDF_SUCCESS;
+}
+
+int32_t DacTestReliability(void)
+{
+ struct DacTester *tester = NULL;
+ uint32_t val;
+
+ val = 0;
+ tester = DacTesterGet();
+ if (tester == NULL || tester->handle == NULL) {
+ return HDF_ERR_INVALID_OBJECT;
+ }
+ HDF_LOGD("%s: test dfr for DacRead ...", __func__);
+ // invalid handle
+ (void)DacWrite(NULL, tester->config.channel, val);
+ // invalid channel
+ (void)DacWrite(tester->handle, tester->config.maxChannel + 1, val);
+ return HDF_SUCCESS;
+}
+
+struct DacTestEntry {
+ int cmd;
+ int32_t (*func)(void);
+ const char *name;
+};
+static struct DacTestEntry g_entry[] = {
+ { DAC_TEST_CMD_WRITE, DacTestWrite, "DacTestWrite" },
+ { DAC_TEST_CMD_MULTI_THREAD, DacTestMultiThread, "DacTestMultiThread" },
+ { DAC_TEST_CMD_RELIABILITY, DacTestReliability, "DacTestReliability" },
+};
+
+int32_t DacTestExecute(int cmd)
+{
+ uint32_t i;
+ int32_t ret = HDF_ERR_NOT_SUPPORT;
+
+ if (cmd > DAC_TEST_CMD_MAX) {
+ HDF_LOGE("%s: invalid cmd:%d", __func__, cmd);
+ ret = HDF_ERR_NOT_SUPPORT;
+ goto __EXIT__;
+ }
+
+ for (i = 0; i < sizeof(g_entry) / sizeof(g_entry[0]); i++) {
+ if (g_entry[i].cmd != cmd || g_entry[i].func == NULL) {
+ continue;
+ }
+ ret = g_entry[i].func();
+ break;
+ }
+
+__EXIT__:
+ HDF_LOGE("[%s][======cmd:%d====ret:%d======]", __func__, cmd, ret);
+ return ret;
+}
diff --git a/test/unittest/platform/common/dac_test.h b/test/unittest/platform/common/dac_test.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e25d2f0ce86266a16e865faf617673189e4fe87
--- /dev/null
+++ b/test/unittest/platform/common/dac_test.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#ifndef DAC_TEST_H
+#define DAC_TEST_H
+
+#include "dac_if.h"
+
+#ifdef __cplusplus
+#if __cplusplus
+extern "C" {
+#endif
+#endif /* __cplusplus */
+
+struct DacTestConfig {
+ uint32_t devNum;
+ uint32_t channel;
+ uint32_t maxChannel;
+ uint32_t dataWidth;
+ uint32_t rate;
+};
+
+struct DacTester {
+ struct DacTestConfig config;
+ DevHandle handle;
+};
+
+enum DacTestCmd {
+ DAC_TEST_CMD_WRITE = 0,
+ DAC_TEST_CMD_MULTI_THREAD,
+ DAC_TEST_CMD_RELIABILITY,
+ DAC_TEST_CMD_MAX,
+};
+
+int32_t DacTestExecute(int cmd);
+
+#ifdef __cplusplus
+#if __cplusplus
+}
+#endif
+#endif /* __cplusplus */
+
+#endif /* DAC_TEST_H */
diff --git a/test/unittest/platform/hdf_dac_entry_test.c b/test/unittest/platform/hdf_dac_entry_test.c
new file mode 100644
index 0000000000000000000000000000000000000000..afcf67744c1dbf632a94ed3077a3ce547b542c90
--- /dev/null
+++ b/test/unittest/platform/hdf_dac_entry_test.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include "hdf_dac_entry_test.h"
+#include "hdf_log.h"
+#include "dac_test.h"
+#include "hdf_log.h"
+
+#define HDF_LOG_TAG hdf_dac_entry_test
+
+int32_t HdfDacTestEntry(HdfTestMsg *msg)
+{
+ HDF_LOGE("%s: enter", __func__);
+ if (msg == NULL) {
+ return HDF_FAILURE;
+ }
+
+ msg->result = DacTestExecute(msg->subCmd);
+
+ return HDF_SUCCESS;
+}
diff --git a/test/unittest/platform/hdf_dac_entry_test.h b/test/unittest/platform/hdf_dac_entry_test.h
new file mode 100644
index 0000000000000000000000000000000000000000..b693b6b0e3c40d4cbbf6bf398e82b6bb70669e8f
--- /dev/null
+++ b/test/unittest/platform/hdf_dac_entry_test.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#ifndef HDF_DAC_ENTRY_TEST_H
+#define HDF_DAC_ENTRY_TEST_H
+
+#include "hdf_main_test.h"
+
+int32_t HdfDacTestEntry(HdfTestMsg *msg);
+
+#endif /* HDF_DAC_ENTRY_TEST_H */
\ No newline at end of file
diff --git a/test/unittest/platform/virtual/dac_virtual.c b/test/unittest/platform/virtual/dac_virtual.c
new file mode 100644
index 0000000000000000000000000000000000000000..b8314ed27d2439f6c3bbea27315a35dd8f380bf1
--- /dev/null
+++ b/test/unittest/platform/virtual/dac_virtual.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2021 Huawei Device Co., Ltd.
+ *
+ * HDF is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ * See the LICENSE file in the root of this repository for complete details.
+ */
+
+#include "dac/dac_core.h"
+#include "asm/platform.h"
+#include "device_resource_if.h"
+#include "hdf_device_desc.h"
+#include "hdf_log.h"
+#include "los_hwi.h"
+#include "osal_io.h"
+#include "osal_mem.h"
+#include "osal_time.h"
+
+#define HDF_LOG_TAG dac_virtual
+
+struct VirtualDacDevice {
+ struct DacDevice device;
+ uint32_t deviceNum;
+ uint32_t validChannel;
+ uint32_t rate;
+};
+
+static int32_t VirtualDacWrite(struct DacDevice *device, uint32_t channel, uint32_t val)
+{
+ (void)device;
+ (void)channel;
+ (void)val;
+ HDF_LOGI("%s: done!", __func__);
+
+ return HDF_SUCCESS;
+}
+
+static inline int32_t VirtualDacStart(struct DacDevice *device)
+{
+ (void)device;
+ HDF_LOGI("%s: done!", __func__);
+ return HDF_SUCCESS;
+}
+
+static inline int32_t VirtualDacStop(struct DacDevice *device)
+{
+ (void)device;
+ HDF_LOGI("%s: done!", __func__);
+ return HDF_SUCCESS;
+}
+
+static inline void VirtualDacDeviceInit(struct VirtualDacDevice *virtual)
+{
+ HDF_LOGI("%s: device:%u init done!", __func__, virtual->deviceNum);
+}
+
+static const struct DacMethod g_method = {
+ .write = VirtualDacWrite,
+ .stop = VirtualDacStop,
+ .start = VirtualDacStart,
+};
+
+static int32_t VirtualDacReadDrs(struct VirtualDacDevice *virtual, const struct DeviceResourceNode *node)
+{
+ struct DeviceResourceIface *drsOps = NULL;
+
+ drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
+ if (drsOps == NULL || drsOps->GetUint32 == NULL || drsOps->GetUint16 == NULL) {
+ HDF_LOGE("%s: Invalid drs ops fail!", __func__);
+ return HDF_FAILURE;
+ }
+ if (drsOps->GetUint32(node, "deviceNum", &virtual->deviceNum, 0) != HDF_SUCCESS) {
+ HDF_LOGE("%s: Read deviceNum fail!", __func__);
+ return HDF_ERR_IO;
+ }
+ if (drsOps->GetUint32(node, "validChannel", &virtual->validChannel, 0) != HDF_SUCCESS) {
+ HDF_LOGE("%s: Read validChannel fail!", __func__);
+ return HDF_ERR_IO;
+ }
+ if (drsOps->GetUint32(node, "rate", &virtual->rate, 0) != HDF_SUCCESS) {
+ HDF_LOGE("%s: Read rate fail!", __func__);
+ return HDF_ERR_IO;
+ }
+ return HDF_SUCCESS;
+}
+
+static int32_t VirtualDacParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
+{
+ int32_t ret;
+ struct VirtualDacDevice *virtual = NULL;
+ (void)device;
+
+ virtual = (struct VirtualDacDevice *)OsalMemCalloc(sizeof(*virtual));
+ if (virtual == NULL) {
+ HDF_LOGE("%s: Malloc virtual fail!", __func__);
+ return HDF_ERR_MALLOC_FAIL;
+ }
+
+ ret = VirtualDacReadDrs(virtual, node);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: Read drs fail! ret:%d", __func__, ret);
+ goto __ERR__;
+ }
+
+ VirtualDacDeviceInit(virtual);
+ virtual->device.priv = (void *)node;
+ virtual->device.devNum = virtual->deviceNum;
+ virtual->device.ops = &g_method;
+ ret = DacDeviceAdd(&virtual->device);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: add Dac controller failed! ret = %d", __func__, ret);
+ goto __ERR__;
+ }
+
+ return HDF_SUCCESS;
+__ERR__:
+ if (virtual != NULL) {
+ OsalMemFree(virtual);
+ virtual = NULL;
+ }
+
+ return ret;
+}
+
+static int32_t VirtualDacInit(struct HdfDeviceObject *device)
+{
+ int32_t ret;
+ const struct DeviceResourceNode *childNode = NULL;
+
+ if (device == NULL || device->property == NULL) {
+ HDF_LOGE("%s: device or property is NULL", __func__);
+ return HDF_ERR_INVALID_OBJECT;
+ }
+
+ ret = HDF_SUCCESS;
+ DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
+ ret = VirtualDacParseAndInit(device, childNode);
+ if (ret != HDF_SUCCESS) {
+ break;
+ }
+ }
+ return ret;
+}
+
+static void VirtualDacRemoveByNode(const struct DeviceResourceNode *node)
+{
+ int32_t ret;
+ int16_t devNum;
+ struct DacDevice *device = NULL;
+ struct VirtualDacDevice *virtual = NULL;
+ struct DeviceResourceIface *drsOps = NULL;
+
+ drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
+ if (drsOps == NULL || drsOps->GetUint32 == NULL) {
+ HDF_LOGE("%s: invalid drs ops fail!", __func__);
+ return;
+ }
+
+ ret = drsOps->GetUint16(node, "devNum", (uint16_t *)&devNum, 0);
+ if (ret != HDF_SUCCESS) {
+ HDF_LOGE("%s: read devNum fail!", __func__);
+ return;
+ }
+
+ device = DacDeviceGet(devNum);
+ if (device != NULL && device->priv == node) {
+ DacDevicePut(device);
+ DacDeviceRemove(device);
+ virtual = (struct VirtualDacDevice *)device;
+ OsalMemFree(virtual);
+ }
+ return;
+}
+
+static void VirtualDacRelease(struct HdfDeviceObject *device)
+{
+ const struct DeviceResourceNode *childNode = NULL;
+
+ if (device == NULL || device->property == NULL) {
+ HDF_LOGE("%s: device or property is NULL", __func__);
+ return;
+ }
+
+ DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {
+ VirtualDacRemoveByNode(childNode);
+ }
+}
+
+struct HdfDriverEntry g_dacDriverEntry = {
+ .moduleVersion = 1,
+ .Init = VirtualDacInit,
+ .Release = VirtualDacRelease,
+ .moduleName = "virtual_dac_driver",
+};
+HDF_INIT(g_dacDriverEntry);