From 5bf6f06c7cdb55e0701ecfa148621135bb8b5466 Mon Sep 17 00:00:00 2001 From: mahai Date: Thu, 25 Nov 2021 15:04:34 +0800 Subject: [PATCH] feat:Add dac driver framework and test case file Signed-off-by: mahai --- include/platform/dac_if.h | 87 ++++ support/platform/include/dac/dac_core.h | 75 ++++ support/platform/src/dac/dac_core.c | 390 ++++++++++++++++++ support/platform/src/dac/dac_if.c | 56 +++ .../test/unittest/common/hdf_dac_test.cpp | 84 ++++ test/unittest/common/hdf_main_test.c | 6 + test/unittest/common/hdf_main_test.h | 1 + test/unittest/include/hdf_uhdf_test.h | 1 + test/unittest/platform/common/adc_test.c | 13 +- .../platform/common/dac_driver_test.c | 127 ++++++ test/unittest/platform/common/dac_test.c | 242 +++++++++++ test/unittest/platform/common/dac_test.h | 48 +++ test/unittest/platform/hdf_dac_entry_test.c | 26 ++ test/unittest/platform/hdf_dac_entry_test.h | 16 + test/unittest/platform/virtual/dac_virtual.c | 195 +++++++++ 15 files changed, 1355 insertions(+), 12 deletions(-) create mode 100644 include/platform/dac_if.h create mode 100644 support/platform/include/dac/dac_core.h create mode 100644 support/platform/src/dac/dac_core.c create mode 100644 support/platform/src/dac/dac_if.c create mode 100644 support/platform/test/unittest/common/hdf_dac_test.cpp create mode 100644 test/unittest/platform/common/dac_driver_test.c create mode 100644 test/unittest/platform/common/dac_test.c create mode 100644 test/unittest/platform/common/dac_test.h create mode 100644 test/unittest/platform/hdf_dac_entry_test.c create mode 100644 test/unittest/platform/hdf_dac_entry_test.h create mode 100644 test/unittest/platform/virtual/dac_virtual.c diff --git a/include/platform/dac_if.h b/include/platform/dac_if.h new file mode 100644 index 000000000..84dfeb73a --- /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 000000000..8c04f35cd --- /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 000000000..8bb3a6bcc --- /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 000000000..4d188d944 --- /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 000000000..808d90dcc --- /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 ec7bf84c9..52a8d2f1d 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 fc4cd43eb..173b2294b 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 41f419f7a..8dcc54f65 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 3cdc10f00..ca71e5fc1 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 000000000..3b8f5a7d9 --- /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 000000000..b9d6b8a49 --- /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 000000000..4e25d2f0c --- /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 000000000..afcf67744 --- /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 000000000..b693b6b0e --- /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 000000000..b8314ed27 --- /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); -- Gitee