diff --git a/include/platform/adc_if.h b/include/platform/adc_if.h new file mode 100644 index 0000000000000000000000000000000000000000..79c06a0a0e4761a2e9dca1dea5bc59e4c2a4eb89 --- /dev/null +++ b/include/platform/adc_if.h @@ -0,0 +1,37 @@ +/* + * 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 ADC_IF_H +#define ADC_IF_H + +#include "hdf_platform.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct AdcIoMsg { + uint32_t number; + uint32_t channel; +}; + +DevHandle AdcOpen(uint32_t num); + +void AdcClose(DevHandle handle); + +int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* ADC_IF_H */ diff --git a/support/platform/include/adc_core.h b/support/platform/include/adc_core.h new file mode 100644 index 0000000000000000000000000000000000000000..e0e47b521eacdc4161320e5ccde8e123f1eed8ae --- /dev/null +++ b/support/platform/include/adc_core.h @@ -0,0 +1,74 @@ +/* + * 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 ADC_CORE_H +#define ADC_CORE_H + +#include "osal_spinlock.h" +#include "hdf_base.h" +#include "adc_if.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +#define ADC_DEVICES_MAX 15 + +struct AdcDevice; +struct AdcMethod; +struct AdcLockMethod; + +struct AdcDevice { + const struct AdcMethod *ops; + OsalSpinlock spin; + uint32_t devNum; + uint32_t chanNum; + const struct AdcLockMethod *lockOps; + void *priv; +}; + +struct AdcMethod { + int32_t (*read)(struct AdcDevice *device, uint32_t channel, uint32_t *val); + int32_t (*start)(struct AdcDevice *device); + int32_t (*stop)(struct AdcDevice *device); +}; + +struct AdcLockMethod { + int32_t (*lock)(struct AdcDevice *device); + void (*unlock)(struct AdcDevice *device); +}; + +enum AdcIoCmd { + ADC_IO_READ = 0, + ADC_IO_OPEN, + ADC_IO_CLOSE, +}; + +int32_t AdcDeviceAdd(struct AdcDevice *device); + +void AdcDeviceRemove(struct AdcDevice *device); + +struct AdcDevice *AdcDeviceGet(uint32_t number); + +void AdcDevicePut(struct AdcDevice *device); + +int32_t AdcDeviceRead(struct AdcDevice *device, uint32_t channel, uint32_t *val); + +int32_t AdcDeviceStart(struct AdcDevice *device); + +int32_t AdcDeviceStop(struct AdcDevice *device); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* ADC_CORE_H */ diff --git a/support/platform/src/adc_core.c b/support/platform/src/adc_core.c new file mode 100644 index 0000000000000000000000000000000000000000..a5178ab59266609b42fcd4a17a685cfb822acf4b --- /dev/null +++ b/support/platform/src/adc_core.c @@ -0,0 +1,399 @@ +/* + * 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 "adc_core.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "osal_spinlock.h" +#include "osal_time.h" +#include "plat_common.h" +#include "plat_log.h" + +#define HDF_LOG_TAG adc_core_c +#define LOCK_WAIT_SECONDS_M 1 +#define ADC_BUFF_SIZE 4 + +struct AdcManager { + struct IDeviceIoService service; + struct HdfDeviceObject *device; + struct AdcDevice *devices[ADC_DEVICES_MAX]; + OsalSpinlock spin; +}; + +static struct AdcManager *g_adcManager = NULL; + +static int32_t AdcDeviceLockDefault(struct AdcDevice *device) +{ + if (device == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + return OsalSpinLock(&device->spin); +} + +static void AdcDeviceUnlockDefault(struct AdcDevice *device) +{ + if (device == NULL) { + return; + } + (void)OsalSpinUnlock(&device->spin); +} + +static const struct AdcLockMethod g_adcLockOpsDefault = { + .lock = AdcDeviceLockDefault, + .unlock = AdcDeviceUnlockDefault, +}; + +static int32_t AdcManagerAddDevice(struct AdcDevice *device) +{ + int32_t ret; + struct AdcManager *manager = g_adcManager; + + if (device->devNum >= ADC_DEVICES_MAX) { + HDF_LOGE("%s: devNum:%u exceed", __func__, device->devNum); + return HDF_ERR_INVALID_OBJECT; + } + + if (manager == NULL) { + HDF_LOGE("%s: get adc manager fail", __func__); + return HDF_ERR_NOT_SUPPORT; + } + + if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) { + HDF_LOGE("%s: lock adc manager fail", __func__); + return HDF_ERR_DEVICE_BUSY; + } + + if (manager->devices[device->devNum] != NULL) { + HDF_LOGE("%s: adc device num:%u already exits", __func__, device->devNum); + ret = HDF_FAILURE; + } else { + manager->devices[device->devNum] = device; + ret = HDF_SUCCESS; + } + + (void)OsalSpinUnlockIrq(&manager->spin); + return ret; +} + +static void AdcManagerRemoveDevice(struct AdcDevice *device) +{ + struct AdcManager *manager = g_adcManager; + + if (device->devNum < 0 || device->devNum >= ADC_DEVICES_MAX) { + HDF_LOGE("%s: invalid devNum:%u", __func__, device->devNum); + return; + } + + if (manager == NULL) { + HDF_LOGE("%s: get adc manager fail", __func__); + return; + } + + if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) { + HDF_LOGE("%s: lock adc manager fail", __func__); + return; + } + + if (manager->devices[device->devNum] != device) { + HDF_LOGE("%s: adc device(%u) not in manager", __func__, device->devNum); + } else { + manager->devices[device->devNum] = NULL; + } + + (void)OsalSpinUnlockIrq(&manager->spin); +} + +static struct AdcDevice *AdcManagerFindDevice(uint32_t number) +{ + struct AdcDevice *device = NULL; + struct AdcManager *manager = g_adcManager; + + if (number < 0 || number >= ADC_DEVICES_MAX) { + HDF_LOGE("%s: invalid devNum:%u", __func__, number); + return NULL; + } + + if (manager == NULL) { + HDF_LOGE("%s: get adc manager fail", __func__); + return NULL; + } + + if (OsalSpinLockIrq(&manager->spin) != HDF_SUCCESS) { + HDF_LOGE("%s: lock adc manager fail", __func__); + return NULL; + } + + device = manager->devices[number]; + (void)OsalSpinUnlockIrq(&manager->spin); + + return device; +} + +int32_t AdcDeviceAdd(struct AdcDevice *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_adcLockOpsDefault; + } + + if (OsalSpinInit(&device->spin) != HDF_SUCCESS) { + HDF_LOGE("%s: init lock failed", __func__); + return HDF_FAILURE; + } + + ret = AdcManagerAddDevice(device); + if (ret != HDF_SUCCESS) { + (void)OsalSpinDestroy(&device->spin); + } + return ret; +} + +void AdcDeviceRemove(struct AdcDevice *device) +{ + if (device == NULL) { + return; + } + AdcManagerRemoveDevice(device); + (void)OsalSpinDestroy(&device->spin); +} + +struct AdcDevice *AdcDeviceGet(uint32_t number) +{ + return AdcManagerFindDevice(number); +} + +void AdcDevicePut(struct AdcDevice *device) +{ + (void)device; +} + +static inline int32_t AdcDeviceLock(struct AdcDevice *device) +{ + if (device->lockOps == NULL || device->lockOps->lock == NULL) { + return HDF_ERR_NOT_SUPPORT; + } + return device->lockOps->lock(device); +} + +static inline void AdcDeviceUnlock(struct AdcDevice *device) +{ + if (device->lockOps != NULL && device->lockOps->unlock != NULL) { + device->lockOps->unlock(device); + } +} + +int32_t AdcDeviceRead(struct AdcDevice *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->read == NULL) { + HDF_LOGE("%s: ops or read is null", __func__); + return HDF_ERR_NOT_SUPPORT; + } + + if (val == NULL) { + HDF_LOGE("%s: invalid val pointer!", __func__); + return HDF_ERR_INVALID_PARAM; + } + + if (AdcDeviceLock(device) != HDF_SUCCESS) { + HDF_LOGE("%s: lock add device failed", __func__); + return HDF_ERR_DEVICE_BUSY; + } + + ret = device->ops->read(device, channel, val); + AdcDeviceUnlock(device); + return ret; +} + +int32_t AdcDeviceStart(struct AdcDevice *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 (AdcDeviceLock(device) != HDF_SUCCESS) { + HDF_LOGE("%s: lock add device failed", __func__); + return HDF_ERR_DEVICE_BUSY; + } + + ret = device->ops->start(device); + AdcDeviceUnlock(device); + return ret; +} + +int32_t AdcDeviceStop(struct AdcDevice *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 (AdcDeviceLock(device) != HDF_SUCCESS) { + HDF_LOGE("%s: lock add device failed", __func__); + return HDF_ERR_DEVICE_BUSY; + } + + ret = device->ops->stop(device); + AdcDeviceUnlock(device); + return ret; +} + +static int32_t AdcManagerIoOpen(struct HdfSBuf *data, struct HdfSBuf *reply) +{ + uint32_t number; + + if (!HdfSbufReadUint32(data, &number)) { + return HDF_ERR_IO; + } + + if (number < 0 || number >= ADC_DEVICES_MAX || reply == NULL) { + return HDF_ERR_INVALID_PARAM; + } + + if (AdcDeviceGet(number) == NULL) { + return HDF_ERR_NOT_SUPPORT; + } + + if (!HdfSbufWriteUint32(reply, number)) { + return HDF_ERR_IO; + } + return HDF_SUCCESS; +} + +static int32_t AdcManagerIoClose(struct HdfSBuf *data, struct HdfSBuf *reply) +{ + uint32_t number; + + if (!HdfSbufReadUint32(data, &number)) { + return HDF_ERR_IO; + } + + if (number < 0 || number >= ADC_DEVICES_MAX) { + return HDF_ERR_INVALID_PARAM; + } + AdcDevicePut(AdcManagerFindDevice(number)); + return HDF_SUCCESS; +} + +static int32_t AdcManagerIoRead(struct HdfSBuf *data, struct HdfSBuf *reply) +{ + (void)data; + (void)reply; + return HDF_SUCCESS; +} + +static int32_t AdcManagerDispatch(struct HdfDeviceIoClient *client, int cmd, + struct HdfSBuf *data, struct HdfSBuf *reply) +{ + int32_t ret; + + switch (cmd) { + case ADC_IO_OPEN: + return AdcManagerIoOpen(data, reply); + case ADC_IO_CLOSE: + return AdcManagerIoClose(data, reply); + case ADC_IO_READ: + return AdcManagerIoRead(data, reply); + default: + ret = HDF_ERR_NOT_SUPPORT; + break; + } + return ret; +} + +static int32_t AdcManagerInit(struct HdfDeviceObject *device) +{ + int32_t ret; + struct AdcManager *manager = NULL; + + HDF_LOGI("%s: Enter", __func__); + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + manager = (struct AdcManager *)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_adcManager = manager; + device->service = &manager->service; + device->service->Dispatch = AdcManagerDispatch; + return HDF_SUCCESS; +} + +static void AdcManagerRelease(struct HdfDeviceObject *device) +{ + struct AdcManager *manager = NULL; + + HDF_LOGI("%s: Enter", __func__); + if (device == NULL) { + HDF_LOGE("%s: device is null", __func__); + return; + } + + manager = (struct AdcManager *)device->service; + if (manager == NULL) { + HDF_LOGI("%s: no service bind", __func__); + return; + } + + g_adcManager = NULL; + OsalMemFree(manager); +} + +struct HdfDriverEntry g_adcManagerEntry = { + .moduleVersion = 1, + .Init = AdcManagerInit, + .Release = AdcManagerRelease, + .moduleName = "HDF_PLATFORM_ADC_MANAGER", +}; +HDF_INIT(g_adcManagerEntry); diff --git a/support/platform/src/adc_if.c b/support/platform/src/adc_if.c new file mode 100644 index 0000000000000000000000000000000000000000..23c5fcc8b555c35fe499a8be64402cc0be0f3d48 --- /dev/null +++ b/support/platform/src/adc_if.c @@ -0,0 +1,54 @@ +/* + * 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 "adc_if.h" +#include "adc_core.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "securec.h" +#define HDF_LOG_TAG adc_if_c +#define ADC_SERVICE_NAME "HDF_PLATFORM_ADC_MANAGER" + +DevHandle AdcOpen(uint32_t number) +{ + int32_t ret; + struct AdcDevice *device = NULL; + + device = AdcDeviceGet(number); + if (device == NULL) { + return NULL; + } + + ret = AdcDeviceStart(device); + if (ret != HDF_SUCCESS) { + return NULL; + } + + return (DevHandle)device; +} + +void AdcClose(DevHandle handle) +{ + struct AdcDevice *device = (struct AdcDevice *)handle; + + if (device == NULL) { + return; + } + + (void)AdcDeviceStop(device); + AdcDevicePut(device); +} + +int32_t AdcRead(DevHandle handle, uint32_t channel, uint32_t *val) +{ + if (handle == NULL) { + HDF_LOGE("%s: invalid handle!", __func__); + return HDF_ERR_INVALID_PARAM; + } + return AdcDeviceRead((struct AdcDevice *)handle, channel, val); +} diff --git a/support/platform/test/unittest/common/hdf_adc_test.cpp b/support/platform/test/unittest/common/hdf_adc_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a486d7eacef59b0bb20d7e109e086a6d6975d380 --- /dev/null +++ b/support/platform/test/unittest/common/hdf_adc_test.cpp @@ -0,0 +1,83 @@ +/* + * 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 "adc_test.h" +#include "hdf_io_service_if.h" + +using namespace testing::ext; + +class HdfLiteAdcTest : public testing::Test { +public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); +}; + +void HdfLiteAdcTest::SetUpTestCase() +{ + HdfTestOpenService(); +} + +void HdfLiteAdcTest::TearDownTestCase() +{ + HdfTestCloseService(); +} + +void HdfLiteAdcTest::SetUp() +{ +} + +void HdfLiteAdcTest::TearDown() +{ +} + +/** + * @tc.name: AdcTestRead001 + * @tc.desc: adc read test + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(HdfLiteAdcTest, AdcTestRead001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_ADC_TYPE, ADC_TEST_CMD_READ, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: AdcTestMultiThread001 + * @tc.desc: adc multi thread test + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(HdfLiteAdcTest, AdcTestMultiThread001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_ADC_TYPE, ADC_TEST_CMD_MULTI_THREAD, -1}; + EXPECT_EQ(0, HdfTestSendMsgToService(&msg)); +} + +/** + * @tc.name: AdcTestReliability001 + * @tc.desc: adc reliability test + * @tc.type: FUNC + * @tc.require: NA + */ +HWTEST_F(HdfLiteAdcTest, AdcTestReliability001, TestSize.Level1) +{ + struct HdfTestMsg msg = {TEST_PAL_ADC_TYPE, ADC_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 af2847f9892a8b0f31170a40f5da4ab1c1820b3e..7c5be8c78a94bb6e147e908c521d328214b1451d 100644 --- a/test/unittest/common/hdf_main_test.c +++ b/test/unittest/common/hdf_main_test.c @@ -20,6 +20,9 @@ #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2C) #include "hdf_i2c_entry_test.h" #endif +#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_SPI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SPI) #include "hdf_spi_entry_test.h" #endif @@ -68,6 +71,9 @@ HdfTestFuncList g_hdfTestFuncList[] = { #if defined(LOSCFG_DRIVERS_HDF_PLATFORM_I2C) || defined(CONFIG_DRIVERS_HDF_PLATFORM_I2C) { TEST_PAL_I2C_TYPE, HdfI2cTestEntry }, #endif +#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_SPI) || defined(CONFIG_DRIVERS_HDF_PLATFORM_SPI) { TEST_PAL_SPI_TYPE, HdfSpiUnitTestEntry }, #endif diff --git a/test/unittest/platform/common/adc_driver_test.c b/test/unittest/platform/common/adc_driver_test.c new file mode 100644 index 0000000000000000000000000000000000000000..eacb5f4409e1f70bf6dde75a3e8fe31ea9cd742c --- /dev/null +++ b/test/unittest/platform/common/adc_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 "adc_test.h" +#include "device_resource_if.h" +#include "hdf_base.h" +#include "hdf_device_desc.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG adc_test_driver_c + +static struct AdcTestConfig g_config; + +static int32_t AdcTestDispatch(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 AdcTestReadConfig(struct AdcTestConfig *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 AdcTestBind(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 = AdcTestReadConfig(&g_config, device->property); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read config failed", __func__); + return ret; + } + service.Dispatch = AdcTestDispatch; + device->service = &service; + HDF_LOGI("%s: Done!", __func__); + return HDF_SUCCESS; +} + +static int32_t AdcTestInit(struct HdfDeviceObject *device) +{ + (void)device; + HDF_LOGI("%s: Done!", __func__); + return HDF_SUCCESS; +} + +static void AdcTestRelease(struct HdfDeviceObject *device) +{ + if (device != NULL) { + device->service = NULL; + } + HDF_LOGI("%s: Done!", __func__); + return; +} + +struct HdfDriverEntry g_adcTestEntry = { + .moduleVersion = 1, + .Bind = AdcTestBind, + .Init = AdcTestInit, + .Release = AdcTestRelease, + .moduleName = "PLATFORM_ADC_TEST", +}; +HDF_INIT(g_adcTestEntry); diff --git a/test/unittest/platform/common/adc_test.c b/test/unittest/platform/common/adc_test.c new file mode 100644 index 0000000000000000000000000000000000000000..1ab30f0355de36a1c3e8f92f06d8ea8a08831632 --- /dev/null +++ b/test/unittest/platform/common/adc_test.c @@ -0,0 +1,256 @@ +/* + * 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 "adc_test.h" +#include "adc_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 adc_test_c + +#define TEST_ADC_VAL_NUM 50 +#define ADC_TEST_WAIT_TIMES 100 +#define ADC_TEST_STACK_SIZE (1024 * 64) + +static int32_t AdcTestGetConfig(struct AdcTestConfig *config) +{ + int32_t ret; + struct HdfSBuf *reply = NULL; + struct HdfIoService *service = NULL; + const void *buf = NULL; + uint32_t len; + + HDF_LOGD("%s: enter", __func__); + service = HdfIoServiceBind("ADC_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 AdcTester *AdcTesterGet(void) +{ + int32_t ret; + static struct AdcTester tester; + static bool hasInit = false; + + HDF_LOGE("%s: enter", __func__); + if (hasInit) { + return &tester; + } + ret = AdcTestGetConfig(&tester.config); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read config failed:%d", __func__, ret); + return NULL; + } + tester.handle = AdcOpen(tester.config.devNum); + if (tester.handle == NULL) { + HDF_LOGE("%s: open adc device:%u failed", __func__, tester.config.devNum); + return NULL; + } + hasInit = true; + HDF_LOGI("%s: done", __func__); + return &tester; +} + +int32_t AdcTestRead(void) +{ + struct AdcTester *tester = NULL; + uint32_t value[TEST_ADC_VAL_NUM]; + int32_t ret; + int i; + + HDF_LOGI("%s: enter", __func__); + tester = AdcTesterGet(); + if (tester == NULL) { + HDF_LOGE("%s: get tester failed", __func__); + return HDF_ERR_INVALID_OBJECT; + } + for (i = 0; i < TEST_ADC_VAL_NUM; i++) { + ret = AdcRead(tester->handle, tester->config.channel, &value[i]); + if (ret != HDF_SUCCESS || value[i] >= (1 << tester->config.dataWidth)) { + HDF_LOGE("%s: read value invalid:%u, ret:%d", __func__, value[i], ret); + return HDF_ERR_IO; + } + } + + HDF_LOGI("%s: done", __func__); + return HDF_SUCCESS; +} + +static int AdcTestThreadFunc(void *param) +{ + struct AdcTester *tester = NULL; + uint32_t val; + int i; + int32_t ret; + + HDF_LOGI("%s: enter", __func__); + tester = AdcTesterGet(); + if (tester == NULL) { + HDF_LOGE("%s: get tester failed", __func__); + *((int32_t *)param) = 1; + return HDF_ERR_INVALID_OBJECT; + } + + for (i = 0; i < ADC_TEST_WAIT_TIMES; i++) { + ret = AdcRead(tester->handle, tester->config.channel, &val); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read value invalid:%u, ret:%d", __func__, val, ret); + return HDF_ERR_IO; + } + } + + *((int32_t *)param) = 1; + HDF_LOGI("%s: done", __func__); + return val; +} + +int32_t AdcTestMultiThread(void) +{ + int32_t ret; + struct OsalThread thread1, thread2; + struct OsalThreadParam cfg1, cfg2; + 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); + return HDF_FAILURE; + } + + ret = OsalThreadCreate(&thread2, (OsalThreadEntry)AdcTestThreadFunc, (void *)&count2); + if (ret != HDF_SUCCESS) { + HDF_LOGE("create test thread1 fail:%d", ret); + return HDF_FAILURE; + } + + cfg1.name = "AdcTestThread-1"; + cfg2.name = "AdcTestThread-2"; + cfg1.priority = cfg2.priority = OSAL_THREAD_PRI_DEFAULT; + cfg1.stackSize = cfg2.stackSize = ADC_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(ADC_TEST_WAIT_TIMES); + } + + (void)OsalThreadDestroy(&thread1); + (void)OsalThreadDestroy(&thread2); + HDF_LOGI("%s: done", __func__); + return HDF_SUCCESS; +} + +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; + } + HDF_LOGD("%s: test dfr for AdcRead ...", __func__); + // invalid handle + (void)AdcRead(NULL, tester->config.channel, &val); + // invalid channel + (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; +} + +struct AdcTestEntry { + int cmd; + int32_t (*func)(void); + const char *name; +}; + +static struct AdcTestEntry g_entry[] = { + { ADC_TEST_CMD_READ, AdcTestRead, "AdcTestRead" }, + { ADC_TEST_CMD_MULTI_THREAD, AdcTestMultiThread, "AdcTestMultiThread" }, + { ADC_TEST_CMD_RELIABILITY, AdcTestReliability, "AdcTestReliability" }, +}; + +int32_t AdcTestExecute(int cmd) +{ + uint32_t i; + int32_t ret = HDF_ERR_NOT_SUPPORT; + + if (cmd > ADC_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/adc_test.h b/test/unittest/platform/common/adc_test.h new file mode 100644 index 0000000000000000000000000000000000000000..4f1e1bbab55bfc18dadb4213ba2266762f1fb15a --- /dev/null +++ b/test/unittest/platform/common/adc_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 ADC_TEST_H +#define ADC_TEST_H + +#include "adc_if.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif /* __cplusplus */ + +struct AdcTestConfig { + uint32_t devNum; + uint32_t channel; + uint32_t maxChannel; + uint32_t dataWidth; + uint32_t rate; +}; + +struct AdcTester { + struct AdcTestConfig config; + DevHandle handle; +}; + +enum AdcTestCmd { + ADC_TEST_CMD_READ = 0, + ADC_TEST_CMD_MULTI_THREAD, + ADC_TEST_CMD_RELIABILITY, + ADC_TEST_CMD_MAX, +}; + +int32_t AdcTestExecute(int cmd); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif /* __cplusplus */ + +#endif /* ADC_TEST_H */ diff --git a/test/unittest/platform/hdf_adc_entry_test.c b/test/unittest/platform/hdf_adc_entry_test.c new file mode 100644 index 0000000000000000000000000000000000000000..63960616b11c3723856a97c5c1c4d5516f4a1c96 --- /dev/null +++ b/test/unittest/platform/hdf_adc_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_adc_entry_test.h" +#include "hdf_log.h" +#include "adc_test.h" +#include "hdf_log.h" + +#define HDF_LOG_TAG hdf_adc_entry_test + +int32_t HdfAdcTestEntry(HdfTestMsg *msg) +{ + HDF_LOGE("%s: enter", __func__); + if (msg == NULL) { + return HDF_FAILURE; + } + + msg->result = AdcTestExecute(msg->subCmd); + + return HDF_SUCCESS; +} diff --git a/test/unittest/platform/hdf_adc_entry_test.h b/test/unittest/platform/hdf_adc_entry_test.h new file mode 100644 index 0000000000000000000000000000000000000000..f239f29319e10d6462ba46a63c0ad136e0830328 --- /dev/null +++ b/test/unittest/platform/hdf_adc_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_ADC_ENTRY_TEST_H +#define HDF_ADC_ENTRY_TEST_H + +#include "hdf_main_test.h" + +int32_t HdfAdcTestEntry(HdfTestMsg *msg); + +#endif /* HDF_ADC_ENTRY_TEST_H */ \ No newline at end of file